3

I am using the swift package manager. I have a module ModuleA which exports two types: ModuleA and Test. I have a module ModuleB which defines a single type: Test. In ModuleB, how can I refer to the type Test from ModuleA? Ideally, I would like syntax such as #module(ModuleA) to refer directly to the module ModuleA.

Reproducible example:

Package.swift:

// swift-tools-version:5.3

import PackageDescription

let package = Package(
    name: "ShadowingTest",
    products: [
        .library(
            name: "ModuleA",
            targets: ["ModuleA"]),
        .library(
            name: "ModuleB",
            targets: ["ModuleB"]),
    ],
    dependencies: [
    ],
    targets: [
        .target(
            name: "ModuleA",
            dependencies: []),
        .target(
            name: "ModuleB",
            dependencies: ["ModuleA"]),
    ]
)

Sources/ModuleA/ModuleA.swift:

public enum ModuleA {}
public struct Test {
    public static let module: String = "ModuleA"
}

Sources/ModuleB/ModuleB.swift:

import ModuleA

struct Test {
    static let module: String = "ModuleB"
}

func test() {
    print(ModuleA.Test.module)
}

Running swift build errors with

Sources/ModuleB/ModuleB.swift:8:19: error: type 'ModuleA' has no member 'Test'

but succeeds when public is removed from the ModuleA enum in ModuleA.

deaton.dg
  • 1,282
  • 9
  • 21

1 Answers1

3

the issue is ModuleA enum in ModuleA module does not have Test.

When you remove public in ModuleA enum then ModuleB cannot recognize there is a ModuleA enum because its access modifier is internal by default so ModuleB recognizes Test struct in ModuleA instead of trying to find Test in ModuleA enum


Bonus: There is a answer in SO about access modifiers I think you'll find useful.


EDIT:

If you need to use ModuleA.Test even there is an enum named ModuleA then you can use import (class|struct|func|protocol|enum) <needed_component> so in your case you should import like this:

import struct ModuleA.Test

If you want to use the struct with another name to avoid naming conflicts then you can set a typealias ->

import struct ModuleA.Test

typealias TestA = ModuleA.Test
emrcftci
  • 3,355
  • 3
  • 21
  • 35
  • I understand what the access modifiers are doing, but this does not answer my question. My issue is that I cannot access the `Test` type from the module `ModuleA` if the module `ModuleA` exports a `ModuleA` type. If there is no such type, `ModuleA.Test` refers to the `Test` type from the module `ModuleA`, but if there is such a type, `ModuleA.Test` refers to the static member `Test` from the enum `ModuleA` from the module `ModuleA` (which does not exist). I want to access `Test` from module `ModuleA` when module `ModuleA` exports type `ModuleA`. – deaton.dg May 22 '21 at 01:24
  • @deaton.dg I've updated my answer could you please check? – emrcftci May 22 '21 at 11:45
  • This works, thank you! Ideally, I would prefer syntax like `#module(ModuleA)` to refer specifically to the module (question edited accordingly). I will accept this answer in a couple days if this is still the solution I am using. – deaton.dg May 22 '21 at 18:26