@@ -1469,6 +1469,16 @@ SourceLoc RequirementSource::getLoc() const {
1469
1469
return SourceLoc ();
1470
1470
}
1471
1471
1472
+ SourceRange RequirementSource::getSourceRange () const {
1473
+ if (auto requirementRepr = getRequirementRepr ())
1474
+ return requirementRepr->getSourceRange ();
1475
+
1476
+ if (auto *typeRepr = getTypeRepr ())
1477
+ return typeRepr->getSourceRange ();
1478
+
1479
+ return SourceRange ();
1480
+ }
1481
+
1472
1482
// / Compute the path length of a requirement source, counting only the number
1473
1483
// / of \c ProtocolRequirement elements.
1474
1484
static unsigned sourcePathLength (const RequirementSource *source) {
@@ -1697,6 +1707,25 @@ SourceLoc FloatingRequirementSource::getLoc() const {
1697
1707
return SourceLoc ();
1698
1708
}
1699
1709
1710
+ SourceRange FloatingRequirementSource::getSourceRange () const {
1711
+ // If this is a source for a protocol requirement, get the source range
1712
+ // for that requirement.
1713
+ if (kind == Kind::AbstractProtocol)
1714
+ if (auto *written = protocolReq.written .dyn_cast <const RequirementRepr *>())
1715
+ return written->getSourceRange ();
1716
+
1717
+ if (auto *requirement = storage.dyn_cast <const RequirementRepr *>())
1718
+ return requirement->getSourceRange ();
1719
+
1720
+ if (auto *source = storage.dyn_cast <const RequirementSource *>())
1721
+ return source->getSourceRange ();
1722
+
1723
+ if (auto *typeRepr = storage.dyn_cast <const TypeRepr *>())
1724
+ return typeRepr->getSourceRange ();
1725
+
1726
+ return SourceRange ();
1727
+ }
1728
+
1700
1729
bool FloatingRequirementSource::isExplicit () const {
1701
1730
switch (kind) {
1702
1731
case Explicit:
@@ -4146,20 +4175,29 @@ static ConstraintResult visitInherited(
4146
4175
llvm::function_ref<ConstraintResult(Type, const TypeRepr *)> visitType) {
4147
4176
// Local function that (recursively) adds inherited types.
4148
4177
ConstraintResult result = ConstraintResult::Resolved;
4149
- std::function<void (Type, const TypeRepr *)> visitInherited;
4150
-
4151
- visitInherited = [&](Type inheritedType, const TypeRepr *typeRepr) {
4152
- // Decompose explicitly-written protocol compositions.
4153
- if (auto composition = dyn_cast_or_null<CompositionTypeRepr>(typeRepr)) {
4154
- if (auto compositionType
4155
- = inheritedType->getAs <ProtocolCompositionType>()) {
4156
- unsigned index = 0 ;
4157
- for (auto memberType : compositionType->getMembers ()) {
4158
- visitInherited (memberType, composition->getTypes ()[index]);
4159
- index++;
4160
- }
4178
+ std::function<void (Type, const TypeRepr *, bool )> visitInherited;
4161
4179
4162
- return ;
4180
+ auto typeDecl = decl.dyn_cast <TypeDecl *>();
4181
+ auto extDecl = decl.dyn_cast <ExtensionDecl *>();
4182
+ auto &ctx = typeDecl ? typeDecl->getASTContext () : extDecl->getASTContext ();
4183
+
4184
+ visitInherited = [&](Type inheritedType, const TypeRepr *typeRepr,
4185
+ bool skipDecomposition) {
4186
+ if (!skipDecomposition) {
4187
+ // Decompose explicitly-written protocol compositions.
4188
+ if (auto composition = dyn_cast_or_null<CompositionTypeRepr>(typeRepr)) {
4189
+ if (auto compositionType =
4190
+ inheritedType->getAs <ProtocolCompositionType>()) {
4191
+
4192
+ unsigned index = 0 ;
4193
+ for (auto memberType : compositionType->getMembers ()) {
4194
+ visitInherited (memberType, composition->getTypes ()[index],
4195
+ skipDecomposition);
4196
+ index++;
4197
+ }
4198
+
4199
+ return ;
4200
+ }
4163
4201
}
4164
4202
}
4165
4203
@@ -4169,17 +4207,27 @@ static ConstraintResult visitInherited(
4169
4207
};
4170
4208
4171
4209
// Visit all of the inherited types.
4172
- auto typeDecl = decl.dyn_cast <TypeDecl *>();
4173
- auto extDecl = decl.dyn_cast <ExtensionDecl *>();
4174
4210
ArrayRef<TypeLoc> inheritedTypes = typeDecl ? typeDecl->getInherited ()
4175
4211
: extDecl->getInherited ();
4176
4212
for (unsigned index : indices (inheritedTypes)) {
4177
4213
Type inheritedType = typeDecl ? typeDecl->getInheritedType (index)
4178
4214
: extDecl->getInheritedType (index);
4179
4215
if (!inheritedType) continue ;
4180
4216
4217
+ // If the inherited type is 'Any', allow it to pass through verbatim, as
4218
+ // GSB diagnoses redundant 'Any' constraints. The reason we do this check
4219
+ // here instead of inside visitInherited is in order to avoid diagnosing on
4220
+ // constraints such as ': Any & P'. This is because:
4221
+ // - 1: It preserves parity with the behaviour for protocol composition
4222
+ // constraints that appear in 'where' clauses (which aren't decomposed until
4223
+ // after the redundant 'Any' diagnostic).
4224
+ // - 2: The diagnosis of 'Any & ...' protocol composititions is better done
4225
+ // as a separate broader diagnostic that warns on the usage of such
4226
+ // compositions anywhere, not just in constraints.
4227
+ bool skipDecomposition = inheritedType->isEqual (ctx.TheAnyType );
4228
+
4181
4229
const auto &inherited = inheritedTypes[index];
4182
- visitInherited (inheritedType, inherited.getTypeRepr ());
4230
+ visitInherited (inheritedType, inherited.getTypeRepr (), skipDecomposition );
4183
4231
}
4184
4232
4185
4233
return result;
@@ -4711,14 +4759,19 @@ ConstraintResult GenericSignatureBuilder::addTypeRequirement(
4711
4759
assert (constraintType && " No type to express resolved constraint?" );
4712
4760
}
4713
4761
4762
+ auto getSubjectInterfaceTy = [&] {
4763
+ if (auto subjectType = subject.dyn_cast <Type>())
4764
+ return subjectType;
4765
+
4766
+ return subject.get <PotentialArchetype *>()->getDependentType (
4767
+ getGenericParams ());
4768
+ };
4769
+
4714
4770
// Check whether we have a reasonable constraint type at all.
4715
4771
if (!constraintType->isExistentialType () &&
4716
4772
!constraintType->getClassOrBoundGenericClass ()) {
4717
4773
if (source.getLoc ().isValid () && !constraintType->hasError ()) {
4718
- auto subjectType = subject.dyn_cast <Type>();
4719
- if (!subjectType)
4720
- subjectType = subject.get <PotentialArchetype *>()
4721
- ->getDependentType (getGenericParams ());
4774
+ auto subjectType = getSubjectInterfaceTy ();
4722
4775
4723
4776
Impl->HadAnyError = true ;
4724
4777
Diags.diagnose (source.getLoc (), diag::requires_conformance_nonprotocol,
@@ -4780,6 +4833,18 @@ ConstraintResult GenericSignatureBuilder::addTypeRequirement(
4780
4833
return ConstraintResult::Resolved;
4781
4834
}
4782
4835
4836
+ // An explicit 'Any' constraint is redundant.
4837
+ if (source.isExplicit () && constraintType->isEqual (Context.TheAnyType )) {
4838
+ auto subjectType = getSubjectInterfaceTy ();
4839
+ SourceLoc diagLoc = source.getLoc ();
4840
+
4841
+ Diags.diagnose (diagLoc, diag::redundant_conformance_constraint,
4842
+ subjectType, constraintType)
4843
+ .highlight (source.getSourceRange ());
4844
+ Diags.diagnose (diagLoc, diag::all_types_implicitly_conform_to,
4845
+ constraintType);
4846
+ }
4847
+
4783
4848
// Protocol requirements.
4784
4849
if (constraintType->isExistentialType ()) {
4785
4850
bool anyErrors = false ;
0 commit comments