blob: c47bd329bd5b6633cd5942884bfc0d949e9c0abf [file] [log] [blame]
//===--- TypeCheckExpr.cpp - Type Checking for Expressions ----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file implements semantic analysis for expressions, analysing an
// expression tree in post-order, bottom-up, from leaves up to the root.
//
//===----------------------------------------------------------------------===//
#include "TypeChecker.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/Attr.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/Decl.h"
#include "swift/Basic/Defer.h"
#include "swift/Parse/Lexer.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/STLExtras.h"
using namespace swift;
//===----------------------------------------------------------------------===//
// Expression Semantic Analysis Routines
//===----------------------------------------------------------------------===//
static void substituteInputSugarArgumentType(Type argTy, CanType resultTy,
Type &resultSugarTy,
bool &uniqueSugarTy) {
// If we already failed finding a unique sugar, bail out.
if (!uniqueSugarTy)
return;
if (TupleType *argTupleTy = argTy->getAs<TupleType>()) {
// Recursively walk tuple arguments.
for (auto &field : argTupleTy->getElements()) {
substituteInputSugarArgumentType(field.getType(), resultTy,
resultSugarTy, uniqueSugarTy);
if (!uniqueSugarTy)
return;
}
return;
}
if (argTy->getCanonicalType() != resultTy) {
// If the argument is a metatype of what we're looking for, propagate that.
if (auto MTT = argTy->getAs<MetatypeType>())
argTy = MTT->getInstanceType();
if (argTy->getCanonicalType() != resultTy)
return;
}
// If this type is parenthesized, remove the parens. We don't want to
// propagate parens from arguments to the result type.
if (auto *PT = dyn_cast<ParenType>(argTy.getPointer()))
argTy = PT->getUnderlyingType();
// If this is the first match against the sugar type we found, use it.
if (!resultSugarTy) {
resultSugarTy = argTy;
return;
}
// Make sure this argument's sugar is consistent with the sugar we
// already found.
if (argTy->isSpelledLike(resultSugarTy))
return;
uniqueSugarTy = false;
}
/// If we can propagate type sugar from input arguments types to the result of
/// an apply, do so.
///
Expr *TypeChecker::substituteInputSugarTypeForResult(ApplyExpr *E) {
if (!E->getType() || E->getType()->is<ErrorType>())
return E;
Type resultTy = E->getFn()->getType()->castTo<FunctionType>()->getResult();
/// Check to see if you have "x+y" (where x and y are type aliases) that match
// the canonical result type. If so, propagate the sugar.
Type resultSugarTy; // null if no sugar found, set when sugar found
bool uniqueSugarTy = true; // true if a unique sugar mapping found
substituteInputSugarArgumentType(E->getArg()->getType(),
resultTy->getCanonicalType(),
resultSugarTy, uniqueSugarTy);
if (resultSugarTy && uniqueSugarTy && E->getType()->isCanonical()) {
E->setType(resultSugarTy);
return E;
}
// Otherwise check to see if this is a ConstructorRefExpr on a TypeExpr with
// sugar on it. If so, propagate the sugar to the curried result function
// type.
if (isa<ConstructorRefCallExpr>(E) && isa<TypeExpr>(E->getArg())) {
auto resultSugar =
E->getArg()->getType()->castTo<MetatypeType>()->getInstanceType();
// The result of this apply is "(args) -> T" where T is the type being
// constructed. Apply the sugar onto it.
if (auto FT = E->getType()->getAs<FunctionType>())
if (FT->getResult()->isEqual(resultSugar) && !resultSugar->isCanonical()){
auto NFT = FunctionType::get(FT->getInput(), resultSugar,
FT->getExtInfo());
E->setType(NFT);
return E;
}
}
// Otherwise, if the callee function had sugar on the result type, but it got
// dropped, make sure to propagate it along.
if (!resultTy->isCanonical() && E->getType()->isCanonical() &&
resultTy->isEqual(E->getType())) {
E->setType(resultTy);
return E;
}
return E;
}
/// getInfixData - If the specified expression is an infix binary
/// operator, return its infix operator attributes.
static InfixData getInfixData(TypeChecker &TC, DeclContext *DC, Expr *E) {
if (auto *ifExpr = dyn_cast<IfExpr>(E)) {
// Ternary has fixed precedence.
assert(!ifExpr->isFolded() && "already folded if expr in sequence?!");
(void)ifExpr;
return InfixData(IntrinsicPrecedences::IfExpr,
Associativity::Right,
/*assignment*/ false);
}
if (auto *assign = dyn_cast<AssignExpr>(E)) {
// Assignment has fixed precedence.
assert(!assign->isFolded() && "already folded assign expr in sequence?!");
(void)assign;
return InfixData(IntrinsicPrecedences::AssignExpr,
Associativity::Right,
/*assignment*/ true);
}
if (auto *as = dyn_cast<ExplicitCastExpr>(E)) {
// 'as' and 'is' casts have fixed precedence.
assert(!as->isFolded() && "already folded 'as' expr in sequence?!");
(void)as;
return InfixData(IntrinsicPrecedences::ExplicitCastExpr,
Associativity::None,
/*assignment*/ false);
}
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
SourceFile *SF = DC->getParentSourceFile();
Identifier name = DRE->getDecl()->getName();
bool isCascading = DC->isCascadingContextForLookup(true);
if (InfixOperatorDecl *op = SF->lookupInfixOperator(name, isCascading,
E->getLoc()))
return op->getInfixData();
}
if (OverloadedDeclRefExpr *OO = dyn_cast<OverloadedDeclRefExpr>(E)) {
SourceFile *SF = DC->getParentSourceFile();
Identifier name = OO->getDecls()[0]->getName();
bool isCascading = DC->isCascadingContextForLookup(true);
if (InfixOperatorDecl *op = SF->lookupInfixOperator(name, isCascading,
E->getLoc()))
return op->getInfixData();
}
// If E is already an ErrorExpr, then we've diagnosed it as invalid already,
// otherwise emit an error.
if (!isa<ErrorExpr>(E))
TC.diagnose(E->getLoc(), diag::unknown_binop);
// Recover with an infinite-precedence left-associative operator.
return InfixData((unsigned char)~0U, Associativity::Left,
/*assignment*/ false);
}
// The way we compute isEndOfSequence relies on the assumption that
// the sequence-folding algorithm never recurses with a prefix of the
// entire sequence.
static Expr *makeBinOp(TypeChecker &TC, Expr *Op, Expr *LHS, Expr *RHS,
const InfixData &infixData, bool isEndOfSequence) {
if (!LHS || !RHS)
return nullptr;
// If the left-hand-side is a 'try', hoist it up.
AnyTryExpr *tryEval = dyn_cast<AnyTryExpr>(LHS);
if (tryEval) {
LHS = tryEval->getSubExpr();
}
// If this is an assignment operator, and the left operand is an optional
// evaluation, pull the operator into the chain.
OptionalEvaluationExpr *optEval = nullptr;
if (infixData.isAssignment()) {
if ((optEval = dyn_cast<OptionalEvaluationExpr>(LHS))) {
LHS = optEval->getSubExpr();
}
}
// If the right operand is a try, it's an error unless the operator
// is an assignment or conditional operator and there's nothing to
// the right that didn't parse as part of the right operand.
//
// Generally, nothing to the right will fail to parse as part of the
// right operand because there are no standard operators that have
// lower precedence than assignment operators or the conditional
// operator.
//
// We allow the right operand of the conditional operator to begin
// with 'try' for consistency with the middle operand. This allows:
// x ? try foo() : try bar()
// but not:
// x ? try foo() : try bar() $#! 1
// assuming $#! is some crazy operator with lower precedence
// than the conditional operator.
if (isa<AnyTryExpr>(RHS)) {
// If you change this, also change TRY_KIND_SELECT in diagnostics.
enum class TryKindForDiagnostics : unsigned {
Try,
ForceTry,
OptionalTry
};
TryKindForDiagnostics tryKind;
switch (RHS->getKind()) {
case ExprKind::Try:
tryKind = TryKindForDiagnostics::Try;
break;
case ExprKind::ForceTry:
tryKind = TryKindForDiagnostics::ForceTry;
break;
case ExprKind::OptionalTry:
tryKind = TryKindForDiagnostics::OptionalTry;
break;
default:
llvm_unreachable("unknown try-like expression");
}
if (isa<IfExpr>(Op) || infixData.isAssignment()) {
if (!isEndOfSequence) {
if (isa<IfExpr>(Op)) {
TC.diagnose(RHS->getStartLoc(), diag::try_if_rhs_noncovering,
static_cast<unsigned>(tryKind));
} else {
TC.diagnose(RHS->getStartLoc(), diag::try_assign_rhs_noncovering,
static_cast<unsigned>(tryKind));
}
}
} else {
TC.diagnose(RHS->getStartLoc(), diag::try_rhs,
static_cast<unsigned>(tryKind));
}
}
// Fold the result into the optional evaluation or try.
auto makeResultExpr = [&](Expr *result) -> Expr * {
if (optEval) {
optEval->setSubExpr(result);
result = optEval;
}
if (tryEval) {
tryEval->setSubExpr(result);
result = tryEval;
}
return result;
};
if (auto *ifExpr = dyn_cast<IfExpr>(Op)) {
// Resolve the ternary expression.
assert(!ifExpr->isFolded() && "already folded if expr in sequence?!");
ifExpr->setCondExpr(LHS);
ifExpr->setElseExpr(RHS);
return makeResultExpr(ifExpr);
}
if (auto *assign = dyn_cast<AssignExpr>(Op)) {
// Resolve the assignment expression.
assert(!assign->isFolded() && "already folded assign expr in sequence?!");
assign->setDest(LHS);
assign->setSrc(RHS);
return makeResultExpr(assign);
}
if (auto *as = dyn_cast<ExplicitCastExpr>(Op)) {
// Resolve the 'as' or 'is' expression.
assert(!as->isFolded() && "already folded 'as' expr in sequence?!");
assert(RHS == as && "'as' with non-type RHS?!");
as->setSubExpr(LHS);
return makeResultExpr(as);
}
// Build the argument to the operation.
Expr *ArgElts[] = { LHS, RHS };
auto ArgElts2 = TC.Context.AllocateCopy(MutableArrayRef<Expr*>(ArgElts));
TupleExpr *Arg = TupleExpr::create(TC.Context,
SourceLoc(),
ArgElts2, { }, { }, SourceLoc(),
/*hasTrailingClosure=*/false,
LHS->isImplicit() && RHS->isImplicit());
// Build the operation.
return makeResultExpr(new (TC.Context) BinaryExpr(Op, Arg, Op->isImplicit()));
}
/// foldSequence - Take a sequence of expressions and fold a prefix of
/// it into a tree of BinaryExprs using precedence parsing.
static Expr *foldSequence(TypeChecker &TC, DeclContext *DC,
Expr *LHS,
ArrayRef<Expr*> &S,
unsigned MinPrecedence) {
// Invariant: S is even-sized.
// Invariant: All elements at even indices are operator references.
assert(!S.empty());
assert((S.size() & 1) == 0);
struct Op {
Expr *op;
InfixData infixData;
explicit operator bool() const { return op; }
};
/// Get the operator, if appropriate to this pass.
auto getNextOperator = [&]() -> Op {
Expr *op = S[0];
// If the operator's precedence is lower than the minimum, stop here.
InfixData opInfo = getInfixData(TC, DC, op);
if (opInfo.getPrecedence() < MinPrecedence) return {nullptr, {}};
return {op, opInfo};
};
// Extract out the first operator.
Op Op1 = getNextOperator();
if (!Op1) return LHS;
// We will definitely be consuming at least one operator.
// Pull out the prospective RHS and slice off the first two elements.
Expr *RHS = S[1];
S = S.slice(2);
while (!S.empty()) {
assert((S.size() & 1) == 0);
assert(Op1.infixData.isValid() && "Not a valid operator to fold");
assert(Op1.infixData.getPrecedence() >= MinPrecedence);
// If the operator is a cast operator, the RHS can't extend past the type
// that's part of the cast production.
if (isa<ExplicitCastExpr>(Op1.op)) {
LHS = makeBinOp(TC, Op1.op, LHS, RHS, Op1.infixData, S.empty());
Op1 = getNextOperator();
if (!Op1) return LHS;
RHS = S[1];
S = S.slice(2);
continue;
}
// Pull out the next binary operator.
Expr *Op2 = S[0];
InfixData Op2Info = getInfixData(TC, DC, Op2);
// If the second operator's precedence is lower than the min
// precedence, break out of the loop.
if (Op2Info.getPrecedence() < MinPrecedence) break;
// If the first operator's precedence is higher than the second
// operator's precedence, or they have matching precedence and are
// both left-associative, fold LHS and RHS immediately.
if (Op1.infixData.getPrecedence() > Op2Info.getPrecedence() ||
(Op1.infixData == Op2Info && Op1.infixData.isLeftAssociative())) {
LHS = makeBinOp(TC, Op1.op, LHS, RHS, Op1.infixData, S.empty());
Op1 = getNextOperator();
assert(Op1 && "should get a valid operator here");
RHS = S[1];
S = S.slice(2);
continue;
}
// If the first operator's precedence is lower than the second
// operator's precedence, recursively fold all such
// higher-precedence operators starting from this point, then
// repeat.
if (Op1.infixData.getPrecedence() < Op2Info.getPrecedence()) {
RHS = foldSequence(TC, DC, RHS, S, Op1.infixData.getPrecedence() + 1);
continue;
}
// If the first operator's precedence is the same as the second
// operator's precedence, and they're both right-associative,
// recursively fold operators starting from this point, then
// immediately fold LHS and RHS.
if (Op1.infixData == Op2Info && Op1.infixData.isRightAssociative()) {
RHS = foldSequence(TC, DC, RHS, S, Op1.infixData.getPrecedence());
LHS = makeBinOp(TC, Op1.op, LHS, RHS, Op1.infixData, S.empty());
// If we've drained the entire sequence, we're done.
if (S.empty()) return LHS;
// Otherwise, start all over with our new LHS.
return foldSequence(TC, DC, LHS, S, MinPrecedence);
}
// If we ended up here, it's because we have two operators
// with mismatched or no associativity.
assert(Op1.infixData.getPrecedence() == Op2Info.getPrecedence());
assert(Op1.infixData.getAssociativity() != Op2Info.getAssociativity()
|| Op1.infixData.isNonAssociative());
if (Op1.infixData.isNonAssociative()) {
// FIXME: QoI ranges
TC.diagnose(Op1.op->getLoc(), diag::non_assoc_adjacent);
} else if (Op2Info.isNonAssociative()) {
TC.diagnose(Op2->getLoc(), diag::non_assoc_adjacent);
} else {
TC.diagnose(Op1.op->getLoc(), diag::incompatible_assoc);
}
// Recover by arbitrarily binding the first two.
LHS = makeBinOp(TC, Op1.op, LHS, RHS, Op1.infixData, S.empty());
return foldSequence(TC, DC, LHS, S, MinPrecedence);
}
// Fold LHS and RHS together and declare completion.
return makeBinOp(TC, Op1.op, LHS, RHS, Op1.infixData, S.empty());
}
Type TypeChecker::getTypeOfRValue(ValueDecl *value, bool wantInterfaceType) {
validateDecl(value);
Type type;
if (wantInterfaceType)
type = value->getInterfaceType();
else
type = value->getType();
// Uses of inout argument values are lvalues.
if (auto iot = type->getAs<InOutType>())
return iot->getObjectType();
// Uses of values with lvalue type produce their rvalue.
if (auto LV = type->getAs<LValueType>())
return LV->getObjectType();
// Ignore 'unowned', 'weak' and @unmanaged qualification.
if (type->is<ReferenceStorageType>())
return type->getReferenceStorageReferent();
// No other transforms necessary.
return type;
}
bool TypeChecker::requireOptionalIntrinsics(SourceLoc loc) {
if (Context.hasOptionalIntrinsics(this)) return false;
diagnose(loc, diag::optional_intrinsics_not_found);
return true;
}
bool TypeChecker::requirePointerArgumentIntrinsics(SourceLoc loc) {
if (Context.hasPointerArgumentIntrinsics(this)) return false;
diagnose(loc, diag::pointer_argument_intrinsics_not_found);
return true;
}
bool TypeChecker::requireArrayLiteralIntrinsics(SourceLoc loc) {
if (Context.hasArrayLiteralIntrinsics(this)) return false;
diagnose(loc, diag::array_literal_intrinsics_not_found);
return true;
}
/// Does a var or subscript produce an l-value?
///
/// \param baseType - the type of the base on which this object
/// is being accessed; must be null if and only if this is not
/// a type member
static bool doesStorageProduceLValue(TypeChecker &TC,
AbstractStorageDecl *storage,
Type baseType, DeclContext *useDC,
const DeclRefExpr *base = nullptr) {
// Unsettable storage decls always produce rvalues.
if (!storage->isSettable(useDC, base))
return false;
if (TC.Context.LangOpts.EnableAccessControl &&
!storage->isSetterAccessibleFrom(useDC))
return false;
// If there is no base, or if the base isn't being used, it is settable.
// This is only possible for vars.
if (auto var = dyn_cast<VarDecl>(storage)) {
if (!baseType || var->isStatic())
return true;
}
// If the base is an lvalue, then a reference produces an lvalue.
if (baseType->is<LValueType>())
return true;
// Stored properties of reference types produce lvalues.
if (baseType->hasReferenceSemantics() && storage->hasStorage())
return true;
// So the base is an rvalue type. The only way an accessor can
// produce an lvalue is if we have a property where both the
// getter and setter are nonmutating.
return !storage->hasStorage() &&
!storage->isGetterMutating() &&
storage->isSetterNonMutating();
}
Type TypeChecker::getUnopenedTypeOfReference(ValueDecl *value, Type baseType,
DeclContext *UseDC,
const DeclRefExpr *base,
bool wantInterfaceType) {
validateDecl(value);
if (value->isInvalid())
return ErrorType::get(Context);
Type requestedType = getTypeOfRValue(value, wantInterfaceType);
// Qualify storage declarations with an lvalue when appropriate.
// Otherwise, they yield rvalues (and the access must be a load).
if (auto *storage = dyn_cast<AbstractStorageDecl>(value)) {
if (doesStorageProduceLValue(*this, storage, baseType, UseDC, base)) {
// Vars are simply lvalues of their rvalue type.
if (isa<VarDecl>(storage))
return LValueType::get(requestedType);
// Subscript decls have function type. For the purposes of later type
// checker consumption, model this as returning an lvalue.
assert(isa<SubscriptDecl>(storage));
auto *RFT = requestedType->castTo<FunctionType>();
return FunctionType::get(RFT->getInput(),
LValueType::get(RFT->getResult()),
RFT->getExtInfo());
}
}
return requestedType;
}
Expr *TypeChecker::buildCheckedRefExpr(ValueDecl *value, DeclContext *UseDC,
SourceLoc loc, bool Implicit) {
auto type = getUnopenedTypeOfReference(value, Type(), UseDC);
AccessSemantics semantics = value->getAccessSemanticsFromContext(UseDC);
return new (Context) DeclRefExpr(value, loc, Implicit, semantics, type);
}
Expr *TypeChecker::buildRefExpr(ArrayRef<ValueDecl *> Decls,
DeclContext *UseDC, SourceLoc NameLoc,
bool Implicit, bool isSpecialized) {
assert(!Decls.empty() && "Must have at least one declaration");
if (Decls.size() == 1 && !isa<ProtocolDecl>(Decls[0]->getDeclContext())) {
AccessSemantics semantics = Decls[0]->getAccessSemanticsFromContext(UseDC);
auto result = new (Context) DeclRefExpr(Decls[0], NameLoc, Implicit,
semantics);
if (isSpecialized)
result->setSpecialized();
return result;
}
Decls = Context.AllocateCopy(Decls);
auto result = new (Context) OverloadedDeclRefExpr(Decls, NameLoc, Implicit);
result->setSpecialized(isSpecialized);
return result;
}
static Type lookupDefaultLiteralType(TypeChecker &TC, DeclContext *dc,
StringRef name) {
auto lookupOptions = defaultUnqualifiedLookupOptions;
if (isa<AbstractFunctionDecl>(dc))
lookupOptions |= NameLookupFlags::KnownPrivate;
auto lookup = TC.lookupUnqualified(dc->getModuleScopeContext(),
TC.Context.getIdentifier(name),
SourceLoc(),
lookupOptions);
TypeDecl *TD = lookup.getSingleTypeResult();
if (!TD)
return Type();
TC.validateDecl(TD);
return TD->getDeclaredType();
}
Type TypeChecker::getDefaultType(ProtocolDecl *protocol, DeclContext *dc) {
Type *type = nullptr;
const char *name = nullptr;
// UnicodeScalarLiteralConvertible -> UnicodeScalarType
if (protocol ==
getProtocol(
SourceLoc(),
KnownProtocolKind::UnicodeScalarLiteralConvertible)) {
type = &UnicodeScalarType;
name = "UnicodeScalarType";
}
// ExtendedGraphemeClusterLiteralConvertible -> ExtendedGraphemeClusterType
else if (protocol ==
getProtocol(
SourceLoc(),
KnownProtocolKind::ExtendedGraphemeClusterLiteralConvertible)) {
type = &ExtendedGraphemeClusterType;
name = "ExtendedGraphemeClusterType";
}
// StringLiteralConvertible -> StringLiteralType
// StringInterpolationConvertible -> StringLiteralType
else if (protocol == getProtocol(
SourceLoc(),
KnownProtocolKind::StringLiteralConvertible) ||
protocol == getProtocol(
SourceLoc(),
KnownProtocolKind::StringInterpolationConvertible)) {
type = &StringLiteralType;
name = "StringLiteralType";
}
// IntegerLiteralConvertible -> IntegerLiteralType
else if (protocol == getProtocol(
SourceLoc(),
KnownProtocolKind::IntegerLiteralConvertible)) {
type = &IntLiteralType;
name = "IntegerLiteralType";
}
// FloatLiteralConvertible -> FloatLiteralType
else if (protocol == getProtocol(SourceLoc(),
KnownProtocolKind::FloatLiteralConvertible)){
type = &FloatLiteralType;
name = "FloatLiteralType";
}
// BooleanLiteralConvertible -> BoolLiteralType
else if (protocol == getProtocol(
SourceLoc(),
KnownProtocolKind::BooleanLiteralConvertible)){
type = &BooleanLiteralType;
name = "BooleanLiteralType";
}
// ArrayLiteralConvertible -> Array
else if (protocol == getProtocol(SourceLoc(),
KnownProtocolKind::ArrayLiteralConvertible)){
type = &ArrayLiteralType;
name = "Array";
}
// DictionaryLiteralConvertible -> Dictionary
else if (protocol == getProtocol(
SourceLoc(),
KnownProtocolKind::DictionaryLiteralConvertible)) {
type = &DictionaryLiteralType;
name = "Dictionary";
}
// _ColorLiteralConvertible -> _ColorLiteralType
else if (protocol == getProtocol(
SourceLoc(),
KnownProtocolKind::ColorLiteralConvertible)) {
type = &ColorLiteralType;
name = "_ColorLiteralType";
}
// _ImageLiteralConvertible -> _ImageLiteralType
else if (protocol == getProtocol(
SourceLoc(),
KnownProtocolKind::ImageLiteralConvertible)) {
type = &ImageLiteralType;
name = "_ImageLiteralType";
}
// _FileReferenceLiteralConvertible -> _FileReferenceLiteralType
else if (protocol == getProtocol(
SourceLoc(),
KnownProtocolKind::FileReferenceLiteralConvertible)) {
type = &FileReferenceLiteralType;
name = "_FileReferenceLiteralType";
}
if (!type)
return nullptr;
// If we haven't found the type yet, look for it now.
if (!*type) {
*type = lookupDefaultLiteralType(*this, dc, name);
if (!*type)
*type = lookupDefaultLiteralType(*this, getStdlibModule(dc), name);
// Strip off one level of sugar; we don't actually want to print
// the name of the typealias itself anywhere.
if (type && *type) {
if (auto typeAlias = dyn_cast<NameAliasType>(type->getPointer()))
*type = typeAlias->getDecl()->getUnderlyingType();
}
}
return *type;
}
Expr *TypeChecker::foldSequence(SequenceExpr *expr, DeclContext *dc) {
ArrayRef<Expr*> Elts = expr->getElements();
assert(Elts.size() > 1 && "inadequate number of elements in sequence");
assert((Elts.size() & 1) == 1 && "even number of elements in sequence");
Expr *LHS = Elts[0];
Elts = Elts.slice(1);
Expr *Result = ::foldSequence(*this, dc, LHS, Elts, /*min precedence*/ 0);
assert(Elts.empty());
return Result;
}
namespace {
class FindCapturedVars : public ASTWalker {
TypeChecker &TC;
SmallVectorImpl<CapturedValue> &captureList;
llvm::SmallDenseMap<ValueDecl*, unsigned, 4> captureEntryNumber;
SourceLoc CaptureLoc;
llvm::SmallPtrSet<ValueDecl *, 2> Diagnosed;
/// The AbstractClosureExpr or AbstractFunctionDecl being analyzed.
AnyFunctionRef AFR;
bool &capturesTypes;
public:
FindCapturedVars(TypeChecker &tc,
SmallVectorImpl<CapturedValue> &captureList,
bool &capturesTypes,
AnyFunctionRef AFR)
: TC(tc), captureList(captureList), AFR(AFR),
capturesTypes(capturesTypes) {
if (auto AFD = AFR.getAbstractFunctionDecl())
CaptureLoc = AFD->getLoc();
else {
auto ACE = AFR.getAbstractClosureExpr();
if (auto closure = dyn_cast<ClosureExpr>(ACE))
CaptureLoc = closure->getInLoc();
if (CaptureLoc.isInvalid())
CaptureLoc = ACE->getLoc();
}
}
/// \brief Check if the type of an expression references any generic
/// type parameters.
///
/// FIXME: SILGen doesn't currently allow local generic functions to
/// capture generic parameters from an outer context. Once it does, we
/// will need to distinguish outer and inner type parameters here.
void checkType(Type type) {
// Nothing to do if the type is concrete.
if (!type || !type->hasArchetype())
return;
// Easy case.
if (!type->hasOpenedExistential()) {
capturesTypes = true;
return;
}
// This type contains both an archetype and an open existential. Walk the
// type to see if we have any archetypes that are *not* open existentials.
if (type.findIf([](Type t) -> bool {
return (t->is<ArchetypeType>() && !t->isOpenedExistential());
}))
capturesTypes = true;
}
/// Add the specified capture to the closure's capture list, diagnosing it
/// if invalid.
void addCapture(CapturedValue capture, SourceLoc Loc) {
auto VD = capture.getDecl();
// Check to see if we already have an entry for this decl.
unsigned &entryNumber = captureEntryNumber[VD];
if (entryNumber == 0) {
captureList.push_back(capture);
entryNumber = captureList.size();
} else {
// If this already had an entry in the capture list, make sure to merge
// the information together. If one is noescape but the other isn't,
// then the result is escaping.
unsigned Flags =
captureList[entryNumber-1].getFlags() & capture.getFlags();
capture = CapturedValue(VD, Flags);
captureList[entryNumber-1] = capture;
}
// If VD is a noescape decl, then the closure we're computing this for
// must also be noescape.
if (VD->getAttrs().hasAttribute<NoEscapeAttr>() &&
!capture.isNoEscape() &&
// Don't repeatedly diagnose the same thing.
Diagnosed.insert(VD).second) {
// Otherwise, diagnose this as an invalid capture.
bool isDecl = AFR.getAbstractFunctionDecl() != nullptr;
TC.diagnose(Loc, isDecl ? diag::decl_closure_noescape_use :
diag::closure_noescape_use, VD->getName());
if (VD->getAttrs().hasAttribute<AutoClosureAttr>() &&
VD->getAttrs().getAttribute<NoEscapeAttr>()->isImplicit())
TC.diagnose(VD->getLoc(), diag::noescape_autoclosure,
VD->getName());
}
}
std::pair<bool, Expr *> walkToDeclRefExpr(DeclRefExpr *DRE) {
auto *D = DRE->getDecl();
// DC is the DeclContext where D was defined
// CurDC is the DeclContext where D was referenced
auto DC = D->getDeclContext();
auto CurDC = AFR.getAsDeclContext();
// A local reference is not a capture.
if (CurDC == DC)
return { false, DRE };
auto TmpDC = CurDC;
if (!isa<TopLevelCodeDecl>(DC)) {
while (TmpDC != nullptr) {
if (TmpDC == DC)
break;
// We have an intervening nominal type context that is not the
// declaration context, and the declaration context is not global.
// This is not supported since nominal types cannot capture values.
if (auto NTD = dyn_cast<NominalTypeDecl>(TmpDC)) {
if (DC->isLocalContext()) {
TC.diagnose(DRE->getLoc(), diag::capture_across_type_decl,
NTD->getDescriptiveKind(),
D->getName());
TC.diagnose(NTD->getLoc(), diag::type_declared_here);
TC.diagnose(D->getLoc(), diag::decl_declared_here,
D->getName());
return { false, DRE };
}
}
TmpDC = TmpDC->getParent();
}
// We walked all the way up to the root without finding the declaration,
// so this is not a capture.
if (TmpDC == nullptr)
return { false, DRE };
}
// Only capture var decls at global scope. Other things can be captured
// if they are local.
if (!isa<VarDecl>(D) && !DC->isLocalContext())
return { false, DRE };
// Can only capture a variable that is declared before the capturing
// entity.
llvm::DenseSet<ValueDecl *> checkedCaptures;
llvm::SmallVector<FuncDecl *, 2> capturePath;
std::function<bool (ValueDecl *)>
validateForwardCapture = [&](ValueDecl *capturedDecl) -> bool {
if (!checkedCaptures.insert(capturedDecl).second)
return true;
// Captures at nonlocal scope are order-invariant.
if (!capturedDecl->getDeclContext()->isLocalContext())
return true;
// Assume implicit decl captures are OK.
if (!CaptureLoc.isValid() || !capturedDecl->getLoc().isValid())
return true;
// Check the order of the declarations.
if (!TC.Context.SourceMgr.isBeforeInBuffer(CaptureLoc,
capturedDecl->getLoc()))
return true;
// Forward captures of functions are OK, if the function doesn't
// transitively capture variables ahead of the original function.
if (auto func = dyn_cast<FuncDecl>(capturedDecl)) {
if (!func->getCaptureInfo().hasBeenComputed()) {
// Check later.
TC.ForwardCapturedFuncs[func].push_back(AFR);
return true;
}
// Recursively check the transitive captures.
capturePath.push_back(func);
defer { capturePath.pop_back(); };
for (auto capture : func->getCaptureInfo().getCaptures())
if (!validateForwardCapture(capture.getDecl()))
return false;
return true;
}
// Diagnose the improper forward capture.
if (Diagnosed.insert(capturedDecl).second) {
if (capturedDecl == DRE->getDecl()) {
TC.diagnose(DRE->getLoc(), diag::capture_before_declaration,
capturedDecl->getName());
} else {
TC.diagnose(DRE->getLoc(),
diag::transitive_capture_before_declaration,
DRE->getDecl()->getName(),
capturedDecl->getName());
ValueDecl *prevDecl = capturedDecl;
for (auto path : reversed(capturePath)) {
TC.diagnose(path->getLoc(),
diag::transitive_capture_through_here,
path->getName(),
prevDecl->getName());
prevDecl = path;
}
}
TC.diagnose(capturedDecl->getLoc(), diag::decl_declared_here,
capturedDecl->getName());
}
return false;
};
if (!validateForwardCapture(DRE->getDecl()))
return { false, DRE };
// We're going to capture this, compute flags for the capture.
unsigned Flags = 0;
// If this is a direct reference to underlying storage, then this is a
// capture of the storage address - not a capture of the getter/setter.
if (DRE->getAccessSemantics() == AccessSemantics::DirectToStorage)
Flags |= CapturedValue::IsDirect;
// If the closure is noescape, then we can capture the decl as noescape.
if (AFR.isKnownNoEscape())
Flags |= CapturedValue::IsNoEscape;
addCapture(CapturedValue(D, Flags), DRE->getStartLoc());
return { false, DRE };
}
void propagateCaptures(AnyFunctionRef innerClosure, SourceLoc captureLoc) {
TC.computeCaptures(innerClosure);
auto CurDC = AFR.getAsDeclContext();
bool isNoEscapeClosure = AFR.isKnownNoEscape();
for (auto capture : innerClosure.getCaptureInfo().getCaptures()) {
// If the decl was captured from us, it isn't captured *by* us.
if (capture.getDecl()->getDeclContext() == CurDC)
continue;
// Compute adjusted flags.
unsigned Flags = capture.getFlags();
// The decl is captured normally, even if it was captured directly
// in the subclosure.
Flags &= ~CapturedValue::IsDirect;
// If this is an escaping closure, then any captured decls are also
// escaping, even if they are coming from an inner noescape closure.
if (!isNoEscapeClosure)
Flags &= ~CapturedValue::IsNoEscape;
addCapture(CapturedValue(capture.getDecl(), Flags), captureLoc);
}
if (innerClosure.getCaptureInfo().hasGenericParamCaptures())
capturesTypes = true;
}
bool walkToDeclPre(Decl *D) override {
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
propagateCaptures(AFD, AFD->getLoc());
for (auto *paramPattern : AFD->getBodyParamPatterns())
paramPattern->walk(*this);
return false;
}
return true;
}
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
checkType(E->getType());
if (auto *ECE = dyn_cast<ExplicitCastExpr>(E)) {
checkType(ECE->getCastTypeLoc().getType());
return { true, E };
}
if (auto *DRE = dyn_cast<DeclRefExpr>(E))
return walkToDeclRefExpr(DRE);
// When we see a reference to the 'super' expression, capture 'self' decl.
if (auto *superE = dyn_cast<SuperRefExpr>(E)) {
auto CurDC = AFR.getAsDeclContext();
if (CurDC->isChildContextOf(superE->getSelf()->getDeclContext()))
addCapture(CapturedValue(superE->getSelf(), 0), superE->getLoc());
return { false, superE };
}
// Don't recurse into child closures. They should already have a capture
// list computed; we just propagate it, filtering out stuff that they
// capture from us.
if (auto *SubCE = dyn_cast<AbstractClosureExpr>(E)) {
propagateCaptures(SubCE, SubCE->getStartLoc());
return { false, E };
}
return { true, E };
}
};
}
void TypeChecker::maybeDiagnoseCaptures(Expr *E, AnyFunctionRef AFR) {
if (!AFR.getCaptureInfo().hasBeenComputed()) {
// The capture list is not always initialized by the point we reference
// it. Remember we formed a C function pointer so we can diagnose later
// if necessary.
LocalCFunctionPointers[AFR].push_back(E);
return;
}
if (AFR.getCaptureInfo().hasGenericParamCaptures() ||
AFR.getCaptureInfo().hasLocalCaptures()) {
diagnose(E->getLoc(),
diag::c_function_pointer_from_function_with_context,
/*closure*/ AFR.getAbstractClosureExpr() != nullptr,
/*generic params*/ AFR.getCaptureInfo().hasGenericParamCaptures());
}
}
void TypeChecker::computeCaptures(AnyFunctionRef AFR) {
if (AFR.getCaptureInfo().hasBeenComputed())
return;
SmallVector<CapturedValue, 4> Captures;
bool GenericParamCaptures = false;
FindCapturedVars finder(*this, Captures, GenericParamCaptures, AFR);
AFR.getBody()->walk(finder);
if (AFR.hasType())
finder.checkType(AFR.getType());
// If this is an init(), explicitly walk the initializer values for members of
// the type. They will be implicitly emitted by SILGen into the generated
// initializer.
if (auto CD =
dyn_cast_or_null<ConstructorDecl>(AFR.getAbstractFunctionDecl())) {
auto *typeDecl = dyn_cast<NominalTypeDecl>(CD->getDeclContext());
if (typeDecl && CD->isDesignatedInit()) {
for (auto member : typeDecl->getMembers()) {
// Ignore everything other than PBDs.
auto *PBD = dyn_cast<PatternBindingDecl>(member);
if (!PBD) continue;
// Walk the initializers for all properties declared in the type with
// an initializer.
for (auto &elt : PBD->getPatternList())
if (auto *init = elt.getInit())
init->walk(finder);
}
}
}
// Since nested generic functions are not supported yet, the only case where
// generic parameters can be captured is by closures and non-generic local
// functions.
//
// So we only set GenericParamCaptures if we have a closure, or a
// non-generic function defined inside a local context.
auto *AFD = AFR.getAbstractFunctionDecl();
if (!AFD ||
(!AFD->getGenericParams() &&
AFD->getDeclContext()->isLocalContext())) {
AFR.getCaptureInfo().setGenericParamCaptures(GenericParamCaptures);
}
if (Captures.empty())
AFR.getCaptureInfo().setCaptures(None);
else
AFR.getCaptureInfo().setCaptures(Context.AllocateCopy(Captures));
// Diagnose if we have local captures and there were C pointers formed to
// this function before we computed captures.
auto cFunctionPointers = LocalCFunctionPointers.find(AFR);
if (cFunctionPointers != LocalCFunctionPointers.end())
for (auto *expr : cFunctionPointers->second)
maybeDiagnoseCaptures(expr, AFR);
}