mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #70196 from simanerush/nested-pack-iteration
[SE-0408] Enable nested iteration
This commit is contained in:
@@ -1543,6 +1543,10 @@ public:
|
||||
llvm::MapVector<PackElementExpr *, PackExpansionExpr *>
|
||||
PackEnvironments;
|
||||
|
||||
/// The outer pack element generic environment to use when dealing with nested
|
||||
/// pack iteration (see \c getPackElementEnvironment).
|
||||
llvm::SmallVector<GenericEnvironment *> PackElementGenericEnvironments;
|
||||
|
||||
/// The locators of \c Defaultable constraints whose defaults were used.
|
||||
llvm::DenseSet<ConstraintLocator *> DefaultedConstraints;
|
||||
|
||||
@@ -2344,6 +2348,8 @@ private:
|
||||
llvm::SmallMapVector<PackElementExpr *, PackExpansionExpr *, 2>
|
||||
PackEnvironments;
|
||||
|
||||
llvm::SmallVector<GenericEnvironment *, 4> PackElementGenericEnvironments;
|
||||
|
||||
/// The set of functions that have been transformed by a result builder.
|
||||
llvm::MapVector<AnyFunctionRef, AppliedBuilderTransform>
|
||||
resultBuilderTransformed;
|
||||
@@ -2833,6 +2839,9 @@ public:
|
||||
/// The length of \c PackEnvironments.
|
||||
unsigned numPackEnvironments;
|
||||
|
||||
/// The length of \c PackElementGenericEnvironments.
|
||||
unsigned numPackElementGenericEnvironments;
|
||||
|
||||
/// The length of \c DefaultedConstraints.
|
||||
unsigned numDefaultedConstraints;
|
||||
|
||||
|
||||
@@ -160,6 +160,7 @@ private:
|
||||
DeclContext *dc;
|
||||
Pattern *pattern;
|
||||
bool ignoreWhereClause;
|
||||
GenericEnvironment *packElementEnv;
|
||||
ForEachStmtInfo info;
|
||||
} forEachStmt;
|
||||
|
||||
@@ -239,11 +240,13 @@ public:
|
||||
}
|
||||
|
||||
SyntacticElementTarget(ForEachStmt *stmt, DeclContext *dc,
|
||||
bool ignoreWhereClause)
|
||||
bool ignoreWhereClause,
|
||||
GenericEnvironment *packElementEnv)
|
||||
: kind(Kind::forEachStmt) {
|
||||
forEachStmt.stmt = stmt;
|
||||
forEachStmt.dc = dc;
|
||||
forEachStmt.ignoreWhereClause = ignoreWhereClause;
|
||||
forEachStmt.packElementEnv = packElementEnv;
|
||||
}
|
||||
|
||||
/// Form a target for the initialization of a pattern from an expression.
|
||||
@@ -259,9 +262,10 @@ public:
|
||||
unsigned patternBindingIndex, bool bindPatternVarsOneWay);
|
||||
|
||||
/// Form a target for a for-in loop.
|
||||
static SyntacticElementTarget forForEachStmt(ForEachStmt *stmt,
|
||||
DeclContext *dc,
|
||||
bool ignoreWhereClause = false);
|
||||
static SyntacticElementTarget
|
||||
forForEachStmt(ForEachStmt *stmt, DeclContext *dc,
|
||||
bool ignoreWhereClause = false,
|
||||
GenericEnvironment *packElementEnv = nullptr);
|
||||
|
||||
/// Form a target for a property with an attached property wrapper that is
|
||||
/// initialized out-of-line.
|
||||
@@ -536,6 +540,11 @@ public:
|
||||
return forEachStmt.ignoreWhereClause;
|
||||
}
|
||||
|
||||
GenericEnvironment *getPackElementEnv() const {
|
||||
assert(isForEachStmt());
|
||||
return forEachStmt.packElementEnv;
|
||||
}
|
||||
|
||||
const ForEachStmtInfo &getForEachStmtInfo() const {
|
||||
assert(isForEachStmt());
|
||||
return forEachStmt.info;
|
||||
|
||||
@@ -734,10 +734,11 @@ GenericEnvironment::mapElementTypeIntoPackContext(Type type) const {
|
||||
|
||||
type = type->mapTypeOutOfContext();
|
||||
|
||||
auto interfaceType = element->getInterfaceType();
|
||||
|
||||
llvm::SmallDenseMap<GenericParamKey, GenericTypeParamType *>
|
||||
packParamForElement;
|
||||
auto elementDepth =
|
||||
sig.getInnermostGenericParams().front()->getDepth() + 1;
|
||||
auto elementDepth = interfaceType->getRootGenericParam()->getDepth();
|
||||
|
||||
for (auto *genericParam : sig.getGenericParams()) {
|
||||
if (!genericParam->isParameterPack())
|
||||
@@ -792,6 +793,8 @@ Type BuildForwardingSubstitutions::operator()(SubstitutableType *type) const {
|
||||
auto param = type->castTo<GenericTypeParamType>();
|
||||
if (!param->isParameterPack())
|
||||
return resultType;
|
||||
if (resultType->is<PackType>())
|
||||
return resultType;
|
||||
return PackType::getSingletonPackExpansion(resultType);
|
||||
}
|
||||
return Type();
|
||||
|
||||
@@ -4929,6 +4929,12 @@ bool ConstraintSystem::generateConstraints(
|
||||
}
|
||||
|
||||
case SyntacticElementTarget::Kind::forEachStmt: {
|
||||
|
||||
// Cache the outer generic environment, if it exists.
|
||||
if (target.getPackElementEnv()) {
|
||||
PackElementGenericEnvironments.push_back(target.getPackElementEnv());
|
||||
}
|
||||
|
||||
// For a for-each statement, generate constraints for the pattern, where
|
||||
// clause, and sequence traversal.
|
||||
auto resultTarget = generateForEachStmtConstraints(*this, target);
|
||||
|
||||
@@ -247,6 +247,9 @@ Solution ConstraintSystem::finalize() {
|
||||
for (const auto &packEnv : PackEnvironments)
|
||||
solution.PackEnvironments.insert(packEnv);
|
||||
|
||||
for (const auto &packEltGenericEnv : PackElementGenericEnvironments)
|
||||
solution.PackElementGenericEnvironments.push_back(packEltGenericEnv);
|
||||
|
||||
return solution;
|
||||
}
|
||||
|
||||
@@ -316,6 +319,12 @@ void ConstraintSystem::applySolution(const Solution &solution) {
|
||||
PackEnvironments.insert(packEnvironment);
|
||||
}
|
||||
|
||||
// Register the solutions's pack element generic environments.
|
||||
for (auto &packElementGenericEnvironment :
|
||||
solution.PackElementGenericEnvironments) {
|
||||
PackElementGenericEnvironments.push_back(packElementGenericEnvironment);
|
||||
}
|
||||
|
||||
// Register the defaulted type variables.
|
||||
DefaultedConstraints.insert(solution.DefaultedConstraints.begin(),
|
||||
solution.DefaultedConstraints.end());
|
||||
@@ -647,6 +656,7 @@ ConstraintSystem::SolverScope::SolverScope(ConstraintSystem &cs)
|
||||
numOpenedPackExpansionTypes = cs.OpenedPackExpansionTypes.size();
|
||||
numPackExpansionEnvironments = cs.PackExpansionEnvironments.size();
|
||||
numPackEnvironments = cs.PackEnvironments.size();
|
||||
numPackElementGenericEnvironments = cs.PackElementGenericEnvironments.size();
|
||||
numDefaultedConstraints = cs.DefaultedConstraints.size();
|
||||
numAddedNodeTypes = cs.addedNodeTypes.size();
|
||||
numAddedKeyPathComponentTypes = cs.addedKeyPathComponentTypes.size();
|
||||
@@ -736,6 +746,10 @@ ConstraintSystem::SolverScope::~SolverScope() {
|
||||
// Remove any pack environments.
|
||||
truncate(cs.PackEnvironments, numPackEnvironments);
|
||||
|
||||
// Remove any pack element generic environments.
|
||||
truncate(cs.PackElementGenericEnvironments,
|
||||
numPackElementGenericEnvironments);
|
||||
|
||||
// Remove any defaulted type variables.
|
||||
truncate(cs.DefaultedConstraints, numDefaultedConstraints);
|
||||
|
||||
|
||||
@@ -792,9 +792,11 @@ ConstraintSystem::getPackElementEnvironment(ConstraintLocator *locator,
|
||||
shapeClass->mapTypeOutOfContext()->getCanonicalType());
|
||||
|
||||
auto &ctx = getASTContext();
|
||||
auto *contextEnv = PackElementGenericEnvironments.empty()
|
||||
? DC->getGenericEnvironmentOfContext()
|
||||
: PackElementGenericEnvironments.back();
|
||||
auto elementSig = ctx.getOpenedElementSignature(
|
||||
DC->getGenericSignatureOfContext().getCanonicalSignature(), shapeParam);
|
||||
auto *contextEnv = DC->getGenericEnvironmentOfContext();
|
||||
contextEnv->getGenericSignature().getCanonicalSignature(), shapeParam);
|
||||
auto contextSubs = contextEnv->getForwardingSubstitutionMap();
|
||||
return GenericEnvironment::forOpenedElement(elementSig, uuidAndShape.first,
|
||||
shapeParam, contextSubs);
|
||||
@@ -4413,6 +4415,7 @@ size_t Solution::getTotalMemory() const {
|
||||
OpenedPackExpansionTypes.getMemorySize() +
|
||||
PackExpansionEnvironments.getMemorySize() +
|
||||
size_in_bytes(PackEnvironments) +
|
||||
PackElementGenericEnvironments.size() +
|
||||
(DefaultedConstraints.size() * sizeof(void *)) +
|
||||
ImplicitCallAsFunctionRoots.getMemorySize() +
|
||||
nodeTypes.getMemorySize() +
|
||||
|
||||
@@ -181,8 +181,9 @@ SyntacticElementTarget SyntacticElementTarget::forInitialization(
|
||||
|
||||
SyntacticElementTarget
|
||||
SyntacticElementTarget::forForEachStmt(ForEachStmt *stmt, DeclContext *dc,
|
||||
bool ignoreWhereClause) {
|
||||
SyntacticElementTarget target(stmt, dc, ignoreWhereClause);
|
||||
bool ignoreWhereClause,
|
||||
GenericEnvironment *packElementEnv) {
|
||||
SyntacticElementTarget target(stmt, dc, ignoreWhereClause, packElementEnv);
|
||||
return target;
|
||||
}
|
||||
|
||||
|
||||
@@ -906,7 +906,8 @@ bool TypeChecker::typeCheckPatternBinding(PatternBindingDecl *PBD,
|
||||
return hadError;
|
||||
}
|
||||
|
||||
bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
|
||||
bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt,
|
||||
GenericEnvironment *packElementEnv) {
|
||||
auto &Context = dc->getASTContext();
|
||||
FrontendStatsTracer statsTracer(Context.Stats, "typecheck-for-each", stmt);
|
||||
PrettyStackTraceStmt stackTrace(Context, "type-checking-for-each", stmt);
|
||||
@@ -922,7 +923,8 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
|
||||
return true;
|
||||
};
|
||||
|
||||
auto target = SyntacticElementTarget::forForEachStmt(stmt, dc);
|
||||
auto target = SyntacticElementTarget::forForEachStmt(
|
||||
stmt, dc, /*ignoreWhereClause=*/false, packElementEnv);
|
||||
if (!typeCheckTarget(target))
|
||||
return failed();
|
||||
|
||||
|
||||
@@ -1000,6 +1000,8 @@ public:
|
||||
|
||||
StmtChecker(DeclContext *DC) : Ctx(DC->getASTContext()), DC(DC) { }
|
||||
|
||||
llvm::SmallVector<GenericEnvironment *, 4> genericSigStack;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Helper Functions.
|
||||
//===--------------------------------------------------------------------===//
|
||||
@@ -1434,7 +1436,10 @@ public:
|
||||
}
|
||||
|
||||
Stmt *visitForEachStmt(ForEachStmt *S) {
|
||||
if (TypeChecker::typeCheckForEachBinding(DC, S))
|
||||
GenericEnvironment *genericSignature =
|
||||
genericSigStack.empty() ? nullptr : genericSigStack.back();
|
||||
|
||||
if (TypeChecker::typeCheckForEachBinding(DC, S, genericSignature))
|
||||
return nullptr;
|
||||
|
||||
// Type-check the body of the loop.
|
||||
@@ -1442,9 +1447,17 @@ public:
|
||||
checkLabeledStmtShadowing(getASTContext(), sourceFile, S);
|
||||
|
||||
BraceStmt *Body = S->getBody();
|
||||
|
||||
if (auto packExpansion =
|
||||
dyn_cast<PackExpansionExpr>(S->getParsedSequence()))
|
||||
genericSigStack.push_back(packExpansion->getGenericEnvironment());
|
||||
|
||||
typeCheckStmt(Body);
|
||||
S->setBody(Body);
|
||||
|
||||
|
||||
if (isa<PackExpansionExpr>(S->getParsedSequence()))
|
||||
genericSigStack.pop_back();
|
||||
|
||||
return S;
|
||||
}
|
||||
|
||||
|
||||
@@ -748,7 +748,8 @@ bool typeCheckPatternBinding(PatternBindingDecl *PBD, unsigned patternNumber,
|
||||
/// Type-check a for-each loop's pattern binding and sequence together.
|
||||
///
|
||||
/// \returns true if a failure occurred.
|
||||
bool typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt);
|
||||
bool typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt,
|
||||
GenericEnvironment *packElementEnv);
|
||||
|
||||
/// Compute the set of captures for the given function or closure.
|
||||
void computeCaptures(AnyFunctionRef AFR);
|
||||
|
||||
@@ -330,4 +330,14 @@ do {
|
||||
// expected-error@-1 {{'where' clause in pack iteration is not supported}}
|
||||
}
|
||||
}
|
||||
|
||||
func nested<each T, each U>(value: repeat each T, value1: repeat each U) {
|
||||
for e1 in repeat each value {
|
||||
for _ in [] {}
|
||||
for e2 in repeat each value1 {
|
||||
let y = e1 // Ok
|
||||
}
|
||||
let x = e1 // Ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user