Skip to content

Commit e65dfc8

Browse files
authored
Merge pull request #25221 from rjmccall/function-builders
Preliminary support for function builders
2 parents 2df3652 + b4cdbc0 commit e65dfc8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+2330
-147
lines changed

include/swift/AST/ASTTypeIDs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ struct PropertyWrapperTypeInfo;
2727
class Type;
2828
class VarDecl;
2929
class TypeAliasDecl;
30+
class Type;
3031

3132
#define SWIFT_AST_TYPEID_ZONE 1
3233

include/swift/AST/Attr.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,9 @@ SIMPLE_DECL_ATTR(_propertyWrapper, PropertyWrapper,
407407
SIMPLE_DECL_ATTR(_disfavoredOverload, DisfavoredOverload,
408408
OnAbstractFunction | OnVar | OnSubscript | UserInaccessible,
409409
87)
410+
SIMPLE_DECL_ATTR(_functionBuilder, FunctionBuilder,
411+
OnNominalType,
412+
88)
410413

411414
SIMPLE_DECL_ATTR(IBSegueAction, IBSegueAction,
412415
OnFunc,

include/swift/AST/Decl.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2709,6 +2709,14 @@ class ValueDecl : public Decl {
27092709
/// `this` must be of a decl type that supports opaque return types, and
27102710
/// must not have previously had an opaque result type set.
27112711
void setOpaqueResultTypeDecl(OpaqueTypeDecl *D);
2712+
2713+
/// Retrieve the attribute associating this declaration with a
2714+
/// function builder, if there is one.
2715+
CustomAttr *getAttachedFunctionBuilder() const;
2716+
2717+
/// Retrieve the @functionBuilder type attached to this declaration,
2718+
/// if there is one.
2719+
Type getFunctionBuilderType() const;
27122720
};
27132721

27142722
/// This is a common base class for declarations which declare a type.
@@ -5334,7 +5342,7 @@ class ParamDecl : public VarDecl {
53345342
assert(isVariadic());
53355343
return getVarargBaseTy(getInterfaceType());
53365344
}
5337-
5345+
53385346
SourceRange getSourceRange() const;
53395347

53405348
AnyFunctionType::Param toFunctionParam(Type type = Type()) const;

include/swift/AST/DiagnosticsSema.def

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4463,6 +4463,44 @@ ERROR(property_wrapper_type_not_usable_from_inline,none,
44634463
"must be '@usableFromInline' or public",
44644464
(bool, bool))
44654465

4466+
//------------------------------------------------------------------------------
4467+
// MARK: function builder diagnostics
4468+
//------------------------------------------------------------------------------
4469+
ERROR(function_builder_decl, none,
4470+
"closure containing a declaration cannot be used with function "
4471+
"builder %0", (DeclName))
4472+
NOTE(note_function_builder_decl, none,
4473+
"closure containing a declaration cannot be used with function "
4474+
"builder %0", (DeclName))
4475+
ERROR(function_builder_control_flow, none,
4476+
"closure containing control flow statement cannot be used with function "
4477+
"builder %0", (DeclName))
4478+
NOTE(note_function_builder_control_flow, none,
4479+
"closure containing control flow statement cannot be used with function "
4480+
"builder %0", (DeclName))
4481+
ERROR(function_builder_attribute_not_allowed_here, none,
4482+
"function builder attribute %0 can only be applied to a parameter, "
4483+
"function, or computed property", (DeclName))
4484+
ERROR(function_builder_attribute_on_storage_without_getter, none,
4485+
"function builder attribute %0 can only be applied to a "
4486+
"%select{subscript|property|constant|variable}1 if it defines a getter",
4487+
(DeclName, unsigned))
4488+
ERROR(function_builder_parameter_not_of_function_type, none,
4489+
"function builder attribute %0 can only be applied to a parameter of "
4490+
"function type",
4491+
(DeclName))
4492+
ERROR(function_builder_parameter_autoclosure, none,
4493+
"function builder attribute %0 cannot be applied to an autoclosure "
4494+
"parameter",
4495+
(DeclName))
4496+
ERROR(function_builder_multiple, none,
4497+
"only one function builder attribute can be attached to a "
4498+
"%select{declaration|parameter}0", (bool))
4499+
NOTE(previous_function_builder_here, none,
4500+
"previous function builder specified here", ())
4501+
ERROR(function_builder_arguments, none,
4502+
"function builder attributes cannot have arguments", ())
4503+
44664504
#ifndef DIAG_NO_UNDEF
44674505
# if defined(DIAG)
44684506
# undef DIAG

include/swift/AST/KnownIdentifiers.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ IDENTIFIER(Any)
3131
IDENTIFIER(ArrayLiteralElement)
3232
IDENTIFIER(atIndexedSubscript)
3333
IDENTIFIER_(bridgeToObjectiveC)
34+
IDENTIFIER(buildBlock)
35+
IDENTIFIER(buildDo)
36+
IDENTIFIER(buildEither)
37+
IDENTIFIER(buildIf)
3438
IDENTIFIER(Change)
3539
IDENTIFIER_WITH_NAME(code_, "_code")
3640
IDENTIFIER(CodingKeys)
@@ -59,6 +63,7 @@ IDENTIFIER(Encoder)
5963
IDENTIFIER(encoder)
6064
IDENTIFIER(error)
6165
IDENTIFIER(errorDomain)
66+
IDENTIFIER(first)
6267
IDENTIFIER(forKeyedSubscript)
6368
IDENTIFIER(Foundation)
6469
IDENTIFIER(for)
@@ -93,6 +98,7 @@ IDENTIFIER(parameter)
9398
IDENTIFIER(Protocol)
9499
IDENTIFIER(rawValue)
95100
IDENTIFIER(RawValue)
101+
IDENTIFIER(second)
96102
IDENTIFIER(Selector)
97103
IDENTIFIER(self)
98104
IDENTIFIER(Self)

include/swift/AST/TypeCheckRequests.h

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class RequirementRepr;
3535
class SpecializeAttr;
3636
class TypeAliasDecl;
3737
struct TypeLoc;
38+
class ValueDecl;
3839

3940
/// Display a nominal type or extension thereof.
4041
void simple_display(
@@ -622,6 +623,57 @@ class StructuralTypeRequest :
622623
bool isCached() const { return true; }
623624
};
624625

626+
/// Request the custom attribute which attaches a function builder to the
627+
/// given declaration.
628+
class AttachedFunctionBuilderRequest :
629+
public SimpleRequest<AttachedFunctionBuilderRequest,
630+
CacheKind::Cached,
631+
CustomAttr *,
632+
ValueDecl *> {
633+
public:
634+
using SimpleRequest::SimpleRequest;
635+
636+
private:
637+
friend SimpleRequest;
638+
639+
// Evaluation.
640+
llvm::Expected<CustomAttr *>
641+
evaluate(Evaluator &evaluator, ValueDecl *decl) const;
642+
643+
public:
644+
// Caching
645+
bool isCached() const;
646+
647+
// Cycle handling
648+
void diagnoseCycle(DiagnosticEngine &diags) const;
649+
void noteCycleStep(DiagnosticEngine &diags) const;
650+
};
651+
652+
/// Request the function builder type attached to the given declaration,
653+
/// if any.
654+
class FunctionBuilderTypeRequest :
655+
public SimpleRequest<FunctionBuilderTypeRequest,
656+
CacheKind::Cached,
657+
Type,
658+
ValueDecl *> {
659+
public:
660+
using SimpleRequest::SimpleRequest;
661+
662+
private:
663+
friend SimpleRequest;
664+
665+
llvm::Expected<Type>
666+
evaluate(Evaluator &evaluator, ValueDecl *decl) const;
667+
668+
public:
669+
// Caching
670+
bool isCached() const { return true; }
671+
672+
// Cycle handling
673+
void diagnoseCycle(DiagnosticEngine &diags) const;
674+
void noteCycleStep(DiagnosticEngine &diags) const;
675+
};
676+
625677
// Allow AnyValue to compare two Type values, even though Type doesn't
626678
// support ==.
627679
template<>
@@ -631,7 +683,7 @@ inline bool AnyValue::Holder<Type>::equals(const HolderBase &other) const {
631683
static_cast<const Holder<Type> &>(other).value.getPointer();
632684
}
633685

634-
void simple_display(llvm::raw_ostream &out, const Type &type);
686+
void simple_display(llvm::raw_ostream &out, Type value);
635687

636688
/// The zone number for the type checker.
637689
#define SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE 10

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,5 @@ SWIFT_TYPEID(AttachedPropertyWrapperRequest)
3333
SWIFT_TYPEID(AttachedPropertyWrapperTypeRequest)
3434
SWIFT_TYPEID(PropertyWrapperBackingPropertyTypeRequest)
3535
SWIFT_TYPEID(PropertyWrapperBackingPropertyInfoRequest)
36+
SWIFT_TYPEID(AttachedFunctionBuilderRequest)
37+
SWIFT_TYPEID(FunctionBuilderTypeRequest)

include/swift/AST/Types.h

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3113,12 +3113,32 @@ BEGIN_CAN_TYPE_WRAPPER(FunctionType, AnyFunctionType)
31133113
}
31143114
END_CAN_TYPE_WRAPPER(FunctionType, AnyFunctionType)
31153115

3116-
/// Map the given parameter list onto a bitvector describing whether
3117-
/// the argument type at each index has a default argument associated with
3118-
/// it.
3119-
SmallBitVector
3120-
computeDefaultMap(ArrayRef<AnyFunctionType::Param> params,
3121-
const ValueDecl *paramOwner, bool skipCurriedSelf);
3116+
/// Provides information about the parameter list of a given declaration, including whether each parameter
3117+
/// has a default argument.
3118+
struct ParameterListInfo {
3119+
SmallBitVector defaultArguments;
3120+
std::vector<Type> functionBuilderTypes;
3121+
3122+
public:
3123+
ParameterListInfo() { }
3124+
3125+
ParameterListInfo(ArrayRef<AnyFunctionType::Param> params,
3126+
const ValueDecl *paramOwner, bool skipCurriedSelf);
3127+
3128+
/// Whether the parameter at the given index has a default argument.
3129+
bool hasDefaultArgument(unsigned paramIdx) const;
3130+
3131+
/// Retrieve the number of non-defaulted parameters.
3132+
unsigned numNonDefaultedParameters() const {
3133+
return defaultArguments.count();
3134+
}
3135+
3136+
/// Retrieve the number of parameters for which we have information.
3137+
unsigned size() const { return defaultArguments.size(); }
3138+
3139+
/// Retrieve the function builder type for the given parameter.
3140+
Type getFunctionBuilderType(unsigned paramIdx) const;
3141+
};
31223142

31233143
/// Turn a param list into a symbolic and printable representation that does not
31243144
/// include the types, something like (: , b:, c:)

include/swift/Parse/CodeCompletionCallbacks.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class CodeCompletionCallbacks {
116116
};
117117

118118
/// Set target decl for attribute if the CC token is in attribute of the decl.
119-
virtual void setAttrTargetDecl(Decl *D) {}
119+
virtual void setAttrTargetDeclKind(Optional<DeclKind> DK) {}
120120

121121
/// Complete the whole expression. This is a fallback that should
122122
/// produce results when more specific completion methods failed.

lib/AST/ASTPrinter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2590,6 +2590,7 @@ void PrintAST::printOneParameter(const ParamDecl *param,
25902590

25912591
auto TheTypeLoc = param->getTypeLoc();
25922592

2593+
printAttributes(param);
25932594
printArgName();
25942595

25952596
if (!TheTypeLoc.getTypeRepr() && param->hasInterfaceType())

lib/AST/ASTWalker.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,13 +1154,16 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
11541154
// Walk each parameter's decl and typeloc and default value.
11551155
if (doIt(P))
11561156
return true;
1157-
1157+
1158+
// Visit any custom attributes on the parameter.
1159+
visitCustomAttributes(P);
1160+
11581161
// Don't walk into the type if the decl is implicit, or if the type is
11591162
// implicit.
11601163
if (!P->isImplicit() && !P->isTypeLocImplicit() &&
11611164
doIt(P->getTypeLoc()))
11621165
return true;
1163-
1166+
11641167
if (auto *E = P->getDefaultValue()) {
11651168
auto res = doIt(E);
11661169
if (!res) return true;

lib/AST/Decl.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5740,6 +5740,30 @@ void ParamDecl::setStoredProperty(VarDecl *var) {
57405740
DefaultValueAndFlags.getPointer()->DefaultArg = var;
57415741
}
57425742

5743+
Type ValueDecl::getFunctionBuilderType() const {
5744+
// Fast path: most declarations (especially parameters, which is where
5745+
// this is hottest) do not have any custom attributes at all.
5746+
if (!getAttrs().hasAttribute<CustomAttr>()) return Type();
5747+
5748+
auto &ctx = getASTContext();
5749+
auto mutableThis = const_cast<ValueDecl *>(this);
5750+
return evaluateOrDefault(ctx.evaluator,
5751+
FunctionBuilderTypeRequest{mutableThis},
5752+
Type());
5753+
}
5754+
5755+
CustomAttr *ValueDecl::getAttachedFunctionBuilder() const {
5756+
// Fast path: most declarations (especially parameters, which is where
5757+
// this is hottest) do not have any custom attributes at all.
5758+
if (!getAttrs().hasAttribute<CustomAttr>()) return nullptr;
5759+
5760+
auto &ctx = getASTContext();
5761+
auto mutableThis = const_cast<ValueDecl *>(this);
5762+
return evaluateOrDefault(ctx.evaluator,
5763+
AttachedFunctionBuilderRequest{mutableThis},
5764+
nullptr);
5765+
}
5766+
57435767
void ParamDecl::setDefaultArgumentInitContext(Initializer *initContext) {
57445768
assert(DefaultValueAndFlags.getPointer());
57455769
DefaultValueAndFlags.getPointer()->InitContext = initContext;

lib/AST/Expr.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ namespace {
117117
return getStartLocImpl(E);
118118
}
119119
template <class T> static SourceRange getSourceRange(const T *E) {
120+
if (E->getStartLoc().isInvalid() != E->getEndLoc().isInvalid())
121+
return SourceRange();
120122
return { E->getStartLoc(), E->getEndLoc() };
121123
}
122124
};

lib/AST/Type.cpp

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -729,16 +729,19 @@ Type TypeBase::replaceCovariantResultType(Type newResultType,
729729
return FunctionType::get(inputType, resultType, fnType->getExtInfo());
730730
}
731731

732-
SmallBitVector
733-
swift::computeDefaultMap(ArrayRef<AnyFunctionType::Param> params,
734-
const ValueDecl *paramOwner, bool skipCurriedSelf) {
735-
SmallBitVector resultVector(params.size());
732+
ParameterListInfo::ParameterListInfo(
733+
ArrayRef<AnyFunctionType::Param> params,
734+
const ValueDecl *paramOwner,
735+
bool skipCurriedSelf) {
736+
defaultArguments.resize(params.size());
737+
functionBuilderTypes.resize(params.size());
738+
736739
// No parameter owner means no parameter list means no default arguments
737740
// - hand back the zeroed bitvector.
738741
//
739742
// FIXME: We ought to not request default argument info in this case.
740743
if (!paramOwner)
741-
return resultVector;
744+
return;
742745

743746
// Find the corresponding parameter list.
744747
const ParameterList *paramList = nullptr;
@@ -759,27 +762,44 @@ swift::computeDefaultMap(ArrayRef<AnyFunctionType::Param> params,
759762
// No parameter list means no default arguments - hand back the zeroed
760763
// bitvector.
761764
if (!paramList)
762-
return resultVector;
765+
return;
763766

764767
switch (params.size()) {
765768
case 0:
766-
return resultVector;
769+
return;
767770

768771
default:
769772
// Arguments and parameters are not guaranteed to always line-up
770773
// perfectly, e.g. failure diagnostics tries to match argument type
771774
// to different "candidate" parameters.
772775
if (params.size() != paramList->size())
773-
return resultVector;
776+
return;
774777

775-
for (auto i : range(0, params.size())) {
776-
if (paramList->get(i)->isDefaultArgument()) {
777-
resultVector.set(i);
778-
}
779-
}
780778
break;
781779
}
782-
return resultVector;
780+
781+
// Note which parameters have default arguments and/or function builders.
782+
for (auto i : range(0, params.size())) {
783+
auto param = paramList->get(i);
784+
if (param->isDefaultArgument()) {
785+
defaultArguments.set(i);
786+
}
787+
788+
if (Type functionBuilderType = param->getFunctionBuilderType()) {
789+
functionBuilderTypes[i] = functionBuilderType;
790+
}
791+
}
792+
}
793+
794+
bool ParameterListInfo::hasDefaultArgument(unsigned paramIdx) const {
795+
return paramIdx < defaultArguments.size() ? defaultArguments[paramIdx]
796+
: false;
797+
}
798+
799+
Type ParameterListInfo::getFunctionBuilderType(unsigned paramIdx) const {
800+
return paramIdx < functionBuilderTypes.size()
801+
? functionBuilderTypes[paramIdx]
802+
: Type();
783803
}
784804

785805
/// Turn a param list into a symbolic and printable representation that does not

0 commit comments

Comments
 (0)