Skip to content

Commit a700e23

Browse files
authored
Merge pull request #17191 from CodaFi/tuplet-rudiments
2 parents 2fe6b11 + f208886 commit a700e23

29 files changed

+223
-197
lines changed

include/swift/AST/DiagnosticsCommon.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ ERROR(generic_signature_not_minimal,none,
9090
ERROR(attr_only_on_parameters, none,
9191
"'%0' may only be used on parameters", (StringRef))
9292

93+
ERROR(function_type_no_parens,none,
94+
"single argument function types require parentheses", ())
95+
9396
#ifndef DIAG_NO_UNDEF
9497
# if defined(DIAG)
9598
# undef DIAG

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3464,8 +3464,6 @@ ERROR(objc_invalid_with_generic_params,none,
34643464
ERROR(objc_convention_invalid,none,
34653465
"%0 is not representable in Objective-C, so it cannot be used"
34663466
" with '@convention(%1)'", (Type, StringRef))
3467-
ERROR(function_type_no_parens,none,
3468-
"single argument function types require parentheses", ())
34693467
WARNING(paren_void_probably_void,none,
34703468
"when calling this function in Swift 4 or later, you must pass a '()' tuple; did you mean for the input type to be '()'?", ())
34713469
NOTE(not_objc_empty_protocol_composition,none,

include/swift/AST/TypeRepr.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ namespace swift {
3434
class DeclContext;
3535
class GenericEnvironment;
3636
class IdentTypeRepr;
37+
class TupleTypeRepr;
3738
class TypeDecl;
3839

3940
enum class TypeReprKind : uint8_t {
@@ -467,21 +468,23 @@ inline IdentTypeRepr::ComponentRange IdentTypeRepr::getComponentRange() {
467468

468469
/// \brief A function type.
469470
/// \code
470-
/// Foo -> Bar
471+
/// (Foo) -> Bar
472+
/// (Foo, Bar) -> Baz
473+
/// (x: Foo, y: Bar) -> Baz
471474
/// \endcode
472475
class FunctionTypeRepr : public TypeRepr {
473476
// These three are only used in SIL mode, which is the only time
474477
// we can have polymorphic function values.
475478
GenericParamList *GenericParams;
476479
GenericEnvironment *GenericEnv;
477480

478-
TypeRepr *ArgsTy;
481+
TupleTypeRepr *ArgsTy;
479482
TypeRepr *RetTy;
480483
SourceLoc ArrowLoc;
481484
SourceLoc ThrowsLoc;
482485

483486
public:
484-
FunctionTypeRepr(GenericParamList *genericParams, TypeRepr *argsTy,
487+
FunctionTypeRepr(GenericParamList *genericParams, TupleTypeRepr *argsTy,
485488
SourceLoc throwsLoc, SourceLoc arrowLoc, TypeRepr *retTy)
486489
: TypeRepr(TypeReprKind::Function),
487490
GenericParams(genericParams),
@@ -498,7 +501,7 @@ class FunctionTypeRepr : public TypeRepr {
498501
GenericEnv = genericEnv;
499502
}
500503

501-
TypeRepr *getArgsTypeRepr() const { return ArgsTy; }
504+
TupleTypeRepr *getArgsTypeRepr() const { return ArgsTy; }
502505
TypeRepr *getResultTypeRepr() const { return RetTy; }
503506
bool throws() const { return ThrowsLoc.isValid(); }
504507

@@ -511,7 +514,7 @@ class FunctionTypeRepr : public TypeRepr {
511514
static bool classof(const FunctionTypeRepr *T) { return true; }
512515

513516
private:
514-
SourceLoc getStartLocImpl() const { return ArgsTy->getStartLoc(); }
517+
SourceLoc getStartLocImpl() const;
515518
SourceLoc getEndLocImpl() const { return RetTy->getEndLoc(); }
516519
SourceLoc getLocImpl() const { return ArrowLoc; }
517520

lib/AST/TypeRepr.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,12 @@ TypeRepr *CloneVisitor::visitCompoundIdentTypeRepr(CompoundIdentTypeRepr *T) {
157157
}
158158

159159
TypeRepr *CloneVisitor::visitFunctionTypeRepr(FunctionTypeRepr *T) {
160-
return new (Ctx) FunctionTypeRepr(/*FIXME: Clone?*/T->getGenericParams(),
161-
visit(T->getArgsTypeRepr()),
162-
T->getThrowsLoc(),
163-
T->getArrowLoc(),
164-
visit(T->getResultTypeRepr()));
160+
return new (Ctx) FunctionTypeRepr(
161+
/*FIXME: Clone?*/T->getGenericParams(),
162+
cast<TupleTypeRepr>(visit(T->getArgsTypeRepr())),
163+
T->getThrowsLoc(),
164+
T->getArrowLoc(),
165+
visit(T->getResultTypeRepr()));
165166
}
166167

167168
TypeRepr *CloneVisitor::visitArrayTypeRepr(ArrayTypeRepr *T) {
@@ -478,6 +479,10 @@ SILBoxTypeRepr *SILBoxTypeRepr::create(ASTContext &C,
478479
ArgLAngleLoc, GenericArgs, ArgRAngleLoc);
479480
}
480481

482+
SourceLoc FunctionTypeRepr::getStartLocImpl() const {
483+
return ArgsTy->getStartLoc();
484+
}
485+
481486
SourceLoc SILBoxTypeRepr::getStartLocImpl() const {
482487
if (GenericParams && GenericParams->getSourceRange().isValid())
483488
return GenericParams->getSourceRange().Start;

lib/Parse/ParseType.cpp

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,24 +44,6 @@ TypeRepr *Parser::applyAttributeToType(TypeRepr *ty,
4444

4545
// Apply 'inout' or '__shared' or '__owned'
4646
if (specifierLoc.isValid()) {
47-
if (auto *fnTR = dyn_cast<FunctionTypeRepr>(ty)) {
48-
// If the input to the function isn't parenthesized, apply the inout
49-
// to the first (only) parameter, as we would in Swift 2. (This
50-
// syntax is deprecated in Swift 3.)
51-
TypeRepr *argsTR = fnTR->getArgsTypeRepr();
52-
if (!isa<TupleTypeRepr>(argsTR)) {
53-
auto *newArgsTR =
54-
new (Context) InOutTypeRepr(argsTR, specifierLoc);
55-
auto *newTR =
56-
new (Context) FunctionTypeRepr(fnTR->getGenericParams(),
57-
newArgsTR,
58-
fnTR->getThrowsLoc(),
59-
fnTR->getArrowLoc(),
60-
fnTR->getResultTypeRepr());
61-
newTR->setGenericEnvironment(fnTR->getGenericEnvironment());
62-
return newTR;
63-
}
64-
}
6547
switch (specifier) {
6648
case VarDecl::Specifier::Owned:
6749
ty = new (Context) OwnedTypeRepr(ty, specifierLoc);
@@ -461,7 +443,33 @@ ParserResult<TypeRepr> Parser::parseType(Diag<> MessageID,
461443
}
462444
SyntaxContext->addSyntax(Builder.build());
463445
}
464-
tyR = new (Context) FunctionTypeRepr(generics, tyR, throwsLoc, arrowLoc,
446+
447+
TupleTypeRepr *argsTyR = nullptr;
448+
if (auto *TTArgs = dyn_cast<TupleTypeRepr>(tyR)) {
449+
argsTyR = TTArgs;
450+
} else {
451+
bool isVoid = false;
452+
if (const auto Void = dyn_cast<SimpleIdentTypeRepr>(tyR)) {
453+
if (Void->getIdentifier().str() == "Void") {
454+
isVoid = true;
455+
}
456+
}
457+
458+
if (isVoid) {
459+
diagnose(tyR->getStartLoc(), diag::function_type_no_parens)
460+
.fixItReplace(tyR->getStartLoc(), "()");
461+
argsTyR = TupleTypeRepr::createEmpty(Context, tyR->getSourceRange());
462+
} else {
463+
diagnose(tyR->getStartLoc(), diag::function_type_no_parens)
464+
.highlight(tyR->getSourceRange())
465+
.fixItInsert(tyR->getStartLoc(), "(")
466+
.fixItInsertAfter(tyR->getEndLoc(), ")");
467+
argsTyR = TupleTypeRepr::create(Context, {tyR},
468+
tyR->getSourceRange());
469+
}
470+
}
471+
472+
tyR = new (Context) FunctionTypeRepr(generics, argsTyR, throwsLoc, arrowLoc,
465473
SecondHalf.get());
466474
} else if (generics) {
467475
// Only function types may be generic.

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,6 +1474,53 @@ TypeExpr *PreCheckExpression::simplifyTypeExpr(Expr *E) {
14741474
if (auto *AE = dyn_cast<ArrowExpr>(E)) {
14751475
if (!AE->isFolded()) return nullptr;
14761476

1477+
auto diagnoseMissingParens = [](TypeChecker &TC, TypeRepr *tyR) {
1478+
bool isVoid = false;
1479+
if (const auto Void = dyn_cast<SimpleIdentTypeRepr>(tyR)) {
1480+
if (Void->getIdentifier().str() == "Void") {
1481+
isVoid = true;
1482+
}
1483+
}
1484+
1485+
if (isVoid) {
1486+
TC.diagnose(tyR->getStartLoc(), diag::function_type_no_parens)
1487+
.fixItReplace(tyR->getStartLoc(), "()");
1488+
} else {
1489+
TC.diagnose(tyR->getStartLoc(), diag::function_type_no_parens)
1490+
.highlight(tyR->getSourceRange())
1491+
.fixItInsert(tyR->getStartLoc(), "(")
1492+
.fixItInsertAfter(tyR->getEndLoc(), ")");
1493+
}
1494+
};
1495+
1496+
auto extractInputTypeRepr = [&](Expr *E) -> TupleTypeRepr * {
1497+
if (!E)
1498+
return nullptr;
1499+
if (auto *TyE = dyn_cast<TypeExpr>(E)) {
1500+
auto ArgRepr = TyE->getTypeRepr();
1501+
if (auto *TTyRepr = dyn_cast<TupleTypeRepr>(ArgRepr))
1502+
return TTyRepr;
1503+
diagnoseMissingParens(TC, ArgRepr);
1504+
return TupleTypeRepr::create(TC.Context, {ArgRepr},
1505+
ArgRepr->getSourceRange());
1506+
}
1507+
if (auto *TE = dyn_cast<TupleExpr>(E))
1508+
if (TE->getNumElements() == 0)
1509+
return TupleTypeRepr::createEmpty(TC.Context, TE->getSourceRange());
1510+
1511+
// When simplifying a type expr like "(P1 & P2) -> (P3 & P4) -> Int",
1512+
// it may have been folded at the same time; recursively simplify it.
1513+
if (auto ArgsTypeExpr = simplifyTypeExpr(E)) {
1514+
auto ArgRepr = ArgsTypeExpr->getTypeRepr();
1515+
if (auto *TTyRepr = dyn_cast<TupleTypeRepr>(ArgRepr))
1516+
return TTyRepr;
1517+
diagnoseMissingParens(TC, ArgRepr);
1518+
return TupleTypeRepr::create(TC.Context, {ArgRepr},
1519+
ArgRepr->getSourceRange());
1520+
}
1521+
return nullptr;
1522+
};
1523+
14771524
auto extractTypeRepr = [&](Expr *E) -> TypeRepr * {
14781525
if (!E)
14791526
return nullptr;
@@ -1490,12 +1537,14 @@ TypeExpr *PreCheckExpression::simplifyTypeExpr(Expr *E) {
14901537
return nullptr;
14911538
};
14921539

1493-
TypeRepr *ArgsTypeRepr = extractTypeRepr(AE->getArgsExpr());
1540+
TupleTypeRepr *ArgsTypeRepr = extractInputTypeRepr(AE->getArgsExpr());
14941541
if (!ArgsTypeRepr) {
14951542
TC.diagnose(AE->getArgsExpr()->getLoc(),
14961543
diag::expected_type_before_arrow);
1497-
ArgsTypeRepr =
1498-
new (TC.Context) ErrorTypeRepr(AE->getArgsExpr()->getSourceRange());
1544+
auto ArgRange = AE->getArgsExpr()->getSourceRange();
1545+
auto ErrRepr =
1546+
new (TC.Context) ErrorTypeRepr(ArgRange);
1547+
ArgsTypeRepr = TupleTypeRepr::create(TC.Context, {ErrRepr}, ArgRange);
14991548
}
15001549

15011550
TypeRepr *ResultTypeRepr = extractTypeRepr(AE->getResultExpr());

lib/Sema/TypeCheckType.cpp

Lines changed: 22 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2036,7 +2036,7 @@ Type TypeResolver::resolveAttributedType(TypeAttributes &attrs,
20362036
attrs.clearAttribute(TAK_autoclosure);
20372037
}
20382038

2039-
auto *FuncTyInput = dyn_cast<TupleTypeRepr>(fnRepr->getArgsTypeRepr());
2039+
auto *FuncTyInput = fnRepr->getArgsTypeRepr();
20402040
if ((!FuncTyInput || FuncTyInput->getNumElements() != 0)
20412041
&& attrs.has(TAK_autoclosure)) {
20422042
TC.diagnose(attrs.getLoc(TAK_autoclosure),
@@ -2210,43 +2210,18 @@ Type TypeResolver::resolveASTFunctionType(FunctionTypeRepr *repr,
22102210

22112211
// If this is a function type without parens around the parameter list,
22122212
// diagnose this and produce a fixit to add them.
2213-
if (!isa<TupleTypeRepr>(repr->getArgsTypeRepr()) &&
2214-
!repr->isWarnedAbout()) {
2215-
auto args = repr->getArgsTypeRepr();
2216-
2217-
bool isVoid = false;
2218-
if (const auto Void = dyn_cast<SimpleIdentTypeRepr>(args)) {
2219-
if (Void->getIdentifier().str() == "Void") {
2220-
isVoid = true;
2221-
}
2222-
}
2223-
if (isVoid) {
2224-
TC.diagnose(args->getStartLoc(), diag::function_type_no_parens)
2225-
.fixItReplace(args->getStartLoc(), "()");
2226-
} else {
2227-
TC.diagnose(args->getStartLoc(), diag::function_type_no_parens)
2228-
.highlight(args->getSourceRange())
2229-
.fixItInsert(args->getStartLoc(), "(")
2230-
.fixItInsertAfter(args->getEndLoc(), ")");
2231-
}
2232-
2233-
// Don't emit this warning three times when in generics.
2234-
repr->setWarned();
2235-
} else if (isa<TupleTypeRepr>(repr->getArgsTypeRepr()) &&
2236-
!repr->isWarnedAbout()) {
2213+
if (!repr->isWarnedAbout()) {
22372214
// If someone wrote (Void) -> () in Swift 3, they probably meant
22382215
// () -> (), but (Void) -> () is (()) -> () so emit a warning
22392216
// asking if they meant () -> ().
22402217
auto args = repr->getArgsTypeRepr();
2241-
if (const auto Tuple = dyn_cast<TupleTypeRepr>(args)) {
2242-
if (Tuple->getNumElements() == 1) {
2243-
if (const auto Void =
2244-
dyn_cast<SimpleIdentTypeRepr>(Tuple->getElementType(0))) {
2245-
if (Void->getIdentifier().str() == "Void") {
2246-
TC.diagnose(args->getStartLoc(), diag::paren_void_probably_void)
2247-
.fixItReplace(args->getSourceRange(), "()");
2248-
repr->setWarned();
2249-
}
2218+
if (args->getNumElements() == 1) {
2219+
if (const auto Void =
2220+
dyn_cast<SimpleIdentTypeRepr>(args->getElementType(0))) {
2221+
if (Void->getIdentifier().str() == "Void") {
2222+
TC.diagnose(args->getStartLoc(), diag::paren_void_probably_void)
2223+
.fixItReplace(args->getSourceRange(), "()");
2224+
repr->setWarned();
22502225
}
22512226
}
22522227
}
@@ -2394,29 +2369,20 @@ Type TypeResolver::resolveSILFunctionType(FunctionTypeRepr *repr,
23942369
&*resolveSILFunctionGenericParams);
23952370
}
23962371

2397-
if (auto tuple = dyn_cast<TupleTypeRepr>(repr->getArgsTypeRepr())) {
2398-
// SIL functions cannot be variadic.
2399-
if (tuple->hasEllipsis()) {
2400-
TC.diagnose(tuple->getEllipsisLoc(), diag::sil_function_ellipsis);
2401-
}
2402-
// SIL functions cannot have parameter names.
2403-
for (auto &element : tuple->getElements()) {
2404-
if (element.UnderscoreLoc.isValid())
2405-
TC.diagnose(element.UnderscoreLoc, diag::sil_function_input_label);
2406-
}
2407-
2408-
for (auto elt : tuple->getElements()) {
2409-
auto param = resolveSILParameter(elt.Type,
2410-
options | TypeResolutionFlags::ImmediateFunctionInput);
2411-
params.push_back(param);
2412-
if (!param.getType()) return nullptr;
2372+
auto argsTuple = repr->getArgsTypeRepr();
2373+
// SIL functions cannot be variadic.
2374+
if (argsTuple->hasEllipsis()) {
2375+
TC.diagnose(argsTuple->getEllipsisLoc(), diag::sil_function_ellipsis);
2376+
}
2377+
// SIL functions cannot have parameter names.
2378+
for (auto &element : argsTuple->getElements()) {
2379+
if (element.UnderscoreLoc.isValid())
2380+
TC.diagnose(element.UnderscoreLoc, diag::sil_function_input_label);
2381+
}
24132382

2414-
if (param.getType()->hasError())
2415-
hasError = true;
2416-
}
2417-
} else {
2418-
SILParameterInfo param = resolveSILParameter(repr->getArgsTypeRepr(),
2419-
options | TypeResolutionFlags::ImmediateFunctionInput);
2383+
for (auto elt : argsTuple->getElements()) {
2384+
auto param = resolveSILParameter(elt.Type,
2385+
options | TypeResolutionFlags::ImmediateFunctionInput);
24202386
params.push_back(param);
24212387
if (!param.getType()) return nullptr;
24222388

test/IDE/complete_crashes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ func flip<A, B, C>(_ f: A -> B -> C) -> B -> A -> C { }
140140
func rdar22688199() {
141141
let f = flip(curried)(#^RDAR_22688199^#
142142
}
143-
// FLIP_CURRIED: Pattern/CurrModule: ['(']{#Int#}, {#Int#}[')'][#(Int) -> ()#]
143+
// FLIP_CURRIED: Pattern/CurrModule: ['(']{#(Int, Int)#}[')'][#(Int) -> ()#]
144144

145145
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=RDAR_22836263
146146
func rdar22836263() {

test/IRGen/bridge_object_arm64.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@ entry(%c : $C, %w : $Builtin.Word):
4141
// CHECK: br label %tagged-cont
4242
// CHECK: tagged-cont:
4343
// CHECK: phi [[C]] [ [[TAGGED_RESULT]], %tagged-pointer ], [ [[MASKED_RESULT]], %not-tagged-pointer ]
44-
sil @convert_from_bridge_object : $Builtin.BridgeObject -> (ObjC, Builtin.Word) {
44+
sil @convert_from_bridge_object : $(Builtin.BridgeObject) -> (ObjC, Builtin.Word) {
4545
entry(%b : $Builtin.BridgeObject):
4646
%c = bridge_object_to_ref %b : $Builtin.BridgeObject to $ObjC
4747
%w = bridge_object_to_word %b : $Builtin.BridgeObject to $Builtin.Word
4848
%t = tuple (%c : $ObjC, %w : $Builtin.Word)
4949
return %t : $(ObjC, Builtin.Word)
5050
}
5151

52-
sil @convert_from_native_bridge_object : $Builtin.BridgeObject -> C {
52+
sil @convert_from_native_bridge_object : $(Builtin.BridgeObject) -> C {
5353
entry(%b : $Builtin.BridgeObject):
5454
%c = bridge_object_to_ref %b : $Builtin.BridgeObject to $C
5555
return %c : $C

test/IRGen/bridge_object_armv7.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ entry(%c : $C, %w : $Builtin.Word):
2828
// CHECK: [[BOBITS:%.*]] = ptrtoint [[BRIDGE:%swift.bridge\*]] %0 to i32
2929
// CHECK: [[MASKED_BITS:%.*]] = and i32 [[BOBITS]], -4
3030
// CHECK: inttoptr i32 [[MASKED_BITS]] to [[C:%objc_object\*]]
31-
sil @convert_from_bridge_object : $Builtin.BridgeObject -> (ObjC, Builtin.Word) {
31+
sil @convert_from_bridge_object : $(Builtin.BridgeObject) -> (ObjC, Builtin.Word) {
3232
entry(%b : $Builtin.BridgeObject):
3333
%c = bridge_object_to_ref %b : $Builtin.BridgeObject to $ObjC
3434
%w = bridge_object_to_word %b : $Builtin.BridgeObject to $Builtin.Word
3535
%t = tuple (%c : $ObjC, %w : $Builtin.Word)
3636
return %t : $(ObjC, Builtin.Word)
3737
}
3838

39-
sil @convert_from_native_bridge_object : $Builtin.BridgeObject -> C {
39+
sil @convert_from_native_bridge_object : $(Builtin.BridgeObject) -> C {
4040
entry(%b : $Builtin.BridgeObject):
4141
%c = bridge_object_to_ref %b : $Builtin.BridgeObject to $C
4242
return %c : $C

test/IRGen/bridge_object_x86_64.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ entry(%c : $C, %w : $Builtin.Word):
4848
// CHECK: tagged-cont:
4949
// CHECK: phi [[C]] [ [[TAGGED_RESULT]], %tagged-pointer ], [ [[MASKED_RESULT]], %not-tagged-pointer ]
5050

51-
sil @convert_from_bridge_object : $Builtin.BridgeObject -> (ObjC, Builtin.Word) {
51+
sil @convert_from_bridge_object : $(Builtin.BridgeObject) -> (ObjC, Builtin.Word) {
5252
entry(%b : $Builtin.BridgeObject):
5353
%c = bridge_object_to_ref %b : $Builtin.BridgeObject to $ObjC
5454
%w = bridge_object_to_word %b : $Builtin.BridgeObject to $Builtin.Word
@@ -61,7 +61,7 @@ entry(%b : $Builtin.BridgeObject):
6161
// CHECK: [[MASKED_BITS:%.*]] = and i64 [[BOBITS]], 72057594037927928
6262
// CHECK: [[RESULT:%.*]] = inttoptr i64 [[MASKED_BITS]] to [[C:%T13bridge_object1CC\*]]
6363
// CHECK: ret %T13bridge_object1CC* [[RESULT]]
64-
sil @convert_from_native_bridge_object : $Builtin.BridgeObject -> C {
64+
sil @convert_from_native_bridge_object : $(Builtin.BridgeObject) -> C {
6565
entry(%b : $Builtin.BridgeObject):
6666
%c = bridge_object_to_ref %b : $Builtin.BridgeObject to $C
6767
return %c : $C

0 commit comments

Comments
 (0)