Skip to content

Commit bb04542

Browse files
committed
Sema: Add diagnostics for ShapeOf constraint
1 parent 06eba02 commit bb04542

File tree

7 files changed

+115
-8
lines changed

7 files changed

+115
-8
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2104,6 +2104,9 @@ NOTE(type_does_not_inherit_or_conform_requirement,none,
21042104
ERROR(types_not_equal,none,
21052105
"%0 requires the types %1 and %2 be equivalent",
21062106
(Type, Type, Type))
2107+
ERROR(types_not_same_shape,none,
2108+
"%0 requires the type packs %1 and %2 have the same shape",
2109+
(Type, Type, Type))
21072110
ERROR(type_does_not_conform_owner,none,
21082111
"%0 requires that %1 conform to %2", (Type, Type, Type))
21092112
ERROR(type_does_not_conform_in_decl_ref,none,
@@ -2133,6 +2136,12 @@ ERROR(types_not_equal_decl,none,
21332136
ERROR(types_not_equal_in_decl_ref,none,
21342137
"referencing %0 %1 on %2 requires the types %3 and %4 be equivalent",
21352138
(DescriptiveDeclKind, DeclName, Type, Type, Type))
2139+
ERROR(types_not_same_shape_decl,none,
2140+
"%0 %1 requires the type packs %2 and %3 have the same shape",
2141+
(DescriptiveDeclKind, DeclName, Type, Type))
2142+
ERROR(types_not_same_shape_in_decl_ref,none,
2143+
"referencing %0 %1 on %2 requires the type packs %3 and %4 have the same shape",
2144+
(DescriptiveDeclKind, DeclName, Type, Type, Type))
21362145
ERROR(types_not_inherited_decl,none,
21372146
"%0 %1 requires that %2 inherit from %3",
21382147
(DescriptiveDeclKind, DeclName, Type, Type))
@@ -2155,6 +2164,10 @@ NOTE(candidate_types_equal_requirement,none,
21552164
"candidate requires that the types %0 and %1 be equivalent "
21562165
"(requirement specified as %2 == %3)",
21572166
(Type, Type, Type, Type))
2167+
NOTE(candidate_types_same_shape_requirement,none,
2168+
"candidate requires that the type packs %0 and %1 have the same shape "
2169+
"(requirement specified as %2.shape == %3.shape)",
2170+
(Type, Type, Type, Type))
21582171
NOTE(candidate_types_inheritance_requirement,none,
21592172
"candidate requires that %1 inherit from %2 "
21602173
"(requirement specified as %2 : %3)",

include/swift/Sema/CSFix.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ enum class FixKind : uint8_t {
9393
/// and assume that types are equal.
9494
SkipSameTypeRequirement,
9595

96+
/// Skip same-shape generic requirement constraint,
97+
/// and assume that pack types have the same shape.
98+
SkipSameShapeRequirement,
99+
96100
/// Skip superclass generic requirement constraint,
97101
/// and assume that types are related.
98102
SkipSuperclassRequirement,
@@ -655,6 +659,34 @@ class SkipSameTypeRequirement final : public ConstraintFix {
655659
}
656660
};
657661

662+
/// Skip same-shape generic requirement constraint,
663+
/// and assume that types are equal.
664+
class SkipSameShapeRequirement final : public ConstraintFix {
665+
Type LHS, RHS;
666+
667+
SkipSameShapeRequirement(ConstraintSystem &cs, Type lhs, Type rhs,
668+
ConstraintLocator *locator)
669+
: ConstraintFix(cs, FixKind::SkipSameShapeRequirement, locator), LHS(lhs),
670+
RHS(rhs) {}
671+
672+
public:
673+
std::string getName() const override {
674+
return "skip same-shape generic requirement";
675+
}
676+
677+
bool diagnose(const Solution &solution, bool asNote = false) const override;
678+
679+
Type lhsType() { return LHS; }
680+
Type rhsType() { return RHS; }
681+
682+
static SkipSameShapeRequirement *create(ConstraintSystem &cs, Type lhs,
683+
Type rhs, ConstraintLocator *locator);
684+
685+
static bool classof(ConstraintFix *fix) {
686+
return fix->getKind() == FixKind::SkipSameTypeRequirement;
687+
}
688+
};
689+
658690
/// Skip 'superclass' generic requirement constraint,
659691
/// and assume that types are equal.
660692
class SkipSuperclassRequirement final : public ConstraintFix {

lib/Sema/CSDiagnostics.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,40 @@ class SameTypeRequirementFailure final : public RequirementFailure {
435435
}
436436
};
437437

438+
/// Diagnose failures related to same-shape generic requirements, e.g.
439+
/// ```swift
440+
/// func foo<T..., U...>(t: T..., u: U...) -> (T, U)... {}
441+
/// func bar<T..., U...>(t: T..., u: U...) {
442+
/// foo(t: t..., u: u...)
443+
/// }
444+
/// ```
445+
///
446+
/// `S.T` is not the same type as `Int`, which is required by `foo`.
447+
class SameShapeRequirementFailure final : public RequirementFailure {
448+
public:
449+
SameShapeRequirementFailure(const Solution &solution, Type lhs, Type rhs,
450+
ConstraintLocator *locator)
451+
: RequirementFailure(solution, lhs, rhs, locator) {
452+
#ifndef NDEBUG
453+
auto reqElt = locator->castLastElementTo<LocatorPathElt::AnyRequirement>();
454+
assert(reqElt.getRequirementKind() == RequirementKind::SameShape);
455+
#endif
456+
}
457+
458+
protected:
459+
DiagOnDecl getDiagnosticOnDecl() const override {
460+
return diag::types_not_same_shape_decl;
461+
}
462+
463+
DiagInReference getDiagnosticInRereference() const override {
464+
return diag::types_not_same_shape_in_decl_ref;
465+
}
466+
467+
DiagAsNote getDiagnosticAsNote() const override {
468+
return diag::candidate_types_same_shape_requirement;
469+
}
470+
};
471+
438472
/// Diagnose failures related to superclass generic requirements, e.g.
439473
/// ```swift
440474
/// class A {

lib/Sema/CSFix.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,18 @@ SkipSameTypeRequirement::create(ConstraintSystem &cs, Type lhs, Type rhs,
465465
return new (cs.getAllocator()) SkipSameTypeRequirement(cs, lhs, rhs, locator);
466466
}
467467

468+
bool SkipSameShapeRequirement::diagnose(const Solution &solution,
469+
bool asNote) const {
470+
SameShapeRequirementFailure failure(solution, LHS, RHS, getLocator());
471+
return failure.diagnose(asNote);
472+
}
473+
474+
SkipSameShapeRequirement *
475+
SkipSameShapeRequirement::create(ConstraintSystem &cs, Type lhs, Type rhs,
476+
ConstraintLocator *locator) {
477+
return new (cs.getAllocator()) SkipSameShapeRequirement(cs, lhs, rhs, locator);
478+
}
479+
468480
bool SkipSuperclassRequirement::diagnose(const Solution &solution,
469481
bool asNote) const {
470482
SuperclassRequirementFailure failure(solution, LHS, RHS, getLocator());

lib/Sema/CSSimplify.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4222,16 +4222,14 @@ static ConstraintFix *fixRequirementFailure(ConstraintSystem &cs, Type type1,
42224222
auto *reqLoc = cs.getConstraintLocator(anchor, path);
42234223

42244224
switch (req.getRequirementKind()) {
4225-
case RequirementKind::SameShape:
4226-
llvm_unreachable("Same-shape requirement not supported here");
4227-
4228-
case RequirementKind::SameType: {
4225+
case RequirementKind::SameType:
42294226
return SkipSameTypeRequirement::create(cs, type1, type2, reqLoc);
4230-
}
42314227

4232-
case RequirementKind::Superclass: {
4228+
case RequirementKind::SameShape:
4229+
return SkipSameShapeRequirement::create(cs, type1, type2, reqLoc);
4230+
4231+
case RequirementKind::Superclass:
42334232
return SkipSuperclassRequirement::create(cs, type1, type2, reqLoc);
4234-
}
42354233

42364234
case RequirementKind::Layout:
42374235
case RequirementKind::Conformance:
@@ -13642,6 +13640,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
1364213640

1364313641
case FixKind::AddConformance:
1364413642
case FixKind::SkipSameTypeRequirement:
13643+
case FixKind::SkipSameShapeRequirement:
1364513644
case FixKind::SkipSuperclassRequirement: {
1364613645
return recordFix(fix, assessRequirementFailureImpact(*this, type1,
1364713646
fix->getLocator()))

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,6 +910,13 @@ static Optional<RequirementMatch> findMissingGenericRequirementForSolutionFix(
910910
missingType = requirementFix->rhsType();
911911
break;
912912
}
913+
case FixKind::SkipSameShapeRequirement: {
914+
requirementKind = RequirementKind::SameShape;
915+
auto requirementFix = (SkipSameShapeRequirement *)fix;
916+
type = requirementFix->lhsType();
917+
missingType = requirementFix->rhsType();
918+
break;
919+
}
913920
case FixKind::SkipSuperclassRequirement: {
914921
requirementKind = RequirementKind::Superclass;
915922
auto requirementFix = (SkipSuperclassRequirement *)fix;

test/Constraints/variadic_generic_constraints.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,21 @@ takesParallelSequences(t: Array<String>(), Set<Int>(), u: Array<Int>(), Set<Stri
5656
// Same-shape requirements
5757

5858
func zip<T..., U...>(t: T..., u: U...) -> ((T, U)...) {}
59+
// expected-note@-1 {{where 'T' = 'U', 'U' = 'Pack{T...}'}}
5960

6061
let _ = zip() // ok
6162
let _ = zip(t: 1, u: "hi") // ok
6263
let _ = zip(t: 1, 2, u: "hi", "hello") // ok
6364
let _ = zip(t: 1, 2, 3, u: "hi", "hello", "greetings") // ok
6465

6566
// FIXME: Bad diagnostic
66-
let _ = zip(t: 1, u: "hi", "hello", "greetings") // expected-error {{type of expression is ambiguous without more context}}
67+
let _ = zip(t: 1, u: "hi", "hello", "greetings") // expected-error {{type of expression is ambiguous without more context}}
68+
69+
func goodCallToZip<T..., U...>(t: T..., u: U...) where ((T, U)...): Any {
70+
_ = zip(t: t..., u: u...)
71+
}
72+
73+
func badCallToZip<T..., U...>(t: T..., u: U...) {
74+
_ = zip(t: t..., u: u...)
75+
// expected-error@-1 {{global function 'zip(t:u:)' requires the type packs 'U' and 'Pack{T...}' have the same shape}}
76+
}

0 commit comments

Comments
 (0)