Sema now type-checks the alternate ABI-providing decls inside of @abi attributes.
Making this work—particularly, making redeclaration checking work—required making name lookup aware of ABI decls. Name lookup now evaluates both API-providing and ABI-providing declarations. In most cases, it will filter ABI-only decls out unless a specific flag is passed, in which case it will filter API-only decls out instead. Calls that simply retrieve a list of declarations, like `IterableDeclContext::getMembers()` and friends, typically only return API-providing decls; you have to access the ABI-providing ones through those.
As part of that work, I have also added some basic compiler interfaces for working with the API-providing and ABI-providing variants. `ABIRole` encodes whether a declaration provides only API, only ABI, or both, and `ABIRoleInfo` combines that with a pointer to the counterpart providing the other role (for a declaration that provides both, that’ll just be a pointer to `this`).
Decl checking of behavior specific to @abi will come in a future commit.
Note that this probably doesn’t properly exercise some of the new code (ASTScope::lookupEnclosingABIAttributeScope(), for instance); I expect that to happen only once we can rename types using an @abi attribute, since that will create distinguishable behavior differences when resolving TypeReprs in other @abi attributes.
Control enforcement of member import visibility requirements via a new option,
instead of piggy-backing on the existing IgnoreAccessControl option. Adopt the
option when doing fallback lookups for unviable members so that the compiler
can diagnose the reason that a member is inaccessible more reliably.
Previously, with MemberImportVisibility enabled decls with the package access
level could be mis-diagnosed as inaccessible due to their access level when
really they were inaccessible due to a missing import.
Resolves rdar://131501862.
When performing name lookup for freestanding macros (e.g., after the
`#`), don't allow types to shadow macros from imported libraries.
Fixes rdar://110429368.
The macro name resolution in the source lookup cache was only looking at
macros in the current module, meaning that any names introduced by peer
or declaration macros declared in one module but used in another would
not be found by name lookup.
Switch the source lookup cache over to using the same
`forEachPotentialResolvedMacro` API that is used by lookup within
types, so we have consistent name-lookup-level macro resolution in both
places.
... except that would be horribly cyclic, of course, so introduce name
lookup flags to ignore top-level declarations introduced by macro
expansions. This is semantically correct because macro expansions are
not allowed to introduce new macros anyway, because that would have
been a terrible idea.
Fixes rdar://107321469. Peer and declaration macros at module scope
should work a whole lot better now.
This attribute allows to define a pre-specialized entry point of a
generic function in a library.
The following definition provides a pre-specialized entry point for
`genericFunc(_:)` for the parameter type `Int` that clients of the
library can call.
```
@_specialize(exported: true, where T == Int)
public func genericFunc<T>(_ t: T) { ... }
```
Pre-specializations of internal `@inlinable` functions are allowed.
```
@usableFromInline
internal struct GenericThing<T> {
@_specialize(exported: true, where T == Int)
@inlinable
internal func genericMethod(_ t: T) {
}
}
```
There is syntax to pre-specialize a method from a different module.
```
import ModuleDefiningGenericFunc
@_specialize(exported: true, target: genericFunc(_:), where T == Double)
func prespecialize_genericFunc(_ t: T) { fatalError("dont call") }
```
Specially marked extensions allow for pre-specialization of internal
methods accross module boundries (respecting `@inlinable` and
`@usableFromInline`).
```
import ModuleDefiningGenericThing
public struct Something {}
@_specializeExtension
extension GenericThing {
@_specialize(exported: true, target: genericMethod(_:), where T == Something)
func prespecialize_genericMethod(_ t: T) { fatalError("dont call") }
}
```
rdar://64993425
"Accessibility" has a different meaning for app developers, so we've
already deliberately excised it from our diagnostics in favor of terms
like "access control" and "access level". Do the same in the compiler
now that we aren't constantly pulling things into the release branch.
Rename AccessibilityAttr to AccessControlAttr and
SetterAccessibilityAttr to SetterAccessAttr, then track down the last
few uses of "accessibility" that don't have to do with
NSAccessibility. (I left the SourceKit XPC API alone because that's
supposed to be more stable.)
Name lookup into a class type always looks into its supertypes; if you
want to look directly into a particular class and its extensions, use
lookupDirect and filter.
With the previous resolveTypeInContext() patch, a few compiler
crashers regressed with this problem, presumably because we were now
performing lookups in more contexts than before.
This is a class of problems where we would attempt a recursive
validation:
1) Generic signature validation begins for type T
2) Name lookup in type context finds a non-type declaration D nested in T
3) Generic signature validation begins for D
4) The outer generic context of D is T, but T doesn't have a generic
signature yet
The right way to break such cycles is to implement the iterative
decl checker design. However when the recursion is via name lookup,
we can try to avoid the problem in the first place by not validating
non-type declarations if the client requested a type-only lookup.
Note that there is a small semantic change here, where programs that
were previously rejected as invalid because of name clashes are
now valid. It is arguable if we want to allow stuff like this or not:
class A {
func A(a: A) {}
}
or
class Case {}
enum Foo {
case Case(Case)
}
However at the very least, the new behavior is better because it
gives us an opportunity to add a diagnostic in the right place
later. The old diagnostics were not very good, for example the
second example just yields "use of undeclared type 'Case'".
In other examples, the undeclared type diagnostic would come up
multiple times, or we would generate a cryptic "type 'A' used within
its own definition".
As far as I understand, this should not change behavior of any existing
valid code.