Skip to content

Commit 0ad118e

Browse files
authored
Merge pull request #6669 from slavapestov/resilience-diagnostics
Resilience diagnostics
2 parents b062f16 + d65d1d2 commit 0ad118e

Some content is hidden

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

48 files changed

+472
-124
lines changed

include/swift/AST/AST.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include "swift/AST/Builtins.h"
2323
#include "swift/AST/Decl.h"
2424
#include "swift/AST/Expr.h"
25-
#include "swift/AST/Initializer.h"
2625
#include "swift/AST/Module.h"
2726
#include "swift/AST/ParameterList.h"
2827
#include "swift/AST/Pattern.h"

include/swift/AST/DiagnosticsSema.def

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1178,6 +1178,9 @@ ERROR(pattern_binds_no_variables,none,
11781178
ERROR(unsupported_type_nested_in_generic_function,none,
11791179
"type %0 cannot be nested in generic function %1",
11801180
(Identifier, Identifier))
1181+
ERROR(unsupported_type_nested_in_generic_closure,none,
1182+
"type %0 cannot be nested in closure in generic context",
1183+
(Identifier))
11811184
ERROR(unsupported_type_nested_in_protocol,none,
11821185
"type %0 cannot be nested in protocol %1",
11831186
(Identifier, Identifier))
@@ -3292,6 +3295,35 @@ NOTE(availability_protocol_requirement_here, none,
32923295
NOTE(availability_conformance_introduced_here, none,
32933296
"conformance introduced here", ())
32943297

3298+
//------------------------------------------------------------------------------
3299+
// Resilience diagnostics
3300+
//------------------------------------------------------------------------------
3301+
3302+
ERROR(versioned_attr_with_explicit_accessibility,
3303+
none, "'@_versioned' attribute can only be applied to internal "
3304+
"declarations, but %0 is %select{private|fileprivate|%error|public}1",
3305+
(Identifier, Accessibility))
3306+
3307+
#define FRAGILE_FUNC_KIND \
3308+
"%select{a '@_transparent' function|" \
3309+
"an '@inline(__always)' function|" \
3310+
"an '@_inlineable' function|" \
3311+
"a default argument value}"
3312+
3313+
ERROR(local_type_in_inlineable_function,
3314+
none, "type %0 cannot be nested inside " FRAGILE_FUNC_KIND "1",
3315+
(DeclName, unsigned))
3316+
3317+
ERROR(resilience_decl_unavailable,
3318+
none, "%0 %1 is %select{private|fileprivate|internal|%error}2 and "
3319+
"cannot be referenced from " FRAGILE_FUNC_KIND "3",
3320+
(DescriptiveDeclKind, DeclName, Accessibility, unsigned))
3321+
3322+
NOTE(resilience_decl_declared_here,
3323+
none, "%0 %1 is not '@_versioned' or public", (DescriptiveDeclKind, DeclName))
3324+
3325+
#undef FRAGILE_FUNC_KIND
3326+
32953327
//------------------------------------------------------------------------------
32963328
// Variable usage diagnostics
32973329
//------------------------------------------------------------------------------
@@ -3334,7 +3366,7 @@ ERROR(circular_reference, none,
33343366
"circular reference", ())
33353367

33363368
ERROR(redundant_type_alias_define, none,
3337-
"redundant type alias declaration", ())
3369+
"redundant type alias declaration", ())
33383370

33393371
NOTE(circular_reference_through, none,
33403372
"through reference here", ())

include/swift/AST/Initializer.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#define SWIFT_INITIALIZER_H
2222

2323
#include "swift/AST/DeclContext.h"
24+
#include "swift/AST/Decl.h"
2425

2526
namespace swift {
2627
class PatternBindingDecl;
@@ -147,16 +148,26 @@ class DefaultArgumentInitializer : public Initializer {
147148
public:
148149
explicit DefaultArgumentInitializer(DeclContext *parent, unsigned index)
149150
: Initializer(InitializerKind::DefaultArgument, parent) {
150-
SpareBits = index;
151+
SpareBits = (unsigned(ResilienceExpansion::Maximal) | index << 1);
151152
}
152153

153-
unsigned getIndex() const { return SpareBits; }
154+
unsigned getIndex() const { return SpareBits >> 1; }
155+
156+
ResilienceExpansion getResilienceExpansion() const {
157+
return ResilienceExpansion(SpareBits & 1);
158+
}
154159

155160
/// Change the parent of this context. This is necessary because
156161
/// the function signature is parsed before the function
157162
/// declaration/expression itself is built.
158163
void changeFunction(AbstractFunctionDecl *parent);
159-
164+
165+
/// Change the resilience expansion of this context, necessary
166+
/// for the same reason as above.
167+
void changeResilienceExpansion(ResilienceExpansion expansion) {
168+
SpareBits = (SpareBits & ~1) | unsigned(expansion);
169+
}
170+
160171
static bool classof(const DeclContext *DC) {
161172
if (auto init = dyn_cast<Initializer>(DC))
162173
return classof(init);

lib/AST/ASTDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/ASTVisitor.h"
2121
#include "swift/AST/ForeignErrorConvention.h"
2222
#include "swift/AST/GenericEnvironment.h"
23+
#include "swift/AST/Initializer.h"
2324
#include "swift/AST/ParameterList.h"
2425
#include "swift/AST/TypeVisitor.h"
2526
#include "swift/Basic/STLExtras.h"

lib/AST/ASTVerifier.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/AST/ASTWalker.h"
2222
#include "swift/AST/ForeignErrorConvention.h"
2323
#include "swift/AST/GenericEnvironment.h"
24+
#include "swift/AST/Initializer.h"
2425
#include "swift/AST/Mangle.h"
2526
#include "swift/AST/PrettyStackTrace.h"
2627
#include "swift/Basic/SourceManager.h"

lib/AST/Decl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "swift/AST/Expr.h"
2525
#include "swift/AST/ForeignErrorConvention.h"
2626
#include "swift/AST/GenericEnvironment.h"
27+
#include "swift/AST/Initializer.h"
2728
#include "swift/AST/LazyResolver.h"
2829
#include "swift/AST/Mangle.h"
2930
#include "swift/AST/ParameterList.h"

lib/AST/DeclContext.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "swift/AST/AccessScope.h"
1616
#include "swift/AST/ASTWalker.h"
1717
#include "swift/AST/GenericEnvironment.h"
18+
#include "swift/AST/Initializer.h"
1819
#include "swift/AST/Types.h"
1920
#include "swift/Basic/SourceManager.h"
2021
#include "llvm/ADT/DenseMap.h"
@@ -468,13 +469,20 @@ bool DeclContext::isGenericContext() const {
468469
/// are used.
469470
ResilienceExpansion DeclContext::getResilienceExpansion() const {
470471
for (const auto *dc = this; dc->isLocalContext(); dc = dc->getParent()) {
472+
// Default argument initializer contexts have their resilience expansion
473+
// set when they're type checked.
474+
if (auto *DAI = dyn_cast<DefaultArgumentInitializer>(dc))
475+
return DAI->getResilienceExpansion();
476+
471477
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(dc)) {
472478
// If the function is a nested function, we will serialize its body if
473479
// we serialize the parent's body.
474480
if (AFD->getDeclContext()->isLocalContext())
475481
continue;
476482

477-
if (AFD->isInvalid())
483+
// FIXME: Make sure this method is never called on decls that have not
484+
// been fully validated.
485+
if (!AFD->hasAccessibility())
478486
break;
479487

480488
// If the function is not externally visible, we will not be serializing
@@ -494,8 +502,8 @@ ResilienceExpansion DeclContext::getResilienceExpansion() const {
494502
if (attr->getKind() == InlineKind::Always)
495503
return ResilienceExpansion::Minimal;
496504

497-
// If a property or subscript is @_fragile, the accessors are
498-
// @_fragile also.
505+
// If a property or subscript is @_inlineable, the accessors are
506+
// @_inlineable also.
499507
if (auto FD = dyn_cast<FuncDecl>(AFD))
500508
if (auto *ASD = FD->getAccessorStorageDecl())
501509
if (ASD->getAttrs().getAttribute<InlineableAttr>())
@@ -504,7 +512,6 @@ ResilienceExpansion DeclContext::getResilienceExpansion() const {
504512
}
505513

506514
return ResilienceExpansion::Maximal;
507-
508515
}
509516

510517
/// Determine whether the innermost context is generic.

lib/AST/LookupVisibleDecls.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@
1616
//===----------------------------------------------------------------------===//
1717

1818
#include "NameLookupImpl.h"
19-
#include "swift/AST/NameLookup.h"
2019
#include "swift/AST/AST.h"
20+
#include "swift/AST/NameLookup.h"
21+
#include "swift/AST/Initializer.h"
2122
#include "swift/Basic/SourceManager.h"
2223
#include "swift/Basic/STLExtras.h"
2324
#include "swift/Sema/IDETypeChecking.h"

lib/AST/NameLookup.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/AST/ASTVisitor.h"
2222
#include "swift/AST/DebuggerClient.h"
2323
#include "swift/AST/LazyResolver.h"
24+
#include "swift/AST/Initializer.h"
2425
#include "swift/AST/ReferencedNameTracker.h"
2526
#include "swift/Basic/Fallthrough.h"
2627
#include "swift/Basic/SourceManager.h"

lib/IDE/CodeCompletion.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "swift/AST/ASTPrinter.h"
1616
#include "swift/AST/ASTWalker.h"
1717
#include "swift/AST/Comment.h"
18+
#include "swift/AST/Initializer.h"
1819
#include "swift/AST/LazyResolver.h"
1920
#include "swift/AST/NameLookup.h"
2021
#include "swift/AST/USRGeneration.h"

lib/Parse/ParseDecl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/AST/Attr.h"
2222
#include "swift/AST/DebuggerClient.h"
2323
#include "swift/AST/DiagnosticsParse.h"
24+
#include "swift/AST/Initializer.h"
2425
#include "swift/AST/Module.h"
2526
#include "swift/AST/ParameterList.h"
2627
#include "swift/Basic/Defer.h"

lib/Parse/ParsePattern.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "swift/Parse/CodeCompletionCallbacks.h"
1818
#include "swift/Parse/Parser.h"
1919
#include "swift/AST/ASTWalker.h"
20+
#include "swift/AST/Initializer.h"
2021
#include "swift/Basic/StringExtras.h"
2122
#include "llvm/ADT/SmallString.h"
2223
#include "llvm/ADT/StringMap.h"

lib/SILGen/SILGenFunction.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/Basic/Fallthrough.h"
2222
#include "swift/AST/AST.h"
2323
#include "swift/AST/GenericEnvironment.h"
24+
#include "swift/AST/Initializer.h"
2425
#include "swift/SIL/SILArgument.h"
2526
#include "swift/SIL/SILUndef.h"
2627

lib/Sema/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ add_swift_library(swiftSema STATIC
2323
NameBinding.cpp
2424
PCMacro.cpp
2525
PlaygroundTransform.cpp
26+
ResilienceDiagnostics.cpp
2627
SourceLoader.cpp
2728
TypeCheckAttr.cpp
2829
TypeCheckAvailability.cpp

lib/Sema/CSDiag.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "MiscDiagnostics.h"
1919
#include "swift/AST/ASTWalker.h"
2020
#include "swift/AST/GenericEnvironment.h"
21+
#include "swift/AST/Initializer.h"
2122
#include "swift/AST/TypeWalker.h"
2223
#include "swift/AST/TypeMatcher.h"
2324
#include "swift/Basic/Defer.h"

lib/Sema/ResilienceDiagnostics.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
//===--- ResilienceDiagnostics.cpp - Resilience Inlineability Diagnostics -===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file implements diagnostics for @inlineable.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#include "TypeChecker.h"
18+
#include "swift/AST/Attr.h"
19+
#include "swift/AST/Decl.h"
20+
#include "swift/AST/Initializer.h"
21+
#include "swift/AST/DeclContext.h"
22+
using namespace swift;
23+
24+
enum FragileFunctionKind : unsigned {
25+
Transparent,
26+
InlineAlways,
27+
Inlineable,
28+
DefaultArgument
29+
};
30+
31+
FragileFunctionKind getFragileFunctionKind(const DeclContext *DC) {
32+
for (; DC->isLocalContext(); DC = DC->getParent()) {
33+
if (auto *DAI = dyn_cast<DefaultArgumentInitializer>(DC))
34+
if (DAI->getResilienceExpansion() == ResilienceExpansion::Minimal)
35+
return FragileFunctionKind::DefaultArgument;
36+
37+
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(DC)) {
38+
// If the function is a nested function, we will serialize its body if
39+
// we serialize the parent's body.
40+
if (AFD->getDeclContext()->isLocalContext())
41+
continue;
42+
43+
// Bodies of public transparent and always-inline functions are
44+
// serialized, so use conservative access patterns.
45+
if (AFD->isTransparent())
46+
return FragileFunctionKind::Transparent;
47+
48+
if (AFD->getAttrs().hasAttribute<InlineableAttr>())
49+
return FragileFunctionKind::Inlineable;
50+
51+
if (auto attr = AFD->getAttrs().getAttribute<InlineAttr>())
52+
if (attr->getKind() == InlineKind::Always)
53+
return FragileFunctionKind::InlineAlways;
54+
55+
// If a property or subscript is @_inlineable, the accessors are
56+
// @_inlineable also.
57+
if (auto FD = dyn_cast<FuncDecl>(AFD))
58+
if (auto *ASD = FD->getAccessorStorageDecl())
59+
if (ASD->getAttrs().getAttribute<InlineableAttr>())
60+
return FragileFunctionKind::Inlineable;
61+
}
62+
}
63+
64+
llvm_unreachable("Context is not nested inside a fragile function");
65+
}
66+
67+
void TypeChecker::diagnoseInlineableLocalType(const NominalTypeDecl *NTD) {
68+
auto *DC = NTD->getDeclContext();
69+
auto expansion = DC->getResilienceExpansion();
70+
if (expansion == ResilienceExpansion::Minimal) {
71+
diagnose(NTD, diag::local_type_in_inlineable_function,
72+
NTD->getFullName(), getFragileFunctionKind(DC));
73+
}
74+
}
75+
76+
bool TypeChecker::diagnoseInlineableDeclRef(SourceLoc loc,
77+
const ValueDecl *D,
78+
const DeclContext *DC) {
79+
auto expansion = DC->getResilienceExpansion();
80+
if (expansion == ResilienceExpansion::Minimal) {
81+
if (!isa<GenericTypeParamDecl>(D) &&
82+
// FIXME: Figure out what to do with typealiases
83+
!isa<TypeAliasDecl>(D) &&
84+
!D->getDeclContext()->isLocalContext() &&
85+
D->hasAccessibility()) {
86+
if (D->getEffectiveAccess() < Accessibility::Public) {
87+
diagnose(loc, diag::resilience_decl_unavailable,
88+
D->getDescriptiveKind(), D->getFullName(),
89+
D->getFormalAccess(), getFragileFunctionKind(DC));
90+
diagnose(D, diag::resilience_decl_declared_here,
91+
D->getDescriptiveKind(), D->getFullName());
92+
return true;
93+
}
94+
}
95+
}
96+
97+
return false;
98+
}

lib/Sema/TypeCheckAttr.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -727,9 +727,6 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
727727
IGNORED_ATTR(WarnUnqualifiedAccess)
728728
IGNORED_ATTR(ShowInInterface)
729729
IGNORED_ATTR(DiscardableResult)
730-
731-
// FIXME: We actually do have things to enforce for versioned API.
732-
IGNORED_ATTR(Versioned)
733730
#undef IGNORED_ATTR
734731

735732
void visitAvailableAttr(AvailableAttr *attr);
@@ -764,6 +761,8 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
764761
void visitPrefixAttr(PrefixAttr *attr) { checkOperatorAttribute(attr); }
765762

766763
void visitSpecializeAttr(SpecializeAttr *attr);
764+
765+
void visitVersionedAttr(VersionedAttr *attr);
767766
};
768767
} // end anonymous namespace
769768

@@ -1522,6 +1521,19 @@ void AttributeChecker::visitSpecializeAttr(SpecializeAttr *attr) {
15221521
ConcreteDeclRef(DC->getASTContext(), FD, substitutions));
15231522
}
15241523

1524+
void AttributeChecker::visitVersionedAttr(VersionedAttr *attr) {
1525+
auto *VD = cast<ValueDecl>(D);
1526+
1527+
if (VD->getFormalAccess() != Accessibility::Internal) {
1528+
TC.diagnose(attr->getLocation(),
1529+
diag::versioned_attr_with_explicit_accessibility,
1530+
VD->getName(),
1531+
VD->getFormalAccess())
1532+
.fixItRemove(attr->getRangeWithAt());
1533+
attr->setInvalid();
1534+
}
1535+
}
1536+
15251537
void TypeChecker::checkDeclAttributes(Decl *D) {
15261538
AttributeChecker Checker(*this, D);
15271539

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2259,6 +2259,10 @@ bool AvailabilityWalker::diagAvailability(const ValueDecl *D, SourceRange R,
22592259
return true;
22602260
}
22612261

2262+
if (R.isValid())
2263+
if (TC.diagnoseInlineableDeclRef(R.Start, D, DC))
2264+
return true;
2265+
22622266
if (TC.diagnoseExplicitUnavailability(D, R, DC, call))
22632267
return true;
22642268

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/AST/ASTVisitor.h"
2424
#include "swift/AST/ASTWalker.h"
2525
#include "swift/AST/DiagnosticsParse.h"
26+
#include "swift/AST/Initializer.h"
2627
#include "swift/AST/NameLookup.h"
2728
#include "swift/AST/PrettyStackTrace.h"
2829
#include "swift/AST/TypeCheckerDebugConsumer.h"

0 commit comments

Comments
 (0)