Skip to content

Commit d0dbb66

Browse files
authored
Merge pull request #1101 from swiftwasm/release/5.3
[pull] swiftwasm-release/5.3 from release/5.3
2 parents 6e935f4 + c21b26d commit d0dbb66

File tree

22 files changed

+420
-44
lines changed

22 files changed

+420
-44
lines changed

include/swift/AST/ASTTypeIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ SWIFT_TYPEID_NAMED(PatternBindingEntry *, PatternBindingEntry)
5656
SWIFT_TYPEID_NAMED(PostfixOperatorDecl *, PostfixOperatorDecl)
5757
SWIFT_TYPEID_NAMED(PrecedenceGroupDecl *, PrecedenceGroupDecl)
5858
SWIFT_TYPEID_NAMED(PrefixOperatorDecl *, PrefixOperatorDecl)
59+
SWIFT_TYPEID_NAMED(ProtocolConformance *, ProtocolConformance)
5960
SWIFT_TYPEID_NAMED(ProtocolDecl *, ProtocolDecl)
6061
SWIFT_TYPEID_NAMED(SourceFile *, SourceFile)
6162
SWIFT_TYPEID_NAMED(TypeAliasDecl *, TypeAliasDecl)

include/swift/AST/ASTTypeIDs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ struct PropertyWrapperTypeInfo;
5151
enum class CtorInitializerKind;
5252
struct PropertyWrapperLValueness;
5353
struct PropertyWrapperMutability;
54+
class ProtocolConformance;
5455
class ProtocolDecl;
5556
class Requirement;
5657
enum class ResilienceExpansion : unsigned;

include/swift/AST/DiagnosticsSema.def

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5048,6 +5048,14 @@ NOTE(function_builder_remove_attr, none,
50485048
"remove the attribute to explicitly disable the function builder", ())
50495049
NOTE(function_builder_remove_returns, none,
50505050
"remove 'return' statements to apply the function builder", ())
5051+
ERROR(function_builder_infer_ambig, none,
5052+
"ambiguous function builder inferred for %0: %1 or %2",
5053+
(DeclName, Type, Type))
5054+
NOTE(function_builder_infer_add_return, none,
5055+
"add an explicit 'return' statement to not use a function builder", ())
5056+
NOTE(function_builder_infer_pick_specific, none,
5057+
"apply function builder %0 (inferred from protocol %1)",
5058+
(Type, DeclName))
50515059

50525060
//------------------------------------------------------------------------------
50535061
// MARK: Tuple Shuffle Diagnostics

include/swift/AST/PrintOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,8 @@ struct PrintOptions {
232232
/// Whether to print unavailable parts of the AST.
233233
bool SkipUnavailable = false;
234234

235+
bool SkipSwiftPrivateClangDecls = false;
236+
235237
/// Whether to skip internal stdlib declarations.
236238
bool SkipPrivateStdlibDecls = false;
237239

@@ -515,6 +517,7 @@ struct PrintOptions {
515517
PrintOptions result = printForDiagnostics();
516518
result.SkipUnavailable = true;
517519
result.SkipImplicit = true;
520+
result.SkipSwiftPrivateClangDecls = true;
518521
result.SkipPrivateStdlibDecls = true;
519522
result.SkipUnderscoredStdlibProtocols = true;
520523
result.SkipDeinit = true;

include/swift/AST/TypeCheckRequests.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2234,7 +2234,7 @@ class ClosureHasExplicitResultRequest
22342234
bool isCached() const { return true; }
22352235
};
22362236

2237-
using ProtocolConformanceLookupResult = SmallVector<ProtocolConformance *, 2>;
2237+
using ProtocolConformanceLookupResult = std::vector<ProtocolConformance *>;
22382238
void simple_display(llvm::raw_ostream &out, ConformanceLookupKind kind);
22392239

22402240
/// Lookup and expand all conformances in the given context.
@@ -2255,7 +2255,7 @@ void simple_display(llvm::raw_ostream &out, ConformanceLookupKind kind);
22552255
class LookupAllConformancesInContextRequest
22562256
: public SimpleRequest<LookupAllConformancesInContextRequest,
22572257
ProtocolConformanceLookupResult(const DeclContext *),
2258-
RequestFlags::Uncached |
2258+
RequestFlags::Cached |
22592259
RequestFlags::DependencySink |
22602260
RequestFlags::DependencySource> {
22612261
public:
@@ -2269,6 +2269,8 @@ class LookupAllConformancesInContextRequest
22692269
evaluate(Evaluator &evaluator, const DeclContext *DC) const;
22702270

22712271
public:
2272+
bool isCached() const { return true; }
2273+
22722274
// Incremental dependencies
22732275
evaluator::DependencySource readDependencySource(Evaluator &eval) const;
22742276
void writeDependencySink(Evaluator &eval, ReferencedNameTracker &tracker,

include/swift/Basic/SimpleDisplay.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,20 @@ namespace swift {
136136
out << "}";
137137
}
138138

139+
template<typename T>
140+
void simple_display(llvm::raw_ostream &out,
141+
const std::vector<T> &vec) {
142+
out << "{";
143+
bool first = true;
144+
for (const T &value : vec) {
145+
if (first) first = false;
146+
else out << ", ";
147+
148+
simple_display(out, value);
149+
}
150+
out << "}";
151+
}
152+
139153
template<typename T, typename U>
140154
void simple_display(llvm::raw_ostream &out,
141155
const llvm::PointerUnion<T, U> &ptrUnion) {

lib/AST/ASTPrinter.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "swift/Parse/Lexer.h"
4444
#include "swift/Strings.h"
4545
#include "clang/AST/ASTContext.h"
46+
#include "clang/AST/Attr.h"
4647
#include "clang/AST/Decl.h"
4748
#include "clang/AST/DeclObjC.h"
4849
#include "clang/Basic/Module.h"
@@ -1670,6 +1671,14 @@ bool ShouldPrintChecker::shouldPrint(const Decl *D,
16701671
return false;
16711672
}
16721673

1674+
// Skip clang decls marked with the swift_private attribute.
1675+
if (Options.SkipSwiftPrivateClangDecls) {
1676+
if (auto ClangD = D->getClangDecl()) {
1677+
if (ClangD->hasAttr<clang::SwiftPrivateAttr>())
1678+
return false;
1679+
}
1680+
}
1681+
16731682
if (Options.SkipPrivateStdlibDecls &&
16741683
D->isPrivateStdlibDecl(!Options.SkipUnderscoredStdlibProtocols))
16751684
return false;

lib/AST/Attr.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -758,11 +758,13 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
758758
case DAK_Custom: {
759759
if (!Options.IsForSwiftInterface)
760760
break;
761-
// For Swift interface, we should only print function builder attribute
762-
// on parameter decls. Printing the attribute elsewhere isn't ABI relevant.
761+
// For Swift interface, we should print function builder attributes
762+
// on parameter decls and on protocol requirements.
763+
// Printing the attribute elsewhere isn't ABI relevant.
763764
if (auto *VD = dyn_cast<ValueDecl>(D)) {
764765
if (VD->getAttachedFunctionBuilder() == this) {
765-
if (!isa<ParamDecl>(D))
766+
if (!isa<ParamDecl>(D) &&
767+
!(isa<VarDecl>(D) && isa<ProtocolDecl>(D->getDeclContext())))
766768
return false;
767769
}
768770
}

lib/AST/Decl.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6345,10 +6345,6 @@ void ParamDecl::setStoredProperty(VarDecl *var) {
63456345
}
63466346

63476347
Type ValueDecl::getFunctionBuilderType() const {
6348-
// Fast path: most declarations (especially parameters, which is where
6349-
// this is hottest) do not have any custom attributes at all.
6350-
if (!getAttrs().hasAttribute<CustomAttr>()) return Type();
6351-
63526348
auto &ctx = getASTContext();
63536349
auto mutableThis = const_cast<ValueDecl *>(this);
63546350
return evaluateOrDefault(ctx.evaluator,
@@ -6357,10 +6353,6 @@ Type ValueDecl::getFunctionBuilderType() const {
63576353
}
63586354

63596355
CustomAttr *ValueDecl::getAttachedFunctionBuilder() const {
6360-
// Fast path: most declarations (especially parameters, which is where
6361-
// this is hottest) do not have any custom attributes at all.
6362-
if (!getAttrs().hasAttribute<CustomAttr>()) return nullptr;
6363-
63646356
auto &ctx = getASTContext();
63656357
auto mutableThis = const_cast<ValueDecl *>(this);
63666358
return evaluateOrDefault(ctx.evaluator,

lib/Sema/BuilderTransform.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,10 +1223,6 @@ BraceStmt *swift::applyFunctionBuilderTransform(
12231223
captured.first, captured.second)));
12241224
}
12251225

1226-
/// Find the return statements in the given body, which block the application
1227-
/// of a function builder.
1228-
static std::vector<ReturnStmt *> findReturnStatements(AnyFunctionRef fn);
1229-
12301226
Optional<BraceStmt *> TypeChecker::applyFunctionBuilderBodyTransform(
12311227
FuncDecl *func, Type builderType) {
12321228
// Pre-check the body: pre-check any expressions in it and look
@@ -1552,7 +1548,7 @@ PreCheckFunctionBuilderRequest::evaluate(Evaluator &eval,
15521548
return PreCheckFunctionBuilderApplication(fn, false).run();
15531549
}
15541550

1555-
std::vector<ReturnStmt *> findReturnStatements(AnyFunctionRef fn) {
1551+
std::vector<ReturnStmt *> TypeChecker::findReturnStatements(AnyFunctionRef fn) {
15561552
PreCheckFunctionBuilderApplication precheck(fn, true);
15571553
(void)precheck.run();
15581554
return precheck.getReturnStmts();

lib/Sema/TypeCheckAttr.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2941,9 +2941,11 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) {
29412941

29422942
// Module interfaces don't print bodies for all getters, so allow getters
29432943
// that don't have a body if we're compiling a module interface.
2944+
// Within a protocol definition, there will never be a body.
29442945
SourceFile *parent = storage->getDeclContext()->getParentSourceFile();
29452946
bool isInInterface = parent && parent->Kind == SourceFileKind::Interface;
2946-
if (!isInInterface && !getter->hasBody())
2947+
if (!isInInterface && !getter->hasBody() &&
2948+
!isa<ProtocolDecl>(storage->getDeclContext()))
29472949
return true;
29482950

29492951
return false;

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5100,10 +5100,11 @@ diagnoseMissingAppendInterpolationMethod(NominalTypeDecl *typeDecl) {
51005100
}
51015101
}
51025102

5103-
SmallVector<ProtocolConformance *, 2>
5103+
std::vector<ProtocolConformance *>
51045104
LookupAllConformancesInContextRequest::evaluate(
51055105
Evaluator &eval, const DeclContext *DC) const {
5106-
return DC->getLocalConformances(ConformanceLookupKind::All);
5106+
auto result = DC->getLocalConformances(ConformanceLookupKind::All);
5107+
return std::vector<ProtocolConformance *>(result.begin(), result.end());
51075108
}
51085109

51095110
void TypeChecker::checkConformancesInContext(DeclContext *dc,

lib/Sema/TypeCheckRequestFunctions.cpp

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "swift/AST/ExistentialLayout.h"
1919
#include "swift/AST/GenericSignature.h"
2020
#include "swift/AST/NameLookupRequests.h"
21+
#include "swift/AST/ProtocolConformance.h"
2122
#include "swift/AST/TypeLoc.h"
2223
#include "swift/AST/Types.h"
2324
#include "swift/Subsystems.h"
@@ -182,11 +183,114 @@ AttachedFunctionBuilderRequest::evaluate(Evaluator &evaluator,
182183
return nullptr;
183184
}
184185

186+
/// Attempt to infer the function builder type for a declaration.
187+
static Type inferFunctionBuilderType(ValueDecl *decl) {
188+
auto dc = decl->getDeclContext();
189+
if (!dc->isTypeContext() || isa<ProtocolDecl>(dc))
190+
return Type();
191+
192+
auto funcDecl = dyn_cast<FuncDecl>(decl);
193+
if (!funcDecl || !funcDecl->hasBody() ||
194+
!decl->getDeclContext()->getParentSourceFile())
195+
return Type();
196+
197+
// Check whether there are any return statements in the function's body.
198+
// If there are, the function builder transform will be disabled,
199+
// so don't infer a function builder.
200+
if (!TypeChecker::findReturnStatements(funcDecl).empty())
201+
return Type();
202+
203+
// Only getters can have function builders. When we find one, look at
204+
// the storage declaration for the purposes of witness matching.
205+
auto lookupDecl = decl;
206+
if (auto accessor = dyn_cast<AccessorDecl>(funcDecl)) {
207+
if (accessor->getAccessorKind() != AccessorKind::Get)
208+
return Type();
209+
210+
lookupDecl = accessor->getStorage();
211+
}
212+
213+
// Determine all of the conformances within the same context as
214+
// this declaration. If this declaration is a witness to any
215+
// requirement within one of those protocols that has a function builder
216+
// attached, use that function builder type.
217+
auto conformances = evaluateOrDefault(
218+
dc->getASTContext().evaluator,
219+
LookupAllConformancesInContextRequest{dc}, { });
220+
221+
// Find all of the potentially inferred function builder types.
222+
struct Match {
223+
ProtocolConformance *conformance;
224+
ValueDecl *requirement;
225+
Type functionBuilderType;
226+
};
227+
SmallVector<Match, 2> matches;
228+
for (auto conformance : conformances) {
229+
auto protocol = conformance->getProtocol();
230+
for (auto found : protocol->lookupDirect(lookupDecl->getName())) {
231+
if (!isa<ProtocolDecl>(found->getDeclContext()))
232+
continue;
233+
234+
auto requirement = dyn_cast<ValueDecl>(found);
235+
if (!requirement)
236+
continue;
237+
238+
Type functionBuilderType = requirement->getFunctionBuilderType();
239+
if (!functionBuilderType)
240+
continue;
241+
242+
auto witness = conformance->getWitnessDecl(requirement);
243+
if (witness != lookupDecl)
244+
continue;
245+
246+
// Substitute into the function builder type.
247+
auto subs = conformance->getSubstitutions(decl->getModuleContext());
248+
Type subFunctionBuilderType = functionBuilderType.subst(subs);
249+
250+
matches.push_back({conformance, requirement, subFunctionBuilderType});
251+
}
252+
}
253+
254+
if (matches.size() == 0)
255+
return Type();
256+
257+
// Determine whether there is more than one actual function builder type.
258+
Type functionBuilderType = matches[0].functionBuilderType;
259+
for (const auto &match : matches) {
260+
// If the types were the same anyway, there's nothing to do.
261+
Type otherFunctionBuilderType = match.functionBuilderType;
262+
if (functionBuilderType->isEqual(otherFunctionBuilderType))
263+
continue;
264+
265+
// We have at least two different function builder types.
266+
// Diagnose the ambiguity and provide potential solutions.
267+
decl->diagnose(
268+
diag::function_builder_infer_ambig, lookupDecl->getName(),
269+
functionBuilderType, otherFunctionBuilderType);
270+
decl->diagnose(diag::function_builder_infer_add_return)
271+
.fixItInsert(funcDecl->getBodySourceRange().End, "return <#expr#>\n");
272+
for (const auto &match : matches) {
273+
decl->diagnose(
274+
diag::function_builder_infer_pick_specific,
275+
match.functionBuilderType,
276+
match.conformance->getProtocol()->getName())
277+
.fixItInsert(
278+
lookupDecl->getAttributeInsertionLoc(false),
279+
"@" + match.functionBuilderType.getString() + " ");
280+
}
281+
282+
return Type();
283+
}
284+
285+
return functionBuilderType;
286+
}
287+
185288
Type FunctionBuilderTypeRequest::evaluate(Evaluator &evaluator,
186289
ValueDecl *decl) const {
187290
// Look for a function-builder custom attribute.
188291
auto attr = decl->getAttachedFunctionBuilder();
189-
if (!attr) return Type();
292+
if (!attr)
293+
return inferFunctionBuilderType(decl);
190294

191295
// Resolve a type for the attribute.
192296
auto mutableAttr = const_cast<CustomAttr*>(attr);

lib/Sema/TypeCheckStmt.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1871,7 +1871,8 @@ TypeCheckFunctionBodyUntilRequest::evaluate(Evaluator &evaluator,
18711871
if (auto *func = dyn_cast<FuncDecl>(AFD)) {
18721872
if (Type builderType = getFunctionBuilderType(func)) {
18731873
if (auto optBody =
1874-
TypeChecker::applyFunctionBuilderBodyTransform(func, builderType)) {
1874+
TypeChecker::applyFunctionBuilderBodyTransform(
1875+
func, builderType)) {
18751876
if (!*optBody)
18761877
return true;
18771878

lib/Sema/TypeChecker.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,9 @@ bool typeCheckAbstractFunctionBody(AbstractFunctionDecl *AFD);
601601
Optional<BraceStmt *> applyFunctionBuilderBodyTransform(FuncDecl *func,
602602
Type builderType);
603603

604+
/// Find the return statements within the body of the given function.
605+
std::vector<ReturnStmt *> findReturnStatements(AnyFunctionRef fn);
606+
604607
bool typeCheckClosureBody(ClosureExpr *closure);
605608

606609
bool typeCheckTapBody(TapExpr *expr, DeclContext *DC);

0 commit comments

Comments
 (0)