Skip to content

Commit c47aea7

Browse files
committed
[GSB] Cope with typealiases within protocol hierarchies.
When we see two type(aliase)s with the same name in a protocol hierarchy, make them equal with an implied same-type requirement. This detects inconstencies in typealiases across different protocols, and eliminates the need for ad hoc consistency checking. This is a step toward simplifying away the need for direct-diagnosis operations involving concrete type mismatches. While here, warn when we see an associated type with the same as a typealias from an inherited protocol; in this case, the associated type is basically useless, because it's going to be equivalent to the typealias.
1 parent b51529f commit c47aea7

File tree

5 files changed

+40
-39
lines changed

5 files changed

+40
-39
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1680,9 +1680,6 @@ ERROR(requires_generic_param_same_type_does_not_conform,none,
16801680
(Type, Identifier))
16811681
ERROR(requires_same_concrete_type,none,
16821682
"generic signature requires types %0 and %1 to be the same", (Type, Type))
1683-
ERROR(protocol_typealias_conflict, none,
1684-
"type alias %0 requires types %1 and %2 to be the same",
1685-
(Identifier, Type, Type))
16861683
WARNING(redundant_conformance_constraint,none,
16871684
"redundant conformance constraint %0: %1", (Type, ProtocolDecl *))
16881685
NOTE(redundant_conformance_here,none,
@@ -1733,6 +1730,9 @@ WARNING(inherited_associated_type_redecl,none,
17331730
WARNING(typealias_override_associated_type,none,
17341731
"typealias overriding associated type %0 from protocol %1 is better "
17351732
"expressed as same-type constraint on the protocol", (DeclName, Type))
1733+
WARNING(associated_type_override_typealias,none,
1734+
"associated type %0 is redundant with type %0 declared in inherited "
1735+
"%1 %2", (DeclName, DescriptiveDeclKind, Type))
17361736

17371737
ERROR(generic_param_access,none,
17381738
"%0 %select{must be declared %select{"

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,24 +1720,10 @@ PotentialArchetype *PotentialArchetype::getArchetypeAnchor(
17201720
}
17211721

17221722
namespace {
1723-
/// Function object to diagnose a conflict in same-type constraints for a
1724-
/// given potential archetype.
1725-
struct DiagnoseSameTypeConflict {
1726-
DiagnosticEngine &diags;
1727-
const RequirementSource *source;
1728-
PotentialArchetype *pa;
1729-
1730-
void operator()(Type type1, Type type2) const {
1731-
// FIXME: Shouldn't need this!
1732-
if (pa->getParent() && pa->getConcreteTypeDecl() &&
1733-
source->getLoc().isInvalid()) {
1734-
diags.diagnose(pa->getConcreteTypeDecl()->getLoc(),
1735-
diag::protocol_typealias_conflict,
1736-
pa->getConcreteTypeDecl()->getName(),
1737-
type1, type2);
1738-
return;
1739-
}
1740-
}
1723+
/// Function object used to suppress conflict diagnoses when we know we'll
1724+
/// see them again later.
1725+
struct SameTypeConflictCheckedLater {
1726+
void operator()(Type type1, Type type2) const { }
17411727
};
17421728
} // end anonymous namespace
17431729

@@ -1786,10 +1772,7 @@ static void concretizeNestedTypeFromConcreteParent(
17861772
builder.addSameTypeRequirement(
17871773
nestedPA, witnessType, source,
17881774
GenericSignatureBuilder::UnresolvedHandlingKind::GenerateConstraints,
1789-
DiagnoseSameTypeConflict{
1790-
builder.getASTContext().Diags,
1791-
source, nestedPA
1792-
});
1775+
SameTypeConflictCheckedLater());
17931776
}
17941777

17951778
PotentialArchetype *PotentialArchetype::getNestedType(
@@ -2855,7 +2838,20 @@ ConstraintResult GenericSignatureBuilder::addConformanceRequirement(
28552838
continue;
28562839
}
28572840

2858-
// FIXME: this is a weird situation.
2841+
// We inherited a type; this associated type will be identical
2842+
// to that typealias.
2843+
if (Source->kind == RequirementSource::RequirementSignatureSelf) {
2844+
auto inheritedOwningDecl =
2845+
inheritedType->getDeclContext()
2846+
->getAsNominalTypeOrNominalTypeExtensionContext();
2847+
Diags.diagnose(assocTypeDecl,
2848+
diag::associated_type_override_typealias,
2849+
assocTypeDecl->getFullName(),
2850+
inheritedOwningDecl->getDescriptiveKind(),
2851+
inheritedOwningDecl->getDeclaredInterfaceType());
2852+
}
2853+
2854+
addInferredSameTypeReq(assocTypeDecl, inheritedType);
28592855
}
28602856

28612857
inheritedTypeDecls.erase(knownInherited);
@@ -2898,7 +2894,8 @@ ConstraintResult GenericSignatureBuilder::addConformanceRequirement(
28982894
continue;
28992895
}
29002896

2901-
// FIXME: More typealiases
2897+
// Two typealiases that should be the same.
2898+
addInferredSameTypeReq(inheritedType, typealias);
29022899
}
29032900

29042901
inheritedTypeDecls.erase(knownInherited);
@@ -3371,7 +3368,7 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
33713368
(void)addSameTypeRequirement(equivClass->concreteType,
33723369
equivClass2->concreteType, Source,
33733370
UnresolvedHandlingKind::GenerateConstraints,
3374-
DiagnoseSameTypeConflict{Diags, Source, T1});
3371+
SameTypeConflictCheckedLater());
33753372
} else {
33763373
equivClass->concreteType = equivClass2->concreteType;
33773374
}
@@ -3466,7 +3463,7 @@ ConstraintResult GenericSignatureBuilder::addSameTypeRequirementToConcrete(
34663463
if (equivClass->concreteType) {
34673464
return addSameTypeRequirement(equivClass->concreteType, Concrete, Source,
34683465
UnresolvedHandlingKind::GenerateConstraints,
3469-
DiagnoseSameTypeConflict{ Diags, Source, T});
3466+
SameTypeConflictCheckedLater());
34703467

34713468
}
34723469

test/Generics/protocol_type_aliases.swift

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,21 +53,17 @@ func concreteRequirementOnConcreteNestedTypeAlias<T>(_: T) where T: Q2, S<T.C> =
5353

5454
// Incompatible concrete typealias types are flagged as such
5555
protocol P3 {
56-
typealias T = Int // expected-error{{type alias 'T' requires types 'Q3.T' (aka 'Float') and 'Int' to be the same}}
56+
typealias T = Int
5757
}
58-
protocol Q3: P3 {
58+
protocol Q3: P3 { // expected-error{{generic signature requires types 'Int'}}
5959
typealias T = Float
6060
}
6161

6262
protocol P3_1 {
63-
typealias T = Float // expected-error{{type alias 'T' requires types 'P3.T' (aka 'Int') and 'Float' to be the same}}
63+
typealias T = Float
6464
}
6565
protocol Q3_1: P3, P3_1 {} // expected-error{{generic signature requires types 'Float'}}
6666

67-
// FIXME: these shouldn't be necessary to trigger the errors above, but are, due to
68-
// the 'recursive decl validation' FIXME in GenericSignatureBuilder.cpp.
69-
func useTypealias<T: Q3>(_: T, _: T.T) {}
70-
func useTypealias1<T: Q3_1>(_: T, _: T.T) {}
7167

7268
// Subprotocols can force associated types in their parents to be concrete, and
7369
// this should be understood for types constrained by the subprotocols.
@@ -114,3 +110,11 @@ func checkQ6<T: Q6>(x: T.Type) {
114110
sameType(getP6_1_A(x), getP6_2_B(x))
115111
}
116112

113+
protocol P7 {
114+
typealias A = Int
115+
}
116+
117+
protocol P7a : P7 {
118+
associatedtype A // expected-warning{{associated type 'A' is redundant with type 'A' declared in inherited protocol 'P7'}}
119+
}
120+

test/attr/attr_specialize.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ struct FloatElement : HasElt {
8787
typealias Element = Float
8888
}
8989
@_specialize(where T == FloatElement)
90-
@_specialize(where T == IntElement) // expected-error{{associated type 'T.Element' cannot be equal to both 'Float' and 'Int'}}
90+
@_specialize(where T == IntElement) // expected-error{{'T.Element' cannot be equal to both 'IntElement.Element' (aka 'Int') and 'Float'}}
9191
func sameTypeRequirement<T : HasElt>(_ t: T) where T.Element == Float {}
9292

9393
@_specialize(where T == Sub)

validation-test/compiler_crashers_2_fixed/0042-rdar21775089.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ protocol MySequenceType {}
77
protocol MyIndexableType {}
88

99
protocol MyCollectionType : MySequenceType, MyIndexableType {
10-
typealias SubSequence = MySlice<Self>
10+
associatedtype SubSequence = MySlice<Self>
1111
func makeSubSequence() -> SubSequence
1212
}
1313
extension MyCollectionType {
@@ -18,7 +18,7 @@ extension MyCollectionType {
1818
}
1919

2020
protocol MyMutableCollectionType : MyCollectionType {
21-
typealias SubSequence = MyMutableSlice<Self>
21+
associatedtype SubSequence = MyMutableSlice<Self>
2222
}
2323
extension MyMutableCollectionType {
2424
func makeSubSequence() -> MyMutableSlice<Self> {

0 commit comments

Comments
 (0)