mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Emit module selectors in swiftinterfaces
This support is currently opt-in and can be disabled by a blocklist.
This commit is contained in:
@@ -580,6 +580,9 @@ public:
|
||||
/// 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 @@ public:
|
||||
///
|
||||
/// \see swift::emitSwiftInterface
|
||||
static PrintOptions printSwiftInterfaceFile(ModuleDecl *ModuleToPrint,
|
||||
bool useModuleSelectors,
|
||||
bool preferTypeRepr,
|
||||
bool printFullConvention,
|
||||
InterfaceMode interfaceMode,
|
||||
|
||||
@@ -27,5 +27,6 @@ BLOCKLIST_ACTION(ShouldDisableOwnershipVerification)
|
||||
BLOCKLIST_ACTION(SkipEmittingFineModuleTrace)
|
||||
BLOCKLIST_ACTION(SkipIndexingModule)
|
||||
BLOCKLIST_ACTION(ShouldUseTypeCheckerPerfHacks)
|
||||
BLOCKLIST_ACTION(DisableModuleSelectorsInModuleInterface)
|
||||
|
||||
#undef BLOCKLIST_ACTION
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -736,6 +736,16 @@ def emit_variant_package_module_interface_path :
|
||||
MetaVarName<"<path>">,
|
||||
HelpText<"Output package module interface file for the target variant to <path>">;
|
||||
|
||||
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]>,
|
||||
|
||||
@@ -263,6 +263,7 @@ private:
|
||||
};
|
||||
|
||||
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 TypeVisitor<TypePrinter, void, NonRecursivePrintOptio
|
||||
return Options.CurrentModule->getVisibleClangModules(Options.InterfaceContentKind);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void printModuleContext(T *Ty) {
|
||||
FileUnit *File = cast<FileUnit>(Ty->getDecl()->getModuleScopeContext());
|
||||
void printModuleContext(GenericTypeDecl *TyDecl) {
|
||||
FileUnit *File = cast<FileUnit>(TyDecl->getModuleScopeContext());
|
||||
ModuleDecl *Mod = File->getParentModule();
|
||||
StringRef ExportedModuleName = File->getExportedModuleName();
|
||||
|
||||
@@ -6069,7 +6070,7 @@ class TypePrinter : public TypeVisitor<TypePrinter, void, NonRecursivePrintOptio
|
||||
// all of these modules may be visible. We therefore need to make sure we
|
||||
// choose a module that is visible from the current module. This is possible
|
||||
// only if we know what the current module is.
|
||||
const clang::Decl *ClangDecl = Ty->getDecl()->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 TypeVisitor<TypePrinter, void, NonRecursivePrintOptio
|
||||
}
|
||||
|
||||
if (Options.UseOriginallyDefinedInModuleNames) {
|
||||
Decl *D = Ty->getDecl();
|
||||
for (auto attr: D->getAttrs().getAttributes<OriginallyDefinedInAttr>()) {
|
||||
if (auto attr =
|
||||
TyDecl->getAttrs().getAttribute<OriginallyDefinedInAttr>()) {
|
||||
Name = Mod->getASTContext().getIdentifier(
|
||||
const_cast<OriginallyDefinedInAttr *>(attr)
|
||||
->getManglingModuleName());
|
||||
break;
|
||||
attr->getManglingModuleName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6122,7 +6121,6 @@ class TypePrinter : public TypeVisitor<TypePrinter, void, NonRecursivePrintOptio
|
||||
}
|
||||
|
||||
Printer.printModuleRef(Mod, Name);
|
||||
Printer << ".";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -6140,7 +6138,42 @@ class TypePrinter : public TypeVisitor<TypePrinter, void, NonRecursivePrintOptio
|
||||
return M->getRealName().str().starts_with(LLDB_EXPRESSIONS_MODULE_NAME_PREFIX);
|
||||
}
|
||||
|
||||
bool isMemberOfGenericParameter(TypeBase *T) {
|
||||
Type parent = nullptr;
|
||||
if (auto alias = dyn_cast<TypeAliasType>(T))
|
||||
parent = alias->getParent();
|
||||
else if (auto generic = T->getAs<AnyGenericType>())
|
||||
parent = generic->getParent();
|
||||
return parent && parent->isTypeParameter();
|
||||
}
|
||||
|
||||
bool shouldPrintModuleSelector(TypeBase *T) {
|
||||
if (!Options.UseModuleSelectors)
|
||||
return false;
|
||||
|
||||
GenericTypeDecl *GTD = T->getAnyGeneric();
|
||||
if (!GTD && isa<TypeAliasType>(T))
|
||||
GTD = cast<TypeAliasType>(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 @@ public:
|
||||
printParentType(parent);
|
||||
NameContext = PrintNameContext::TypeMember;
|
||||
} else if (shouldPrintFullyQualified(Ty)) {
|
||||
printModuleContext(Ty);
|
||||
printModuleContext(Ty->getDecl());
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<bool>(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)) {
|
||||
|
||||
@@ -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<Decl *, 16> topLevelDecls;
|
||||
@@ -909,7 +918,8 @@ bool swift::emitSwiftInterface(raw_ostream &out,
|
||||
D->print(out, printOptions);
|
||||
out << "\n";
|
||||
|
||||
diagnoseIfDeclShadowsKnownModule(Opts, const_cast<Decl *>(D), M);
|
||||
if (!useModuleSelectors)
|
||||
diagnoseIfDeclShadowsKnownModule(Opts, const_cast<Decl *>(D), M);
|
||||
}
|
||||
|
||||
// Print dummy extensions for any protocols that were indirectly conformed to.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
DisableModuleSelectorsInModuleInterface:
|
||||
ModuleName:
|
||||
- TestCase
|
||||
137
test/ModuleInterface/module_selector.swift
Normal file
137
test/ModuleInterface/module_selector.swift
Normal file
@@ -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<T> :
|
||||
// CHECK-ENABLED-SAME: Swift::Hashable where T : Swift::Hashable {
|
||||
// CHECK-DISABLED-SAME: Swift.Hashable where T : Swift.Hashable {
|
||||
public struct Struct<T: Hashable>: 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<T>, b: TestCase::Struct<T>) -> Swift::Bool
|
||||
// CHECK-DISABLED-SAME: (a: TestCase.Struct<T>, b: TestCase.Struct<T>) -> 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<T>)
|
||||
// CHECK-DISABLED-SAME: (TestCase.Struct<T>)
|
||||
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<T>
|
||||
// CHECK-ENABLED-SAME: (_: TestCase::Struct<T>, _: TestCase::Struct<T>.TestCase::Nested)
|
||||
// CHECK-DISABLED-SAME: (_: TestCase.Struct<T>, _: TestCase.Struct<T>.Nested)
|
||||
public func fn<T: Hashable>(_: Struct<T>, _: Struct<T>.Nested) {}
|
||||
|
||||
// CHECK-LABEL: public func fn2<T>
|
||||
// CHECK-ENABLED-SAME: (_: T) where T : Swift::Identifiable, T.ID == TestCase::Struct<Swift::Int>
|
||||
// CHECK-DISABLED-SAME: (_: T) where T : Swift.Identifiable, T.ID == TestCase.Struct<Swift.Int>
|
||||
@available(SwiftStdlib 5.1, *)
|
||||
public func fn2<T: Identifiable>(_: T) where T.ID == Struct<Int> {}
|
||||
|
||||
// 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<Swift::Int>
|
||||
// CHECK-DISABLED-SAME: TestCase.Struct<Swift.Int>
|
||||
typealias TypeAlias = Struct<Int>
|
||||
|
||||
// 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: }
|
||||
}
|
||||
Reference in New Issue
Block a user