//===--- ParseType.cpp - Swift Language Parser for Types ------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Type Parsing and AST Building
//
//===----------------------------------------------------------------------===//

#include "ParseList.h"
#include "swift/Parse/Parser.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/Attr.h"
#include "swift/AST/TypeLoc.h"
#include "swift/AST/TypeRepr.h"
#include "swift/Parse/Lexer.h"
#include "swift/Parse/CodeCompletionCallbacks.h"
#include "swift/Parse/SyntaxParsingContext.h"
#include "swift/Parse/ParsedSyntaxBuilders.h"
#include "swift/Parse/ParsedSyntaxRecorder.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/SaveAndRestore.h"

using namespace swift;
using namespace swift::syntax;

TypeRepr *Parser::applyAttributeToType(TypeRepr *ty,
                                       const TypeAttributes &attrs,
                                       ParamDecl::Specifier specifier,
                                       SourceLoc specifierLoc) {
  // Apply those attributes that do apply.
  if (!attrs.empty()) {
    ty = new (Context) AttributedTypeRepr(attrs, ty);
  }

  // Apply 'inout' or '__shared' or '__owned'
  if (specifierLoc.isValid()) {
    switch (specifier) {
    case ParamDecl::Specifier::Owned:
      ty = new (Context) OwnedTypeRepr(ty, specifierLoc);
      break;
    case ParamDecl::Specifier::InOut:
      ty = new (Context) InOutTypeRepr(ty, specifierLoc);
      break;
    case ParamDecl::Specifier::Shared:
      ty = new (Context) SharedTypeRepr(ty, specifierLoc);
      break;
    case ParamDecl::Specifier::Default:
      break;
    }
  }

  return ty;
}

/// Apply specifier and attributes to the parsed type.
ParsedSyntaxResult<ParsedTypeSyntax>
Parser::applyAttributeToTypeSyntax(ParsedSyntaxResult<ParsedTypeSyntax> &&ty,
                                   Optional<ParsedTokenSyntax> specifier,
                                   Optional<ParsedAttributeListSyntax> attrs) {
  if (!attrs && !specifier)
    return std::move(ty);

  if (ty.isNull()) {
    SmallVector<ParsedSyntax, 2> junk;
    if (specifier)
      junk.emplace_back(std::move(*specifier));
    if (attrs)
      junk.emplace_back(std::move(*attrs));
    return makeParsedResult(
        ParsedSyntaxRecorder::makeUnknownType(junk, *SyntaxContext),
        ty.getStatus());
  }

  return makeParsedResult(
      ParsedSyntaxRecorder::makeAttributedType(
          std::move(specifier), std::move(attrs), ty.get(), *SyntaxContext),
      ty.getStatus());
}

/// Parse layout constraint for 'where' clause in '@_specialize' attribute
/// and in SIL.
///
///   layout-constraint:
///     identifier
///     identifier '(' integer-literal ')'
///     identifier '(' integer-literal ',' integer-literal ')'
ParsedSyntaxResult<ParsedLayoutConstraintSyntax>
Parser::parseLayoutConstraintSyntax() {
  assert(Tok.is(tok::identifier));
  ParsedLayoutConstraintSyntaxBuilder builder(*SyntaxContext);

  builder.useName(consumeTokenSyntax(tok::identifier));

  if (!Tok.isFollowingLParen())
    return makeParsedResult(builder.build());

  auto lParenLoc = Tok.getLoc();
  builder.useLeftParen(consumeTokenSyntax(tok::l_paren));

  auto parseTrivialConstraintBody = [&]() -> bool {
    int value;

    if (!Tok.is(tok::integer_literal) ||
        Tok.getText().getAsInteger(10, value) || value < 0) {
      diagnose(Tok, diag::layout_size_should_be_positive);
      return true;
    }
    builder.useSize(consumeTokenSyntax(tok::integer_literal));

    if (Tok.is(tok::comma)) {
      builder.useComma(consumeTokenSyntax(tok::comma));

      if (!Tok.is(tok::integer_literal) ||
          Tok.getText().getAsInteger(10, value) || value < 0) {
        diagnose(Tok, diag::layout_alignment_should_be_positive);
        return true;
      }
      builder.useAlignment(consumeTokenSyntax(tok::integer_literal));
    }
    return false;
  };

  auto hasError = parseTrivialConstraintBody();
  if (hasError)
    ignoreUntil(tok::r_paren);
  auto rParen = parseMatchingTokenSyntax(
      tok::r_paren, diag::expected_rparen_layout_constraint, lParenLoc,
      /*silenceDiag=*/hasError);
  if (!rParen.isNull())
    builder.useRightParen(rParen.get());

  return makeParsedResult(builder.build());
}

/// parseTypeSimple
///   type-simple:
///     type-identifier
///     type-tuple
///     type-composition-deprecated
///     'Any'
///     type-simple '.Type'
///     type-simple '.Protocol'
///     type-simple '?'
///     type-simple '!'
///     type-collection
///     type-array
ParsedSyntaxResult<ParsedTypeSyntax>
Parser::parseTypeSimple(Diag<> MessageID, bool HandleCodeCompletion) {
  if (Tok.is(tok::kw_inout) ||
      (Tok.is(tok::identifier) && (Tok.getRawText().equals("__shared") ||
                                   Tok.getRawText().equals("__owned")))) {
    // Type specifier should already be parsed before here. This only happens
    // for construct like 'P1 & inout P2'.
    diagnose(Tok.getLoc(), diag::attr_only_on_parameters, Tok.getRawText());
    ignoreToken();
  }

  auto TypeLoc = leadingTriviaLoc();

  ParsedSyntaxResult<ParsedTypeSyntax> Result;
  switch (Tok.getKind()) {
  case tok::kw_Self:
  case tok::kw_Any:
  case tok::identifier:
    Result = parseTypeIdentifier();
    break;
  case tok::l_paren:
    Result = parseTypeTupleBody();
    break;
  case tok::code_complete: {
    if (!HandleCodeCompletion)
      break;
    ParsedTypeSyntax ty = ParsedSyntaxRecorder::makeCodeCompletionType(
        None, None, consumeTokenSyntax(), *SyntaxContext);
    return makeParsedCodeCompletion(std::move(ty));
  }
  case tok::l_square:
    Result = parseTypeCollection();
    break;
  case tok::kw_protocol:
    if (startsWithLess(peekToken())) {
      Result = parseOldStyleProtocolComposition();
      break;
    }
    LLVM_FALLTHROUGH;
  default:
    {
      auto diag = diagnose(Tok, MessageID);
      // If the next token is closing or separating, the type was likely forgotten
      if (Tok.isAny(tok::r_paren, tok::r_brace, tok::r_square, tok::arrow,
                    tok::equal, tok::comma, tok::semi))
        diag.fixItInsert(getEndOfPreviousLoc(), " <#type#>");
    }

    if (Tok.isKeyword() && !Tok.isAtStartOfLine()) {
      auto token = consumeTokenSyntax();
      ParsedTypeSyntax ty = ParsedSyntaxRecorder::makeUnknownType(
          {&token, 1}, *SyntaxContext);
      // Return success result because we recovered.
      return makeParsedResult(std::move(ty));
    }

    checkForInputIncomplete();
    return makeParsedError<ParsedTypeSyntax>();
  }

  // '.Type', '.Protocol', '?', '!', and '[]' still leave us with type-simple.
  while (Result.isSuccess()) {
    if ((Tok.is(tok::period) || Tok.is(tok::period_prefix)) &&
        (peekToken().isContextualKeyword("Type") ||
         peekToken().isContextualKeyword("Protocol"))) {
      Result = parseMetatypeType(Result.get());
      continue;
    }

    if (!Tok.isAtStartOfLine()) {
      if (isOptionalToken(Tok)) {
        Result = parseOptionalType(Result.get());
        continue;
      }
      if (isImplicitlyUnwrappedOptionalToken(Tok)) {
        Result = parseImplicitlyUnwrappedOptionalType(Result.get());
        continue;
      }
      // Parse legacy array types for migration.
      if (Tok.is(tok::l_square)) {
        Result = parseTypeArray(Result.get(), TypeLoc);
        continue;
      }
    }
    break;
  }

  return Result;
}

ParsedSyntaxResult<ParsedTypeSyntax> Parser::parseSILBoxTypeSyntax(
    Optional<ParsedGenericParameterClauseListSyntax> generics) {
  ParsedSILBoxTypeSyntaxBuilder builder(*SyntaxContext);
  ParserStatus status;

  if (generics)
    builder.useGenericParameterClauses(std::move(*generics));

  // Parse '{'.
  builder.useLeftBrace(consumeTokenSyntax(tok::l_brace));

  // Parse comma separated field list.
  if (!Tok.is(tok::r_brace)) {
    bool hasNext = true;
    do {
      ParsedSILBoxTypeFieldSyntaxBuilder fieldBuilder(*SyntaxContext);

      // Parse 'let' or 'var'.
      if (!Tok.isAny(tok::kw_var, tok::kw_let)) {
        diagnose(Tok, diag::sil_box_expected_var_or_let);
        break;
      }
      fieldBuilder.useSpecifier(consumeTokenSyntax());

      // Parse the type.
      auto ty = parseTypeSyntax();
      status |= ty.getStatus();
      if (!ty.isNull())
        fieldBuilder.useType(ty.get());
      else
        fieldBuilder.useType(
            ParsedSyntaxRecorder::makeUnknownType({}, *SyntaxContext));

      // Parse ','.
      hasNext = (status.isSuccess() && Tok.is(tok::comma));
      if (hasNext)
        fieldBuilder.useTrailingComma(consumeTokenSyntax());

      builder.addFieldsMember(fieldBuilder.build());
    } while (hasNext);
  }

  // Parse '}'.
  if (!Tok.is(tok::r_brace)) {
    diagnose(Tok, diag::sil_box_expected_r_brace);
    return makeParsedError(builder.build());
  }
  builder.useRightBrace(consumeTokenSyntax(tok::r_brace));

  // Parse the generic argument.
  if (startsWithLess(Tok)) {
    auto genericArgs = parseGenericArgumentClauseSyntax();
    status |= genericArgs.getStatus();
    if (!genericArgs.isNull())
      builder.useGenericArgumentClause(genericArgs.get());
  }

  return makeParsedResult(builder.build());
}

/// parseType
///   type:
///     attribute-list type-composition
///     attribute-list type-function
///     attribute-list sil-generic-function-type
///     sil-box-type
///
///   type-function:
///     '(' tuple-type-element-list ')' 'throws'? '->' type
///
///   sil-generic-function-type:
///     generic-parameter-clause-list type-function
ParsedSyntaxResult<ParsedTypeSyntax>
Parser::parseTypeSyntax(Diag<> MessageID, bool HandleCodeCompletion,
                        bool IsSILFuncDecl) {
  ParserStatus status;

  // Parse attributes.
  Optional<ParsedTokenSyntax> specifier;
  Optional<ParsedAttributeListSyntax> attrs;
  if (Tok.isAny(tok::at_sign, tok::kw_inout) ||
      (Tok.is(tok::identifier) && (Tok.getRawText().equals("__shared") ||
                                   Tok.getRawText().equals("__owned"))))
    status |= parseTypeAttributeListSyntax(specifier, attrs);

  // Parse generic parameters in SIL mode.
  Optional<ParsedGenericParameterClauseListSyntax> genericParams;
  SourceLoc genericParamsLoc = Tok.getLoc();
  if (isInSILMode())
    (void)parseSILGenericParamsSyntax(genericParams);

  // In SIL mode, parse box types { ... }.
  if (isInSILMode() && Tok.is(tok::l_brace)) {
    auto ty = parseSILBoxTypeSyntax(std::move(genericParams));
    return applyAttributeToTypeSyntax(std::move(ty), std::move(specifier),
                                      std::move(attrs));
  }

  auto startLoc = Tok.getLoc();
  // Parse the type.
  auto ty = parseTypeSimpleOrComposition(MessageID, HandleCodeCompletion);
  status |= ty.getStatus();
  auto endLoc = PreviousLoc;

  // Don't consume 'throws', if the next token is not '->', so we can emit a
  // more useful diagnostic when parsing a function decl.
  bool canBeFunctionTy =
      Tok.is(tok::arrow) ||
      (Tok.isAny(tok::kw_throws, tok::kw_rethrows, tok::kw_throw) &&
       peekToken().is(tok::arrow));

  // If the first type has an error, or this is not a function type, return the
  // first result.
  if (ty.isNull() || !canBeFunctionTy) {
    // Diagnose generic parameter for non-function types.
    if (!genericParams && !specifier && !attrs)
      return ty;

    if (genericParams) {
      SmallVector<ParsedSyntax, 2> junk;
      diagnose(genericParamsLoc, diag::generic_non_function);
      junk.push_back(std::move(*genericParams));
      if (!ty.isNull())
        junk.emplace_back(ty.get());
      ty = makeParsedResult(
          ParsedSyntaxRecorder::makeUnknownType(junk, *SyntaxContext),
          status);
    }

    return applyAttributeToTypeSyntax(std::move(ty), std::move(specifier),
                                      std::move(attrs));
  }

  // Parse a throws specifier.
  Optional<ParsedTokenSyntax> throws;
  if (Tok.isAny(tok::kw_throws, tok::kw_rethrows, tok::kw_throw) &&
      peekToken().is(tok::arrow)) {
    if (Tok.isNot(tok::kw_throws)) {
      // 'rethrows' is only allowed on function declarations for now.
      // 'throw' is probably a typo for 'throws'.
      Diag<> DiagID = Tok.is(tok::kw_rethrows) ? diag::rethrowing_function_type
                                               : diag::throw_in_function_type;
      diagnose(Tok.getLoc(), DiagID).fixItReplace(Tok.getLoc(), "throws");
      ignoreToken();
    } else {
      throws = consumeTokenSyntax();
    }
  }

  auto arrowLoc = Tok.getLoc();
  auto arrow = consumeTokenSyntax(tok::arrow);
  if (Tok.is(tok::kw_throws)) {
    Diag<> DiagID = diag::throws_in_wrong_position;
    diagnose(Tok.getLoc(), DiagID)
        .fixItInsert(arrowLoc, "throws ")
        .fixItRemove(Tok.getLoc());
    ignoreToken();
  }

  auto input = ty.get();
  auto result = parseTypeSyntax(diag::expected_type_function_result);
  status |= result.getStatus();

  ParsedFunctionTypeSyntaxBuilder builder(*SyntaxContext);
  if (auto tuple = input.getAs<ParsedTupleTypeSyntax>()) {
    assert(tuple->getRaw().isDeferredLayout());
    builder.useLeftParen(tuple->getDeferredLeftParen());
    builder.useArguments(tuple->getDeferredElements());
    builder.useRightParen(tuple->getDeferredRightParen());
  } else {
    builder.addArgumentsMember(ParsedSyntaxRecorder::makeTupleTypeElement(
        std::move(input), /*TrailingComma=*/None, *SyntaxContext));

    // Diagnose only if the result type is successfully parsed, to reduce the
    // noisy diagnostics.
    if (result.isSuccess()) {
      auto charRange = Lexer::getCharSourceRangeFromSourceRange(
          SourceMgr, {startLoc, endLoc});
      auto diag = diagnose(startLoc, diag::function_type_no_parens);
      if (SourceMgr.extractText(charRange) == "Void") {
        diag.fixItReplace(startLoc, "()");
      } else {
        diag.highlight(SourceRange(startLoc, endLoc));
        diag.fixItInsert(startLoc, "(");
        diag.fixItInsertAfter(endLoc, ")");
      }
    }
  }

  if (throws)
    builder.useThrowsOrRethrowsKeyword(std::move(*throws));
  builder.useArrow(std::move(arrow));
  if (!result.isNull())
    builder.useReturnType(result.get());
  else
    builder.useReturnType(
        ParsedSyntaxRecorder::makeUnknownType({}, *SyntaxContext));

  ParsedFunctionTypeSyntax funcTy = builder.build();

  // Apply generic parameters if exists in SIL mode.
  if (genericParams) {
    auto silTy = ParsedSyntaxRecorder::makeSILFunctionType(
        std::move(*genericParams), std::move(funcTy), *SyntaxContext);
    return applyAttributeToTypeSyntax(
        makeParsedResult(std::move(silTy), status), std::move(specifier),
        std::move(attrs));
  }

  return applyAttributeToTypeSyntax(makeParsedResult(std::move(funcTy), status),
                                    std::move(specifier), std::move(attrs));
}

ParsedSyntaxResult<ParsedTypeSyntax> Parser::parseTypeSyntax() {
  return parseTypeSyntax(diag::expected_type);
}

ParserResult<TypeRepr> Parser::parseType(Diag<> MessageID,
                                         bool HandleCodeCompletion,
                                         bool IsSILFuncDecl) {
  auto leadingLoc = leadingTriviaLoc();
  auto result = parseTypeSyntax(MessageID, HandleCodeCompletion, IsSILFuncDecl);
  auto status = result.getStatus();
  if (result.isNull())
    return status;

  SyntaxContext->addSyntax(result.get());
  auto syntax = SyntaxContext->topNode<TypeSyntax>();
  auto tyR = Generator.generate(syntax, leadingLoc, IsSILFuncDecl);
  if (!tyR)
    status.setIsParseError();
  return makeParserResult(status, tyR);
}

ParserResult<TypeRepr> Parser::parseType() {
  return parseType(diag::expected_type);
}


ParserResult<TypeRepr> Parser::parseDeclResultType(Diag<> MessageID) {
  if (Tok.is(tok::code_complete)) {
    if (CodeCompletion)
      CodeCompletion->completeTypeDeclResultBeginning();
    consumeToken(tok::code_complete);
    return makeParserCodeCompletionStatus();
  }

  auto result = parseType(MessageID);

  if (!result.isParseError() && Tok.is(tok::r_square)) {
    auto diag = diagnose(Tok, diag::extra_rbracket);
    diag.fixItInsert(result.get()->getStartLoc(), getTokenText(tok::l_square));
    consumeToken();
    return makeParserErrorResult(new (Context)
                                     ErrorTypeRepr(getTypeErrorLoc()));
  } else if (!result.isParseError() && Tok.is(tok::colon)) {
    auto colonTok = consumeToken();
    auto secondType = parseType(diag::expected_dictionary_value_type);

    auto diag = diagnose(colonTok, diag::extra_colon);
    diag.fixItInsert(result.get()->getStartLoc(), getTokenText(tok::l_square));
    if (!secondType.isParseError()) {
      if (Tok.is(tok::r_square)) {
        consumeToken();
      } else {
        diag.fixItInsertAfter(secondType.get()->getEndLoc(), getTokenText(tok::r_square));
      }
    }
    return makeParserErrorResult(new (Context)
                                     ErrorTypeRepr(getTypeErrorLoc()));
  }
  return result;
}

SourceLoc Parser::getTypeErrorLoc() const {
  // Use the same location as a missing close brace, etc.
  return getErrorOrMissingLoc();
}

ParsedSyntaxResult<ParsedGenericArgumentClauseSyntax>
Parser::parseGenericArgumentClauseSyntax() {
  assert(startsWithLess(Tok) && "Generic parameter list must start with '<'");
  auto LAngleLoc = Tok.getLoc();
  ParsedGenericArgumentClauseSyntaxBuilder builder(*SyntaxContext);
  ParserStatus status;

  // Parse '<'.
  builder.useLeftAngleBracket(consumeStartingLessSyntax());

  bool hasNext = true;
  do {
    // Parse argument type.
    auto ty = parseTypeSyntax(diag::expected_type);
    status |= ty.getStatus();
    if (ty.isNull())
      break;
    ParsedGenericArgumentSyntaxBuilder argBuilder(*SyntaxContext);
    argBuilder.useArgumentType(ty.get());

    // Parse trailing comma: ','.
    if (Tok.is(tok::comma)) {
      argBuilder.useTrailingComma(consumeTokenSyntax());
    } else {
      hasNext = false;
    }
    builder.addArgumentsMember(argBuilder.build());
  } while (hasNext);

  // Parse '>'.
  if (startsWithGreater(Tok)) {
    builder.useRightAngleBracket(consumeStartingGreaterSyntax());
  } else {
    if (status.isSuccess()) {
      diagnose(Tok, diag::expected_rangle_generic_arg_list);
      diagnose(LAngleLoc, diag::opening_angle);
    }
    checkForInputIncomplete();
    status.setIsParseError();
    if (ignoreUntilGreaterInTypeList())
      builder.useRightAngleBracket(consumeStartingGreaterSyntax());
  }

  return makeParsedResult(builder.build(), status);
}

ParserStatus Parser::parseGenericArguments(SmallVectorImpl<TypeRepr *> &ArgsAST,
                                           SourceLoc &LAngleLoc,
                                           SourceLoc &RAngleLoc) {
  auto leadingLoc = leadingTriviaLoc();
  auto ParsedClauseResult = parseGenericArgumentClauseSyntax();
  if (ParsedClauseResult.isNull())
    return ParsedClauseResult.getStatus();

  SyntaxContext->addSyntax(ParsedClauseResult.get());
  if (ParsedClauseResult.isError())
    return ParsedClauseResult.getStatus();

  auto Clause = SyntaxContext->topNode<GenericArgumentClauseSyntax>();
  Generator.generate(Clause, leadingLoc, LAngleLoc, RAngleLoc, ArgsAST);
  return makeParserSuccess();
}

/// SWIFT_ENABLE_TENSORFLOW
bool Parser::canParseTypeQualifierForDeclName() {
  BacktrackingScope backtrack(*this);

  // First, parse a single type identifier component.
  if (!Tok.isAny(tok::identifier, tok::kw_Self, tok::kw_Any))
    return false;
  consumeToken();

  if (startsWithLess(Tok)) {
    if (!canParseGenericArguments())
      return false;
  }

  // If the next token is a period or starts with a period, then this can be
  // parsed as a type qualifier.
  return startsWithSymbol(Tok, '.');
}

/// parseTypeIdentifier
///
///   type-identifier:
///     identifier generic-args? ('.' identifier generic-args?)*
///
// SWIFT_ENABLE_TENSORFLOW: Added `isParsingQualifiedDeclName` flag.
ParsedSyntaxResult<ParsedTypeSyntax> Parser::parseTypeIdentifier(bool isParsingQualifiedDeclName) {
  if (isParsingQualifiedDeclName && !canParseTypeQualifierForDeclName())
    return makeParsedError<ParsedTypeSyntax>();

  // SWIFT_ENABLE_TENSORFLOW: Condition body intentionally not indented, to
  // reduce merge conflicts.
  if (!isParsingQualifiedDeclName || Tok.isNotAnyOperator()) {
  if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_Self)) {
    // is this the 'Any' type
    if (Tok.is(tok::kw_Any))
      return parseAnyType();

    if (Tok.is(tok::code_complete)) {
      auto CCTok = consumeTokenSyntax(tok::code_complete);
      auto ty = ParsedSyntaxRecorder::makeCodeCompletionType(
          None, None, std::move(CCTok), *SyntaxContext);
      return makeParsedCodeCompletion(std::move(ty));
    }

    diagnose(Tok, diag::expected_identifier_for_type);

    // If there is a keyword at the start of a new line, we won't want to
    // skip it as a recovery but rather keep it.
    if (Tok.isKeyword() && !Tok.isAtStartOfLine()) {
      auto kwTok = consumeTokenSyntax();
      ParsedTypeSyntax ty =
          ParsedSyntaxRecorder::makeUnknownType({&kwTok, 1}, *SyntaxContext);
      return makeParsedError(std::move(ty));
    }

    return makeParsedError<ParsedTypeSyntax>();
  }
  }

  SmallVector<ParsedSyntax, 0> Junk;

  auto parseComponent =
      [&](Optional<ParsedTokenSyntax> &Identifier,
          Optional<ParsedGenericArgumentClauseSyntax> &GenericArgs) {
        if (Tok.is(tok::kw_Self)) {
          Identifier = consumeIdentifierSyntax();
        } else {
          // FIXME: specialize diagnostic for 'Type': type cannot start with
          // 'metatype'
          // FIXME: offer a fixit: 'self' -> 'Self'
          Identifier =
              parseIdentifierSyntax(diag::expected_identifier_in_dotted_type);
        }

        if (!Identifier)
          return makeParserError();

        if (!startsWithLess(Tok))
          return makeParserSuccess();

        SmallVector<TypeRepr *, 4> GenericArgsAST;
        SourceLoc LAngleLoc, RAngleLoc;
        auto GenericArgsResult = parseGenericArgumentClauseSyntax();
        if (!GenericArgsResult.isNull())
          GenericArgs = GenericArgsResult.get();
        return GenericArgsResult.getStatus();
      };

  ParsedSyntaxResult<ParsedTypeSyntax> result;

  // Parse the base identifier.
  result = [&]() {
    Optional<ParsedTokenSyntax> identifier;
    Optional<ParsedGenericArgumentClauseSyntax> genericArgs;
    auto status = parseComponent(identifier, genericArgs);
    assert(identifier);
    return makeParsedResult(
        ParsedSyntaxRecorder::makeSimpleTypeIdentifier(
            std::move(*identifier), std::move(genericArgs), *SyntaxContext),
        status);
  }();

  // Parse member identifiers.
  while (result.isSuccess() && Tok.isAny(tok::period, tok::period_prefix)) {
    if (peekToken().isContextualKeyword("Type") ||
        peekToken().isContextualKeyword("Protocol"))
      break;

    if (isParsingQualifiedDeclName) {
      // If we're parsing a qualified decl name, break out before parsing the
      // last period.

      BacktrackingScope backtrack(*this);

      if (Tok.is(tok::period) || Tok.is(tok::period_prefix))
        consumeToken();
      else if (startsWithSymbol(Tok, '.'))
        consumeStartingCharacterOfCurrentToken(tok::period);

      if (!canParseTypeQualifierForDeclName())
        break;
    }

    // Parse '.'.
    auto period = consumeTokenSyntax();

    if (isParsingQualifiedDeclName && Tok.isAnyOperator()) {
      // If an operator is encountered, break and do not backtrack later.
      break;
    }

    // Parse component;
    Optional<ParsedTokenSyntax> identifier;
    Optional<ParsedGenericArgumentClauseSyntax> genericArgs;
    auto status = parseComponent(identifier, genericArgs);
    if (identifier) {
      ParsedMemberTypeIdentifierSyntaxBuilder builder(*SyntaxContext);
      builder.useBaseType(result.get());
      builder.usePeriod(std::move(period));
      builder.useName(std::move(*identifier));
      if (genericArgs)
        builder.useGenericArgumentClause(std::move(*genericArgs));
      result = makeParsedResult(builder.build(), status);
      continue;
    }

    assert(!genericArgs);

    if (Tok.is(tok::code_complete)) {
      auto ty = ParsedSyntaxRecorder::makeCodeCompletionType(
          result.get(), std::move(period), consumeTokenSyntax(),
          *SyntaxContext);
      return makeParsedCodeCompletion(std::move(ty));
    }

    ParsedSyntax parts[] = {result.get(), std::move(period)};
    return makeParsedResult(
        ParsedSyntaxRecorder::makeUnknownType({parts, 2}, *SyntaxContext),
        status);
  }

  if (result.isSuccess() && Tok.is(tok::code_complete) &&
      !Tok.isAtStartOfLine()) {
    auto ty = ParsedSyntaxRecorder::makeCodeCompletionType(
        result.get(), None, consumeTokenSyntax(), *SyntaxContext);
    return makeParsedCodeCompletion(std::move(ty));
  }

  // Don't propagate malformed type as valid type.
  if (!result.isSuccess()) {
    auto ty = result.get();
    return makeParsedResult(
        ParsedSyntaxRecorder::makeUnknownType({&ty, 1}, *SyntaxContext),
        result.getStatus());
  }

  return result;
}

/// parseTypeSimpleOrComposition
///
///   type-composition:
///     'some'? type-simple
///     type-composition '&' type-simple
ParsedSyntaxResult<ParsedTypeSyntax>
Parser::parseTypeSimpleOrComposition(Diag<> MessageID,
                                     bool HandleCodeCompletion) {
  // Check for the opaque modifier.
  // This is only semantically allowed in certain contexts, but we parse it
  // generally for diagnostics and recovery.
  Optional<ParsedTokenSyntax> FirstSome;
  if (Tok.is(tok::identifier) && Tok.getRawText() == "some") {
    // Treat some as a keyword.
    TokReceiver->registerTokenKindChange(Tok.getLoc(), tok::contextual_keyword);
    FirstSome = consumeTokenSyntax();
  }

  auto ApplySome = [this](ParsedTypeSyntax Type,
                          Optional<ParsedTokenSyntax> Some) {
    return Some ? ParsedSyntaxRecorder::makeSomeType(
                      std::move(*Some), std::move(Type), *SyntaxContext)
                : std::move(Type);
  };

  // Parse the first type
  auto FirstTypeResult = parseTypeSimple(MessageID, HandleCodeCompletion);

  if (FirstTypeResult.isError())
    return FirstTypeResult;

  auto FirstType = FirstTypeResult.get();

  if (!Tok.isContextualPunctuator("&"))
    return makeParsedResult(
        ApplySome(std::move(FirstType), std::move(FirstSome)));

  SmallVector<ParsedCompositionTypeElementSyntax, 4> Elements;

  Optional<ParsedTokenSyntax> Ampersand = consumeTokenSyntax();
  auto FirstElement = ParsedSyntaxRecorder::makeCompositionTypeElement(
      std::move(FirstType), std::move(*Ampersand), *SyntaxContext);
  Elements.push_back(std::move(FirstElement));

  ParserStatus Status;

  do {
    // Diagnose invalid `some` after an ampersand.
    Optional<ParsedTokenSyntax> NextSome;
    if (Tok.is(tok::identifier) && Tok.getRawText() == "some") {
      auto NextSomeLoc = Tok.getLoc();
      NextSome = consumeTokenSyntax();
      // TODO: Fixit to move to beginning of composition.
      diagnose(NextSomeLoc, diag::opaque_mid_composition);
    }

    auto NextTypeResult = parseTypeSimple(diag::expected_identifier_for_type,
                                          HandleCodeCompletion);

    if (!NextTypeResult.isSuccess()) {
      Status |= NextTypeResult.getStatus();
      if (NextTypeResult.isNull())
        break;

      SmallVector<ParsedSyntax, 0> nodes;
      if (FirstSome)
        nodes.push_back(std::move(*FirstSome));
      std::move(Elements.begin(), Elements.end(), std::back_inserter(nodes));
      if (NextSome)
        nodes.push_back(std::move(*NextSome));
      nodes.push_back(NextTypeResult.get());

      auto ty = ParsedSyntaxRecorder::makeUnknownType(nodes, *SyntaxContext);
      return makeParsedResult(std::move(ty), Status);
    }

    auto NextType = ApplySome(NextTypeResult.get(), std::move(NextSome));
    Ampersand = Tok.isContextualPunctuator("&")
        ? consumeTokenSyntax()
        : llvm::Optional<ParsedTokenSyntax>();
    auto NextElement = ParsedSyntaxRecorder::makeCompositionTypeElement(
        std::move(NextType), std::move(Ampersand), *SyntaxContext);
    Elements.push_back(std::move(NextElement));
  } while (Ampersand);

  auto ElementList = ParsedSyntaxRecorder::makeCompositionTypeElementList(
      Elements, *SyntaxContext);
  auto Composition = ParsedSyntaxRecorder::makeCompositionType(
      std::move(ElementList), *SyntaxContext);
  return makeParsedResult(
      ApplySome(std::move(Composition), std::move(FirstSome)), Status);
}

ParserResult<TypeRepr> Parser::parseAnyTypeAST() {
  auto AnyLoc = leadingTriviaLoc();
  auto ParsedAny = parseAnyType().get();
  SyntaxContext->addSyntax(std::move(ParsedAny));
  auto Any = SyntaxContext->topNode<SimpleTypeIdentifierSyntax>();
  return makeParserResult(Generator.generate(Any, AnyLoc));
}

ParsedSyntaxResult<ParsedTypeSyntax> Parser::parseAnyType() {
  auto Any = consumeTokenSyntax(tok::kw_Any);
  auto Type = ParsedSyntaxRecorder::makeSimpleTypeIdentifier(
      std::move(Any), llvm::None, *SyntaxContext);
  return makeParsedResult(std::move(Type));
}

/// parseOldStyleProtocolComposition
///   type-composition-deprecated:
///     'protocol' '<' '>'
///     'protocol' '<' type-composition-list-deprecated '>'
///
///   type-composition-list-deprecated:
///     type-identifier
///     type-composition-list-deprecated ',' type-identifier
ParsedSyntaxResult<ParsedTypeSyntax>
Parser::parseOldStyleProtocolComposition() {
  // Defer all nodes so that we can de-structure the composed types in case we
  // need to emit a diagnostic (below).
  DeferringContextRAII Deferring(*SyntaxContext);

  SmallVector<ParsedSyntax, 0> Junk;

  auto ProtocolLoc = Tok.getLoc();
  auto Protocol = consumeTokenSyntax();
  auto LAngleLoc = Tok.getLoc();
  auto LAngle = consumeStartingLessSyntax();

  Junk.push_back(Protocol.copyDeferred());
  Junk.push_back(LAngle.copyDeferred());

  // Parse the type-composition-list.
  ParserStatus Status;
  SmallVector<ParsedTypeSyntax, 4> Protocols;
  Optional<ParsedTokenSyntax> Comma;
  bool IsEmpty = startsWithGreater(Tok);
  if (!IsEmpty) {
    do {
      bool IsAny = Tok.getKind() == tok::kw_Any;
      auto TypeResult = parseTypeIdentifier();
      Status |= TypeResult.getStatus();
      if (!TypeResult.isNull()) {
        auto Type = TypeResult.get();
        Junk.push_back(Type.copyDeferred());
        if (!IsAny)
          Protocols.push_back(std::move(Type));
      }
      Comma = consumeTokenSyntaxIf(tok::comma);
      if (Comma)
        Junk.push_back(Comma->copyDeferred());
    } while (Comma);
  }

  // Check for the terminating '>'.
  Optional<SourceLoc> RAngleLoc;
  if (startsWithGreater(Tok)) {
    RAngleLoc = Tok.getLoc();
    auto RAngle = consumeStartingGreaterSyntax();
    Junk.push_back(RAngle.copyDeferred());
  } else {
    if (Status.isSuccess()) {
      diagnose(Tok, diag::expected_rangle_protocol);
      diagnose(LAngleLoc, diag::opening_angle);
      Status.setIsParseError();
    }

    SmallVector<ParsedSyntax, 4> RAngleJunk;
    // Skip until we hit the '>'.
    skipUntilGreaterInTypeListSyntax(RAngleJunk, /*protocolComposition=*/true);
    for (auto &&Piece : RAngleJunk)
      Junk.push_back(Piece.copyDeferred());
  }

  if (Status.isSuccess()) {
    SmallString<32> replacement;
    if (Protocols.empty()) {
      replacement = "Any";
    } else {
      auto extractText = [&](ParsedTypeSyntax &Type) -> StringRef {
        auto SourceRange = Type.getRaw().getDeferredRange();
        return SourceMgr.extractText(SourceRange).trim();
      };
      auto Begin = Protocols.begin();
      replacement += extractText(*Begin);
      while (++Begin != Protocols.end()) {
        replacement += " & ";
        replacement += extractText(*Begin);
      }
    }

    if (Protocols.size() > 1) {
      // Need parenthesis if the next token looks like postfix TypeRepr.
      // i.e. '?', '!', '.Type', '.Protocol'
      bool needParen = false;
      needParen |= !Tok.isAtStartOfLine() &&
          (isOptionalToken(Tok) || isImplicitlyUnwrappedOptionalToken(Tok));
      needParen |= Tok.isAny(tok::period, tok::period_prefix);
      if (needParen) {
        replacement.insert(replacement.begin(), '(');
        replacement += ")";
      }
    }

    // Copy split token after '>' to the replacement string.
    // FIXME: lexer should smartly separate '>' and trailing contents like '?'.
    StringRef TrailingContent = L->getTokenAt(*RAngleLoc).getRange().str().
      substr(1);
    if (!TrailingContent.empty())
      replacement += TrailingContent;

    // Replace 'protocol<T1, T2>' with 'T1 & T2'
    diagnose(ProtocolLoc,
      IsEmpty              ? diag::deprecated_any_composition :
      Protocols.size() > 1 ? diag::deprecated_protocol_composition :
                             diag::deprecated_protocol_composition_single)
      .highlight({ProtocolLoc, *RAngleLoc})
      .fixItReplace({ProtocolLoc, *RAngleLoc}, replacement);
  }

  auto Unknown = ParsedSyntaxRecorder::makeUnknownType(Junk, *SyntaxContext);
  return makeParsedResult(std::move(Unknown));
}

/// parseTypeTupleBody
///   type-tuple:
///     '(' type-tuple-body? ')'
///   type-tuple-body:
///     type-tuple-element (',' type-tuple-element)* '...'?
///   type-tuple-element:
///     identifier? identifier ':' type
///     type
ParsedSyntaxResult<ParsedTypeSyntax> Parser::parseTypeTupleBody() {
  // Force the context to create deferred nodes, as we might need to
  // de-structure the tuple type to create a function type.
  DeferringContextRAII Deferring(*SyntaxContext);
  Parser::StructureMarkerRAII ParsingTypeTuple(*this, Tok);

  if (ParsingTypeTuple.isFailed())
    return makeParsedError<ParsedTypeSyntax>();

  ParsedTupleTypeSyntaxBuilder builder(*SyntaxContext);

  // Parse '('.
  auto LParenLoc = Tok.getLoc();
  builder.useLeftParen(consumeTokenSyntax(tok::l_paren));

  // Parse the elements.
  SmallVector<ParsedTupleTypeElementSyntax, 4> Elements;
  SmallVector<std::tuple<SourceLoc, SourceLoc, SourceLoc>, 4> ElementsLoc;
  SourceLoc FirstEllipsisLoc;
  auto Status = parseListSyntax(
      Elements, /*AllowEmpty=*/true, /*AllowSepAfterLast=*/false,
      [&] { return Tok.is(tok::r_paren); },
      [&](ParsedTupleTypeElementSyntaxBuilder &elemBuilder) {
        Optional<BacktrackingScope> Backtracking;

        // 'inout' here can be a obsoleted use of the marker in an argument
        // list, consume it in backtracking context so we can determine it's
        // really a deprecated use of it.
        SourceLoc InOutLoc;
        Optional<ParsedTokenSyntax> InOut;
        bool IsInOutObsoleted = false;
        if (Tok.is(tok::kw_inout)) {
          InOutLoc = Tok.getLoc();
          InOut = consumeTokenSyntax(tok::kw_inout);
          IsInOutObsoleted = true;
        }

        // If the label is "some", this could end up being an opaque type
        // description if there's `some <identifier>` without a following colon,
        // so we may need to backtrack as well.
        if (Tok.getText().equals("some"))
          Backtracking.emplace(*this);

        // 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.
        Optional<ParsedTokenSyntax> Name;
        Optional<ParsedTokenSyntax> SecondName;
        Optional<ParsedTokenSyntax> Colon;
        SourceLoc NameLoc;
        SourceLoc SecondNameLoc;
        if (Tok.canBeArgumentLabel() &&
            (peekToken().is(tok::colon) || peekToken().canBeArgumentLabel())) {
          // Consume a name.
          NameLoc = Tok.getLoc();
          Name = consumeArgumentLabelSyntax();

          // If there is a second name, consume it as well.
          if (Tok.canBeArgumentLabel()) {
            SecondNameLoc = Tok.getLoc();
            SecondName = consumeArgumentLabelSyntax();
          }

          // Consume the ':'.
          if ((Colon = consumeTokenSyntaxIf(tok::colon))) {
            // If we succeed, then we successfully parsed a label.
            if (Backtracking)
              Backtracking->cancelBacktrack();
            // Otherwise, if we can't backtrack to parse this as a type,
            // this is a syntax error.
          } else {
            if (!Backtracking)
              diagnose(Tok, diag::expected_parameter_colon);
            NameLoc = SourceLoc();
            SecondNameLoc = SourceLoc();
          }
        } else if (InOut) {
          // If we don't have labels, 'inout' is not a obsoleted use.
          IsInOutObsoleted = false;
        }

        if (!Backtracking || !Backtracking->willBacktrack()) {
          if (Name)
            elemBuilder.useName(std::move(*Name));
          if (SecondName)
            elemBuilder.useSecondName(std::move(*SecondName));
          if (Colon)
            elemBuilder.useColon(std::move(*Colon));
        } else if (Backtracking && Backtracking->willBacktrack()) {
          NameLoc = SourceLoc();
          SecondNameLoc = SourceLoc();
          Name.reset();
          SecondName.reset();
          assert(!Colon.hasValue());
        }
        Backtracking.reset();

        // Parse the type.
        auto TypeLoc = Tok.getLoc();
        auto ty = parseTypeSyntax(diag::expected_type);
        if (ty.isNull()) {
          ty = makeParsedResult(
              ParsedSyntaxRecorder::makeUnknownType({}, *SyntaxContext),
              ty.getStatus());
        }

        // Handle pre-parsed 'inout'.
        if (InOut) {
          if (IsInOutObsoleted) {
            elemBuilder.useInOut(std::move(*InOut));
            bool IsTypeAlreadyAttributed = false;
            if (!ty.isNull()) {
              if (auto AttributedType =
                      ty.getAs<ParsedAttributedTypeSyntax>()) {
                IsTypeAlreadyAttributed =
                    AttributedType->getDeferredSpecifier().hasValue();
                ty = makeParsedResult(std::move(*AttributedType),
                                      ty.getStatus());
              }
            }
            if (IsTypeAlreadyAttributed) {
              // If the parsed type is already attributed, suggest removing
              // `inout`.
              diagnose(Tok, diag::parameter_specifier_repeated)
                  .fixItRemove(InOutLoc);
            } else {
              diagnose(InOutLoc, diag::parameter_specifier_as_attr_disallowed,
                       "inout")
                  .fixItRemove(InOutLoc)
                  .fixItInsert(TypeLoc, "inout ");
            }
          } else {
            // Apply 'inout' to the parsed type.
            ParsedAttributedTypeSyntaxBuilder builder(*SyntaxContext);
            ty = applyAttributeToTypeSyntax(std::move(ty), std::move(InOut),
                                            None);
            TypeLoc = InOutLoc;
            InOutLoc = SourceLoc();
            InOut.reset();
          }
        }
        if (!ty.isNull())
          elemBuilder.useType(ty.get());
        ElementsLoc.emplace_back(NameLoc, SecondNameLoc, TypeLoc);
        if (ty.isError())
          return ty.getStatus();

        // Parse '...'.
        if (Tok.isEllipsis()) {
          auto ElementEllipsisLoc = Tok.getLoc();
          Tok.setKind(tok::ellipsis);
          elemBuilder.useEllipsis(consumeTokenSyntax(tok::ellipsis));
          if (!FirstEllipsisLoc.isValid()) {
            FirstEllipsisLoc = ElementEllipsisLoc;
          } else {
            diagnose(ElementEllipsisLoc, diag::multiple_ellipsis_in_tuple)
                .highlight(FirstEllipsisLoc)
                .fixItRemove(ElementEllipsisLoc);
          }
        }

        // Parse the initializer ('=' expr).
        if (Tok.is(tok::equal)) {
          ParsedInitializerClauseSyntaxBuilder initBuilder(*SyntaxContext);
          auto EqualLoc = Tok.getLoc();
          initBuilder.useEqual(consumeTokenSyntax(tok::equal));
          SyntaxParsingContext tmpCtxt(SyntaxContext);
          tmpCtxt.setTransparent();
          auto Init = parseExpr(diag::expected_init_value);
          auto InFlight = diagnose(EqualLoc, diag::tuple_type_init);
          if (Init.isNonNull())
            InFlight.fixItRemove(SourceRange(EqualLoc, PreviousLoc));
          if (auto expr = SyntaxContext->popIf<ParsedExprSyntax>())
            initBuilder.useValue(std::move(*expr));
          else
            initBuilder.useValue(
                ParsedSyntaxRecorder::makeUnknownExpr({}, *SyntaxContext));
          elemBuilder.useInitializer(initBuilder.build());
        }

        return makeParserSuccess();
      });

  // Parse ')'.
  auto RParen = parseMatchingTokenSyntax(
      tok::r_paren, diag::expected_rparen_tuple_type_list, LParenLoc,
      /*silenceDiag=*/Status.isError());
  Status |= RParen.getStatus();

  bool IsFunctionType = Tok.isAny(tok::arrow, tok::kw_throws, tok::kw_rethrows);

  auto GetNameText = [this](Optional<ParsedTokenSyntax> Name) {
    return !Name ? StringRef()
                 : SourceMgr.extractText(
                       Name->getRaw().getDeferredTokenRange(),
                       L->getBufferID());
  };

  if (!IsFunctionType) {
    for (unsigned i = 0; i < Elements.size(); i++) {
      // true tuples have labels
      auto &Element = Elements[i];
      SourceLoc NameLoc, SecondNameLoc, TypeLoc;
      std::tie(NameLoc, SecondNameLoc, TypeLoc) = ElementsLoc[i];
      // If there were two names, complain.
      if (NameLoc.isValid() && SecondNameLoc.isValid()) {
        auto Diag = diagnose(NameLoc, diag::tuple_type_multiple_labels);
        auto Name = Element.getDeferredName();
        auto NameText = SourceMgr.extractText(
            Name->getRaw().getDeferredTokenRange(),
            L->getBufferID());
        if (NameText == "_") {
          Diag.fixItRemoveChars(NameLoc, TypeLoc);
        } else {
          Diag.fixItRemove(SourceRange(
              Lexer::getLocForEndOfToken(SourceMgr, NameLoc), SecondNameLoc));
        }
      }
    }
  } else {
    for (unsigned i = 0; i < Elements.size(); i++) {
      // If there was a first name, complain; arguments in function types are
      // always unlabeled.
      auto &Element = Elements[i];
      SourceLoc NameLoc, SecondNameLoc, TypeLoc;
      std::tie(NameLoc, SecondNameLoc, TypeLoc) = ElementsLoc[i];
      if (NameLoc.isValid()) {
        auto NameText = GetNameText(Element.getDeferredName());
        if (NameText != "_") {
          auto NameIdentifier = Context.getIdentifier(NameText);
          auto Diag = diagnose(NameLoc, diag::function_type_argument_label,
                               NameIdentifier);
          auto SecondNameText = GetNameText(Element.getDeferredSecondName());
          if (SecondNameLoc.isInvalid())
            Diag.fixItInsert(NameLoc, "_ ");
          else if (SecondNameText == "_")
            Diag.fixItRemoveChars(NameLoc, TypeLoc);
          else
            Diag.fixItReplace(SourceRange(NameLoc), "_");
        }
      }
    }
  }
  for (auto &elem : Elements)
    builder.addElementsMember(std::move(elem));
  if (!RParen.isNull())
    builder.useRightParen(RParen.get());

  return makeParsedResult(builder.build(), Status);
}

/// parseTypeArray - Parse the type-array production, given that we
/// are looking at the initial l_square.  Note that this index
/// clause is actually the outermost (first-indexed) clause.
///
///   type-array:
///     type-simple
///     type-array '[' ']'
///     type-array '[' expr ']'
///
ParsedSyntaxResult<ParsedTypeSyntax>
Parser::parseTypeArray(ParsedTypeSyntax Base, SourceLoc BaseLoc) {
  assert(Tok.isFollowingLSquare());
  auto LSquareLoc = Tok.getLoc();
  ignoreToken(tok::l_square);

  // Ignore integer literal between '[' and ']'
  ignoreIf(tok::integer_literal);

  auto RSquareLoc = Tok.getLoc();
  auto RSquare = parseMatchingTokenSyntax(
      tok::r_square, diag::expected_rbracket_array_type, LSquareLoc);

  if (!RSquare.isNull()) {
    // If we parsed something valid, diagnose it with a fixit to rewrite it to
    // Swift syntax.
    diagnose(LSquareLoc, diag::new_array_syntax)
        .fixItInsert(BaseLoc, "[")
        .fixItRemoveChars(LSquareLoc, RSquareLoc);
  }

  ParsedArrayTypeSyntaxBuilder builder(*SyntaxContext);
  ParserStatus status;

  builder.useElementType(std::move(Base));
  if (!RSquare.isNull())
    builder.useRightSquareBracket(RSquare.get());
  status |= RSquare.getStatus();

  return makeParsedResult(builder.build(), status);
}

/// Parse a collection type.
///   type-simple:
///     '[' type ']'
///     '[' type ':' type ']'
ParsedSyntaxResult<ParsedTypeSyntax> Parser::parseTypeCollection() {
  ParserStatus Status;
  assert(Tok.is(tok::l_square));
  Parser::StructureMarkerRAII parsingCollection(*this, Tok);
  auto LSquareLoc = Tok.getLoc();
  auto LSquare = consumeTokenSyntax(tok::l_square);

  auto ElementTypeResult = parseTypeSyntax(diag::expected_element_type);
  Status |= ElementTypeResult.getStatus();
  auto ElementType = ElementTypeResult.getOrNull();
  if (!ElementType)
    ElementType = ParsedSyntaxRecorder::makeUnknownType({}, *SyntaxContext);

  Optional<ParsedTokenSyntax> Colon;
  Optional<ParsedTypeSyntax> ValueType;

  if (Tok.is(tok::colon)) {
    Colon = consumeTokenSyntax(tok::colon);
    auto ValueTypeResult =
        parseTypeSyntax(diag::expected_dictionary_value_type);
    ValueType = ValueTypeResult.getOrNull();
    if (!ValueType)
      ValueType = ParsedSyntaxRecorder::makeUnknownType({}, *SyntaxContext);
    Status |= ValueTypeResult.getStatus();
  }

  auto Diag = Colon ? diag::expected_rbracket_dictionary_type
                    : diag::expected_rbracket_array_type;

  auto RSquare = parseMatchingTokenSyntax(tok::r_square, Diag, LSquareLoc);
  Status |= RSquare.getStatus();

  if (Colon) {
    ParsedDictionaryTypeSyntaxBuilder builder(*SyntaxContext);
    builder.useLeftSquareBracket(std::move(LSquare));
    builder.useKeyType(std::move(*ElementType));
    builder.useColon(std::move(*Colon));
    builder.useValueType(std::move(*ValueType));
    if (!RSquare.isNull())
      builder.useRightSquareBracket(RSquare.get());
    return makeParsedResult(builder.build(), Status);
  } else {
    ParsedArrayTypeSyntaxBuilder builder(*SyntaxContext);
    builder.useLeftSquareBracket(std::move(LSquare));
    builder.useElementType(std::move(*ElementType));
    if (!RSquare.isNull())
      builder.useRightSquareBracket(RSquare.get());
    return makeParsedResult(builder.build(), Status);
  }
}

ParsedSyntaxResult<ParsedTypeSyntax>
Parser::parseMetatypeType(ParsedTypeSyntax Base) {
  auto Period = consumeTokenSyntax(); // tok::period or tok::period_prefix
  auto Keyword = consumeTokenSyntax(tok::identifier); // "Type" or "Protocol"
  auto MetatypeType = ParsedSyntaxRecorder::makeMetatypeType(
      std::move(Base), std::move(Period), std::move(Keyword), *SyntaxContext);
  return makeParsedResult(std::move(MetatypeType));
}

bool Parser::isOptionalToken(const Token &T) const {
  // A postfix '?' by itself is obviously optional.
  if (T.is(tok::question_postfix))
    return true;
  
  // A postfix or bound infix operator token that begins with '?' can be
  // optional too. We'll munch off the '?', so long as it is left-bound with
  // the type (i.e., parsed as a postfix or unspaced binary operator).
  if ((T.is(tok::oper_postfix) || T.is(tok::oper_binary_unspaced)) &&
      T.getText().startswith("?"))
    return true;
  return false;
}

bool Parser::isImplicitlyUnwrappedOptionalToken(const Token &T) const {
  // A postfix '!' by itself, or a '!' in SIL mode, is obviously implicitly
  // unwrapped optional.
  if (T.is(tok::exclaim_postfix) || T.is(tok::sil_exclamation))
    return true;
  // A postfix or bound infix operator token that begins with '!' can be
  // implicitly unwrapped optional too. We'll munch off the '!', so long as it
  // is left-bound with the type (i.e., parsed as a postfix or unspaced binary
  // operator).
  if ((T.is(tok::oper_postfix) || T.is(tok::oper_binary_unspaced)) &&
      T.getText().startswith("!"))
    return true;
  return false;
}

ParsedTokenSyntax Parser::consumeOptionalTokenSyntax() {
  assert(isOptionalToken(Tok) && "not a '?' token?!");
  return consumeStartingCharacterOfCurrentTokenSyntax(tok::question_postfix, 1);
}

SourceLoc Parser::consumeOptionalToken() {
  assert(isOptionalToken(Tok) && "not a '?' token?!");
  return consumeStartingCharacterOfCurrentToken(tok::question_postfix);
}

ParsedTokenSyntax Parser::consumeImplicitlyUnwrappedOptionalTokenSyntax() {
  assert(isImplicitlyUnwrappedOptionalToken(Tok) && "not a '!' token?!");
  // If the text of the token is just '!', grab the next token.
  return consumeStartingCharacterOfCurrentTokenSyntax(tok::exclaim_postfix, 1);
}

SourceLoc Parser::consumeImplicitlyUnwrappedOptionalToken() {
  assert(isImplicitlyUnwrappedOptionalToken(Tok) && "not a '!' token?!");
  // If the text of the token is just '!', grab the next token.
  return consumeStartingCharacterOfCurrentToken(tok::exclaim_postfix);
}

ParsedSyntaxResult<ParsedTypeSyntax>
Parser::parseOptionalType(ParsedTypeSyntax Base) {
  auto Question = consumeOptionalTokenSyntax();
  auto Optional = ParsedSyntaxRecorder::makeOptionalType(
      std::move(Base), std::move(Question), *SyntaxContext);
  return makeParsedResult(std::move(Optional));
}

ParsedSyntaxResult<ParsedTypeSyntax>
Parser::parseImplicitlyUnwrappedOptionalType(ParsedTypeSyntax Base) {
  auto Exclamation = consumeImplicitlyUnwrappedOptionalTokenSyntax();
  auto Unwrapped = ParsedSyntaxRecorder::makeImplicitlyUnwrappedOptionalType(
      std::move(Base), std::move(Exclamation), *SyntaxContext);
  return makeParsedResult(std::move(Unwrapped));
}

//===----------------------------------------------------------------------===//
// Speculative type list parsing
//===----------------------------------------------------------------------===//

static bool isGenericTypeDisambiguatingToken(Parser &P) {
  auto &tok = P.Tok;
  switch (tok.getKind()) {
  default:
    return false;
  case tok::r_paren:
  case tok::r_square:
  case tok::l_brace:
  case tok::r_brace:
  case tok::period:
  case tok::period_prefix:
  case tok::comma:
  case tok::semi:
  case tok::eof:
  case tok::code_complete:
  case tok::exclaim_postfix:
  case tok::question_postfix:
  case tok::colon:
    return true;

  case tok::oper_binary_spaced:
    if (tok.getText() == "&")
      return true;

    LLVM_FALLTHROUGH;
  case tok::oper_binary_unspaced:
  case tok::oper_postfix:
    // These might be '?' or '!' type modifiers.
    return P.isOptionalToken(tok) || P.isImplicitlyUnwrappedOptionalToken(tok);

  case tok::l_paren:
  case tok::l_square:
    // These only apply to the generic type if they don't start a new line.
    return !tok.isAtStartOfLine();
  }
}

bool Parser::canParseAsGenericArgumentList() {
  if (!Tok.isAnyOperator() || !Tok.getText().equals("<"))
    return false;

  BacktrackingScope backtrack(*this);

  if (canParseGenericArguments())
    // The generic-args case is ambiguous with an expression involving '<'
    // and '>' operators. The operator expression is favored unless a generic
    // argument list can be successfully parsed, and the closing bracket is
    // followed by one of dis-ambiguating tokens.
    return isGenericTypeDisambiguatingToken(*this);

  return false;
}

bool Parser::canParseGenericArguments() {
  // Parse the opening '<'.
  if (!startsWithLess(Tok))
    return false;
  consumeStartingLess();
  
  do {
    if (!canParseType())
      return false;
    // Parse the comma, if the list continues.
  } while (consumeIf(tok::comma));
  
  if (!startsWithGreater(Tok)) {
    return false;
  } else {
    consumeStartingGreater();
    return true;
  }
}

bool Parser::canParseType() {
  // Accept 'inout' at for better recovery.
  consumeIf(tok::kw_inout);

  switch (Tok.getKind()) {
  case tok::kw_Self:
  case tok::kw_Any:
      if (!canParseTypeIdentifier())
        return false;
      break;
  case tok::kw_protocol: // Deprecated composition syntax
  case tok::identifier:
    if (!canParseTypeIdentifierOrTypeComposition())
      return false;
    break;
  case tok::l_paren: {
    consumeToken();
    if (!canParseTypeTupleBody())
      return false;
    break;
  }
  case tok::at_sign: {
    consumeToken();
    if (!canParseTypeAttribute())
      return false;
    return canParseType();
  }
  case tok::l_square:
    consumeToken();
    if (!canParseType())
      return false;
    if (consumeIf(tok::colon)) {
      if (!canParseType())
        return false;
    }
    if (!consumeIf(tok::r_square))
      return false;
    break;


  default:
    return false;
  }

  // '.Type', '.Protocol', '?', and '!' still leave us with type-simple.
  while (true) {
    if ((Tok.is(tok::period) || Tok.is(tok::period_prefix)) &&
        (peekToken().isContextualKeyword("Type")
         || peekToken().isContextualKeyword("Protocol"))) {
      consumeToken();
      consumeToken(tok::identifier);
      continue;
    }
    if (isOptionalToken(Tok)) {
      consumeOptionalToken();
      continue;
    }
    if (isImplicitlyUnwrappedOptionalToken(Tok)) {
      consumeImplicitlyUnwrappedOptionalToken();
      continue;
    }
    break;
  }
  
  // Handle type-function if we have an arrow or 'throws'/'rethrows' modifier.
  if (Tok.isAny(tok::kw_throws, tok::kw_rethrows)) {
    consumeToken();
    // "throws" or "rethrows" isn't a valid type without being followed by
    // a return.
    if (!Tok.is(tok::arrow))
      return false;
  }
  
  if (consumeIf(tok::arrow)) {
    if (!canParseType())
      return false;
    return true;
  }

  return true;
}

bool Parser::canParseTypeIdentifierOrTypeComposition() {
  if (Tok.is(tok::kw_protocol))
    return canParseOldStyleProtocolComposition();
  
  while (true) {
    if (!canParseTypeIdentifier())
      return false;
    
    if (Tok.isContextualPunctuator("&")) {
      consumeToken();
      continue;
    } else {
      return true;
    }
  }
}

bool Parser::canParseTypeIdentifier() {
  while (true) {
    if (!Tok.isAny(tok::identifier, tok::kw_Self, tok::kw_Any))
      return false;
    consumeToken();
    
    if (startsWithLess(Tok)) {
      if (!canParseGenericArguments())
        return false;
    }

    // Treat 'Foo.<anything>' as an attempt to write a dotted type
    // unless <anything> is 'Type'.
    if ((Tok.is(tok::period) || Tok.is(tok::period_prefix)) &&
        !peekToken().isContextualKeyword("Type") &&
        !peekToken().isContextualKeyword("Protocol")) {
      consumeToken();
    } else {
      return true;
    }
  }
}

bool Parser::canParseOldStyleProtocolComposition() {
  consumeToken(tok::kw_protocol);
  
  // Check for the starting '<'.
  if (!startsWithLess(Tok)) {
    return false;
  }
  consumeStartingLess();
  
  // Check for empty protocol composition.
  if (startsWithGreater(Tok)) {
    consumeStartingGreater();
    return true;
  }
  
  // Parse the type-composition-list.
  do {
    if (!canParseTypeIdentifier()) {
      return false;
    }
  } while (consumeIf(tok::comma));
  
  // Check for the terminating '>'.
  if (!startsWithGreater(Tok)) {
    return false;
  }
  consumeStartingGreater();
  
  return true;
}

bool Parser::canParseTypeTupleBody() {
  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::r_brace) &&
      Tok.isNotEllipsis() && !isStartOfDecl()) {
    do {
      // The contextual inout marker is part of argument lists.
      consumeIf(tok::kw_inout);

      // If the tuple element starts with "ident :", then it is followed
      // by a type annotation.
      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 a type.
        if (!canParseType())
          return false;

        // Parse default values. This aren't actually allowed, but we recover
        // better if we skip over them.
        if (consumeIf(tok::equal)) {
          while (Tok.isNot(tok::eof) && Tok.isNot(tok::r_paren) &&
                 Tok.isNot(tok::r_brace) && Tok.isNotEllipsis() &&
                 Tok.isNot(tok::comma) &&
                 !isStartOfDecl()) {
            skipSingle();
          }
        }

        continue;
      }
      
      // Otherwise, this has to be a type.
      if (!canParseType())
        return false;

      if (Tok.isEllipsis())
        consumeToken();

    } while (consumeIf(tok::comma));
  }
  
  return consumeIf(tok::r_paren);
}
