diff --git a/include/swift/AST/ASTDemangler.h b/include/swift/AST/ASTDemangler.h index 3218d5ed448b2..58bcf68281a23 100644 --- a/include/swift/AST/ASTDemangler.h +++ b/include/swift/AST/ASTDemangler.h @@ -158,6 +158,8 @@ class ASTBuilder { Type createBoundGenericType(GenericTypeDecl *decl, ArrayRef args); + OpaqueTypeDecl *resolveOpaqueTypeDecl(NodePointer opaqueDescriptor); + Type resolveOpaqueType(NodePointer opaqueDescriptor, ArrayRef> args, unsigned ordinal); diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index b7900ee2723da..65e846435d357 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -332,8 +332,7 @@ Type ASTBuilder::createTypeAliasType(GenericTypeDecl *decl, Type parent) { static SubstitutionMap createSubstitutionMapFromGenericArgs(GenericSignature genericSig, - ArrayRef args, - LookupConformanceFn lookupConformance) { + ArrayRef args) { if (!genericSig) return SubstitutionMap(); @@ -341,15 +340,7 @@ createSubstitutionMapFromGenericArgs(GenericSignature genericSig, return SubstitutionMap(); return SubstitutionMap::get( - genericSig, - [&](SubstitutableType *t) -> Type { - auto *gp = cast(t); - unsigned ordinal = genericSig->getGenericParamOrdinal(gp); - if (ordinal < args.size()) - return args[ordinal]; - return Type(); - }, - lookupConformance); + genericSig, args, LookUpConformanceInModule()); } Type ASTBuilder::createBoundGenericType(GenericTypeDecl *decl, @@ -364,8 +355,7 @@ Type ASTBuilder::createBoundGenericType(GenericTypeDecl *decl, // Build a SubstitutionMap. auto genericSig = nominalDecl->getGenericSignature(); - auto subs = createSubstitutionMapFromGenericArgs( - genericSig, args, LookUpConformanceInModule()); + auto subs = createSubstitutionMapFromGenericArgs(genericSig, args); if (!subs) return Type(); auto origType = nominalDecl->getDeclaredInterfaceType(); @@ -375,48 +365,53 @@ Type ASTBuilder::createBoundGenericType(GenericTypeDecl *decl, return origType.subst(subs); } -Type ASTBuilder::resolveOpaqueType(NodePointer opaqueDescriptor, - ArrayRef> args, - unsigned ordinal) { - if (opaqueDescriptor->getKind() == Node::Kind::OpaqueReturnTypeOf) { - auto definingDecl = opaqueDescriptor->getChild(0); - auto definingGlobal = Factory.createNode(Node::Kind::Global); - definingGlobal->addChild(definingDecl, Factory); - auto mangling = mangleNode(definingGlobal, ManglingFlavor); - if (!mangling.isSuccess()) - return Type(); - auto mangledName = mangling.result(); +OpaqueTypeDecl *ASTBuilder::resolveOpaqueTypeDecl(NodePointer opaqueDescriptor) { + if (opaqueDescriptor->getKind() != Node::Kind::OpaqueReturnTypeOf) + return nullptr; - auto moduleNode = findModuleNode(definingDecl); - if (!moduleNode) - return Type(); + auto definingDecl = opaqueDescriptor->getChild(0); + auto definingGlobal = Factory.createNode(Node::Kind::Global); + definingGlobal->addChild(definingDecl, Factory); + auto mangling = mangleNode(definingGlobal, ManglingFlavor); + if (!mangling.isSuccess()) + return nullptr; + auto mangledName = mangling.result(); - ModuleDecl *scratch; - auto potentialParentModules = findPotentialModules(moduleNode, scratch); - if (potentialParentModules.empty()) - return Type(); + auto moduleNode = findModuleNode(definingDecl); + if (!moduleNode) + return nullptr; - OpaqueTypeDecl *opaqueDecl = nullptr; - for (auto module : potentialParentModules) - if (auto decl = module->lookupOpaqueResultType(mangledName)) - opaqueDecl = decl; + ModuleDecl *scratch; + auto potentialParentModules = findPotentialModules(moduleNode, scratch); + if (potentialParentModules.empty()) + return nullptr; - if (!opaqueDecl) - return Type(); - SmallVector allArgs; - for (auto argSet : args) { - allArgs.append(argSet.begin(), argSet.end()); - } + for (auto module : potentialParentModules) + if (auto decl = module->lookupOpaqueResultType(mangledName)) + return decl; + + return nullptr; +} + +Type ASTBuilder::resolveOpaqueType(NodePointer opaqueDescriptor, + ArrayRef> args, + unsigned ordinal) { + OpaqueTypeDecl *opaqueDecl = resolveOpaqueTypeDecl(opaqueDescriptor); + if (!opaqueDecl) + return Type(); - SubstitutionMap subs = createSubstitutionMapFromGenericArgs( - opaqueDecl->getGenericSignature(), allArgs, - LookUpConformanceInModule()); - Type interfaceType = opaqueDecl->getOpaqueGenericParams()[ordinal]; - return OpaqueTypeArchetypeType::get(opaqueDecl, interfaceType, subs); + SmallVector allArgs; + for (auto argSet : args) { + allArgs.append(argSet.begin(), argSet.end()); } - - // TODO: named opaque types - return Type(); + + if (ordinal >= opaqueDecl->getOpaqueGenericParams().size()) + return Type(); + + SubstitutionMap subs = createSubstitutionMapFromGenericArgs( + opaqueDecl->getGenericSignature(), allArgs); + Type interfaceType = opaqueDecl->getOpaqueGenericParams()[ordinal]; + return OpaqueTypeArchetypeType::get(opaqueDecl, interfaceType, subs); } Type ASTBuilder::createBoundGenericType(GenericTypeDecl *decl, @@ -1143,8 +1138,7 @@ Type ASTBuilder::createSILBoxTypeWithLayout( SubstitutionMap substs; if (signature) substs = createSubstitutionMapFromGenericArgs( - signature, replacements, - LookUpConformanceInModule()); + signature, replacements); return SILBoxType::get(Ctx, layout, substs); } diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index d23bcd445deec..99fce169bc559 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -7515,10 +7515,37 @@ class TypePrinter : public TypeVisitorgetASTContext(), - genericSig.getGenericParams(), - T->getSubstitutions().getReplacementTypes()); + auto &ctx = decl->getASTContext(); + auto params = genericSig.getGenericParams(); + auto args = T->getSubstitutions().getReplacementTypes(); + + // Use the new "nested" syntax if there is at least one parameter pack, + // because that case didn't round trip at all before anyway. Otherwise, + // use the old "flat" syntax, even when the owner declaration is in a + // nested generic context, because we want the generated swiftinterface + // to continue to work on old compilers. + if (genericSig->hasParameterPack()) { + bool first = true; + + while (!params.empty()) { + if (!first) { Printer << ".__"; } + first = false; + + unsigned end = 1; + unsigned depth = params.front()->getDepth(); + while (end < params.size() && params[end]->getDepth() == depth) { + ++end; + } + + printGenericArgs(ctx, params.take_front(end), args.take_front(end)); + params = params.slice(end); + args = args.slice(end); + } + } else { + printGenericArgs(ctx, params, args); + } } + return; } case PrintOptions::OpaqueReturnTypePrintingMode::Description: { diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index 392e69483f314..8a964165eb4d2 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -581,8 +581,7 @@ namespace { void addGenericParameters() { GenericSignature sig = asImpl().getGenericSignature(); auto metadata = - irgen::addGenericParameters(IGM, B, - asImpl().getGenericSignature(), + irgen::addGenericParameters(IGM, B, sig, /*implicit=*/false); assert(metadata.NumParams == metadata.NumParamsEmitted && "We can't use implicit GenericParamDescriptors here"); diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 49179465b47eb..e3707e4e56003 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -827,6 +827,130 @@ namespace { }; } +/// Returns true on error. +static bool resolveGenericArguments(ValueDecl *decl, + const GenericContext *genCtx, + const TypeResolution &resolution, + SILTypeResolutionContext *silContext, + DeclRefTypeRepr *repr, + SmallVectorImpl &args) { + auto options = resolution.getOptions(); + auto &ctx = decl->getASTContext(); + + auto genericParams = genCtx->getGenericParams(); + auto hasParameterPack = llvm::any_of(*genericParams, [](auto *paramDecl) { + return paramDecl->isParameterPack(); + }); + auto hasValueParam = llvm::any_of(*genericParams, [](auto *paramDecl) { + return paramDecl->isValue(); + }); + + // If the type declares at least one parameter pack, allow pack expansions + // anywhere in the argument list. We'll use the PackMatcher to ensure that + // everything lines up. Otherwise, don't allow pack expansions to appear + // at all. + auto argOptions = options.withoutContext().withContext( + hasParameterPack + ? TypeResolverContext::VariadicGenericArgument + : TypeResolverContext::ScalarGenericArgument); + if (hasValueParam) + argOptions = argOptions.withContext(TypeResolverContext::ValueGenericArgument); + auto genericResolution = resolution.withOptions(argOptions); + + // In SIL mode, Optional interprets T as a SIL type. + if (options.contains(TypeResolutionFlags::SILType)) { + if (auto nominal = dyn_cast(genCtx)) { + if (nominal->isOptionalDecl()) { + genericResolution = resolution; + } + } + } + + auto genericArgs = repr->getGenericArgs(); + auto loc = repr->getNameLoc().getBaseNameLoc(); + + // Resolve the types of the generic arguments. + for (auto tyR : genericArgs) { + // Propagate failure. + Type substTy = genericResolution.resolveType(tyR, silContext); + if (!substTy || substTy->hasError()) + return true; + + args.push_back(substTy); + } + + // Make sure we have the right number of generic arguments. + if (!hasParameterPack) { + // For generic types without type parameter packs, we require + // the number of declared generic parameters match the number of + // arguments. + if (genericArgs.size() != genericParams->size()) { + if (!options.contains(TypeResolutionFlags::SilenceErrors)) { + diagnoseInvalidGenericArguments( + loc, decl, genericArgs.size(), genericParams->size(), + /*hasParameterPack=*/false, repr->getAngleBrackets()); + } + return true; + } + + return false; + } + + // For generic types with type parameter packs, we only require + // that the number of arguments is enough to saturate the number of + // regular generic parameters. The parameter pack will absorb + // zero or arguments. + SmallVector params; + for (auto paramDecl : genericParams->getParams()) { + auto paramType = paramDecl->getDeclaredInterfaceType(); + params.push_back(paramDecl->isParameterPack() + ? PackExpansionType::get(paramType, paramType) + : paramType); + } + + PackMatcher matcher(params, args, ctx); + if (matcher.match() || matcher.pairs.size() != params.size()) { + if (!options.contains(TypeResolutionFlags::SilenceErrors)) { + diagnoseInvalidGenericArguments( + loc, decl, genericArgs.size(), genericParams->size(), + /*hasParameterPack=*/true, repr->getAngleBrackets()); + } + return true; + } + + args.clear(); + for (unsigned i : indices(params)) { + auto found = std::find_if(matcher.pairs.begin(), + matcher.pairs.end(), + [&](const MatchedPair &pair) -> bool { + return pair.lhsIdx == i; + }); + assert(found != matcher.pairs.end()); + + auto arg = found->rhs; + + // PackMatcher will always produce a PackExpansionType as the + // arg for a pack parameter, if necessary by wrapping a PackType + // in one. (It's a weird representation.) Look for that pattern + // and unwrap the pack. Otherwise, we must have matched with a + // single component which happened to be an expansion; wrap that + // in a PackType. In either case, we always want arg to end up + // a PackType. + if (auto *expansionType = arg->getAs()) { + auto pattern = expansionType->getPatternType(); + if (auto pack = pattern->getAs()) { + arg = pack; + } else { + arg = PackType::get(ctx, {expansionType}); + } + } + + args.push_back(arg); + } + + return false; +} + /// Apply generic arguments to the given type. /// /// If the type is itself not generic, this does nothing. @@ -1005,112 +1129,10 @@ static Type applyGenericArguments(Type type, auto *unboundType = type->castTo(); auto *decl = unboundType->getDecl(); - auto genericParams = decl->getGenericParams(); - auto hasParameterPack = llvm::any_of(*genericParams, [](auto *paramDecl) { - return paramDecl->isParameterPack(); - }); - auto hasValueParam = llvm::any_of(*genericParams, [](auto *paramDecl) { - return paramDecl->isValue(); - }); - - // If the type declares at least one parameter pack, allow pack expansions - // anywhere in the argument list. We'll use the PackMatcher to ensure that - // everything lines up. Otherwise, don't allow pack expansions to appear - // at all. - auto argOptions = options.withoutContext().withContext( - hasParameterPack - ? TypeResolverContext::VariadicGenericArgument - : TypeResolverContext::ScalarGenericArgument); - if (hasValueParam) - argOptions = argOptions.withContext(TypeResolverContext::ValueGenericArgument); - auto genericResolution = resolution.withOptions(argOptions); - - // In SIL mode, Optional interprets T as a SIL type. - if (options.contains(TypeResolutionFlags::SILType)) { - if (auto nominal = dyn_cast(decl)) { - if (nominal->isOptionalDecl()) { - genericResolution = resolution; - } - } - } - // Resolve the types of the generic arguments. SmallVector args; - for (auto tyR : genericArgs) { - // Propagate failure. - Type substTy = genericResolution.resolveType(tyR, silContext); - if (!substTy || substTy->hasError()) - return ErrorType::get(ctx); - - args.push_back(substTy); - } - - // Make sure we have the right number of generic arguments. - if (!hasParameterPack) { - // For generic types without type parameter packs, we require - // the number of declared generic parameters match the number of - // arguments. - if (genericArgs.size() != genericParams->size()) { - if (!options.contains(TypeResolutionFlags::SilenceErrors)) { - diagnoseInvalidGenericArguments( - loc, decl, genericArgs.size(), genericParams->size(), - /*hasParameterPack=*/false, repr->getAngleBrackets()); - } - return ErrorType::get(ctx); - } - } else { - // For generic types with type parameter packs, we only require - // that the number of arguments is enough to saturate the number of - // regular generic parameters. The parameter pack will absorb - // zero or arguments. - SmallVector params; - for (auto paramDecl : genericParams->getParams()) { - auto paramType = paramDecl->getDeclaredInterfaceType(); - params.push_back(paramDecl->isParameterPack() - ? PackExpansionType::get(paramType, paramType) - : paramType); - } - - PackMatcher matcher(params, args, ctx); - if (matcher.match() || matcher.pairs.size() != params.size()) { - if (!options.contains(TypeResolutionFlags::SilenceErrors)) { - diagnoseInvalidGenericArguments( - loc, decl, genericArgs.size(), genericParams->size(), - /*hasParameterPack=*/true, repr->getAngleBrackets()); - } - return ErrorType::get(ctx); - } - - args.clear(); - for (unsigned i : indices(params)) { - auto found = std::find_if(matcher.pairs.begin(), - matcher.pairs.end(), - [&](const MatchedPair &pair) -> bool { - return pair.lhsIdx == i; - }); - assert(found != matcher.pairs.end()); - - auto arg = found->rhs; - - // PackMatcher will always produce a PackExpansionType as the - // arg for a pack parameter, if necessary by wrapping a PackType - // in one. (It's a weird representation.) Look for that pattern - // and unwrap the pack. Otherwise, we must have matched with a - // single component which happened to be an expansion; wrap that - // in a PackType. In either case, we always want arg to end up - // a PackType. - if (auto *expansionType = arg->getAs()) { - auto pattern = expansionType->getPatternType(); - if (auto pack = pattern->getAs()) { - arg = pack; - } else { - arg = PackType::get(ctx, {expansionType}); - } - } - - args.push_back(arg); - } - } + if (resolveGenericArguments(decl, decl, resolution, silContext, repr, args)) + return ErrorType::get(ctx); // Construct the substituted type. const auto result = resolution.applyUnboundGenericArguments( @@ -1130,6 +1152,7 @@ static Type applyGenericArguments(Type type, if (auto clangDecl = decl->getClangDecl()) { if (auto classTemplateDecl = dyn_cast(clangDecl)) { + // FIXME: Why does this resolve the types twice? SmallVector typesOfGenericArgs; for (auto typeRepr : genericArgs) { typesOfGenericArgs.push_back(resolution.resolveType(typeRepr)); @@ -3995,25 +4018,12 @@ TypeResolver::resolveASTFunctionTypeParams(TupleTypeRepr *inputRepr, return elements; } +/// Implement the special @_opaqueReturnTypeOf attribute syntax in +/// module interface files. NeverNullType TypeResolver::resolveOpaqueReturnType(TypeRepr *repr, StringRef mangledName, unsigned ordinal, TypeResolutionOptions options) { - // The type representation should be an unqualified identifier. We don't - // really use the identifier for anything, but we do resolve any generic - // arguments to instantiate the possibly-generic opaque type. - SmallVector TypeArgsBuf; - if (auto *unqualIdentRepr = dyn_cast(repr)) { - for (auto argRepr : unqualIdentRepr->getGenericArgs()) { - auto argTy = resolveType(argRepr, options); - // If we cannot resolve the generic parameter, propagate the error out. - if (argTy->hasError()) { - return ErrorType::get(getASTContext()); - } - TypeArgsBuf.push_back(argTy); - } - } - // Use type reconstruction to summon the opaque type decl. Demangler demangle; auto definingDeclNode = demangle.demangleSymbol(mangledName); @@ -4027,14 +4037,98 @@ TypeResolver::resolveOpaqueReturnType(TypeRepr *repr, StringRef mangledName, auto opaqueNode = builder.getNodeFactory().createNode(Node::Kind::OpaqueReturnTypeOf); opaqueNode->addChild(definingDeclNode, builder.getNodeFactory()); - - auto TypeArgs = ArrayRef(TypeArgsBuf); - auto ty = builder.resolveOpaqueType(opaqueNode, TypeArgs, ordinal); - if (!ty || ty->hasError()) { + auto *opaqueDecl = builder.resolveOpaqueTypeDecl(opaqueNode); + + auto *ownerDecl = opaqueDecl->getNamingDecl(); + if (!ownerDecl) { diagnose(repr->getLoc(), diag::no_opaque_return_type_of); return ErrorType::get(getASTContext()); } - return ty; + + auto genericSig = ownerDecl->getInnermostDeclContext() + ->getGenericSignatureOfContext(); + + SubstitutionMap subs; + if (genericSig) { + SmallVector args; + + // The type representation should either be a single identifier, or a + // series of member references. We don't use the identifiers for + // anything, but we do resolve the generic arguments at each level + // to instantiate the possibly-generic opaque type. + if (isa(repr) && + !genericSig->hasParameterPack()) { + // When there are no parameter packs and we just have a single + // unqualified identifier, we fall back to the legacy behavior, + // which collects the generic arguments for all levels of nesting + // in a flat list. + // + // This matches the old behavior of the ASTPrinter. + auto *unqualIdentRepr = cast(repr); + + for (auto argRepr : unqualIdentRepr->getGenericArgs()) { + auto argTy = resolveType(argRepr, options); + // If we cannot resolve the generic parameter, propagate the error out. + if (argTy->hasError()) { + return ErrorType::get(getASTContext()); + } + args.push_back(argTy); + } + + if (args.size() != genericSig.getGenericParams().size()) { + diagnose(repr->getLoc(), diag::no_opaque_return_type_of); + return ErrorType::get(getASTContext()); + } + } else { + // Correct handling of nested types. We interpret a qualified + // TypeRepr with a generic argument list at each level, like + // __.__. + SmallVector, 2> nestedArgs; + + auto *dc = ownerDecl->getInnermostDeclContext(); + while (!dc->isModuleScopeContext()) { + if (dc->isInnermostContextGeneric()) { + if (repr == nullptr || !isa(repr)) { + diagnose(repr->getLoc(), diag::no_opaque_return_type_of); + return ErrorType::get(getASTContext()); + } + + auto *identRepr = cast(repr); + nestedArgs.emplace_back(); + + auto *decl = dyn_cast(dc->getAsDecl()); + if (decl == nullptr) + decl = dc->getSelfNominalTypeDecl(); + ASSERT(decl); + + resolveGenericArguments(decl, + decl->getAsGenericContext(), + resolution, + silContext, + identRepr, + nestedArgs.back()); + repr = identRepr->getBase(); + } + + dc = dc->getParent(); + } + + for (auto &subArgs : llvm::reverse(nestedArgs)) { + args.append(subArgs.begin(), subArgs.end()); + } + } + + subs = SubstitutionMap::get(genericSig, args, + LookUpConformanceInModule()); + } + + if (ordinal >= opaqueDecl->getOpaqueGenericParams().size()) { + diagnose(repr->getLoc(), diag::no_opaque_return_type_of); + return ErrorType::get(getASTContext()); + } + + Type interfaceType = opaqueDecl->getOpaqueGenericParams()[ordinal]; + return OpaqueTypeArchetypeType::get(opaqueDecl, interfaceType, subs); } NeverNullType TypeResolver::resolveASTFunctionType( diff --git a/test/ModuleInterface/invalid-opaque-result-types.swift b/test/ModuleInterface/invalid-opaque-result-types.swift index fffc5dc985ade..40a13fca65840 100644 --- a/test/ModuleInterface/invalid-opaque-result-types.swift +++ b/test/ModuleInterface/invalid-opaque-result-types.swift @@ -17,7 +17,6 @@ // // RUN: not %target-swift-frontend -typecheck %s -I %t 2>&1 | %FileCheck %s -// CHECK: cannot find type 'InvalidParameter' in scope // CHECK: unable to resolve type for _opaqueReturnTypeOf attribute // CHECK: failed to build module 'InvalidOpaqueResultType' for importation import InvalidOpaqueResultType diff --git a/test/ModuleInterface/variadic-opaque-result-types.swift b/test/ModuleInterface/variadic-opaque-result-types.swift new file mode 100644 index 0000000000000..7874a76d9b426 --- /dev/null +++ b/test/ModuleInterface/variadic-opaque-result-types.swift @@ -0,0 +1,122 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-emit-module-interface(%t/VariadicOpaqueResultTypes.swiftinterface) %s -module-name VariadicOpaqueResultTypes -target %target-swift-5.9-abi-triple +// RUN: %target-swift-typecheck-module-from-interface(%t/VariadicOpaqueResultTypes.swiftinterface) -module-name VariadicOpaqueResultTypes +// RUN: %FileCheck %s < %t/VariadicOpaqueResultTypes.swiftinterface + + +/// +/// First, make sure pack expansions can appear in the generic argument list of an opaque return type. +/// + +public struct I1: IteratorProtocol { + public mutating func next() -> (some Any)? { return 3 } +} + +// CHECK: public struct I1 : Swift.IteratorProtocol { +// CHECK: public mutating func next() -> (some Any)? +// CHECK: public typealias Element = @_opaqueReturnTypeOf("$s25VariadicOpaqueResultTypes2I1V4nextQrSgyF", 0) __ +// CHECK: } + + +public struct S1: Sequence { + public func makeIterator() -> some IteratorProtocol { + return I1() + } +} + +// CHECK: public struct S1 : Swift.Sequence { +// CHECK: public func makeIterator() -> some Swift.IteratorProtocol +// CHECK: public typealias Element = (@_opaqueReturnTypeOf("$s25VariadicOpaqueResultTypes2S1V12makeIteratorQryF", 0) __).Element +// CHECK: public typealias Iterator = @_opaqueReturnTypeOf("$s25VariadicOpaqueResultTypes2S1V12makeIteratorQryF", 0) __ +// CHECK: } + + +public struct Scalar { + public struct I2: IteratorProtocol { + public mutating func next() -> (some Any)? { return 3 } + } +} + + +/// +/// Now, test nested types. The next example uses the old "flat" syntax, because parameter packs are not involved. +/// + + +// CHECK: public struct Scalar { +// CHECK: public struct I2 : Swift.IteratorProtocol { +// CHECK: public mutating func next() -> (some Any)? +// CHECK: public typealias Element = @_opaqueReturnTypeOf("$s25VariadicOpaqueResultTypes6ScalarV2I2V4nextQrSgyF", 0) __ +// CHECK: } +// CHECK: } + + +public struct S2: Sequence { + public func makeIterator() -> Scalar.I2 { + return .init() + } +} + +// CHECK: public struct S2 : Swift.Sequence { +// CHECK: public func makeIterator() -> VariadicOpaqueResultTypes.Scalar.I2 +// CHECK: public typealias Element = @_opaqueReturnTypeOf("$s25VariadicOpaqueResultTypes6ScalarV2I2V4nextQrSgyF", 0) __ +// CHECK: public typealias Iterator = VariadicOpaqueResultTypes.Scalar.I2 +// CHECK: } + + +/// +/// The remaining examples use the new nested syntax. +/// + +// CHECK: public struct Variadic { +public struct Variadic { + public struct I3: IteratorProtocol { + public mutating func next() -> (some Any)? { return 3 } + } + + // CHECK: public struct I3 : Swift.IteratorProtocol { + // CHECK: public mutating func next() -> (some Any)? + // CHECK: public typealias Element = @_opaqueReturnTypeOf("$s25VariadicOpaqueResultTypes0A0V2I3V4nextQrSgyF", 0) __.__ + // CHECK: } + + public struct Middle { + public struct Inner { + public struct I4: IteratorProtocol { + public mutating func next() -> (some Any)? { return 3 } + } + } + } + + // CHECK: public struct Middle { + // CHECK: public struct Inner { + // CHECK: public struct I4 : Swift.IteratorProtocol { + // CHECK: public mutating func next() -> (some Any)? + // CHECK: public typealias Element = @_opaqueReturnTypeOf("$s25VariadicOpaqueResultTypes0A0V6MiddleV5InnerV2I4V4nextQrSgyF", 0) __.__ + // CHECK: } + // CHECK: } + // CHECK: } +} +// CHECK: } + +// CHECK: public struct S3 : Swift.Sequence { +// CHECK: public func makeIterator() -> VariadicOpaqueResultTypes.Variadic.I3 +// CHECK: public typealias Element = @_opaqueReturnTypeOf("$s25VariadicOpaqueResultTypes0A0V2I3V4nextQrSgyF", 0) __.__ +// CHECK: public typealias Iterator = VariadicOpaqueResultTypes.Variadic.I3 +// CHECK: } +public struct S3: Sequence { + public func makeIterator() -> Variadic.I3 { + return .init() + } +} + +// CHECK: public struct S4 : Swift.Sequence { +// CHECK: public func makeIterator() -> VariadicOpaqueResultTypes.Variadic.Middle.Inner.I4 +// CHECK: public typealias Element = @_opaqueReturnTypeOf("$s25VariadicOpaqueResultTypes0A0V6MiddleV5InnerV2I4V4nextQrSgyF", 0) __.__ +// CHECK: public typealias Iterator = VariadicOpaqueResultTypes.Variadic.Middle.Inner.I4 +// CHECK: } +public struct S4: Sequence { + public func makeIterator() -> Variadic.Middle.Inner.I4 { + return .init() + } +} +