Merge pull request #7361 from jckarter/raw-rep-synthesized-conformance-3.1
[3.1] Sema: Treat the implicit RawRepresentable conformance for enums as `Synthesized` again.
diff --git a/lib/AST/ConformanceLookupTable.cpp b/lib/AST/ConformanceLookupTable.cpp
index fdf0b67..7e393dd 100644
--- a/lib/AST/ConformanceLookupTable.cpp
+++ b/lib/AST/ConformanceLookupTable.cpp
@@ -858,7 +858,8 @@
}
void ConformanceLookupTable::registerProtocolConformance(
- ProtocolConformance *conformance) {
+ ProtocolConformance *conformance,
+ bool synthesized) {
auto protocol = conformance->getProtocol();
auto dc = conformance->getDeclContext();
auto nominal = dc->getAsNominalTypeOrNominalTypeExtensionContext();
@@ -878,8 +879,9 @@
// Otherwise, add a new entry.
auto inherited = dyn_cast<InheritedProtocolConformance>(conformance);
ConformanceSource source
- = inherited ? ConformanceSource::forInherited(cast<ClassDecl>(nominal))
- : ConformanceSource::forExplicit(dc);
+ = inherited ? ConformanceSource::forInherited(cast<ClassDecl>(nominal)) :
+ synthesized ? ConformanceSource::forSynthesized(nominal) :
+ ConformanceSource::forExplicit(dc);
ASTContext &ctx = nominal->getASTContext();
ConformanceEntry *entry = new (ctx) ConformanceEntry(SourceLoc(),
diff --git a/lib/AST/ConformanceLookupTable.h b/lib/AST/ConformanceLookupTable.h
index e9a8bb2..cb58319 100644
--- a/lib/AST/ConformanceLookupTable.h
+++ b/lib/AST/ConformanceLookupTable.h
@@ -439,7 +439,8 @@
ProtocolDecl *protocol);
/// Register an externally-supplied protocol conformance.
- void registerProtocolConformance(ProtocolConformance *conformance);
+ void registerProtocolConformance(ProtocolConformance *conformance,
+ bool synthesized = false);
/// Look for conformances to the given protocol.
///
diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp
index a2fd35f..3bb2ffb 100644
--- a/lib/AST/ProtocolConformance.cpp
+++ b/lib/AST/ProtocolConformance.cpp
@@ -628,14 +628,10 @@
if (resolver)
resolver->resolveRawType(theEnum);
if (theEnum->hasRawType()) {
- if (auto rawRepresentable = ctx.getProtocol(KnownProtocolKind::RawRepresentable)) {
-
- // The presence of a raw type is an explicit declaration that
- // the compiler should derive a RawRepresentable conformance.
- auto conformance = ctx.getConformance(mutableThis->getDeclaredTypeInContext(), rawRepresentable,
- mutableThis->getNameLoc(), mutableThis->getInnermostDeclContext(),
- ProtocolConformanceState::Incomplete);
- ConformanceTable->registerProtocolConformance(conformance);
+ if (auto rawRepresentable =
+ ctx.getProtocol(KnownProtocolKind::RawRepresentable)) {
+ ConformanceTable->addSynthesizedConformance(mutableThis,
+ rawRepresentable);
}
}
}
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 7937dec..8acfaad 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -2789,6 +2789,10 @@
llvm::SmallDenseMap<RawValueKey, RawValueSource, 8> uniqueRawValues;
for (auto elt : ED->getAllElements()) {
+ // Skip if the raw value expr has already been checked.
+ if (elt->getTypeCheckedRawValueExpr())
+ continue;
+
// Make sure the element is checked out before we poke at it.
TC.validateDecl(elt);
@@ -6298,6 +6302,12 @@
if (auto extendedTy = ED->getExtendedType()) {
if (auto nominal = extendedTy->getAnyNominal()) {
TC.validateDecl(nominal);
+ // Check the raw values of an enum, since we might synthesize
+ // RawRepresentable while checking conformances on this extension.
+ if (auto enumDecl = dyn_cast<EnumDecl>(nominal)) {
+ if (enumDecl->hasRawType())
+ checkEnumRawValues(TC, enumDecl);
+ }
}
}
@@ -7454,7 +7464,7 @@
ext->setGenericEnvironment(env);
return;
}
-
+
// If we're extending a protocol, check the generic parameters.
//
// Canonicalize the type to work around the fact that getAs<> cannot
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index 35c2a21..c40f584 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -5491,9 +5491,10 @@
// Special case: explain that 'RawRepresentable' conformance
// is implied for enums which already declare a raw type.
if (auto enumDecl = dyn_cast<EnumDecl>(existingDecl)) {
- if (diag.Protocol->isSpecificProtocol(KnownProtocolKind::RawRepresentable) &&
- enumDecl->derivesProtocolConformance(diag.Protocol) &&
- enumDecl->hasRawType()) {
+ if (diag.Protocol->isSpecificProtocol(KnownProtocolKind::RawRepresentable)
+ && enumDecl->derivesProtocolConformance(diag.Protocol)
+ && enumDecl->hasRawType()
+ && enumDecl->getInherited()[0].getSourceRange().isValid()) {
diagnose(enumDecl->getInherited()[0].getSourceRange().Start,
diag::enum_declares_rawrep_with_raw_type,
dc->getDeclaredInterfaceType(), enumDecl->getRawType());
diff --git a/test/Sema/Inputs/enum_raw_representable_explicit_multi_file_2.swift b/test/Sema/Inputs/enum_raw_representable_explicit_multi_file_2.swift
new file mode 100644
index 0000000..6ff4164
--- /dev/null
+++ b/test/Sema/Inputs/enum_raw_representable_explicit_multi_file_2.swift
@@ -0,0 +1,8 @@
+
+extension Foo: RawRepresentable {}
+
+enum Bar: Int { case A }
+
+// expected-error@+1{{redundant conformance of 'Bas' to protocol 'RawRepresentable'}}
+extension Bas: RawRepresentable {}
+
diff --git a/test/Sema/Inputs/enum_with_raw_type.swift b/test/Sema/Inputs/enum_with_raw_type.swift
new file mode 100644
index 0000000..9ad55e1
--- /dev/null
+++ b/test/Sema/Inputs/enum_with_raw_type.swift
@@ -0,0 +1 @@
+public enum Foo: Int { case A }
diff --git a/test/Sema/enum_post_hoc_raw_representable_with_raw_type.swift b/test/Sema/enum_post_hoc_raw_representable_with_raw_type.swift
new file mode 100644
index 0000000..9d8f407
--- /dev/null
+++ b/test/Sema/enum_post_hoc_raw_representable_with_raw_type.swift
@@ -0,0 +1,9 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: %target-swift-frontend -emit-module -o %t/enum_with_raw_type.swiftmodule %S/Inputs/enum_with_raw_type.swift
+// RUN: %target-swift-frontend -I %t -typecheck -verify %s
+
+import enum_with_raw_type
+
+// expected-error@+1{{redundant conformance of 'Foo' to protocol 'RawRepresentable'}}
+extension Foo: RawRepresentable {}
diff --git a/test/Sema/enum_raw_representable_explicit.swift b/test/Sema/enum_raw_representable_explicit.swift
new file mode 100644
index 0000000..d06108e
--- /dev/null
+++ b/test/Sema/enum_raw_representable_explicit.swift
@@ -0,0 +1,15 @@
+// RUN: %target-swift-frontend -typecheck -verify %s
+
+enum Foo: Int, RawRepresentable { case A }
+
+enum Bar: Int { case A }
+
+extension Bar: RawRepresentable {}
+
+enum Bas: Int { case A }
+
+// expected-note@+1{{'Bas' declares conformance to protocol 'RawRepresentable' here}}
+extension Bas: RawRepresentable {}
+
+// expected-error@+1{{redundant conformance of 'Bas' to protocol 'RawRepresentable'}}
+extension Bas: RawRepresentable {}
diff --git a/test/Sema/enum_raw_representable_explicit_cart_before_horse.swift b/test/Sema/enum_raw_representable_explicit_cart_before_horse.swift
new file mode 100644
index 0000000..09d6ed5
--- /dev/null
+++ b/test/Sema/enum_raw_representable_explicit_cart_before_horse.swift
@@ -0,0 +1,4 @@
+// RUN: %target-swift-frontend -typecheck -verify %s
+
+enum Foo: Int { case A }
+extension Foo: RawRepresentable {}
diff --git a/test/Sema/enum_raw_representable_explicit_multi_file.swift b/test/Sema/enum_raw_representable_explicit_multi_file.swift
new file mode 100644
index 0000000..c16a4f4
--- /dev/null
+++ b/test/Sema/enum_raw_representable_explicit_multi_file.swift
@@ -0,0 +1,10 @@
+// RUN: %target-swift-frontend -typecheck -primary-file %s %S/Inputs/enum_raw_representable_explicit_multi_file_2.swift
+// RUN: %target-swift-frontend -typecheck -verify %s -primary-file %S/Inputs/enum_raw_representable_explicit_multi_file_2.swift
+
+enum Foo: Int { case A }
+
+extension Bar: RawRepresentable {}
+
+enum Bas: Int { case A }
+// expected-note@+1 {{'Bas' declares conformance to protocol 'RawRepresentable' here}}
+extension Bas: RawRepresentable {}
diff --git a/test/decl/protocol/conforms/Inputs/placement_2.swift b/test/decl/protocol/conforms/Inputs/placement_2.swift
index 7c201f1..0e02c9e 100644
--- a/test/decl/protocol/conforms/Inputs/placement_2.swift
+++ b/test/decl/protocol/conforms/Inputs/placement_2.swift
@@ -39,6 +39,6 @@
extension MFSynthesizedSubClass4 : AnyObjectRefinement { }
-enum MFSynthesizedEnum1 : Int { case a } // expected-note {{'MFSynthesizedEnum1' declares raw type 'Int', which implies RawRepresentable}}
+enum MFSynthesizedEnum1 : Int { case a }
extension MFSynthesizedEnum2 : RawRepresentable { }
diff --git a/test/decl/protocol/conforms/placement.swift b/test/decl/protocol/conforms/placement.swift
index bd749ca..bf5434e 100644
--- a/test/decl/protocol/conforms/placement.swift
+++ b/test/decl/protocol/conforms/placement.swift
@@ -127,10 +127,10 @@
class SynthesizedSubClass4 : SynthesizedClass2 { }
extension SynthesizedSubClass4 : AnyObjectRefinement { }
-enum SynthesizedEnum1 : Int, RawRepresentable { case none = 0 } // expected-error{{redundant conformance of 'SynthesizedEnum1' to protocol 'RawRepresentable'}} expected-note{{'SynthesizedEnum1' declares raw type 'Int', which implies RawRepresentable}}
+enum SynthesizedEnum1 : Int, RawRepresentable { case none = 0 }
-enum SynthesizedEnum2 : Int { case none = 0 } // expected-note {{'SynthesizedEnum2' declares raw type 'Int', which implies RawRepresentable}}
-extension SynthesizedEnum2 : RawRepresentable { } // expected-error{{redundant conformance of 'SynthesizedEnum2' to protocol 'RawRepresentable'}}
+enum SynthesizedEnum2 : Int { case none = 0 }
+extension SynthesizedEnum2 : RawRepresentable { }
// ===========================================================================
@@ -182,7 +182,7 @@
class MFSynthesizedSubClass4 : MFSynthesizedClass2 { }
-extension MFSynthesizedEnum1 : RawRepresentable { } // expected-error{{redundant conformance of 'MFSynthesizedEnum1' to protocol 'RawRepresentable'}}
+extension MFSynthesizedEnum1 : RawRepresentable { }
enum MFSynthesizedEnum2 : Int { case none = 0 }