Let's say I am a good citizen and document my private symbols:
/** My TOP SECRET DOCUMENTATION */
private class Foo {
}
When I go to distribute the compiled binary, I find out my private
documentation is distributed as well:
$ swiftc test.swift -emit-module -module-name "test"
$ strings test.swiftdoc
My TOP SECRET DOCUMENTATION
/** My TOP SECRET DOCUMENTATION */
If a client can't use a symbol (e.g. it's private [or internal and not
-enable-testing]) don't emit the documentation for a symbol in the
swiftdoc.
Fixes: SR-762, rdar://21453624
The test coverage implements this truth table:
| visibility | -enable-testing | documentation? |
|------------|-----------------|----------------|
| private | no | ❌ |
| internal | no | ❌ |
| public | no | ✅ |
| private | yes | ❌ |
| internal | yes | ✅ |
| public | yes | ✅ |
Modified the existing comments test coverage to expect non-public
documentation not to be emitted.
Don't rely on existing comment structure
Refuse to emit comments if the decl cannot actually have one. To
accomplish this, we move `canHaveComment` into the Decl instance. It
must also be marked `const`, since one of its existing usages operates
on a const pointer.
Perform fewer checks when serializing the standard library.
This was added at some point to make 'import Foundation' faster in the REPL.
What we really care about though is not delaying synthesis of the rawValue
accessors (those are synthesized on demand anyway), but delaying the
conformance check to RawRepresentable.
Split up parsing of typealias and associatedtype, including dropping a
now unneeded ParseDeclOptions flag.
Then made typealias in a protocol valid, and act like you would
hope for protocol conformance purposes (i.e. as an alias possibly
involved in the types of other func/var conformances, not as a hidden
generic param in itself).
Also added support for simple type aliases in generic constraints. Aliases
to simple (non-sugared) archetype types (and also - trivially - aliases to
concrete types) can now be part of same-type constraints.
The strategy here is to add type aliases to the tree of
PotentialArchetypes, and if they are an alias to an archetype, also to
immediately find the real associated type and set it as the
representative for the PA. Thus the typealias PA node becomes just a
shortcut farther down into the tree for purposes of lookup and
generating same type requirements.
Then the typealias PA nodes need to be explicitly skipped when walking
the tree for building archetype types and other types of requirements,
in order to keep from getting extra out-of-order archetypes/witness
markers of the real associated type inserted where the typealias is
defined.
Any constraint with a typealias more complex than pointing to a single
nested associated type (e.g. `typealias T = A.B.C.D`), will now get a
specialized diagnoses.
If the resulting function type contains an ErrorType, this is an indicator that
something else is wrong. Bail out in this case.
This happened if an enum case was referenced inside the where-clause and treated
as a type.
Try to match the original spelling of static/class in diagnostics and
when printing the AST. Also fixes cases with
PrintOptions.PrintImplicitAttrs = false, where we would just print
'class', which was not valid code.
We had four duplicated implementations of checking how a protocol
requirement uses 'Self', all slightly wrong or incomplete:
- When deciding if the protocol type can be used as an existential.
This one would just ignore 'Self' in the return type of a method
completely, which was incorrect for cases where 'Self' is
contravariant but part of the return value, for example:
func foo() -> (Self -> ())
- When deciding if a member access can be performed on an existential
value. This is distinct from the former, because the member may
have been defined in a protocol extension, in which case it cannot
be used even if the protocol type can be used as an existential.
Unfortunately, this implementation was overly conservative, and
would reject uses of 'Self' where Sema could in fact erase the
existential type, for example:
func foo() -> Self??
func foo() -> Self.Type
func foo() -> (Self, Self)
This function handled function return types correctly, effectively
plugging the leak in the previous code. It did lead to inconsistent
behavior with protocols that had contravariant Self in requirements
though; sometimes we would diagnose uses of the existential type,
other times we would only complain about specific members.
- When deciding if a method in a non-final class can model a protocol
requirement. This one was the most elaborate one, but here
contravariance and uses of associated types are actually okay, so
it was written to pick up covariant 'Self' only. However, it also
did not handle metatypes and tuples.
- When opening the type of member of an existential, we would check
if the return value was 'Self' or an optional of 'Self', but again
this check was too conservative, so after the previous three were
fixed, we could reference members on existentials that did not
have a correct opened type.
Now, these have been combined into one check. To fix some crashes,
Sema's implementation of erasing existentials now relies on
coerceToType() instead of hand-rolling a few coercions of its own,
and wrapping the rest in CovariantFunctionConversionExpr, which
didn't make much sense if the result was not a function type.
SILGen still does not support function type conversions where an
existential return value is being erased; these would silently
miscompile before, but crash with an assertion now, because they
are correctly modeled as a FunctionConversionExpr, and not
CovariantFunctionConversionExpr.
If behaviors are specified after the declaration, something like this:
```swift
var x: Int __behavior foo // __behavior is a stand-in keyword
```
we're thinking this encourages a simpler design for smaller, more composable behaviors. If we think of behavior application as function-like, then parameters to the behavior could be passed with function-like syntax:
```swift
__behavior lazy(@autoclosure initialValue: () -> Value) { ... }
var x: Int __behavior lazy(1738)
__behavior didSet(body: (oldValue: Value) -> Void) { ... }
var x: Int __behavior didSet {
trailingClosure()
}
```
Since behaviors are implementation details, they arguably belong to the right of the declaration as well.
The Objective-C Cocoa convention eschew "is" on property names, but
use it on the getter, while the Swift API guidelines state that
Boolean properties should read as assertions (e.g., "isEmpty" rather
than "empty"). Map Swift properties named "isFoo" to Objective-C by
removing the "is" from the resulting Objective-C property name (so it
will be named "foo") and from the setter (which will have the
Objective-C selector "setFoo:") while retaining the "is" for the
getter selector ("isFoo").
Fixes rdar://problem/17090661.
Fix some interface type/context type confusion in the AST synthesis from the previous patch, add a unique private mangling for behavior protocol conformances, and set up SILGen to emit the conformances when property declarations with behaviors are visited. Disable synthesis of the struct memberwise initializer if any instance properties use behaviors; codegen will need to be redesigned here.
Parse 'var [behavior] x: T', and when we see it, try to instantiate the property's
implementation in terms of the given behavior. To start out, behaviors are modeled
as protocols. If the protocol follows this pattern:
```
protocol behavior {
associatedtype Value
}
extension behavior {
var value: Value { ... }
}
```
then the property is instantiated by forming a conformance to `behavior` where
`Self` is bound to the enclosing type and `Value` is bound to the property's
declared type, and invoking the accessors of the `value` implementation:
```
struct Foo {
var [behavior] foo: Int
}
/* behaves like */
extension Foo: private behavior {
@implements(behavior.Value)
private typealias `[behavior].Value` = Int
var foo: Int {
get { return value }
set { value = newValue }
}
}
```
If the protocol requires a `storage` member, and provides an `initStorage` method
to provide an initial value to the storage:
```
protocol storageBehavior {
associatedtype Value
var storage: Something<Value> { ... }
}
extension storageBehavior {
var value: Value { ... }
static func initStorage() -> Something<Value> { ... }
}
```
then a stored property of the appropriate type is instantiated to witness the
requirement, using `initStorage` to initialize:
```
struct Foo {
var [storageBehavior] foo: Int
}
/* behaves like */
extension Foo: private storageBehavior {
@implements(storageBehavior.Value)
private typealias `[storageBehavior].Value` = Int
@implements(storageBehavior.storage)
private var `[storageBehavior].storage`: Something<Int> = initStorage()
var foo: Int {
get { return value }
set { value = newValue }
}
}
```
In either case, the `value` and `storage` properties should support any combination
of get-only/settable and mutating/nonmutating modifiers. The instantiated property
follows the settability and mutating-ness of the `value` implementation. The
protocol can also impose requirements on the `Self` and `Value` types.
Bells and whistles such as initializer expressions, accessors,
out-of-line initialization, etc. are not implemented. Additionally, behaviors
that instantiate storage are currently only supported on instance properties.
This also hasn't been tested past sema yet; SIL and IRGen will likely expose
additional issues.
...because "build configuration" is already the name of an Xcode feature.
- '#if' et al are "conditional compilation directives".
- The condition is a "conditional compilation expression", or just
"condition" if it's obvious.
- The predicates are "platform conditions" (including 'swift(>=...)')
- The options set with -D are "custom conditional compilation flags".
(Thanks, Kevin!)
I left "IfConfigDecl" as is, as well as SourceKit's various "BuildConfig"
settings because some of them are part of the SourceKit request format.
We can change these in follow-up commits, or not.
rdar://problem/19812930
There's a group of methods in `DeclContext` with names that start with *is*,
such as `isClassOrClassExtensionContext()`. These names suggests a boolean
return value, while the methods actually return a type declaration. This
patch replaces the *is* prefix with *getAs* to better reflect their interface.
Replace pointer arithmetic between multiple base classes with pointer arithmetic
between adjacent allocations. This is still pretty fragile, but at least not
ABI-dependent, and in practice we should generate exactly the same code.
This class formalizes the common case of the "trailing allocation" idiom we use
frequently. I didn't spot any true bugs while making this change, but I did see
places where we were using the wrong pointer type or casting through void* for
no good reason. This will keep us honest.
I'll get to the other libraries soon.
UnresolvedConstructorExpr is not providing any value here; it's
essentially just UnresolvedDotExpr where the name refers to an
initializer, so use that instead. NFC