Skip to content

Commit 386a11f

Browse files
authored
Merge pull request #62016 from slavapestov/shape-requirements-misc
Mangling for shape requirements, and related fixes
2 parents ddc69e7 + 07b0c5c commit 386a11f

30 files changed

+525
-259
lines changed

docs/ABI/Mangling.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,8 @@ now codified into the ABI; the index 0 is therefore reserved.
887887
requirement ::= type assoc-type-list 'RM' GENERIC-PARAM-INDEX LAYOUT-CONSTRAINT // layout requirement on associated type at depth
888888
requirement ::= type substitution 'RM' LAYOUT-CONSTRAINT // layout requirement with substitution
889889

890+
requirement ::= type 'Rh' GENERIC-PARAM-INDEX // same-shape requirement (only supported on a generic parameter)
891+
890892
GENERIC-PARAM-INDEX ::= 'z' // depth = 0, idx = 0
891893
GENERIC-PARAM-INDEX ::= INDEX // depth = 0, idx = N+1
892894
GENERIC-PARAM-INDEX ::= 'd' INDEX INDEX // depth = M+1, idx = N

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5144,6 +5144,10 @@ ERROR(tuple_duplicate_label,none,
51445144
ERROR(multiple_ellipsis_in_tuple,none,
51455145
"only a single element can be variadic", ())
51465146

5147+
ERROR(expansion_not_same_shape,none,
5148+
"variadic expansion %0 requires that %1 and %2 have the same shape",
5149+
(Type, Type, Type))
5150+
51475151
ERROR(enum_element_ellipsis,none,
51485152
"variadic enum cases are not supported", ())
51495153
ERROR(unlabeled_parameter_following_variadic_parameter,none,

include/swift/AST/Types.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,7 @@ class alignas(1 << TypeAlignInBits) TypeBase
661661

662662
/// Retrieve the set of type parameter packs that occur within this type.
663663
void getTypeParameterPacks(
664-
SmallVectorImpl<Type> &rootParameterPacks) const;
664+
SmallVectorImpl<Type> &rootParameterPacks);
665665

666666
/// Replace opened archetypes with the given root with their most
667667
/// specific non-dependent upper bounds throughout this type.
@@ -1290,6 +1290,18 @@ class alignas(1 << TypeAlignInBits) TypeBase
12901290
/// Error.
12911291
bool isExistentialWithError();
12921292

1293+
/// Returns the reduced shape of the type, which represents an equivalence
1294+
/// class for the same-shape generic requirement:
1295+
///
1296+
/// - The shape of a scalar type is always the empty tuple type ().
1297+
/// - The shape of a pack archetype is computed from the generic signature
1298+
/// using same-shape requirements.
1299+
/// - The shape of a pack type is computed recursively from its elements.
1300+
///
1301+
/// Two types satisfy a same-shape requirement if their reduced shapes are
1302+
/// equal as canonical types.
1303+
CanType getReducedShape();
1304+
12931305
SWIFT_DEBUG_DUMP;
12941306
void dump(raw_ostream &os, unsigned indent = 0) const;
12951307

@@ -6028,7 +6040,7 @@ class PackArchetypeType final
60286040
LayoutConstraint Layout);
60296041

60306042
// Returns the reduced shape type for this pack archetype.
6031-
Type getShape() const;
6043+
CanType getReducedShape() const;
60326044

60336045
static bool classof(const TypeBase *T) {
60346046
return T->getKind() == TypeKind::PackArchetype;
@@ -6481,6 +6493,8 @@ class PackType final : public TypeBase, public llvm::FoldingSetNode,
64816493

64826494
PackType *flattenPackTypes();
64836495

6496+
CanTypeWrapper<PackType> getReducedShape();
6497+
64846498
public:
64856499
void Profile(llvm::FoldingSetNodeID &ID) const {
64866500
Profile(ID, getElementTypes());
@@ -6553,6 +6567,8 @@ class PackExpansionType : public TypeBase, public llvm::FoldingSetNode {
65536567

65546568
PackExpansionType *expand();
65556569

6570+
CanType getReducedShape();
6571+
65566572
public:
65576573
void Profile(llvm::FoldingSetNodeID &ID) {
65586574
Profile(ID, getPatternType(), getCountType());

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ NODE(DependentGenericConformanceRequirement)
5959
NODE(DependentGenericParamCount)
6060
NODE(DependentGenericParamType)
6161
NODE(DependentGenericSameTypeRequirement)
62+
NODE(DependentGenericSameShapeRequirement)
6263
NODE(DependentGenericLayoutRequirement)
6364
NODE(DependentGenericSignature)
6465
NODE(DependentGenericType)

lib/AST/ASTMangler.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2912,8 +2912,6 @@ void ASTMangler::appendRequirement(const Requirement &reqt,
29122912
Type FirstTy = reqt.getFirstType()->getCanonicalType();
29132913

29142914
switch (reqt.getKind()) {
2915-
case RequirementKind::SameShape:
2916-
llvm_unreachable("Same-shape requirement not supported here");
29172915
case RequirementKind::Layout:
29182916
break;
29192917
case RequirementKind::Conformance: {
@@ -2925,7 +2923,8 @@ void ASTMangler::appendRequirement(const Requirement &reqt,
29252923
appendProtocolName(reqt.getProtocolDecl());
29262924
} break;
29272925
case RequirementKind::Superclass:
2928-
case RequirementKind::SameType: {
2926+
case RequirementKind::SameType:
2927+
case RequirementKind::SameShape: {
29292928
Type SecondTy = reqt.getSecondType();
29302929
appendType(SecondTy->getCanonicalType(), sig);
29312930
break;
@@ -2957,7 +2956,7 @@ void ASTMangler::appendRequirement(const Requirement &reqt,
29572956
assert(gpBase);
29582957
switch (reqt.getKind()) {
29592958
case RequirementKind::SameShape:
2960-
llvm_unreachable("Same-shape requirement not supported here");
2959+
llvm_unreachable("Same-shape requirement with a dependent member type?");
29612960
case RequirementKind::Conformance:
29622961
return appendOpWithGenericParamIndex(isAssocTypeAtDepth ? "RP" : "Rp",
29632962
gpBase, lhsBaseIsProtocolSelf);
@@ -2977,8 +2976,6 @@ void ASTMangler::appendRequirement(const Requirement &reqt,
29772976
}
29782977
GenericTypeParamType *gpBase = FirstTy->castTo<GenericTypeParamType>();
29792978
switch (reqt.getKind()) {
2980-
case RequirementKind::SameShape:
2981-
llvm_unreachable("Same-shape requirement not supported here");
29822979
case RequirementKind::Conformance:
29832980
return appendOpWithGenericParamIndex("R", gpBase);
29842981
case RequirementKind::Layout:
@@ -2989,6 +2986,8 @@ void ASTMangler::appendRequirement(const Requirement &reqt,
29892986
return appendOpWithGenericParamIndex("Rb", gpBase);
29902987
case RequirementKind::SameType:
29912988
return appendOpWithGenericParamIndex("Rs", gpBase);
2989+
case RequirementKind::SameShape:
2990+
return appendOpWithGenericParamIndex("Rh", gpBase);
29922991
}
29932992
llvm_unreachable("bad requirement type");
29942993
}

lib/AST/ASTPrinter.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1787,22 +1787,26 @@ void PrintAST::printSingleDepthOfGenericSignature(
17871787
}
17881788

17891789
void PrintAST::printRequirement(const Requirement &req) {
1790-
printTransformedType(req.getFirstType());
17911790
switch (req.getKind()) {
17921791
case RequirementKind::SameShape:
1793-
Printer << ".shape == ";
1792+
Printer << "((";
1793+
printTransformedType(req.getFirstType());
1794+
Printer << ", ";
17941795
printTransformedType(req.getSecondType());
1795-
Printer << ".shape";
1796+
Printer << ")...) : Any";
17961797
return;
17971798
case RequirementKind::Layout:
1799+
printTransformedType(req.getFirstType());
17981800
Printer << " : ";
17991801
req.getLayoutConstraint()->print(Printer, Options);
18001802
return;
18011803
case RequirementKind::Conformance:
18021804
case RequirementKind::Superclass:
1805+
printTransformedType(req.getFirstType());
18031806
Printer << " : ";
18041807
break;
18051808
case RequirementKind::SameType:
1809+
printTransformedType(req.getFirstType());
18061810
Printer << " == ";
18071811
break;
18081812
}

lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ add_swift_host_library(swiftAST STATIC
7777
ProtocolConformance.cpp
7878
ProtocolConformanceRef.cpp
7979
RawComment.cpp
80+
Requirement.cpp
8081
RequirementEnvironment.cpp
8182
RequirementMachine/ConcreteContraction.cpp
8283
RequirementMachine/ConcreteTypeWitness.cpp

lib/AST/GenericSignature.cpp

Lines changed: 0 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -741,173 +741,6 @@ void swift::simple_display(raw_ostream &out, GenericSignature sig) {
741741
out << "NULL";
742742
}
743743

744-
bool Requirement::hasError() const {
745-
if (getFirstType()->hasError())
746-
return true;
747-
748-
if (getKind() != RequirementKind::Layout && getSecondType()->hasError())
749-
return true;
750-
751-
return false;
752-
}
753-
754-
bool Requirement::isCanonical() const {
755-
if (!getFirstType()->isCanonical())
756-
return false;
757-
758-
switch (getKind()) {
759-
case RequirementKind::SameShape:
760-
case RequirementKind::Conformance:
761-
case RequirementKind::SameType:
762-
case RequirementKind::Superclass:
763-
if (!getSecondType()->isCanonical())
764-
return false;
765-
break;
766-
767-
case RequirementKind::Layout:
768-
break;
769-
}
770-
771-
return true;
772-
}
773-
774-
/// Get the canonical form of this requirement.
775-
Requirement Requirement::getCanonical() const {
776-
Type firstType = getFirstType()->getCanonicalType();
777-
778-
switch (getKind()) {
779-
case RequirementKind::SameShape:
780-
case RequirementKind::Conformance:
781-
case RequirementKind::SameType:
782-
case RequirementKind::Superclass: {
783-
Type secondType = getSecondType()->getCanonicalType();
784-
return Requirement(getKind(), firstType, secondType);
785-
}
786-
787-
case RequirementKind::Layout:
788-
return Requirement(getKind(), firstType, getLayoutConstraint());
789-
}
790-
llvm_unreachable("Unhandled RequirementKind in switch");
791-
}
792-
793-
ProtocolDecl *Requirement::getProtocolDecl() const {
794-
assert(getKind() == RequirementKind::Conformance);
795-
return getSecondType()->castTo<ProtocolType>()->getDecl();
796-
}
797-
798-
bool
799-
Requirement::isSatisfied(ArrayRef<Requirement> &conditionalRequirements,
800-
bool allowMissing) const {
801-
switch (getKind()) {
802-
case RequirementKind::SameShape:
803-
llvm_unreachable("Same-shape requirements not supported here");
804-
805-
case RequirementKind::Conformance: {
806-
auto *proto = getProtocolDecl();
807-
auto *module = proto->getParentModule();
808-
auto conformance = module->lookupConformance(
809-
getFirstType(), proto, allowMissing);
810-
if (!conformance)
811-
return false;
812-
813-
conditionalRequirements = conformance.getConditionalRequirements();
814-
return true;
815-
}
816-
817-
case RequirementKind::Layout: {
818-
if (auto *archetypeType = getFirstType()->getAs<ArchetypeType>()) {
819-
auto layout = archetypeType->getLayoutConstraint();
820-
return (layout && layout.merge(getLayoutConstraint()));
821-
}
822-
823-
if (getLayoutConstraint()->isClass())
824-
return getFirstType()->satisfiesClassConstraint();
825-
826-
// TODO: Statically check other layout constraints, once they can
827-
// be spelled in Swift.
828-
return true;
829-
}
830-
831-
case RequirementKind::Superclass:
832-
return getSecondType()->isExactSuperclassOf(getFirstType());
833-
834-
case RequirementKind::SameType:
835-
return getFirstType()->isEqual(getSecondType());
836-
}
837-
838-
llvm_unreachable("Bad requirement kind");
839-
}
840-
841-
bool Requirement::canBeSatisfied() const {
842-
switch (getKind()) {
843-
case RequirementKind::SameShape:
844-
llvm_unreachable("Same-shape requirements not supported here");
845-
846-
case RequirementKind::Conformance:
847-
return getFirstType()->is<ArchetypeType>();
848-
849-
case RequirementKind::Layout: {
850-
if (auto *archetypeType = getFirstType()->getAs<ArchetypeType>()) {
851-
auto layout = archetypeType->getLayoutConstraint();
852-
return (!layout || layout.merge(getLayoutConstraint()));
853-
}
854-
855-
return false;
856-
}
857-
858-
case RequirementKind::Superclass:
859-
return (getFirstType()->isBindableTo(getSecondType()) ||
860-
getSecondType()->isBindableTo(getFirstType()));
861-
862-
case RequirementKind::SameType:
863-
return (getFirstType()->isBindableTo(getSecondType()) ||
864-
getSecondType()->isBindableTo(getFirstType()));
865-
}
866-
867-
llvm_unreachable("Bad requirement kind");
868-
}
869-
870-
/// Determine the canonical ordering of requirements.
871-
static unsigned getRequirementKindOrder(RequirementKind kind) {
872-
switch (kind) {
873-
case RequirementKind::SameShape: return 4;
874-
case RequirementKind::Conformance: return 2;
875-
case RequirementKind::Superclass: return 0;
876-
case RequirementKind::SameType: return 3;
877-
case RequirementKind::Layout: return 1;
878-
}
879-
llvm_unreachable("unhandled kind");
880-
}
881-
882-
/// Linear order on requirements in a generic signature.
883-
int Requirement::compare(const Requirement &other) const {
884-
int compareLHS =
885-
compareDependentTypes(getFirstType(), other.getFirstType());
886-
887-
if (compareLHS != 0)
888-
return compareLHS;
889-
890-
int compareKind = (getRequirementKindOrder(getKind()) -
891-
getRequirementKindOrder(other.getKind()));
892-
893-
if (compareKind != 0)
894-
return compareKind;
895-
896-
// We should only have multiple conformance requirements.
897-
if (getKind() != RequirementKind::Conformance) {
898-
llvm::errs() << "Unordered generic requirements\n";
899-
llvm::errs() << "LHS: "; dump(llvm::errs()); llvm::errs() << "\n";
900-
llvm::errs() << "RHS: "; other.dump(llvm::errs()); llvm::errs() << "\n";
901-
abort();
902-
}
903-
904-
int compareProtos =
905-
TypeDecl::compare(getProtocolDecl(), other.getProtocolDecl());
906-
assert(compareProtos != 0 && "Duplicate conformance requirements");
907-
908-
return compareProtos;
909-
}
910-
911744
/// Compare two associated types.
912745
int swift::compareAssociatedTypes(AssociatedTypeDecl *assocType1,
913746
AssociatedTypeDecl *assocType2) {

0 commit comments

Comments
 (0)