Skip to content

Commit f368ebf

Browse files
committed
---
yaml --- r: 349607 b: refs/heads/master-next c: 930a142 h: refs/heads/master i: 349605: aba6e27 349603: 1b296b2 349599: 56192a2
1 parent 8f47210 commit f368ebf

File tree

2 files changed

+74
-16
lines changed

2 files changed

+74
-16
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
refs/heads/master: 3574c513bbc5578dd9346b4ea9ab5995c5927bb5
3-
refs/heads/master-next: 8f203f393074efe245a47c9ff9ad198b67817cc5
3+
refs/heads/master-next: 930a142c203987a2d83f9f05f50ee06a71f50083
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea
66
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-b: 66d897bfcf64a82cb9a87f5e663d889189d06d07

branches/master-next/lib/Sema/DerivedConformanceEquatableHashable.cpp

Lines changed: 73 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,17 @@ enumElementPayloadSubpattern(EnumElementDecl *enumElementDecl,
257257
return pat;
258258
}
259259

260+
/// Build a type-checked integer literal.
261+
static IntegerLiteralExpr *buildIntegerLiteral(ASTContext &C, unsigned index) {
262+
Type intType = C.getIntDecl()->getDeclaredType();
263+
264+
auto literal = IntegerLiteralExpr::createFromUnsigned(C, index);
265+
literal->setType(intType);
266+
literal->setBuiltinInitializer(C.getIntBuiltinInitDecl(C.getIntDecl()));
267+
268+
return literal;
269+
}
270+
260271
/// Create AST statements which convert from an enum to an Int with a switch.
261272
/// \p stmts The generated statements are appended to this vector.
262273
/// \p parentDC Either an extension or the enum itself.
@@ -298,15 +309,20 @@ static DeclRefExpr *convertEnumToIndex(SmallVectorImpl<ASTNode> &stmts,
298309
SourceLoc(), SourceLoc(),
299310
Identifier(), elt, nullptr);
300311
pat->setImplicit();
312+
pat->setType(enumType);
301313

302314
auto labelItem = CaseLabelItem(pat);
303315

304316
// generate: indexVar = <index>
305-
auto indexExpr = IntegerLiteralExpr::createFromUnsigned(C, index++);
317+
auto indexExpr = buildIntegerLiteral(C, index++);
318+
306319
auto indexRef = new (C) DeclRefExpr(indexVar, DeclNameLoc(),
307-
/*implicit*/true);
320+
/*implicit*/true,
321+
AccessSemantics::Ordinary,
322+
LValueType::get(intType));
308323
auto assignExpr = new (C) AssignExpr(indexRef, SourceLoc(),
309324
indexExpr, /*implicit*/ true);
325+
assignExpr->setType(TupleType::getEmpty(C));
310326
auto body = BraceStmt::create(C, SourceLoc(), ASTNode(assignExpr),
311327
SourceLoc());
312328
cases.push_back(CaseStmt::create(C, SourceLoc(), labelItem, SourceLoc(),
@@ -316,7 +332,9 @@ static DeclRefExpr *convertEnumToIndex(SmallVectorImpl<ASTNode> &stmts,
316332

317333
// generate: switch enumVar { }
318334
auto enumRef = new (C) DeclRefExpr(enumVarDecl, DeclNameLoc(),
319-
/*implicit*/true);
335+
/*implicit*/true,
336+
AccessSemantics::Ordinary,
337+
enumVarDecl->getType());
320338
auto switchStmt = SwitchStmt::create(LabeledStmtInfo(), SourceLoc(), enumRef,
321339
SourceLoc(), cases, SourceLoc(), C);
322340

@@ -381,17 +399,23 @@ deriveBodyEquatable_enum_uninhabited_eq(AbstractFunctionDecl *eqDecl, void *) {
381399
SmallVector<ASTNode, 0> cases;
382400

383401
// switch (a, b) { }
384-
auto aRef = new (C) DeclRefExpr(aParam, DeclNameLoc(), /*implicit*/ true);
385-
auto bRef = new (C) DeclRefExpr(bParam, DeclNameLoc(), /*implicit*/ true);
402+
auto aRef = new (C) DeclRefExpr(aParam, DeclNameLoc(), /*implicit*/ true,
403+
AccessSemantics::Ordinary,
404+
aParam->getType());
405+
auto bRef = new (C) DeclRefExpr(bParam, DeclNameLoc(), /*implicit*/ true,
406+
AccessSemantics::Ordinary,
407+
bParam->getType());
408+
TupleTypeElt abTupleElts[2] = { aParam->getType(), bParam->getType() };
386409
auto abExpr = TupleExpr::create(C, SourceLoc(), {aRef, bRef}, {}, {},
387410
SourceLoc(), /*HasTrailingClosure*/ false,
388-
/*implicit*/ true);
411+
/*implicit*/ true,
412+
TupleType::get(abTupleElts, C));
389413
auto switchStmt = SwitchStmt::create(LabeledStmtInfo(), SourceLoc(), abExpr,
390414
SourceLoc(), cases, SourceLoc(), C);
391415
statements.push_back(switchStmt);
392416

393417
auto body = BraceStmt::create(C, SourceLoc(), statements, SourceLoc());
394-
return { body, /*isTypeChecked=*/false };
418+
return { body, /*isTypeChecked=*/true };
395419
}
396420

397421
/// Derive the body for an '==' operator for an enum that has no associated
@@ -439,16 +463,20 @@ deriveBodyEquatable_enum_noAssociatedValues_eq(AbstractFunctionDecl *eqDecl,
439463
fnType);
440464
}
441465

466+
TupleTypeElt abTupleElts[2] = { aIndex->getType(), bIndex->getType() };
442467
TupleExpr *abTuple = TupleExpr::create(C, SourceLoc(), { aIndex, bIndex },
443468
{ }, { }, SourceLoc(),
444469
/*HasTrailingClosure*/ false,
445-
/*Implicit*/ true);
470+
/*Implicit*/ true,
471+
TupleType::get(abTupleElts, C));
446472

447-
auto *cmpExpr = new (C) BinaryExpr(cmpFuncExpr, abTuple, /*implicit*/ true);
473+
auto *cmpExpr = new (C) BinaryExpr(
474+
cmpFuncExpr, abTuple, /*implicit*/ true,
475+
fnType->castTo<FunctionType>()->getResult());
448476
statements.push_back(new (C) ReturnStmt(SourceLoc(), cmpExpr));
449477

450478
BraceStmt *body = BraceStmt::create(C, SourceLoc(), statements, SourceLoc());
451-
return { body, /*isTypeChecked=*/false };
479+
return { body, /*isTypeChecked=*/true };
452480
}
453481

454482
/// Derive the body for an '==' operator for an enum where at least one of the
@@ -1132,19 +1160,49 @@ deriveBodyHashable_hashValue(AbstractFunctionDecl *hashValueDecl, void *) {
11321160
ASTContext &C = parentDC->getASTContext();
11331161

11341162
// return _hashValue(for: self)
1135-
auto *hashFunc = C.getHashValueForDecl();
1136-
auto hashExpr = new (C) DeclRefExpr(hashFunc, DeclNameLoc(),
1137-
/*implicit*/ true);
1163+
1164+
// 'self'
11381165
auto selfDecl = hashValueDecl->getImplicitSelfDecl();
1166+
Type selfType = selfDecl->getType();
11391167
auto selfRef = new (C) DeclRefExpr(selfDecl, DeclNameLoc(),
1140-
/*implicit*/ true);
1168+
/*implicit*/ true,
1169+
AccessSemantics::Ordinary,
1170+
selfType);
1171+
1172+
// _hashValue(for:)
1173+
auto *hashFunc = C.getHashValueForDecl();
1174+
if (!hashFunc->hasInterfaceType())
1175+
static_cast<TypeChecker *>(C.getLazyResolver())->validateDecl(hashFunc);
1176+
1177+
auto substitutions = SubstitutionMap::get(
1178+
hashFunc->getGenericSignature(),
1179+
[&](SubstitutableType *dependentType) {
1180+
if (auto gp = dyn_cast<GenericTypeParamType>(dependentType)) {
1181+
if (gp->getDepth() == 0 && gp->getIndex() == 0)
1182+
return selfType;
1183+
}
1184+
1185+
return Type(dependentType);
1186+
},
1187+
LookUpConformanceInModule(hashValueDecl->getModuleContext()));
1188+
ConcreteDeclRef hashFuncRef(hashFunc, substitutions);
1189+
1190+
Type hashFuncType = hashFunc->getInterfaceType().subst(substitutions);
1191+
auto hashExpr = new (C) DeclRefExpr(hashFuncRef, DeclNameLoc(),
1192+
/*implicit*/ true,
1193+
AccessSemantics::Ordinary,
1194+
hashFuncType);
1195+
Type hashFuncResultType =
1196+
hashFuncType->castTo<AnyFunctionType>()->getResult();
11411197
auto callExpr = CallExpr::createImplicit(C, hashExpr,
11421198
{ selfRef }, { C.Id_for });
1199+
callExpr->setType(hashFuncResultType);
1200+
11431201
auto returnStmt = new (C) ReturnStmt(SourceLoc(), callExpr);
11441202

11451203
auto body = BraceStmt::create(C, SourceLoc(), {returnStmt}, SourceLoc(),
11461204
/*implicit*/ true);
1147-
return { body, /*isTypeChecked=*/false };
1205+
return { body, /*isTypeChecked=*/true };
11481206
}
11491207

11501208
/// Derive a 'hashValue' implementation.

0 commit comments

Comments
 (0)