Skip to content

Commit b87122d

Browse files
authored
Merge pull request #1098 from swiftwasm/master
[pull] swiftwasm from master
2 parents f292d2f + ef7da4d commit b87122d

26 files changed

+790
-38
lines changed

include/swift/AST/ASTTypeIDZone.def

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

include/swift/AST/ASTTypeIDs.h

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

include/swift/AST/DiagnosticsSema.def

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5069,6 +5069,14 @@ NOTE(function_builder_remove_attr, none,
50695069
"remove the attribute to explicitly disable the function builder", ())
50705070
NOTE(function_builder_remove_returns, none,
50715071
"remove 'return' statements to apply the function builder", ())
5072+
ERROR(function_builder_infer_ambig, none,
5073+
"ambiguous function builder inferred for %0: %1 or %2",
5074+
(DeclName, Type, Type))
5075+
NOTE(function_builder_infer_add_return, none,
5076+
"add an explicit 'return' statement to not use a function builder", ())
5077+
NOTE(function_builder_infer_pick_specific, none,
5078+
"apply function builder %0 (inferred from protocol %1)",
5079+
(Type, DeclName))
50725080

50735081
//------------------------------------------------------------------------------
50745082
// MARK: Tuple Shuffle Diagnostics

include/swift/AST/TypeCheckRequests.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2240,7 +2240,7 @@ class ClosureHasExplicitResultRequest
22402240
bool isCached() const { return true; }
22412241
};
22422242

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

22462246
/// Lookup and expand all conformances in the given context.
@@ -2262,7 +2262,7 @@ class LookupAllConformancesInContextRequest
22622262
: public SimpleRequest<LookupAllConformancesInContextRequest,
22632263
ProtocolConformanceLookupResult(
22642264
const IterableDeclContext *),
2265-
RequestFlags::Uncached |
2265+
RequestFlags::Cached |
22662266
RequestFlags::DependencySink |
22672267
RequestFlags::DependencySource> {
22682268
public:
@@ -2276,6 +2276,8 @@ class LookupAllConformancesInContextRequest
22762276
evaluate(Evaluator &evaluator, const IterableDeclContext *IDC) const;
22772277

22782278
public:
2279+
bool isCached() const { return true; }
2280+
22792281
// Incremental dependencies
22802282
evaluator::DependencySource
22812283
readDependencySource(const evaluator::DependencyRecorder &eval) const;

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/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
@@ -6324,10 +6324,6 @@ void ParamDecl::setStoredProperty(VarDecl *var) {
63246324
}
63256325

63266326
Type ValueDecl::getFunctionBuilderType() const {
6327-
// Fast path: most declarations (especially parameters, which is where
6328-
// this is hottest) do not have any custom attributes at all.
6329-
if (!getAttrs().hasAttribute<CustomAttr>()) return Type();
6330-
63316327
auto &ctx = getASTContext();
63326328
auto mutableThis = const_cast<ValueDecl *>(this);
63336329
return evaluateOrDefault(ctx.evaluator,
@@ -6336,10 +6332,6 @@ Type ValueDecl::getFunctionBuilderType() const {
63366332
}
63376333

63386334
CustomAttr *ValueDecl::getAttachedFunctionBuilder() const {
6339-
// Fast path: most declarations (especially parameters, which is where
6340-
// this is hottest) do not have any custom attributes at all.
6341-
if (!getAttrs().hasAttribute<CustomAttr>()) return nullptr;
6342-
63436335
auto &ctx = getASTContext();
63446336
auto mutableThis = const_cast<ValueDecl *>(this);
63456337
return evaluateOrDefault(ctx.evaluator,

lib/Sema/BuilderTransform.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,10 +1401,6 @@ BraceStmt *swift::applyFunctionBuilderTransform(
14011401
captured.first, captured.second)));
14021402
}
14031403

1404-
/// Find the return statements in the given body, which block the application
1405-
/// of a function builder.
1406-
static std::vector<ReturnStmt *> findReturnStatements(AnyFunctionRef fn);
1407-
14081404
Optional<BraceStmt *> TypeChecker::applyFunctionBuilderBodyTransform(
14091405
FuncDecl *func, Type builderType) {
14101406
// Pre-check the body: pre-check any expressions in it and look
@@ -1708,7 +1704,7 @@ PreCheckFunctionBuilderRequest::evaluate(Evaluator &eval,
17081704
return PreCheckFunctionBuilderApplication(fn, false).run();
17091705
}
17101706

1711-
std::vector<ReturnStmt *> findReturnStatements(AnyFunctionRef fn) {
1707+
std::vector<ReturnStmt *> TypeChecker::findReturnStatements(AnyFunctionRef fn) {
17121708
PreCheckFunctionBuilderApplication precheck(fn, true);
17131709
(void)precheck.run();
17141710
return precheck.getReturnStmts();

lib/Sema/CSFix.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -287,9 +287,11 @@ getStructuralTypeContext(const Solution &solution, ConstraintLocator *locator) {
287287
solution.getType(coerceExpr->getSubExpr()),
288288
solution.getType(coerceExpr));
289289
} else if (auto *assignExpr = getAsExpr<AssignExpr>(locator->getAnchor())) {
290-
return std::make_tuple(CTP_AssignSource,
290+
auto CTP = isa<SubscriptExpr>(assignExpr->getDest()) ? CTP_SubscriptAssignSource
291+
: CTP_AssignSource;
292+
return std::make_tuple(CTP,
291293
solution.getType(assignExpr->getSrc()),
292-
solution.getType(assignExpr->getDest()));
294+
solution.getType(assignExpr->getDest())->getRValueType());
293295
} else if (auto *call = getAsExpr<CallExpr>(locator->getAnchor())) {
294296
assert(isa<TypeExpr>(call->getFn()));
295297
return std::make_tuple(
@@ -332,8 +334,10 @@ bool AllowTupleTypeMismatch::coalesceAndDiagnose(
332334
return false;
333335
}
334336

335-
TupleContextualFailure failure(solution, purpose, fromType, toType, indices,
336-
locator);
337+
TupleContextualFailure failure(solution, purpose,
338+
fromType->lookThroughAllOptionalTypes(),
339+
toType->lookThroughAllOptionalTypes(),
340+
indices, locator);
337341
return failure.diagnose(asNote);
338342
}
339343

lib/Sema/CSSimplify.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3356,13 +3356,18 @@ bool ConstraintSystem::repairFailures(
33563356
// related to immutability, otherwise it's a type mismatch.
33573357
auto result = matchTypes(lhs, rhs, ConstraintKind::Conversion,
33583358
TMF_ApplyingFix, locator);
3359-
3359+
3360+
auto *loc = getConstraintLocator(locator);
33603361
if (getType(destExpr)->is<LValueType>() || result.isFailure()) {
3361-
conversionsOrFixes.push_back(IgnoreAssignmentDestinationType::create(
3362-
*this, lhs, rhs, getConstraintLocator(locator)));
3363-
} else {
3362+
// Let this asignment failure be diagnosed by the AllowTupleTypeMismatch
3363+
// fix already recorded.
3364+
if (hasFixFor(loc, FixKind::AllowTupleTypeMismatch))
3365+
return true;
3366+
33643367
conversionsOrFixes.push_back(
3365-
TreatRValueAsLValue::create(*this, getConstraintLocator(locator)));
3368+
IgnoreAssignmentDestinationType::create(*this, lhs, rhs, loc));
3369+
} else {
3370+
conversionsOrFixes.push_back(TreatRValueAsLValue::create(*this, loc));
33663371
}
33673372

33683373
return true;
@@ -8865,6 +8870,11 @@ ConstraintSystem::simplifyRestrictedConstraintImpl(
88658870
CoerceToCheckedCast::attempt(*this, fromType, toType, loc))
88668871
return !recordFix(fix, impact);
88678872
}
8873+
8874+
// We already have a fix for this locator indicating a
8875+
// tuple mismatch.
8876+
if (hasFixFor(loc, FixKind::AllowTupleTypeMismatch))
8877+
return true;
88688878

88698879
if (restriction == ConversionRestrictionKind::ValueToOptional ||
88708880
restriction == ConversionRestrictionKind::OptionalToOptional)

lib/Sema/TypeCheckAttr.cpp

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

29722972
// Module interfaces don't print bodies for all getters, so allow getters
29732973
// that don't have a body if we're compiling a module interface.
2974+
// Within a protocol definition, there will never be a body.
29742975
SourceFile *parent = storage->getDeclContext()->getParentSourceFile();
29752976
bool isInInterface = parent && parent->Kind == SourceFileKind::Interface;
2976-
if (!isInInterface && !getter->hasBody())
2977+
if (!isInInterface && !getter->hasBody() &&
2978+
!isa<ProtocolDecl>(storage->getDeclContext()))
29772979
return true;
29782980

29792981
return false;

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5037,10 +5037,11 @@ diagnoseMissingAppendInterpolationMethod(NominalTypeDecl *typeDecl) {
50375037
}
50385038
}
50395039

5040-
SmallVector<ProtocolConformance *, 2>
5040+
std::vector<ProtocolConformance *>
50415041
LookupAllConformancesInContextRequest::evaluate(
50425042
Evaluator &eval, const IterableDeclContext *IDC) const {
5043-
return IDC->getLocalConformances(ConformanceLookupKind::All);
5043+
auto result = IDC->getLocalConformances(ConformanceLookupKind::All);
5044+
return std::vector<ProtocolConformance *>(result.begin(), result.end());
50445045
}
50455046

50465047
void TypeChecker::checkConformancesInContext(IterableDeclContext *idc) {

lib/Sema/TypeCheckRequestFunctions.cpp

Lines changed: 106 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,115 @@ 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 idc = cast<IterableDeclContext>(dc->getAsDecl());
218+
auto conformances = evaluateOrDefault(
219+
dc->getASTContext().evaluator,
220+
LookupAllConformancesInContextRequest{idc}, { });
221+
222+
// Find all of the potentially inferred function builder types.
223+
struct Match {
224+
ProtocolConformance *conformance;
225+
ValueDecl *requirement;
226+
Type functionBuilderType;
227+
};
228+
SmallVector<Match, 2> matches;
229+
for (auto conformance : conformances) {
230+
auto protocol = conformance->getProtocol();
231+
for (auto found : protocol->lookupDirect(lookupDecl->getName())) {
232+
if (!isa<ProtocolDecl>(found->getDeclContext()))
233+
continue;
234+
235+
auto requirement = dyn_cast<ValueDecl>(found);
236+
if (!requirement)
237+
continue;
238+
239+
Type functionBuilderType = requirement->getFunctionBuilderType();
240+
if (!functionBuilderType)
241+
continue;
242+
243+
auto witness = conformance->getWitnessDecl(requirement);
244+
if (witness != lookupDecl)
245+
continue;
246+
247+
// Substitute into the function builder type.
248+
auto subs = conformance->getSubstitutions(decl->getModuleContext());
249+
Type subFunctionBuilderType = functionBuilderType.subst(subs);
250+
251+
matches.push_back({conformance, requirement, subFunctionBuilderType});
252+
}
253+
}
254+
255+
if (matches.size() == 0)
256+
return Type();
257+
258+
// Determine whether there is more than one actual function builder type.
259+
Type functionBuilderType = matches[0].functionBuilderType;
260+
for (const auto &match : matches) {
261+
// If the types were the same anyway, there's nothing to do.
262+
Type otherFunctionBuilderType = match.functionBuilderType;
263+
if (functionBuilderType->isEqual(otherFunctionBuilderType))
264+
continue;
265+
266+
// We have at least two different function builder types.
267+
// Diagnose the ambiguity and provide potential solutions.
268+
decl->diagnose(
269+
diag::function_builder_infer_ambig, lookupDecl->getName(),
270+
functionBuilderType, otherFunctionBuilderType);
271+
decl->diagnose(diag::function_builder_infer_add_return)
272+
.fixItInsert(funcDecl->getBodySourceRange().End, "return <#expr#>\n");
273+
for (const auto &match : matches) {
274+
decl->diagnose(
275+
diag::function_builder_infer_pick_specific,
276+
match.functionBuilderType,
277+
match.conformance->getProtocol()->getName())
278+
.fixItInsert(
279+
lookupDecl->getAttributeInsertionLoc(false),
280+
"@" + match.functionBuilderType.getString() + " ");
281+
}
282+
283+
return Type();
284+
}
285+
286+
return functionBuilderType;
287+
}
288+
185289
Type FunctionBuilderTypeRequest::evaluate(Evaluator &evaluator,
186290
ValueDecl *decl) const {
187291
// Look for a function-builder custom attribute.
188292
auto attr = decl->getAttachedFunctionBuilder();
189-
if (!attr) return Type();
293+
if (!attr)
294+
return inferFunctionBuilderType(decl);
190295

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

lib/Sema/TypeCheckStmt.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1862,7 +1862,8 @@ TypeCheckFunctionBodyUntilRequest::evaluate(Evaluator &evaluator,
18621862
if (auto *func = dyn_cast<FuncDecl>(AFD)) {
18631863
if (Type builderType = getFunctionBuilderType(func)) {
18641864
if (auto optBody =
1865-
TypeChecker::applyFunctionBuilderBodyTransform(func, builderType)) {
1865+
TypeChecker::applyFunctionBuilderBodyTransform(
1866+
func, builderType)) {
18661867
if (!*optBody)
18671868
return true;
18681869

lib/Sema/TypeChecker.h

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

564+
/// Find the return statements within the body of the given function.
565+
std::vector<ReturnStmt *> findReturnStatements(AnyFunctionRef fn);
566+
564567
bool typeCheckClosureBody(ClosureExpr *closure);
565568

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

0 commit comments

Comments
 (0)