Skip to content

Commit b9f42b3

Browse files
authored
Merge pull request swiftlang#24665 from slavapestov/fully-checked-trivial-accessors
Build type checked bodies for more synthesized declarations
2 parents aea3626 + a18c32a commit b9f42b3

13 files changed

+849
-568
lines changed

lib/AST/Decl.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6856,7 +6856,13 @@ Type ConstructorDecl::getInitializerInterfaceType() {
68566856
return InitializerInterfaceType;
68576857

68586858
// Lazily calculate initializer type.
6859-
auto funcTy = getInterfaceType()->castTo<AnyFunctionType>()->getResult();
6859+
auto allocatorTy = getInterfaceType();
6860+
if (!allocatorTy->is<AnyFunctionType>()) {
6861+
InitializerInterfaceType = ErrorType::get(getASTContext());
6862+
return InitializerInterfaceType;
6863+
}
6864+
6865+
auto funcTy = allocatorTy->castTo<AnyFunctionType>()->getResult();
68606866
assert(funcTy->is<FunctionType>());
68616867

68626868
// Constructors have an initializer type that takes an instance

lib/SILGen/SILGenExpr.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,25 @@ RValue RValueEmitter::visitOtherConstructorDeclRefExpr(
931931
}
932932

933933
RValue RValueEmitter::visitNilLiteralExpr(NilLiteralExpr *E, SGFContext C) {
934+
// Peephole away the call to Optional<T>(nilLiteral: ()).
935+
if (E->getType()->getOptionalObjectType()) {
936+
auto *noneDecl = SGF.getASTContext().getOptionalNoneDecl();
937+
auto enumTy = SGF.getLoweredType(E->getType());
938+
939+
ManagedValue noneValue;
940+
if (enumTy.isLoadable(SGF.F) || !SGF.silConv.useLoweredAddresses()) {
941+
noneValue = ManagedValue::forUnmanaged(
942+
SGF.B.createEnum(E, SILValue(), noneDecl, enumTy));
943+
} else {
944+
noneValue =
945+
SGF.B.bufferForExpr(E, enumTy, SGF.getTypeLowering(enumTy), C,
946+
[&](SILValue newAddr) {
947+
SGF.B.createInjectEnumAddr(E, newAddr, noneDecl);
948+
});
949+
}
950+
return RValue(SGF, E, noneValue);
951+
}
952+
934953
return SGF.emitLiteral(E, C);
935954
}
936955

lib/Sema/CSApply.cpp

Lines changed: 10 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1912,57 +1912,27 @@ namespace {
19121912
}
19131913

19141914
Expr *visitNilLiteralExpr(NilLiteralExpr *expr) {
1915+
auto type = simplifyType(cs.getType(expr));
1916+
1917+
// By far the most common 'nil' literal is for Optional<T>.none.
1918+
// We don't have to look up the witness in this case since SILGen
1919+
// knows how to lower it directly.
1920+
if (auto objectType = type->getOptionalObjectType()) {
1921+
cs.setType(expr, type);
1922+
return expr;
1923+
}
1924+
19151925
auto &tc = cs.getTypeChecker();
19161926
auto *protocol = tc.getProtocol(expr->getLoc(),
19171927
KnownProtocolKind::ExpressibleByNilLiteral);
19181928

19191929
// For type-sugar reasons, prefer the spelling of the default literal
19201930
// type.
1921-
auto type = simplifyType(cs.getType(expr));
19221931
if (auto defaultType = tc.getDefaultType(protocol, dc)) {
19231932
if (defaultType->isEqual(type))
19241933
type = defaultType;
19251934
}
19261935

1927-
// By far the most common 'nil' literal is for Optional<T>.none.
1928-
//
1929-
// Emit this case directly instead of calling Optional.init(nilLiteral:),
1930-
// since this generates more efficient SIL.
1931-
if (auto objectType = type->getOptionalObjectType()) {
1932-
auto *nilDecl = tc.Context.getOptionalNoneDecl();
1933-
tc.validateDecl(nilDecl);
1934-
if (!nilDecl->hasInterfaceType())
1935-
return nullptr;
1936-
1937-
auto genericSig =
1938-
nilDecl->getDeclContext()->getGenericSignatureOfContext();
1939-
SubstitutionMap subs =
1940-
SubstitutionMap::get(genericSig, llvm::makeArrayRef(objectType),
1941-
{ });
1942-
ConcreteDeclRef concreteDeclRef(nilDecl, subs);
1943-
1944-
auto nilType = FunctionType::get(
1945-
{FunctionType::Param(MetatypeType::get(type))}, type);
1946-
auto *nilRefExpr = new (tc.Context) DeclRefExpr(
1947-
concreteDeclRef, DeclNameLoc(expr->getLoc()),
1948-
/*implicit=*/true, AccessSemantics::Ordinary,
1949-
nilType);
1950-
cs.cacheType(nilRefExpr);
1951-
1952-
auto *typeExpr = TypeExpr::createImplicitHack(
1953-
expr->getLoc(),
1954-
type,
1955-
tc.Context);
1956-
cs.cacheType(typeExpr);
1957-
1958-
auto *callExpr = new (tc.Context) DotSyntaxCallExpr(
1959-
nilRefExpr, expr->getLoc(), typeExpr, type);
1960-
callExpr->setImplicit(true);
1961-
cs.cacheType(callExpr);
1962-
1963-
return callExpr;
1964-
}
1965-
19661936
DeclName initName(tc.Context, DeclBaseName::createConstructor(),
19671937
{ tc.Context.Id_nilLiteral });
19681938
return convertLiteralInPlace(expr, type, protocol,

0 commit comments

Comments
 (0)