If a C++ method is not static, let's not allow changing its parent struct type to a different type, since the implicit `this` parameter would have an incompatible type.
This fixes an assertion that would previously fire for this scenario.
rdar://161208348
Previously, we would import operator bool() by simply renaming it to
__convertToBool() using NameImporter. When we had a struct with that
member, we would conform it to CxxConvertibleToBool, which would allow
Swift.Bool to be initialized via Bool(fromCxx:).
However, this conformance relies on importing operator bool() eagerly,
and didn't work reliably when operator bool() was inherited. (Part of
the reason is because our base method synthesis logic would only create
clang::CXXMethodDecls but logic elsewhere specifically expected a
clang::CXXConversionDecl.) We also weren't handling things like
const-ness etc. directly.
This patch instead synthesizes a shim method __convertToBool() that
calls the underlying operator bool() const, which we no longer import
directly. It follows the same "look up and import on demand" pattern as
other special synthesized members that wrap operators, like .pointee and
.successor() and .subscript.
rdar://170857484
The implementation for this behavior was added in a previous patch;
this patch integrates and removes unused call sites.
This patch also adds some tests exercising the overloading behavior.
Annoyingly, imported members that point to the same source location
aren't sorted correctly in the module interface, so this changes the
order in a bunch of module interface tests.
rdar://170857428
Also, un-comment broken test case of using Base::operator[], which is
fixed by this commit.
rdar://145345345
Computes per-field abstract layout (offset, size, alignment, mangled name,
bitwiseCopyable, isOpaque) for structs with both Clang-imported and Swift-native fields.
This API will be used from the library-side to serialize layout information to binary modules.
function that queries Clang's ASTRecordLayout to extract size, alignment,
stride, bitwiseCopyable, and isOpaque for C-backed nominal types.
This also adds a -dump-abstract-layout frontend debugging flag that prints
layout info for Clang-backed stored property types in the primary source
file.
Anything that can be forward declared in ASTContext.h should be because it is
included by nearly every implementation file in the compiler. Avoiding these
includes allows these various options types to be changed without a full
rebuild.
NFC.
Opaque return types are special type declarations that have it
own nested generic signature. Thus, given this:
```
protocol P<A> { associatedtype A: ~Copyable }
func f<T: ~Copyable>() -> some P<T> {}
```
The generic signature for f is <T where T Escapable>, and
for the opaque return type, its nested signature ends up as
```
<X where X: P, X.A == T>
```
With SE-503, we will now also expand a default for the suppressed
primary associated type, so the signature after expansion becomes
```
<X where X: P, X.A == T, X.A: Copyable>
```
It would be smarter to effectively have this rule
```
X.A == T, T: ~Copyable
----------------------
X.A: ~Copyable
```
where we infer the inverse on X.A to cancel-out the
expanded default X.A: Copyable. We already do this for
two in-scope type parameters, and it would be better if
we did it if one side was out-of-scope, but that would
be source-breaking to do in general.
In the case of opaque return types, the fact that
it has a nested generic signature seems more an
artifact of the implementation. There also is little
risk of source break, as the only kinds of same-type
requirements that can appear are from parameterized
protocol type.
The experimental suppressed associated types prior to
SE-503 wouldn't be broken by this change, as they do
not infer defaults that need suppression, and we only
filter-out requirements from defaults expansion, rather
than explicitly-written ones.
rdar://175500824
There's a need for more control over how default requirements
for conformance to Copyable/Escapable are expanded, and
subsequently how inverses are applied or inferred to cancel-out
those defaults.
The pattern of `/*applyInverses*/BOOL` is insufficient, so this
is a refactoring to grow that into a proper type that carries
an option that can be used in some future scenario about inferring
inverses for opaque return types.
We wrote the same code multiple times, this PR replaces some of that
code with function calls. It is not entirely NFC as the called function
has some special case for parameters. That being said, having uniform
logic for looking up attributes is probably beneficial. If it does not
work out, we can always introduce a compile-time parameter to opt in/out
of the special case.
As it turns out, no additional work was needed here to make this behave
as expected. Lazy name lookup is able to find virtual methods just fine.
rdar://174587922
Now that Clang supports anyAppleOS availability, Swift should import anyAppleOS
availability attributes attached to Clang declarations.
Resolves rdar://173339280.
Importing a friend constructor decl causes an assertion failure because
we eagerly add constructors as members, but the decl context of the
friend decl is different from the context we are adding it to.
That causes us to hit the following assertion:
void IterableDeclContext::addMember(Decl *member, Decl *hint, bool insertAtHead) {
...
assert(member->getDeclContext() == static_cast<DeclContext *>(nominal) &&
"Added member to the wrong context");
...
}
This patch continues to import friend decls (in case we rely on any side
effects from doing so) but bypasses any logic in VisitRecordDecl that
might cause a friend decl to be added as a member.
rdar://174353241
It is possible to get into situations where we have a derived FRT whose
definition is not reachable (in the modules sense). This is problematic
when we need to synthesize reference counting operations for derived
those FRTs via clang::Sema, because those operations require knowledge
about the layout of those classes, i.e.,
Base::ref((Base *)derived) // otherwise-implicit cast added for emphasis
As such, clang::Sema would be unable to generate valid call expressions,
leading to assertion failures in the decl synthesizer logic which
assumed everything is hunky dory.
This patch adds logic to accommodate this scenario, throwing a compiler
error when reachability is an problem, so that the user can look into
possible modulemap/module layout issues.
rdar://172291423
The shouldEagerlyImportClangRecordMember logic checked whether this
*could* be imported as a property getter/setter, but didn't check
whether it *would*---that behavior is controlled a compiler flag or an
annotation, which this patch now makes ClangImporter check for.
rdar://174587372
In f305ffc69f I added change that eagerly
instantiates return type templates before importing them, which
technically makes ClangImporter *more* eager. I made this change, in
conjunction with 3a213c0085, in an attempt
to make sure that the `__Unsafe` name mangling does not rely on the
unintentional side effect of importing typedefs eagerly (which I made
lazy in c57863df0c). The fact that this is
more eager is not sound, but I hadn't thought of any better ways around
this at the time.
This patch gets rid of the over-eager return type instantiation by
moving it to *after* the function is imported. If and only if the
method is actually imported, Swift will instantiate the return type,
re-import the name, and overwrite the name of the imported decl, in case
the instantiation or some other side effect during import causes it to
gain the `__Unsafe` name mangling. Admittedly, this is an ugly hack, but
an inevitable consequence of how we do name importing.
I've added a test scenario to ensure that deleted functions do not have
their return types instantiated, but other test to pay attention to is
test/Interop/Cxx/templates/using-return-type.swift, which checks that
the `__Unsafe` mangling logic is robust. This test does not change.
rdar://174028575
Previously, any declaration whose raw name started with `NS` and ended
with `FunctionKey` or `Character` was considered a special AppKit
function key property. This change requires the declaration to have a
`__attribute__((swift_name(...)))` that starts with
`NSEvent.SpecialKey.`. This prevents matching decls that are not special
keys, like `NSAttachmentCharacter`.
Checking the decl name given that we check `NSEvent.SpecialKey` is
probably redundant, but I'm too afraid to remove it :)
rdar://171083643
This was previously used to control whether a CxxRecordSemantics or
CxxRecordAsSwiftType request would trigger diagnostics when determining
a type is a foreign reference type. That interface led to obscure
control flow and was removed recently. This patch removes the vestigial
pointer field those requests used.
(Actually, that pointer was *never* used by CxxRecordAsSwiftType
requests; its call sites just happened to pick it up because it shares
the same input descriptor type as CxxRecordSemantics).
rdar://170858418
Previously, the getRefParentOrDiag() function was used both to determine
the reference typedness of an imported record, and to diagnose cases
where that determination was invalid (e.g., due to complications that
arise from inheritance). However, it exposed a rather brutish interface
for controlling whether diagnostics are emitted: when it is given
a non-null ClangImporter::Implementation pointer, it emits diagnostics,
and when given a null pointer it doesn't. A lack of consideration for
where we actually needed these diagnostics led to that pointer being
unnecessarily threaded through a couple of requests and a half dozen
call sites, leading to unnecessarily obscure control flow.
This patch gets rid of getRefParentOrDiag() and replaces it with two
well-defined entry points: a request that does not emit diagnostics, and
a function that does. The nullable ClangImporter::Implementation pointer
is hidden from the interface of those entry points, and their side
effects are well-documented.
The code is migrated from ClangImporter.cpp to ClangAnalysis.cpp, which
I've introduced as the new home for various subroutines that analyze and
extract information from clang decls.
The reference type inference logic of getRefParentOrDiag() (and its
associated helpers) is also rewritten to replace the clang-provided
clang::CXXRecordDecl::forAllBases() with an explicit graph traversal
through the class hierarchy that is easier to debug and adjust (with
imminent behavior changes in mind). It also avoids an unnecessary
class hierarchy traversal whose only purpose was to look for reference
types that participates in diamond inheritance.
No behavior change is intended: we (should) still make perform the same
reference typedness analysis, and emit the exact same diagnostics.
rdar://170858418
* Simplify some patterns (isa + cast)
* Add some consts
* Get rid of some temporary objects by constructing more objects in
place
* Remove some duplicated lookups
* Other minor cleanups
Exercise the forward-declared ObjC import path with repeated unrelated Swift
module imports and assert that the duplicate-module skip counter is non-zero.
Co-authored-by: Codex <noreply@openai.com>
Forward-declared Objective-C types fall back to hasNonLocalNativeSwiftDecl to search imported Swift modules for a matching native declaration. The imported module list can contain the same ModuleDecl multiple times, especially in large builds with repeated imports. Because the lookup only uses import.importedModule, repeated entries trigger identical resolveSwiftDeclImpl calls and can make a single forward declaration surprisingly expensive.
Deduplicate ModuleDecl pointers before scanning so each imported Swift module is checked at most once. In the reported CoreHaptics repro, this drops the forward-declaration scan from roughly 500ms to roughly 5ms and removes the long-expression warning entirely.
Co-authored-by: Codex <noreply@openai.com>
Due to still-to-be investigated shortcomings of lazy name lookup, the
Swift compiler is is unable to look up templated member functions. This
previously worked because we were loading all members eagerly, including
such templated member functions, but once we started only loading
storage members in 3b4a298da5, this broke.
For now, load FunctionTemplateDecl members eagerly to restore that old
behavior.
The updated test fails without this change, and passes after it. More
thorough testing should be done for satisfactory coverage, but there
seem to be other unrelated issues to work through like SILGen assertion
failures due to incorrect nullability handling, etc. In particular, we
are only testing methods that return references for now, and not
pointers, which do not get imported properly due to imperfect type
round-tripping during template instantiation.
rdar://170576709
The formal types of all methods are curried:
- Instance method: (Self) -> (Params...) -> Result
- Static method: (Self.Type) -> (Params...) -> Result
To be able to express lifetime dependencies on the self parameter, the lifetime
dependence information is computed as though the type has been uncurried (which
it will be during SILGen), and attached to the outer function type:
(Params..., Self) -> Result
This causes the lifetime dependence information to be lost when referring to the
inner function type (which is of more interest in most cases). Representing the
lifetimes this way is (mostly) unnecessary for static methods, since there is no
instance of the type to depend on.
We now attach lifetime dependence information to the inner function type for
static methods. This allows us to convert static methods to their inner function
types without losing their lifetime dependence information.
Once we add support for dependencies on the captured context, we will be able to
use a similar representation for instance methods.
The only complication is that the lifetime information attached to the inner
function type must be "uncurried" when lowering static methods to SIL. This will
also be necessary for closures when we add support for dependencies on the
closure context. See LifetimeDependenceInfo::uncurry.
Example:
struct S {
static func f(ne: NE) -> NE { ne }
}
- Before: S.f had type @_lifetime(2: copy 0) (S.Type) -> (NE) -> NE.
- Now: S.f has type (S.Type) -> @_lifetime(copy 0) (NE) -> NE.
In the short term, this makes it impossible to express lifetime dependencies on
the self parameter of a static method (i.e. S.Type), which should almost never
be necessary.
Swift currently doesn't import `static constexpr` fields of C++ structs. An unintended side effect of this was that if a C++ struct has a `static constexpr` field, Swift would try to import it, fail, and decide that the C++ struct can not be initialized with a memberwise Swift initializer. This change removes the limitation.
rdar://169736395