Skip to content

Commit 0d3504f

Browse files
authored
Merge pull request #62729 from hborla/pack-diagnostics
[CSDiagnostics] Add an error message for pack expansion expressions over packs that don't have the same shape.
2 parents ed630db + e966b4e commit 0d3504f

File tree

8 files changed

+43
-4
lines changed

8 files changed

+43
-4
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5164,6 +5164,9 @@ ERROR(multiple_ellipsis_in_tuple,none,
51645164
ERROR(expansion_not_same_shape,none,
51655165
"variadic expansion %0 requires that %1 and %2 have the same shape",
51665166
(Type, Type, Type))
5167+
ERROR(expansion_expr_not_same_shape,none,
5168+
"pack expansion requires that %0 and %1 have the same shape",
5169+
(Type, Type))
51675170

51685171
ERROR(enum_element_ellipsis,none,
51695172
"variadic enum cases are not supported", ())

include/swift/Sema/CSFix.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -659,8 +659,10 @@ class SkipSameTypeRequirement final : public ConstraintFix {
659659
}
660660
};
661661

662-
/// Skip same-shape generic requirement constraint,
663-
/// and assume that types are equal.
662+
/// Skip a same-shape requirement between two type packs.
663+
///
664+
/// A same shape requirement can be inferred from a generic requirement,
665+
/// or from a pack expansion expression.
664666
class SkipSameShapeRequirement final : public ConstraintFix {
665667
Type LHS, RHS;
666668

@@ -671,7 +673,7 @@ class SkipSameShapeRequirement final : public ConstraintFix {
671673

672674
public:
673675
std::string getName() const override {
674-
return "skip same-shape generic requirement";
676+
return "skip same-shape requirement";
675677
}
676678

677679
bool diagnose(const Solution &solution, bool asNote = false) const override;

lib/Sema/CSDiagnostics.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,11 @@ bool MissingConformanceFailure::diagnoseAsAmbiguousOperatorRef() {
681681
return true;
682682
}
683683

684+
bool SameShapeExpansionFailure::diagnoseAsError() {
685+
emitDiagnostic(diag::expansion_expr_not_same_shape, lhs, rhs);
686+
return true;
687+
}
688+
684689
Optional<Diag<Type, Type>> GenericArgumentsMismatchFailure::getDiagnosticFor(
685690
ContextualTypePurpose context) {
686691
switch (context) {

lib/Sema/CSDiagnostics.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,17 @@ class SameShapeRequirementFailure final : public RequirementFailure {
470470
}
471471
};
472472

473+
class SameShapeExpansionFailure final : public FailureDiagnostic {
474+
Type lhs, rhs;
475+
476+
public:
477+
SameShapeExpansionFailure(const Solution &solution, Type lhs, Type rhs,
478+
ConstraintLocator *locator)
479+
: FailureDiagnostic(solution, locator), lhs(lhs), rhs(rhs) {}
480+
481+
bool diagnoseAsError() override;
482+
};
483+
473484
/// Diagnose failures related to superclass generic requirements, e.g.
474485
/// ```swift
475486
/// class A {

lib/Sema/CSFix.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,11 @@ SkipSameTypeRequirement::create(ConstraintSystem &cs, Type lhs, Type rhs,
467467

468468
bool SkipSameShapeRequirement::diagnose(const Solution &solution,
469469
bool asNote) const {
470+
if (getLocator()->isLastElement<LocatorPathElt::PackShape>()) {
471+
SameShapeExpansionFailure failure(solution, LHS, RHS, getLocator());
472+
return failure.diagnose(asNote);
473+
}
474+
470475
SameShapeRequirementFailure failure(solution, LHS, RHS, getLocator());
471476
return failure.diagnose(asNote);
472477
}

lib/Sema/CSGen.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3025,7 +3025,7 @@ namespace {
30253025
}
30263026

30273027
CS.addConstraint(ConstraintKind::ShapeOf, packType, shapeTypeVar,
3028-
CS.getConstraintLocator(expr));
3028+
CS.getConstraintLocator(expr, ConstraintLocator::PackShape));
30293029
}
30303030

30313031
return PackExpansionType::get(patternTy, shapeTypeVar);

lib/Sema/CSSimplify.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6017,6 +6017,13 @@ bool ConstraintSystem::repairFailures(
60176017
getConstraintLocator(anchor, path));
60186018
}
60196019

6020+
case ConstraintLocator::PackShape: {
6021+
auto *shapeLocator = getConstraintLocator(locator);
6022+
auto *fix = SkipSameShapeRequirement::create(*this, lhs, rhs, shapeLocator);
6023+
conversionsOrFixes.push_back(fix);
6024+
break;
6025+
}
6026+
60206027
case ConstraintLocator::SequenceElementType: {
60216028
if (lhs->isPlaceholder() || rhs->isPlaceholder()) {
60226029
recordAnyTypeVarAsPotentialHole(lhs);

test/Constraints/pack-expansion-expressions.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,9 @@ func typeReprPacks<T...>(_ t: T...) where T: ExpressibleByIntegerLiteral {
7171
_ = Array<each T>() // expected-error {{pack reference 'T' can only appear in pack expansion or generic requirement}}
7272
_ = 1 as each T // expected-error {{pack reference 'T' can only appear in pack expansion or generic requirement}}
7373
}
74+
75+
func sameShapeDiagnostics<T..., U...>(t: T..., u: U...) {
76+
_ = (each t, each u)... // expected-error {{pack expansion requires that 'U' and 'T' have the same shape}}
77+
_ = Array<(each T, each U)>()... // expected-error {{pack expansion requires that 'U' and 'T' have the same shape}}
78+
_ = (Array<each T>(), each u)... // expected-error {{pack expansion requires that 'U' and 'T' have the same shape}}
79+
}

0 commit comments

Comments
 (0)