mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Sema] Migrate almost everything to use DerivedConformance.
This commit is contained in:
@@ -68,14 +68,13 @@ static ArraySliceType *computeAllCasesType(NominalTypeDecl *enumType) {
|
||||
return ArraySliceType::get(metaTy->getRValueInstanceType());
|
||||
}
|
||||
|
||||
static Type deriveCaseIterable_AllCases(TypeChecker &tc, Decl *parentDecl,
|
||||
EnumDecl *enumDecl) {
|
||||
static Type deriveCaseIterable_AllCases(DerivedConformance &derived) {
|
||||
// enum SomeEnum : CaseIterable {
|
||||
// @derived
|
||||
// typealias AllCases = [SomeEnum]
|
||||
// }
|
||||
auto *rawInterfaceType = computeAllCasesType(enumDecl);
|
||||
return cast<DeclContext>(parentDecl)->mapTypeIntoContext(rawInterfaceType);
|
||||
auto *rawInterfaceType = computeAllCasesType(cast<EnumDecl>(derived.Nominal));
|
||||
return derived.getConformanceContext()->mapTypeIntoContext(rawInterfaceType);
|
||||
}
|
||||
|
||||
ValueDecl *DerivedConformance::deriveCaseIterable(ValueDecl *requirement) {
|
||||
@@ -115,10 +114,7 @@ ValueDecl *DerivedConformance::deriveCaseIterable(ValueDecl *requirement) {
|
||||
|
||||
getterDecl->setBodySynthesizer(&deriveCaseIterable_enum_getter);
|
||||
|
||||
auto dc = cast<IterableDeclContext>(ConformanceDecl);
|
||||
dc->addMember(getterDecl);
|
||||
dc->addMember(propDecl);
|
||||
dc->addMember(pbDecl);
|
||||
addMembersToConformanceContext({getterDecl, propDecl, pbDecl});
|
||||
|
||||
return propDecl;
|
||||
}
|
||||
@@ -139,8 +135,7 @@ Type DerivedConformance::deriveCaseIterable(AssociatedTypeDecl *assocType) {
|
||||
return nullptr;
|
||||
|
||||
if (assocType->getName() == TC.Context.Id_AllCases) {
|
||||
auto enumDecl = cast<EnumDecl>(Nominal);
|
||||
return deriveCaseIterable_AllCases(TC, ConformanceDecl, enumDecl);
|
||||
return deriveCaseIterable_AllCases(*this);
|
||||
}
|
||||
|
||||
TC.diagnose(assocType->getLoc(), diag::broken_case_iterable_requirement);
|
||||
|
||||
@@ -144,17 +144,11 @@ static CodableConformanceType varConformsToCodable(TypeChecker &tc,
|
||||
/// Validates the given CodingKeys enum decl by ensuring its cases are a 1-to-1
|
||||
/// match with the stored vars of the given type.
|
||||
///
|
||||
/// \param tc The typechecker to use in validating {En,De}codable conformance.
|
||||
///
|
||||
/// \param codingKeysDecl The \c CodingKeys enum decl to validate.
|
||||
///
|
||||
/// \param target The nominal type decl to validate the \c CodingKeys against.
|
||||
///
|
||||
/// \param proto The {En,De}codable protocol to validate all the keys conform
|
||||
/// to.
|
||||
static bool
|
||||
validateCodingKeysEnum(TypeChecker &tc, EnumDecl *codingKeysDecl,
|
||||
NominalTypeDecl *target, ProtocolDecl *proto) {
|
||||
static bool validateCodingKeysEnum(DerivedConformance &derived,
|
||||
EnumDecl *codingKeysDecl) {
|
||||
auto &tc = derived.TC;
|
||||
|
||||
// Look through all var decls in the given type.
|
||||
// * Filter out lazy/computed vars.
|
||||
// * Filter out ones which are present in the given decl (by name).
|
||||
@@ -167,7 +161,8 @@ validateCodingKeysEnum(TypeChecker &tc, EnumDecl *codingKeysDecl,
|
||||
// Here we'll hold on to properties by name -- when we've validated a property
|
||||
// against its CodingKey entry, it will get removed.
|
||||
llvm::SmallDenseMap<Identifier, VarDecl *, 8> properties;
|
||||
for (auto *varDecl : target->getStoredProperties(/*skipInaccessible=*/true)) {
|
||||
for (auto *varDecl :
|
||||
derived.Nominal->getStoredProperties(/*skipInaccessible=*/true)) {
|
||||
if (varDecl->getAttrs().hasAttribute<LazyAttr>())
|
||||
continue;
|
||||
|
||||
@@ -187,8 +182,8 @@ validateCodingKeysEnum(TypeChecker &tc, EnumDecl *codingKeysDecl,
|
||||
}
|
||||
|
||||
// We have a property to map to. Ensure it's {En,De}codable.
|
||||
auto conformance = varConformsToCodable(tc, target->getDeclContext(),
|
||||
it->second, proto);
|
||||
auto conformance = varConformsToCodable(
|
||||
tc, derived.Nominal->getDeclContext(), it->second, derived.Protocol);
|
||||
switch (conformance) {
|
||||
case Conforms:
|
||||
// The property was valid. Remove it from the list.
|
||||
@@ -198,7 +193,7 @@ validateCodingKeysEnum(TypeChecker &tc, EnumDecl *codingKeysDecl,
|
||||
case DoesNotConform:
|
||||
tc.diagnose(it->second->getLoc(),
|
||||
diag::codable_non_conforming_property_here,
|
||||
proto->getDeclaredType(), it->second->getType());
|
||||
derived.getProtocolType(), it->second->getType());
|
||||
LLVM_FALLTHROUGH;
|
||||
|
||||
case TypeNotValidated:
|
||||
@@ -216,7 +211,7 @@ validateCodingKeysEnum(TypeChecker &tc, EnumDecl *codingKeysDecl,
|
||||
// we can skip them on encode. On decode, though, we can only skip them if
|
||||
// they have a default value.
|
||||
if (!properties.empty() &&
|
||||
proto->isSpecificProtocol(KnownProtocolKind::Decodable)) {
|
||||
derived.Protocol->isSpecificProtocol(KnownProtocolKind::Decodable)) {
|
||||
for (auto it = properties.begin(); it != properties.end(); ++it) {
|
||||
// If the var is default initializable, then it need not have an explicit
|
||||
// initial value.
|
||||
@@ -233,7 +228,7 @@ validateCodingKeysEnum(TypeChecker &tc, EnumDecl *codingKeysDecl,
|
||||
// initial value.
|
||||
propertiesAreValid = false;
|
||||
tc.diagnose(it->second->getLoc(), diag::codable_non_decoded_property_here,
|
||||
proto->getDeclaredType(), it->first);
|
||||
derived.getProtocolType(), it->first);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,19 +251,12 @@ struct CodingKeysValidity {
|
||||
/// diagnostics here, we don't want to then attempt to synthesize a CodingKeys
|
||||
/// enum.
|
||||
///
|
||||
/// \param tc The typechecker to use in validating {En,Decodable} conformance.
|
||||
///
|
||||
/// \param target The type decl whose nested \c CodingKeys type to validate.
|
||||
///
|
||||
/// \param proto The {En,De}codable protocol to ensure the properties matching
|
||||
/// the keys conform to.
|
||||
///
|
||||
/// \returns A \c CodingKeysValidity value representing the result of the check.
|
||||
static CodingKeysValidity hasValidCodingKeysEnum(TypeChecker &tc,
|
||||
NominalTypeDecl *target,
|
||||
ProtocolDecl *proto) {
|
||||
static CodingKeysValidity hasValidCodingKeysEnum(DerivedConformance &derived) {
|
||||
auto &tc = derived.TC;
|
||||
auto &C = tc.Context;
|
||||
auto codingKeysDecls = target->lookupDirect(DeclName(C.Id_CodingKeys));
|
||||
auto codingKeysDecls =
|
||||
derived.Nominal->lookupDirect(DeclName(C.Id_CodingKeys));
|
||||
if (codingKeysDecls.empty())
|
||||
return CodingKeysValidity(/*hasType=*/false, /*isValid=*/true);
|
||||
|
||||
@@ -281,7 +269,7 @@ static CodingKeysValidity hasValidCodingKeysEnum(TypeChecker &tc,
|
||||
if (!codingKeysTypeDecl) {
|
||||
tc.diagnose(result->getLoc(),
|
||||
diag::codable_codingkeys_type_is_not_an_enum_here,
|
||||
proto->getDeclaredType());
|
||||
derived.getProtocolType());
|
||||
return CodingKeysValidity(/*hasType=*/true, /*isValid=*/false);
|
||||
}
|
||||
|
||||
@@ -297,7 +285,7 @@ static CodingKeysValidity hasValidCodingKeysEnum(TypeChecker &tc,
|
||||
// Ensure that the type we found conforms to the CodingKey protocol.
|
||||
auto *codingKeyProto = C.getProtocol(KnownProtocolKind::CodingKey);
|
||||
if (!tc.conformsToProtocol(codingKeysType, codingKeyProto,
|
||||
target->getDeclContext(),
|
||||
derived.Nominal->getDeclContext(),
|
||||
ConformanceCheckFlags::Used)) {
|
||||
// If CodingKeys is a typealias which doesn't point to a valid nominal type,
|
||||
// codingKeysTypeDecl will be nullptr here. In that case, we need to warn on
|
||||
@@ -308,7 +296,7 @@ static CodingKeysValidity hasValidCodingKeysEnum(TypeChecker &tc,
|
||||
cast<TypeDecl>(result)->getLoc();
|
||||
|
||||
tc.diagnose(loc, diag::codable_codingkeys_type_does_not_conform_here,
|
||||
proto->getDeclaredType());
|
||||
derived.getProtocolType());
|
||||
|
||||
return CodingKeysValidity(/*hasType=*/true, /*isValid=*/false);
|
||||
}
|
||||
@@ -318,29 +306,20 @@ static CodingKeysValidity hasValidCodingKeysEnum(TypeChecker &tc,
|
||||
if (!codingKeysEnum) {
|
||||
tc.diagnose(codingKeysTypeDecl->getLoc(),
|
||||
diag::codable_codingkeys_type_is_not_an_enum_here,
|
||||
proto->getDeclaredType());
|
||||
derived.getProtocolType());
|
||||
return CodingKeysValidity(/*hasType=*/true, /*isValid=*/false);
|
||||
}
|
||||
|
||||
bool valid = validateCodingKeysEnum(tc, codingKeysEnum, target, proto);
|
||||
bool valid = validateCodingKeysEnum(derived, codingKeysEnum);
|
||||
return CodingKeysValidity(/*hasType=*/true, /*isValid=*/valid);
|
||||
}
|
||||
|
||||
/// Synthesizes a new \c CodingKeys enum based on the {En,De}codable members of
|
||||
/// the given type (\c nullptr if unable to synthesize).
|
||||
///
|
||||
/// If able to synthesize the enum, adds it directly to \c type.
|
||||
///
|
||||
/// \param tc The typechecker to use in validating {En,De}codable conformance.
|
||||
///
|
||||
/// \param target The nominal type decl whose nested \c CodingKeys type to
|
||||
/// synthesize.
|
||||
///
|
||||
/// \param proto The {En,De}codable protocol to validate all the keys conform
|
||||
/// to.
|
||||
static EnumDecl *synthesizeCodingKeysEnum(TypeChecker &tc,
|
||||
NominalTypeDecl *target,
|
||||
ProtocolDecl *proto) {
|
||||
/// If able to synthesize the enum, adds it directly to \c derived.Nominal.
|
||||
static EnumDecl *synthesizeCodingKeysEnum(DerivedConformance &derived) {
|
||||
auto &tc = derived.TC;
|
||||
auto &C = tc.Context;
|
||||
|
||||
// We want to look through all the var declarations of this type to create
|
||||
@@ -350,6 +329,7 @@ static EnumDecl *synthesizeCodingKeysEnum(TypeChecker &tc,
|
||||
TypeLoc protoTypeLoc[1] = {TypeLoc::withoutLoc(codingKeyType)};
|
||||
MutableArrayRef<TypeLoc> inherited = C.AllocateCopy(protoTypeLoc);
|
||||
|
||||
auto target = derived.Nominal;
|
||||
auto *enumDecl = new (C) EnumDecl(SourceLoc(), C.Id_CodingKeys, SourceLoc(),
|
||||
inherited, nullptr, target);
|
||||
enumDecl->setImplicit();
|
||||
@@ -377,7 +357,7 @@ static EnumDecl *synthesizeCodingKeysEnum(TypeChecker &tc,
|
||||
continue;
|
||||
|
||||
auto conformance = varConformsToCodable(tc, target->getDeclContext(),
|
||||
varDecl, proto);
|
||||
varDecl, derived.Protocol);
|
||||
switch (conformance) {
|
||||
case Conforms:
|
||||
{
|
||||
@@ -392,7 +372,7 @@ static EnumDecl *synthesizeCodingKeysEnum(TypeChecker &tc,
|
||||
case DoesNotConform:
|
||||
tc.diagnose(varDecl->getLoc(),
|
||||
diag::codable_non_conforming_property_here,
|
||||
proto->getDeclaredType(), varDecl->getType());
|
||||
derived.getProtocolType(), varDecl->getType());
|
||||
LLVM_FALLTHROUGH;
|
||||
|
||||
case TypeNotValidated:
|
||||
@@ -703,15 +683,10 @@ static void deriveBodyEncodable_encode(AbstractFunctionDecl *encodeDecl) {
|
||||
/// lazily synthesized body for the given type.
|
||||
///
|
||||
/// Adds the function declaration to the given type before returning it.
|
||||
///
|
||||
/// \param tc The type checker whose AST context to synthesize the decl in.
|
||||
///
|
||||
/// \param parentDecl The parent declaration of the type.
|
||||
///
|
||||
/// \param target The nominal type to synthesize the function for.
|
||||
static FuncDecl *deriveEncodable_encode(TypeChecker &tc, Decl *parentDecl,
|
||||
NominalTypeDecl *target) {
|
||||
auto &C = tc.Context;
|
||||
static FuncDecl *deriveEncodable_encode(DerivedConformance &derived) {
|
||||
auto &C = derived.TC.Context;
|
||||
|
||||
auto target = derived.Nominal;
|
||||
|
||||
// Expected type: (Self) -> (Encoder) throws -> ()
|
||||
// Constructed as: func type
|
||||
@@ -783,7 +758,7 @@ static FuncDecl *deriveEncodable_encode(TypeChecker &tc, Decl *parentDecl,
|
||||
encodeDecl->setValidationStarted();
|
||||
encodeDecl->copyFormalAccessFrom(target, /*sourceIsParentContext*/true);
|
||||
|
||||
tc.Context.addSynthesizedDecl(encodeDecl);
|
||||
C.addSynthesizedDecl(encodeDecl);
|
||||
|
||||
target->addMember(encodeDecl);
|
||||
return encodeDecl;
|
||||
@@ -1034,15 +1009,10 @@ static void deriveBodyDecodable_init(AbstractFunctionDecl *initDecl) {
|
||||
/// lazily synthesized body for the given type.
|
||||
///
|
||||
/// Adds the function declaration to the given type before returning it.
|
||||
///
|
||||
/// \param tc The type checker whose AST context to synthesize the decl in.
|
||||
///
|
||||
/// \param parentDecl The parent declaration of the type.
|
||||
///
|
||||
/// \param target The nominal type to synthesize the function for.
|
||||
static ValueDecl *deriveDecodable_init(TypeChecker &tc, Decl *parentDecl,
|
||||
NominalTypeDecl *target) {
|
||||
auto &C = tc.Context;
|
||||
static ValueDecl *deriveDecodable_init(DerivedConformance &derived) {
|
||||
auto &C = derived.TC.Context;
|
||||
|
||||
auto target = derived.Nominal;
|
||||
|
||||
// Expected type: (Self) -> (Decoder) throws -> (Self)
|
||||
// Constructed as: func type
|
||||
@@ -1123,9 +1093,9 @@ static ValueDecl *deriveDecodable_init(TypeChecker &tc, Decl *parentDecl,
|
||||
initDecl->setInitializerInterfaceType(initializerType);
|
||||
initDecl->copyFormalAccessFrom(target, /*sourceIsParentContext*/true);
|
||||
|
||||
tc.Context.addSynthesizedDecl(initDecl);
|
||||
C.addSynthesizedDecl(initDecl);
|
||||
|
||||
target->addMember(initDecl);
|
||||
derived.addMembersToConformanceContext({initDecl});
|
||||
return initDecl;
|
||||
}
|
||||
|
||||
@@ -1134,15 +1104,8 @@ static ValueDecl *deriveDecodable_init(TypeChecker &tc, Decl *parentDecl,
|
||||
/// Checks to see whether the given type has a valid \c CodingKeys enum, and if
|
||||
/// not, attempts to synthesize one for it.
|
||||
///
|
||||
/// \param tc The typechecker to use in validating {En,Decodable} conformance.
|
||||
///
|
||||
/// \param target The type to validate.
|
||||
///
|
||||
/// \param requirement The requirement we want to synthesize.
|
||||
///
|
||||
/// \param proto The *codable protocol to check for validity.
|
||||
static bool canSynthesize(TypeChecker &tc, NominalTypeDecl *target,
|
||||
ValueDecl *requirement, ProtocolDecl *proto) {
|
||||
static bool canSynthesize(DerivedConformance &derived, ValueDecl *requirement) {
|
||||
// Before we attempt to look up (or more importantly, synthesize) a CodingKeys
|
||||
// entity on target, we need to make sure the type is otherwise valid.
|
||||
//
|
||||
@@ -1153,8 +1116,10 @@ static bool canSynthesize(TypeChecker &tc, NominalTypeDecl *target,
|
||||
//
|
||||
// If the required initializer is not available, we shouldn't attempt to
|
||||
// synthesize CodingKeys.
|
||||
auto &tc = derived.TC;
|
||||
ASTContext &C = tc.Context;
|
||||
auto *classDecl = dyn_cast<ClassDecl>(target);
|
||||
auto proto = derived.Protocol;
|
||||
auto *classDecl = dyn_cast<ClassDecl>(derived.Nominal);
|
||||
if (proto->isSpecificProtocol(KnownProtocolKind::Decodable) && classDecl) {
|
||||
if (auto *superclassDecl = classDecl->getSuperclassDecl()) {
|
||||
DeclName memberName;
|
||||
@@ -1192,9 +1157,9 @@ static bool canSynthesize(TypeChecker &tc, NominalTypeDecl *target,
|
||||
diag::decodable_super_init_not_designated_here,
|
||||
requirement->getFullName(), memberName);
|
||||
return false;
|
||||
} else if (!initializer->isAccessibleFrom(target)) {
|
||||
} else if (!initializer->isAccessibleFrom(classDecl)) {
|
||||
// Cannot call an inaccessible method.
|
||||
auto accessScope = initializer->getFormalAccessScope(target);
|
||||
auto accessScope = initializer->getFormalAccessScope(classDecl);
|
||||
tc.diagnose(initializer, diag::decodable_inaccessible_super_init_here,
|
||||
requirement->getFullName(), memberName,
|
||||
accessScope.accessLevelForDiagnostics());
|
||||
@@ -1212,7 +1177,7 @@ static bool canSynthesize(TypeChecker &tc, NominalTypeDecl *target,
|
||||
|
||||
// If the target already has a valid CodingKeys enum, we won't need to
|
||||
// synthesize one.
|
||||
auto validity = hasValidCodingKeysEnum(tc, target, proto);
|
||||
auto validity = hasValidCodingKeysEnum(derived);
|
||||
|
||||
// We found a type, but it wasn't valid.
|
||||
if (!validity.isValid)
|
||||
@@ -1220,7 +1185,7 @@ static bool canSynthesize(TypeChecker &tc, NominalTypeDecl *target,
|
||||
|
||||
// We can try to synthesize a type here.
|
||||
if (!validity.hasType) {
|
||||
auto *synthesizedEnum = synthesizeCodingKeysEnum(tc, target, proto);
|
||||
auto *synthesizedEnum = synthesizeCodingKeysEnum(derived);
|
||||
if (!synthesizedEnum)
|
||||
return false;
|
||||
}
|
||||
@@ -1271,9 +1236,9 @@ ValueDecl *DerivedConformance::deriveEncodable(ValueDecl *requirement) {
|
||||
|
||||
// Check other preconditions for synthesized conformance.
|
||||
// This synthesizes a CodingKeys enum if possible.
|
||||
if (canSynthesize(TC, Nominal, requirement, encodableProto)) {
|
||||
if (canSynthesize(*this, requirement)) {
|
||||
diagnosticTransaction.abort();
|
||||
return deriveEncodable_encode(TC, ConformanceDecl, Nominal);
|
||||
return deriveEncodable_encode(*this);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@@ -1313,9 +1278,9 @@ ValueDecl *DerivedConformance::deriveDecodable(ValueDecl *requirement) {
|
||||
|
||||
// Check other preconditions for synthesized conformance.
|
||||
// This synthesizes a CodingKeys enum if possible.
|
||||
if (canSynthesize(TC, Nominal, requirement, decodableProto)) {
|
||||
if (canSynthesize(*this, requirement)) {
|
||||
diagnosticTransaction.abort();
|
||||
return deriveDecodable_init(TC, ConformanceDecl, Nominal);
|
||||
return deriveDecodable_init(*this);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
||||
@@ -102,24 +102,17 @@ static void deriveRawValueInit(AbstractFunctionDecl *initDecl) {
|
||||
/// Synthesizes a constructor declaration with the given parameter name and
|
||||
/// type.
|
||||
///
|
||||
/// \param tc The type checker to use in synthesizing the constructor.
|
||||
///
|
||||
/// \param parentDecl The parent declaration of the enum.
|
||||
///
|
||||
/// \param enumDecl The enum on which to synthesize the constructor.
|
||||
///
|
||||
/// \param paramType The type of the parameter.
|
||||
///
|
||||
/// \param paramName The name of the parameter.
|
||||
///
|
||||
/// \param synthesizer A lambda to call to set the constructor's body.
|
||||
template <typename Synthesizer>
|
||||
static ValueDecl *deriveInitDecl(TypeChecker &tc, Decl *parentDecl,
|
||||
EnumDecl *enumDecl, Type paramType,
|
||||
static ValueDecl *deriveInitDecl(DerivedConformance &derived, Type paramType,
|
||||
Identifier paramName,
|
||||
const Synthesizer &synthesizer) {
|
||||
auto &C = tc.Context;
|
||||
auto *parentDC = cast<DeclContext>(parentDecl);
|
||||
auto &C = derived.TC.Context;
|
||||
auto *parentDC = derived.getConformanceContext();
|
||||
|
||||
// rawValue
|
||||
auto *rawDecl =
|
||||
@@ -179,12 +172,12 @@ static ValueDecl *deriveInitDecl(TypeChecker &tc, Decl *parentDecl,
|
||||
}
|
||||
initDecl->setInterfaceType(allocIfaceType);
|
||||
initDecl->setInitializerInterfaceType(initIfaceType);
|
||||
initDecl->setAccess(enumDecl->getFormalAccess());
|
||||
initDecl->setAccess(derived.Nominal->getFormalAccess());
|
||||
initDecl->setValidationStarted();
|
||||
|
||||
tc.Context.addSynthesizedDecl(initDecl);
|
||||
C.addSynthesizedDecl(initDecl);
|
||||
|
||||
cast<IterableDeclContext>(parentDecl)->addMember(initDecl);
|
||||
derived.addMembersToConformanceContext({initDecl});
|
||||
return initDecl;
|
||||
}
|
||||
|
||||
@@ -366,24 +359,18 @@ deriveBodyCodingKey_init_stringValue(AbstractFunctionDecl *initDecl) {
|
||||
}
|
||||
|
||||
/// Returns whether the given enum is eligible for CodingKey synthesis.
|
||||
///
|
||||
/// \param tc The type checker to use in checking eligibility.
|
||||
///
|
||||
/// \param parentDecl The parent declaration of the enum.
|
||||
///
|
||||
/// \param enumDecl The enum to check.
|
||||
static bool canSynthesizeCodingKey(TypeChecker &tc, Decl *parentDecl,
|
||||
EnumDecl *enumDecl) {
|
||||
static bool canSynthesizeCodingKey(DerivedConformance &derived) {
|
||||
auto enumDecl = cast<EnumDecl>(derived.Nominal);
|
||||
// Validate the enum and its raw type.
|
||||
tc.validateDecl(enumDecl);
|
||||
derived.TC.validateDecl(enumDecl);
|
||||
|
||||
// If the enum has a raw type (optional), it must be String or Int.
|
||||
Type rawType = enumDecl->getRawType();
|
||||
if (rawType) {
|
||||
auto *parentDC = cast<DeclContext>(parentDecl);
|
||||
auto *parentDC = derived.getConformanceContext();
|
||||
rawType = parentDC->mapTypeIntoContext(rawType);
|
||||
|
||||
auto &C = tc.Context;
|
||||
auto &C = derived.TC.Context;
|
||||
auto *nominal = rawType->getCanonicalType()->getAnyNominal();
|
||||
if (nominal != C.getStringDecl() && nominal != C.getIntDecl())
|
||||
return false;
|
||||
@@ -407,7 +394,7 @@ ValueDecl *DerivedConformance::deriveCodingKey(ValueDecl *requirement) {
|
||||
return nullptr;
|
||||
|
||||
// Check other preconditions for synthesized conformance.
|
||||
if (!canSynthesizeCodingKey(TC, Nominal, enumDecl))
|
||||
if (!canSynthesizeCodingKey(*this))
|
||||
return nullptr;
|
||||
|
||||
auto &C = TC.Context;
|
||||
@@ -505,8 +492,7 @@ ValueDecl *DerivedConformance::deriveCodingKey(ValueDecl *requirement) {
|
||||
}
|
||||
};
|
||||
|
||||
return deriveInitDecl(TC, ConformanceDecl, enumDecl, stringType,
|
||||
C.Id_stringValue, synth);
|
||||
return deriveInitDecl(*this, stringType, C.Id_stringValue, synth);
|
||||
} else if (argumentNames[0] == C.Id_intValue) {
|
||||
// Synthesize `init?(intValue:)`
|
||||
auto intType = C.getIntDecl()->getDeclaredType();
|
||||
@@ -530,8 +516,7 @@ ValueDecl *DerivedConformance::deriveCodingKey(ValueDecl *requirement) {
|
||||
}
|
||||
};
|
||||
|
||||
return deriveInitDecl(TC, ConformanceDecl, enumDecl, intType,
|
||||
C.Id_intValue, synthesizer);
|
||||
return deriveInitDecl(*this, intType, C.Id_intValue, synthesizer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -541,8 +541,7 @@ static void deriveBodyEquatable_struct_eq(AbstractFunctionDecl *eqDecl) {
|
||||
|
||||
/// Derive an '==' operator implementation for an enum or a struct.
|
||||
static ValueDecl *
|
||||
deriveEquatable_eq(TypeChecker &tc, Decl *parentDecl, NominalTypeDecl *typeDecl,
|
||||
Identifier generatedIdentifier,
|
||||
deriveEquatable_eq(DerivedConformance &derived, Identifier generatedIdentifier,
|
||||
void (*bodySynthesizer)(AbstractFunctionDecl *)) {
|
||||
// enum SomeEnum<T...> {
|
||||
// case A, B(Int), C(String, Int)
|
||||
@@ -579,9 +578,9 @@ deriveEquatable_eq(TypeChecker &tc, Decl *parentDecl, NominalTypeDecl *typeDecl,
|
||||
// }
|
||||
// }
|
||||
|
||||
ASTContext &C = tc.Context;
|
||||
ASTContext &C = derived.TC.Context;
|
||||
|
||||
auto parentDC = cast<DeclContext>(parentDecl);
|
||||
auto parentDC = derived.getConformanceContext();
|
||||
auto enumTy = parentDC->getDeclaredTypeInContext();
|
||||
auto enumIfaceTy = parentDC->getDeclaredInterfaceType();
|
||||
|
||||
@@ -634,14 +633,15 @@ deriveEquatable_eq(TypeChecker &tc, Decl *parentDecl, NominalTypeDecl *typeDecl,
|
||||
DeclNameLoc()));
|
||||
|
||||
if (!C.getEqualIntDecl()) {
|
||||
tc.diagnose(parentDecl->getLoc(), diag::no_equal_overload_for_int);
|
||||
derived.TC.diagnose(derived.ConformanceDecl->getLoc(),
|
||||
diag::no_equal_overload_for_int);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
eqDecl->setBodySynthesizer(bodySynthesizer);
|
||||
|
||||
// Compute the type.
|
||||
Type paramsTy = params[1]->getType(tc.Context);
|
||||
Type paramsTy = params[1]->getType(C);
|
||||
|
||||
// Compute the interface type.
|
||||
Type interfaceTy;
|
||||
@@ -664,13 +664,13 @@ deriveEquatable_eq(TypeChecker &tc, Decl *parentDecl, NominalTypeDecl *typeDecl,
|
||||
FunctionType::ExtInfo());
|
||||
}
|
||||
eqDecl->setInterfaceType(interfaceTy);
|
||||
eqDecl->copyFormalAccessFrom(typeDecl, /*sourceIsParentContext*/true);
|
||||
eqDecl->copyFormalAccessFrom(derived.Nominal, /*sourceIsParentContext*/ true);
|
||||
eqDecl->setValidationStarted();
|
||||
|
||||
tc.Context.addSynthesizedDecl(eqDecl);
|
||||
C.addSynthesizedDecl(eqDecl);
|
||||
|
||||
// Add the operator to the parent scope.
|
||||
cast<IterableDeclContext>(parentDecl)->addMember(eqDecl);
|
||||
derived.addMembersToConformanceContext({eqDecl});
|
||||
|
||||
return eqDecl;
|
||||
}
|
||||
@@ -701,12 +701,10 @@ ValueDecl *DerivedConformance::deriveEquatable(ValueDecl *requirement) {
|
||||
theEnum->hasOnlyCasesWithoutAssociatedValues()
|
||||
? &deriveBodyEquatable_enum_noAssociatedValues_eq
|
||||
: &deriveBodyEquatable_enum_hasAssociatedValues_eq;
|
||||
return deriveEquatable_eq(TC, ConformanceDecl, theEnum,
|
||||
TC.Context.Id_derived_enum_equals,
|
||||
return deriveEquatable_eq(*this, TC.Context.Id_derived_enum_equals,
|
||||
bodySynthesizer);
|
||||
} else if (auto theStruct = dyn_cast<StructDecl>(Nominal))
|
||||
return deriveEquatable_eq(TC, ConformanceDecl, theStruct,
|
||||
TC.Context.Id_derived_struct_equals,
|
||||
} else if (isa<StructDecl>(Nominal))
|
||||
return deriveEquatable_eq(*this, TC.Context.Id_derived_struct_equals,
|
||||
&deriveBodyEquatable_struct_eq);
|
||||
else
|
||||
llvm_unreachable("todo");
|
||||
@@ -740,13 +738,12 @@ static CallExpr *createHasherCombineCall(ASTContext &C,
|
||||
}
|
||||
|
||||
static FuncDecl *
|
||||
deriveHashable_hashInto(TypeChecker &tc, Decl *parentDecl,
|
||||
NominalTypeDecl *typeDecl,
|
||||
deriveHashable_hashInto(DerivedConformance &derived,
|
||||
void (*bodySynthesizer)(AbstractFunctionDecl *)) {
|
||||
// @derived func hash(into hasher: inout Hasher)
|
||||
|
||||
ASTContext &C = tc.Context;
|
||||
auto parentDC = cast<DeclContext>(parentDecl);
|
||||
ASTContext &C = derived.TC.Context;
|
||||
auto parentDC = derived.getConformanceContext();
|
||||
|
||||
// Expected type: (Self) -> (into: inout Hasher) -> ()
|
||||
// Constructed as:
|
||||
@@ -757,8 +754,9 @@ deriveHashable_hashInto(TypeChecker &tc, Decl *parentDecl,
|
||||
|
||||
auto hasherDecl = C.getHasherDecl();
|
||||
if (!hasherDecl) {
|
||||
auto hashableProto = tc.Context.getProtocol(KnownProtocolKind::Hashable);
|
||||
tc.diagnose(hashableProto->getLoc(), diag::broken_hashable_no_hasher);
|
||||
auto hashableProto = C.getProtocol(KnownProtocolKind::Hashable);
|
||||
derived.TC.diagnose(hashableProto->getLoc(),
|
||||
diag::broken_hashable_no_hasher);
|
||||
return nullptr;
|
||||
}
|
||||
Type hasherType = hasherDecl->getDeclaredType();
|
||||
@@ -807,12 +805,12 @@ deriveHashable_hashInto(TypeChecker &tc, Decl *parentDecl,
|
||||
FunctionType::ExtInfo());
|
||||
}
|
||||
hashDecl->setInterfaceType(interfaceType);
|
||||
hashDecl->copyFormalAccessFrom(typeDecl);
|
||||
hashDecl->copyFormalAccessFrom(derived.Nominal);
|
||||
hashDecl->setValidationStarted();
|
||||
|
||||
C.addSynthesizedDecl(hashDecl);
|
||||
|
||||
cast<IterableDeclContext>(parentDecl)->addMember(hashDecl);
|
||||
derived.addMembersToConformanceContext({hashDecl});
|
||||
return hashDecl;
|
||||
}
|
||||
|
||||
@@ -1038,29 +1036,30 @@ deriveBodyHashable_hashValue(AbstractFunctionDecl *hashValueDecl) {
|
||||
}
|
||||
|
||||
/// Derive a 'hashValue' implementation.
|
||||
static ValueDecl *
|
||||
deriveHashable_hashValue(TypeChecker &tc, Decl *parentDecl,
|
||||
NominalTypeDecl *typeDecl) {
|
||||
static ValueDecl *deriveHashable_hashValue(DerivedConformance &derived) {
|
||||
// @derived var hashValue: Int {
|
||||
// return _hashValue(for: self)
|
||||
// }
|
||||
auto &tc = derived.TC;
|
||||
ASTContext &C = tc.Context;
|
||||
|
||||
auto parentDC = cast<DeclContext>(parentDecl);
|
||||
auto parentDC = derived.getConformanceContext();
|
||||
Type intType = C.getIntDecl()->getDeclaredType();
|
||||
|
||||
// We can't form a Hashable conformance if Int isn't Hashable or
|
||||
// ExpressibleByIntegerLiteral.
|
||||
if (!tc.conformsToProtocol(intType,C.getProtocol(KnownProtocolKind::Hashable),
|
||||
typeDecl, None)) {
|
||||
tc.diagnose(typeDecl->getLoc(), diag::broken_int_hashable_conformance);
|
||||
if (!tc.conformsToProtocol(intType,
|
||||
C.getProtocol(KnownProtocolKind::Hashable),
|
||||
derived.Nominal, None)) {
|
||||
tc.diagnose(derived.Nominal->getLoc(),
|
||||
diag::broken_int_hashable_conformance);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ProtocolDecl *intLiteralProto =
|
||||
C.getProtocol(KnownProtocolKind::ExpressibleByIntegerLiteral);
|
||||
if (!tc.conformsToProtocol(intType, intLiteralProto, typeDecl, None)) {
|
||||
tc.diagnose(typeDecl->getLoc(),
|
||||
if (!tc.conformsToProtocol(intType, intLiteralProto, derived.Nominal, None)) {
|
||||
tc.diagnose(derived.Nominal->getLoc(),
|
||||
diag::broken_int_integer_literal_convertible_conformance);
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1088,7 +1087,7 @@ deriveHashable_hashValue(TypeChecker &tc, Decl *parentDecl,
|
||||
getterDecl->setBodySynthesizer(&deriveBodyHashable_hashValue);
|
||||
|
||||
// Compute the type of hashValue().
|
||||
Type methodType = FunctionType::get(TupleType::getEmpty(tc.Context), intType);
|
||||
Type methodType = FunctionType::get(TupleType::getEmpty(C), intType);
|
||||
|
||||
// Compute the interface type of hashValue().
|
||||
Type interfaceType;
|
||||
@@ -1103,7 +1102,8 @@ deriveHashable_hashValue(TypeChecker &tc, Decl *parentDecl,
|
||||
|
||||
getterDecl->setInterfaceType(interfaceType);
|
||||
getterDecl->setValidationStarted();
|
||||
getterDecl->copyFormalAccessFrom(typeDecl, /*sourceIsParentContext*/true);
|
||||
getterDecl->copyFormalAccessFrom(derived.Nominal,
|
||||
/*sourceIsParentContext*/ true);
|
||||
|
||||
// Finish creating the property.
|
||||
hashValueDecl->setImplicit();
|
||||
@@ -1111,7 +1111,8 @@ deriveHashable_hashValue(TypeChecker &tc, Decl *parentDecl,
|
||||
hashValueDecl->setValidationStarted();
|
||||
hashValueDecl->makeComputed(SourceLoc(), getterDecl,
|
||||
nullptr, nullptr, SourceLoc());
|
||||
hashValueDecl->copyFormalAccessFrom(typeDecl, /*sourceIsParentContext*/true);
|
||||
hashValueDecl->copyFormalAccessFrom(derived.Nominal,
|
||||
/*sourceIsParentContext*/ true);
|
||||
|
||||
Pattern *hashValuePat = new (C) NamedPattern(hashValueDecl, /*implicit*/true);
|
||||
hashValuePat->setType(intType);
|
||||
@@ -1126,13 +1127,10 @@ deriveHashable_hashValue(TypeChecker &tc, Decl *parentDecl,
|
||||
parentDC);
|
||||
patDecl->setImplicit();
|
||||
|
||||
tc.Context.addSynthesizedDecl(hashValueDecl);
|
||||
tc.Context.addSynthesizedDecl(getterDecl);
|
||||
C.addSynthesizedDecl(hashValueDecl);
|
||||
C.addSynthesizedDecl(getterDecl);
|
||||
|
||||
auto dc = cast<IterableDeclContext>(parentDecl);
|
||||
dc->addMember(getterDecl);
|
||||
dc->addMember(hashValueDecl);
|
||||
dc->addMember(patDecl);
|
||||
derived.addMembersToConformanceContext({getterDecl, hashValueDecl, patDecl});
|
||||
return hashValueDecl;
|
||||
}
|
||||
|
||||
@@ -1180,7 +1178,7 @@ ValueDecl *DerivedConformance::deriveHashable(ValueDecl *requirement) {
|
||||
if (requirement->getBaseName() == C.Id_hashValue) {
|
||||
// We always allow hashValue to be synthesized; invalid cases are diagnosed
|
||||
// during hash(into:) synthesis.
|
||||
return deriveHashable_hashValue(TC, ConformanceDecl, Nominal);
|
||||
return deriveHashable_hashValue(*this);
|
||||
}
|
||||
|
||||
// Hashable.hash(into:)
|
||||
@@ -1223,10 +1221,9 @@ ValueDecl *DerivedConformance::deriveHashable(ValueDecl *requirement) {
|
||||
auto bodySynthesizer = hasAssociatedValues
|
||||
? &deriveBodyHashable_enum_hasAssociatedValues_hashInto
|
||||
: &deriveBodyHashable_enum_noAssociatedValues_hashInto;
|
||||
return deriveHashable_hashInto(TC, ConformanceDecl, theEnum,
|
||||
bodySynthesizer);
|
||||
} else if (auto theStruct = dyn_cast<StructDecl>(Nominal))
|
||||
return deriveHashable_hashInto(TC, ConformanceDecl, theStruct,
|
||||
return deriveHashable_hashInto(*this, bodySynthesizer);
|
||||
} else if (isa<StructDecl>(Nominal))
|
||||
return deriveHashable_hashInto(*this,
|
||||
&deriveBodyHashable_struct_hashInto);
|
||||
else // This should've been caught by canDeriveHashable above.
|
||||
llvm_unreachable("Attempt to derive Hashable for a type other "
|
||||
@@ -1234,7 +1231,7 @@ ValueDecl *DerivedConformance::deriveHashable(ValueDecl *requirement) {
|
||||
} else {
|
||||
// We can always derive hash(into:) if hashValue has an explicit
|
||||
// implementation.
|
||||
return deriveHashable_hashInto(TC, ConformanceDecl, Nominal,
|
||||
return deriveHashable_hashInto(*this,
|
||||
&deriveBodyHashable_compat_hashInto);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,10 +80,7 @@ deriveBridgedNSError_enum_nsErrorDomain(DerivedConformance &derived) {
|
||||
derived.TC, propDecl, stringTy);
|
||||
getterDecl->setBodySynthesizer(&deriveBodyBridgedNSError_enum_nsErrorDomain);
|
||||
|
||||
auto dc = cast<IterableDeclContext>(derived.ConformanceDecl);
|
||||
dc->addMember(getterDecl);
|
||||
dc->addMember(propDecl);
|
||||
dc->addMember(pbDecl);
|
||||
derived.addMembersToConformanceContext({getterDecl, propDecl, pbDecl});
|
||||
|
||||
return propDecl;
|
||||
}
|
||||
|
||||
@@ -50,14 +50,13 @@ static LiteralExpr *cloneRawLiteralExpr(ASTContext &C, LiteralExpr *expr) {
|
||||
return clone;
|
||||
}
|
||||
|
||||
static Type deriveRawRepresentable_Raw(TypeChecker &tc, Decl *parentDecl,
|
||||
EnumDecl *enumDecl) {
|
||||
static Type deriveRawRepresentable_Raw(DerivedConformance &derived) {
|
||||
// enum SomeEnum : SomeType {
|
||||
// @derived
|
||||
// typealias Raw = SomeType
|
||||
// }
|
||||
auto rawInterfaceType = enumDecl->getRawType();
|
||||
return cast<DeclContext>(parentDecl)->mapTypeIntoContext(rawInterfaceType);
|
||||
auto rawInterfaceType = cast<EnumDecl>(derived.Nominal)->getRawType();
|
||||
return derived.getConformanceContext()->mapTypeIntoContext(rawInterfaceType);
|
||||
}
|
||||
|
||||
static void deriveBodyRawRepresentable_raw(AbstractFunctionDecl *toRawDecl) {
|
||||
@@ -122,11 +121,11 @@ static void deriveBodyRawRepresentable_raw(AbstractFunctionDecl *toRawDecl) {
|
||||
toRawDecl->setBody(body);
|
||||
}
|
||||
|
||||
static VarDecl *deriveRawRepresentable_raw(DerivedConformance &derived,
|
||||
EnumDecl *enumDecl) {
|
||||
static VarDecl *deriveRawRepresentable_raw(DerivedConformance &derived) {
|
||||
ASTContext &C = derived.TC.Context;
|
||||
|
||||
auto parentDC = cast<DeclContext>(derived.ConformanceDecl);
|
||||
auto enumDecl = cast<EnumDecl>(derived.Nominal);
|
||||
auto parentDC = derived.getConformanceContext();
|
||||
auto rawInterfaceType = enumDecl->getRawType();
|
||||
auto rawType = parentDC->mapTypeIntoContext(rawInterfaceType);
|
||||
|
||||
@@ -153,10 +152,7 @@ static VarDecl *deriveRawRepresentable_raw(DerivedConformance &derived,
|
||||
getterDecl->getAttrs().add(new (C) InlinableAttr(/*implicit*/false));
|
||||
}
|
||||
|
||||
auto dc = cast<IterableDeclContext>(derived.ConformanceDecl);
|
||||
dc->addMember(getterDecl);
|
||||
dc->addMember(propDecl);
|
||||
dc->addMember(pbDecl);
|
||||
derived.addMembersToConformanceContext({getterDecl, propDecl, pbDecl});
|
||||
|
||||
return propDecl;
|
||||
}
|
||||
@@ -279,12 +275,13 @@ deriveBodyRawRepresentable_init(AbstractFunctionDecl *initDecl) {
|
||||
initDecl->setBody(body);
|
||||
}
|
||||
|
||||
static ConstructorDecl *deriveRawRepresentable_init(TypeChecker &tc,
|
||||
Decl *parentDecl,
|
||||
EnumDecl *enumDecl) {
|
||||
static ConstructorDecl *
|
||||
deriveRawRepresentable_init(DerivedConformance &derived) {
|
||||
auto &tc = derived.TC;
|
||||
ASTContext &C = tc.Context;
|
||||
|
||||
auto parentDC = cast<DeclContext>(parentDecl);
|
||||
auto enumDecl = cast<EnumDecl>(derived.Nominal);
|
||||
auto parentDC = derived.getConformanceContext();
|
||||
auto rawInterfaceType = enumDecl->getRawType();
|
||||
auto rawType = parentDC->mapTypeIntoContext(rawInterfaceType);
|
||||
|
||||
@@ -362,14 +359,16 @@ static ConstructorDecl *deriveRawRepresentable_init(TypeChecker &tc,
|
||||
initDecl->getAttrs().add(new (C) InlinableAttr(/*implicit*/false));
|
||||
}
|
||||
|
||||
tc.Context.addSynthesizedDecl(initDecl);
|
||||
C.addSynthesizedDecl(initDecl);
|
||||
|
||||
cast<IterableDeclContext>(parentDecl)->addMember(initDecl);
|
||||
derived.addMembersToConformanceContext({initDecl});
|
||||
return initDecl;
|
||||
}
|
||||
|
||||
static bool canSynthesizeRawRepresentable(TypeChecker &tc, Decl *parentDecl,
|
||||
EnumDecl *enumDecl) {
|
||||
static bool canSynthesizeRawRepresentable(DerivedConformance &derived) {
|
||||
auto enumDecl = cast<EnumDecl>(derived.Nominal);
|
||||
auto &tc = derived.TC;
|
||||
|
||||
// Validate the enum and its raw type.
|
||||
tc.validateDecl(enumDecl);
|
||||
|
||||
@@ -377,7 +376,7 @@ static bool canSynthesizeRawRepresentable(TypeChecker &tc, Decl *parentDecl,
|
||||
Type rawType = enumDecl->getRawType();
|
||||
if (!rawType)
|
||||
return false;
|
||||
auto parentDC = cast<DeclContext>(parentDecl);
|
||||
auto parentDC = cast<DeclContext>(derived.ConformanceDecl);
|
||||
rawType = parentDC->mapTypeIntoContext(rawType);
|
||||
|
||||
auto inherited = enumDecl->getInherited();
|
||||
@@ -387,8 +386,8 @@ static bool canSynthesizeRawRepresentable(TypeChecker &tc, Decl *parentDecl,
|
||||
|
||||
// The raw type must be Equatable, so that we have a suitable ~= for
|
||||
// synthesized switch statements.
|
||||
auto equatableProto = tc.getProtocol(enumDecl->getLoc(),
|
||||
KnownProtocolKind::Equatable);
|
||||
auto equatableProto =
|
||||
tc.getProtocol(enumDecl->getLoc(), KnownProtocolKind::Equatable);
|
||||
if (!equatableProto)
|
||||
return false;
|
||||
|
||||
@@ -416,19 +415,18 @@ static bool canSynthesizeRawRepresentable(TypeChecker &tc, Decl *parentDecl,
|
||||
ValueDecl *DerivedConformance::deriveRawRepresentable(ValueDecl *requirement) {
|
||||
|
||||
// We can only synthesize RawRepresentable for enums.
|
||||
auto enumDecl = dyn_cast<EnumDecl>(Nominal);
|
||||
if (!enumDecl)
|
||||
if (!isa<EnumDecl>(Nominal))
|
||||
return nullptr;
|
||||
|
||||
// Check other preconditions for synthesized conformance.
|
||||
if (!canSynthesizeRawRepresentable(TC, ConformanceDecl, enumDecl))
|
||||
if (!canSynthesizeRawRepresentable(*this))
|
||||
return nullptr;
|
||||
|
||||
if (requirement->getBaseName() == TC.Context.Id_rawValue)
|
||||
return deriveRawRepresentable_raw(*this, enumDecl);
|
||||
return deriveRawRepresentable_raw(*this);
|
||||
|
||||
if (requirement->getBaseName() == DeclBaseName::createConstructor())
|
||||
return deriveRawRepresentable_init(TC, ConformanceDecl, enumDecl);
|
||||
return deriveRawRepresentable_init(*this);
|
||||
|
||||
TC.diagnose(requirement->getLoc(),
|
||||
diag::broken_raw_representable_requirement);
|
||||
@@ -438,16 +436,15 @@ ValueDecl *DerivedConformance::deriveRawRepresentable(ValueDecl *requirement) {
|
||||
Type DerivedConformance::deriveRawRepresentable(AssociatedTypeDecl *assocType) {
|
||||
|
||||
// We can only synthesize RawRepresentable for enums.
|
||||
auto enumDecl = dyn_cast<EnumDecl>(Nominal);
|
||||
if (!enumDecl)
|
||||
if (!isa<EnumDecl>(Nominal))
|
||||
return nullptr;
|
||||
|
||||
// Check other preconditions for synthesized conformance.
|
||||
if (!canSynthesizeRawRepresentable(TC, ConformanceDecl, enumDecl))
|
||||
if (!canSynthesizeRawRepresentable(*this))
|
||||
return nullptr;
|
||||
|
||||
if (assocType->getName() == TC.Context.Id_RawValue) {
|
||||
return deriveRawRepresentable_Raw(TC, ConformanceDecl, enumDecl);
|
||||
return deriveRawRepresentable_Raw(*this);
|
||||
}
|
||||
|
||||
TC.diagnose(assocType->getLoc(), diag::broken_raw_representable_requirement);
|
||||
|
||||
@@ -27,10 +27,26 @@ DerivedConformance::DerivedConformance(TypeChecker &tc, Decl *conformanceDecl,
|
||||
ProtocolDecl *protocol)
|
||||
: TC(tc), ConformanceDecl(conformanceDecl), Nominal(nominal),
|
||||
Protocol(protocol) {
|
||||
assert(cast<DeclContext>(conformanceDecl)
|
||||
assert(getConformanceContext()
|
||||
->getAsNominalTypeOrNominalTypeExtensionContext() == nominal);
|
||||
}
|
||||
|
||||
DeclContext *DerivedConformance::getConformanceContext() const {
|
||||
return cast<DeclContext>(ConformanceDecl);
|
||||
}
|
||||
|
||||
void DerivedConformance::addMembersToConformanceContext(
|
||||
ArrayRef<Decl *> children) {
|
||||
auto IDC = cast<IterableDeclContext>(ConformanceDecl);
|
||||
for (auto child : children) {
|
||||
IDC->addMember(child);
|
||||
}
|
||||
}
|
||||
|
||||
Type DerivedConformance::getProtocolType() const {
|
||||
return Protocol->getDeclaredType();
|
||||
}
|
||||
|
||||
bool DerivedConformance::derivesProtocolConformance(TypeChecker &TC,
|
||||
NominalTypeDecl *Nominal,
|
||||
ProtocolDecl *Protocol) {
|
||||
|
||||
@@ -41,6 +41,16 @@ public:
|
||||
DerivedConformance(TypeChecker &tc, Decl *conformanceDecl,
|
||||
NominalTypeDecl *nominal, ProtocolDecl *protocol);
|
||||
|
||||
/// Retrieve the context in which the conformance is declared (either the
|
||||
/// nominal type, or an extension of it) as a \c DeclContext.
|
||||
DeclContext *getConformanceContext() const;
|
||||
|
||||
/// Add \c children as members of the context that declares the conformance.
|
||||
void addMembersToConformanceContext(ArrayRef<Decl *> children);
|
||||
|
||||
/// Get the declared type of the protocol that this is conformance is for.
|
||||
Type getProtocolType() const;
|
||||
|
||||
/// True if the type can implicitly derive a conformance for the given
|
||||
/// protocol.
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user