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