Skip to content

Commit 7926880

Browse files
authored
Merge pull request swiftlang#30427 from CodaFi/an-enumeration-of-grievances
Do a little extra validation of RawRepresentable.RawValue
2 parents a1fdad7 + 2966a38 commit 7926880

File tree

3 files changed

+65
-2
lines changed

3 files changed

+65
-2
lines changed

lib/Sema/DerivedConformanceRawRepresentable.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,22 @@ bool DerivedConformance::canDeriveRawRepresentable(DeclContext *DC,
466466
if (TypeChecker::conformsToProtocol(rawType, equatableProto, DC, None)
467467
.isInvalid())
468468
return false;
469-
469+
470+
auto &C = type->getASTContext();
471+
auto rawValueDecls = enumDecl->lookupDirect(DeclName(C.Id_RawValue));
472+
if (rawValueDecls.size() > 1)
473+
return false;
474+
475+
// Check that the RawValue matches the expected raw type.
476+
if (!rawValueDecls.empty()) {
477+
if (auto alias = dyn_cast<TypeDecl>(rawValueDecls.front())) {
478+
auto ty = alias->getDeclaredInterfaceType();
479+
if (!DC->mapTypeIntoContext(ty)->isEqual(rawType)) {
480+
return false;
481+
}
482+
}
483+
}
484+
470485
// There must be enum elements.
471486
if (enumDecl->getAllElements().empty())
472487
return false;

lib/Sema/TypeCheckDecl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,10 @@ EnumRawValuesRequest::evaluate(Evaluator &eval, EnumDecl *ED,
981981
return true;
982982
}
983983

984+
if (!computeAutomaticEnumValueKind(ED)) {
985+
return true;
986+
}
987+
984988
if (ED->getGenericEnvironmentOfContext() != nullptr)
985989
rawTy = ED->mapTypeIntoContext(rawTy);
986990
if (rawTy->hasError())

test/Sema/enum_raw_representable.swift

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,4 +228,48 @@ enum NotEquatableRawType3: NotEquatableString {
228228
// expected-note@-1 {{candidate has non-matching type '(rawValue: Int)'}}
229229
var rawValue: Int { 0 }
230230
// expected-note@-1 {{candidate has non-matching type 'Int'}}
231-
}
231+
}
232+
233+
enum MismatchedRawValues {
234+
enum ExistentialBound: Any? {
235+
// expected-error@-1 {{raw type 'Any?' is not expressible}}
236+
// expected-error@-2 {{'MismatchedRawValues.ExistentialBound' declares raw type 'Any?'}}
237+
// expected-error@-3 {{RawRepresentable conformance cannot be synthesized }}
238+
case test = nil
239+
}
240+
241+
public enum StringViaStaticString: StaticString {
242+
// expected-error@-1 {{'MismatchedRawValues.StringViaStaticString' declares raw type 'StaticString', but does not conform to RawRepresentable}}
243+
// expected-error@-2 {{RawRepresentable conformance cannot be synthesized because}}
244+
public typealias RawValue = String
245+
246+
case TRUE = "TRUE"
247+
case FALSE = "FALSE"
248+
}
249+
250+
public enum IntViaString: String {
251+
// expected-error@-1 {{'MismatchedRawValues.IntViaString' declares raw type 'String', but does not conform to RawRepresentable}}
252+
public typealias RawValue = Int
253+
254+
case TRUE = "TRUE"
255+
case FALSE = "FALSE"
256+
}
257+
258+
public enum ViaNested: String {
259+
// expected-error@-1 {{'MismatchedRawValues.ViaNested' declares raw type 'String', but does not conform to RawRepresentable}}
260+
struct RawValue: Equatable {
261+
let x: String
262+
}
263+
264+
case TRUE = "TRUE"
265+
case FALSE = "FALSE"
266+
}
267+
268+
public enum ViaGenericBound<RawValue: Equatable>: String {
269+
// expected-error@-1 {{'MismatchedRawValues.ViaGenericBound<RawValue>' declares raw type 'String'}}
270+
typealias RawValue = RawValue
271+
case TRUE = "TRUE"
272+
case FALSE = "FALSE"
273+
}
274+
}
275+

0 commit comments

Comments
 (0)