mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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:
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user