@@ -6976,169 +6976,178 @@ void TypeChecker::checkExistentialTypes(
69766976 checker.checkRequirements (genericParams->getRequirements ());
69776977}
69786978
6979- // / Retrieves the valid result types of the result builder
6980- // / (the return types of `buildFinalResult` / `buildBlock` /
6981- // / `buildPartialResult`).
6982- llvm::SmallVector<Type, 4 >
6983- retrieveResultBuilderResultTypes (NominalTypeDecl *builder) {
6984- ASTContext &ctx = builder->getASTContext ();
6985- llvm::SmallVector<Type, 4 > resultTypes;
6986-
6987- Identifier methodIds[] = {ctx.Id_buildFinalResult , ctx.Id_buildBlock ,
6988- ctx.Id_buildPartialBlock };
6989-
6990- for (auto methodId : methodIds) {
6991- SmallVector<ValueDecl *, 4 > potentialMatches;
6992- bool supportsMethod = TypeChecker::typeSupportsBuilderOp (
6993- builder->getDeclaredInterfaceType (), builder, methodId,
6994- /* argLabels=*/ {}, &potentialMatches);
6995-
6996- if (!supportsMethod)
6997- continue ;
6979+ // / Opens a result builder `UnboundGenericType` into a `BoundGenericType`
6980+ // / by creating and solving a constraint between the result builder's
6981+ // / result type and the return type of the attached declaration.
6982+ struct ResultBuilderUnboundTypeOpener {
6983+ DeclContext *dc;
6984+ CustomAttr *attr;
6985+
6986+ Type operator ()(UnboundGenericType *unboundTy) const {
6987+ auto resultBuilderDecl =
6988+ dyn_cast_or_null<NominalTypeDecl>(unboundTy->getDecl ());
6989+ if (!resultBuilderDecl ||
6990+ !resultBuilderDecl->getAttrs ().hasAttribute <ResultBuilderAttr>()) {
6991+ return invalidResultBuilderType (unboundTy);
6992+ }
6993+
6994+ Decl *owningDecl = attr->getOwner ().getAsDecl ();
6995+ if (!owningDecl) {
6996+ return invalidResultBuilderType (unboundTy);
6997+ }
6998+
6999+ // Retrieve the return type of the owning declaration that
7000+ // provides type inference for the result builder type.
7001+ Type owningDeclResultType;
7002+ if (auto varDecl = dyn_cast<VarDecl>(owningDecl)) {
7003+ if (auto closureResultType =
7004+ varDecl->getInterfaceType ()->getAs <FunctionType>()) {
7005+ owningDeclResultType = closureResultType->getResult ();
7006+ } else {
7007+ owningDeclResultType = varDecl->getInterfaceType ();
7008+ }
7009+ } else if (auto funcDecl = dyn_cast<FuncDecl>(owningDecl)) {
7010+ owningDeclResultType = funcDecl->getResultInterfaceType ();
7011+ }
69987012
6999- for (auto decl : potentialMatches) {
7000- auto func = dyn_cast<FuncDecl>(decl);
7001- if (!func || !func->isStatic ())
7002- continue ;
7013+ if (!owningDeclResultType) {
7014+ return invalidResultBuilderType (unboundTy);
7015+ }
70037016
7004- auto resultType = func->getResultInterfaceType ();
7005- if (!resultType || resultType->hasError ())
7006- continue ;
7017+ // Retrieve the supported result types of the result builder.
7018+ auto resultTypes = retrieveResultBuilderResultTypes (resultBuilderDecl);
7019+ if (resultTypes.empty ()) {
7020+ return invalidResultBuilderType (unboundTy);
7021+ }
70077022
7008- // Add the result type if we haven't seen it before
7009- bool isDuplicate = false ;
7010- for (auto existingType : resultTypes) {
7011- if (existingType->isEqual (resultType)) {
7012- isDuplicate = true ;
7013- break ;
7014- }
7015- }
7023+ auto genericSig = resultBuilderDecl->getGenericSignature ();
7024+
7025+ // Try each result type and return the first one that produces a valid
7026+ // solution
7027+ for (auto componentType : resultTypes) {
7028+ using namespace constraints ;
7029+ ConstraintSystem cs (dc, std::nullopt );
70167030
7017- if (!isDuplicate) {
7018- resultTypes.push_back (resultType);
7031+ // Create a type variable for each of the result builder's generic params
7032+ llvm::SmallVector<Type, 8 > typeVarReplacements;
7033+ llvm::SmallVector<TypeVariableType *, 8 > typeVars;
7034+ for (unsigned i = 0 ; i < genericSig.getGenericParams ().size (); ++i) {
7035+ auto locator = cs.getConstraintLocator (
7036+ resultBuilderDecl, {ConstraintLocator::GenericArgument, i});
7037+ auto typeVar = cs.createTypeVariable (locator, TVO_CanBindToHole);
7038+ typeVarReplacements.push_back (typeVar);
7039+ typeVars.push_back (typeVar);
70197040 }
7020- }
7021- }
70227041
7023- return resultTypes;
7024- }
7042+ // Replace any references to the result builder's generic params
7043+ // in the result type with the corresponding type variables.
7044+ auto subMap = SubstitutionMap::get (genericSig, typeVarReplacements,
7045+ LookUpConformanceInModule ());
70257046
7026- Type invalidResultBuilderType (UnboundGenericType* unboundTy,
7027- CustomAttr *attr, DeclContext *dc) {
7028- dc->getASTContext ().Diags .diagnose (
7029- attr->getTypeExpr ()->getLoc (),
7030- diag::result_builder_generic_inference_failed,
7031- unboundTy->getDecl ()->getName ());
7032-
7033- return ErrorType::get (dc->getASTContext ());
7034- }
7047+ auto componentTypeWithTypeVars = componentType.subst (subMap);
70357048
7036- // / Opens a result builder `UnboundGenericType` into a `BoundGenericType`
7037- // / by creating and solving a constraint between the result builder's
7038- // / result type and the return type of the attached declaration.
7039- Type openUnboundResultBuilderType (UnboundGenericType* unboundTy,
7040- CustomAttr *attr, DeclContext *dc) {
7041- auto resultBuilderDecl =
7042- dyn_cast_or_null<NominalTypeDecl>(unboundTy->getDecl ());
7043- if (!resultBuilderDecl) {
7044- return invalidResultBuilderType (unboundTy, attr, dc);
7045- }
7046-
7047- // Retrieve the return type of the owning declaration that
7048- // provides type inference for the result builder type.
7049- Type owningDeclResultType;
7050- Decl *owningDecl = attr->getOwner ().getAsDecl ();
7051-
7052- if (auto varDecl = dyn_cast_or_null<VarDecl>(owningDecl)) {
7053- if (auto closureResultType = varDecl->getInterfaceType ()->getAs <FunctionType>()) {
7054- owningDeclResultType = closureResultType->getResult ();
7055- } else {
7056- owningDeclResultType = varDecl->getInterfaceType ();
7049+ // The result builder result type should be equal to the return type of
7050+ // the attached declaration.
7051+ cs.addConstraint (ConstraintKind::Equal, owningDeclResultType,
7052+ componentTypeWithTypeVars,
7053+ /* preparedOverload:*/ nullptr );
7054+
7055+ auto solution = cs.solveSingle ();
7056+
7057+ // If a solution exists, bind the result builder's generic params to the
7058+ // solved types.
7059+ if (solution) {
7060+ llvm::SmallVector<Type, 8 > solvedReplacements;
7061+ for (auto typeVar : typeVars) {
7062+ solvedReplacements.push_back (solution->typeBindings [typeVar]);
7063+ }
7064+
7065+ return BoundGenericType::get (resultBuilderDecl, unboundTy->getParent (),
7066+ solvedReplacements);
7067+ }
70577068 }
7058- } else if (auto funcDecl = dyn_cast_or_null<FuncDecl>(owningDecl)) {
7059- owningDeclResultType = funcDecl->getResultInterfaceType ();
7060- }
7061-
7062- if (!owningDeclResultType) {
7063- return invalidResultBuilderType (unboundTy, attr, dc);
7069+
7070+ // No result type produced a valid solution
7071+ return invalidResultBuilderType (unboundTy);
70647072 }
70657073
7066- // Retrieve the supported result types of the result builder.
7067- auto resultTypes = retrieveResultBuilderResultTypes (resultBuilderDecl);
7068- if (resultTypes.empty ()) {
7069- return invalidResultBuilderType (unboundTy, attr, dc);
7074+ private:
7075+ Type invalidResultBuilderType (UnboundGenericType *unboundTy) const {
7076+ dc->getASTContext ().Diags .diagnose (
7077+ attr->getTypeExpr ()->getLoc (),
7078+ diag::result_builder_generic_inference_failed,
7079+ unboundTy->getDecl ()->getName ());
7080+
7081+ return ErrorType::get (dc->getASTContext ());
70707082 }
70717083
7072- auto genericSig = resultBuilderDecl->getGenericSignature ();
7084+ // / Retrieves the valid result types of the result builder
7085+ // / (the return types of `buildFinalResult` / `buildBlock` /
7086+ // / `buildPartialBlock`).
7087+ llvm::SmallVector<Type, 4 >
7088+ retrieveResultBuilderResultTypes (NominalTypeDecl *builder) const {
7089+ ASTContext &ctx = builder->getASTContext ();
7090+ llvm::SmallVector<Type, 4 > resultTypes;
70737091
7074- for (auto componentType : resultTypes) {
7075- using namespace constraints ;
7076- ConstraintSystem cs (dc, std::nullopt );
7092+ Identifier methodIds[] = {ctx.Id_buildFinalResult , ctx.Id_buildBlock ,
7093+ ctx.Id_buildPartialBlock };
70777094
7078- // Create a type variable for each of the result builder's generic params
7079- llvm::SmallVector<Type, 8 > typeVarReplacements;
7080- llvm::SmallVector<TypeVariableType *, 8 > typeVars;
7081- for (unsigned i = 0 ; i < genericSig.getGenericParams ().size (); ++i) {
7082- auto locator = cs.getConstraintLocator (
7083- resultBuilderDecl, {ConstraintLocator::GenericArgument, i});
7084- auto typeVar = cs.createTypeVariable (locator, TVO_CanBindToHole);
7085- typeVarReplacements.push_back (typeVar);
7086- typeVars.push_back (typeVar);
7087- }
7095+ for (auto methodId : methodIds) {
7096+ SmallVector<ValueDecl *, 4 > potentialMatches;
7097+ bool supportsMethod = TypeChecker::typeSupportsBuilderOp (
7098+ builder->getDeclaredInterfaceType (), builder, methodId,
7099+ /* argLabels=*/ {}, &potentialMatches);
70887100
7089- // Replace any references to the result builder's generic params
7090- // in the result type with the corresponding type variables.
7091- auto subMap = SubstitutionMap::get (genericSig, typeVarReplacements,
7092- LookUpConformanceInModule ());
7101+ if (!supportsMethod)
7102+ continue ;
70937103
7094- auto componentTypeWithTypeVars = componentType.subst (subMap);
7104+ for (auto decl : potentialMatches) {
7105+ auto func = dyn_cast<FuncDecl>(decl);
7106+ if (!func || !func->isStatic ())
7107+ continue ;
70957108
7096- // The result builder result type should be equal to the return type of the
7097- // attached declaration.
7098- cs.addConstraint (ConstraintKind::Equal, owningDeclResultType,
7099- componentTypeWithTypeVars,
7100- /* preparedOverload:*/ nullptr );
7109+ auto resultType = func->getResultInterfaceType ();
7110+ if (!resultType || resultType->hasError ())
7111+ continue ;
71017112
7102- auto solution = cs.solveSingle ();
7113+ // Add the result type if we haven't seen it before
7114+ bool isDuplicate = false ;
7115+ for (auto existingType : resultTypes) {
7116+ if (existingType->isEqual (resultType)) {
7117+ isDuplicate = true ;
7118+ break ;
7119+ }
7120+ }
71037121
7104- // If a solution exists, bind the result builder's generic params to the
7105- // solved types.
7106- if (solution) {
7107- llvm::SmallVector<Type, 8 > solvedReplacements;
7108- for (auto typeVar : typeVars) {
7109- solvedReplacements.push_back (solution->typeBindings [typeVar]);
7122+ if (!isDuplicate) {
7123+ resultTypes.push_back (resultType);
7124+ }
71107125 }
7111-
7112- return BoundGenericType::get (resultBuilderDecl, unboundTy->getParent (),
7113- solvedReplacements);
71147126 }
7115- }
71167127
7117- // No result type produced a valid solution
7118- return invalidResultBuilderType (unboundTy, attr, dc);
7119- }
7128+ return resultTypes;
7129+ }
7130+ };
71207131
71217132Type CustomAttrTypeRequest::evaluate (Evaluator &eval, CustomAttr *attr,
71227133 DeclContext *dc,
71237134 CustomAttrTypeKind typeKind) const {
71247135 const TypeResolutionOptions options (TypeResolverContext::PatternBindingDecl);
71257136
71267137 OpenUnboundGenericTypeFn unboundTyOpener = nullptr ;
7127-
7128- // Property delegates allow their type to be an unbound generic.
7138+
7139+ // Property wrappers and result builders allow their type to be an unbound
7140+ // generic.
71297141 if (typeKind == CustomAttrTypeKind::PropertyWrapper) {
71307142 unboundTyOpener = TypeResolution::defaultUnboundTypeOpener;
7131- }
7132-
7133- // / Result builder types can have their generics parameters inferred
7134- // / from the attached declaration.
7135- else if (typeKind == CustomAttrTypeKind::ResultBuilder){
7136- unboundTyOpener = [attr, dc](UnboundGenericType* unboundTy) -> Type {
7137- return openUnboundResultBuilderType (unboundTy, attr, dc);
7138- };
7143+ } else if (typeKind == CustomAttrTypeKind::ResultBuilder) {
7144+ auto &ctx = dc->getASTContext ();
7145+ void *mem = ctx.Allocate (sizeof (ResultBuilderUnboundTypeOpener),
7146+ alignof (ResultBuilderUnboundTypeOpener));
7147+ unboundTyOpener = *new (mem) ResultBuilderUnboundTypeOpener{dc, attr};
71397148 }
71407149
7141- const auto type = TypeResolution::resolveContextualType (
7150+ auto type = TypeResolution::resolveContextualType (
71427151 attr->getTypeRepr (), dc, options, unboundTyOpener,
71437152 /* placeholderHandler*/ nullptr , /* packElementOpener*/ nullptr );
71447153
0 commit comments