Commit Graph

2854 Commits

Author SHA1 Message Date
Egor Zhdan 227346870c Merge pull request #89074 from egorzhdan/egorzhdan/swift-name-this
[cxx-interop] Do not allow `swift_name` to add a method to a different struct
2026-05-14 18:18:17 +01:00
Egor Zhdan e27c9fc5f0 [cxx-interop] Do not allow swift_name to add a method to a different struct
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
2026-05-13 18:55:29 +01:00
John Hui e68687d9e8 Merge pull request #88909 from j-hui/op-bool 2026-05-13 08:31:51 -07:00
John Hui 9c35230739 [cxx-interop] Synthesize __convertToBool() on-demand
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
2026-05-12 17:29:12 -07:00
John Hui 0597c897b8 Merge pull request #87871 from j-hui/lazy-subscriptz 2026-05-12 07:53:36 -07:00
John Hui f1f17b8c75 [cxx-interop] Synthesize subscript on-demand
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
2026-05-11 23:23:39 -07:00
Xi Ge 74362dae21 Merge pull request #88972 from nkcsgexi/struct-layout-all
Frontend: Add computeAbstractStructLayout for full struct layout computation
2026-05-08 22:44:49 -07:00
Xi Ge 1c15202f8a Frontend: Add computeAbstractStructLayout for full struct layout computation
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.
2026-05-08 14:10:06 -07:00
Allan Shortlidge e9aa9ac3f4 Merge pull request #88813 from tshortli/expand-any-apple-os-in-symbol-graphs 2026-05-08 09:35:30 -07:00
Xi Ge 5911603ce4 AST: introduce the AbstractTypeLayout struct and computeAbstractLayout()
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.
2026-05-06 16:14:13 -07:00
Allan Shortlidge d4ffb7802c AST: Avoid including unnecessary headers in ASTContext.h.
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.
2026-05-06 06:43:45 -07:00
Gábor Horváth 43cae24ed4 Merge pull request #88228 from Xazax-hun/dedup-attr-logic
[cxx-interop] Deduplicate some logic to search for attributes
2026-05-06 12:22:50 +01:00
Kavon Farvardin 21b2ebff12 Sema: infer inverses in opaque return types
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
2026-05-04 14:49:34 -07:00
Kavon Farvardin 6651cb6389 NFC: refactor the applyInverses bool
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.
2026-04-29 16:56:00 -07:00
Susana Monteiro 2781a1bd5d Merge pull request #88586 from susmonteiro/susmonteiro/empty-bases-unreferenceable-storage
[cxx-interop] C++ types with empty bases have referenceable storage
2026-04-28 15:53:10 +01:00
Gabor Horvath 970253b14a [cxx-interop] Deduplicate some logic to search for attributes
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.
2026-04-27 16:52:25 +01:00
Aidan Hall fb2aa63295 Merge pull request #87217 from aidan-hall/lifedep-infer-closure-dependence
LifetimeDependence closure context dependence
2026-04-27 16:23:04 +01:00
Aidan Hall d779a13f2d LifetimeDependence: Closure capture dependencies 2026-04-24 16:14:21 +01:00
susmonteiro 080af8bba9 [cxx-interop] C++ types with empty bases have referenceable storage 2026-04-22 12:19:12 +01:00
John Hui bbcfc93300 Merge pull request #88551 from j-hui/import-virtual-lazily 2026-04-21 14:23:14 -07:00
John Hui 3d879ffb60 [cxx-interop] Import virtual functions lazily
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
2026-04-19 19:52:17 -07:00
John Hui 9e745c5cd3 Merge pull request #88372 from j-hui/non-constructive-friendship 2026-04-19 12:04:11 -07:00
Allan Shortlidge 37ac04c9ad ClangImporter: Import anyAppleOS availability attributes.
Now that Clang supports anyAppleOS availability, Swift should import anyAppleOS
availability attributes attached to Clang declarations.

Resolves rdar://173339280.
2026-04-16 16:02:55 -07:00
John Hui 75bcebe095 [cxx-interop] Do not add friend decls as members
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
2026-04-14 15:07:18 -07:00
John Hui 9ec33840db [cxx-interop] [NFC] Remove unused vector of methods 2026-04-14 15:07:16 -07:00
John Hui 699da1ef91 Merge pull request #88301 from j-hui/no-eager-return-instantiation 2026-04-14 14:08:41 -07:00
John Hui 4317981951 Merge pull request #88426 from j-hui/unreachable-frts 2026-04-14 14:08:15 -07:00
John Hui d35ca56385 Merge pull request #88427 from j-hui/no-property-no-eager-import 2026-04-14 14:07:26 -07:00
John Hui d588fb2c78 [cxx-interop] Ensure FRT base has reachable definition
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
2026-04-12 11:25:22 -07:00
John Hui 7b4ec230fd [cxx-interop] Import getSomething() lazily if not it isn't a property getter/setter
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
2026-04-12 00:05:13 -07:00
susmonteiro 61c6038d45 [cxx-interop] Re-apply support for subscripts of non-copyable types 2026-04-08 17:14:06 +01:00
John Hui 35048429b3 [cxx-interop] Stop instantiating return types before importing them
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
2026-04-07 21:16:28 -07:00
Patryk Stefanski 223d09e0f2 [cxx-interop] Tighten isSpecialAppKitFunctionKeyProperty
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
2026-04-02 23:40:15 -07:00
John Hui 20b97fb62d [cxx-interop] [NFC] Fix lookupAndImport comments + add (void) cast to calls
Those calls are throwing away the result and using the function for its
side effect of adding pointee and successor as members
2026-03-31 17:37:23 -07:00
John Hui 0df1783907 [cxx-interop] [NFC] Push addAlternateDecl() into makeSubscript() 2026-03-31 17:37:23 -07:00
Gabor Horvath 0da3b379db [cxx-interop] Fix some clang tidy warnings
* Make some methods const or static
* Other minor cleanups
2026-03-26 14:48:24 +00:00
John Hui 9fe81ed792 Merge pull request #87643 from j-hui/frt-rq 2026-03-06 16:11:10 -08:00
John Hui f4b5ddf9be [cxx-interop] Stop importing begin() and end() eagerly
We no longer need to do so since as of the previous commit we are using
clang lookup to find these during protocol conformances.

rdar://170857633
2026-03-05 20:03:58 -08:00
John Hui c62949c51c [cxx-interop] [NFC] Remove unused ClangImporter::Implementation pointer
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
2026-03-05 14:22:57 -08:00
John Hui 346bfe476b [cxx-interop] [NFCi] Clean up reference type analysis logic
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
2026-03-05 14:22:57 -08:00
Henrik G. Olsson bf75abb5de Merge pull request #87497 from NachoSoto/nachosoto/fix-75107-dedupe-imported-modules
[Perf] Deduplicate imported-module scans for forward-declared ObjC types
2026-03-02 10:13:20 -08:00
Gabor Horvath 75dc9b0283 [cxx-interop] More cleaups, no functional change intended
* 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
2026-02-28 23:43:22 +00:00
Gabor Horvath 76e1f71674 [cxx-interop] Various code cleanups, no functional change intended
* Simplify conditionals
* Simplify loops
* Use llvm:: algorithms
* Simplify use of isa
* Deduplicate some code
* Other minor simplifications
2026-02-28 10:57:25 +00:00
John Hui 3a213c0085 [cxx-interop] Look for non-unsafe name during Clang lookup (#87471) 2026-02-26 20:21:13 -05:00
Nacho Soto fdcdafd222 Add a stats test for duplicate imported Swift modules
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>
2026-02-25 16:36:36 -08:00
Nacho Soto 29cd31848a Deduplicate imported-module scans for forward-declared ObjC types
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>
2026-02-25 11:24:38 -08:00
Aidan Hall 7c5b0f760c Merge pull request #87345 from aidan-hall/lifedep-static-method-inner-type-lifetimes
LifetimeDependence: static method type lifetimes with uncurrying
2026-02-24 11:28:13 +00:00
John Hui 807496352b [cxx-interop] Load function template members alongside storage (#87409)
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
2026-02-23 15:35:12 -08:00
Aidan Hall 27d1d9c266 LifetimeDependence: static method type lifetimes with uncurrying
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.
2026-02-23 14:15:55 +00:00
Egor Zhdan 2b0f72c161 [cxx-interop] static constexpr fields should not prevent memberwise initialization
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
2026-02-18 15:53:07 +00:00