Skip to content

Commit 8012e45

Browse files
committed
[Diagnostics] Diagnose pack element expressions containing a non-pack subexpression.
1 parent ebcd444 commit 8012e45

File tree

8 files changed

+80
-0
lines changed

8 files changed

+80
-0
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/Sema/CSBindings.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1482,6 +1482,12 @@ void PotentialBindings::infer(Constraint *constraint) {
14821482
packType = packType->mapTypeOutOfContext();
14831483
auto *elementEnv = CS.getPackElementEnvironment(constraint->getLocator(),
14841484
shapeClass);
1485+
1486+
// Without an opened element environment, we cannot derive the
1487+
// element binding.
1488+
if (!elementEnv)
1489+
break;
1490+
14851491
auto elementType = elementEnv->mapPackTypeIntoElementContext(packType);
14861492
addPotentialBinding({elementType, AllowedBindingKind::Exact, constraint});
14871493

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)