diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 89ce69ff428..e3707e4e560 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -4018,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); @@ -4050,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 fffc5dc985a..40a13fca658 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