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 &currentLabel = 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=}}