Skip to content

Commit e6f29f8

Browse files
authored
Merge pull request #64119 from hborla/pack-expansion-shape-crash
[Diagnostics] Diagnose pack element expressions containing a non-pack a subexpression.
2 parents 6a9e9d6 + 8012e45 commit e6f29f8

File tree

10 files changed

+93
-11
lines changed

10 files changed

+93
-11
lines changed

include/swift/Sema/CSFix.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,9 @@ enum class FixKind : uint8_t {
425425

426426
/// Produce an error about a type that must be Copyable
427427
MustBeCopyable,
428+
429+
/// Allow 'each' applied to a non-pack type.
430+
AllowInvalidPackElement,
428431
};
429432

430433
class ConstraintFix {
@@ -2061,6 +2064,30 @@ class MustBeCopyable final : public ConstraintFix {
20612064
}
20622065
};
20632066

2067+
class AllowInvalidPackElement final : public ConstraintFix {
2068+
Type packElementType;
2069+
2070+
AllowInvalidPackElement(ConstraintSystem &cs, Type packElementType,
2071+
ConstraintLocator *locator)
2072+
: ConstraintFix(cs, FixKind::AllowInvalidPackElement, locator),
2073+
packElementType(packElementType) {}
2074+
2075+
public:
2076+
std::string getName() const override {
2077+
return "allow concrete pack element";
2078+
}
2079+
2080+
bool diagnose(const Solution &solution, bool asNote = false) const override;
2081+
2082+
static AllowInvalidPackElement *create(ConstraintSystem &cs,
2083+
Type packElementType,
2084+
ConstraintLocator *locator);
2085+
2086+
static bool classof(ConstraintFix const* fix) {
2087+
return fix->getKind() == FixKind::AllowInvalidPackElement;
2088+
}
2089+
};
2090+
20642091
class CollectionElementContextualMismatch final
20652092
: public ContextualMismatch,
20662093
private llvm::TrailingObjects<CollectionElementContextualMismatch,

lib/AST/ASTContext.cpp

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3247,17 +3247,7 @@ PackExpansionType::PackExpansionType(Type patternType, Type countType,
32473247
RecursiveTypeProperties properties,
32483248
const ASTContext *canCtx)
32493249
: TypeBase(TypeKind::PackExpansion, canCtx, properties),
3250-
patternType(patternType), countType(countType) {
3251-
3252-
// TODO: it would be nice if the solver didn't stick PlaceholderTypes and
3253-
// UnresolvedTypes in here.
3254-
assert(countType->is<PackType>() ||
3255-
countType->is<TypeVariableType>() ||
3256-
countType->is<PackArchetypeType>() ||
3257-
countType->is<PlaceholderType>() ||
3258-
countType->is<UnresolvedType>() ||
3259-
countType->castTo<GenericTypeParamType>()->isParameterPack());
3260-
}
3250+
patternType(patternType), countType(countType) {}
32613251

32623252
CanPackExpansionType
32633253
CanPackExpansionType::get(CanType patternType, CanType countType) {

lib/AST/ASTVerifier.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,18 @@ class Verifier : public ASTWalker {
603603
abort();
604604
}
605605

606+
// Check for invalid pack expansion shape types.
607+
if (auto *expansion = type->getAs<PackExpansionType>()) {
608+
auto countType = expansion->getCountType();
609+
if (!(countType->is<PackType>() ||
610+
countType->is<PackArchetypeType>() ||
611+
(countType->is<GenericTypeParamType>() &&
612+
countType->castTo<GenericTypeParamType>()->isParameterPack()))) {
613+
Out << "non-pack shape type" << countType->getString() << "\n";
614+
abort();
615+
}
616+
}
617+
606618
if (!type->hasArchetype())
607619
return;
608620

lib/Sema/CSBindings.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,6 +1494,12 @@ void PotentialBindings::infer(Constraint *constraint) {
14941494
packType = packType->mapTypeOutOfContext();
14951495
auto *elementEnv = CS.getPackElementEnvironment(constraint->getLocator(),
14961496
shapeClass);
1497+
1498+
// Without an opened element environment, we cannot derive the
1499+
// element binding.
1500+
if (!elementEnv)
1501+
break;
1502+
14971503
auto elementType = elementEnv->mapPackTypeIntoElementContext(packType);
14981504
addPotentialBinding({elementType, AllowedBindingKind::Exact, constraint});
14991505

lib/Sema/CSDiagnostics.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5996,6 +5996,11 @@ bool NotCopyableFailure::diagnoseAsError() {
59965996
return true;
59975997
}
59985998

5999+
bool InvalidPackElement::diagnoseAsError() {
6000+
emitDiagnostic(diag::each_non_pack, packElementType);
6001+
return true;
6002+
}
6003+
59996004
bool CollectionElementContextualFailure::diagnoseAsError() {
60006005
auto anchor = getRawAnchor();
60016006
auto *locator = getLocator();

lib/Sema/CSDiagnostics.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1838,6 +1838,19 @@ class NotCopyableFailure final : public FailureDiagnostic {
18381838
bool diagnoseAsError() override;
18391839
};
18401840

1841+
/// Diagnose \c each applied to an expression that is not a pack type.
1842+
class InvalidPackElement final : public FailureDiagnostic {
1843+
Type packElementType;
1844+
1845+
public:
1846+
InvalidPackElement(const Solution &solution, Type packElementType,
1847+
ConstraintLocator *locator)
1848+
: FailureDiagnostic(solution, locator),
1849+
packElementType(packElementType) {}
1850+
1851+
bool diagnoseAsError() override;
1852+
};
1853+
18411854
/// Diagnose a contextual mismatch between expected collection element type
18421855
/// and the one provided (e.g. source of the assignment or argument to a call)
18431856
/// e.g.:

lib/Sema/CSFix.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,6 +1366,20 @@ bool MustBeCopyable::diagnoseForAmbiguity(CommonFixesArray commonFixes) const {
13661366
return diagnose(*commonFixes.front().first);
13671367
}
13681368

1369+
bool AllowInvalidPackElement::diagnose(const Solution &solution,
1370+
bool asNote) const {
1371+
InvalidPackElement failure(solution, packElementType, getLocator());
1372+
return failure.diagnose(asNote);
1373+
}
1374+
1375+
AllowInvalidPackElement *
1376+
AllowInvalidPackElement::create(ConstraintSystem &cs,
1377+
Type packElementType,
1378+
ConstraintLocator *locator) {
1379+
return new (cs.getAllocator())
1380+
AllowInvalidPackElement(cs, packElementType, locator);
1381+
}
1382+
13691383
bool CollectionElementContextualMismatch::diagnose(const Solution &solution,
13701384
bool asNote) const {
13711385
CollectionElementContextualFailure failure(

lib/Sema/CSSimplify.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8818,6 +8818,13 @@ ConstraintSystem::simplifyPackElementOfConstraint(Type first, Type second,
88188818
return SolutionKind::Solved;
88198819
}
88208820

8821+
if (shouldAttemptFixes()) {
8822+
auto *loc = getConstraintLocator(locator);
8823+
auto *fix = AllowInvalidPackElement::create(*this, packType, loc);
8824+
if (!recordFix(fix))
8825+
return SolutionKind::Solved;
8826+
}
8827+
88218828
return SolutionKind::Error;
88228829
}
88238830

@@ -14029,6 +14036,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
1402914036
case FixKind::NotCompileTimeConst:
1403014037
case FixKind::RenameConflictingPatternVariables:
1403114038
case FixKind::MustBeCopyable:
14039+
case FixKind::AllowInvalidPackElement:
1403214040
case FixKind::MacroMissingPound:
1403314041
case FixKind::AllowGlobalActorMismatch: {
1403414042
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;

lib/Sema/ConstraintSystem.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,9 @@ ConstraintSystem::getPackElementEnvironment(ConstraintLocator *locator,
661661
if (result == PackExpansionEnvironments.end())
662662
return nullptr;
663663

664+
if (!shapeClass->is<PackArchetypeType>())
665+
return nullptr;
666+
664667
auto uuid = result->second;
665668
auto &ctx = getASTContext();
666669
auto elementSig = ctx.getOpenedElementSignature(

test/Constraints/pack-expansion-expressions.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,8 @@ func generateTuple<each T : Generatable>() -> (repeat each T) {
120120

121121
func packElementInvalidBinding<each T>(_ arg: repeat each T) {
122122
_ = (repeat print(each arg))
123+
124+
let x = 1
125+
repeat print(each x)
126+
// expected-error@-1 {{'each' cannot be applied to non-pack type 'Int'}}
123127
}

0 commit comments

Comments
 (0)