Skip to content

Refactor TypeChecker visitor for MemberAccess expression.#16448

Merged
rodiazet merged 8 commits intodevelopfrom
type-checker-member-access-refactoring
Apr 20, 2026
Merged

Refactor TypeChecker visitor for MemberAccess expression.#16448
rodiazet merged 8 commits intodevelopfrom
type-checker-member-access-refactoring

Conversation

@rodiazet
Copy link
Copy Markdown
Contributor

@rodiazet rodiazet commented Feb 6, 2026

This PR refactors implementation of the TypeChecker visitor for MemberAccess expression. It is needed based on the outcome from the discussion on changes in #16376 (comment).

Intentionally no logic has changed.

@stackenbotten3000

This comment was marked as resolved.

@rodiazet rodiazet force-pushed the type-checker-member-access-refactoring branch from cf38fdd to fe24189 Compare February 6, 2026 14:20
@rodiazet rodiazet force-pushed the type-checker-member-access-refactoring branch from 1131cb9 to bf9c42e Compare February 6, 2026 14:39
@rodiazet rodiazet changed the title Refactor TypeChecker visitor od MemberAccess expression. Refactor TypeChecker visitor for MemberAccess expression. Feb 6, 2026
@rodiazet rodiazet requested a review from Copilot February 6, 2026 14:52

This comment was marked as resolved.

@rodiazet rodiazet force-pushed the type-checker-member-access-refactoring branch 3 times, most recently from cc730b5 to 60443be Compare February 9, 2026 08:31
Comment thread libsolidity/analysis/TypeChecker.cpp Outdated
size_t const initialMemberCount = possibleMembers.size();
if (initialMemberCount > 1 && arguments)
// do overload resolution
for (auto it = _possibleMembers.begin(); it != _possibleMembers.end();)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

std::remove_if(_possibleMembers, [](auto const& member) { return ....; })?

Of course, you're not liable to change this since it was already like that, and would make the review a bit more difficult then just comparing the moved around code snippets.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I plan to make it i a separated PR/PRs.

Comment thread libsolidity/analysis/TypeChecker.h Outdated
Comment thread libsolidity/analysis/TypeChecker.cpp Outdated
Comment thread libsolidity/analysis/TypeChecker.cpp Outdated
Comment thread libsolidity/analysis/TypeChecker.cpp Outdated
Comment thread libsolidity/analysis/TypeChecker.cpp Outdated
Comment thread libsolidity/analysis/TypeChecker.cpp Outdated
@rodiazet rodiazet force-pushed the type-checker-member-access-refactoring branch from 737b9e4 to c8b5654 Compare February 24, 2026 14:41
Comment thread libsolidity/analysis/TypeChecker.cpp Outdated
@rodiazet rodiazet force-pushed the type-checker-member-access-refactoring branch 2 times, most recently from bcb45e9 to 70b945e Compare February 24, 2026 15:17
Comment thread libsolidity/analysis/TypeChecker.cpp Outdated
Comment thread libsolidity/analysis/TypeChecker.cpp Outdated
Comment thread libsolidity/analysis/TypeChecker.cpp Outdated
Comment thread libsolidity/analysis/TypeChecker.cpp Outdated
Comment thread libsolidity/analysis/TypeChecker.cpp Outdated
@rodiazet rodiazet force-pushed the type-checker-member-access-refactoring branch 6 times, most recently from b069f00 to ab4a83d Compare March 18, 2026 09:25
clonker
clonker previously approved these changes Apr 8, 2026
Copy link
Copy Markdown
Member

@clonker clonker left a comment

Choose a reason for hiding this comment

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

I couldn't find discrepancies between develop and the refactor when tracing through the code paths. I'd feel better if someone else did the same before we merge. The changes are quite convoluted at times :)

What I found:

  • checkAccessedMemberFunction is called after requiredLookup = Super - develop does it before. These are independent operations but the reordering made it harder to review ofc.
  • if -> solAssert for StringConcat/BytesConcat is technically not equivalent. Develop silently skips isPure = true if the condition fails and with this PR we get an abort.
  • varDecl check is moved below MagicType handling. This is equivalent today but a potential bug source if MagicType members ever change. Guess this should be folded to where it actually belongs in a follow-up (as the todo states)
  • The general reordering throughout made it hard to track code paths

I am sure that none of these lead to wrong results but at least the second and third point aren't strictly equivalent.

@cameel
Copy link
Copy Markdown
Collaborator

cameel commented Apr 14, 2026

  • if -> solAssert for StringConcat/BytesConcat is technically not equivalent. Develop silently skips isPure = true if the condition fails and with this PR we get an abort.

It's equivalent if you look at the broader context. bytes/string types are not supposed to have other members (and we excluded the case of a bound function).

I'd feel better if someone else did the same before we merge. The changes are quite convoluted at times :)

I did already. I compared both versions and made sure nothing was lost or added. Now everything I found back then seems fixed and I went through it again just in case (though in much less detail). If we both did that then I think we'll be find here.

And yeah, this is indeed a hell to review. Though TBH it's just that the logic here was convoluted to begin with, with many overlapping cases and multiple responsibilities stuffed into one monster function. I'll take cleaning this up once and for all over having to do this in my head every time I go over #16376 and any other change related to constants in the future :)

@cameel cameel force-pushed the type-checker-member-access-refactoring branch from f4a0090 to dc9f632 Compare April 14, 2026 14:42
cameel
cameel previously approved these changes Apr 14, 2026
Copy link
Copy Markdown
Collaborator

@cameel cameel left a comment

Choose a reason for hiding this comment

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

The code is fine now. Approving, but please don't forget to squash the review fixes before merging.

Would not hurt to add an assert for #16448 (comment) too.

@clonker
Copy link
Copy Markdown
Member

clonker commented Apr 14, 2026

It's equivalent if you look at the broader context. bytes/string types are not supposed to have other members (and we excluded the case of a bound function).

Makes sense, thx for the clarification!

If we both did that then I think we'll be fine here.

Good to go then :)

And yeah, this is indeed a hell to review. Though TBH it's just that the logic here was convoluted to begin with, with many overlapping cases and multiple responsibilities stuffed into one monster function.

Agree! With core solidity on the horizon not a thing anymore, but I think that perhaps there's something to be gained from rethinking the c++ types that encode solidity types. I suspect at least some of the repeated checks here could be encoded in type invariants.

@cameel
Copy link
Copy Markdown
Collaborator

cameel commented Apr 14, 2026

There's definitely value in improving things even with Core Solidity on the horizon. We will still have to maintain Classic for quite a while and must not let it deteriorate and end up with some crits in the process.

I agree about the types. We could use fewer manual checks for every specific thing and more general properties on them.

One example of this that still sits in my head is that we may have avoided the recent transient storage codegen bug if we had Type::identifier() properly reflect the location. Requiring the user of the class to check location and build the right identifier is more error prone. The type should do more.

Or the named parameter ordering bug could have been avoided if the parameters were encapsulated in a proper type, aware of its purpose, rather than just a dumb collection being passed around without any safeguards.

We just have to be selective about it. This refactor ended up being much harder than I expected and this is likely to be the case with anything touching analysis due to all the interdependencies. I think we might have been better off slicing it into even smaller pieces. Any changes that need to shuffle big chunks of code around would probably be easier to review if done separately with as few other modification thrown in as possible.

matheusaaguiar
matheusaaguiar previously approved these changes Apr 15, 2026
@rodiazet rodiazet force-pushed the type-checker-member-access-refactoring branch from dc9f632 to 23050cd Compare April 16, 2026 14:02
@rodiazet
Copy link
Copy Markdown
Contributor Author

rodiazet commented Apr 16, 2026

I think refactoring PRs should be handled in different way. This one contains a lot of changes which potentially do not change anything, but because there is so many different aspects it's hard to follow them. I think next time I will try to push smaller PRs with minimal changes which in summary will end up with bigger refactoring. Actually each of the initial commits from the PR should be a separated PR.

@cameel
Copy link
Copy Markdown
Collaborator

cameel commented Apr 18, 2026

Can you squash "Address PR review comments." into other commits? All the review changes fixes should generally be squashed into the original commits they apply to.

@rodiazet rodiazet dismissed stale reviews from matheusaaguiar, cameel, and clonker via 89b3d26 April 20, 2026 12:23
@rodiazet rodiazet force-pushed the type-checker-member-access-refactoring branch from 23050cd to 89b3d26 Compare April 20, 2026 12:23
@rodiazet rodiazet requested review from cameel and clonker April 20, 2026 12:38
Comment on lines +3548 to +3549
// TODO: Leave it for now, but it should be moved to TypeType -> Contract case.
// We do not want to change the logic in refactor PR.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why do you want to check magic type but i.e. not struct type also?

MagicType was the only thing checked after VariableDeclaration. Structs and other stuff were originally before so nothing changed there.

If I get it right I think it's already checked in the following PR

Yes, that assert would check that and more. You could move it here. Or add the one @clonker suggested.

@cameel cameel force-pushed the type-checker-member-access-refactoring branch from 89b3d26 to d97b44c Compare April 20, 2026 12:46
@rodiazet rodiazet force-pushed the type-checker-member-access-refactoring branch from d97b44c to e903693 Compare April 20, 2026 13:32
@rodiazet rodiazet merged commit e10eb96 into develop Apr 20, 2026
83 checks passed
@rodiazet rodiazet deleted the type-checker-member-access-refactoring branch April 20, 2026 14:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants