Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
62193c9
[CodeCompletion] Enable type completion at beginning of attribute
rintaro Apr 17, 2019
b31c142
[CodeCompletion] Implement completion at custom attribute argument
rintaro Apr 18, 2019
1e4f5f7
Add @functionBuilder and check its applications to parameters.
rjmccall Apr 16, 2019
15e7fa0
Ignore unresolvable custom attributes in the function-builder checker.
rjmccall Apr 16, 2019
e1b6386
Add an unused request for getting the type of a custom attribute.
rjmccall Apr 16, 2019
93b3320
Make getFunctionBuilderType() return a Type.
rjmccall Apr 16, 2019
2268939
Underscore _functionBuilder.
rjmccall Apr 17, 2019
0078422
Rework the requests for getting a parameter's function-builder type.
rjmccall Apr 17, 2019
0494574
Factor the computation of default arguments into ParameterListInfo.
DougGregor Apr 16, 2019
a4301cc
[Type checker] Transform multi-statement closures via function builders.
DougGregor Apr 17, 2019
6a3739a
Ensure that we use the right closure context for constraint generation.
DougGregor Apr 17, 2019
ffd1601
[DSL] Allow function builders to opt in to "do" support via buildDo().
DougGregor Apr 17, 2019
c98f017
[DSL] Allow function builders to opt in to "if" statements.
DougGregor Apr 17, 2019
ac47c9d
[Function builders] Diagnose unhandled closure constructs within the …
DougGregor Apr 18, 2019
b634f59
[Function builders] Create a FailureDiagnostic for unhandled constructs.
DougGregor Apr 18, 2019
f2db407
[Type checker] Collapse some duplicate code. Thanks, Pavel!
DougGregor Apr 18, 2019
b7bbf4c
[Function builders] Allow uses of generic function builders.
DougGregor Apr 23, 2019
fa461a7
[Function builders] Add AST walker support for custom attributes on p…
DougGregor Apr 23, 2019
50fe8e2
[AST Printing] Print custom attributes on parameters.
DougGregor Apr 26, 2019
04ca975
[CodeCompletion] Enable type name completion for param decl attribute
rintaro Apr 25, 2019
5cc5b93
[SourceKit] Function builder: Add cursor-info test cases
rintaro Apr 24, 2019
06e8483
[IDE] Function builder: add syntax coloring test for custom attribute
rintaro Apr 25, 2019
648a76e
[CodeCompletion] Add basic test cases inside builder closure
rintaro Apr 25, 2019
992c752
[CodeCompletion] Function builder: add test case for attribute at params
rintaro Apr 25, 2019
1c2c5c5
[placeholder-expansion] Function builder: add basic expansion test
rintaro Apr 26, 2019
25bfdb6
[CodeCompletion] Function builder: test case with context types in bu…
rintaro Apr 27, 2019
7475bcd
[Function builders] Prescan closure bodies for a 'return' statement.
DougGregor Apr 29, 2019
83b5b2f
Support if-else chains on function builders.
rjmccall Apr 30, 2019
5d0d8d9
[Constraint solver] Capture/roll back type mappings generated while s…
DougGregor Apr 19, 2019
952eb9d
Allow function-builder attributes on funcs and computed vars.
rjmccall May 7, 2019
999d98a
Fix treatment of single-line getters with function builders.
rjmccall May 8, 2019
a183f76
Address review feedback on the function-builders-on-funcs/vars patch.
rjmccall May 8, 2019
2594de6
[Type checker] Don't re-insert node types when merging solutions.
DougGregor May 17, 2019
e08f1fb
[DSL] Clean up assignment of types to synthesized TypeExprs.
DougGregor May 17, 2019
cf0a50b
Remove restriction that @functionBuilders have to be uppercased;
rjmccall Jun 5, 2019
990ded6
Merge fix: IBSegueAction apparently comes last in this list.
rjmccall Jun 6, 2019
b4cdbc0
Move the core builder-transform logic into its own file.
rjmccall Jun 12, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/swift/AST/ASTTypeIDs.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ struct PropertyWrapperTypeInfo;
class Type;
class VarDecl;
class TypeAliasDecl;
class Type;

#define SWIFT_AST_TYPEID_ZONE 1

Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/Attr.def
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,9 @@ SIMPLE_DECL_ATTR(_propertyWrapper, PropertyWrapper,
SIMPLE_DECL_ATTR(_disfavoredOverload, DisfavoredOverload,
OnAbstractFunction | OnVar | OnSubscript | UserInaccessible,
87)
SIMPLE_DECL_ATTR(_functionBuilder, FunctionBuilder,
OnNominalType,
88)

SIMPLE_DECL_ATTR(IBSegueAction, IBSegueAction,
OnFunc,
Expand Down
10 changes: 9 additions & 1 deletion include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2709,6 +2709,14 @@ class ValueDecl : public Decl {
/// `this` must be of a decl type that supports opaque return types, and
/// must not have previously had an opaque result type set.
void setOpaqueResultTypeDecl(OpaqueTypeDecl *D);

/// Retrieve the attribute associating this declaration with a
/// function builder, if there is one.
CustomAttr *getAttachedFunctionBuilder() const;

/// Retrieve the @functionBuilder type attached to this declaration,
/// if there is one.
Type getFunctionBuilderType() const;
};

/// This is a common base class for declarations which declare a type.
Expand Down Expand Up @@ -5334,7 +5342,7 @@ class ParamDecl : public VarDecl {
assert(isVariadic());
return getVarargBaseTy(getInterfaceType());
}

SourceRange getSourceRange() const;

AnyFunctionType::Param toFunctionParam(Type type = Type()) const;
Expand Down
38 changes: 38 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -4463,6 +4463,44 @@ ERROR(property_wrapper_type_not_usable_from_inline,none,
"must be '@usableFromInline' or public",
(bool, bool))

//------------------------------------------------------------------------------
// MARK: function builder diagnostics
//------------------------------------------------------------------------------
ERROR(function_builder_decl, none,
"closure containing a declaration cannot be used with function "
"builder %0", (DeclName))
NOTE(note_function_builder_decl, none,
"closure containing a declaration cannot be used with function "
"builder %0", (DeclName))
ERROR(function_builder_control_flow, none,
"closure containing control flow statement cannot be used with function "
"builder %0", (DeclName))
NOTE(note_function_builder_control_flow, none,
"closure containing control flow statement cannot be used with function "
"builder %0", (DeclName))
ERROR(function_builder_attribute_not_allowed_here, none,
"function builder attribute %0 can only be applied to a parameter, "
"function, or computed property", (DeclName))
ERROR(function_builder_attribute_on_storage_without_getter, none,
"function builder attribute %0 can only be applied to a "
"%select{subscript|property|constant|variable}1 if it defines a getter",
(DeclName, unsigned))
ERROR(function_builder_parameter_not_of_function_type, none,
"function builder attribute %0 can only be applied to a parameter of "
"function type",
(DeclName))
ERROR(function_builder_parameter_autoclosure, none,
"function builder attribute %0 cannot be applied to an autoclosure "
"parameter",
(DeclName))
ERROR(function_builder_multiple, none,
"only one function builder attribute can be attached to a "
"%select{declaration|parameter}0", (bool))
NOTE(previous_function_builder_here, none,
"previous function builder specified here", ())
ERROR(function_builder_arguments, none,
"function builder attributes cannot have arguments", ())

#ifndef DIAG_NO_UNDEF
# if defined(DIAG)
# undef DIAG
Expand Down
6 changes: 6 additions & 0 deletions include/swift/AST/KnownIdentifiers.def
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ IDENTIFIER(Any)
IDENTIFIER(ArrayLiteralElement)
IDENTIFIER(atIndexedSubscript)
IDENTIFIER_(bridgeToObjectiveC)
IDENTIFIER(buildBlock)
IDENTIFIER(buildDo)
IDENTIFIER(buildEither)
IDENTIFIER(buildIf)
IDENTIFIER(Change)
IDENTIFIER_WITH_NAME(code_, "_code")
IDENTIFIER(CodingKeys)
Expand Down Expand Up @@ -59,6 +63,7 @@ IDENTIFIER(Encoder)
IDENTIFIER(encoder)
IDENTIFIER(error)
IDENTIFIER(errorDomain)
IDENTIFIER(first)
IDENTIFIER(forKeyedSubscript)
IDENTIFIER(Foundation)
IDENTIFIER(for)
Expand Down Expand Up @@ -93,6 +98,7 @@ IDENTIFIER(parameter)
IDENTIFIER(Protocol)
IDENTIFIER(rawValue)
IDENTIFIER(RawValue)
IDENTIFIER(second)
IDENTIFIER(Selector)
IDENTIFIER(self)
IDENTIFIER(Self)
Expand Down
54 changes: 53 additions & 1 deletion include/swift/AST/TypeCheckRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class RequirementRepr;
class SpecializeAttr;
class TypeAliasDecl;
struct TypeLoc;
class ValueDecl;

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

/// Request the custom attribute which attaches a function builder to the
/// given declaration.
class AttachedFunctionBuilderRequest :
public SimpleRequest<AttachedFunctionBuilderRequest,
CacheKind::Cached,
CustomAttr *,
ValueDecl *> {
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

// Evaluation.
llvm::Expected<CustomAttr *>
evaluate(Evaluator &evaluator, ValueDecl *decl) const;

public:
// Caching
bool isCached() const;

// Cycle handling
void diagnoseCycle(DiagnosticEngine &diags) const;
void noteCycleStep(DiagnosticEngine &diags) const;
};

/// Request the function builder type attached to the given declaration,
/// if any.
class FunctionBuilderTypeRequest :
public SimpleRequest<FunctionBuilderTypeRequest,
CacheKind::Cached,
Type,
ValueDecl *> {
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

llvm::Expected<Type>
evaluate(Evaluator &evaluator, ValueDecl *decl) const;

public:
// Caching
bool isCached() const { return true; }

// Cycle handling
void diagnoseCycle(DiagnosticEngine &diags) const;
void noteCycleStep(DiagnosticEngine &diags) const;
};

// Allow AnyValue to compare two Type values, even though Type doesn't
// support ==.
template<>
Expand All @@ -631,7 +683,7 @@ inline bool AnyValue::Holder<Type>::equals(const HolderBase &other) const {
static_cast<const Holder<Type> &>(other).value.getPointer();
}

void simple_display(llvm::raw_ostream &out, const Type &type);
void simple_display(llvm::raw_ostream &out, Type value);

/// The zone number for the type checker.
#define SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE 10
Expand Down
2 changes: 2 additions & 0 deletions include/swift/AST/TypeCheckerTypeIDZone.def
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@ SWIFT_TYPEID(AttachedPropertyWrapperRequest)
SWIFT_TYPEID(AttachedPropertyWrapperTypeRequest)
SWIFT_TYPEID(PropertyWrapperBackingPropertyTypeRequest)
SWIFT_TYPEID(PropertyWrapperBackingPropertyInfoRequest)
SWIFT_TYPEID(AttachedFunctionBuilderRequest)
SWIFT_TYPEID(FunctionBuilderTypeRequest)
32 changes: 26 additions & 6 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -3113,12 +3113,32 @@ BEGIN_CAN_TYPE_WRAPPER(FunctionType, AnyFunctionType)
}
END_CAN_TYPE_WRAPPER(FunctionType, AnyFunctionType)

/// Map the given parameter list onto a bitvector describing whether
/// the argument type at each index has a default argument associated with
/// it.
SmallBitVector
computeDefaultMap(ArrayRef<AnyFunctionType::Param> params,
const ValueDecl *paramOwner, bool skipCurriedSelf);
/// Provides information about the parameter list of a given declaration, including whether each parameter
/// has a default argument.
struct ParameterListInfo {
SmallBitVector defaultArguments;
std::vector<Type> functionBuilderTypes;

public:
ParameterListInfo() { }

ParameterListInfo(ArrayRef<AnyFunctionType::Param> params,
const ValueDecl *paramOwner, bool skipCurriedSelf);

/// Whether the parameter at the given index has a default argument.
bool hasDefaultArgument(unsigned paramIdx) const;

/// Retrieve the number of non-defaulted parameters.
unsigned numNonDefaultedParameters() const {
return defaultArguments.count();
}

/// Retrieve the number of parameters for which we have information.
unsigned size() const { return defaultArguments.size(); }

/// Retrieve the function builder type for the given parameter.
Type getFunctionBuilderType(unsigned paramIdx) const;
};

/// Turn a param list into a symbolic and printable representation that does not
/// include the types, something like (: , b:, c:)
Expand Down
2 changes: 1 addition & 1 deletion include/swift/Parse/CodeCompletionCallbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class CodeCompletionCallbacks {
};

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

/// Complete the whole expression. This is a fallback that should
/// produce results when more specific completion methods failed.
Expand Down
1 change: 1 addition & 0 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2590,6 +2590,7 @@ void PrintAST::printOneParameter(const ParamDecl *param,

auto TheTypeLoc = param->getTypeLoc();

printAttributes(param);
printArgName();

if (!TheTypeLoc.getTypeRepr() && param->hasInterfaceType())
Expand Down
7 changes: 5 additions & 2 deletions lib/AST/ASTWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1154,13 +1154,16 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
// Walk each parameter's decl and typeloc and default value.
if (doIt(P))
return true;


// Visit any custom attributes on the parameter.
visitCustomAttributes(P);

// Don't walk into the type if the decl is implicit, or if the type is
// implicit.
if (!P->isImplicit() && !P->isTypeLocImplicit() &&
doIt(P->getTypeLoc()))
return true;

if (auto *E = P->getDefaultValue()) {
auto res = doIt(E);
if (!res) return true;
Expand Down
24 changes: 24 additions & 0 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5740,6 +5740,30 @@ void ParamDecl::setStoredProperty(VarDecl *var) {
DefaultValueAndFlags.getPointer()->DefaultArg = var;
}

Type ValueDecl::getFunctionBuilderType() const {
// Fast path: most declarations (especially parameters, which is where
// this is hottest) do not have any custom attributes at all.
if (!getAttrs().hasAttribute<CustomAttr>()) return Type();

auto &ctx = getASTContext();
auto mutableThis = const_cast<ValueDecl *>(this);
return evaluateOrDefault(ctx.evaluator,
FunctionBuilderTypeRequest{mutableThis},
Type());
}

CustomAttr *ValueDecl::getAttachedFunctionBuilder() const {
// Fast path: most declarations (especially parameters, which is where
// this is hottest) do not have any custom attributes at all.
if (!getAttrs().hasAttribute<CustomAttr>()) return nullptr;

auto &ctx = getASTContext();
auto mutableThis = const_cast<ValueDecl *>(this);
return evaluateOrDefault(ctx.evaluator,
AttachedFunctionBuilderRequest{mutableThis},
nullptr);
}

void ParamDecl::setDefaultArgumentInitContext(Initializer *initContext) {
assert(DefaultValueAndFlags.getPointer());
DefaultValueAndFlags.getPointer()->InitContext = initContext;
Expand Down
2 changes: 2 additions & 0 deletions lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ namespace {
return getStartLocImpl(E);
}
template <class T> static SourceRange getSourceRange(const T *E) {
if (E->getStartLoc().isInvalid() != E->getEndLoc().isInvalid())
return SourceRange();
return { E->getStartLoc(), E->getEndLoc() };
}
};
Expand Down
48 changes: 34 additions & 14 deletions lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -729,16 +729,19 @@ Type TypeBase::replaceCovariantResultType(Type newResultType,
return FunctionType::get(inputType, resultType, fnType->getExtInfo());
}

SmallBitVector
swift::computeDefaultMap(ArrayRef<AnyFunctionType::Param> params,
const ValueDecl *paramOwner, bool skipCurriedSelf) {
SmallBitVector resultVector(params.size());
ParameterListInfo::ParameterListInfo(
ArrayRef<AnyFunctionType::Param> params,
const ValueDecl *paramOwner,
bool skipCurriedSelf) {
defaultArguments.resize(params.size());
functionBuilderTypes.resize(params.size());

// No parameter owner means no parameter list means no default arguments
// - hand back the zeroed bitvector.
//
// FIXME: We ought to not request default argument info in this case.
if (!paramOwner)
return resultVector;
return;

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

switch (params.size()) {
case 0:
return resultVector;
return;

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

for (auto i : range(0, params.size())) {
if (paramList->get(i)->isDefaultArgument()) {
resultVector.set(i);
}
}
break;
}
return resultVector;

// Note which parameters have default arguments and/or function builders.
for (auto i : range(0, params.size())) {
auto param = paramList->get(i);
if (param->isDefaultArgument()) {
defaultArguments.set(i);
}

if (Type functionBuilderType = param->getFunctionBuilderType()) {
functionBuilderTypes[i] = functionBuilderType;
}
}
}

bool ParameterListInfo::hasDefaultArgument(unsigned paramIdx) const {
return paramIdx < defaultArguments.size() ? defaultArguments[paramIdx]
: false;
}

Type ParameterListInfo::getFunctionBuilderType(unsigned paramIdx) const {
return paramIdx < functionBuilderTypes.size()
? functionBuilderTypes[paramIdx]
: Type();
}

/// Turn a param list into a symbolic and printable representation that does not
Expand Down
Loading