mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Add a function parameter to Expr::propagateLValueAccessKind.
This parameter implements getType() for the given expression, making it possible to use this from within the constraint system, which now has it's own side map for types of expressions.
This commit is contained in:
@@ -576,6 +576,10 @@ public:
|
|||||||
/// \param allowOverwrite - true if it's okay if an expression already
|
/// \param allowOverwrite - true if it's okay if an expression already
|
||||||
/// has an access kind
|
/// has an access kind
|
||||||
void propagateLValueAccessKind(AccessKind accessKind,
|
void propagateLValueAccessKind(AccessKind accessKind,
|
||||||
|
std::function<Type(Expr *)> getType
|
||||||
|
= [](Expr *E) -> Type {
|
||||||
|
return E->getType();
|
||||||
|
},
|
||||||
bool allowOverwrite = false);
|
bool allowOverwrite = false);
|
||||||
|
|
||||||
/// Retrieves the declaration that is being referenced by this
|
/// Retrieves the declaration that is being referenced by this
|
||||||
|
|||||||
@@ -213,17 +213,20 @@ DeclRefExpr *Expr::getMemberOperatorRef() {
|
|||||||
|
|
||||||
/// Propagate l-value use information to children.
|
/// Propagate l-value use information to children.
|
||||||
void Expr::propagateLValueAccessKind(AccessKind accessKind,
|
void Expr::propagateLValueAccessKind(AccessKind accessKind,
|
||||||
|
std::function<Type(Expr *)> getType,
|
||||||
bool allowOverwrite) {
|
bool allowOverwrite) {
|
||||||
/// A visitor class which walks an entire l-value expression.
|
/// A visitor class which walks an entire l-value expression.
|
||||||
class PropagateAccessKind
|
class PropagateAccessKind
|
||||||
: public ExprVisitor<PropagateAccessKind, void, AccessKind> {
|
: public ExprVisitor<PropagateAccessKind, void, AccessKind> {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
std::function<Type(Expr *)> GetType;
|
||||||
bool AllowOverwrite;
|
bool AllowOverwrite;
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
PropagateAccessKind(bool allowOverwrite)
|
PropagateAccessKind(std::function<Type(Expr *)> getType,
|
||||||
|
bool allowOverwrite)
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
: AllowOverwrite(allowOverwrite)
|
: GetType(getType), AllowOverwrite(allowOverwrite)
|
||||||
#endif
|
#endif
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -231,7 +234,7 @@ void Expr::propagateLValueAccessKind(AccessKind accessKind,
|
|||||||
assert((AllowOverwrite || !E->hasLValueAccessKind()) &&
|
assert((AllowOverwrite || !E->hasLValueAccessKind()) &&
|
||||||
"l-value access kind has already been set");
|
"l-value access kind has already been set");
|
||||||
|
|
||||||
assert(E->getType()->isAssignableType() &&
|
assert(GetType(E)->isAssignableType() &&
|
||||||
"setting access kind on non-l-value");
|
"setting access kind on non-l-value");
|
||||||
E->setLValueAccessKind(kind);
|
E->setLValueAccessKind(kind);
|
||||||
|
|
||||||
@@ -255,11 +258,11 @@ void Expr::propagateLValueAccessKind(AccessKind accessKind,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void visitMemberRefExpr(MemberRefExpr *E, AccessKind accessKind) {
|
void visitMemberRefExpr(MemberRefExpr *E, AccessKind accessKind) {
|
||||||
if (!E->getBase()->getType()->isLValueType()) return;
|
if (!GetType(E->getBase())->isLValueType()) return;
|
||||||
visit(E->getBase(), getBaseAccessKind(E->getMember(), accessKind));
|
visit(E->getBase(), getBaseAccessKind(E->getMember(), accessKind));
|
||||||
}
|
}
|
||||||
void visitSubscriptExpr(SubscriptExpr *E, AccessKind accessKind) {
|
void visitSubscriptExpr(SubscriptExpr *E, AccessKind accessKind) {
|
||||||
if (!E->getBase()->getType()->isLValueType()) return;
|
if (!GetType(E->getBase())->isLValueType()) return;
|
||||||
visit(E->getBase(), getBaseAccessKind(E->getDecl(), accessKind));
|
visit(E->getBase(), getBaseAccessKind(E->getDecl(), accessKind));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,7 +357,7 @@ void Expr::propagateLValueAccessKind(AccessKind accessKind,
|
|||||||
#undef NON_LVALUE_EXPR
|
#undef NON_LVALUE_EXPR
|
||||||
};
|
};
|
||||||
|
|
||||||
PropagateAccessKind(allowOverwrite).visit(this, accessKind);
|
PropagateAccessKind(getType, allowOverwrite).visit(this, accessKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConcreteDeclRef Expr::getReferencedDecl() const {
|
ConcreteDeclRef Expr::getReferencedDecl() const {
|
||||||
|
|||||||
@@ -266,7 +266,18 @@ getImplicitMemberReferenceAccessSemantics(Expr *base, VarDecl *member,
|
|||||||
return member->getAccessSemanticsFromContext(DC);
|
return member->getAccessSemanticsFromContext(DC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConstraintSystem::propagateLValueAccessKind(Expr *E,
|
||||||
|
AccessKind accessKind,
|
||||||
|
bool allowOverwrite) {
|
||||||
|
E->propagateLValueAccessKind(accessKind,
|
||||||
|
[&](Expr *E) -> Type {
|
||||||
|
return getType(E);
|
||||||
|
},
|
||||||
|
allowOverwrite);
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// \brief Rewrites an expression by applying the solution of a constraint
|
/// \brief Rewrites an expression by applying the solution of a constraint
|
||||||
/// system to that expression.
|
/// system to that expression.
|
||||||
class ExprRewriter : public ExprVisitor<ExprRewriter, Expr *> {
|
class ExprRewriter : public ExprVisitor<ExprRewriter, Expr *> {
|
||||||
@@ -688,8 +699,8 @@ namespace {
|
|||||||
// down to the original existential value. Otherwise, propagateLVAK
|
// down to the original existential value. Otherwise, propagateLVAK
|
||||||
// will handle this.
|
// will handle this.
|
||||||
if (record.OpaqueValue->hasLValueAccessKind())
|
if (record.OpaqueValue->hasLValueAccessKind())
|
||||||
record.ExistentialValue->propagateLValueAccessKind(
|
cs.propagateLValueAccessKind(record.ExistentialValue,
|
||||||
record.OpaqueValue->getLValueAccessKind());
|
record.OpaqueValue->getLValueAccessKind());
|
||||||
|
|
||||||
// Form the open-existential expression.
|
// Form the open-existential expression.
|
||||||
result = new (tc.Context) OpenExistentialExpr(
|
result = new (tc.Context) OpenExistentialExpr(
|
||||||
@@ -2803,7 +2814,7 @@ namespace {
|
|||||||
// case (when we turn the inout into an UnsafePointer) than to try to
|
// case (when we turn the inout into an UnsafePointer) than to try to
|
||||||
// discover that we're in that case right now.
|
// discover that we're in that case right now.
|
||||||
if (!cs.getType(expr->getSubExpr())->is<UnresolvedType>())
|
if (!cs.getType(expr->getSubExpr())->is<UnresolvedType>())
|
||||||
expr->getSubExpr()->propagateLValueAccessKind(AccessKind::ReadWrite);
|
cs.propagateLValueAccessKind(expr->getSubExpr(), AccessKind::ReadWrite);
|
||||||
auto objectTy = cs.getType(expr->getSubExpr())->getRValueType();
|
auto objectTy = cs.getType(expr->getSubExpr())->getRValueType();
|
||||||
|
|
||||||
// The type is simply inout of whatever the lvalue's object type was.
|
// The type is simply inout of whatever the lvalue's object type was.
|
||||||
@@ -3322,7 +3333,7 @@ namespace {
|
|||||||
auto destTy = cs.computeAssignDestType(expr->getDest(), expr->getLoc());
|
auto destTy = cs.computeAssignDestType(expr->getDest(), expr->getLoc());
|
||||||
if (!destTy)
|
if (!destTy)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
expr->getDest()->propagateLValueAccessKind(AccessKind::Write);
|
cs.propagateLValueAccessKind(expr->getDest(), AccessKind::Write);
|
||||||
|
|
||||||
// Convert the source to the simplified destination type.
|
// Convert the source to the simplified destination type.
|
||||||
auto locator =
|
auto locator =
|
||||||
@@ -5284,7 +5295,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
// Load from the lvalue.
|
// Load from the lvalue.
|
||||||
expr->propagateLValueAccessKind(AccessKind::Read);
|
cs.propagateLValueAccessKind(expr, AccessKind::Read);
|
||||||
expr = cs.cacheType(
|
expr = cs.cacheType(
|
||||||
new (tc.Context) LoadExpr(expr, fromType->getRValueType()));
|
new (tc.Context) LoadExpr(expr, fromType->getRValueType()));
|
||||||
|
|
||||||
@@ -5427,8 +5438,9 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
|
|||||||
if (pointerKind == PTK_UnsafePointer) {
|
if (pointerKind == PTK_UnsafePointer) {
|
||||||
// Overwrite the l-value access kind to be read-only if we're
|
// Overwrite the l-value access kind to be read-only if we're
|
||||||
// converting to a non-mutable pointer type.
|
// converting to a non-mutable pointer type.
|
||||||
cast<InOutExpr>(expr->getValueProvidingExpr())->getSubExpr()
|
auto *E = cast<InOutExpr>(expr->getValueProvidingExpr())->getSubExpr();
|
||||||
->propagateLValueAccessKind(AccessKind::Read, /*overwrite*/ true);
|
cs.propagateLValueAccessKind(E,
|
||||||
|
AccessKind::Read, /*overwrite*/ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
tc.requirePointerArgumentIntrinsics(expr->getLoc());
|
tc.requirePointerArgumentIntrinsics(expr->getLoc());
|
||||||
@@ -5560,7 +5572,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
|
|||||||
// In an 'inout' operator like "++i", the operand is converted from
|
// In an 'inout' operator like "++i", the operand is converted from
|
||||||
// an implicit lvalue to an inout argument.
|
// an implicit lvalue to an inout argument.
|
||||||
assert(toIO->getObjectType()->isEqual(fromLValue->getObjectType()));
|
assert(toIO->getObjectType()->isEqual(fromLValue->getObjectType()));
|
||||||
expr->propagateLValueAccessKind(AccessKind::ReadWrite);
|
cs.propagateLValueAccessKind(expr, AccessKind::ReadWrite);
|
||||||
return cs.cacheType(new (tc.Context)
|
return cs.cacheType(new (tc.Context)
|
||||||
InOutExpr(expr->getStartLoc(), expr, toType,
|
InOutExpr(expr->getStartLoc(), expr, toType,
|
||||||
/*isImplicit*/ true));
|
/*isImplicit*/ true));
|
||||||
@@ -5578,7 +5590,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
|
|||||||
|
|
||||||
if (performLoad) {
|
if (performLoad) {
|
||||||
// Load from the lvalue.
|
// Load from the lvalue.
|
||||||
expr->propagateLValueAccessKind(AccessKind::Read);
|
cs.propagateLValueAccessKind(expr, AccessKind::Read);
|
||||||
expr = cs.cacheType(new (tc.Context)
|
expr = cs.cacheType(new (tc.Context)
|
||||||
LoadExpr(expr, fromLValue->getObjectType()));
|
LoadExpr(expr, fromLValue->getObjectType()));
|
||||||
|
|
||||||
@@ -5811,7 +5823,7 @@ ExprRewriter::coerceObjectArgumentToType(Expr *expr,
|
|||||||
|
|
||||||
// Use InOutExpr to convert it to an explicit inout argument for the
|
// Use InOutExpr to convert it to an explicit inout argument for the
|
||||||
// receiver.
|
// receiver.
|
||||||
expr->propagateLValueAccessKind(AccessKind::ReadWrite);
|
cs.propagateLValueAccessKind(expr, AccessKind::ReadWrite);
|
||||||
return cs.cacheType(new (ctx) InOutExpr(expr->getStartLoc(), expr, toType,
|
return cs.cacheType(new (ctx) InOutExpr(expr->getStartLoc(), expr, toType,
|
||||||
/*isImplicit*/ true));
|
/*isImplicit*/ true));
|
||||||
}
|
}
|
||||||
@@ -6600,7 +6612,7 @@ Expr *ConstraintSystem::coerceToRValue(Expr *expr) {
|
|||||||
|
|
||||||
// If we already have an rvalue, we're done, otherwise emit a load.
|
// If we already have an rvalue, we're done, otherwise emit a load.
|
||||||
if (auto lvalueTy = getType(expr)->getAs<LValueType>()) {
|
if (auto lvalueTy = getType(expr)->getAs<LValueType>()) {
|
||||||
expr->propagateLValueAccessKind(AccessKind::Read);
|
propagateLValueAccessKind(expr, AccessKind::Read);
|
||||||
return cacheType(new (getASTContext())
|
return cacheType(new (getASTContext())
|
||||||
LoadExpr(expr, lvalueTy->getObjectType()));
|
LoadExpr(expr, lvalueTy->getObjectType()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1764,6 +1764,13 @@ public:
|
|||||||
/// \brief Determine if the type in question is AnyHashable.
|
/// \brief Determine if the type in question is AnyHashable.
|
||||||
bool isAnyHashableType(Type t);
|
bool isAnyHashableType(Type t);
|
||||||
|
|
||||||
|
/// Call Expr::propagateLValueAccessKind on the given expression,
|
||||||
|
/// using a custom accessor for the type on the expression which
|
||||||
|
/// reads the type from the ConstraintSystem expression type map.
|
||||||
|
void propagateLValueAccessKind(Expr *E,
|
||||||
|
AccessKind accessKind,
|
||||||
|
bool allowOverwrite = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Introduce the constraints associated with the given type variable
|
/// Introduce the constraints associated with the given type variable
|
||||||
/// into the worklist.
|
/// into the worklist.
|
||||||
|
|||||||
Reference in New Issue
Block a user