Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
6096a6b
[CodeCompletion] Enable type completion at beginning of attribute
rintaro Apr 17, 2019
dec254c
[CodeCompletion] Implement completion at custom attribute argument
rintaro Apr 18, 2019
08dc287
Add @functionBuilder and check its applications to parameters.
rjmccall Apr 16, 2019
c5b3af0
Ignore unresolvable custom attributes in the function-builder checker.
rjmccall Apr 16, 2019
d2fbd1e
Add an unused request for getting the type of a custom attribute.
rjmccall Apr 16, 2019
137b90c
Make getFunctionBuilderType() return a Type.
rjmccall Apr 16, 2019
a7b16ae
Underscore _functionBuilder.
rjmccall Apr 17, 2019
1ea0086
Rework the requests for getting a parameter's function-builder type.
rjmccall Apr 17, 2019
15e8b4b
Factor the computation of default arguments into ParameterListInfo.
DougGregor Apr 16, 2019
42aac2f
[Type checker] Transform multi-statement closures via function builders.
DougGregor Apr 17, 2019
6947fd8
Ensure that we use the right closure context for constraint generation.
DougGregor Apr 17, 2019
1bd5238
[DSL] Allow function builders to opt in to "do" support via buildDo().
DougGregor Apr 17, 2019
0e59548
[DSL] Allow function builders to opt in to "if" statements.
DougGregor Apr 17, 2019
efc75ed
[Function builders] Diagnose unhandled closure constructs within the …
DougGregor Apr 18, 2019
32b6f55
[Function builders] Create a FailureDiagnostic for unhandled constructs.
DougGregor Apr 18, 2019
b7279fb
[Type checker] Collapse some duplicate code. Thanks, Pavel!
DougGregor Apr 18, 2019
d88e0f1
[Function builders] Allow uses of generic function builders.
DougGregor Apr 23, 2019
891a2a3
[Function builders] Add AST walker support for custom attributes on p…
DougGregor Apr 23, 2019
621d88f
[AST Printing] Print custom attributes on parameters.
DougGregor Apr 26, 2019
aa33a1e
[CodeCompletion] Enable type name completion for param decl attribute
rintaro Apr 25, 2019
75323a3
[SourceKit] Function builder: Add cursor-info test cases
rintaro Apr 24, 2019
2bbd78d
[IDE] Function builder: add syntax coloring test for custom attribute
rintaro Apr 25, 2019
afca645
[CodeCompletion] Add basic test cases inside builder closure
rintaro Apr 25, 2019
72f7656
[CodeCompletion] Function builder: add test case for attribute at params
rintaro Apr 25, 2019
e550ecf
[placeholder-expansion] Function builder: add basic expansion test
rintaro Apr 26, 2019
ff9b1ed
[CodeCompletion] Function builder: test case with context types in bu…
rintaro Apr 27, 2019
8d802b3
[Function builders] Prescan closure bodies for a 'return' statement.
DougGregor Apr 29, 2019
5cbfd58
Support if-else chains on function builders.
rjmccall Apr 30, 2019
0780059
[Constraint solver] Capture/roll back type mappings generated while s…
DougGregor Apr 19, 2019
57cd610
Allow function-builder attributes on funcs and computed vars.
rjmccall May 7, 2019
6afd405
Fix treatment of single-line getters with function builders.
rjmccall May 8, 2019
3c3d130
Address review feedback on the function-builders-on-funcs/vars patch.
rjmccall May 8, 2019
810cfc4
[Type checker] Don't re-insert node types when merging solutions.
DougGregor May 17, 2019
5c51270
[DSL] Clean up assignment of types to synthesized TypeExprs.
DougGregor May 17, 2019
13fb516
Remove restriction that @functionBuilders have to be uppercased;
rjmccall Jun 5, 2019
8d2cc9f
Merge fix: IBSegueAction apparently comes last in this list.
rjmccall Jun 6, 2019
2675608
Move the core builder-transform logic into its own file.
rjmccall Jun 12, 2019
9c8be4c
Fix cherry-pick to 5.1.
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
2 changes: 2 additions & 0 deletions include/swift/AST/ASTTypeIDs.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ struct PropertyWrapperBackingPropertyInfo;
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 @@ -406,6 +406,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 @@ -2705,6 +2705,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 @@ -5309,7 +5317,7 @@ class ParamDecl : public VarDecl {
assert(isVariadic());
return getVarargBaseTy(getInterfaceType());
}

SourceRange getSourceRange() const;

// Implement isa/cast/dyncast/etc.
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 @@ -4441,6 +4441,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
60 changes: 58 additions & 2 deletions include/swift/AST/TypeCheckRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ struct PropertyWrapperBackingPropertyInfo;
class RequirementRepr;
class SpecializeAttr;
struct TypeLoc;
class ValueDecl;

/// Display a nominal type or extension thereof.
void simple_display(
Expand Down Expand Up @@ -521,12 +522,67 @@ class PropertyWrapperBackingPropertyInfoRequest :
void noteCycleStep(DiagnosticEngine &diags) const;
};

/// 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<>
bool AnyValue::Holder<Type>::equals(const HolderBase &other) const;
inline bool AnyValue::Holder<Type>::equals(const HolderBase &other) const {
assert(typeID == other.typeID && "Caller should match type IDs");
return value.getPointer() ==
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 @@ -29,3 +29,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 @@ -3118,12 +3118,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 @@ -2598,6 +2598,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 @@ -1160,13 +1160,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 @@ -5649,6 +5649,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 @@ -742,16 +742,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 @@ -772,27 +775,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