swiftlang / swiftlang/swift-java

Compilation error for default protocol function implementation: "invalid redeclaration of..."

Open
#891 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Swift
Stars
1.2k
Forks
123
Avg merge
1d 7h
Merged PRs (30d)
16

Description

Commit hash: 0dd772b8fcae9efd5bda701f1a0be95f9deb2836

Context:
While testing swiftly's support of existing Swift code, noticed that a protocol with default implementation results in generated Java code that is not compiling due to a duplicate Java_com_example_swiftexamplelib_TestBox__00024action_1__JJ symbol.

import Foundation

public protocol Test {
    func action()
}
public extension Test {
    func action() { }
}

Results in the following compilation error:

.../.build/plugins/outputs/lib/SwiftTestLib/destination/JExtractSwiftPlugin/Sources/Sample+SwiftJava.swift:54:13: error: invalid redeclaration of 'Java_com_example_swiftexamplelib_TestBox__00024action_1__JJ(environment:thisClass:selfPointer:selfTypePointer:)'
26 | #endif
27 | @_cdecl("Java_com_example_swiftexamplelib_TestBox__00024action_1__JJ")
28 | public func Java_com_example_swiftexamplelib_TestBox__00024action_1__JJ(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, selfPointer: jlong, selfTypePointer: jlong) {
   |             `- note: 'Java_com_example_swiftexamplelib_TestBox__00024action_1__JJ(environment:thisClass:selfPointer:selfTypePointer:)' previously declared here
29 |   guard let selfPointerTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: selfTypePointer, in: environment))) else {
30 |     fatalError("selfTypePointer memory address was null")
   :
52 | #endif
53 | @_cdecl("Java_com_example_swiftexamplelib_TestBox__00024action_1__JJ")
54 | public func Java_com_example_swiftexamplelib_TestBox__00024action_1__JJ(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, selfPointer: jlong, selfTypePointer: jlong) {
   |             `- error: invalid redeclaration of 'Java_com_example_swiftexamplelib_TestBox__00024action_1__JJ(environment:thisClass:selfPointer:selfTypePointer:)'
55 |   guard let selfPointerTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: selfTypePointer, in: environment))) else {
56 |     fatalError("selfTypePointer memory address was null")

Generated Java file:

// ==== --------------------------------------------------
// Thunks for Test

// Generated by swift-java

#if hasFeature(InternalImportsByDefault)
public import SwiftJava
public import SwiftJavaJNICore
public import SwiftJavaRuntimeSupport
#else
import SwiftJava
import SwiftJavaJNICore
import SwiftJavaRuntimeSupport
#endif
import Foundation
import SwiftJava
import SwiftJavaRuntimeSupport


#if compiler(>=6.3)
@used
#endif
#if compiler(>=6.4)
@diagnose(DeprecatedDeclaration, as: ignored)
#endif
@_cdecl("Java_com_example_swiftexamplelib_TestBox__00024action_1__JJ")
public func Java_com_example_swiftexamplelib_TestBox__00024action_1__JJ(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, selfPointer: jlong, selfTypePointer: jlong) {
  guard let selfPointerTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: selfTypePointer, in: environment))) else {
    fatalError("selfTypePointer memory address was null")
  }
  let selfPointerDynamicType$: Any.Type = unsafeBitCast(selfPointerTypeMetadataPointer$, to: Any.Type.self)
  guard let selfPointerRawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment))) else {
    fatalError("selfPointer memory address was null")
  }
  #if hasFeature(ImplicitOpenExistentials)
  let selfPointerExistential$ = selfPointerRawPointer$.load(as: selfPointerDynamicType$) as! (any Test)
  #else
  func selfPointerDoLoad<Ty>(_ ty: Ty.Type) -> (any Test) {
    selfPointerRawPointer$.load(as: ty) as! (any Test)
  }
  let selfPointerExistential$ = _openExistential(selfPointerDynamicType$, do: selfPointerDoLoad)
  #endif
  selfPointerExistential$.action()
} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:893

#if compiler(>=6.3)
@used
#endif
#if compiler(>=6.4)
@diagnose(DeprecatedDeclaration, as: ignored)
#endif
@_cdecl("Java_com_example_swiftexamplelib_TestBox__00024action_1__JJ")
public func Java_com_example_swiftexamplelib_TestBox__00024action_1__JJ(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, selfPointer: jlong, selfTypePointer: jlong) {
  guard let selfPointerTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: selfTypePointer, in: environment))) else {
    fatalError("selfTypePointer memory address was null")
  }
  let selfPointerDynamicType$: Any.Type = unsafeBitCast(selfPointerTypeMetadataPointer$, to: Any.Type.self)
  guard let selfPointerRawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment))) else {
    fatalError("selfPointer memory address was null")
  }
  #if hasFeature(ImplicitOpenExistentials)
  let selfPointerExistential$ = selfPointerRawPointer$.load(as: selfPointerDynamicType$) as! (any Test)
  #else
  func selfPointerDoLoad<Ty>(_ ty: Ty.Type) -> (any Test) {
    selfPointerRawPointer$.load(as: ty) as! (any Test)
  }
  let selfPointerExistential$ = _openExistential(selfPointerDynamicType$, do: selfPointerDoLoad)
  #endif
  selfPointerExistential$.action()
} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:893

Environment: Swift 6.3.3 on macOS.

$ swiftly run swift --version
Apple Swift version 6.3.3 (swift-6.3.3-RELEASE)
Target: arm64-apple-macosx26.0

$ uname -a
Darwin it-C01241 25.6.0 Darwin Kernel Version 25.6.0: Sat Jul 11 15:26:21 PDT 2026; root:xnu-12377.161.13~4/RELEASE_ARM64_T6000 arm64

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the protocol default-implementation case and inspect the generated Sample+SwiftJava.swift output. Start in JNISwift2JavaGenerator+SwiftThunkPrinting.swift around printCDecl at line 893, then trace why the same JNI symbol is emitted twice. Done means the generated Swift compiles without an invalid redeclaration and the reproduction case still calls the default implementation.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, swift
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.