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

[NFC] Eliminate the majority of dynamic_cast usage in the codebase in favor of ICastable interface #4382

Merged
merged 4 commits into from
Feb 1, 2024

Conversation

asl
Copy link
Contributor

@asl asl commented Jan 30, 2024

This is a spin-off from #4377

@asl
Copy link
Contributor Author

asl commented Jan 30, 2024

Tagging @fruffy @vlstill

@asl asl force-pushed the icastable branch 3 times, most recently from 16be4f6 to 9d008e1 Compare January 30, 2024 22:53
@@ -450,9 +450,8 @@ bool TypeUnification::unify(const BinaryConstraint *constraint) {
}
return constraint->reportError(constraints->getCurrentSubstitution());
} else if (dest->is<IR::Type_Declaration>() && src->is<IR::Type_Declaration>()) {
bool canUnify = typeid(dest) == typeid(src) && dest->to<IR::Type_Declaration>()->name ==
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a pre-existing p4c bug. typeid(dest) == typeid(src) is always true since both dest and src are of IR::Type* types and typeid of these expressions matches. Changing to typeid(*dest) == typeid(*src) would yield an error as it will consider generic substituted type and correspondent substitution to be separate types, when they are not. This change just removes always true condition. No test changes / failures.

Copy link
Contributor

Choose a reason for hiding this comment

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

I definitely agree this was always-true conjunct. I am just wondering if this is a bug that we are not checking that the "kinds" of types match, but I would say it is probably safe to compare names only. It doubt there can be two entities with the same name and one declaring different kind of thing then the other (e.g. extern vs. parser), as you already have an example where the types does not match correctly, I agree with just dropping the conjunct.

Copy link
Contributor Author

@asl asl Jan 31, 2024

Choose a reason for hiding this comment

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

If we take the exiting testcase for this code, then checking the typeids yields to very confusing error message. As I noted – the ordinary type and the substituted generic type are different nodes, so the typeid check would fail. However, the diagnostics produced is confusing, IIRC – cannot unify "int" with "int" or something like this.

/// produces a message that is easier to debug.

// default checkedTo implementation for nodes: just fallback to generic ICastable method
template <typename T>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note that static_type_name is defined only on concrete classes, not on interfaces. So, without this change use of checkedCastTo<T> where T is interface would produce compile error. As a result, one was able to use as<T>() with T being interface, but not checkedCastTo<T>().

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, maybe we should have static_type_name generated also for interfaces. That is a separate task though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Likely there was some rationale for this behavior. But maybe not. Though, I tend to agree that having a static type name everywhere would be be better.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Likely there was some rationale for this behavior.

I added the ICastable class at some point because I noticed we repeated this pattern a lot. At the time node_type_name and static_type_name were simply not required. There is no reason not to add them, but it will likely take some effort across the entire compiler.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@fruffy Sorry, I do not follow. What are you suggesting? Indeed we can get rid of this implementation, however we'll end with less friendly error message. Some tests checks this btw.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Just clarifying on

Likely there was some rationale for this behavior.

There was not a concrete reason why things were done this way. No need to get rid of the implementation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Btw, as far as I can see static_type_name and its usage in checkedTo predates ICastable. It's just checkedTo is rarely used in the codebase for issue to trigger :)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, there were a few nodes that implemented their own checkedTo and to but did not add the other functions. This class just unified things, the mangled typename was, well, "good enough".

@vlstill vlstill added the run-sanitizer Use this tag to run a Clang+Sanitzers CI run. label Jan 31, 2024
Copy link
Contributor

@vlstill vlstill left a comment

Choose a reason for hiding this comment

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

Thank you for this changes and for splitting them off, this is a great cleanup. I have just a few minor points and questions.

backends/ebpf/ebpfControl.cpp Show resolved Hide resolved
backends/p4tools/common/core/abstract_execution_state.cpp Outdated Show resolved Hide resolved
frontends/p4/reassociation.cpp Outdated Show resolved Hide resolved
ir/ir-inline.h Outdated Show resolved Hide resolved
ir/node.h Outdated Show resolved Hide resolved
/// produces a message that is easier to debug.

// default checkedTo implementation for nodes: just fallback to generic ICastable method
template <typename T>
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, maybe we should have static_type_name generated also for interfaces. That is a separate task though.

ir/node.h Outdated Show resolved Hide resolved
lib/castable.h Outdated Show resolved Hide resolved
@@ -450,9 +450,8 @@ bool TypeUnification::unify(const BinaryConstraint *constraint) {
}
return constraint->reportError(constraints->getCurrentSubstitution());
} else if (dest->is<IR::Type_Declaration>() && src->is<IR::Type_Declaration>()) {
bool canUnify = typeid(dest) == typeid(src) && dest->to<IR::Type_Declaration>()->name ==
Copy link
Contributor

Choose a reason for hiding this comment

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

I definitely agree this was always-true conjunct. I am just wondering if this is a bug that we are not checking that the "kinds" of types match, but I would say it is probably safe to compare names only. It doubt there can be two entities with the same name and one declaring different kind of thing then the other (e.g. extern vs. parser), as you already have an example where the types does not match correctly, I agree with just dropping the conjunct.

@asl
Copy link
Contributor Author

asl commented Jan 31, 2024

@vlstill Added suggestions from the review, please check

@@ -32,12 +32,18 @@ class ICastable {
return to<T>() != nullptr;
}

/// Tries to convert the class to type T. Returns a nullptr if the cast fails.
/// Performs a checked cast. A BUG occurs if the cast fails.
Copy link
Collaborator

Choose a reason for hiding this comment

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

std::bad_cast instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Let's leave it as-is. As I said, custom-rtti branch implements it via checkedCast. So we won't change the comment all the time.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Mostly asking because it might take a while longer until the other PR is merged. But the comment was wrong in the first place and this is an improvement...

BUG and std::bad_cast are close enough in behavior so it is fine.

/// produces a message that is easier to debug.

// default checkedTo implementation for nodes: just fallback to generic ICastable method
template <typename T>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Likely there was some rationale for this behavior.

I added the ICastable class at some point because I noticed we repeated this pattern a lot. At the time node_type_name and static_type_name were simply not required. There is no reason not to add them, but it will likely take some effort across the entire compiler.

Copy link
Collaborator

@fruffy fruffy left a comment

Choose a reason for hiding this comment

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

I have no further comments from my side on this PR.

backends/p4tools/common/core/abstract_execution_state.cpp Outdated Show resolved Hide resolved
ir/node.h Outdated Show resolved Hide resolved
@asl
Copy link
Contributor Author

asl commented Feb 1, 2024

@fruffy @vlstill Thanks for the reviews. I addressed the last comments. Will you please merge when you will have a chance? I will rebase custom-rtti branch afterwards.

@fruffy fruffy enabled auto-merge (squash) February 1, 2024 17:36
auto-merge was automatically disabled February 1, 2024 18:00

Head branch was pushed to by a user without write access

Co-authored-by: Vladimír Štill <git@vstill.eu>
@asl
Copy link
Contributor Author

asl commented Feb 1, 2024

@fruffy Looks like bazel is stuck, I cannot restart it sadly:

Received 987342403 of 999925315 (98.7%), 0.2 MBs/sec
Received 987342403 of 999925315 (98.7%), 0.2 MBs/sec
Received 987342403 of 999925315 (98.7%), 0.2 MBs/sec
Received 987342403 of 999925315 (98.7%), 0.2 MBs/sec
Received 987342403 of 999925315 (98.7%), 0.2 MBs/sec
Received 987342403 of 999925315 (98.7%), 0.2 MBs/sec
Received 987342403 of 999925315 (98.7%), 0.2 MBs/sec
Received 987342403 of 999925315 (98.7%), 0.2 MBs/sec
Received 987342403 of 999925315 (98.7%), 0.2 MBs/sec

@asl
Copy link
Contributor Author

asl commented Feb 1, 2024

@fruffy Thanks for restarting! Could you please merge it for me? Auto-merge does not work since I do not have write access.

@fruffy fruffy merged commit a16fd93 into p4lang:main Feb 1, 2024
16 checks passed
@fruffy
Copy link
Collaborator

fruffy commented Feb 1, 2024

@fruffy Thanks for restarting! Could you please merge it for me? Auto-merge does not work since I do not have write access.

If you plan on contributing more to p4c going forward we could make Kyle and you contributors with merge rights (https://github.com/orgs/p4lang/teams/p4c-committers).

@asl
Copy link
Contributor Author

asl commented Feb 1, 2024

@fruffy Thanks for restarting! Could you please merge it for me? Auto-merge does not work since I do not have write access.

If you plan on contributing more to p4c going forward we could make Kyle and you contributors with merge rights (https://github.com/orgs/p4lang/teams/p4c-committers).

I do have other patches in my queue, yes. Just one step at a time :)

@asl asl deleted the icastable branch February 1, 2024 21:58
@kfcripps
Copy link
Contributor

kfcripps commented Feb 2, 2024

If you plan on contributing more to p4c going forward we could make Kyle and you contributors with merge rights (https://github.com/orgs/p4lang/teams/p4c-committers).

Yes, that will be great. As Anton mentioned earlier, we have already made some of these changes to our compiler over a year ago, but haven't been able to upstream them yet for a number of reasons. But moving forward, we should be able to contribute more, I think. :)

@fruffy
Copy link
Collaborator

fruffy commented Feb 2, 2024

If you plan on contributing more to p4c going forward we could make Kyle and you contributors with merge rights (https://github.com/orgs/p4lang/teams/p4c-committers).

Yes, that will be great. As Anton mentioned earlier, we have already made some of these changes to our compiler over a year ago, but haven't been able to upstream them yet for a number of reasons. But moving forward, we should be able to contribute more, I think. :)

Could you send me an email (on my website) with your email addresses and some context? I can then start the discussion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
run-sanitizer Use this tag to run a Clang+Sanitzers CI run.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants