AsyncSequence and protocol conformance rethrows (#35224)

* Initial draft of async sequences

* Adjust AsyncSequence associated type requirements

* Add a draft implementation of AsyncSequence and associated functionality

* Correct merge damage and rename from GeneratorProtocol to AsyncIteratorProtocol

* Add AsyncSequence types to the cmake lists

* Add cancellation support

* [DRAFT] Implementation of protocol conformance rethrowing

* Account for ASTVerifier passes to ensure throwing and by conformance rethrowing verifies appropriately

* Remove commented out code

* OtherConstructorDeclRefExpr can also be a source of a rethrowing kind function

* Re-order the checkApply logic to account for existing throwing calculations better

* Extract rethrowing calculation into smaller functions

* Allow for closures and protocol conformances to contribute to throwing

* Add unit tests for conformance based rethrowing

* Restrict rethrowing requirements to only protocols marked with @rethrows

* Correct logic for gating of `@rethrows` and adjust the determinates to be based upon throws and not rethrows spelling

* Attempt to unify the async sequence features together

* Reorder try await to latest syntax

* revert back to the inout diagnosis

* House mutations in local scope

* Revert "House mutations in local scope"

This reverts commit d91f1b25b59fff8e4be107c808895ff3f293b394.

* Adjust for inout diagnostics and fall back to original mutation strategy

* Convert async flag to source locations and add initial try support to for await in syntax

* Fix case typo of MinMax.swift

* Adjust rethrowing tests to account for changes associated with @rethrows

* Allow parsing and diagnostics associated with try applied to for await in syntax

* Correct the code-completion for @rethrows

* Additional corrections for the code-completion for @rethrows this time for the last in the list

* Handle throwing cases of iteration of async sequences

* restore building XCTest

* First wave of feedback fixes

* Rework constraints checking for async sequence for-try-await-in checking

* Allow testing of for-await-in parsing and silgen testing and add unit tests for both

* Remove async sequence operators for now

* Back out cancellation of AsyncIteratorProtocols

* Restructure protocol conformance throws checking and cache results

* remove some stray whitespaces

* Correct some merge damage

* Ensure the throwing determinate for applying for-await-in always has a valid value and adjust the for-await-in silgen test to reflect the cancel changes

* Squelch the python linter for line length
This commit is contained in:
Philippe Hausler
2021-01-25 18:48:50 -08:00
committed by GitHub
parent a86430b937
commit 6e05240426
42 changed files with 1414 additions and 85 deletions

View File

@@ -26,6 +26,7 @@
#include "swift/AST/TypeCheckRequests.h"
#include "swift/AST/TypeWalker.h"
#include "swift/AST/Types.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/Basic/Statistic.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/Statistic.h"
@@ -185,6 +186,79 @@ ProtocolConformanceRef::getWitnessByName(Type type, DeclName name) const {
return getConcrete()->getWitnessDeclRef(requirement);
}
static bool classifyRequirement(ModuleDecl *module,
ProtocolConformance *reqConformance,
ValueDecl *requiredFn) {
auto declRef = reqConformance->getWitnessDeclRef(requiredFn);
auto witnessDecl = cast<AbstractFunctionDecl>(declRef.getDecl());
switch (witnessDecl->getRethrowingKind()) {
case FunctionRethrowingKind::ByConformance: {
auto substitutions = reqConformance->getSubstitutions(module);
for (auto conformanceRef : substitutions.getConformances()) {
if (conformanceRef.classifyAsThrows()) {
return true;
}
}
break;
}
case FunctionRethrowingKind::None:
break;
case FunctionRethrowingKind::Throws:
return true;
default:
return true;
}
return false;
}
// classify the type requirements of a given prottocol type with a function
// requirement as throws or not. This will detect if the signature of the
// function is throwing or not depending on associated types.
static bool classifyTypeRequirement(ModuleDecl *module, Type protoType,
ValueDecl *requiredFn,
ProtocolConformance *conformance,
ProtocolDecl *requiredProtocol) {
auto reqProtocol = cast<ProtocolDecl>(requiredFn->getDeclContext());
ProtocolConformance *reqConformance;
if(protoType->isEqual(reqProtocol->getSelfInterfaceType()) &&
requiredProtocol == reqProtocol) {
reqConformance = conformance;
} else {
auto reqConformanceRef =
conformance->getAssociatedConformance(protoType, reqProtocol);
if (!reqConformanceRef.isConcrete()) {
return true;
}
reqConformance = reqConformanceRef.getConcrete();
}
return classifyRequirement(module, reqConformance, requiredFn);
}
bool
ProtocolConformanceRefClassifyAsThrowsRequest::evaluate(
Evaluator &evaluator, ProtocolConformanceRef conformanceRef) const {
auto conformance = conformanceRef.getConcrete();
auto requiredProtocol = conformanceRef.getRequirement();
auto module = requiredProtocol->getModuleContext();
for (auto req : requiredProtocol->getRethrowingRequirements()) {
if (classifyTypeRequirement(module, req.first, req.second,
conformance, requiredProtocol)) {
return true;
}
}
return false;
}
bool ProtocolConformanceRef::classifyAsThrows() const {
if (!isConcrete()) { return true; }
return evaluateOrDefault(getRequirement()->getASTContext().evaluator,
ProtocolConformanceRefClassifyAsThrowsRequest{ *this },
true);
}
void *ProtocolConformance::operator new(size_t bytes, ASTContext &context,
AllocationArena arena,
unsigned alignment) {
@@ -1529,3 +1603,20 @@ void swift::simple_display(llvm::raw_ostream &out,
const ProtocolConformance *conf) {
conf->printName(out);
}
void swift::simple_display(llvm::raw_ostream &out, ProtocolConformanceRef conformanceRef) {
if (conformanceRef.isAbstract()) {
simple_display(out, conformanceRef.getAbstract());
} else if (conformanceRef.isConcrete()) {
simple_display(out, conformanceRef.getConcrete());
}
}
SourceLoc swift::extractNearestSourceLoc(const ProtocolConformanceRef conformanceRef) {
if (conformanceRef.isAbstract()) {
return extractNearestSourceLoc(conformanceRef.getAbstract());
} else if (conformanceRef.isConcrete()) {
return extractNearestSourceLoc(conformanceRef.getConcrete()->getProtocol());
}
return SourceLoc();
}