-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[WIP][SR-14665] Warn of potentially incorrectly synthesized Equatable
conformance for custom Comparable
conformance
#39047
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
base: main
Are you sure you want to change the base?
Conversation
@@ -454,6 +454,43 @@ ValueDecl *DerivedConformance::deriveEquatable(ValueDecl *requirement) { | |||
|
|||
// Build the necessary decl. | |||
if (requirement->getBaseName() == "==") { | |||
auto NominalType = Nominal->getDeclaredType(); | |||
ASTContext &ConformanceContext = ConformanceDecl->getASTContext(); |
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.
DerivedConformance already has a Context instance variable, you can use that (the ASTContext instance is a global singleton).
@@ -454,6 +454,43 @@ ValueDecl *DerivedConformance::deriveEquatable(ValueDecl *requirement) { | |||
|
|||
// Build the necessary decl. | |||
if (requirement->getBaseName() == "==") { | |||
auto NominalType = Nominal->getDeclaredType(); |
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.
Use getDeclaredInterfaceType() instead
if (ComparableConformance) { | ||
DeclName LessThanFunctionName( | ||
ConformanceContext, | ||
DeclBaseName(ConformanceContext.Id_LessThanOperator), |
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 should work to just pass the Identifier directly to getWitnessByName(). It will implicitly convert to a DeclName.
DeclBaseName(ConformanceContext.Id_LessThanOperator), | ||
{Identifier(), Identifier()}); | ||
ConcreteDeclRef LessThanFunctionWitness = | ||
ComparableConformance.getWitnessByName(NominalType->getRValueType(), |
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.
You don't need getRValueType() here.
How is the user meant to silence this warning if they intend for this behavior? |
…d `<` Synthesized `==` is composed of member-wise `==`s, which is likely incorrect if the non-synthesized `<` is not composed of member-wise inequalities.
eed2918
to
667fe74
Compare
@slavapestov I made the changes that you suggested, but I'm not sure if I did them correctly (the last time I used C++ was from 4 years ago). Could you help me check them again? |
@CodaFi I don't think the user can silence the warning with the current implementation in this PR. Something like the following code will result in a false-positive warning: struct IntegerWrapper: Comparable {
let wrappedInteger: Int
func < (lhs: Self, rhs: Self) {
lhs.wrappedInteger < rhs.wrappedInteger
}
} even though the code above is correct, and basically the same as what the compiler would have synthesized. Is there a way to offer user the ability to silence this warning? I'm not familiar with things in the compiler, so any advice would be great! I think a better solution would be for the compiler to check if the user-implemented |
@swift-ci please smoke test |
Just for convenicence. * Replace `llvm::isa_and_nonnull` with imported `isa_and_nonnull` * Repalce some `EXPR && isa<T>(EXPR)` with `isa_and_nonnull<T>(EXPR)`
Allow the installation of the back-deployment shared libraries for concurrency via build-script.
… name When linking against the back-deployed _Concurrency library, ensure that clients record an `@rpath`-relative dependency.
When testing the runtime in the OS (via the lit parameter `use_os_stdlib`), add the path to the back-deployed concurrency libraries into `DYLD_LIBRARY_PATH` for the test run. This should allow us to run our regression tests on older OS's.
build-script-impl effectively ignores the `install_destdir` provided to it by build-toolchain, and uses something based on the build subdir instead. But build-script products do follow `install_destdir`, so make `build-toolchain` provide something closer to correct.
…odel them similarly as Swift SPIs For clang symbols marked with SPI_AVAILABLE, we add SPIAccessControlAttr to them so they will be considered as SPIs in the AST. To be able to use all these symbols, we also add an implicit SPI import statement for all clang modules. All clang SPIs belong to the same SPI group named "OBJC_DEFUALT_SPI_GROUP" because clang currently doesn't support custom SPI group. rdar://73902734
In a back deployment scenario, this will provide a place where one could provide function implementations that are not available in the relevant stdlib. This is just setting up for future work and isn't doing anything interesting beyond wiring it up/making sure that it is wired up correctly with tests.
Remove the option that explicitly enables concurrency back-deployment, and instead always enable its support in the compiler. Remove the use of the extraneous CMake option as well.
…locations. Those instructions should not be "visible" for debugging and for diagnostic messages. Fixes a wrong "unreachable code" warning. https://bugs.swift.org/browse/SR-14873 rdar://80237870
There can be, currently, up to eight child nodes for a FunctionType. OldRemangler seemed to think there could only be three, while NodePrinter plumped for six. rdar://82252704
Fixes rdar://76473697.
It is not well supported rdar://82082527
Once coerced initializer expression has been set for a particular pattern binding entry, let's mark it as checked, otherwise decl checker might try to re-typecheck it.
Coercion should be aligned with `PatternBindingEntryRequest::evaluate` and that uses only one flag - `TypeResolverContext::PatternBindingDecl`.
If you have a class with an (invalid) protocol nested inside: class OuterGenericClass<T, U> { protocol InnerProtocol : OuterGenericClass {} } The reference to 'OuterGenericClass' in the protocol's inheritance clause is not "in context", and should not have inferred generic arguments <T, U>, because the protocol does not inherit the generic arguments of the outer scope. Previously, this would trigger an assertion in the requirement machine, because the generic parameter τ_0_1 is not a valid generic parameter in the protocol's generic signature.
Darwin OSes support vouchers, which are key/value sets that can be adopted on a thread to influence its execution, or sent to another process. APIs like Dispatch propagate vouchers to worker threads when running async code. This change makes Swift Concurrency do the same. The change consists of a few different parts: 1. A set of shims (in VoucherShims.h) which provides declarations for the necessary calls when they're not available from the SDK, and stub implementations for non-Darwin platforms. 2. One of Job's reserved fields is now used to store the voucher associated with a job. 3. Jobs grab the current thread's voucher when they're created. 4. A VoucherManager class manages adoption of vouchers when running a Job, and replacing vouchers in suspended tasks. 5. A VoucherManager instance is maintained in ExecutionTrackingInfo, and is updated as necessary throughout a Job/Task's lifecycle. rdar://76080222
Otherwise, these tests fail when one runs these tests against a just built toolchain but have not yet installed a stage2 stdlib.
And restructure the "Debug Information" section to make it flow better.
rdar://82734785
…opt from the SDK.
…to method named "self" can be used without qualification) https://bugs.swift.org/browse/SR-4559
…n be used without qualification) https://bugs.swift.org/browse/SR-4559
If anyone else is building Windows ARM64 they should be using a new enough Visual Studio. This workaround is more difficult to keep working properly and the CI hosts should have a new enough Visual Studio installation hopefully in order to enable the ARM64 builds of the runtime. If they do not, we can re-evaluate whether to re-instate the workaround. This allows building part of the runtime with Visual Studio 2022 and reduces the maintenance overheads for the runtime.
All enum elments should have been handled separately so we don't need to anything special for EnumCaseDecl except consuming them.
…` since it's not needed there Also allows removing the "swift/Runtime/Config.h" include from that header.
Returning a null GenericSignature is not the right way to break a cycle, because then callers have to be careful to handle the case of a null GenericSignature together with a non-null GenericParamList, for example in applyGenericArguments(). An even worse problem can occur when a GenericSignatureRequest for a nested generic declaration requests the signature of the parent context, which hits a cycle. In this case, we would build a signature where the first generic parameter did not have depth 0. This makes the requirement machine upset, so this patch implements a new strategy to break such cycles. Instead of returning a null GenericSignature, we build a signature with the correct generic parameters, but no requirements. The generic parameters can be computed just by traversing GenericParamLists, which does not trigger more GenericSignatureRequests, so this should be safe.
Introduce the ArgumentList type, which represents a set of call arguments for a function or subscript. This will supersede the use of tuple and paren exprs as argument lists.
Switch out the representation of argument lists in various AST nodes with ArgumentList.
Split up the expr list parsing members such that there are separate entry points for tuple and argument list parsing, and start using the argument list parsing member for call and subscripts.
With the removal of TupleExpr and ParenExpr argument lists, it's no longer sufficient to check whether a given parent expr has a possible chain sub-expr, as it might be a child that's unrelated to the chain under consideration. For example, for a chain that's an argument to a function call, we don't want to walk up and consider the call expr to be an extension of the chain just because it has a function expr. Tighten up the check by comparing whether the given sub-expr of a possible chain parent matches the current expr in the chain.
- Explicitly limit favoring logic to only handle unary args, this seems to have always been the case, but needs to be handled explicitly now that argument lists aren't exprs - Update the ConstraintLocator simplification to handle argument lists - Store a mapping of locators to argument lists in the constraint system - Abstract more logic into a getArgumentLocator method which retrieves an argument-to-param locator from an argument anchor expr
Most of this should be fairly mechanical, the changes in PlaygroundTransform are a little more involved though.
Track the depth and clear out the map when it reaches 0 to save memory.
We were accidentally continuing to walk the old argument list even if the caller had returned a new one.
- Remove OriginalArguments in favor of storing the pre-rewritten argument list, which simplifies things nicely - Adopt llvm::indexed_accessor_iterator
Currently
Comparable
inherits fromEquatable
, but does not provide a default implementation for==
, so the compiler synthesizes one composed of member-wise==
s. This leads to a problem where if a type's<
is not composed of member-wise inequalities, then<
,>
, and==
can all evaluate tofalse
for some pairs of values, contradictingComparable
's documentation:For example:
Relevant forums discussion: https://forums.swift.org/t/add-default-implementation-of-to-comparable/48832
This bug has previously resulted in incorrect semantic version comparison in SwiftPM (swiftlang/swift-package-manager#3486 and swiftlang/swift-tools-support-core#214)
The implementation in this PR is mostly based on #27801. It checks if a
Comparable
conformance is user-implemented or compiler-synthesized. If it's the former, it presents a warning to the user that the synthesized==
might contradict the user-defined<
. Probably a better implementation would be checking if a user defined<
is composed of (or equivalent to) member-wise inequalities, so it can avoid false positives. However, my C++ skills and my knowledge of the Swift compiler are rather lousy, so I'm not able to code out the better implementation.This PR is currently a work in progress, because I need to add tests to it.