From 89ecc5ab2a9f0d7e06e633e7d67f0306ac3dd701 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Wed, 20 Aug 2025 14:51:57 -0700 Subject: [PATCH 1/2] [NFC] Pipe PrintDiagnosticNames through swiftinterface loader --- .../swift/Frontend/ModuleInterfaceLoader.h | 3 ++- lib/Frontend/ModuleInterfaceLoader.cpp | 20 +++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/include/swift/Frontend/ModuleInterfaceLoader.h b/include/swift/Frontend/ModuleInterfaceLoader.h index a5fadd951074b..8be00a2ee8e89 100644 --- a/include/swift/Frontend/ModuleInterfaceLoader.h +++ b/include/swift/Frontend/ModuleInterfaceLoader.h @@ -646,7 +646,8 @@ struct InterfaceSubContextDelegateImpl : InterfaceSubContextDelegate { const LangOptions &LangOpts, const ClangImporterOptions &clangImporterOpts, const CASOptions &casOpts, - bool suppressNotes, bool suppressRemarks); + bool suppressNotes, bool suppressRemarks, + PrintDiagnosticNamesMode diagnosticNamesMode); bool extractSwiftInterfaceVersionAndArgs(CompilerInvocation &subInvocation, DiagnosticEngine &subInstanceDiags, SwiftInterfaceInfo &interfaceInfo, diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index 1f5343d664380..2e7f7c2992bd2 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -1663,7 +1663,8 @@ void InterfaceSubContextDelegateImpl::inheritOptionsForBuildingInterface( FrontendOptions::ActionType requestedAction, const SearchPathOptions &SearchPathOpts, const LangOptions &LangOpts, const ClangImporterOptions &clangImporterOpts, const CASOptions &casOpts, - bool suppressNotes, bool suppressRemarks) { + bool suppressNotes, bool suppressRemarks, + PrintDiagnosticNamesMode printDiagnosticNames) { GenericArgs.push_back("-frontend"); // Start with a genericSubInvocation that copies various state from our // invoking ASTContext. @@ -1764,6 +1765,20 @@ void InterfaceSubContextDelegateImpl::inheritOptionsForBuildingInterface( GenericArgs.push_back("-suppress-remarks"); } + // Inherit the parent invocation's setting for printing diagnostic IDs. + genericSubInvocation.getDiagnosticOptions().PrintDiagnosticNames = + printDiagnosticNames; + switch (printDiagnosticNames) { + case PrintDiagnosticNamesMode::None: + break; + case PrintDiagnosticNamesMode::Identifier: + GenericArgs.push_back("-debug-diagnostic-names"); + break; + case PrintDiagnosticNamesMode::Group: + // FIXME: Currently no flag for Group mode + break; + } + // Inherit this setting down so that it can affect error diagnostics (mostly // by making them non-fatal). genericSubInvocation.getLangOptions().DebuggerSupport = LangOpts.DebuggerSupport; @@ -1870,7 +1885,8 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl( inheritOptionsForBuildingInterface(LoaderOpts.requestedAction, searchPathOpts, langOpts, clangImporterOpts, casOpts, Diags->getSuppressNotes(), - Diags->getSuppressRemarks()); + Diags->getSuppressRemarks(), + Diags->getPrintDiagnosticNamesMode()); // Configure front-end input. auto &SubFEOpts = genericSubInvocation.getFrontendOptions(); SubFEOpts.RequestedAction = LoaderOpts.requestedAction; From 9454c0aaa42fecc5dc3b87aca4365b8106e8aedf Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Fri, 17 Oct 2025 19:05:53 -0700 Subject: [PATCH 2/2] Emit module selectors in swiftinterfaces This support is currently opt-in and can be disabled by a blocklist. --- include/swift/AST/PrintOptions.h | 4 + include/swift/Basic/BlockListAction.def | 1 + .../swift/Frontend/ModuleInterfaceSupport.h | 3 + include/swift/Option/Options.td | 10 ++ lib/AST/ASTPrinter.cpp | 63 ++++++-- lib/Driver/ToolChains.cpp | 2 + lib/Frontend/CompilerInvocation.cpp | 21 ++- lib/Frontend/ModuleInterfaceSupport.cpp | 16 +- .../Inputs/module_selector/blocklist.yml | 4 + test/ModuleInterface/module_selector.swift | 137 ++++++++++++++++++ 10 files changed, 245 insertions(+), 16 deletions(-) create mode 100644 test/ModuleInterface/Inputs/module_selector/blocklist.yml create mode 100644 test/ModuleInterface/module_selector.swift diff --git a/include/swift/AST/PrintOptions.h b/include/swift/AST/PrintOptions.h index 5cef5ca5ef934..9dbaa32354a0a 100644 --- a/include/swift/AST/PrintOptions.h +++ b/include/swift/AST/PrintOptions.h @@ -580,6 +580,9 @@ struct PrintOptions { /// with types sharing a name with a module. bool AliasModuleNames = false; + /// Use module selectors when printing names. + bool UseModuleSelectors = false; + /// Name of the modules that have been aliased in AliasModuleNames mode. /// Ideally we would use something other than a string to identify a module, /// but since one alias can apply to more than one module, strings happen @@ -769,6 +772,7 @@ struct PrintOptions { /// /// \see swift::emitSwiftInterface static PrintOptions printSwiftInterfaceFile(ModuleDecl *ModuleToPrint, + bool useModuleSelectors, bool preferTypeRepr, bool printFullConvention, InterfaceMode interfaceMode, diff --git a/include/swift/Basic/BlockListAction.def b/include/swift/Basic/BlockListAction.def index ffa570e27272f..7d3a1ef3f1ed6 100644 --- a/include/swift/Basic/BlockListAction.def +++ b/include/swift/Basic/BlockListAction.def @@ -27,5 +27,6 @@ BLOCKLIST_ACTION(ShouldDisableOwnershipVerification) BLOCKLIST_ACTION(SkipEmittingFineModuleTrace) BLOCKLIST_ACTION(SkipIndexingModule) BLOCKLIST_ACTION(ShouldUseTypeCheckerPerfHacks) +BLOCKLIST_ACTION(DisableModuleSelectorsInModuleInterface) #undef BLOCKLIST_ACTION diff --git a/include/swift/Frontend/ModuleInterfaceSupport.h b/include/swift/Frontend/ModuleInterfaceSupport.h index 6777eee8f10cf..5cf6480b6a9dd 100644 --- a/include/swift/Frontend/ModuleInterfaceSupport.h +++ b/include/swift/Frontend/ModuleInterfaceSupport.h @@ -40,6 +40,9 @@ struct ModuleInterfaceOptions { /// with types sharing a name with a module. bool AliasModuleNames = false; + /// Should we emit module selectors into the module interface? + bool UseModuleSelectors = false; + /// See \ref FrontendOptions.PrintFullConvention. /// [TODO: Clang-type-plumbing] This check should go away. bool PrintFullConvention = false; diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 85a11d114d03b..0ceda51d030e5 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -736,6 +736,16 @@ def emit_variant_package_module_interface_path : MetaVarName<"">, HelpText<"Output package module interface file for the target variant to ">; +def enable_module_selectors_in_module_interface : + Flag<["-"], "enable-module-selectors-in-module-interface">, + Flags<[FrontendOption, NoInteractiveOption]>, + HelpText<"When emitting module interface files, use module selectors to avoid name collisions">; + +def disable_module_selectors_in_module_interface : + Flag<["-"], "disable-module-selectors-in-module-interface">, + Flags<[FrontendOption, NoInteractiveOption]>, + HelpText<"When emitting module interface files, do not use module selectors to avoid name collisions">; + def verify_emitted_module_interface : Flag<["-"], "verify-emitted-module-interface">, Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>, diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 349f18e6fa01f..2f1777d4784fa 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -263,6 +263,7 @@ struct PrintWithOpaqueResultTypeKeywordRAII { }; PrintOptions PrintOptions::printSwiftInterfaceFile(ModuleDecl *ModuleToPrint, + bool useModuleSelectors, bool preferTypeRepr, bool printFullConvention, InterfaceMode interfaceMode, @@ -276,6 +277,7 @@ PrintOptions PrintOptions::printSwiftInterfaceFile(ModuleDecl *ModuleToPrint, result.PrintLongAttrsOnSeparateLines = true; result.TypeDefinitions = true; result.CurrentModule = ModuleToPrint; + result.UseModuleSelectors = useModuleSelectors; result.FullyQualifiedTypes = true; result.FullyQualifiedTypesIfAmbiguous = true; result.FullyQualifiedExtendedTypesIfAmbiguous = true; @@ -6058,9 +6060,8 @@ class TypePrinter : public TypeVisitorgetVisibleClangModules(Options.InterfaceContentKind); } - template - void printModuleContext(T *Ty) { - FileUnit *File = cast(Ty->getDecl()->getModuleScopeContext()); + void printModuleContext(GenericTypeDecl *TyDecl) { + FileUnit *File = cast(TyDecl->getModuleScopeContext()); ModuleDecl *Mod = File->getParentModule(); StringRef ExportedModuleName = File->getExportedModuleName(); @@ -6069,7 +6070,7 @@ class TypePrinter : public TypeVisitorgetDecl()->getClangDecl(); + const clang::Decl *ClangDecl = TyDecl->getClangDecl(); if (ClangDecl && Options.CurrentModule) { for (auto *Redecl : ClangDecl->redecls()) { auto *owningModule = Redecl->getOwningModule(); @@ -6106,12 +6107,10 @@ class TypePrinter : public TypeVisitorgetDecl(); - for (auto attr: D->getAttrs().getAttributes()) { + if (auto attr = + TyDecl->getAttrs().getAttribute()) { Name = Mod->getASTContext().getIdentifier( - const_cast(attr) - ->getManglingModuleName()); - break; + attr->getManglingModuleName()); } } @@ -6122,7 +6121,6 @@ class TypePrinter : public TypeVisitor @@ -6140,7 +6138,42 @@ class TypePrinter : public TypeVisitorgetRealName().str().starts_with(LLDB_EXPRESSIONS_MODULE_NAME_PREFIX); } + bool isMemberOfGenericParameter(TypeBase *T) { + Type parent = nullptr; + if (auto alias = dyn_cast(T)) + parent = alias->getParent(); + else if (auto generic = T->getAs()) + parent = generic->getParent(); + return parent && parent->isTypeParameter(); + } + + bool shouldPrintModuleSelector(TypeBase *T) { + if (!Options.UseModuleSelectors) + return false; + + GenericTypeDecl *GTD = T->getAnyGeneric(); + if (!GTD && isa(T)) + GTD = cast(T)->getDecl(); + if (!GTD) + return false; + + // Builtin types must always be qualified somehow. + ModuleDecl *M = GTD->getDeclContext()->getParentModule(); + if (M->isBuiltinModule()) + return true; + + // A member of a generic parameter can't be qualified by a module selector. + if (isMemberOfGenericParameter(T)) + return false; + + // Module selectors skip over local types, so don't add one. + return GTD->getLocalContext() == nullptr; + } + bool shouldPrintFullyQualified(TypeBase *T) { + if (Options.UseModuleSelectors) + return false; + if (Options.FullyQualifiedTypes) return true; @@ -6197,7 +6230,15 @@ class TypePrinter : public TypeVisitorgetDecl()); + Printer << "."; + NameContext = PrintNameContext::TypeMember; + } + + // We print module selectors whether or not we printed a parent type. + if (shouldPrintModuleSelector(Ty)) { + printModuleContext(Ty->getDecl()); + Printer << "::"; NameContext = PrintNameContext::TypeMember; } diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 9008afcb2070b..dda7052b50382 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -316,6 +316,8 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI, inputArgs.AddLastArg(arguments, options::OPT_module_cache_path); inputArgs.AddLastArg(arguments, options::OPT_module_link_name); inputArgs.AddLastArg(arguments, options::OPT_module_abi_name); + inputArgs.AddLastArg(arguments, options::OPT_enable_module_selectors_in_module_interface, + options::OPT_disable_module_selectors_in_module_interface); inputArgs.AddLastArg(arguments, options::OPT_package_name); inputArgs.AddLastArg(arguments, options::OPT_export_as); inputArgs.AddLastArg(arguments, options::OPT_nostdimport); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 568105785a041..f31d31ca493a9 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -536,7 +536,8 @@ static void PrintArg(raw_ostream &OS, const char *Arg, StringRef TempDir) { } static void ParseModuleInterfaceArgs(ModuleInterfaceOptions &Opts, - ArgList &Args) { + ArgList &Args, + DiagnosticEngine &diags) { using namespace options; Opts.PreserveTypesAsWritten |= @@ -545,6 +546,7 @@ static void ParseModuleInterfaceArgs(ModuleInterfaceOptions &Opts, Args.hasFlag(OPT_alias_module_names_in_module_interface, OPT_disable_alias_module_names_in_module_interface, ::getenv("SWIFT_ALIAS_MODULE_NAMES_IN_INTERFACES")); + Opts.PrintFullConvention |= Args.hasArg(OPT_experimental_print_full_convention); Opts.DebugPrintInvalidSyntax |= @@ -558,6 +560,21 @@ static void ParseModuleInterfaceArgs(ModuleInterfaceOptions &Opts, Opts.setInterfaceMode(PrintOptions::InterfaceMode::Private); } } + + if (Args.hasArgNoClaim(OPT_enable_module_selectors_in_module_interface) + || Args.hasArgNoClaim(OPT_disable_module_selectors_in_module_interface)) { + Opts.UseModuleSelectors = + Args.hasFlag(OPT_enable_module_selectors_in_module_interface, + OPT_disable_module_selectors_in_module_interface, + false); + } else if (auto envValue = ::getenv("SWIFT_MODULE_SELECTORS_IN_INTERFACES")) { + Opts.UseModuleSelectors = llvm::StringSwitch(envValue) + .CasesLower("false", "no", "off", "0", false) + .Default(true); + } else { + // Any heuristics we might add would go here. + Opts.UseModuleSelectors = false; + } } /// Checks if an arg is generally allowed to be included @@ -4169,7 +4186,7 @@ bool CompilerInvocation::parseArgs( setMainExecutablePath(mainExecutablePath); } - ParseModuleInterfaceArgs(ModuleInterfaceOpts, ParsedArgs); + ParseModuleInterfaceArgs(ModuleInterfaceOpts, ParsedArgs, Diags); SaveModuleInterfaceArgs(ModuleInterfaceOpts, FrontendOpts, ParsedArgs, Diags); if (ParseCASArgs(CASOpts, ParsedArgs, Diags, FrontendOpts)) { diff --git a/lib/Frontend/ModuleInterfaceSupport.cpp b/lib/Frontend/ModuleInterfaceSupport.cpp index 04877b8e3eea4..72b8d48973887 100644 --- a/lib/Frontend/ModuleInterfaceSupport.cpp +++ b/lib/Frontend/ModuleInterfaceSupport.cpp @@ -884,13 +884,22 @@ bool swift::emitSwiftInterface(raw_ostream &out, printImports(out, Opts, M, aliasModuleNamesTargets); - bool useExportedModuleNames = Opts.printPublicInterface(); + // Apply module selector blocklist. + bool useModuleSelectors = Opts.UseModuleSelectors; + if (useModuleSelectors && M->getASTContext().blockListConfig + .hasBlockListAction(M->getNameStr(), BlockListKeyKind::ModuleName, + BlockListAction:: + DisableModuleSelectorsInModuleInterface)) + useModuleSelectors = false; + bool useExportedModuleNames = Opts.printPublicInterface(); const PrintOptions printOptions = PrintOptions::printSwiftInterfaceFile( - M, Opts.PreserveTypesAsWritten, Opts.PrintFullConvention, + M, useModuleSelectors, Opts.PreserveTypesAsWritten, + Opts.PrintFullConvention, Opts.InterfaceContentMode, useExportedModuleNames, Opts.AliasModuleNames, &aliasModuleNamesTargets); + InheritedProtocolCollector::PerTypeMap inheritedProtocolMap; SmallVector topLevelDecls; @@ -909,7 +918,8 @@ bool swift::emitSwiftInterface(raw_ostream &out, D->print(out, printOptions); out << "\n"; - diagnoseIfDeclShadowsKnownModule(Opts, const_cast(D), M); + if (!useModuleSelectors) + diagnoseIfDeclShadowsKnownModule(Opts, const_cast(D), M); } // Print dummy extensions for any protocols that were indirectly conformed to. diff --git a/test/ModuleInterface/Inputs/module_selector/blocklist.yml b/test/ModuleInterface/Inputs/module_selector/blocklist.yml new file mode 100644 index 0000000000000..f236cbbff3fee --- /dev/null +++ b/test/ModuleInterface/Inputs/module_selector/blocklist.yml @@ -0,0 +1,4 @@ +--- +DisableModuleSelectorsInModuleInterface: + ModuleName: + - TestCase diff --git a/test/ModuleInterface/module_selector.swift b/test/ModuleInterface/module_selector.swift new file mode 100644 index 0000000000000..4fdbcfcfd85c0 --- /dev/null +++ b/test/ModuleInterface/module_selector.swift @@ -0,0 +1,137 @@ +// RUN: %empty-directory(%t) + +// Test with -enable-module-selectors-in-module-interface +// RUN: %empty-directory(%t/enabled) +// RUN: %target-swift-emit-module-interface(%t/enabled/TestCase.swiftinterface) %s %clang-importer-sdk -F %clang-importer-sdk-path/frameworks -I %S/Inputs/module_selector -target %target-stable-abi-triple -module-name TestCase -enable-module-selectors-in-module-interface +// RUN: %FileCheck --input-file %t/enabled/TestCase.swiftinterface %s --check-prefixes CHECK,CHECK-ENABLED +// RUN: %target-swift-typecheck-module-from-interface(%t/enabled/TestCase.swiftinterface) %clang-importer-sdk -F %clang-importer-sdk-path/frameworks -I %S/Inputs/module_selector -target %target-stable-abi-triple -module-name TestCase + +// Test with -disable-module-selectors-in-module-interface +// RUN: %empty-directory(%t/disabled) +// RUN: %target-swift-emit-module-interface(%t/disabled/TestCase.swiftinterface) %s %clang-importer-sdk -F %clang-importer-sdk-path/frameworks -I %S/Inputs/module_selector -target %target-stable-abi-triple -module-name TestCase -disable-module-selectors-in-module-interface +// RUN: %FileCheck --input-file %t/disabled/TestCase.swiftinterface %s --check-prefixes CHECK,CHECK-DISABLED +// RUN: %target-swift-typecheck-module-from-interface(%t/disabled/TestCase.swiftinterface) %clang-importer-sdk -F %clang-importer-sdk-path/frameworks -I %S/Inputs/module_selector -target %target-stable-abi-triple -module-name TestCase + +// Test default behavior +// RUN: %empty-directory(%t/default) +// RUN: %target-swift-emit-module-interface(%t/default/TestCase.swiftinterface) %s %clang-importer-sdk -F %clang-importer-sdk-path/frameworks -I %S/Inputs/module_selector -target %target-stable-abi-triple -module-name TestCase +// RUN: %FileCheck --input-file %t/default/TestCase.swiftinterface %s --check-prefixes CHECK,CHECK-DISABLED +// RUN: %target-swift-typecheck-module-from-interface(%t/default/TestCase.swiftinterface) %clang-importer-sdk -F %clang-importer-sdk-path/frameworks -I %S/Inputs/module_selector -target %target-stable-abi-triple -module-name TestCase + +// Test with -enable-module-selectors-in-module-interface and blocklist +// RUN: %empty-directory(%t/blocked) +// RUN: %target-swift-emit-module-interface(%t/blocked/TestCase.swiftinterface) %s %clang-importer-sdk -F %clang-importer-sdk-path/frameworks -I %S/Inputs/module_selector -target %target-stable-abi-triple -module-name TestCase -enable-module-selectors-in-module-interface -blocklist-file %S/Inputs/module_selector/blocklist.yml +// RUN: %FileCheck --input-file %t/blocked/TestCase.swiftinterface %s --check-prefixes CHECK,CHECK-DISABLED +// RUN: %target-swift-typecheck-module-from-interface(%t/blocked/TestCase.swiftinterface) %clang-importer-sdk -F %clang-importer-sdk-path/frameworks -I %S/Inputs/module_selector -target %target-stable-abi-triple -module-name TestCase + +// CHECK: import enums_using_attributes +import enums_using_attributes + +// CHECK-LABEL: public struct Struct : +// CHECK-ENABLED-SAME: Swift::Hashable where T : Swift::Hashable { +// CHECK-DISABLED-SAME: Swift.Hashable where T : Swift.Hashable { +public struct Struct: Hashable { + // CHECK: public let integer: + // CHECK-ENABLED-SAME: Swift::Int + // CHECK-DISABLED-SAME: Swift.Int + public let integer: Int = 42 + + // CHECK: public let enumeration: + // CHECK-ENABLED-SAME: enums_using_attributes::CFEnumWithAttr + // CHECK-DISABLED-SAME: enums_using_attributes.CFEnumWithAttr + public let enumeration: CFEnumWithAttr = CFEnumWithAttr.first + + // CHECK: public let t: T? + public let t: T? = nil + + // CHECK: public static func == + // CHECK-ENABLED-SAME: (a: TestCase::Struct, b: TestCase::Struct) -> Swift::Bool + // CHECK-DISABLED-SAME: (a: TestCase.Struct, b: TestCase.Struct) -> Swift.Bool + + // CHECK: public func hash + // CHECK-ENABLED-SAME: (into hasher: inout Swift::Hasher) + // CHECK-DISABLED-SAME: (into hasher: inout Swift.Hasher) + + // CHECK: public var hashValue: + // CHECK-ENABLED-SAME: Swift::Int { + // CHECK-DISABLED-SAME: Swift.Int { + + // CHECK: } +} + +// CHECK-ENABLED: extension TestCase::Struct { +// CHECK-DISABLED: extension TestCase.Struct { +extension Struct { + // CHECK-LABEL: public enum Nested { + public enum Nested { + // CHECK: case integer + // CHECK-ENABLED-SAME: (Swift::Int) + // CHECK-DISABLED-SAME: (Swift.Int) + case integer(Int) + + // CHECK: case enumeration + // CHECK-ENABLED-SAME: (enums_using_attributes::CFEnumWithAttr) + // CHECK-DISABLED-SAME: (enums_using_attributes.CFEnumWithAttr) + case enumeration(CFEnumWithAttr) + + // CHECK: case t(T) + case t(T) + + // CHECK: case `struct` + // CHECK-ENABLED-SAME: (TestCase::Struct) + // CHECK-DISABLED-SAME: (TestCase.Struct) + case `struct`(Struct) + + // CHECK: } + } + + // CHECK: } +} + +// CHECK-ENABLED: extension Swift::Int { +// CHECK-DISABLED: extension Swift.Int { +extension Swift::Int { + // CHECK-LABEL: public enum RetroactiveNested { + public enum RetroactiveNested {} +} + +// CHECK-ENABLED: extension Swift::Int.TestCase::RetroactiveNested { +// CHECK-DISABLED: extension Swift.Int.RetroactiveNested { +extension Int.RetroactiveNested { + public func anchor() {} +} + +// CHECK-LABEL: public func fn +// CHECK-ENABLED-SAME: (_: TestCase::Struct, _: TestCase::Struct.TestCase::Nested) +// CHECK-DISABLED-SAME: (_: TestCase.Struct, _: TestCase.Struct.Nested) +public func fn(_: Struct, _: Struct.Nested) {} + +// CHECK-LABEL: public func fn2 +// CHECK-ENABLED-SAME: (_: T) where T : Swift::Identifiable, T.ID == TestCase::Struct +// CHECK-DISABLED-SAME: (_: T) where T : Swift.Identifiable, T.ID == TestCase.Struct +@available(SwiftStdlib 5.1, *) +public func fn2(_: T) where T.ID == Struct {} + +// CHECK-LABEL: public protocol Proto { +@available(SwiftStdlib 5.1, *) +public protocol Proto { + // CHECK: associatedtype AssocType : + // CHECK-ENABLED-SAME: Swift::Identifiable + // CHECK-DISABLED-SAME: Swift.Identifiable + associatedtype AssocType: Identifiable + + // CHECK: typealias TypeAlias = + // CHECK-ENABLED-SAME: TestCase::Struct + // CHECK-DISABLED-SAME: TestCase.Struct + typealias TypeAlias = Struct + + // CHECK: func requirement() -> Self.AssocType.ID + func requirement() -> AssocType.ID + + // CHECK: func requirement2() -> + // CHECK-ENABLED: Self.TypeAlias.TestCase::Nested + // CHECK-DISABLED: Self.TypeAlias.Nested + func requirement2() -> TypeAlias.Nested + + // CHECK: } +}