Skip to content

Commit 4474118

Browse files
committed
---
yaml --- r: 348140 b: refs/heads/master c: 63ad182 h: refs/heads/master
1 parent 3f1098d commit 4474118

19 files changed

+221
-99
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 3c5a513352a7876ae5586248605b915af37839a2
2+
refs/heads/master: 63ad18242b8f7ba9987f6902318139b853095983
33
refs/heads/master-next: 203b3026584ecad859eb328b2e12490099409cd5
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea

trunk/include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4152,6 +4152,9 @@ ERROR(availability_protocol_requires_version,
41524152
NOTE(availability_protocol_requirement_here, none,
41534153
"protocol requirement here", ())
41544154

4155+
WARNING(public_decl_needs_availability, none,
4156+
"public declarations should have an availability attribute with -require-explicit-availability", ())
4157+
41554158
// This doesn't display as an availability diagnostic, but it's
41564159
// implemented there and fires when these subscripts are marked
41574160
// unavailable, so it seems appropriate to put it here.

trunk/include/swift/AST/Expr.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2126,8 +2126,6 @@ class CollectionExpr : public Expr {
21262126
SourceLoc RBracketLoc;
21272127
ConcreteDeclRef Initializer;
21282128

2129-
Expr *SemanticExpr = nullptr;
2130-
21312129
/// Retrieve the intrusive pointer storage from the subtype
21322130
Expr *const *getTrailingObjectsPointer() const;
21332131
Expr **getTrailingObjectsPointer() {
@@ -2192,9 +2190,6 @@ class CollectionExpr : public Expr {
21922190
SourceRange getSourceRange() const {
21932191
return SourceRange(LBracketLoc, RBracketLoc);
21942192
}
2195-
2196-
Expr *getSemanticExpr() const { return SemanticExpr; }
2197-
void setSemanticExpr(Expr *e) { SemanticExpr = e; }
21982193

21992194
static bool classof(const Expr *e) {
22002195
return e->getKind() >= ExprKind::First_CollectionExpr &&
@@ -2272,6 +2267,8 @@ class DictionaryExpr final : public CollectionExpr,
22722267
static bool classof(const Expr *e) {
22732268
return e->getKind() == ExprKind::Dictionary;
22742269
}
2270+
2271+
Type getElementType();
22752272
};
22762273

22772274
/// Subscripting expressions like a[i] that refer to an element within a

trunk/include/swift/Basic/LangOptions.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,13 @@ namespace swift {
9696
/// Enable 'availability' restrictions for App Extensions.
9797
bool EnableAppExtensionRestrictions = false;
9898

99+
/// Require public declarations to declare an introduction OS version.
100+
bool RequireExplicitAvailability = false;
101+
102+
/// Introduction platform and version to suggest as fix-it
103+
/// when using RequireExplicitAvailability.
104+
std::string RequireExplicitAvailabilityTarget;
105+
99106
///
100107
/// Support for alternate usage modes
101108
///

trunk/include/swift/Option/Options.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,14 @@ def enable_library_evolution : Flag<["-"], "enable-library-evolution">,
312312
Flags<[FrontendOption, ModuleInterfaceOption]>,
313313
HelpText<"Build the module to allow binary-compatible library evolution">;
314314

315+
def require_explicit_availability : Flag<["-"], "require-explicit-availability">,
316+
Flags<[FrontendOption, NoInteractiveOption]>,
317+
HelpText<"Require explicit availability on public declarations">;
318+
def require_explicit_availability_target : Separate<["-"], "require-explicit-availability-target">,
319+
Flags<[FrontendOption, NoInteractiveOption]>,
320+
HelpText<"Suggest fix-its adding @available(<target>, *) to public declarations without availability">,
321+
MetaVarName<"<target>">;
322+
315323
def module_name : Separate<["-"], "module-name">,
316324
Flags<[FrontendOption, ModuleInterfaceOption]>,
317325
HelpText<"Name of the module to build">;

trunk/lib/AST/ASTDumper.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2127,16 +2127,16 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
21272127
OS << '\n';
21282128
printRec(elt);
21292129
}
2130-
printSemanticExpr(E->getSemanticExpr());
21312130
PrintWithColorRAII(OS, ParenthesisColor) << ')';
21322131
}
21332132
void visitDictionaryExpr(DictionaryExpr *E) {
21342133
printCommon(E, "dictionary_expr");
2134+
PrintWithColorRAII(OS, LiteralValueColor) << " initializer=";
2135+
E->getInitializer().dump(PrintWithColorRAII(OS, LiteralValueColor).getOS());
21352136
for (auto elt : E->getElements()) {
21362137
OS << '\n';
21372138
printRec(elt);
21382139
}
2139-
printSemanticExpr(E->getSemanticExpr());
21402140
PrintWithColorRAII(OS, ParenthesisColor) << ')';
21412141
}
21422142
void visitSubscriptExpr(SubscriptExpr *E) {

trunk/lib/AST/ASTWalker.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,8 +525,6 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
525525
}
526526

527527
Expr *visitCollectionExpr(CollectionExpr *E) {
528-
HANDLE_SEMANTIC_EXPR(E);
529-
530528
for (auto &elt : E->getElements())
531529
if (Expr *Sub = doIt(elt))
532530
elt = Sub;

trunk/lib/AST/Expr.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,6 +1485,19 @@ Type ArrayExpr::getElementType() {
14851485
.subst(init.getSubstitutions());
14861486
}
14871487

1488+
Type DictionaryExpr::getElementType() {
1489+
auto init = getInitializer();
1490+
if (!init)
1491+
return Type();
1492+
1493+
auto *decl = cast<ConstructorDecl>(init.getDecl());
1494+
return decl->getMethodInterfaceType()
1495+
->getAs<AnyFunctionType>()
1496+
->getParams()[0]
1497+
.getPlainType()
1498+
.subst(init.getSubstitutions());
1499+
}
1500+
14881501
DictionaryExpr *DictionaryExpr::create(ASTContext &C, SourceLoc LBracketLoc,
14891502
ArrayRef<Expr*> Elements,
14901503
ArrayRef<SourceLoc> CommaLocs,

trunk/lib/Frontend/CompilerInvocation.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,13 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
395395
Opts.RequestEvaluatorGraphVizPath = A->getValue();
396396
}
397397

398+
if (Args.getLastArg(OPT_require_explicit_availability, OPT_require_explicit_availability_target)) {
399+
Opts.RequireExplicitAvailability = true;
400+
if (const Arg *A = Args.getLastArg(OPT_require_explicit_availability_target)) {
401+
Opts.RequireExplicitAvailabilityTarget = A->getValue();
402+
}
403+
}
404+
398405
if (const Arg *A = Args.getLastArg(OPT_solver_memory_threshold)) {
399406
unsigned threshold;
400407
if (StringRef(A->getValue()).getAsInteger(10, threshold)) {

trunk/lib/SILGen/SILGenExpr.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,7 @@ namespace {
462462
RValue visitKeyPathExpr(KeyPathExpr *E, SGFContext C);
463463
RValue visitMagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr *E,
464464
SGFContext C);
465-
RValue visitArrayExpr(ArrayExpr *E, SGFContext C);
466-
RValue visitDictionaryExpr(DictionaryExpr *E, SGFContext C);
465+
RValue visitCollectionExpr(CollectionExpr *E, SGFContext C);
467466
RValue visitRebindSelfInConstructorExpr(RebindSelfInConstructorExpr *E,
468467
SGFContext C);
469468
RValue visitInjectIntoOptionalExpr(InjectIntoOptionalExpr *E, SGFContext C);
@@ -3671,15 +3670,20 @@ visitMagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr *E, SGFContext C) {
36713670
llvm_unreachable("Unhandled MagicIdentifierLiteralExpr in switch.");
36723671
}
36733672

3674-
RValue RValueEmitter::visitArrayExpr(ArrayExpr *E, SGFContext C) {
3673+
RValue RValueEmitter::visitCollectionExpr(CollectionExpr *E, SGFContext C) {
36753674
auto loc = SILLocation(E);
36763675
ArgumentScope scope(SGF, loc);
36773676

36783677
// CSApply builds ArrayExprs without an initializer for the trivial case
36793678
// of emitting varargs.
36803679
CanType arrayType, elementType;
36813680
if (E->getInitializer()) {
3682-
elementType = E->getElementType()->getCanonicalType();
3681+
if (auto *arrayExpr = dyn_cast<ArrayExpr>(E)) {
3682+
elementType = arrayExpr->getElementType()->getCanonicalType();
3683+
} else {
3684+
auto *dictionaryExpr = cast<DictionaryExpr>(E);
3685+
elementType = dictionaryExpr->getElementType()->getCanonicalType();
3686+
}
36833687
arrayType = ArraySliceType::get(elementType)->getCanonicalType();
36843688
} else {
36853689
arrayType = E->getType()->getCanonicalType();
@@ -3742,10 +3746,6 @@ RValue RValueEmitter::visitArrayExpr(ArrayExpr *E, SGFContext C) {
37423746
loc, E->getInitializer(), std::move(args), E->getType(), C);
37433747
}
37443748

3745-
RValue RValueEmitter::visitDictionaryExpr(DictionaryExpr *E, SGFContext C) {
3746-
return visit(E->getSemanticExpr(), C);
3747-
}
3748-
37493749
/// Flattens one level of optional from a nested optional value.
37503750
static ManagedValue flattenOptional(SILGenFunction &SGF, SILLocation loc,
37513751
ManagedValue optVal) {

trunk/lib/Sema/CSApply.cpp

Lines changed: 9 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2929,65 +2929,20 @@ namespace {
29292929
if (!conformance)
29302930
return nullptr;
29312931

2932-
// Call the witness that builds the dictionary literal.
2933-
// FIXME: callWitness() may end up re-doing some work we already did
2934-
// to convert the dictionary literal elements to the (key, value) tuple.
2935-
// It would be nicer to re-use them.
2936-
// FIXME: Cache the name.
2937-
// FIXME: This location info is bogus.
2938-
Expr *typeRef = TypeExpr::createImplicitHack(expr->getLoc(), dictionaryTy,
2939-
tc.Context);
2940-
cs.cacheExprTypes(typeRef);
2941-
29422932
DeclName name(tc.Context, DeclBaseName::createConstructor(),
29432933
{ tc.Context.Id_dictionaryLiteral });
2944-
2945-
// Restructure the argument to provide the appropriate labels in the
2946-
// tuple.
2947-
SmallVector<TupleTypeElt, 4> typeElements;
2948-
SmallVector<Identifier, 4> names;
2949-
bool first = true;
2950-
for (auto elt : expr->getElements()) {
2951-
if (first) {
2952-
typeElements.push_back(TupleTypeElt(cs.getType(elt),
2953-
tc.Context.Id_dictionaryLiteral));
2954-
names.push_back(tc.Context.Id_dictionaryLiteral);
2955-
2956-
first = false;
2957-
continue;
2958-
}
2959-
2960-
typeElements.push_back(cs.getType(elt));
2961-
names.push_back(Identifier());
2962-
}
2963-
2964-
Type argType = TupleType::get(typeElements, tc.Context);
2965-
assert(isa<TupleType>(argType.getPointer()));
2966-
2967-
Expr *arg =
2968-
TupleExpr::create(tc.Context, expr->getLBracketLoc(),
2969-
expr->getElements(),
2970-
names,
2971-
{ },
2972-
expr->getRBracketLoc(),
2973-
/*HasTrailingClosure=*/false,
2974-
/*Implicit=*/true,
2975-
argType);
2976-
2977-
cs.cacheExprTypes(arg);
2978-
2979-
cs.setExprTypes(typeRef);
2980-
cs.setExprTypes(arg);
2981-
2982-
Expr *result = tc.callWitness(typeRef, dc, dictionaryProto,
2983-
*conformance, name, arg,
2984-
diag::dictionary_protocol_broken);
2985-
if (!result)
2934+
ConcreteDeclRef witness =
2935+
conformance->getWitnessByName(dictionaryTy->getRValueType(), name);
2936+
if (!witness || !isa<AbstractFunctionDecl>(witness.getDecl()))
29862937
return nullptr;
2938+
expr->setInitializer(witness);
29872939

2988-
cs.cacheExprTypes(result);
2940+
auto elementType = expr->getElementType();
2941+
for (auto &element : expr->getElements()) {
2942+
element = coerceToType(element, elementType,
2943+
cs.getConstraintLocator(element));
2944+
}
29892945

2990-
expr->setSemanticExpr(result);
29912946
return expr;
29922947
}
29932948

trunk/lib/Sema/CSDiag.cpp

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,7 +1280,6 @@ namespace {
12801280
llvm::DenseMap<Pattern*, Type> PatternTypes;
12811281
llvm::DenseMap<ParamDecl*, Type> ParamDeclTypes;
12821282
llvm::DenseMap<ParamDecl*, Type> ParamDeclInterfaceTypes;
1283-
llvm::DenseMap<CollectionExpr*, Expr*> CollectionSemanticExprs;
12841283
llvm::DenseSet<ValueDecl*> PossiblyInvalidDecls;
12851284
ExprTypeSaverAndEraser(const ExprTypeSaverAndEraser&) = delete;
12861285
void operator=(const ExprTypeSaverAndEraser&) = delete;
@@ -1340,15 +1339,6 @@ namespace {
13401339
P->setInvalid(false);
13411340
}
13421341

1343-
// If we have a CollectionExpr with a type checked SemanticExpr,
1344-
// remove it so we can recalculate a new semantic form.
1345-
if (auto *CE = dyn_cast<CollectionExpr>(expr)) {
1346-
if (auto SE = CE->getSemanticExpr()) {
1347-
TS->CollectionSemanticExprs[CE] = SE;
1348-
CE->setSemanticExpr(nullptr);
1349-
}
1350-
}
1351-
13521342
expr->setType(nullptr);
13531343

13541344
return { true, expr };
@@ -1403,9 +1393,6 @@ namespace {
14031393
paramDeclIfaceElt.first->setInterfaceType(paramDeclIfaceElt.second->getInOutObjectType());
14041394
}
14051395

1406-
for (auto CSE : CollectionSemanticExprs)
1407-
CSE.first->setSemanticExpr(CSE.second);
1408-
14091396
if (!PossiblyInvalidDecls.empty())
14101397
for (auto D : PossiblyInvalidDecls)
14111398
if (D->hasInterfaceType())
@@ -1426,10 +1413,6 @@ namespace {
14261413
// we go digging through failed constraints, and expect their locators to
14271414
// still be meaningful.
14281415
~ExprTypeSaverAndEraser() {
1429-
for (auto CSE : CollectionSemanticExprs)
1430-
if (!CSE.first->getType())
1431-
CSE.first->setSemanticExpr(CSE.second);
1432-
14331416
for (auto exprElt : ExprTypes)
14341417
if (!exprElt.first->getType())
14351418
exprElt.first->setType(exprElt.second);

trunk/lib/Sema/CSGen.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3317,9 +3317,7 @@ namespace {
33173317
}
33183318

33193319
// Remove any semantic expression injected by typechecking.
3320-
if (auto CE = dyn_cast<CollectionExpr>(expr)) {
3321-
CE->setSemanticExpr(nullptr);
3322-
} else if (auto ISLE = dyn_cast<InterpolatedStringLiteralExpr>(expr)) {
3320+
if (auto ISLE = dyn_cast<InterpolatedStringLiteralExpr>(expr)) {
33233321
ISLE->setSemanticExpr(nullptr);
33243322
} else if (auto OLE = dyn_cast<ObjectLiteralExpr>(expr)) {
33253323
OLE->setSemanticExpr(nullptr);

trunk/lib/Sema/TypeCheckAvailability.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2788,3 +2788,60 @@ bool swift::diagnoseDeclAvailability(const ValueDecl *Decl,
27882788
AvailabilityWalker AW(TC, DC);
27892789
return AW.diagAvailability(const_cast<ValueDecl *>(Decl), R, nullptr, Flags);
27902790
}
2791+
2792+
void swift::checkExplicitAvailability(Decl *decl) {
2793+
// Check only if the command line option was set.
2794+
if (!decl->getASTContext().LangOpts.RequireExplicitAvailability)
2795+
return;
2796+
2797+
// Skip nominal type members as the type should be annotated.
2798+
auto declContext = decl->getDeclContext();
2799+
if (isa<NominalTypeDecl>(declContext))
2800+
return;
2801+
2802+
ValueDecl *valueDecl = dyn_cast<ValueDecl>(decl);
2803+
if (valueDecl == nullptr) {
2804+
// decl should be either a ValueDecl or an ExtensionDecl
2805+
auto extension = cast<ExtensionDecl>(decl);
2806+
valueDecl = extension->getExtendedNominal();
2807+
if (!valueDecl)
2808+
return;
2809+
}
2810+
2811+
// Skip decls that are not public and not usable from inline.
2812+
AccessScope scope =
2813+
valueDecl->getFormalAccessScope(/*useDC*/nullptr,
2814+
/*treatUsableFromInlineAsPublic*/true);
2815+
if (!scope.isPublic() ||
2816+
decl->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>())
2817+
return;
2818+
2819+
// Warn on decls without an introduction version.
2820+
auto &ctx = decl->getASTContext();
2821+
auto safeRangeUnderApprox = AvailabilityInference::availableRange(decl, ctx);
2822+
if (!safeRangeUnderApprox.getOSVersion().hasLowerEndpoint()) {
2823+
auto diag = decl->diagnose(diag::public_decl_needs_availability);
2824+
2825+
auto suggestPlatform = decl->getASTContext().LangOpts.RequireExplicitAvailabilityTarget;
2826+
if (!suggestPlatform.empty()) {
2827+
auto InsertLoc = decl->getAttrs().getStartLoc(/*forModifiers=*/false);
2828+
if (InsertLoc.isInvalid())
2829+
InsertLoc = decl->getStartLoc();
2830+
2831+
if (InsertLoc.isInvalid())
2832+
return;
2833+
2834+
std::string AttrText;
2835+
{
2836+
llvm::raw_string_ostream Out(AttrText);
2837+
2838+
StringRef OriginalIndent = Lexer::getIndentationForLine(
2839+
ctx.SourceMgr, InsertLoc);
2840+
Out << "@available(" << suggestPlatform << ", *)\n"
2841+
<< OriginalIndent;
2842+
}
2843+
2844+
diag.fixItInsert(InsertLoc, AttrText);
2845+
}
2846+
}
2847+
}

trunk/lib/Sema/TypeCheckAvailability.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ namespace swift {
2828
class Expr;
2929
class InFlightDiagnostic;
3030
class TypeChecker;
31+
class Decl;
3132
class ValueDecl;
3233

3334
/// Diagnose uses of unavailable declarations.
@@ -82,6 +83,9 @@ bool diagnoseExplicitUnavailability(
8283
const DeclContext *DC,
8384
llvm::function_ref<void(InFlightDiagnostic &)> attachRenameFixIts);
8485

86+
/// Check if \p decl has a introduction version required by -require-explicit-availability
87+
void checkExplicitAvailability(Decl *decl);
88+
8589
} // namespace swift
8690

8791
#endif // SWIFT_SEMA_TYPE_CHECK_AVAILABILITY_H

0 commit comments

Comments
 (0)