@@ -2069,30 +2069,19 @@ bool GenericSignatureBuilder::addConformanceRequirement(PotentialArchetype *PAT,
2069
2069
return false ;
2070
2070
}
2071
2071
2072
- bool GenericSignatureBuilder::addLayoutRequirement (PotentialArchetype *PAT,
2073
- LayoutConstraint Layout ,
2074
- const RequirementSource *Source) {
2075
- // Add the requirement to the representative.
2076
- auto T = PAT->getRepresentative ();
2072
+ bool GenericSignatureBuilder::addLayoutRequirement (
2073
+ PotentialArchetype *PAT ,
2074
+ LayoutConstraint Layout,
2075
+ const RequirementSource *Source) {
2076
+ auto equivClass = PAT->getOrCreateEquivalenceClass ();
2077
2077
2078
- if (T->Layout ) {
2079
- if (T->Layout == Layout) {
2080
- // Update the source.
2081
- T->LayoutSource = Source;
2082
- return false ;
2083
- }
2084
- // There is an existing layout constraint for this archetype.
2085
- Diags.diagnose (Source->getLoc (), diag::mutiple_layout_constraints,
2086
- Layout, T->Layout );
2087
- Diags.diagnose (T->LayoutSource ->getLoc (),
2088
- diag::previous_layout_constraint, T->Layout );
2089
- T->setInvalid ();
2078
+ // Record this layout constraint.
2079
+ equivClass->layoutConstraints .push_back ({PAT, Layout, Source});
2090
2080
2091
- return true ;
2092
- }
2093
-
2094
- T->Layout = Layout;
2095
- T->LayoutSource = Source;
2081
+ // Update the layout in the equivalence class, if we didn't have one already.
2082
+ // FIXME: Layouts can probably be merged sensibly.
2083
+ if (!equivClass->layout )
2084
+ equivClass->layout = Layout;
2096
2085
2097
2086
return false ;
2098
2087
}
@@ -3052,6 +3041,7 @@ GenericSignatureBuilder::finalize(SourceLoc loc,
3052
3041
}
3053
3042
3054
3043
checkConformanceConstraints (genericParams, archetype);
3044
+ checkLayoutConstraints (genericParams, archetype);
3055
3045
checkSameTypeConstraints (genericParams, archetype);
3056
3046
});
3057
3047
@@ -3457,6 +3447,28 @@ void GenericSignatureBuilder::checkSuperclassConstraints(
3457
3447
}
3458
3448
}
3459
3449
3450
+ void GenericSignatureBuilder::checkLayoutConstraints (
3451
+ ArrayRef<GenericTypeParamType *> genericParams,
3452
+ PotentialArchetype *pa) {
3453
+ auto equivClass = pa->getEquivalenceClassIfPresent ();
3454
+ if (!equivClass || !equivClass->layout ) return ;
3455
+
3456
+ checkConstraintList<LayoutConstraint>(
3457
+ genericParams, equivClass->layoutConstraints ,
3458
+ [&](const Constraint<LayoutConstraint> &constraint) {
3459
+ return constraint.value == equivClass->layout ;
3460
+ },
3461
+ [&](LayoutConstraint layout) {
3462
+ if (layout == equivClass->layout )
3463
+ return ConstraintRelation::Redundant;
3464
+
3465
+ return ConstraintRelation::Conflicting;
3466
+ },
3467
+ diag::conflicting_layout_constraints,
3468
+ diag::redundant_layout_constraint,
3469
+ diag::previous_layout_constraint);
3470
+ }
3471
+
3460
3472
template <typename F>
3461
3473
void GenericSignatureBuilder::visitPotentialArchetypes (F f) {
3462
3474
// Stack containing all of the potential archetypes to visit.
@@ -3748,16 +3760,24 @@ void GenericSignatureBuilder::enumerateRequirements(llvm::function_ref<
3748
3760
if (archetype != archetype->getArchetypeAnchor (*this ))
3749
3761
continue ;
3750
3762
3763
+ auto equivClass = rep->getEquivalenceClassIfPresent ();
3764
+
3751
3765
// If we have a layout constraint, produce a layout requirement.
3752
- if (LayoutConstraint Layout = archetype->getLayout ()) {
3753
- f (RequirementKind::Layout, archetype, Layout,
3754
- archetype->getLayoutSource ());
3766
+ if (equivClass && equivClass->layout ) {
3767
+ // Find the best source among the constraints that describe the layout
3768
+ // of this type.
3769
+ auto bestSource = equivClass->layoutConstraints .front ().source ;
3770
+ for (const auto &constraint : equivClass->layoutConstraints ) {
3771
+ if (constraint.source ->compare (bestSource) < 0 )
3772
+ bestSource = constraint.source ;
3773
+ }
3774
+
3775
+ f (RequirementKind::Layout, archetype, equivClass->layout , bestSource);
3755
3776
}
3756
3777
3757
3778
// Enumerate conformance requirements.
3758
3779
SmallVector<ProtocolDecl *, 4 > protocols;
3759
3780
DenseMap<ProtocolDecl *, const RequirementSource *> protocolSources;
3760
- auto equivClass = rep->getEquivalenceClassIfPresent ();
3761
3781
if (equivClass) {
3762
3782
for (const auto &conforms : equivClass->conformsTo ) {
3763
3783
protocols.push_back (conforms.first );
0 commit comments