diff --git a/lib/Sema/CSOptimizer.cpp b/lib/Sema/CSOptimizer.cpp index 2f0aa13fb082a..f24283172baeb 100644 --- a/lib/Sema/CSOptimizer.cpp +++ b/lib/Sema/CSOptimizer.cpp @@ -175,6 +175,18 @@ void forEachDisjunctionChoice( if (!decl) continue; + // Ignore declarations that come from implicitly imported modules + // when `MemberImportVisibility` feature is enabled otherwise + // we might end up favoring an overload that would be diagnosed + // as unavailable later. + if (cs.getASTContext().LangOpts.hasFeature( + Feature::MemberImportVisibility)) { + if (auto *useDC = constraint->getOverloadUseDC()) { + if (!useDC->isDeclImported(decl)) + continue; + } + } + // If disjunction choice is unavailable or disfavored we cannot // do anything with it. if (decl->getAttrs().hasAttribute() || diff --git a/test/Constraints/member_import_visibility.swift b/test/Constraints/member_import_visibility.swift new file mode 100644 index 0000000000000..cda1c01513a7a --- /dev/null +++ b/test/Constraints/member_import_visibility.swift @@ -0,0 +1,39 @@ +// RUN: %empty-directory(%t) +// RUN: %empty-directory(%t/src) +// RUN: split-file %s %t/src + +/// Build the library A +// RUN: %target-swift-frontend -emit-module %t/src/A.swift \ +// RUN: -module-name A \ +// RUN: -emit-module-path %t/A.swiftmodule + +/// Build the library B +// RUN: %target-swift-frontend -I %t -emit-module %t/src/B.swift \ +// RUN: -module-name B \ +// RUN: -emit-module-path %t/B.swiftmodule + +// RUN: %target-swift-frontend -typecheck -I %t %t/src/Main.swift %t/src/Other.swift -enable-upcoming-feature MemberImportVisibility + +// REQUIRES: swift_feature_MemberImportVisibility + +//--- A.swift +public struct Test { + public init(a: Double) { } +} + +//--- B.swift +import A + +extension Test { + public init(a: Int) { fatalError() } +} + +//--- Main.swift +import A + +func test() { + _ = Test(a: 0) // Ok, selects the overload that takes Double. +} + +//--- Other.swift +import B