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:
Ted Kremenek
2015-05-23 15:26:55 +00:00
parent 9917e74533
commit a575727a2b
18 changed files with 163 additions and 321 deletions

View File

@@ -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;

View File

@@ -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,

View File

@@ -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());

View File

@@ -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,11 +288,10 @@ 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.
@@ -310,7 +301,7 @@ ValueDecl *DerivedConformance::deriveEquatable(TypeChecker &tc,
// 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");
} }

View File

@@ -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); enumDecl->addMember(getterDecl);
dc->addMember(getterDecl); enumDecl->addMember(propDecl);
dc->addMember(propDecl); enumDecl->addMember(pbDecl);
dc->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;
} }

View File

@@ -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(),

View File

@@ -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};

View File

@@ -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,

View File

@@ -5338,13 +5338,6 @@ 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);
@@ -5352,6 +5345,10 @@ public:
visit(Global); visit(Global);
} }
if (!IsFirstPass) {
computeDefaultAccessibility(TC, ED);
checkExplicitConformance(ED, ED->getExtendedType());
}
TC.checkDeclAttributes(ED); TC.checkDeclAttributes(ED);
} }

View File

@@ -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;

View File

@@ -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

View File

@@ -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);
} }

View File

@@ -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
}

View File

@@ -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 {}

View File

@@ -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}}

View File

@@ -31,9 +31,3 @@ public enum Lazy<T> : Computable {
// } // }
} }
} }
public enum Breakfast<Champions> : Int {
case Eggs
case Bacon
case Coffee
}

View File

@@ -1,3 +0,0 @@
extension Breakfast : RawRepresentable {}
extension Breakfast : ErrorType {}

View File

@@ -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 {}