Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-631] Extensions in different files do not recognize each other #43248

Closed
swift-ci opened this issue Jan 27, 2016 · 29 comments
Closed

[SR-631] Extensions in different files do not recognize each other #43248

swift-ci opened this issue Jan 27, 2016 · 29 comments

Comments

@swift-ci
Copy link
Collaborator

swift-ci commented Jan 27, 2016

Previous ID SR-631
Radar rdar://problem/20535574
Original Reporter Claus Ruete (JIRA User)
Type Bug
Status Resolved
Resolution Done
Environment

Swift 2.1, OS X 10.11.2, Xcode 7.2, iOS 9.3

Swift 3.0, OS X 10.12.2, Xcode 8.2, iOS 10.2

Swift 4.1, macOS 10.13.4, Xcode 9.3, iOS 11.3.1

Additional Detail from JIRA
Votes 67
Component/s Compiler
Labels Bug
Assignee None
Priority Medium

md5: 03516e4c5cb56edb0b552b12b67921c7

is duplicated by:

  • SR-954 swiftc doesn't find inner type declared in an extension in another file
  • SR-1634 Can't extend a nested type from a different swift file
  • SR-1960 typealias in extension may not work depending on the compile order.
  • SR-2472 Nested class declared in an extension of parent cannot be extended in other files
  • SR-4389 Extending generic nested type in separate files fails
  • SR-4568 Extension of a nested type defined in a separate source file fails to compile
  • SR-4798 Trying to extend a subclass defined in an extension rejected by compiler
  • SR-4841 Compiler generates error because of sequence of files to be compiled
  • SR-5520 Member type inconsistency / file restriction
  • SR-5734 SPM build process depends on file names
  • SR-5868 Second-level declarations in extensions are not seen in dependent file
  • SR-5993 Cannot subclass to a nested class ('Super' is not a member type of 'Baz').
  • SR-6708 Extensions can't see nested types in extensions in other files
  • SR-7988 Cannot extend nested types defined in extensions in some cases

relates to:

  • SR-4389 Extending generic nested type in separate files fails
  • SR-5993 Cannot subclass to a nested class ('Super' is not a member type of 'Baz').
  • SR-6179 Strange error with typealiases and extensions

Issue Description:

This kind of setup does not work (Three different files).

It does even autocomplete when typing the last file, but then it doesn't compile.

class FirstClass { }
extension FirstClass {
    class SecondClass { }
}
extension FirstClass.SecondClass { // Error here!
    class ThirdClass { }
}

The error is:

"SecondClass is not a member type of FirstClass"

On the first line of the last file.

@swift-ci
Copy link
Collaborator Author

swift-ci commented Dec 14, 2016

Comment by Giorgio Calderolla (JIRA)

This can be reproduced with two files as well, as long as the member type is declared in one file and extended in another.

struct Outer {}

// Error: 'Inner' is not a member type of 'Outer'
extension Outer.Inner {}
extension Outer {
  struct Inner {}
}

@swift-ci
Copy link
Collaborator Author

swift-ci commented Jan 9, 2017

Comment by Fedor Korotkov (JIRA)

The funny part that we faced this issue once we re-arranged some files on FS.

We had such cases of using extensions for months in our codebase but it was working until order of files passed to swift compiler changed.

@swift-ci
Copy link
Collaborator Author

swift-ci commented Jan 10, 2017

Comment by Fedor Korotkov (JIRA)

I can confirm that it can work in some case. For example if files passed as `Outer.swift`, `Outer+Inner.swift` swiftc will compile it. But `Outer+Inner.swift`, `Outer.swift` order will fail.

@swift-ci
Copy link
Collaborator Author

swift-ci commented Jan 12, 2017

Comment by Mauro Bolis (JIRA)

+1
A workaround is to change the order of the files in the "compile sources" step
Sometimes (see cocoapods) this is not possible

@swift-ci
Copy link
Collaborator Author

swift-ci commented Feb 7, 2017

Comment by Naoki Hiroshima (JIRA)

Interestingly, you can use it to subclass while you can't extend.

// First.swift
public class Klass {
    public class Foo {}
}
public extension Klass {
    public class Bar {}
}
// Second.swift
class MyFoo: Klass.Foo {}  // Ok
class MyBar: Klass.Bar {}  // Ok
extension Klass.Foo {}  // Ok
extension Klass.Bar {}  // 'Bar' is not a member type of 'Klass'

@belkadan
Copy link
Contributor

belkadan commented May 10, 2017

SR-4841 has the smallest test case I've seen yet.

@swift-ci
Copy link
Collaborator Author

swift-ci commented Oct 28, 2017

Comment by Paul Young (JIRA)

I tried working around this by providing a "sources" array for the relevant target in my Package.swift file but the order didn't seem to matter.

Surprisingly, defining a target per file (also using sources) and listing one as a dependency of the other didn't help either.

@swift-ci
Copy link
Collaborator Author

swift-ci commented Dec 21, 2017

Comment by Mikhail Seriukov (JIRA)

If you are developing a cocoapod and facing this issue you still can get around it.
When pod is installed it seems that in adds sources in an alphabetical order.
So you can just rename your files accordingly to force it appear in the right order.

@DevAndArtist
Copy link
Mannequin

DevAndArtist mannequin commented Jan 9, 2018

Sorry for the re-assignment. I wanted to type a comment while JIRA wasn't fast enough to understand that and interpreted my words as some sort of commands and assigned the issue to me. o.O

Anyways, this issue is really troublesome. I had a couple of files which I added to an iOS project via `Add files to "project"...`. This resulted that all files were randomly added to the build phase of the project and prevented me from compiling. I had to open up `project.pbxproj`, locate all files I added, sort and move them above to any depending swift files like described in the workaround. It would be great if this wouldn't be necessary.

@belkadan
Copy link
Contributor

belkadan commented Jan 9, 2018

It's a longstanding bug to the point where (at least for me) it's a bit infamous, but it's never risen to the top of the heap because you never have to nest types. Rest assured that it's non-trivial to fix. (I don't know if it's going to be hard to fix, but it's not some simple thing like "oh, this for-loop should have a 'deferred' stack".)

@DevAndArtist
Copy link
Mannequin

DevAndArtist mannequin commented Jan 9, 2018

@belkadan Don't get me wrong, I'm not complaining, I'm glad that this issue is known and there is a temporary fix for some cases like mine, otherwise I'd sit for days not knowing what is going on with my project. It's always great when any bugs are finally resolved.

Would it make sense to allow votes here in bugs.swift.org so some bugs may be up voted where you guys can see what bothers people the most?! 🙂

@slavapestov
Copy link
Member

slavapestov commented Jan 9, 2018

@belkadan I think that is more or less the fix though. We need some way to validate a type which can fail instead of erroring out, then iterate over all unbound extensions, trying to validate each one's type, stopping when we can no longer make forward progress (and error out any that remain as invalid types). The devil is in the details though.

@belkadan
Copy link
Contributor

belkadan commented Jan 9, 2018

There is a "Votes" button up there, but that's only one part of deciding what gets fixed. But please do Vote for it!

@hartbit
Copy link
Collaborator

hartbit commented Jan 18, 2018

I encountered this issue for the first time today. Very frustrating, especially the fact that the compilation order makes it look very inconsistent. I've added my vote 😃

@hartbit
Copy link
Collaborator

hartbit commented Jan 18, 2018

Haha, it's the top most voted open issue on the bug tracker 🙂

@swift-ci
Copy link
Collaborator Author

swift-ci commented Feb 13, 2018

Comment by Dmitry Kniazik (JIRA)

Jordan Rose added a comment - 9 Jan 2018 1:32 PM
There is a "Votes" button up there, but that's only one part of deciding what gets fixed. But please do Vote for it!

You can think you're helping to decide what should be fixed firstly, but no, you'll be waiting for 2 years and then they present it as a Swift feature to make your entities look like a mess view controller in MVC 🙂

@swift-ci
Copy link
Collaborator Author

swift-ci commented Feb 16, 2018

Comment by ANDERS MELEN (JIRA)

voted

@swift-ci
Copy link
Collaborator Author

swift-ci commented Feb 22, 2018

Comment by Alex Rupérez (JIRA)

+1

@swift-ci
Copy link
Collaborator Author

swift-ci commented Mar 4, 2018

Comment by Vanderlei Martinelli (JIRA)

I'm in need of this in the code I'm writing right now. Great +1.

@swift-ci
Copy link
Collaborator Author

swift-ci commented Apr 13, 2018

Comment by Keith Moon (JIRA)

I'm also encountering this problem.

One of the closed duplicate tickets has a workaround which works for me:

https://bugs.swift.org/browse/SR-4568

In Xcode: Build Phases -> Compile Sources:
Make sure the source with nested type we gonna extend (Zoo.swift) is above the extension contained source (Zoo+CageSize.swift)

@swift-ci
Copy link
Collaborator Author

swift-ci commented Apr 14, 2018

Comment by Dmitry Kniazik (JIRA)

keefmoon (JIRA User), when you work with a team and merge pbxproj you have to reorder all such files constantly.
With single development it will work though.

@swift-ci
Copy link
Collaborator Author

swift-ci commented Apr 18, 2018

Comment by Daniel Tull (JIRA)

keefmoon (JIRA User), I work around this by using the sort Xcode project script from WebKit (I wrote a blog post about that)) and naming the extension such that it will be sorted below. For instance ZooCageSize.swift because “+” comes before “.” in sorting. I would prefer to use the normal + notation for an extension though, and I have a lot of these nested types in one project which would cause issues.

@swift-ci
Copy link
Collaborator Author

swift-ci commented May 7, 2018

Comment by Pierpaolo Frasa (JIRA)

+1

If it's too difficult to fix this bug properly, then IMHO this sort of coding style should be disallowed by the compiler altogether, preferably with a good error message. I just wasted a lot of time trying to find out why my code didn't compile since somehow this worked in some files and didn't in others. IMHO, compiler behaviour that depends on the compilation order (that cannot even be reliably changed) is not very beginner-friendly.

@DevAndArtist
Copy link
Mannequin

DevAndArtist mannequin commented May 7, 2018

Tainnor (JIRA User) I disagree with you, this is a bug and has to be fixed. It would be really pain in the butt if just due a bug the compiler will disallow nesting.

@swift-ci
Copy link
Collaborator Author

swift-ci commented May 7, 2018

Comment by Pierpaolo Frasa (JIRA)

@DevAndArtist I do agree that this should be fixed properly, but between this working only sometimes without clear indication of why and this not working at all, I find the latter to be preferable. Having to worry that a file rename or project reconfiguration might break my whole codebase (and who's to say my code won't compile locally and on CI but not in production?) seems really bad to me, especially for a language that usually errs on the side of safety.

@DevAndArtist
Copy link
Mannequin

DevAndArtist mannequin commented May 7, 2018

Tainnor (JIRA User) a temporary warning is fine by me though.

@swift-ci
Copy link
Collaborator Author

swift-ci commented May 13, 2018

Comment by Joey Dong (JIRA)

+1

This is particularly useful for me because I often create UIView subclasses where the naming dictates a hierarchy for ease of discoverability. For example:

class InterestingView {
  private let tableView: TableView
  ...
}
 
extension InterestingView {
  class TableView {
    ...
  }
}
 
class InterestingViewController {
  private let tableView: InterestingView.TableView
  ...
}
 

I re-order files in the "Compile Sources" step as a workaround (as mentioned before in this thread).

@swift-ci
Copy link
Collaborator Author

swift-ci commented Jul 22, 2018

Comment by Sam Duke (JIRA)

Potentially a smaller test case, in one single file:

This does not compile:

extension A.B {}

extension A {
    enum B {}
}

enum A {}

This does:

enum A {}

extension A {
    enum B {}
}

extension A.B {}

Using Swift 4.0

(note that I found this issue because I had these definitions spread over different files)

@slavapestov
Copy link
Member

slavapestov commented Jul 24, 2018

#18168

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants