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-2345] Linker Error: Nested classes are hidden from the Linker when calling class methods from Objective-C #44952

Closed
swift-ci opened this issue Aug 15, 2016 · 7 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself regression swift 3.0

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-2345
Radar None
Original Reporter fbartho (JIRA User)
Type Bug
Status Resolved
Resolution Duplicate
Environment

Occurs in (Swift3):

  • Version 8.0 beta 6 (8S201h)

  • beta 5

  • (not verified in other beta versions)

macOS 10.11.6

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, 3.0Regression
Assignee None
Priority Medium

md5: f887ae0d676991544eca9354bd94d1b3

duplicates:

  • SR-2267 Nested Swift classes fail to link for Objective-C

Issue Description:

Scenario:

@objc(A)
public class ASwift: NSObject {
    public class func factory() -> ASwift {
        return ASwift()
    }
}

public extension ASwift {
    @objc(B)
    public class BSwift: NSObject {
        public class func factory() -> BSwift {
            return BSwift()
        }
    }
}

In Objective-C:

// Import your bridging header somewhere

A* a = [A factory]; // No problems
B* b = [B factory]; // Linker error "can't find B used in file.o"

B* b2 = [NSClassFromString(@"B") factory]; // Works

If you examine the -Swift.h bridging header, your classes & methods are properly exposed

Expectation:

  • no linker errors, no need to call NSClassFromString

Workarounds:

  • Call Swift-defined accessible class's method to return an AnyClass reference to bounce into the unaccessible class.

  • Call Swift-defined non-class functions to bounce into the class method.

  • Call NSClassFromString to get the class reference. No longer works as of Beta6

  • Create a top-level unnested Swift subclass of your class and reference that when calling class methods.

@lilyball
Copy link
Mannequin

lilyball mannequin commented Aug 15, 2016

This issue does not reproduce with Xcode 7.3.1.

@lilyball
Copy link
Mannequin

lilyball mannequin commented Aug 15, 2016

The linker error in question:

Undefined symbols for architecture x86_64:
  "_OBJC_CLASS_$_B", referenced from:
      objc-class-ref in File.o
ld: symbol(s) not found for architecture x86_64

@lilyball
Copy link
Mannequin

lilyball mannequin commented Aug 15, 2016

If I run nm on the .o file generated from the Swift file, I see the following:

00000000000007c8 S _OBJC_CLASS_$_A
                 U _OBJC_CLASS_$_NSObject
00000000000004b8 D _OBJC_METACLASS_$_A
00000000000004e0 D _OBJC_METACLASS_$_B
                 U _OBJC_METACLASS_$_NSObject

So we're creating the metaclass runtime info for B but not the class info.

@swift-ci
Copy link
Collaborator Author

Comment by Frederic Barthelemy (JIRA)

My NSClassFromString workaround appears to no longer work for Beta6, updated description after testing the top-level unnested class bounce strategy.

@swift-ci
Copy link
Collaborator Author

Comment by Frederic Barthelemy (JIRA)

I spoke too soon. Using a top level subclass of the nested class doesn't work either. It leads to a similar linker error as above. 🙁

@swift-ci
Copy link
Collaborator Author

Comment by Frederic Barthelemy (JIRA)

Function bound to a top-level class can return the class appears to work in Beta6:

public extension A {
    public class func A.B_LinkerBypass() -> AnyClass {
        return A.B.classForCoder()
    }
}

@swift-ci
Copy link
Collaborator Author

swift-ci commented Dec 1, 2016

Comment by James Richard (JIRA)

Just ran into this bug in an obscure way. We don't directly use our nested class via Obj-C code, but we were encoding one into an archive file. Upon unarchiving the Obj-C runtime would search for the class. It'd fail as the symbols aren't there, so we were getting this error:

cannot decode object of class ([REDACTED]) for key (NS.objects); the class may be defined in source code or a library that is not linked

@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
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself regression swift 3.0
Projects
None yet
Development

No branches or pull requests

2 participants