-
Notifications
You must be signed in to change notification settings - Fork 593
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 Instabilities and Unnecessary Sorting in the Generated Code #3315
Fix Instabilities and Unnecessary Sorting in the Generated Code #3315
Conversation
@@ -3053,7 +3053,6 @@ Slice::InterfaceDef::allBases() const | |||
{ | |||
InterfaceList result = _bases; | |||
result.sort(containedCompare); | |||
result.unique(containedEqual); |
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.
It is illegal to list the same interface multiple times in an inheritance list, so there's no point to calling unique
on _bases
here.
@@ -3584,7 +3583,6 @@ Slice::Exception::createDataMember( | |||
checkIdentifier(name); // Don't return here -- we create the data member anyway. | |||
|
|||
// Check whether any bases have defined a member with the same name already. | |||
ExceptionList bl = allBases(); |
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.
Dead variable.
throws.sort(); | ||
throws.unique(); |
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.
We no longer sort our exception specifications, because there's no point to calling unique
.
The Slice compiler already ensures this for us.
// Arrange exceptions into most-derived to least-derived order. If we don't | ||
// do this, a base exception handler can appear before a derived exception | ||
// handler, causing compiler warnings and resulting in the base exception | ||
// being marshaled instead of the derived exception. | ||
// | ||
throws.sort(Slice::DerivedToBaseCompare()); |
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.
Note that in the languages, we do still sort them by derived-to-base.
This sorting is stable (it won't re-arrange elements that are 'equal'). And this is necessary to prevent dead catch blocks.
We do this in all compilers except 'ice2slice' (where it's correct not to) and 'slice2php', 'slice2py', and 'slice2rb'.
It is suspicious that we aren't sorting exceptions in those languages.
string ns = getNamespace(p); | ||
string name = getDispatchParams(*i, retS, params, args, ns); | ||
_out << sp << nl << "public abstract " << retS << " " << name << spar << params << epar << ';'; | ||
} |
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.
Simplified this whole block.
But the main change was removing the sorting of OperationPtr
that it used to be doing.
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.
After a review comment from Bernard, I just inlined the simplified version of this function.
// being marshaled instead of the derived exception. | ||
// | ||
throws.sort(Slice::DerivedToBaseCompare()); | ||
|
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.
Dead code.
@@ -3956,8 +3954,6 @@ Slice::Gen::ProxyVisitor::ProxyVisitor(const string& dir) : JavaVisitor(dir) {} | |||
bool | |||
Slice::Gen::ProxyVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) | |||
{ | |||
const OperationList ops = p->allOperations(); |
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.
Another dead variable...
@@ -2035,7 +2036,6 @@ Slice::Gen::TypeScriptImportVisitor::visitInterfaceDefStart(const InterfaceDefPt | |||
} | |||
|
|||
// Add imports required for operation parameters and return types. | |||
const OperationList operationList = p->allOperations(); |
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.
Dead.
@@ -1713,7 +1713,6 @@ CodeVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) | |||
const string scoped = p->scoped(); | |||
const string abs = getAbsolute(p); | |||
InterfaceList bases = p->bases(); | |||
const OperationList allOps = p->allOperations(); |
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.
Dead.
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.
I woud also remove:
allOpNames.unique();
from line 2564 in slice2cpp/Gen.cpp.
cpp/src/slice2cs/Gen.cpp
Outdated
@@ -317,26 +317,31 @@ Slice::CsVisitor::writeUnmarshalDataMember( | |||
void | |||
Slice::CsVisitor::writeInheritedOperations(const InterfaceDefPtr& p) | |||
{ |
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.
I think it would be cleaner to eliminate this helper function (called once) and just call allOperations on the interface in the calling function.
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.
I didn't want to make it too hard to review the changes, but you're right.
I 'inlined' this code, and actually managed to simplify a good chunk of the code around where we called this too.
Originally I left that |
@@ -2657,7 +2651,6 @@ Slice::Gen::InterfaceVisitor::visitInterfaceDefEnd(const InterfaceDefPtr& p) | |||
allOpNames.push_back("ice_isA"); | |||
allOpNames.push_back("ice_ping"); | |||
allOpNames.sort(); | |||
allOpNames.unique(); |
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.
The Slice compiler ensures that there are no duplicate operation names, even among inherited operations.
cpp/src/slice2cs/Gen.cpp
Outdated
} | ||
} | ||
} | ||
for (const auto& op : allOps) |
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.
Where writeInheritedOperations
was inlined to.
@@ -3223,17 +3177,14 @@ Slice::Gen::DispatcherVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) | |||
_out << fixId(name); | |||
|
|||
_out << sb; | |||
|
|||
for (const auto& op : p->operations()) | |||
for (const auto& op : p->allOperations()) |
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.
Now we just call allOperations
instead of operations
followed by writeInheritedOperations
.
A side effect of this is that now, the order that we generate operations in is reversed. It used to be Derived -> Base, but now it's Derived -> Base.
This PR fixes #3313 and #3205.
All of the instabilities were caused by places where we were calling
sort
onlist
s ofshared_ptr
s, which meant we were sorting things by unstable memory addresses.Thankfully, all of the sorting we were trying to do in those places was unnecessary and removed.
The two types of sorting which is removed by this PR:
unique
to remove duplicates.But this is useless. The Slice compiler already disallows the same exception to appear twice in an exception specification.
unique
to remove duplicates.But again, the Slice compiler issues errors if there's any conflicts, even from inherited names (including diamonds).
One exception:
We still sort our operations by name in C++ because we use a binary search over operation names to perform dispatch.
So we require the names to be alphabetized. We re-use the same list for generating the actual operations and the dispatch, and I just left it alone. It's fine.