Skip to content

Commit f7331dd

Browse files
authored
Merge pull request swiftlang#25387 from rjmccall/function-builders-5.1
[5.1] Preliminary support for function builders
2 parents 1e36059 + 9c8be4c commit f7331dd

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

+2331
-151
lines changed

include/swift/AST/ASTTypeIDs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ struct PropertyWrapperBackingPropertyInfo;
2626
struct PropertyWrapperTypeInfo;
2727
class Type;
2828
class VarDecl;
29+
class TypeAliasDecl;
30+
class Type;
2931

3032
#define SWIFT_AST_TYPEID_ZONE 1
3133

include/swift/AST/Attr.def

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

410413
SIMPLE_DECL_ATTR(IBSegueAction, IBSegueAction,
411414
OnFunc,

include/swift/AST/Decl.h

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

27102718
/// This is a common base class for declarations which declare a type.
@@ -5309,7 +5317,7 @@ class ParamDecl : public VarDecl {
53095317
assert(isVariadic());
53105318
return getVarargBaseTy(getInterfaceType());
53115319
}
5312-
5320+
53135321
SourceRange getSourceRange() const;
53145322

53155323
// Implement isa/cast/dyncast/etc.

include/swift/AST/DiagnosticsSema.def

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

4444+
//------------------------------------------------------------------------------
4445+
// MARK: function builder diagnostics
4446+
//------------------------------------------------------------------------------
4447+
ERROR(function_builder_decl, none,
4448+
"closure containing a declaration cannot be used with function "
4449+
"builder %0", (DeclName))
4450+
NOTE(note_function_builder_decl, none,
4451+
"closure containing a declaration cannot be used with function "
4452+
"builder %0", (DeclName))
4453+
ERROR(function_builder_control_flow, none,
4454+
"closure containing control flow statement cannot be used with function "
4455+
"builder %0", (DeclName))
4456+
NOTE(note_function_builder_control_flow, none,
4457+
"closure containing control flow statement cannot be used with function "
4458+
"builder %0", (DeclName))
4459+
ERROR(function_builder_attribute_not_allowed_here, none,
4460+
"function builder attribute %0 can only be applied to a parameter, "
4461+
"function, or computed property", (DeclName))
4462+
ERROR(function_builder_attribute_on_storage_without_getter, none,
4463+
"function builder attribute %0 can only be applied to a "
4464+
"%select{subscript|property|constant|variable}1 if it defines a getter",
4465+
(DeclName, unsigned))
4466+
ERROR(function_builder_parameter_not_of_function_type, none,
4467+
"function builder attribute %0 can only be applied to a parameter of "
4468+
"function type",
4469+
(DeclName))
4470+
ERROR(function_builder_parameter_autoclosure, none,
4471+
"function builder attribute %0 cannot be applied to an autoclosure "
4472+
"parameter",
4473+
(DeclName))
4474+
ERROR(function_builder_multiple, none,
4475+
"only one function builder attribute can be attached to a "
4476+
"%select{declaration|parameter}0", (bool))
4477+
NOTE(previous_function_builder_here, none,
4478+
"previous function builder specified here", ())
4479+
ERROR(function_builder_arguments, none,
4480+
"function builder attributes cannot have arguments", ())
4481+
44444482
#ifndef DIAG_NO_UNDEF
44454483
# if defined(DIAG)
44464484
# 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: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ struct PropertyWrapperBackingPropertyInfo;
3434
class RequirementRepr;
3535
class SpecializeAttr;
3636
struct TypeLoc;
37+
class ValueDecl;
3738

3839
/// Display a nominal type or extension thereof.
3940
void simple_display(
@@ -521,12 +522,67 @@ class PropertyWrapperBackingPropertyInfoRequest :
521522
void noteCycleStep(DiagnosticEngine &diags) const;
522523
};
523524

525+
/// Request the custom attribute which attaches a function builder to the
526+
/// given declaration.
527+
class AttachedFunctionBuilderRequest :
528+
public SimpleRequest<AttachedFunctionBuilderRequest,
529+
CacheKind::Cached,
530+
CustomAttr *,
531+
ValueDecl *> {
532+
public:
533+
using SimpleRequest::SimpleRequest;
534+
535+
private:
536+
friend SimpleRequest;
537+
538+
// Evaluation.
539+
llvm::Expected<CustomAttr *>
540+
evaluate(Evaluator &evaluator, ValueDecl *decl) const;
541+
542+
public:
543+
// Caching
544+
bool isCached() const;
545+
546+
// Cycle handling
547+
void diagnoseCycle(DiagnosticEngine &diags) const;
548+
void noteCycleStep(DiagnosticEngine &diags) const;
549+
};
550+
551+
/// Request the function builder type attached to the given declaration,
552+
/// if any.
553+
class FunctionBuilderTypeRequest :
554+
public SimpleRequest<FunctionBuilderTypeRequest,
555+
CacheKind::Cached,
556+
Type,
557+
ValueDecl *> {
558+
public:
559+
using SimpleRequest::SimpleRequest;
560+
561+
private:
562+
friend SimpleRequest;
563+
564+
llvm::Expected<Type>
565+
evaluate(Evaluator &evaluator, ValueDecl *decl) const;
566+
567+
public:
568+
// Caching
569+
bool isCached() const { return true; }
570+
571+
// Cycle handling
572+
void diagnoseCycle(DiagnosticEngine &diags) const;
573+
void noteCycleStep(DiagnosticEngine &diags) const;
574+
};
575+
524576
// Allow AnyValue to compare two Type values, even though Type doesn't
525577
// support ==.
526578
template<>
527-
bool AnyValue::Holder<Type>::equals(const HolderBase &other) const;
579+
inline bool AnyValue::Holder<Type>::equals(const HolderBase &other) const {
580+
assert(typeID == other.typeID && "Caller should match type IDs");
581+
return value.getPointer() ==
582+
static_cast<const Holder<Type> &>(other).value.getPointer();
583+
}
528584

529-
void simple_display(llvm::raw_ostream &out, const Type &type);
585+
void simple_display(llvm::raw_ostream &out, Type value);
530586

531587
/// The zone number for the type checker.
532588
#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
@@ -29,3 +29,5 @@ SWIFT_TYPEID(AttachedPropertyWrapperRequest)
2929
SWIFT_TYPEID(AttachedPropertyWrapperTypeRequest)
3030
SWIFT_TYPEID(PropertyWrapperBackingPropertyTypeRequest)
3131
SWIFT_TYPEID(PropertyWrapperBackingPropertyInfoRequest)
32+
SWIFT_TYPEID(AttachedFunctionBuilderRequest)
33+
SWIFT_TYPEID(FunctionBuilderTypeRequest)

include/swift/AST/Types.h

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3118,12 +3118,32 @@ BEGIN_CAN_TYPE_WRAPPER(FunctionType, AnyFunctionType)
31183118
}
31193119
END_CAN_TYPE_WRAPPER(FunctionType, AnyFunctionType)
31203120

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

31283148
/// Turn a param list into a symbolic and printable representation that does not
31293149
/// 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
@@ -2598,6 +2598,7 @@ void PrintAST::printOneParameter(const ParamDecl *param,
25982598

25992599
auto TheTypeLoc = param->getTypeLoc();
26002600

2601+
printAttributes(param);
26012602
printArgName();
26022603

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

lib/AST/ASTWalker.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,13 +1160,16 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
11601160
// Walk each parameter's decl and typeloc and default value.
11611161
if (doIt(P))
11621162
return true;
1163-
1163+
1164+
// Visit any custom attributes on the parameter.
1165+
visitCustomAttributes(P);
1166+
11641167
// Don't walk into the type if the decl is implicit, or if the type is
11651168
// implicit.
11661169
if (!P->isImplicit() && !P->isTypeLocImplicit() &&
11671170
doIt(P->getTypeLoc()))
11681171
return true;
1169-
1172+
11701173
if (auto *E = P->getDefaultValue()) {
11711174
auto res = doIt(E);
11721175
if (!res) return true;

lib/AST/Decl.cpp

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

5652+
Type ValueDecl::getFunctionBuilderType() const {
5653+
// Fast path: most declarations (especially parameters, which is where
5654+
// this is hottest) do not have any custom attributes at all.
5655+
if (!getAttrs().hasAttribute<CustomAttr>()) return Type();
5656+
5657+
auto &ctx = getASTContext();
5658+
auto mutableThis = const_cast<ValueDecl *>(this);
5659+
return evaluateOrDefault(ctx.evaluator,
5660+
FunctionBuilderTypeRequest{mutableThis},
5661+
Type());
5662+
}
5663+
5664+
CustomAttr *ValueDecl::getAttachedFunctionBuilder() const {
5665+
// Fast path: most declarations (especially parameters, which is where
5666+
// this is hottest) do not have any custom attributes at all.
5667+
if (!getAttrs().hasAttribute<CustomAttr>()) return nullptr;
5668+
5669+
auto &ctx = getASTContext();
5670+
auto mutableThis = const_cast<ValueDecl *>(this);
5671+
return evaluateOrDefault(ctx.evaluator,
5672+
AttachedFunctionBuilderRequest{mutableThis},
5673+
nullptr);
5674+
}
5675+
56525676
void ParamDecl::setDefaultArgumentInitContext(Initializer *initContext) {
56535677
assert(DefaultValueAndFlags.getPointer());
56545678
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
@@ -742,16 +742,19 @@ Type TypeBase::replaceCovariantResultType(Type newResultType,
742742
return FunctionType::get(inputType, resultType, fnType->getExtInfo());
743743
}
744744

745-
SmallBitVector
746-
swift::computeDefaultMap(ArrayRef<AnyFunctionType::Param> params,
747-
const ValueDecl *paramOwner, bool skipCurriedSelf) {
748-
SmallBitVector resultVector(params.size());
745+
ParameterListInfo::ParameterListInfo(
746+
ArrayRef<AnyFunctionType::Param> params,
747+
const ValueDecl *paramOwner,
748+
bool skipCurriedSelf) {
749+
defaultArguments.resize(params.size());
750+
functionBuilderTypes.resize(params.size());
751+
749752
// No parameter owner means no parameter list means no default arguments
750753
// - hand back the zeroed bitvector.
751754
//
752755
// FIXME: We ought to not request default argument info in this case.
753756
if (!paramOwner)
754-
return resultVector;
757+
return;
755758

756759
// Find the corresponding parameter list.
757760
const ParameterList *paramList = nullptr;
@@ -772,27 +775,44 @@ swift::computeDefaultMap(ArrayRef<AnyFunctionType::Param> params,
772775
// No parameter list means no default arguments - hand back the zeroed
773776
// bitvector.
774777
if (!paramList)
775-
return resultVector;
778+
return;
776779

777780
switch (params.size()) {
778781
case 0:
779-
return resultVector;
782+
return;
780783

781784
default:
782785
// Arguments and parameters are not guaranteed to always line-up
783786
// perfectly, e.g. failure diagnostics tries to match argument type
784787
// to different "candidate" parameters.
785788
if (params.size() != paramList->size())
786-
return resultVector;
789+
return;
787790

788-
for (auto i : range(0, params.size())) {
789-
if (paramList->get(i)->isDefaultArgument()) {
790-
resultVector.set(i);
791-
}
792-
}
793791
break;
794792
}
795-
return resultVector;
793+
794+
// Note which parameters have default arguments and/or function builders.
795+
for (auto i : range(0, params.size())) {
796+
auto param = paramList->get(i);
797+
if (param->isDefaultArgument()) {
798+
defaultArguments.set(i);
799+
}
800+
801+
if (Type functionBuilderType = param->getFunctionBuilderType()) {
802+
functionBuilderTypes[i] = functionBuilderType;
803+
}
804+
}
805+
}
806+
807+
bool ParameterListInfo::hasDefaultArgument(unsigned paramIdx) const {
808+
return paramIdx < defaultArguments.size() ? defaultArguments[paramIdx]
809+
: false;
810+
}
811+
812+
Type ParameterListInfo::getFunctionBuilderType(unsigned paramIdx) const {
813+
return paramIdx < functionBuilderTypes.size()
814+
? functionBuilderTypes[paramIdx]
815+
: Type();
796816
}
797817

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

0 commit comments

Comments
 (0)