# @\_exported and fixing import visibility

**URL:** <https://forums.swift.org/t/exported-and-fixing-import-visibility/9415>\
**Category:** Discussion\
**Created:** [February 1, 2018, 4:34am UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415 "2018-02-01T04:34:10Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [December 13, 2018, 9:40pm UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/41 "2018-12-13T21:40:17Z")

</div>

> [@jrose](#):
>
> As I said, the problem is about C frameworks that import Swift frameworks, not about mixed-source frameworks.

If that's the case, then why does this matter at all to Swift's own language design? When people use C, they know C's limitations, and I think they can accept Swift isn't going to magically lift them. If a C module transitively imports a Swift or mixed-source module, I would expect it to leak the C interface of that module through the C module, but it doesn't seem fundamental to me that it'd affect the Swift side of things; we could still conceivably say that to get the Swift part of the interface, the Swift code has to explicitly import it.

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [December 13, 2018, 9:46pm UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/42 "2018-12-13T21:46:20Z")

</div>

> [@jrose](#):
>
> I don't think we'd want to change the default, but let's say it is possible. What does that give us? As I said, the problem is about C frameworks that import Swift frameworks, not about mixed-source frameworks.

Unless I misunderstand, what it gives us is the ability to use C without having to re-export everything. As @Joe_Groff mentioned upthread, sometimes there are reasons to use C right now where people might prefer to stay in Swift-only land. If they had the option to do that without the downside of having to re-export it might be very useful.

> [@jrose](#):
>
> I know, I don't want it either, but it's not a regression. It's (2) and (3) from the original post.

I understand that it's not a regression but it is something I think we should fix if we can (and it sounds like we _can_, the only question is whether we _should_ given source compatibility, etc). The behavior of (2) and (3) is extremely undesirable IMO even if it is what we have today.

Isn't there a path forward that might break _source_ compatibility but allows for automatic migration (at least via a temporary / deprecated `@leaky import` I mentioned earlier).

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [December 13, 2018, 10:11pm UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/43 "2018-12-13T22:11:10Z")

</div>

> [@Joe\_Groff](#):
>
> > As I said, the problem is about C frameworks that import Swift frameworks, not about mixed-source frameworks.
> 
> If that's the case, then why does this matter at all to Swift's own language design? When people use C, they know C's limitations, and I think they can accept Swift isn't going to magically lift them. If a C module transitively imports a Swift or mixed-source module, I would expect it to leak the C interface of that module through the C module, but it doesn't seem fundamental to me that it'd affect the Swift side of things; we could still conceivably say that to get the Swift part of the interface, the Swift code has to explicitly import it.

The compiler can't import "just the C part" of a Swift module because it doesn't know how the types match up with the Swift types. (The way this works in the importer is by basically throwing away the C declarations once they've been mapped back to Swift declarations.) I _guess_ we could treat that as "loaded but not visible", though?

> [@anandabits](#):
>
> I understand that it's not a regression but it is something I think we should fix if we can (and it sounds like we _can_, the only question is whether we _should_ given source compatibility, etc). The behavior of (2) and (3) is extremely undesirable IMO even if it is what we have today.

It's the kind of thing that's technically feasible but definitely non-trivial, and I haven't thought too much about the tricky bits. I was hoping we could define the problem away with the work on "implementation-only imports" and "re-exported imports", but that doesn't seem to be the case, and that means it's just a separate issue. Which means I won't be working on it right now.

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [December 13, 2018, 10:15pm UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/44 "2018-12-13T22:15:04Z")

</div>

> [@jrose](#):
>
> I _guess_ we could treat that as "loaded but not visible", though?

Would this mean it's available to the library but not the client? I think this is pretty much the direction I'm suggesting, isn't it?

> [@jrose](#):
>
> I was hoping we could define the problem away with the work on "implementation-only imports" and "re-exported imports", but that doesn't seem to be the case, and that means it's just a separate issue. Which means I won't be working on it right now.

I see. We've lived with it this long so I suppose that's ok. 🙂 I'll be happy as long as it eventually gets some attention...

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [December 13, 2018, 10:18pm UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/45 "2018-12-13T22:18:41Z")

</div>

Yeah, "loaded but not visible" is my attempt to describe what the current Swift `import` does.

Okay, hm. I'll have to think about how to do this C thing.

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [December 13, 2018, 10:24pm UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/46 "2018-12-13T22:24:43Z")

</div>

> [@jrose](#):
>
> Yeah, "loaded but not visible" is my attempt to describe what the current Swift `import` does.

FWIW, I would interpret "not visible" to include operators and extensions (which current Swift `import` _does_ include)...

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [December 13, 2018, 10:55pm UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/47 "2018-12-13T22:55:05Z")

</div>

:-) I'm describing where we want to be rather than where we are, but since I did just say that probably won't get fixed as part of this work, maybe I should stop.

---

<div class="post-metadata">

**Author:** ![jayton](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jayton/32/5592_2.png) [@jayton](https://forums.swift.org/u/jayton)\
**Post date:** [December 16, 2018, 2:53pm UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/48 "2018-12-16T14:53:25Z")

</div>

> [@anandabits](#):
>
> My reading of your example is that `MyObjCFramework` , being Objective-C, re-exports everything it imports. It imports `MySwiftFramework` so that is automatically re-exported.

I’d like to note that this is _not_ my expectation as an Objective-C developer. Clang modules have explicit export lists, and while `export *` is commonplace, it isn’t the only way to do things.

> [@jrose](#):
>
> That's just not how C works.

It is in fact exactly how the Clang modules dialect of C works. `@import UIKit` only exposes `NSObject` because UIKit’s module map says so.

On top of that (regardless of modules), C and Objective-C libraries can distinguish between public imports (ones that are in their public headers) and private ones (ones in private headers or implementation files only). They can also reduce the number of public imports required by using forward declarations. Swift doesn’t have either of these things.

It seems to me that C and Objective-C compatibility is being used to argue for a semantics that’s leakier than C or Objective-C require.

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [December 16, 2018, 4:09pm UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/49 "2018-12-16T16:09:59Z")

</div>

> [@jayton](#):
>
> It seems to me that C and Objective-C compatibility is being used to argue for a semantics that’s leakier than C or Objective-C require.

I don’t have the expertise that @jrose does in this area so I have been accepting his statement of the problem. If we can get away with more controlled semantics when dealing with C and Objective-C interop I would of course be very happy with that!

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [December 18, 2018, 12:22am UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/50 "2018-12-18T00:22:16Z")

</div>

Ooh, I was hoping no one would bring up `export *`. Swift is currently pretty broken when people _don't_ do `export *`, and I'm not sure Clang works well with it either. But on top of that, the module map for an Xcode-built framework containing Swift code currently always includes `export *` for the Swift part of the module, with no way to configure it. Part of the reason for this is because it's never a good thing when C code behaves differently with and without modules enabled, and while Swift generated headers currently don't support modules-off very well, they _should_ be able to ([SR-805](https://bugs.swift.org/browse/SR-805)).

> [@jayton](#):
>
> On top of that (regardless of modules), C and Objective-C libraries can distinguish between public imports (ones that are in their public headers) and private ones (ones in private headers or implementation files only).

We may not get forward declarations in Swift (for probably dozens of reasons), but this thread definitely covers adding the implementation-only imports. The tricky bits are around the things you want to expose as API, and then around the things you want to expose as ABI but not API. (The latter is where forward declarations are "usually good enough" in C.)

---

<div class="post-metadata">

**Author:** ![beefon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/beefon/32/13391_2.png) [@beefon](https://forums.swift.org/u/beefon)\
**Post date:** [January 11, 2019, 1:19pm UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/51 "2019-01-11T13:19:47Z")

</div>

My bit to the discussion from user of the Swift and SPM.

I use SPM and I have plenty of targets. SPM requires you to explicitly specify the dependencies for each target inside `Package.swift`, but on the other side, Swift allows me to use transitive dependencies in my source code without updating `Package.swift`. Sometimes this breaks the build phase, because, as I think, the compiler meets some `import`-s of not yet built modules/targets. Then I have to dig into the problem, find the missing dependency and update my module inside `Package.swift` so build system would build the libraries in the right order. Usually this is a pain, because `swift build` will just print some not very helpful error about `libc` module. 🙂

I agree that `NSObject` should be usable if you import `AppKit` or `UIKit`, but for non-Apple modules, I think, it will be beneficial to have the ability to disable the use of the transitive deps.

---

<div class="post-metadata">

**Author:** ![hooman](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hooman/32/43536_2.png) [@hooman](https://forums.swift.org/u/hooman)\
**Post date:** [January 25, 2019, 2:27am UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/52 "2019-01-25T02:27:03Z")

</div>

I just ran into an issue related to this. Any new developments?

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [January 25, 2019, 2:33am UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/53 "2019-01-25T02:33:38Z")

</div>

Not really. I've been more focused on module stability right now, but the general outcome of this discussion is that it's probably not worth doing anything clever for Swift vNext: just add "implementation-only import" and maybe "exported import" and leave the rest alone for now.

---

<div class="post-metadata">

**Author:** ![hooman](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hooman/32/43536_2.png) [@hooman](https://forums.swift.org/u/hooman)\
**Post date:** [January 25, 2019, 2:41am UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/54 "2019-01-25T02:41:37Z")

</div>

Thanks for the quick response. That much improvement would be enough for me.

---

<div class="post-metadata">

**Author:** ![wlind](https://avatars.discourse-cdn.com/v4/letter/w/e19adc/32.png) [@wlind](https://forums.swift.org/u/wlind)\
**Post date:** [February 21, 2019, 11:33am UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/55 "2019-02-21T11:33:46Z")

</div>

Sorry to jump in like this but could you clarify whether swift vNext means swift 5 in this case?  
I assume not, but I’d really like to have an official exported import and would just like a clear idea if I can expect this soon.

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [February 21, 2019, 4:53pm UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/56 "2019-02-21T16:53:50Z")

</div>

No, anything like this would have to go through the Swift Evolution Process, and it's well past the deadline for Swift 5 changes for that.

---

<div class="post-metadata">

**Author:** ![wlind](https://avatars.discourse-cdn.com/v4/letter/w/e19adc/32.png) [@wlind](https://forums.swift.org/u/wlind)\
**Post date:** [February 22, 2019, 1:02pm UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/57 "2019-02-22T13:02:35Z")

</div>

Thanks! I thought so, just had to check for sure since the thread’s been going for a year, I’ll keep a lookout on swift evolution

---

<div class="post-metadata">

**Author:** ![MikeIsaev](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mikeisaev/32/3446_2.png) [@MikeIsaev](https://forums.swift.org/u/MikeIsaev)\
**Post date:** [March 1, 2019, 2:40pm UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/58 "2019-03-01T14:40:05Z")

</div>

I developed a lib, it consists from two parts.  
In first part I have a lot of custom infix operators.  
Second part do `@_exported import FirstPart`.

Then my users do `import SecondPart` in their projects, by they facing with problem that infix operators from FirstPart are not available with just `import SecondPart` thought they should. So my users should also do `import FirstPart`.

**Is there any chance if it will be fixed in Swift 5?**

---

<div class="post-metadata">

**Author:** ![scanon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/scanon/32/2445_2.png) [@scanon](https://forums.swift.org/u/scanon)\
**Post date:** [March 1, 2019, 2:49pm UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/59 "2019-03-01T14:49:55Z")

</div>

`@_exported` is an implementation detail (as indicated by the leading underscore); its semantics are whatever it does, and can be changed at any point, so you should not depend on it doing anything specific.

Have you [reported a bug](http://bugs.swift.org)? Bugs that are not reported are unlikely to get fixed in any Swift release. It's also possible that the behavior you're seeing is not a bug (it's hard to tell based on the limited description here), in which case reporting it gives you the opportunity to clarify exactly what you're doing and what behavior you expect to see, and for someone to help you figure out how to get it.

Swift 5 is really only taking fixes for critical regressions at this point, so realistically this is not going to change for that release.

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [July 17, 2019, 1:37am UTC](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415/60 "2019-07-17T01:37:49Z")

</div>

I thought Discourse automatically linked threads that reference a particular thread, but I guess not. Check out "[Update on implementation-only imports](https://forums.swift.org/t/update-on-implementation-only-imports/26996)".

[Previous page](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415.md?page=2)

[Next page](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415.md?page=4)
