Skip to content

Commit ae5b737

Browse files
authored
---
yaml --- r: 340331 b: refs/heads/rxwei-patch-1 c: 5d59600 h: refs/heads/master i: 340329: 0cf5b92 340327: 66b3d16
1 parent 86c81be commit ae5b737

File tree

88 files changed

+366
-226
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+366
-226
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1015,7 +1015,7 @@ refs/tags/swift-DEVELOPMENT-SNAPSHOT-2018-08-18-a: b10b1fce14385faa6d44f6b933e95
10151015
refs/heads/rdar-43033749-fix-batch-mode-no-diags-swift-5.0-branch: a14e64eaad30de89f0f5f0b2a782eed7ecdcb255
10161016
refs/heads/revert-19006-error-bridging-integer-type: 8a9065a3696535305ea53fe9b71f91cbe6702019
10171017
refs/heads/revert-19050-revert-19006-error-bridging-integer-type: ecf752d54b05dd0a20f510f0bfa54a3fec3bcaca
1018-
refs/heads/rxwei-patch-1: ae5a427193a42b9e7427d3f12453d3c03a9dcb12
1018+
refs/heads/rxwei-patch-1: 5d59600a534cff62a515724aae44209c5d25d4e3
10191019
refs/heads/shahmishal-patch-1: e58ec0f7488258d42bef51bc3e6d7b3dc74d7b2a
10201020
refs/heads/typelist-existential: 4046359efd541fb5c72d69a92eefc0a784df8f5e
10211021
refs/tags/swift-4.2-DEVELOPMENT-SNAPSHOT-2018-08-20-a: 4319ba09e4fb8650ee86061075c74a016b6baab9

branches/rxwei-patch-1/include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2538,6 +2538,12 @@ NOTE(decodable_suggest_overriding_init_here,none,
25382538
NOTE(codable_suggest_overriding_init_here,none,
25392539
"did you mean to override 'init(from:)' and 'encode(to:)'?", ())
25402540

2541+
NOTE(missing_member_type_conformance_prevents_synthesis, none,
2542+
"%select{associated value|stored property}0 type %1 does not conform to "
2543+
"protocol %2, preventing synthesized conformance "
2544+
"of %3 to %2",
2545+
(unsigned, Type, Type, Type))
2546+
25412547
// Dynamic Self
25422548
ERROR(dynamic_self_non_method,none,
25432549
"%select{global|local}0 function cannot return 'Self'", (bool))

branches/rxwei-patch-1/lib/AST/Decl.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5444,9 +5444,6 @@ PropertyWrapperTypeInfo VarDecl::getAttachedPropertyWrapperTypeInfo() const {
54445444

54455445
Type VarDecl::getAttachedPropertyWrapperType() const {
54465446
auto &ctx = getASTContext();
5447-
if (!ctx.getLazyResolver())
5448-
return nullptr;
5449-
54505447
auto mutableThis = const_cast<VarDecl *>(this);
54515448
return evaluateOrDefault(ctx.evaluator,
54525449
AttachedPropertyWrapperTypeRequest{mutableThis},
@@ -5455,9 +5452,6 @@ Type VarDecl::getAttachedPropertyWrapperType() const {
54555452

54565453
Type VarDecl::getPropertyWrapperBackingPropertyType() const {
54575454
ASTContext &ctx = getASTContext();
5458-
if (!ctx.getLazyResolver())
5459-
return nullptr;
5460-
54615455
auto mutableThis = const_cast<VarDecl *>(this);
54625456
return evaluateOrDefault(
54635457
ctx.evaluator, PropertyWrapperBackingPropertyTypeRequest{mutableThis},
@@ -5467,9 +5461,6 @@ Type VarDecl::getPropertyWrapperBackingPropertyType() const {
54675461
PropertyWrapperBackingPropertyInfo
54685462
VarDecl::getPropertyWrapperBackingPropertyInfo() const {
54695463
auto &ctx = getASTContext();
5470-
if (!ctx.getLazyResolver())
5471-
return PropertyWrapperBackingPropertyInfo();
5472-
54735464
auto mutableThis = const_cast<VarDecl *>(this);
54745465
return evaluateOrDefault(
54755466
ctx.evaluator,

branches/rxwei-patch-1/lib/AST/TypeCheckRequests.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,7 @@ void PropertyWrapperBackingPropertyTypeRequest::noteCycleStep(
648648
DiagnosticEngine &diags) const {
649649
std::get<0>(getStorage())->diagnose(diag::circular_reference_through);
650650
}
651+
651652
bool PropertyWrapperBackingPropertyInfoRequest::isCached() const {
652653
auto var = std::get<0>(getStorage());
653654
return !var->getAttrs().isEmpty();

branches/rxwei-patch-1/lib/Sema/DerivedConformanceEquatableHashable.cpp

Lines changed: 130 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,21 @@
3232

3333
using namespace swift;
3434

35-
/// Returns true if, for every element of the given enum, it either has no
36-
/// associated values or all of them conform to a protocol.
35+
enum NonconformingMemberKind {
36+
AssociatedValue,
37+
StoredProperty
38+
};
39+
40+
/// Returns the ParamDecl for each associated value of the given enum whose type
41+
/// does not conform to a protocol
3742
/// \p theEnum The enum whose elements and associated values should be checked.
3843
/// \p protocol The protocol being requested.
39-
/// \return True if all associated values of all elements of the enum conform.
40-
static bool allAssociatedValuesConformToProtocol(DeclContext *DC,
41-
EnumDecl *theEnum,
42-
ProtocolDecl *protocol) {
44+
/// \return The ParamDecl of each associated value whose type does not conform.
45+
static SmallVector<ParamDecl *, 3>
46+
associatedValuesNotConformingToProtocol(DeclContext *DC, EnumDecl *theEnum,
47+
ProtocolDecl *protocol) {
4348
auto lazyResolver = DC->getASTContext().getLazyResolver();
49+
SmallVector<ParamDecl *, 3> nonconformingAssociatedValues;
4450
for (auto elt : theEnum->getAllElements()) {
4551
if (!elt->hasInterfaceType())
4652
lazyResolver->resolveDeclSignature(elt);
@@ -53,38 +59,62 @@ static bool allAssociatedValuesConformToProtocol(DeclContext *DC,
5359
auto type = param->getInterfaceType();
5460
if (!TypeChecker::conformsToProtocol(DC->mapTypeIntoContext(type),
5561
protocol, DC, None)) {
56-
return false;
62+
nonconformingAssociatedValues.push_back(param);
5763
}
5864
}
5965
}
60-
return true;
66+
return nonconformingAssociatedValues;
6167
}
6268

63-
/// Returns true if every stored property in the given struct conforms to the
64-
/// protocol (or, vacuously, if it has no stored properties).
65-
/// \p theStruct The struct whose stored properties should be checked.
69+
/// Returns true if, for every element of the given enum, it either has no
70+
/// associated values or all of them conform to a protocol.
71+
/// \p theEnum The enum whose elements and associated values should be checked.
6672
/// \p protocol The protocol being requested.
67-
/// \return True if all stored properties of the struct conform.
68-
static bool allStoredPropertiesConformToProtocol(DeclContext *DC,
69-
StructDecl *theStruct,
73+
/// \return True if all associated values of all elements of the enum conform.
74+
static bool allAssociatedValuesConformToProtocol(DeclContext *DC,
75+
EnumDecl *theEnum,
7076
ProtocolDecl *protocol) {
77+
return associatedValuesNotConformingToProtocol(DC, theEnum, protocol).empty();
78+
}
79+
80+
/// Returns the VarDecl of each stored property in the given struct whose type
81+
/// does not conform to a protocol.
82+
/// \p theStruct The struct whose stored properties should be checked.
83+
/// \p protocol The protocol being requested.
84+
/// \return The VarDecl of each stored property whose type does not conform.
85+
static SmallVector<VarDecl *, 3>
86+
storedPropertiesNotConformingToProtocol(DeclContext *DC, StructDecl *theStruct,
87+
ProtocolDecl *protocol) {
7188
auto lazyResolver = DC->getASTContext().getLazyResolver();
7289
auto storedProperties =
73-
theStruct->getStoredProperties(/*skipInaccessible=*/true);
90+
theStruct->getStoredProperties(/*skipInaccessible=*/true);
91+
SmallVector<VarDecl *, 3> nonconformingProperties;
7492
for (auto propertyDecl : storedProperties) {
7593
if (!propertyDecl->hasInterfaceType())
7694
lazyResolver->resolveDeclSignature(propertyDecl);
7795
if (!propertyDecl->hasInterfaceType())
78-
return false;
96+
nonconformingProperties.push_back(propertyDecl);
7997

8098
auto type = propertyDecl->getValueInterfaceType();
8199

82-
if (!TypeChecker::conformsToProtocol(DC->mapTypeIntoContext(type),
83-
protocol, DC, None)) {
84-
return false;
100+
if (!TypeChecker::conformsToProtocol(DC->mapTypeIntoContext(type), protocol,
101+
DC, None)) {
102+
nonconformingProperties.push_back(propertyDecl);
85103
}
86104
}
87-
return true;
105+
return nonconformingProperties;
106+
}
107+
108+
/// Returns true if every stored property in the given struct conforms to the
109+
/// protocol (or, vacuously, if it has no stored properties).
110+
/// \p theStruct The struct whose stored properties should be checked.
111+
/// \p protocol The protocol being requested.
112+
/// \return True if all stored properties of the struct conform.
113+
static bool allStoredPropertiesConformToProtocol(DeclContext *DC,
114+
StructDecl *theStruct,
115+
ProtocolDecl *protocol) {
116+
return storedPropertiesNotConformingToProtocol(DC, theStruct, protocol)
117+
.empty();
88118
}
89119

90120
/// Common preconditions for Equatable and Hashable.
@@ -106,6 +136,39 @@ static bool canDeriveConformance(DeclContext *DC,
106136
return false;
107137
}
108138

139+
/// Diagnose failed conformance synthesis caused by a member type not conforming
140+
/// to the same protocol
141+
void diagnoseFailedDerivation(DeclContext *DC, NominalTypeDecl *nominal,
142+
ProtocolDecl *protocol) {
143+
ASTContext &ctx = DC->getASTContext();
144+
145+
if (auto *enumDecl = dyn_cast<EnumDecl>(nominal)) {
146+
auto nonconformingAssociatedTypes =
147+
associatedValuesNotConformingToProtocol(DC, enumDecl, protocol);
148+
for (auto *typeToDiagnose : nonconformingAssociatedTypes) {
149+
ctx.Diags.diagnose(
150+
typeToDiagnose->getTypeLoc().getLoc(),
151+
diag::missing_member_type_conformance_prevents_synthesis,
152+
NonconformingMemberKind::AssociatedValue,
153+
typeToDiagnose->getInterfaceType(), protocol->getDeclaredType(),
154+
nominal->getDeclaredInterfaceType());
155+
}
156+
}
157+
158+
if (auto *structDecl = dyn_cast<StructDecl>(nominal)) {
159+
auto nonconformingStoredProperties =
160+
storedPropertiesNotConformingToProtocol(DC, structDecl, protocol);
161+
for (auto *propertyToDiagnose : nonconformingStoredProperties) {
162+
ctx.Diags.diagnose(
163+
propertyToDiagnose->getLoc(),
164+
diag::missing_member_type_conformance_prevents_synthesis,
165+
NonconformingMemberKind::StoredProperty,
166+
propertyToDiagnose->getInterfaceType(), protocol->getDeclaredType(),
167+
nominal->getDeclaredInterfaceType());
168+
}
169+
}
170+
}
171+
109172
/// Creates a named variable based on a prefix character and a numeric index.
110173
/// \p prefixChar The prefix character for the variable's name.
111174
/// \p index The numeric index to append to the variable's name.
@@ -722,6 +785,13 @@ ValueDecl *DerivedConformance::deriveEquatable(ValueDecl *requirement) {
722785
return nullptr;
723786
}
724787

788+
void DerivedConformance::tryDiagnoseFailedEquatableDerivation(
789+
DeclContext *DC, NominalTypeDecl *nominal) {
790+
ASTContext &ctx = DC->getASTContext();
791+
auto *equatableProto = ctx.getProtocol(KnownProtocolKind::Equatable);
792+
diagnoseFailedDerivation(DC, nominal, equatableProto);
793+
}
794+
725795
/// Returns a new \c CallExpr representing
726796
///
727797
/// hasher.combine(hashable)
@@ -1055,18 +1125,41 @@ deriveBodyHashable_hashValue(AbstractFunctionDecl *hashValueDecl, void *) {
10551125

10561126
// return _hashValue(for: self)
10571127
auto *hashFunc = C.getHashValueForDecl();
1058-
auto hashExpr = new (C) DeclRefExpr(hashFunc, DeclNameLoc(),
1128+
if (!hashFunc->hasInterfaceType())
1129+
C.getLazyResolver()->resolveDeclSignature(hashFunc);
1130+
1131+
auto selfType = hashValueDecl->mapTypeIntoContext(
1132+
parentDC->getSelfInterfaceType());
1133+
auto hashableProto = C.getProtocol(KnownProtocolKind::Hashable);
1134+
auto conformance = TypeChecker::conformsToProtocol(selfType, hashableProto,
1135+
parentDC, None);
1136+
auto subs = SubstitutionMap::get(hashFunc->getGenericSignature(),
1137+
ArrayRef<Type>(selfType),
1138+
ArrayRef<ProtocolConformanceRef>(*conformance));
1139+
ConcreteDeclRef hashRef(hashFunc, subs);
1140+
1141+
auto hashExpr = new (C) DeclRefExpr(hashRef, DeclNameLoc(),
10591142
/*implicit*/ true);
1143+
1144+
Type intType = C.getIntDecl()->getDeclaredType();
1145+
hashExpr->setType(FunctionType::get(AnyFunctionType::Param(selfType),
1146+
intType));
1147+
10601148
auto selfDecl = hashValueDecl->getImplicitSelfDecl();
10611149
auto selfRef = new (C) DeclRefExpr(selfDecl, DeclNameLoc(),
10621150
/*implicit*/ true);
1063-
auto callExpr = CallExpr::createImplicit(C, hashExpr,
1064-
{ selfRef }, { C.Id_for });
1151+
selfRef->setType(selfType);
1152+
1153+
auto callExpr = CallExpr::createImplicit(C, hashExpr, { selfRef }, { });
1154+
callExpr->setType(intType);
1155+
callExpr->setThrows(false);
1156+
10651157
auto returnStmt = new (C) ReturnStmt(SourceLoc(), callExpr);
10661158

10671159
auto body = BraceStmt::create(C, SourceLoc(), {returnStmt}, SourceLoc(),
10681160
/*implicit*/ true);
10691161
hashValueDecl->setBody(body);
1162+
hashValueDecl->setBodyTypeCheckedIfPresent();
10701163
}
10711164

10721165
/// Derive a 'hashValue' implementation.
@@ -1185,6 +1278,13 @@ bool DerivedConformance::canDeriveHashable(NominalTypeDecl *type) {
11851278
return true;
11861279
}
11871280

1281+
void DerivedConformance::tryDiagnoseFailedHashableDerivation(
1282+
DeclContext *DC, NominalTypeDecl *nominal) {
1283+
ASTContext &ctx = DC->getASTContext();
1284+
auto *hashableProto = ctx.getProtocol(KnownProtocolKind::Hashable);
1285+
diagnoseFailedDerivation(DC, nominal, hashableProto);
1286+
}
1287+
11881288
ValueDecl *DerivedConformance::deriveHashable(ValueDecl *requirement) {
11891289
ASTContext &C = ConformanceDecl->getASTContext();
11901290

@@ -1218,6 +1318,13 @@ ValueDecl *DerivedConformance::deriveHashable(ValueDecl *requirement) {
12181318
ConformanceDecl->diagnose(diag::type_does_not_conform,
12191319
Nominal->getDeclaredType(),
12201320
hashableProto->getDeclaredType());
1321+
// Ideally, this would be diagnosed in
1322+
// ConformanceChecker::resolveWitnessViaLookup. That doesn't work for
1323+
// Hashable because DerivedConformance::canDeriveHashable returns true
1324+
// even if the conformance can't be derived. See the note there for
1325+
// details.
1326+
auto *dc = ConformanceDecl->getDeclContext();
1327+
tryDiagnoseFailedHashableDerivation(dc, Nominal);
12211328
return nullptr;
12221329
}
12231330

branches/rxwei-patch-1/lib/Sema/DerivedConformances.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,22 @@ bool DerivedConformance::derivesProtocolConformance(DeclContext *DC,
137137
return false;
138138
}
139139

140+
void DerivedConformance::tryDiagnoseFailedDerivation(DeclContext *DC,
141+
NominalTypeDecl *nominal,
142+
ProtocolDecl *protocol) {
143+
auto knownProtocol = protocol->getKnownProtocolKind();
144+
if (!knownProtocol)
145+
return;
146+
147+
if (*knownProtocol == KnownProtocolKind::Equatable) {
148+
tryDiagnoseFailedEquatableDerivation(DC, nominal);
149+
}
150+
151+
if (*knownProtocol == KnownProtocolKind::Hashable) {
152+
tryDiagnoseFailedHashableDerivation(DC, nominal);
153+
}
154+
}
155+
140156
ValueDecl *DerivedConformance::getDerivableRequirement(TypeChecker &tc,
141157
NominalTypeDecl *nominal,
142158
ValueDecl *requirement) {

branches/rxwei-patch-1/lib/Sema/DerivedConformances.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,18 @@ class DerivedConformance {
6969
NominalTypeDecl *nominal,
7070
ProtocolDecl *protocol);
7171

72+
/// Diagnose problems, if any, preventing automatic derivation of protocol
73+
/// requirements
74+
///
75+
/// \param nominal The nominal type for which we would like to diagnose
76+
/// derivation failures
77+
///
78+
/// \param protocol The protocol with requirements we would like to diagnose
79+
/// derivation failures for
80+
static void tryDiagnoseFailedDerivation(DeclContext *DC,
81+
NominalTypeDecl *nominal,
82+
ProtocolDecl *protocol);
83+
7284
/// Determine the derivable requirement that would satisfy the given
7385
/// requirement, if there is one.
7486
///
@@ -128,6 +140,14 @@ class DerivedConformance {
128140
/// \returns the derived member, which will also be added to the type.
129141
ValueDecl *deriveEquatable(ValueDecl *requirement);
130142

143+
/// Diagnose problems, if any, preventing automatic derivation of Equatable
144+
/// requirements
145+
///
146+
/// \param nominal The nominal type for which we would like to diagnose
147+
/// derivation failures
148+
static void tryDiagnoseFailedEquatableDerivation(DeclContext *DC,
149+
NominalTypeDecl *nominal);
150+
131151
/// Determine if a Hashable requirement can be derived for a type.
132152
///
133153
/// This is implemented for enums without associated values or all-Hashable
@@ -144,6 +164,14 @@ class DerivedConformance {
144164
/// \returns the derived member, which will also be added to the type.
145165
ValueDecl *deriveHashable(ValueDecl *requirement);
146166

167+
/// Diagnose problems, if any, preventing automatic derivation of Hashable
168+
/// requirements
169+
///
170+
/// \param nominal The nominal type for which we would like to diagnose
171+
/// derivation failures
172+
static void tryDiagnoseFailedHashableDerivation(DeclContext *DC,
173+
NominalTypeDecl *nominal);
174+
147175
/// Derive a _BridgedNSError requirement for an @objc enum type.
148176
///
149177
/// \returns the derived member, which will also be added to the type.

branches/rxwei-patch-1/lib/Sema/TypeCheckPropertyWrapper.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,12 +371,15 @@ AttachedPropertyWrapperTypeRequest::evaluate(Evaluator &evaluator,
371371
if (!customAttr)
372372
return Type();
373373

374+
ASTContext &ctx = var->getASTContext();
375+
if (!ctx.getLazyResolver())
376+
return nullptr;
377+
374378
auto resolution =
375379
TypeResolution::forContextual(var->getDeclContext());
376380
TypeResolutionOptions options(TypeResolverContext::PatternBindingDecl);
377381
options |= TypeResolutionFlags::AllowUnboundGenerics;
378382

379-
ASTContext &ctx = var->getASTContext();
380383
auto &tc = *static_cast<TypeChecker *>(ctx.getLazyResolver());
381384
if (tc.validateType(customAttr->getTypeLoc(), resolution, options))
382385
return ErrorType::get(ctx);
@@ -409,10 +412,13 @@ PropertyWrapperBackingPropertyTypeRequest::evaluate(
409412
if (!binding)
410413
return Type();
411414

415+
ASTContext &ctx = var->getASTContext();
416+
if (!ctx.getLazyResolver())
417+
return Type();
418+
412419
// If there's an initializer of some sort, checking it will determine the
413420
// property wrapper type.
414421
unsigned index = binding->getPatternEntryIndexForVarDecl(var);
415-
ASTContext &ctx = var->getASTContext();
416422
TypeChecker &tc = *static_cast<TypeChecker *>(ctx.getLazyResolver());
417423
if (binding->isInitialized(index)) {
418424
tc.validateDecl(var);

0 commit comments

Comments
 (0)