Merge pull request #3857 from DougGregor/se-0111-ban-argument-labels
[SE-0111] Ban forming function types with argument labels (still under a flag)
diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def
index 0386ce5..3a4cb4a 100644
--- a/include/swift/AST/DiagnosticsParse.def
+++ b/include/swift/AST/DiagnosticsParse.def
@@ -616,6 +616,9 @@
"expected type before '->'", ())
ERROR(expected_type_after_arrow,none,
"expected type after '->'", ())
+ERROR(function_type_argument_label,none,
+ "function types cannot have argument label %0; use '_' instead",
+ (Identifier))
// Enum Types
ERROR(expected_expr_enum_case_raw_value,PointsToFirstBadToken,
@@ -647,6 +650,8 @@
"default argument not permitted in a protocol method", ())
ERROR(protocol_init_argument_init,none,
"default argument not permitted in a protocol initializer", ())
+ERROR(tuple_type_multiple_labels,none,
+ "tuple element cannot have two labels", ())
// Protocol Types
ERROR(expected_rangle_protocol,PointsToFirstBadToken,
@@ -704,6 +709,8 @@
"expected parameter type following ':'", ())
ERROR(expected_parameter_name,PointsToFirstBadToken,
"expected parameter name followed by ':'", ())
+ERROR(expected_parameter_colon,PointsToFirstBadToken,
+ "expected ':' following argumant label and parameter name", ())
ERROR(missing_parameter_type,PointsToFirstBadToken,
"parameter requires an explicit type", ())
ERROR(multiple_parameter_ellipsis,none,
diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp
index 249c103..68377c9 100644
--- a/lib/Parse/ParseType.cpp
+++ b/lib/Parse/ParseType.cpp
@@ -531,6 +531,10 @@
unsigned EllipsisIdx;
SmallVector<TypeRepr *, 8> ElementsR;
+ // We keep track of the labels separately, and apply them at the end.
+ SmallVector<std::tuple<Identifier, SourceLoc, Identifier, SourceLoc>, 4>
+ Labels;
+
ParserStatus Status = parseList(tok::r_paren, LPLoc, RPLoc,
tok::comma, /*OptionalSep=*/false,
/*AllowSepAfterLast=*/false,
@@ -545,18 +549,30 @@
hasAnyInOut = true;
hasValidInOut = false;
}
- // If the tuple element starts with "ident :", then
- // the identifier is an element tag, and it is followed by a type
- // annotation.
- if (Tok.canBeArgumentLabel() && peekToken().is(tok::colon)) {
+ // If the tuple element starts with a potential argument label followed by a
+ // ':' or another potential argument label, then the identifier is an
+ // element tag, and it is followed by a type annotation.
+ if (Tok.canBeArgumentLabel() &&
+ (peekToken().is(tok::colon) || peekToken().canBeArgumentLabel())) {
// Consume the name
Identifier name;
if (!Tok.is(tok::kw__))
name = Context.getIdentifier(Tok.getText());
SourceLoc nameLoc = consumeToken();
+ // If there is a second name, consume it as well.
+ Identifier secondName;
+ SourceLoc secondNameLoc;
+ if (Tok.canBeArgumentLabel()) {
+ if (!Tok.is(tok::kw__))
+ secondName = Context.getIdentifier(Tok.getText());
+ secondNameLoc = consumeToken();
+ }
+
// Consume the ':'.
- consumeToken(tok::colon);
+ if (!consumeIf(tok::colon))
+ diagnose(Tok, diag::expected_parameter_colon);
+
SourceLoc postColonLoc = Tok.getLoc();
// Consume 'inout' if present.
@@ -566,7 +582,7 @@
SourceLoc extraneousInOutLoc;
while (consumeIf(tok::kw_inout, extraneousInOutLoc)) {
- diagnose(Tok.getLoc(), diag::parameter_inout_var_let_repeated)
+ diagnose(Tok, diag::parameter_inout_var_let_repeated)
.fixItRemove(extraneousInOutLoc);
}
@@ -589,9 +605,17 @@
if (InOutLoc.isValid())
type = makeParserResult(new (Context) InOutTypeRepr(type.get(),
InOutLoc));
-
- ElementsR.push_back(
- new (Context) NamedTypeRepr(name, type.get(), nameLoc));
+
+ // Record the label. We will look at these at the end.
+ if (Labels.empty()) {
+ Labels.assign(ElementsR.size(),
+ std::make_tuple(Identifier(), SourceLoc(),
+ Identifier(), SourceLoc()));
+ }
+ Labels.push_back(std::make_tuple(name, nameLoc,
+ secondName, secondNameLoc));
+
+ ElementsR.push_back(type.get());
} else {
// Otherwise, this has to be a type.
ParserResult<TypeRepr> type = parseType();
@@ -603,6 +627,11 @@
type = makeParserResult(new (Context) InOutTypeRepr(type.get(),
InOutLoc));
+ if (!Labels.empty()) {
+ Labels.push_back(std::make_tuple(Identifier(), SourceLoc(),
+ Identifier(), SourceLoc()));
+ }
+
ElementsR.push_back(type.get());
}
@@ -637,6 +666,55 @@
if (EllipsisLoc.isInvalid())
EllipsisIdx = ElementsR.size();
+ // If there were any labels, figure out which labels should go into the type
+ // representation.
+ if (!Labels.empty()) {
+ assert(Labels.size() == ElementsR.size());
+ bool isFunctionType = Tok.isAny(tok::arrow, tok::kw_throws,
+ tok::kw_rethrows);
+ for (unsigned i : indices(ElementsR)) {
+ auto ¤tLabel = Labels[i];
+
+ Identifier firstName = std::get<0>(currentLabel);
+ SourceLoc firstNameLoc = std::get<1>(currentLabel);
+ Identifier secondName = std::get<2>(currentLabel);
+ SourceLoc secondNameLoc = std::get<3>(currentLabel);
+
+ // True tuples have labels.
+ if (!isFunctionType || !Context.LangOpts.SuppressArgumentLabelsInTypes) {
+ // If there were two names, complain.
+ if (firstNameLoc.isValid() && secondNameLoc.isValid()) {
+ auto diag = diagnose(firstNameLoc, diag::tuple_type_multiple_labels);
+ if (firstName.empty()) {
+ diag.fixItRemoveChars(firstNameLoc, ElementsR[i]->getStartLoc());
+ } else {
+ diag.fixItRemove(
+ SourceRange(Lexer::getLocForEndOfToken(SourceMgr,firstNameLoc),
+ secondNameLoc));
+ }
+ }
+
+ // Form the named type representation.
+ ElementsR[i] = new (Context) NamedTypeRepr(firstName, ElementsR[i],
+ firstNameLoc);
+ continue;
+ }
+
+ // If there was a first name, complain; arguments in function types are
+ // always unlabeled.
+ if (firstNameLoc.isValid() && !firstName.empty()) {
+ auto diag = diagnose(firstNameLoc, diag::function_type_argument_label,
+ firstName);
+ if (secondNameLoc.isInvalid())
+ diag.fixItInsert(firstNameLoc, "_ ");
+ else if (secondName.empty())
+ diag.fixItRemoveChars(firstNameLoc, ElementsR[i]->getStartLoc());
+ else
+ diag.fixItReplace(SourceRange(firstNameLoc), "_");
+ }
+ }
+ }
+
return makeParserResult(Status,
TupleTypeRepr::create(Context, ElementsR,
SourceRange(LPLoc, RPLoc),
@@ -1042,8 +1120,13 @@
// If the tuple element starts with "ident :", then it is followed
// by a type annotation.
- if (Tok.canBeArgumentLabel() && peekToken().is(tok::colon)) {
+ if (Tok.canBeArgumentLabel() &&
+ (peekToken().is(tok::colon) || peekToken().canBeArgumentLabel())) {
consumeToken();
+ if (Tok.canBeArgumentLabel()) {
+ consumeToken();
+ if (!Tok.is(tok::colon)) return false;
+ }
consumeToken(tok::colon);
// Parse attributes then a type.
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index c72b4b0..769fd41 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -812,7 +812,10 @@
if (outputOrigType.isTuple() &&
outputOrigType.getNumTupleElements() == 1) {
outputOrigType = outputOrigType.getTupleElementType(0);
- outputSubstType = cast<TupleType>(outputSubstType).getElementType(0);
+ if (auto outputSubstTuple = dyn_cast<TupleType>(outputSubstType)) {
+ if (outputSubstTuple->getNumElements() > 0)
+ outputSubstType = outputSubstTuple.getElementType(0);
+ }
return translate(inputOrigType, inputSubstType,
outputOrigType, outputSubstType);
}
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 662847a..1cec928 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -436,6 +436,7 @@
Expr *buildDeclRef(ValueDecl *decl, DeclNameLoc loc, Type openedType,
ConstraintLocatorBuilder locator,
bool specialized, bool implicit,
+ FunctionRefKind functionRefKind,
AccessSemantics semantics) {
// Determine the declaration selected for this overloaded reference.
auto &ctx = cs.getASTContext();
@@ -481,8 +482,10 @@
refExpr = new (ctx) MemberRefExpr(base, SourceLoc(), witness,
loc, /*Implicit=*/true);
} else {
- refExpr = new (ctx) DeclRefExpr(witness, loc,
- /*Implicit=*/false);
+ auto declRefExpr = new (ctx) DeclRefExpr(witness, loc,
+ /*Implicit=*/false);
+ declRefExpr->setFunctionRefKind(functionRefKind);
+ refExpr = declRefExpr;
}
if (tc.typeCheckExpression(refExpr, cs.DC,
@@ -508,8 +511,8 @@
return buildMemberRef(base, openedType, SourceLoc(), decl,
loc, openedFnType->getResult(),
- locator, locator, implicit, semantics,
- /*isDynamic=*/false);
+ locator, locator, implicit, functionRefKind,
+ semantics, /*isDynamic=*/false);
}
// If this is a declaration with generic function type, build a
@@ -523,8 +526,11 @@
genericFn, dc, openedType,
getConstraintSystem().getConstraintLocator(locator),
substitutions);
- return new (ctx) DeclRefExpr(ConcreteDeclRef(ctx, decl, substitutions),
- loc, implicit, semantics, type);
+ auto declRefExpr =
+ new (ctx) DeclRefExpr(ConcreteDeclRef(ctx, decl, substitutions),
+ loc, implicit, semantics, type);
+ declRefExpr->setFunctionRefKind(functionRefKind);
+ return declRefExpr;
}
auto type = simplifyType(openedType);
@@ -539,7 +545,10 @@
return nullptr;
}
- return new (ctx) DeclRefExpr(decl, loc, implicit, semantics, type);
+ auto declRefExpr = new (ctx) DeclRefExpr(decl, loc, implicit, semantics,
+ type);
+ declRefExpr->setFunctionRefKind(functionRefKind);
+ return declRefExpr;
}
/// Describes an opened existential that has not yet been closed.
@@ -778,8 +787,8 @@
ValueDecl *member, DeclNameLoc memberLoc,
Type openedType, ConstraintLocatorBuilder locator,
ConstraintLocatorBuilder memberLocator,
- bool Implicit, AccessSemantics semantics,
- bool isDynamic) {
+ bool Implicit, FunctionRefKind functionRefKind,
+ AccessSemantics semantics, bool isDynamic) {
auto &tc = cs.getTypeChecker();
auto &context = tc.Context;
@@ -866,7 +875,8 @@
if (auto func = dyn_cast<AbstractFunctionDecl>(member)) {
if ((isa<FuncDecl>(func) &&
(cast<FuncDecl>(func)->hasDynamicSelf() ||
- (openedExistential && cast<FuncDecl>(func)->hasArchetypeSelf()))) ||
+ (openedExistential &&
+ cast<FuncDecl>(func)->hasArchetypeSelf()))) ||
isPolymorphicConstructor(func)) {
refTy = refTy->replaceCovariantResultType(containerTy,
func->getNumParameterLists());
@@ -901,8 +911,9 @@
assert(semantics == AccessSemantics::Ordinary &&
"Direct property access doesn't make sense for this");
assert(!dynamicSelfFnType && "No reference type to convert to");
- Expr *ref = new (context) DeclRefExpr(memberRef, memberLoc, Implicit);
+ auto ref = new (context) DeclRefExpr(memberRef, memberLoc, Implicit);
ref->setType(refTy);
+ ref->setFunctionRefKind(functionRefKind);
return new (context) DotSyntaxBaseIgnoredExpr(base, dotLoc, ref);
}
@@ -959,6 +970,7 @@
Expr *ref = new (context) DynamicMemberRefExpr(base, dotLoc, memberRef,
memberLoc);
ref->setImplicit(Implicit);
+ // FIXME: FunctionRefKind
// Compute the type of the reference.
Type refType = simplifyType(openedType);
@@ -1005,9 +1017,11 @@
}
// Handle all other references.
- Expr *ref = new (context) DeclRefExpr(memberRef, memberLoc, Implicit,
- semantics);
- ref->setType(refTy);
+ auto declRefExpr = new (context) DeclRefExpr(memberRef, memberLoc,
+ Implicit, semantics);
+ declRefExpr->setFunctionRefKind(functionRefKind);
+ declRefExpr->setType(refTy);
+ Expr *ref = declRefExpr;
// If the reference needs to be converted, do so now.
if (dynamicSelfFnType) {
@@ -1404,8 +1418,8 @@
// Compute the concrete reference.
ConcreteDeclRef ref;
- Type resultTy = ctor->getInitializerInterfaceType();
- if (resultTy->is<GenericFunctionType>()) {
+ Type resultTy;
+ if (ctor->getInitializerInterfaceType()->is<GenericFunctionType>()) {
// Compute the reference to the generic constructor.
SmallVector<Substitution, 4> substitutions;
resultTy = solution.computeSubstitutions(
@@ -1416,20 +1430,23 @@
substitutions);
ref = ConcreteDeclRef(ctx, ctor, substitutions);
-
- // The constructor was opened with the allocating type, not the
- // initializer type. Map the former into the latter.
- auto resultFnTy = resultTy->castTo<FunctionType>();
- auto selfTy = resultFnTy->getInput()->getRValueInstanceType();
- if (!selfTy->hasReferenceSemantics())
- selfTy = InOutType::get(selfTy);
-
- resultTy = FunctionType::get(selfTy, resultFnTy->getResult(),
- resultFnTy->getExtInfo());
} else {
+ Type containerTy = ctor->getDeclContext()->getDeclaredTypeOfContext();
+ resultTy = openedFullType->replaceCovariantResultType(
+ containerTy, ctor->getNumParameterLists());
ref = ConcreteDeclRef(ctor);
}
+ // The constructor was opened with the allocating type, not the
+ // initializer type. Map the former into the latter.
+ auto resultFnTy = resultTy->castTo<FunctionType>();
+ auto selfTy = resultFnTy->getInput()->getRValueInstanceType();
+ if (!selfTy->hasReferenceSemantics())
+ selfTy = InOutType::get(selfTy);
+
+ resultTy = FunctionType::get(selfTy, resultFnTy->getResult(),
+ resultFnTy->getExtInfo());
+
// Build the constructor reference.
return new (ctx) OtherConstructorDeclRefExpr(ref, loc, implicit,
resultTy);
@@ -1449,10 +1466,10 @@
tc.validateDecl(fn);
ConcreteDeclRef fnDeclRef(fn);
- Expr *fnRef = new (tc.Context) DeclRefExpr(fnDeclRef,
- DeclNameLoc(loc),
- /*Implicit=*/true);
+ auto fnRef = new (tc.Context) DeclRefExpr(fnDeclRef, DeclNameLoc(loc),
+ /*Implicit=*/true);
fnRef->setType(fn->getInterfaceType());
+ fnRef->setFunctionRefKind(FunctionRefKind::SingleApply);
Expr *call = CallExpr::createImplicit(tc.Context, fnRef, { value }, { });
if (tc.typeCheckExpressionShallow(call, dc))
return nullptr;
@@ -1531,6 +1548,7 @@
/*implicit*/ true,
AccessSemantics::Ordinary,
bridgeFnTy);
+ fnRef->setFunctionRefKind(FunctionRefKind::SingleApply);
Expr *call = CallExpr::createImplicit(tc.Context, fnRef, valueParen,
{ Identifier() });
call->setType(bridgeTy);
@@ -1629,9 +1647,12 @@
}
ConcreteDeclRef fnSpecRef(tc.Context, fn, Subs);
- Expr *fnRef = new (tc.Context) DeclRefExpr(fnSpecRef,
- DeclNameLoc(object->getStartLoc()),
- /*Implicit=*/true);
+ auto fnRef = new (tc.Context) DeclRefExpr(fnSpecRef,
+ DeclNameLoc(
+ object->getStartLoc()),
+ /*Implicit=*/true);
+ fnRef->setFunctionRefKind(FunctionRefKind::SingleApply);
+
TypeSubstitutionMap subMap;
auto genericParam = fnGenericParams[0];
subMap[genericParam->getCanonicalType()->castTo<SubstitutableType>()]
@@ -2128,6 +2149,7 @@
DeclNameLoc(segment->getStartLoc()),
choice.openedType,
locator, locator, /*Implicit=*/true,
+ choice.choice.getFunctionRefKind(),
AccessSemantics::Ordinary,
/*isDynamic=*/false);
ApplyExpr *apply =
@@ -2237,6 +2259,7 @@
return buildDeclRef(decl, expr->getNameLoc(), selected->openedFullType,
locator, expr->isSpecialized(),
expr->isImplicit(),
+ expr->getFunctionRefKind(),
expr->getAccessSemantics());
}
@@ -2272,6 +2295,7 @@
return buildDeclRef(decl, expr->getNameLoc(), selected.openedFullType,
locator, expr->isSpecialized(), expr->isImplicit(),
+ choice.getFunctionRefKind(),
AccessSemantics::Ordinary);
}
@@ -2310,6 +2334,7 @@
cs.getConstraintLocator(expr),
memberLocator,
expr->isImplicit(),
+ selected.choice.getFunctionRefKind(),
expr->getAccessSemantics(),
isDynamic);
}
@@ -2362,6 +2387,7 @@
cs.getConstraintLocator(expr),
memberLocator,
expr->isImplicit(),
+ selected.choice.getFunctionRefKind(),
AccessSemantics::Ordinary,
isDynamic);
if (!result)
@@ -2395,6 +2421,7 @@
DeclNameLoc nameLoc, bool implicit,
ConstraintLocator *ctorLocator,
ConstructorDecl *ctor,
+ FunctionRefKind functionRefKind,
Type openedType) {
// If the subexpression is a metatype, build a direct reference to the
// constructor.
@@ -2405,6 +2432,7 @@
cs.getConstraintLocator(expr)),
ctorLocator,
implicit,
+ functionRefKind,
AccessSemantics::Ordinary,
/*isDynamic=*/false);
}
@@ -2472,7 +2500,8 @@
auto choice = selected->choice;
auto *ctor = cast<ConstructorDecl>(choice.getDecl());
return applyCtorRefExpr(expr, base, dotLoc, nameLoc, implicit,
- ctorLocator, ctor, selected->openedFullType);
+ ctorLocator, ctor, choice.getFunctionRefKind(),
+ selected->openedFullType);
}
// Determine the declaration selected for this overloaded reference.
@@ -2534,6 +2563,7 @@
cs.getConstraintLocator(expr),
memberLocator,
implicit,
+ selected.choice.getFunctionRefKind(),
AccessSemantics::Ordinary,
isDynamic);
@@ -3418,6 +3448,8 @@
}
DeclRefExpr *fnRef = new (ctx) DeclRefExpr(undefinedDecl, DeclNameLoc(),
/*Implicit=*/true);
+ fnRef->setFunctionRefKind(FunctionRefKind::SingleApply);
+
StringRef msg = "attempt to evaluate editor placeholder";
Expr *argExpr = new (ctx) StringLiteralExpr(msg, E->getLoc(),
/*implicit*/true);
@@ -6188,7 +6220,9 @@
selected->openedType,
locator,
ctorLocator,
- /*Implicit=*/true, AccessSemantics::Ordinary,
+ /*Implicit=*/true,
+ choice.getFunctionRefKind(),
+ AccessSemantics::Ordinary,
isDynamic);
if (!declRef)
return nullptr;
@@ -6774,11 +6808,12 @@
// Form a syntactic expression that describes the reference to the
// witness.
// FIXME: Egregious hack.
- Expr *unresolvedDot = new (Context) UnresolvedDotExpr(
- base, SourceLoc(),
- witness->getFullName(),
- DeclNameLoc(base->getEndLoc()),
- /*Implicit=*/true);
+ auto unresolvedDot = new (Context) UnresolvedDotExpr(
+ base, SourceLoc(),
+ witness->getFullName(),
+ DeclNameLoc(base->getEndLoc()),
+ /*Implicit=*/true);
+ unresolvedDot->setFunctionRefKind(FunctionRefKind::SingleApply);
auto dotLocator = cs.getConstraintLocator(unresolvedDot);
// Form a reference to the witness itself.
@@ -6850,6 +6885,7 @@
DeclNameLoc(base->getEndLoc()),
openedType, dotLocator, dotLocator,
/*Implicit=*/true,
+ FunctionRefKind::SingleApply,
AccessSemantics::Ordinary,
/*isDynamic=*/false);
call->setFn(memberRef);
diff --git a/test/IDE/complete_type.swift b/test/IDE/complete_type.swift
index c258758..9ff3d32 100644
--- a/test/IDE/complete_type.swift
+++ b/test/IDE/complete_type.swift
@@ -637,6 +637,8 @@
typealias TypeInTypealias2 = (#^TYPE_IN_TYPEALIAS_2^#
+func resyncParser0() {}
+
typealias TypeInTypealias3 = ((#^TYPE_IN_TYPEALIAS_3^#
func resyncParser1() {}
diff --git a/test/SILGen/generic_closures.swift b/test/SILGen/generic_closures.swift
index e2c2c6d..12621c8 100644
--- a/test/SILGen/generic_closures.swift
+++ b/test/SILGen/generic_closures.swift
@@ -1,4 +1,5 @@
// RUN: %target-swift-frontend -parse-stdlib -emit-silgen %s | FileCheck %s
+// RUN: %target-swift-frontend -parse-stdlib -emit-silgen -suppress-argument-labels-in-types %s | FileCheck %s
import Swift
diff --git a/test/SILGen/partial_apply_init.swift b/test/SILGen/partial_apply_init.swift
index 403178b..66aaf46 100644
--- a/test/SILGen/partial_apply_init.swift
+++ b/test/SILGen/partial_apply_init.swift
@@ -1,4 +1,5 @@
// RUN: %target-swift-frontend -emit-silgen %s | FileCheck %s
+// RUN: %target-swift-frontend -emit-silgen -suppress-argument-labels-in-types %s | FileCheck %s
class C {
init(x: Int) {}
diff --git a/test/SILGen/protocol_extensions.swift b/test/SILGen/protocol_extensions.swift
index daf48b09..bf84600 100644
--- a/test/SILGen/protocol_extensions.swift
+++ b/test/SILGen/protocol_extensions.swift
@@ -1,4 +1,5 @@
// RUN: %target-swift-frontend -disable-objc-attr-requires-foundation-module -emit-silgen %s | FileCheck %s
+// RUN: %target-swift-frontend -disable-objc-attr-requires-foundation-module -emit-silgen -suppress-argument-labels-in-types %s | FileCheck %s
public protocol P1 {
func reqP1a()
diff --git a/test/Sema/suppress-argument-labels-in-types.swift b/test/Sema/suppress-argument-labels-in-types.swift
index f5cabf9..3a5c1a1 100644
--- a/test/Sema/suppress-argument-labels-in-types.swift
+++ b/test/Sema/suppress-argument-labels-in-types.swift
@@ -57,11 +57,8 @@
let _: (Int, Int) -> Int = f4
let _: (Double, Double) -> Double = f4
- // Note: these will become ill-formed when the rest of SE-0111 is
- // implemented. For now, they check that the labels were removed by the type
- // system.
- let _: (x: Int, y: Int) -> Int = f4
- let _: (x: Double, y: Double) -> Double = f4
+ let _: (_ x: Int, _ y: Int) -> Int = f4
+ let _: (_ x: Double, _ y: Double) -> Double = f4
}
// Test module-qualified function references.
@@ -87,11 +84,8 @@
let _: (Int, Int) -> Int = TestModule.f4
let _: (Double, Double) -> Double = TestModule.f4
- // Note: these will become ill-formed when the rest of SE-0111 is
- // implemented. For now, they check that the labels were removed by the type
- // system.
- let _: (x: Int, y: Int) -> Int = TestModule.f4
- let _: (x: Double, y: Double) -> Double = TestModule.f4
+ let _: (_ x: Int, _ y: Int) -> Int = TestModule.f4
+ let _: (_ x: Double, _ y: Double) -> Double = TestModule.f4
}
// Test member references.
@@ -135,11 +129,8 @@
let _: (Int, Int) -> Int = s0.f4
let _: (Double, Double) -> Double = s0.f4
- // Note: these will become ill-formed when the rest of SE-0111 is
- // implemented. For now, they check that the labels were removed by the type
- // system.
- let _: (x: Int, y: Int) -> Int = s0.f4
- let _: (x: Double, y: Double) -> Double = s0.f4
+ let _: (_ x: Int, _ y: Int) -> Int = s0.f4
+ let _: (_ x: Double, _ y: Double) -> Double = s0.f4
}
// Curried instance methods.
@@ -170,9 +161,46 @@
let _: Int = s0c2 // expected-error{{cannot convert value of type '(Int, Int) -> S0' to specified type 'Int'}}
}
-func testS0Subscripts(s0: S0, a: Int, b: Int) {
+struct S1 {
+ subscript (i: Int) -> Int {
+ get { }
+ nonmutating set { }
+ }
+}
+
+func testS0Subscripts(s0: S0, s1: S1, a: Int, b: Int) {
let _ = s0[a: a, b: b]
var s0Var = s0
s0Var[a: a, b: b] = a
+
+ let _ = s1[a]
+ s1[a] = b
}
+
+struct S2 {
+ let s1: S1
+}
+
+func testS1Subscripts(s2: S2, a: Int) {
+ let _ = s2.s1[a]
+ s2.s1[a] = a
+}
+
+// Test delegating initialization.
+struct S3 {
+ init(a: Int, b: Int) { }
+
+ init(all: Int) {
+ self.init(a:b:)(all, all)
+ }
+}
+
+
+// Check lazy inference, which broke in amusing ways with SE-0111.
+class C0 {
+ lazy var a = 32
+}
+
+// Check diagnostics changes.
+let _ = min(Int(3), Float(2.5)) // expected-error{{cannot convert value of type 'Float' to expected argument type 'Int'}}
diff --git a/test/type/function/labels.swift b/test/type/function/labels.swift
new file mode 100644
index 0000000..df2af1e
--- /dev/null
+++ b/test/type/function/labels.swift
@@ -0,0 +1,35 @@
+// RUN: %target-swift-frontend -module-name TestModule -parse -verify -suppress-argument-labels-in-types %s
+
+// Function type with various forms of argument label.
+typealias Function1 = (a: Int, // expected-error{{function types cannot have argument label 'a'; use '_' instead}}{{24-24=_ }}
+ _ b: Int, // okay
+ c d: Int, // expected-error{{function types cannot have argument label 'c'; use '_' instead}}{{24-25=_}}
+ e _: Int, // expected-error{{function types cannot have argument label 'e'; use '_' instead}}{{24-29=}}
+ _: Int, // okay
+ Int) // okay
+ -> Int
+
+// Throwing versions.
+typealias Function2 = (a: Int, // expected-error{{function types cannot have argument label 'a'; use '_' instead}}{{24-24=_ }}
+ _ b: Int, // okay
+ c d: Int, // expected-error{{function types cannot have argument label 'c'; use '_' instead}}{{24-25=_}}
+ e _: Int, // expected-error{{function types cannot have argument label 'e'; use '_' instead}}{{24-29=}}
+ _: Int, // okay
+ Int) // okay
+ throws -> Int
+
+typealias Function3 = (a: Int, // expected-error{{function types cannot have argument label 'a'; use '_' instead}}{{24-24=_ }}
+ _ b: Int, // okay
+ c d: Int, // expected-error{{function types cannot have argument label 'c'; use '_' instead}}{{24-25=_}}
+ e _: Int, // expected-error{{function types cannot have argument label 'e'; use '_' instead}}{{24-29=}}
+ _: Int, // okay
+ Int) // okay
+ rethrows -> Int // expected-error{{only function declarations may be marked 'rethrows'}}
+
+
+
+struct S2<X> { }
+
+func testTentativeParsing() {
+ let _ = S2<(_ x: Int, _ y: Double) -> Int>()
+}
diff --git a/test/type/tuple/labels.swift b/test/type/tuple/labels.swift
new file mode 100644
index 0000000..9118d28
--- /dev/null
+++ b/test/type/tuple/labels.swift
@@ -0,0 +1,6 @@
+// RUN: %target-swift-frontend -module-name TestModule -parse -verify -suppress-argument-labels-in-types %s
+
+typealias Tuple1 = (a: Int,
+ b _: Int, // expected-error{{tuple element cannot have two labels}}{{22-24=}}
+ _ c: Int, // expected-error{{tuple element cannot have two labels}}{{21-26=}}
+ d e: Int) // expected-error{{tuple element cannot have two labels}}{{22-24=}}