Compare the names of all extension members first, before attempting weirder and more expensive comparisons like stringified type and mangled name. This gives us a sort order that’s a little more comprehensible to humans.
PrintAsClang is supposed to emit declarations in the same order regardless of the compiler’s internal state, but we have repeatedly found that our current criteria are inadequate, resulting in non-functionality-affecting changes to generated header content. Add a diagnostic that’s emitted when this happens soliciting a bug report.
Since there *should* be no cases where the compiler fails to order declarations, this diagnostic is never actually emitted. Instead, we test this change by enabling `-verify` on nearly all PrintAsClang tests to make sure they are unaffected.
This did demonstrate a missing criterion that only mattered in C++ mode: extensions that varied only in their generic signature were not sorted stably. Add a sort criterion for this.
A couple of the rules that `ModuleContentsWriter::write()` uses to sort declarations didn’t actually work because of an incorrect predicate. In addition, there were a number of situations that could come up in C++ interop (where overloading is permitted) where extensions could not be sorted. Rework extension sorting to look for more kinds of differences between extension members.
Eliminates extraneous newlines between top-level Objective-C declarations in `-emit-objc-header` headers. Specifically, there should now always be exactly one—no more, no less—empty line between `@end` and whatever follows it.
Besides being more aesthetically pleasing, this eliminates ordering-dependent behavior where PrintAsClang would print an extra newline when visiting an empty extension, which meant that the order in which empty and non-empty extensions were visited during printing could result in whitespace differences in the compiler output. Printing the blank line is now conditional on whether `tell()` indicates that characters were actually written to the output.
Fixes rdar://143533893.
Because the underlying API for fetching top-level decls returns them in an unspecified order, PrintAsClang sorts the decls before printing them to make the output order more stable. However, the rules currently implemented have at least one known defect (they compare only the unqualified name of a nested class, so two nested classes with the same Swift name sort in an arbitrary order), and there are likely many more.
Add a fallback rule which sorts declarations by their mangled name; this should at least distinguish all non-colliding ValueDecls from each other, albeit according to fairly opaque criteria. Additionally add a rule to help distinguish extensions with very similar content, and tweak other logic so that the comparison function is less likely to give up early rather than continuing to look for a usable difference.
Fixes rdar://129485103.
Previously, when a pseudogeneric function returned a type parameter, it
was unowned. That resulted in invalid OSSA out of SILGen. Here, this
is fixed to use the @autoreleasing convention.
rdar://64375208
This now specifies a category name that’s used in TBDGen, IRGen, and PrintAsClang. There are also now category name conflict diagnostics; these subsume some @implementation diagnostics.
(It turns out there was already a check for @objc(CustomName) to make sure it wasn’t a selector!)
This bleeds into the implementation where "guaranteed" is used
everywhere to talk about optimization of guaranteed values. We need to
use mandatory to indicate we're talking about the pass pipeline.
The pass is already not being run during normal compilation scenarios today
since it bails on OSSA except in certain bit-rot situations where a test wasn't
updated and so was inadvertently invoking the pass. I discovered these while
originally just trying to eliminate the pass from the diagnostic pipeline. The
reason why I am doing this in one larger change is that I found there were a
bunch of sil tests inadvertently relying on guaranteed arc opts to eliminate
copy traffic. So, if I just removed this and did this in two steps, I would
basically be unoptimizing then re-optimizing the tests.
Some notes:
1. The new guaranteed arc opts is based off of SemanticARCOpts and runs only on
ossa. Specifically, in this new pass, we just perform simple
canonicalizations that do not involve any significant analysis. Some
examples: a copy_value all of whose uses are destroys. This will do what the
original pass did and more without more compile time. I did a conservative
first approximation, but we can probably tune this a bit.
2. the reason why I am doing this now is that I was trying to eliminate the
enable-ownership-stripping-after-serialization flag and discovered that the
test opaque_value_mandatory implicitly depends on this since sil-opt by
default was the only place left in the compiler with that option set to false
by default. So I am eliminating that dependency before I land the larger
change.
This test was disabled to work around a bug in the ObjC generics implementation in clang. That bug was corrected by https://reviews.llvm.org/D66696, so we should now be able to turn the Swift test back on.
I also removed the -verify-sil-ownership flag in favor of a disable flag
-disable-sil-ownership-verifier. I used this on only two tests that still need
work to get them to pass with ownership, but whose problems are well understood,
small corner cases. I am going to fix them in follow on commits. I detail them
below:
1. SILOptimizer/definite_init_inout_super_init.swift. This is a test case where
DI is supposed to error. The only problem is that we crash before we error since
the code emitting by SILGen to trigger this error does not pass ownership
invariants. I have spoken with JoeG about this and he suggested that I fix this
earlier in the compiler. Since we do not run the ownership verifier without
asserts enabled, this should not affect compiler users. Given that it has
triggered DI errors previously I think it is safe to disable ownership here.
2. PrintAsObjC/extensions.swift. In this case, the signature generated by type
lowering for one of the thunks here uses an unsafe +0 return value instead of
doing an autorelease return. The ownership checker rightly flags this leak. This
is going to require either an AST level change or a change to TypeLowering. I
think it is safe to turn this off since it is such a corner case that it was
found by a test that has nothing to do with it.
rdar://43398898
This test was designed to ensure that extensions that only add a
non-objc-compatible protocol are not printed in a compatibility header.
That case is already covered by the `extension NSString : NotObjC {}`
test in `PrintAsObjC/protocols.swift`.
Most of the time, "generics" means "cannot be exposed to Objective-C"
and certainly "cannot be exposed in the generated header", but there
is one exception: imported Objective-C parameterized types, and their
extensions. We were previously dropping this on the floor and printing
`Foo</* BarType */>` in the generated header, which is nonsense.
https://bugs.swift.org/browse/SR-3480
Use the keywords `_Nullable`, `_Nonnull`, and `_Null_unspecified`
instead of the older compatibility forms `__nullable`, `__nonnull`, and
`__null_unspecified`.
Part of rdar://problem/23614638
These classes don't show up well in generated headers (rdar://problem/20855568),
can't actually be allocated from Objective-C (rdar://problem/17184317), and
make the story of "what is exposed to Objective-C" more complicated. Better
to just disallow them.
All classes are still "id-compatible" in that they can be converted to
AnyObject and passed to Objective-C, they secretly implement NSObjectProtocol
(via our SwiftObject root class), and their members can still be individually
exposed to Objective-C.
The frontend flag -disable-objc-attr-requires-foundation-module will disable
this requirement as well, which is still necessary for both the standard
library and a variety of tests I didn't feel like transforming.
Swift SVN r29760
This is required to correctly use the mock SDK when the SDK overlay is
built and tested separately. (Otherwise, the mock SDK might not get
used, because the overlay SDK options would expand from the
%-substitution, appear first on the command line, and shadow the mock
SDK in the search path).
Swift SVN r25185
Most tests were using %swift or similar substitutions, which did not
include the target triple and SDK. The driver was defaulting to the
host OS. Thus, we could not run the tests when the standard library was
not built for OS X.
Swift SVN r24504
Doing so is safe even though we have mock SDK. The include paths for
modules with the same name in the real and mock SDKs are different, and
the module files will be distinct (because they will have a different
hash).
This reduces test runtime on OS X by 30% and brings it under a minute on
a 16-core machine.
This also uncovered some problems with some tests -- even when run for
iOS configurations, some tests would still run with macosx triple. I
fixed the tests where I noticed this issue.
rdar://problem/19125022
Swift SVN r23683
There are still problems with nested classes:
- They're much more likely to have colliding compile-time names
(since the outer class's name is dropped).
- They're only picked up if the outer class is also @objc.
But at least now we won't generate invalid Objective-C. Unless the inner
classes have the same name.
rdar://problem/18187877
Swift SVN r21677
The upshot of this is that internal decls in an app target will be in the
generated header but internal decls in a framework target will not. This
is important since the generated header is part of a framework's public
interface. Users always have the option to add members via category to an
internal framework type they need to use from Objective-C, or to write the
@interface themselves if the entire type is missing. Only internal protocols
are left out by this.
The presence of the bridging header isn't a /perfect/ way to decide this,
but it's close enough. In an app target without a bridging header, it's
unlikely that there will be ObjC sources depending on the generated header.
Swift SVN r19763
- Category names weren't unique.
- We were using an attribute to detect if something was a Swift category,
but attributes can't be used on categories.
- The test that this was all working was failing in a way that wasn't caught.
To solve these problems:
- We're using a macro to generate category names based on __LINE__ in addition
to the current module.
- The importer uses the macro to detect that the category comes from Swift
(no attribute needed).
- The test now has a deliberate error for -verify to catch.
<rdar://problem/17342287&17538553>
Swift SVN r19479
Because extensions don't have any identity we can check against, we can't
tell when we see an Objective-C category if it came from a Swift extension.
Change PrintAsObjC to mark all such categories with SWIFT_EXTENSION, and
just skip them unilaterally when importing Objective-C code.
Also, actually give Swift extensions a name when writing them as Objective-C
categories. Previously, they were nameless categories ("class extensions"),
but methods in a class extension are supposed to be implemented in the class's
main @implementation, so people were getting unexpected warnings about missing
implementations.
<rdar://problem/17342287>
Swift SVN r19116
...and just outright import the bridging header if that's what's needed.
This means we'll use @class and @protocol whenever we're just using a class
or protocol in a type, but still import the enclosing module when we need
the definition. We'll also fall back to the module (or bridging header) if
we need something /else/ from C: a struct, a typedef, whatever.
<rdar://problem/17183425>
Swift SVN r18795