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-898] Unresolvable "ambiguous for type lookup" error when using multiple modules #43510

Open
swift-ci opened this issue Mar 8, 2016 · 4 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@swift-ci
Copy link
Collaborator

swift-ci commented Mar 8, 2016

Previous ID SR-898
Radar rdar://problem/19481048
Original Reporter mkadijk (JIRA User)
Type Bug
Environment

Apple Swift version 2.1.1 (swiftlang-700.1.101.15 clang-700.1.81) / Xcode Version 7.2.1 (7C1002) / iOS 9.2

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

md5: ea3a4fb46f14a67b99d4cb07142d5803

blocks:

  • SR-14195 Swift emits an invalid module interface when a public type has the same name as a module

is duplicated by:

  • SR-1386 Can't reference a type inside a module that has a type whose name is the same as the module
  • SR-1389 Types in modules cannot be uniquely referenced if a type and module have the same name.
  • SR-4801 Name resolution problem for packages with same-named data types
  • SR-5110 Name collision not solved with namespacing
  • SR-6705 Symbol with the name of the module overrides module namespace
  • SR-7909 Module type namespace collision
  • SR-12647 Error in parsing module interface when class have the same name with the framework

Issue Description:

Given two modules with the same type, where one module has a type that has the same name as the module itself with generic parameters it will become impossible to explicitly refer to the type you want.

Example

Module A:

struct NoError: ErrorType {}

Module B:

struct B<T> {}
struct NoError: ErrorType {}

The app:

import A
import B

let ambiguousError: NoError // This correctly errors because it's ambiguous
let errorA: A.NoError // This correctly works since we make the module explicit
let errorB: B.NoError // This _incorrectly_ errors, complaining about required arguments

Expected behaviour

Only ambiguousError should give an error, the other two error constants should work since the module is specified to prevent ambiguous type errors.

What happend instead

The error we get with B.NoError is Reference to generic type 'B' requires arguments in <...>. The compiler incorrectly assumes we are referring to struct B instead of the module B. This makes it impossible to fix the ambiguity.

Workaround

It is possible to work around this by creating a typealias in a seperate file where we only import module B and there typealias BNoError = NoError then we can use the BNoError as the type of let errorB to work around the issue.

@belkadan
Copy link
Contributor

belkadan commented Mar 8, 2016

Needs design. import … as … is one possible answer.

@swift-ci
Copy link
Collaborator Author

Comment by Evan Maloney (JIRA)

I've hit this issue as well, and have discovered that it doesn't require the use of generics to trigger it.

In my case, I have a package LegacyStore and a package AppleTart, both of which contain a type named User.

In the case of LegacyStore, User is an Objective-C class, and in the case of AppleTart, User is a Swift struct.

Normally, I'd be able to refer to one as LegacyStore.User and the other as AppleTart.User, but when using this notation for an extension:

extension AppleTart.User
{
    public var legacyUser: LegacyStore.User {
        // implementation
    }
}

...I get a compiler error on the extension declaration line:

error: 'User' is not a member type of 'AppleTart'

Note that the LegacyStore.User notation used in the var declaration never triggers a compiler error, so I'm assuming the notation just isn't supported yet in the context of declaring an extension.

Fortunately, there's a (somewhat cumbersome) work-around, which is to create two separate files, one for each module. Within each file import just that one module, and create a typealias for each clashing name using package-qualified name of the type.

For example, here's the relevant part of my AppleTartTypeDisambiguation.swift file:

import AppleTart

public typealias AppleTartUser = User

And here's my LegacyStoreTypeDisambiguation.swift file:

import LegacyStore

public typealias LegacyUser = User

I can then use the typealiases to extend either type. For example, here's how I successfully extended AppleTart.User:

extension AppleTartUser
{
    public var legacyUser: LegacyStore.User {
        // implementation
    }
}

After circulating the problem above to the Swift-Users mailing list, @belkadan reached out with a (correct) hunch that the underlying problem was that I have a type that has the same name as the module.

In fact, the AppleTart module contained a type also named AppleTart, which acts as an interface for controlling the framework that vends the module. I renamed the type to AppleTartFramework and am no longer experiencing the problem.

@swift-ci
Copy link
Collaborator Author

Comment by Vladimir Shabanov (JIRA)

Please fix. There are problems with importing custom obj-c error classes (descendants of NSError) even from single custom Obj-C framework to Swift app.

@lilyball
Copy link
Mannequin

lilyball mannequin commented Feb 4, 2021

Also see SR-14142 where this missing language feature is causing emitted swiftinterface files to fail to compile.

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
Projects
None yet
Development

No branches or pull requests

2 participants