mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Revert "Sema: Make derived conformances work from extensions"
Speculatively revert; this looks like it is breaking the iOS bots. Swift SVN r28963
This commit is contained in:
@@ -38,7 +38,6 @@ namespace swift {
|
||||
class CanType;
|
||||
class Decl;
|
||||
class DeclContext;
|
||||
class EnumDecl;
|
||||
class ExtensionDecl;
|
||||
class Expr;
|
||||
class GenericParamList;
|
||||
@@ -245,10 +244,6 @@ public:
|
||||
/// ClassDecl, otherwise return null.
|
||||
ClassDecl *isClassOrClassExtensionContext() const;
|
||||
|
||||
/// If this DeclContext is a enum, or an extension on a enum, return the
|
||||
/// EnumDecl, otherwise return null.
|
||||
EnumDecl *isEnumOrEnumExtensionContext() const;
|
||||
|
||||
/// If this DeclContext is a protocol, or an extension on a
|
||||
/// protocol, return the ProtocolDecl, otherwise return null.
|
||||
ProtocolDecl *isProtocolOrProtocolExtensionContext() const;
|
||||
|
||||
@@ -1142,9 +1142,6 @@ NOTE(enum_raw_value_incrementing_from_here,sema_tcd,none,
|
||||
"raw value auto-incremented from here",())
|
||||
NOTE(enum_raw_value_incrementing_from_zero,sema_tcd,none,
|
||||
"raw value implicitly auto-incremented from zero",())
|
||||
|
||||
// Derived conformances
|
||||
|
||||
ERROR(broken_raw_representable_requirement,sema_tcd,none,
|
||||
"RawRepresentable protocol is broken: unexpected requirement", ())
|
||||
ERROR(broken_equatable_requirement,sema_tcd,none,
|
||||
|
||||
@@ -74,11 +74,6 @@ ClassDecl *DeclContext::isClassOrClassExtensionContext() const {
|
||||
isNominalTypeOrNominalTypeExtensionContext());
|
||||
}
|
||||
|
||||
EnumDecl *DeclContext::isEnumOrEnumExtensionContext() const {
|
||||
return dyn_cast_or_null<EnumDecl>(
|
||||
isNominalTypeOrNominalTypeExtensionContext());
|
||||
}
|
||||
|
||||
ProtocolDecl *DeclContext::isProtocolOrProtocolExtensionContext() const {
|
||||
return dyn_cast_or_null<ProtocolDecl>(
|
||||
isNominalTypeOrNominalTypeExtensionContext());
|
||||
|
||||
@@ -48,20 +48,18 @@ static bool canDeriveConformance(NominalTypeDecl *type) {
|
||||
|
||||
/// Create AST statements which convert from an enum to an Int with a switch.
|
||||
/// \p stmts The generated statements are appended to this vector.
|
||||
/// \p parentDC Either an extension or the enum itself.
|
||||
/// \p enumDecl The enum declaration.
|
||||
/// \p enumVarDecl The enum input variable.
|
||||
/// \p funcDecl The parent function.
|
||||
/// \p indexName The name of the output variable.
|
||||
/// \return A DeclRefExpr of the output variable (of type Int).
|
||||
static DeclRefExpr *convertEnumToIndex(SmallVectorImpl<ASTNode> &stmts,
|
||||
DeclContext *parentDC,
|
||||
EnumDecl *enumDecl,
|
||||
VarDecl *enumVarDecl,
|
||||
AbstractFunctionDecl *funcDecl,
|
||||
const char *indexName) {
|
||||
ASTContext &C = enumDecl->getASTContext();
|
||||
Type enumType = enumVarDecl->getType();
|
||||
auto enumType = enumDecl->getDeclaredTypeInContext();
|
||||
Type intType = C.getIntDecl()->getDeclaredType();
|
||||
|
||||
auto indexVar = new (C) VarDecl(/*static*/false, /*let*/false,
|
||||
@@ -125,9 +123,6 @@ static DeclRefExpr *convertEnumToIndex(SmallVectorImpl<ASTNode> &stmts,
|
||||
|
||||
/// Derive the body for an '==' operator for an enum
|
||||
static void deriveBodyEquatable_enum_eq(AbstractFunctionDecl *eqDecl) {
|
||||
auto parentDC = eqDecl->getDeclContext();
|
||||
ASTContext &C = parentDC->getASTContext();
|
||||
|
||||
auto args = cast<TuplePattern>(eqDecl->getBodyParamPatterns().back());
|
||||
auto aPattern = args->getElement(0).getPattern();
|
||||
auto aParamPattern =
|
||||
@@ -138,16 +133,16 @@ static void deriveBodyEquatable_enum_eq(AbstractFunctionDecl *eqDecl) {
|
||||
cast<NamedPattern>(bPattern->getSemanticsProvidingPattern());
|
||||
auto bParam = bParamPattern->getDecl();
|
||||
|
||||
CanType boolTy = C.getBoolDecl()->getDeclaredType().getCanonicalTypeOrNull();
|
||||
|
||||
auto enumDecl = cast<EnumDecl>(aParam->getType()->getAnyNominal());
|
||||
ASTContext &C = enumDecl->getASTContext();
|
||||
CanType boolTy = C.getBoolDecl()->getDeclaredType().getCanonicalTypeOrNull();
|
||||
|
||||
// Generate the conversion from the enums to integer indices.
|
||||
SmallVector<ASTNode, 6> statements;
|
||||
DeclRefExpr *aIndex = convertEnumToIndex(statements, parentDC, enumDecl,
|
||||
aParam, eqDecl, "index_a");
|
||||
DeclRefExpr *bIndex = convertEnumToIndex(statements, parentDC, enumDecl,
|
||||
bParam, eqDecl, "index_b");
|
||||
DeclRefExpr *aIndex = convertEnumToIndex(statements, enumDecl, aParam, eqDecl,
|
||||
"index_a");
|
||||
DeclRefExpr *bIndex = convertEnumToIndex(statements, enumDecl, bParam, eqDecl,
|
||||
"index_b");
|
||||
|
||||
// Generate the compare of the indices.
|
||||
FuncDecl *cmpFunc = C.getEqualIntDecl(nullptr);
|
||||
@@ -174,7 +169,7 @@ static void deriveBodyEquatable_enum_eq(AbstractFunctionDecl *eqDecl) {
|
||||
|
||||
/// Derive an '==' operator implementation for an enum.
|
||||
static ValueDecl *
|
||||
deriveEquatable_enum_eq(TypeChecker &tc, Decl *parentDecl, EnumDecl *enumDecl) {
|
||||
deriveEquatable_enum_eq(TypeChecker &tc, EnumDecl *enumDecl) {
|
||||
// enum SomeEnum<T...> {
|
||||
// case A, B, C
|
||||
// }
|
||||
@@ -197,8 +192,7 @@ deriveEquatable_enum_eq(TypeChecker &tc, Decl *parentDecl, EnumDecl *enumDecl) {
|
||||
|
||||
ASTContext &C = tc.Context;
|
||||
|
||||
auto parentDC = cast<DeclContext>(parentDecl);
|
||||
auto enumTy = parentDC->getDeclaredTypeInContext();
|
||||
auto enumTy = enumDecl->getDeclaredTypeInContext();
|
||||
|
||||
auto getParamPattern = [&](StringRef s) -> std::pair<VarDecl*, Pattern*> {
|
||||
VarDecl *aDecl = new (C) ParamDecl(/*isLet*/ true,
|
||||
@@ -207,7 +201,7 @@ deriveEquatable_enum_eq(TypeChecker &tc, Decl *parentDecl, EnumDecl *enumDecl) {
|
||||
SourceLoc(),
|
||||
C.getIdentifier(s),
|
||||
enumTy,
|
||||
parentDC);
|
||||
enumDecl);
|
||||
aDecl->setImplicit();
|
||||
Pattern *aParam = new (C) NamedPattern(aDecl, /*implicit*/ true);
|
||||
aParam->setType(enumTy);
|
||||
@@ -235,12 +229,10 @@ deriveEquatable_enum_eq(TypeChecker &tc, Decl *parentDecl, EnumDecl *enumDecl) {
|
||||
params->setImplicit();
|
||||
params->setType(paramsTy);
|
||||
|
||||
auto genericParams = parentDC->getGenericParamsOfContext();
|
||||
auto genericParams = enumDecl->getGenericParamsOfContext();
|
||||
|
||||
auto boolTy = C.getBoolDecl()->getDeclaredType();
|
||||
|
||||
auto moduleDC = parentDecl->getModuleContext();
|
||||
|
||||
DeclName name(C, C.Id_EqualsOperator, { Identifier(), Identifier() });
|
||||
auto eqDecl = FuncDecl::create(C, SourceLoc(), StaticSpellingKind::None,
|
||||
SourceLoc(), name,
|
||||
@@ -248,17 +240,17 @@ deriveEquatable_enum_eq(TypeChecker &tc, Decl *parentDecl, EnumDecl *enumDecl) {
|
||||
genericParams,
|
||||
Type(), params,
|
||||
TypeLoc::withoutLoc(boolTy),
|
||||
&moduleDC->getDerivedFileUnit());
|
||||
&enumDecl->getModuleContext()->getDerivedFileUnit());
|
||||
eqDecl->setImplicit();
|
||||
eqDecl->getAttrs().add(new (C) InfixAttr(/*implicit*/false));
|
||||
auto op = C.getStdlibModule()->lookupInfixOperator(C.Id_EqualsOperator);
|
||||
if (!op) {
|
||||
tc.diagnose(parentDecl->getLoc(),
|
||||
tc.diagnose(enumDecl->getLoc(),
|
||||
diag::broken_equatable_eq_operator);
|
||||
return nullptr;
|
||||
}
|
||||
if (!C.getEqualIntDecl(nullptr)) {
|
||||
tc.diagnose(parentDecl->getLoc(), diag::no_equal_overload_for_int);
|
||||
tc.diagnose(enumDecl->getLoc(), diag::no_equal_overload_for_int);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -271,14 +263,14 @@ deriveEquatable_enum_eq(TypeChecker &tc, Decl *parentDecl, EnumDecl *enumDecl) {
|
||||
if (genericParams) {
|
||||
fnTy = PolymorphicFunctionType::get(paramsTy, boolTy, genericParams);
|
||||
|
||||
auto enumIfaceTy = parentDC->getDeclaredInterfaceType();
|
||||
auto enumIfaceTy = enumDecl->getDeclaredInterfaceType();
|
||||
TupleTypeElt ifaceParamElts[] = {
|
||||
enumIfaceTy, enumIfaceTy,
|
||||
};
|
||||
auto ifaceParamsTy = TupleType::get(ifaceParamElts, C);
|
||||
|
||||
interfaceTy = GenericFunctionType::get(
|
||||
parentDC->getGenericSignatureOfContext(),
|
||||
enumDecl->getGenericSignatureOfContext(),
|
||||
ifaceParamsTy, boolTy,
|
||||
AnyFunctionType::ExtInfo());
|
||||
} else {
|
||||
@@ -296,11 +288,10 @@ deriveEquatable_enum_eq(TypeChecker &tc, Decl *parentDecl, EnumDecl *enumDecl) {
|
||||
tc.implicitlyDefinedFunctions.push_back(eqDecl);
|
||||
|
||||
// Since it's an operator we insert the decl after the type at global scope.
|
||||
return insertOperatorDecl(C, cast<IterableDeclContext>(parentDecl), eqDecl);
|
||||
return insertOperatorDecl(C, enumDecl, eqDecl);
|
||||
}
|
||||
|
||||
ValueDecl *DerivedConformance::deriveEquatable(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
NominalTypeDecl *type,
|
||||
ValueDecl *requirement) {
|
||||
// Check that we can actually derive Equatable for this type.
|
||||
@@ -310,7 +301,7 @@ ValueDecl *DerivedConformance::deriveEquatable(TypeChecker &tc,
|
||||
// Build the necessary decl.
|
||||
if (requirement->getName().str() == "==") {
|
||||
if (auto theEnum = dyn_cast<EnumDecl>(type))
|
||||
return deriveEquatable_enum_eq(tc, parentDecl, theEnum);
|
||||
return deriveEquatable_enum_eq(tc, theEnum);
|
||||
else
|
||||
llvm_unreachable("todo");
|
||||
}
|
||||
@@ -321,10 +312,8 @@ ValueDecl *DerivedConformance::deriveEquatable(TypeChecker &tc,
|
||||
|
||||
static void
|
||||
deriveBodyHashable_enum_hashValue(AbstractFunctionDecl *hashValueDecl) {
|
||||
auto parentDC = hashValueDecl->getDeclContext();
|
||||
ASTContext &C = parentDC->getASTContext();
|
||||
|
||||
auto enumDecl = parentDC->isEnumOrEnumExtensionContext();
|
||||
auto enumDecl = cast<EnumDecl>(hashValueDecl->getDeclContext());
|
||||
ASTContext &C = enumDecl->getASTContext();
|
||||
|
||||
SmallVector<ASTNode, 3> statements;
|
||||
|
||||
@@ -333,8 +322,8 @@ deriveBodyHashable_enum_hashValue(AbstractFunctionDecl *hashValueDecl) {
|
||||
cast<NamedPattern>(curriedArgs->getSemanticsProvidingPattern());
|
||||
auto selfDecl = selfPattern->getDecl();
|
||||
|
||||
DeclRefExpr *indexRef = convertEnumToIndex(statements, parentDC, enumDecl,
|
||||
selfDecl, hashValueDecl, "index");
|
||||
DeclRefExpr *indexRef = convertEnumToIndex(statements, enumDecl, selfDecl,
|
||||
hashValueDecl, "index");
|
||||
|
||||
auto memberRef = new (C) UnresolvedDotExpr(indexRef, SourceLoc(),
|
||||
C.getIdentifier("hashValue"),
|
||||
@@ -349,8 +338,7 @@ deriveBodyHashable_enum_hashValue(AbstractFunctionDecl *hashValueDecl) {
|
||||
|
||||
/// Derive a 'hashValue' implementation for an enum.
|
||||
static ValueDecl *
|
||||
deriveHashable_enum_hashValue(TypeChecker &tc, Decl *parentDecl,
|
||||
EnumDecl *enumDecl) {
|
||||
deriveHashable_enum_hashValue(TypeChecker &tc, EnumDecl *enumDecl) {
|
||||
// enum SomeEnum {
|
||||
// case A, B, C
|
||||
// @derived var hashValue: Int {
|
||||
@@ -368,9 +356,7 @@ deriveHashable_enum_hashValue(TypeChecker &tc, Decl *parentDecl,
|
||||
// }
|
||||
ASTContext &C = tc.Context;
|
||||
|
||||
auto parentDC = cast<DeclContext>(parentDecl);
|
||||
|
||||
Type enumType = parentDC->getDeclaredTypeInContext();
|
||||
Type enumType = enumDecl->getDeclaredTypeInContext();
|
||||
Type intType = C.getIntDecl()->getDeclaredType();
|
||||
|
||||
// We can't form a Hashable conformance if Int isn't Hashable or
|
||||
@@ -398,7 +384,7 @@ deriveHashable_enum_hashValue(TypeChecker &tc, Decl *parentDecl,
|
||||
SourceLoc(),
|
||||
C.Id_self,
|
||||
enumType,
|
||||
parentDC);
|
||||
enumDecl);
|
||||
selfDecl->setImplicit();
|
||||
Pattern *selfParam = new (C) NamedPattern(selfDecl, /*implicit*/ true);
|
||||
selfParam->setType(enumType);
|
||||
@@ -411,7 +397,7 @@ deriveHashable_enum_hashValue(TypeChecker &tc, Decl *parentDecl,
|
||||
FuncDecl *getterDecl =
|
||||
FuncDecl::create(C, SourceLoc(), StaticSpellingKind::None, SourceLoc(),
|
||||
Identifier(), SourceLoc(), SourceLoc(), nullptr, Type(),
|
||||
params, TypeLoc::withoutLoc(intType), parentDC);
|
||||
params, TypeLoc::withoutLoc(intType), enumDecl);
|
||||
getterDecl->setImplicit();
|
||||
getterDecl->setBodySynthesizer(deriveBodyHashable_enum_hashValue);
|
||||
|
||||
@@ -430,7 +416,7 @@ deriveHashable_enum_hashValue(TypeChecker &tc, Decl *parentDecl,
|
||||
// Compute the interface type of hashValue().
|
||||
Type interfaceType;
|
||||
Type selfIfaceType = getterDecl->computeInterfaceSelfType(false);
|
||||
if (auto sig = parentDC->getGenericSignatureOfContext())
|
||||
if (auto sig = enumDecl->getGenericSignatureOfContext())
|
||||
interfaceType = GenericFunctionType::get(sig, selfIfaceType, methodType,
|
||||
AnyFunctionType::ExtInfo());
|
||||
else
|
||||
@@ -446,7 +432,7 @@ deriveHashable_enum_hashValue(TypeChecker &tc, Decl *parentDecl,
|
||||
VarDecl *hashValueDecl = new (C) VarDecl(/*static*/ false,
|
||||
/*let*/ false,
|
||||
SourceLoc(), C.Id_hashValue,
|
||||
intType, parentDC);
|
||||
intType, enumDecl);
|
||||
hashValueDecl->setImplicit();
|
||||
hashValueDecl->makeComputed(SourceLoc(), getterDecl,
|
||||
nullptr, nullptr, SourceLoc());
|
||||
@@ -462,18 +448,16 @@ deriveHashable_enum_hashValue(TypeChecker &tc, Decl *parentDecl,
|
||||
auto patDecl = PatternBindingDecl::create(C, SourceLoc(),
|
||||
StaticSpellingKind::None,
|
||||
SourceLoc(), hashValuePat, nullptr,
|
||||
parentDC);
|
||||
enumDecl);
|
||||
patDecl->setImplicit();
|
||||
|
||||
auto dc = cast<IterableDeclContext>(parentDecl);
|
||||
dc->addMember(getterDecl);
|
||||
dc->addMember(hashValueDecl);
|
||||
dc->addMember(patDecl);
|
||||
enumDecl->addMember(getterDecl);
|
||||
enumDecl->addMember(hashValueDecl);
|
||||
enumDecl->addMember(patDecl);
|
||||
return hashValueDecl;
|
||||
}
|
||||
|
||||
ValueDecl *DerivedConformance::deriveHashable(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
NominalTypeDecl *type,
|
||||
ValueDecl *requirement) {
|
||||
// Check that we can actually derive Hashable for this type.
|
||||
@@ -483,7 +467,7 @@ ValueDecl *DerivedConformance::deriveHashable(TypeChecker &tc,
|
||||
// Build the necessary decl.
|
||||
if (requirement->getName().str() == "hashValue") {
|
||||
if (auto theEnum = dyn_cast<EnumDecl>(type))
|
||||
return deriveHashable_enum_hashValue(tc, parentDecl, theEnum);
|
||||
return deriveHashable_enum_hashValue(tc, theEnum);
|
||||
else
|
||||
llvm_unreachable("todo");
|
||||
}
|
||||
|
||||
@@ -61,7 +61,6 @@ static void deriveBodyErrorType_enum_domain(AbstractFunctionDecl *domainDecl) {
|
||||
}
|
||||
|
||||
static ValueDecl *deriveErrorType_enum_domain(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
EnumDecl *enumDecl) {
|
||||
// enum SomeEnum {
|
||||
// @derived
|
||||
@@ -76,24 +75,24 @@ static ValueDecl *deriveErrorType_enum_domain(TypeChecker &tc,
|
||||
ASTContext &C = tc.Context;
|
||||
|
||||
auto stringTy = C.getStringDecl()->getDeclaredType();
|
||||
Type enumType = cast<DeclContext>(parentDecl)->getDeclaredTypeInContext();
|
||||
Type enumType = enumDecl->getDeclaredTypeInContext();
|
||||
|
||||
// Define the getter.
|
||||
auto getterDecl = declareDerivedPropertyGetter(tc, parentDecl, enumDecl,
|
||||
enumType, stringTy, stringTy);
|
||||
auto getterDecl = declareDerivedPropertyGetter(tc, enumDecl, enumType,
|
||||
stringTy, stringTy);
|
||||
getterDecl->setBodySynthesizer(&deriveBodyErrorType_enum_domain);
|
||||
|
||||
// Define the property.
|
||||
VarDecl *propDecl;
|
||||
PatternBindingDecl *pbDecl;
|
||||
std::tie(propDecl, pbDecl)
|
||||
= declareDerivedReadOnlyProperty(tc, parentDecl, enumDecl, C.Id__domain,
|
||||
stringTy, stringTy, getterDecl);
|
||||
= declareDerivedReadOnlyProperty(tc, enumDecl, C.Id__domain,
|
||||
stringTy, stringTy,
|
||||
getterDecl);
|
||||
|
||||
auto dc = cast<IterableDeclContext>(parentDecl);
|
||||
dc->addMember(getterDecl);
|
||||
dc->addMember(propDecl);
|
||||
dc->addMember(pbDecl);
|
||||
enumDecl->addMember(getterDecl);
|
||||
enumDecl->addMember(propDecl);
|
||||
enumDecl->addMember(pbDecl);
|
||||
return propDecl;
|
||||
}
|
||||
|
||||
@@ -114,11 +113,9 @@ static void deriveBodyErrorType_enum_code(AbstractFunctionDecl *codeDecl) {
|
||||
//
|
||||
// TODO: Some convenient way to override the code if that's desired.
|
||||
|
||||
auto parentDC = codeDecl->getDeclContext();
|
||||
ASTContext &C = parentDC->getASTContext();
|
||||
|
||||
auto enumDecl = parentDC->isEnumOrEnumExtensionContext();
|
||||
Type enumType = parentDC->getDeclaredTypeInContext();
|
||||
ASTContext &C = codeDecl->getASTContext();
|
||||
auto enumDecl = cast<EnumDecl>(codeDecl->getDeclContext());
|
||||
Type enumType = enumDecl->getDeclaredTypeInContext();
|
||||
|
||||
SmallVector<CaseStmt*, 4> cases;
|
||||
SmallString<11> strBuf;
|
||||
@@ -179,7 +176,6 @@ static void deriveBodyErrorType_enum_code(AbstractFunctionDecl *codeDecl) {
|
||||
}
|
||||
|
||||
static ValueDecl *deriveErrorType_enum_code(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
EnumDecl *enumDecl) {
|
||||
// enum SomeEnum {
|
||||
// case A,B,C,D
|
||||
@@ -198,32 +194,29 @@ static ValueDecl *deriveErrorType_enum_code(TypeChecker &tc,
|
||||
ASTContext &C = tc.Context;
|
||||
|
||||
auto intTy = C.getIntDecl()->getDeclaredType();
|
||||
Type enumType = cast<DeclContext>(parentDecl)->getDeclaredTypeInContext();
|
||||
Type enumType = enumDecl->getDeclaredTypeInContext();
|
||||
|
||||
// Define the getter.
|
||||
auto getterDecl = declareDerivedPropertyGetter(tc, parentDecl, enumDecl,
|
||||
enumType, intTy, intTy);
|
||||
auto getterDecl = declareDerivedPropertyGetter(tc, enumDecl, enumType,
|
||||
intTy, intTy);
|
||||
getterDecl->setBodySynthesizer(&deriveBodyErrorType_enum_code);
|
||||
|
||||
// Define the property.
|
||||
VarDecl *propDecl;
|
||||
PatternBindingDecl *pbDecl;
|
||||
std::tie(propDecl, pbDecl)
|
||||
= declareDerivedReadOnlyProperty(tc, parentDecl, enumDecl, C.Id__code,
|
||||
= declareDerivedReadOnlyProperty(tc, enumDecl, C.Id__code,
|
||||
intTy, intTy,
|
||||
getterDecl);
|
||||
|
||||
auto dc = cast<IterableDeclContext>(parentDecl);
|
||||
dc->addMember(getterDecl);
|
||||
dc->addMember(propDecl);
|
||||
dc->addMember(pbDecl);
|
||||
|
||||
enumDecl->addMember(getterDecl);
|
||||
enumDecl->addMember(propDecl);
|
||||
enumDecl->addMember(pbDecl);
|
||||
return propDecl;
|
||||
|
||||
}
|
||||
|
||||
ValueDecl *DerivedConformance::deriveErrorType(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
NominalTypeDecl *type,
|
||||
ValueDecl *requirement) {
|
||||
if (!canDeriveConformance(type))
|
||||
@@ -232,9 +225,9 @@ ValueDecl *DerivedConformance::deriveErrorType(TypeChecker &tc,
|
||||
auto enumType = cast<EnumDecl>(type);
|
||||
|
||||
if (requirement->getName() == tc.Context.Id__domain)
|
||||
return deriveErrorType_enum_domain(tc, parentDecl, enumType);
|
||||
return deriveErrorType_enum_domain(tc, enumType);
|
||||
else if (requirement->getName() == tc.Context.Id__code)
|
||||
return deriveErrorType_enum_code(tc, parentDecl, enumType);
|
||||
return deriveErrorType_enum_code(tc, enumType);
|
||||
|
||||
tc.diagnose(requirement->getLoc(),
|
||||
diag::broken_errortype_requirement);
|
||||
@@ -266,7 +259,6 @@ static void deriveBodyBridgedNSError_enum_NSErrorDomain(
|
||||
}
|
||||
|
||||
static ValueDecl *deriveBridgedNSError_enum_NSErrorDomain(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
EnumDecl *enumDecl) {
|
||||
// enum SomeEnum {
|
||||
// @derived
|
||||
@@ -284,8 +276,8 @@ static ValueDecl *deriveBridgedNSError_enum_NSErrorDomain(TypeChecker &tc,
|
||||
Type enumType = enumDecl->getDeclaredTypeInContext();
|
||||
|
||||
// Define the getter.
|
||||
auto getterDecl = declareDerivedPropertyGetter(tc, parentDecl, enumDecl,
|
||||
enumType, stringTy, stringTy,
|
||||
auto getterDecl = declareDerivedPropertyGetter(tc, enumDecl, enumType,
|
||||
stringTy, stringTy,
|
||||
/*isStatic=*/true);
|
||||
getterDecl->setBodySynthesizer(&deriveBodyBridgedNSError_enum_NSErrorDomain);
|
||||
|
||||
@@ -293,21 +285,17 @@ static ValueDecl *deriveBridgedNSError_enum_NSErrorDomain(TypeChecker &tc,
|
||||
VarDecl *propDecl;
|
||||
PatternBindingDecl *pbDecl;
|
||||
std::tie(propDecl, pbDecl)
|
||||
= declareDerivedReadOnlyProperty(tc, parentDecl, enumDecl,
|
||||
C.Id__NSErrorDomain,
|
||||
= declareDerivedReadOnlyProperty(tc, enumDecl, C.Id__NSErrorDomain,
|
||||
stringTy, stringTy,
|
||||
getterDecl, /*isStatic=*/true);
|
||||
|
||||
auto dc = cast<IterableDeclContext>(parentDecl);
|
||||
dc->addMember(getterDecl);
|
||||
dc->addMember(propDecl);
|
||||
dc->addMember(pbDecl);
|
||||
|
||||
enumDecl->addMember(getterDecl);
|
||||
enumDecl->addMember(propDecl);
|
||||
enumDecl->addMember(pbDecl);
|
||||
return propDecl;
|
||||
}
|
||||
|
||||
ValueDecl *DerivedConformance::deriveBridgedNSError(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
NominalTypeDecl *type,
|
||||
ValueDecl *requirement) {
|
||||
if (!canDeriveConformance(type))
|
||||
@@ -316,9 +304,10 @@ ValueDecl *DerivedConformance::deriveBridgedNSError(TypeChecker &tc,
|
||||
auto enumType = cast<EnumDecl>(type);
|
||||
|
||||
if (requirement->getName() == tc.Context.Id__NSErrorDomain)
|
||||
return deriveBridgedNSError_enum_NSErrorDomain(tc, parentDecl, enumType);
|
||||
return deriveBridgedNSError_enum_NSErrorDomain(tc, enumType);
|
||||
|
||||
tc.diagnose(requirement->getLoc(),
|
||||
diag::broken_errortype_requirement);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,15 +52,13 @@ static LiteralExpr *cloneRawLiteralExpr(ASTContext &C, LiteralExpr *expr) {
|
||||
return clone;
|
||||
}
|
||||
|
||||
static Type deriveRawRepresentable_Raw(TypeChecker &tc, Decl *parentDecl,
|
||||
EnumDecl *enumDecl) {
|
||||
static Type deriveRawRepresentable_Raw(TypeChecker &tc, EnumDecl *enumDecl) {
|
||||
// enum SomeEnum : SomeType {
|
||||
// @derived
|
||||
// typealias Raw = SomeType
|
||||
// }
|
||||
auto rawInterfaceType = enumDecl->getRawType();
|
||||
return ArchetypeBuilder::mapTypeIntoContext(cast<DeclContext>(parentDecl),
|
||||
rawInterfaceType);
|
||||
return ArchetypeBuilder::mapTypeIntoContext(enumDecl, rawInterfaceType);
|
||||
}
|
||||
|
||||
static void deriveBodyRawRepresentable_raw(AbstractFunctionDecl *toRawDecl) {
|
||||
@@ -76,11 +74,7 @@ static void deriveBodyRawRepresentable_raw(AbstractFunctionDecl *toRawDecl) {
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
auto parentDC = toRawDecl->getDeclContext();
|
||||
ASTContext &C = parentDC->getASTContext();
|
||||
|
||||
auto enumDecl = parentDC->isEnumOrEnumExtensionContext();
|
||||
auto enumDecl = cast<EnumDecl>(toRawDecl->getDeclContext());
|
||||
|
||||
Type rawTy = enumDecl->getRawType();
|
||||
assert(rawTy);
|
||||
@@ -91,7 +85,8 @@ static void deriveBodyRawRepresentable_raw(AbstractFunctionDecl *toRawDecl) {
|
||||
}
|
||||
}
|
||||
|
||||
Type enumType = parentDC->getDeclaredTypeInContext();
|
||||
ASTContext &C = enumDecl->getASTContext();
|
||||
Type enumType = enumDecl->getDeclaredTypeInContext();
|
||||
|
||||
SmallVector<CaseStmt*, 4> cases;
|
||||
for (auto elt : enumDecl->getAllElements()) {
|
||||
@@ -124,19 +119,16 @@ static void deriveBodyRawRepresentable_raw(AbstractFunctionDecl *toRawDecl) {
|
||||
}
|
||||
|
||||
static VarDecl *deriveRawRepresentable_raw(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
EnumDecl *enumDecl) {
|
||||
ASTContext &C = tc.Context;
|
||||
|
||||
auto parentDC = cast<DeclContext>(parentDecl);
|
||||
auto rawInterfaceType = enumDecl->getRawType();
|
||||
auto rawType = ArchetypeBuilder::mapTypeIntoContext(parentDC,
|
||||
auto rawType = ArchetypeBuilder::mapTypeIntoContext(enumDecl,
|
||||
rawInterfaceType);
|
||||
Type enumType = parentDC->getDeclaredTypeInContext();
|
||||
Type enumType = enumDecl->getDeclaredTypeInContext();
|
||||
|
||||
// Define the getter.
|
||||
auto getterDecl = declareDerivedPropertyGetter(tc, parentDecl, enumDecl,
|
||||
enumType,
|
||||
auto getterDecl = declareDerivedPropertyGetter(tc, enumDecl, enumType,
|
||||
rawInterfaceType,
|
||||
rawType);
|
||||
getterDecl->setBodySynthesizer(&deriveBodyRawRepresentable_raw);
|
||||
@@ -145,16 +137,13 @@ static VarDecl *deriveRawRepresentable_raw(TypeChecker &tc,
|
||||
VarDecl *propDecl;
|
||||
PatternBindingDecl *pbDecl;
|
||||
std::tie(propDecl, pbDecl)
|
||||
= declareDerivedReadOnlyProperty(tc, parentDecl, enumDecl,
|
||||
C.Id_rawValue, rawType,
|
||||
rawInterfaceType,
|
||||
= declareDerivedReadOnlyProperty(tc, enumDecl, C.Id_rawValue,
|
||||
rawType, rawInterfaceType,
|
||||
getterDecl);
|
||||
|
||||
auto dc = cast<IterableDeclContext>(parentDecl);
|
||||
dc->addMember(getterDecl);
|
||||
dc->addMember(propDecl);
|
||||
dc->addMember(pbDecl);
|
||||
|
||||
enumDecl->addMember(getterDecl);
|
||||
enumDecl->addMember(propDecl);
|
||||
enumDecl->addMember(pbDecl);
|
||||
return propDecl;
|
||||
}
|
||||
|
||||
@@ -175,11 +164,7 @@ deriveBodyRawRepresentable_init(AbstractFunctionDecl *initDecl) {
|
||||
// }
|
||||
// }
|
||||
|
||||
auto parentDC = initDecl->getDeclContext();
|
||||
ASTContext &C = parentDC->getASTContext();
|
||||
|
||||
auto nominalTypeDecl = parentDC->isNominalTypeOrNominalTypeExtensionContext();
|
||||
auto enumDecl = cast<EnumDecl>(nominalTypeDecl);
|
||||
auto enumDecl = cast<EnumDecl>(initDecl->getDeclContext());
|
||||
|
||||
Type rawTy = enumDecl->getRawType();
|
||||
assert(rawTy);
|
||||
@@ -192,7 +177,8 @@ deriveBodyRawRepresentable_init(AbstractFunctionDecl *initDecl) {
|
||||
}
|
||||
}
|
||||
|
||||
Type enumType = parentDC->getDeclaredTypeInContext();
|
||||
ASTContext &C = enumDecl->getASTContext();
|
||||
Type enumType = enumDecl->getDeclaredTypeInContext();
|
||||
|
||||
auto selfDecl = cast<ConstructorDecl>(initDecl)->getImplicitSelfDecl();
|
||||
|
||||
@@ -249,13 +235,11 @@ deriveBodyRawRepresentable_init(AbstractFunctionDecl *initDecl) {
|
||||
}
|
||||
|
||||
static ConstructorDecl *deriveRawRepresentable_init(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
EnumDecl *enumDecl) {
|
||||
ASTContext &C = tc.Context;
|
||||
|
||||
auto parentDC = cast<DeclContext>(parentDecl);
|
||||
auto rawInterfaceType = enumDecl->getRawType();
|
||||
auto rawType = ArchetypeBuilder::mapTypeIntoContext(parentDC,
|
||||
auto rawType = ArchetypeBuilder::mapTypeIntoContext(enumDecl,
|
||||
rawInterfaceType);
|
||||
|
||||
// Make sure that the raw type is Equatable. We need it to ensure that we have
|
||||
@@ -271,14 +255,14 @@ static ConstructorDecl *deriveRawRepresentable_init(TypeChecker &tc,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Type enumType = parentDC->getDeclaredTypeInContext();
|
||||
Type enumType = enumDecl->getDeclaredTypeInContext();
|
||||
VarDecl *selfDecl = new (C) ParamDecl(/*IsLet*/false,
|
||||
SourceLoc(),
|
||||
Identifier(),
|
||||
SourceLoc(),
|
||||
C.Id_self,
|
||||
enumType,
|
||||
parentDC);
|
||||
enumDecl);
|
||||
selfDecl->setImplicit();
|
||||
Pattern *selfParam = new (C) NamedPattern(selfDecl, /*implicit*/ true);
|
||||
selfParam->setType(enumType);
|
||||
@@ -293,7 +277,7 @@ static ConstructorDecl *deriveRawRepresentable_init(TypeChecker &tc,
|
||||
SourceLoc(),
|
||||
C.Id_rawValue,
|
||||
rawType,
|
||||
parentDC);
|
||||
enumDecl);
|
||||
rawDecl->setImplicit();
|
||||
Pattern *rawParam = new (C) NamedPattern(rawDecl, /*implicit*/ true);
|
||||
rawParam->setType(rawType);
|
||||
@@ -314,7 +298,7 @@ static ConstructorDecl *deriveRawRepresentable_init(TypeChecker &tc,
|
||||
rawParam,
|
||||
nullptr,
|
||||
SourceLoc(),
|
||||
parentDC);
|
||||
enumDecl);
|
||||
|
||||
initDecl->setImplicit();
|
||||
initDecl->setBodySynthesizer(&deriveBodyRawRepresentable_init);
|
||||
@@ -345,7 +329,7 @@ static ConstructorDecl *deriveRawRepresentable_init(TypeChecker &tc,
|
||||
|
||||
// Compute the interface type of the initializer.
|
||||
Type retInterfaceType
|
||||
= OptionalType::get(parentDC->getDeclaredInterfaceType());
|
||||
= OptionalType::get(enumDecl->getDeclaredInterfaceType());
|
||||
Type interfaceType = FunctionType::get(interfaceArgType, retInterfaceType);
|
||||
Type selfInterfaceType = initDecl->computeInterfaceSelfType(/*init*/ false);
|
||||
Type selfInitializerInterfaceType
|
||||
@@ -353,7 +337,7 @@ static ConstructorDecl *deriveRawRepresentable_init(TypeChecker &tc,
|
||||
|
||||
Type allocIfaceType;
|
||||
Type initIfaceType;
|
||||
if (auto sig = parentDC->getGenericSignatureOfContext()) {
|
||||
if (auto sig = enumDecl->getGenericSignatureOfContext()) {
|
||||
allocIfaceType = GenericFunctionType::get(sig, selfInterfaceType,
|
||||
interfaceType,
|
||||
FunctionType::ExtInfo());
|
||||
@@ -371,12 +355,11 @@ static ConstructorDecl *deriveRawRepresentable_init(TypeChecker &tc,
|
||||
if (enumDecl->hasClangNode())
|
||||
tc.implicitlyDefinedFunctions.push_back(initDecl);
|
||||
|
||||
cast<IterableDeclContext>(parentDecl)->addMember(initDecl);
|
||||
enumDecl->addMember(initDecl);
|
||||
return initDecl;
|
||||
}
|
||||
|
||||
ValueDecl *DerivedConformance::deriveRawRepresentable(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
NominalTypeDecl *type,
|
||||
ValueDecl *requirement) {
|
||||
// Check preconditions. These should already have been diagnosed by
|
||||
@@ -402,10 +385,10 @@ ValueDecl *DerivedConformance::deriveRawRepresentable(TypeChecker &tc,
|
||||
tc.validateDecl(elt);
|
||||
|
||||
if (requirement->getName() == tc.Context.Id_rawValue)
|
||||
return deriveRawRepresentable_raw(tc, parentDecl, enumDecl);
|
||||
return deriveRawRepresentable_raw(tc, enumDecl);
|
||||
|
||||
if (requirement->getName() == tc.Context.Id_init)
|
||||
return deriveRawRepresentable_init(tc, parentDecl, enumDecl);
|
||||
return deriveRawRepresentable_init(tc, enumDecl);
|
||||
|
||||
tc.diagnose(requirement->getLoc(),
|
||||
diag::broken_raw_representable_requirement);
|
||||
@@ -413,7 +396,6 @@ ValueDecl *DerivedConformance::deriveRawRepresentable(TypeChecker &tc,
|
||||
}
|
||||
|
||||
Type DerivedConformance::deriveRawRepresentable(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
NominalTypeDecl *type,
|
||||
AssociatedTypeDecl *assocType) {
|
||||
// Check preconditions. These should already have been diagnosed by
|
||||
@@ -439,7 +421,7 @@ Type DerivedConformance::deriveRawRepresentable(TypeChecker &tc,
|
||||
tc.validateDecl(elt);
|
||||
|
||||
if (assocType->getName() == tc.Context.Id_RawValue) {
|
||||
return deriveRawRepresentable_Raw(tc, parentDecl, enumDecl);
|
||||
return deriveRawRepresentable_Raw(tc, enumDecl);
|
||||
}
|
||||
|
||||
tc.diagnose(assocType->getLoc(),
|
||||
|
||||
@@ -53,7 +53,6 @@ DerivedConformance::createSelfDeclRef(AbstractFunctionDecl *fn) {
|
||||
}
|
||||
|
||||
FuncDecl *DerivedConformance::declareDerivedPropertyGetter(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
NominalTypeDecl *typeDecl,
|
||||
Type contextType,
|
||||
Type propertyInterfaceType,
|
||||
@@ -65,15 +64,13 @@ FuncDecl *DerivedConformance::declareDerivedPropertyGetter(TypeChecker &tc,
|
||||
if (isStatic)
|
||||
selfType = MetatypeType::get(selfType);
|
||||
|
||||
auto parentDC = cast<DeclContext>(parentDecl);
|
||||
|
||||
VarDecl *selfDecl = new (C) ParamDecl(/*IsLet*/true,
|
||||
SourceLoc(),
|
||||
Identifier(),
|
||||
SourceLoc(),
|
||||
C.Id_self,
|
||||
selfType,
|
||||
parentDC);
|
||||
typeDecl);
|
||||
selfDecl->setImplicit();
|
||||
Pattern *selfParam = new (C) NamedPattern(selfDecl, /*implicit*/ true);
|
||||
selfParam->setType(selfType);
|
||||
@@ -88,7 +85,7 @@ FuncDecl *DerivedConformance::declareDerivedPropertyGetter(TypeChecker &tc,
|
||||
FuncDecl::create(C, SourceLoc(), StaticSpellingKind::None, SourceLoc(),
|
||||
DeclName(), SourceLoc(), SourceLoc(), nullptr, Type(),
|
||||
params, TypeLoc::withoutLoc(propertyContextType),
|
||||
parentDC);
|
||||
typeDecl);
|
||||
getterDecl->setImplicit();
|
||||
getterDecl->setStatic(isStatic);
|
||||
|
||||
@@ -108,7 +105,7 @@ FuncDecl *DerivedConformance::declareDerivedPropertyGetter(TypeChecker &tc,
|
||||
Type interfaceType = FunctionType::get(TupleType::getEmpty(C),
|
||||
propertyInterfaceType);
|
||||
Type selfInterfaceType = getterDecl->computeInterfaceSelfType(false);
|
||||
if (auto sig = parentDC->getGenericSignatureOfContext())
|
||||
if (auto sig = typeDecl->getGenericSignatureOfContext())
|
||||
interfaceType = GenericFunctionType::get(sig, selfInterfaceType,
|
||||
interfaceType,
|
||||
FunctionType::ExtInfo());
|
||||
@@ -125,7 +122,6 @@ FuncDecl *DerivedConformance::declareDerivedPropertyGetter(TypeChecker &tc,
|
||||
|
||||
std::pair<VarDecl *, PatternBindingDecl *>
|
||||
DerivedConformance::declareDerivedReadOnlyProperty(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
NominalTypeDecl *typeDecl,
|
||||
Identifier name,
|
||||
Type propertyInterfaceType,
|
||||
@@ -133,13 +129,12 @@ DerivedConformance::declareDerivedReadOnlyProperty(TypeChecker &tc,
|
||||
FuncDecl *getterDecl,
|
||||
bool isStatic) {
|
||||
auto &C = tc.Context;
|
||||
auto parentDC = cast<DeclContext>(parentDecl);
|
||||
|
||||
VarDecl *propDecl = new (C) VarDecl(isStatic,
|
||||
/*let*/ false,
|
||||
SourceLoc(), name,
|
||||
propertyContextType,
|
||||
parentDC);
|
||||
typeDecl);
|
||||
propDecl->setImplicit();
|
||||
propDecl->makeComputed(SourceLoc(), getterDecl, nullptr, nullptr,
|
||||
SourceLoc());
|
||||
@@ -155,7 +150,7 @@ DerivedConformance::declareDerivedReadOnlyProperty(TypeChecker &tc,
|
||||
auto pbDecl = PatternBindingDecl::create(C, SourceLoc(),
|
||||
StaticSpellingKind::None,
|
||||
SourceLoc(), propPat, nullptr,
|
||||
parentDC);
|
||||
typeDecl);
|
||||
pbDecl->setImplicit();
|
||||
|
||||
return {propDecl, pbDecl};
|
||||
|
||||
@@ -35,7 +35,6 @@ namespace DerivedConformance {
|
||||
///
|
||||
/// \returns the derived member, which will also be added to the type.
|
||||
ValueDecl *deriveRawRepresentable(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
NominalTypeDecl *type,
|
||||
ValueDecl *requirement);
|
||||
|
||||
@@ -44,7 +43,6 @@ ValueDecl *deriveRawRepresentable(TypeChecker &tc,
|
||||
///
|
||||
/// \returns the derived member, which will also be added to the type.
|
||||
Type deriveRawRepresentable(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
NominalTypeDecl *type,
|
||||
AssociatedTypeDecl *assocType);
|
||||
|
||||
@@ -56,7 +54,6 @@ Type deriveRawRepresentable(TypeChecker &tc,
|
||||
///
|
||||
/// \returns the derived member, which will also be added to the type.
|
||||
ValueDecl *deriveEquatable(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
NominalTypeDecl *type,
|
||||
ValueDecl *requirement);
|
||||
|
||||
@@ -68,7 +65,6 @@ ValueDecl *deriveEquatable(TypeChecker &tc,
|
||||
///
|
||||
/// \returns the derived member, which will also be added to the type.
|
||||
ValueDecl *deriveHashable(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
NominalTypeDecl *type,
|
||||
ValueDecl *requirement);
|
||||
|
||||
@@ -79,7 +75,6 @@ ValueDecl *deriveHashable(TypeChecker &tc,
|
||||
///
|
||||
/// \returns the derived member, which will also be added to the type.
|
||||
ValueDecl *deriveErrorType(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
NominalTypeDecl *type,
|
||||
ValueDecl *requirement);
|
||||
|
||||
@@ -87,7 +82,6 @@ ValueDecl *deriveErrorType(TypeChecker &tc,
|
||||
///
|
||||
/// \returns the derived member, which will also be added to the type.
|
||||
ValueDecl *deriveBridgedNSError(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
NominalTypeDecl *type,
|
||||
ValueDecl *requirement);
|
||||
|
||||
@@ -109,7 +103,6 @@ inline SomeDecl *insertOperatorDecl(ASTContext &C,
|
||||
|
||||
/// Declare a getter for a derived property.
|
||||
FuncDecl *declareDerivedPropertyGetter(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
NominalTypeDecl *typeDecl,
|
||||
Type contextType,
|
||||
Type propertyInterfaceType,
|
||||
@@ -119,7 +112,6 @@ FuncDecl *declareDerivedPropertyGetter(TypeChecker &tc,
|
||||
/// Declare a read-only property with an existing getter.
|
||||
std::pair<VarDecl *, PatternBindingDecl *>
|
||||
declareDerivedReadOnlyProperty(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
NominalTypeDecl *typeDecl,
|
||||
Identifier name,
|
||||
Type propertyInterfaceType,
|
||||
|
||||
@@ -5338,13 +5338,6 @@ public:
|
||||
validateAttributes(TC, ED);
|
||||
}
|
||||
|
||||
// Check conformances before visiting members, since we might
|
||||
// synthesize bodies for derived conformances
|
||||
if (!IsFirstPass) {
|
||||
computeDefaultAccessibility(TC, ED);
|
||||
checkExplicitConformance(ED, ED->getExtendedType());
|
||||
}
|
||||
|
||||
if (!ED->isInvalid()) {
|
||||
for (Decl *Member : ED->getMembers())
|
||||
visit(Member);
|
||||
@@ -5352,6 +5345,10 @@ public:
|
||||
visit(Global);
|
||||
}
|
||||
|
||||
if (!IsFirstPass) {
|
||||
computeDefaultAccessibility(TC, ED);
|
||||
checkExplicitConformance(ED, ED->getExtendedType());
|
||||
}
|
||||
TC.checkDeclAttributes(ED);
|
||||
}
|
||||
|
||||
|
||||
@@ -2380,7 +2380,7 @@ ResolveWitnessResult ConformanceChecker::resolveWitnessViaDerivation(
|
||||
}
|
||||
|
||||
// Attempt to derive the witness.
|
||||
auto derived = TC.deriveProtocolRequirement(DC, derivingTypeDecl, requirement);
|
||||
auto derived = TC.deriveProtocolRequirement(derivingTypeDecl, requirement);
|
||||
if (!derived)
|
||||
return ResolveWitnessResult::ExplicitFailed;
|
||||
|
||||
@@ -3090,7 +3090,7 @@ void ConformanceChecker::resolveTypeWitnesses() {
|
||||
return Type();
|
||||
|
||||
// Try to derive the type witness.
|
||||
Type derivedType = TC.deriveTypeWitness(DC, derivingTypeDecl, assocType);
|
||||
Type derivedType = TC.deriveTypeWitness(derivingTypeDecl, assocType);
|
||||
if (!derivedType)
|
||||
return Type();
|
||||
|
||||
@@ -3875,8 +3875,7 @@ void TypeChecker::resolveWitness(const NormalProtocolConformance *conformance,
|
||||
checker.resolveSingleWitness(requirement);
|
||||
}
|
||||
|
||||
ValueDecl *TypeChecker::deriveProtocolRequirement(DeclContext *DC,
|
||||
NominalTypeDecl *TypeDecl,
|
||||
ValueDecl *TypeChecker::deriveProtocolRequirement(NominalTypeDecl *TypeDecl,
|
||||
ValueDecl *Requirement) {
|
||||
auto *protocol = cast<ProtocolDecl>(Requirement->getDeclContext());
|
||||
|
||||
@@ -3885,24 +3884,22 @@ ValueDecl *TypeChecker::deriveProtocolRequirement(DeclContext *DC,
|
||||
if (!knownKind)
|
||||
return nullptr;
|
||||
|
||||
auto Decl = DC->getInnermostDeclarationDeclContext();
|
||||
|
||||
switch (*knownKind) {
|
||||
case KnownProtocolKind::RawRepresentable:
|
||||
return DerivedConformance::deriveRawRepresentable(*this, Decl,
|
||||
return DerivedConformance::deriveRawRepresentable(*this,
|
||||
TypeDecl, Requirement);
|
||||
|
||||
case KnownProtocolKind::Equatable:
|
||||
return DerivedConformance::deriveEquatable(*this, Decl, TypeDecl, Requirement);
|
||||
return DerivedConformance::deriveEquatable(*this, TypeDecl, Requirement);
|
||||
|
||||
case KnownProtocolKind::Hashable:
|
||||
return DerivedConformance::deriveHashable(*this, Decl, TypeDecl, Requirement);
|
||||
return DerivedConformance::deriveHashable(*this, TypeDecl, Requirement);
|
||||
|
||||
case KnownProtocolKind::ErrorType:
|
||||
return DerivedConformance::deriveErrorType(*this, Decl, TypeDecl, Requirement);
|
||||
return DerivedConformance::deriveErrorType(*this, TypeDecl, Requirement);
|
||||
|
||||
case KnownProtocolKind::_BridgedNSError:
|
||||
return DerivedConformance::deriveBridgedNSError(*this, Decl, TypeDecl,
|
||||
return DerivedConformance::deriveBridgedNSError(*this, TypeDecl,
|
||||
Requirement);
|
||||
|
||||
default:
|
||||
@@ -3910,22 +3907,19 @@ ValueDecl *TypeChecker::deriveProtocolRequirement(DeclContext *DC,
|
||||
}
|
||||
}
|
||||
|
||||
Type TypeChecker::deriveTypeWitness(DeclContext *DC,
|
||||
NominalTypeDecl *TypeDecl,
|
||||
AssociatedTypeDecl *AssocType) {
|
||||
auto *protocol = cast<ProtocolDecl>(AssocType->getDeclContext());
|
||||
Type TypeChecker::deriveTypeWitness(NominalTypeDecl *nominal,
|
||||
AssociatedTypeDecl *assocType) {
|
||||
auto *protocol = cast<ProtocolDecl>(assocType->getDeclContext());
|
||||
|
||||
auto knownKind = protocol->getKnownProtocolKind();
|
||||
|
||||
if (!knownKind)
|
||||
return nullptr;
|
||||
|
||||
auto Decl = DC->getInnermostDeclarationDeclContext();
|
||||
|
||||
switch (*knownKind) {
|
||||
case KnownProtocolKind::RawRepresentable:
|
||||
return DerivedConformance::deriveRawRepresentable(*this, Decl,
|
||||
TypeDecl, AssocType);
|
||||
return DerivedConformance::deriveRawRepresentable(*this, nominal,
|
||||
assocType);
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
|
||||
@@ -1253,23 +1253,19 @@ public:
|
||||
/// Derive an implicit declaration to satisfy a requirement of a derived
|
||||
/// protocol conformance.
|
||||
///
|
||||
/// \param DC The declaration context where the conformance was
|
||||
/// defined, either the type itself or an extension
|
||||
/// \param TypeDecl The type for which the requirement is being derived.
|
||||
/// \param Requirement The protocol requirement.
|
||||
///
|
||||
/// \returns nullptr if the derivation failed, or the derived declaration
|
||||
/// if it succeeded. If successful, the derived declaration is added
|
||||
/// to TypeDecl's body.
|
||||
ValueDecl *deriveProtocolRequirement(DeclContext *DC,
|
||||
NominalTypeDecl *TypeDecl,
|
||||
ValueDecl *deriveProtocolRequirement(NominalTypeDecl *TypeDecl,
|
||||
ValueDecl *Requirement);
|
||||
|
||||
/// Derive an implicit type witness for the given associated type in
|
||||
/// the conformance of the given nominal type to some known
|
||||
/// protocol.
|
||||
Type deriveTypeWitness(DeclContext *DC,
|
||||
NominalTypeDecl *nominal,
|
||||
Type deriveTypeWitness(NominalTypeDecl *nominal,
|
||||
AssociatedTypeDecl *assocType);
|
||||
|
||||
/// \brief Given a set of archetype substitutions, verify and record all of
|
||||
|
||||
@@ -3500,8 +3500,8 @@ static void addOperatorsAndTopLevel(Serializer &S, Range members,
|
||||
bool isDerivedTopLevel,
|
||||
bool isLocal = false) {
|
||||
for (const Decl *member : members) {
|
||||
if (auto memberValue = dyn_cast<ValueDecl>(member)) {
|
||||
if (!memberValue->hasName())
|
||||
auto memberValue = dyn_cast<ValueDecl>(member);
|
||||
if (!memberValue)
|
||||
continue;
|
||||
|
||||
if (isDerivedTopLevel) {
|
||||
@@ -3518,14 +3518,13 @@ static void addOperatorsAndTopLevel(Serializer &S, Range members,
|
||||
S.addDeclRef(memberValue)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Recurse into nested declarations.
|
||||
if (auto iterable = dyn_cast<IterableDeclContext>(member)) {
|
||||
addOperatorsAndTopLevel(S, iterable->getMembers(),
|
||||
// Recurse into nested types.
|
||||
if (auto nominal = dyn_cast<NominalTypeDecl>(member)) {
|
||||
addOperatorsAndTopLevel(S, nominal->getMembers(),
|
||||
operatorMethodDecls, topLevelDecls, objcMethods,
|
||||
false);
|
||||
addOperatorsAndTopLevel(S, iterable->getDerivedGlobalDecls(),
|
||||
addOperatorsAndTopLevel(S, nominal->getDerivedGlobalDecls(),
|
||||
operatorMethodDecls, topLevelDecls, objcMethods,
|
||||
true);
|
||||
}
|
||||
@@ -3539,7 +3538,7 @@ static void addOperatorsAndTopLevel(Serializer &S, Range members,
|
||||
objcMethods[func->getObjCSelector()].push_back(
|
||||
std::make_tuple(owningTypeID,
|
||||
func->isObjCInstanceMethod(),
|
||||
S.addDeclRef(func)));
|
||||
S.addDeclRef(memberValue)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3566,30 +3565,36 @@ void Serializer::writeAST(ModuleOrSourceFile DC) {
|
||||
for (auto D : fileDecls) {
|
||||
if (isa<ImportDecl>(D))
|
||||
continue;
|
||||
|
||||
if (auto VD = dyn_cast<ValueDecl>(D)) {
|
||||
else if (auto VD = dyn_cast<ValueDecl>(D)) {
|
||||
if (!VD->hasName())
|
||||
continue;
|
||||
topLevelDecls[VD->getName()]
|
||||
.push_back({ getKindForTable(D), addDeclRef(D) });
|
||||
|
||||
// Add operator methods from nominal types.
|
||||
if (auto nominal = dyn_cast<NominalTypeDecl>(VD)) {
|
||||
addOperatorsAndTopLevel(*this, nominal->getMembers(),
|
||||
operatorMethodDecls, topLevelDecls,
|
||||
objcMethods, false);
|
||||
addOperatorsAndTopLevel(*this, nominal->getDerivedGlobalDecls(),
|
||||
operatorMethodDecls, topLevelDecls,
|
||||
objcMethods, true);
|
||||
}
|
||||
} else if (auto ED = dyn_cast<ExtensionDecl>(D)) {
|
||||
Type extendedTy = ED->getExtendedType();
|
||||
const NominalTypeDecl *extendedNominal = extendedTy->getAnyNominal();
|
||||
extensionDecls[extendedNominal->getName()]
|
||||
.push_back({ getKindForTable(extendedNominal), addDeclRef(D) });
|
||||
|
||||
// Add operator methods from extensions.
|
||||
addOperatorsAndTopLevel(*this, ED->getMembers(),
|
||||
operatorMethodDecls, topLevelDecls, objcMethods,
|
||||
false);
|
||||
|
||||
} else if (auto OD = dyn_cast<OperatorDecl>(D)) {
|
||||
operatorDecls[OD->getName()]
|
||||
.push_back({ getStableFixity(OD->getKind()), addDeclRef(D) });
|
||||
}
|
||||
|
||||
if (auto IDC = dyn_cast<IterableDeclContext>(D)) {
|
||||
addOperatorsAndTopLevel(*this, IDC->getMembers(),
|
||||
operatorMethodDecls, topLevelDecls,
|
||||
objcMethods, false);
|
||||
addOperatorsAndTopLevel(*this, IDC->getDerivedGlobalDecls(),
|
||||
operatorMethodDecls, topLevelDecls,
|
||||
objcMethods, true);
|
||||
}
|
||||
}
|
||||
|
||||
SmallVector<TypeDecl *, 16> localTypeDecls;
|
||||
@@ -3609,11 +3614,11 @@ void Serializer::writeAST(ModuleOrSourceFile DC) {
|
||||
addDeclRef(TD), TD->getLocalDiscriminator()
|
||||
});
|
||||
|
||||
if (auto IDC = dyn_cast<IterableDeclContext>(TD)) {
|
||||
addOperatorsAndTopLevel(*this, IDC->getMembers(),
|
||||
if (auto nominal = dyn_cast<NominalTypeDecl>(TD)) {
|
||||
addOperatorsAndTopLevel(*this, nominal->getMembers(),
|
||||
operatorMethodDecls, topLevelDecls,
|
||||
objcMethods, false, /*isLocal=*/true);
|
||||
addOperatorsAndTopLevel(*this, IDC->getDerivedGlobalDecls(),
|
||||
addOperatorsAndTopLevel(*this, nominal->getDerivedGlobalDecls(),
|
||||
operatorMethodDecls, topLevelDecls,
|
||||
objcMethods, true, /*isLocal=*/true);
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
public enum TrafficLight {
|
||||
case Red
|
||||
case Yellow
|
||||
case Green
|
||||
}
|
||||
|
||||
public enum Term<T, U> {
|
||||
case Value(U)
|
||||
case Function(T, U)
|
||||
}
|
||||
|
||||
public enum Phantom<T> : Int {
|
||||
case Up
|
||||
case Down
|
||||
}
|
||||
@@ -1,10 +1,5 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: mkdir %t
|
||||
// RUN: %target-swift-frontend -emit-module -module-name def_enum -o %t %S/Inputs/def_enum.swift
|
||||
// RUN: %target-swift-frontend -I %t -O -primary-file %s -emit-ir | FileCheck -check-prefix=CHECK -check-prefix=CHECK-NORMAL %s
|
||||
// RUN: %target-swift-frontend -I %t -O -primary-file %s -enable-testing -emit-ir | FileCheck -check-prefix=CHECK -check-prefix=CHECK-TESTABLE %s
|
||||
|
||||
import def_enum
|
||||
// RUN: %target-swift-frontend -O -primary-file %s -emit-ir | FileCheck -check-prefix=CHECK -check-prefix=CHECK-NORMAL %s
|
||||
// RUN: %target-swift-frontend -O -primary-file %s -enable-testing -emit-ir | FileCheck -check-prefix=CHECK -check-prefix=CHECK-TESTABLE %s
|
||||
|
||||
// Check if the hashValue and == for an enum (without payload) are generated and
|
||||
// check if that functions are compiled in an optimal way.
|
||||
@@ -29,23 +24,3 @@ enum E {
|
||||
// CHECK-TESTABLE-LABEL:define i1 @_TZF12enum_derivedoi2eeFTOS_1ES0__Sb(i2, i2)
|
||||
// CHECK: %2 = icmp eq i2 %0, %1
|
||||
// CHECK: ret i1 %2
|
||||
|
||||
// Derived conformances from extensions
|
||||
// The actual enums are in Inputs/def_enum.swift
|
||||
|
||||
extension def_enum.TrafficLight : ErrorType {}
|
||||
|
||||
// CHECK-LABEL: define { i8*, i64, i64 } @_TFE12enum_derivedO8def_enum12TrafficLightg7_domainSS(i2) #0
|
||||
// CHECK-LABEL: define i64 @_TFE12enum_derivedO8def_enum12TrafficLightg5_codeSi(i2)
|
||||
|
||||
extension def_enum.Term : ErrorType {}
|
||||
|
||||
// CHECK-NORMAL-LABEL: define hidden i64 @_TFO12enum_derived7Phantomg8rawValueSi(i1, %swift.type* nocapture readnone %T) #1
|
||||
// CHECK-TESTABLE-LABEL: define i64 @_TFO12enum_derived7Phantomg8rawValueSi(i1, %swift.type* nocapture readnone %T) #1
|
||||
|
||||
enum Phantom<T> : Int {
|
||||
case Up
|
||||
case Down
|
||||
}
|
||||
|
||||
extension Phantom : RawRepresentable {}
|
||||
|
||||
@@ -34,7 +34,7 @@ enum CustomHashable {
|
||||
|
||||
var hashValue: Int { return 0 }
|
||||
}
|
||||
func ==(x: CustomHashable, y: CustomHashable) -> Bool { // expected-note{{non-matching type}}
|
||||
func ==(x: CustomHashable, y: CustomHashable) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ enum InvalidCustomHashable {
|
||||
|
||||
var hashValue: String { return "" } // expected-note{{previously declared here}}
|
||||
}
|
||||
func ==(x: InvalidCustomHashable, y: InvalidCustomHashable) -> String { // expected-note{{non-matching type}}
|
||||
func ==(x: InvalidCustomHashable, y: InvalidCustomHashable) -> String {
|
||||
return ""
|
||||
}
|
||||
if InvalidCustomHashable.A == .B { }
|
||||
@@ -100,27 +100,3 @@ private enum Bar<T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Equatable extension -- rdar://20981254
|
||||
enum Instrument {
|
||||
case Piano
|
||||
case Violin
|
||||
case Guitar
|
||||
}
|
||||
|
||||
extension Instrument : Equatable {}
|
||||
|
||||
// Explicit conformance should work too
|
||||
public enum Medicine {
|
||||
case Antibiotic
|
||||
case Antihistamine
|
||||
}
|
||||
|
||||
extension Medicine : Equatable {}
|
||||
|
||||
public func ==(lhs: Medicine, rhs: Medicine) -> Bool { // expected-note{{non-matching type}}
|
||||
return true
|
||||
}
|
||||
|
||||
// No explicit conformance and cannot be derived
|
||||
extension Complex : Hashable {} // expected-error 2 {{does not conform}}
|
||||
|
||||
@@ -31,9 +31,3 @@ public enum Lazy<T> : Computable {
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
public enum Breakfast<Champions> : Int {
|
||||
case Eggs
|
||||
case Bacon
|
||||
case Coffee
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
extension Breakfast : RawRepresentable {}
|
||||
|
||||
extension Breakfast : ErrorType {}
|
||||
@@ -1,6 +1,6 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: mkdir %t
|
||||
// RUN: %target-swift-frontend -emit-module -module-name def_enum -o %t %S/Inputs/def_enum.swift %S/Inputs/def_enum_derived.swift
|
||||
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/def_enum.swift
|
||||
// RUN: llvm-bcanalyzer %t/def_enum.swiftmodule | FileCheck %s
|
||||
// RUN: %target-swift-frontend -parse -I %t %s -o /dev/null
|
||||
// RUN: %target-swift-frontend -emit-sil -I %t %s -o /dev/null
|
||||
@@ -30,9 +30,3 @@ var comp : Computable = lazy
|
||||
comp.compute()
|
||||
lazy.compute()
|
||||
|
||||
struct Tea {}
|
||||
|
||||
let meal = Breakfast<Basic>.Bacon
|
||||
let n = meal.rawValue
|
||||
|
||||
do { throw meal } catch {}
|
||||
|
||||
Reference in New Issue
Block a user