Skip to content

Remove TypeChecker::ClosuresWithUncomputedCaptures #28367

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,10 @@ class ASTContext final {

void installGlobalTypeChecker(TypeChecker *TC);
public:
/// Returns if semantic AST queries are enabled. This generally means module
/// loading and name lookup can take place.
bool areSemanticQueriesEnabled() const;

/// Retrieve the global \c TypeChecker instance associated with this context.
TypeChecker *getLegacyGlobalTypeChecker() const;

Expand Down
4 changes: 4 additions & 0 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,10 @@ RC<syntax::SyntaxArena> ASTContext::getSyntaxArena() const {
return getImpl().TheSyntaxArena;
}

bool ASTContext::areSemanticQueriesEnabled() const {
return getLegacyGlobalTypeChecker() != nullptr;
}

TypeChecker *ASTContext::getLegacyGlobalTypeChecker() const {
return getImpl().Checker;
}
Expand Down
9 changes: 3 additions & 6 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2892,10 +2892,7 @@ bool ValueDecl::isRecursiveValidation() const {
Type ValueDecl::getInterfaceType() const {
auto &ctx = getASTContext();

// N.B. This assertion exists to catch new broken callers. It can be removed
// with the LazyResolver when the time comes.
assert(ctx.getLegacyGlobalTypeChecker()
&& "The type checker must be installed to make semantic queries!");
assert(ctx.areSemanticQueriesEnabled());

if (auto type =
evaluateOrDefault(ctx.evaluator,
Expand Down Expand Up @@ -5697,7 +5694,7 @@ StaticSpellingKind AbstractStorageDecl::getCorrectStaticSpelling() const {

llvm::TinyPtrVector<CustomAttr *> VarDecl::getAttachedPropertyWrappers() const {
auto &ctx = getASTContext();
if (!ctx.getLegacyGlobalTypeChecker()) {
if (!ctx.areSemanticQueriesEnabled()) {
return { };
}

Expand Down Expand Up @@ -6642,7 +6639,7 @@ ObjCSelector
AbstractFunctionDecl::getObjCSelector(DeclName preferredName,
bool skipIsObjCResolution) const {
// FIXME: Forces computation of the Objective-C selector.
if (getASTContext().getLegacyGlobalTypeChecker() && !skipIsObjCResolution)
if (getASTContext().areSemanticQueriesEnabled() && !skipIsObjCResolution)
(void)isObjC();

// If there is an @objc attribute with a name, use that name.
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/NameLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1660,7 +1660,7 @@ bool DeclContext::lookupQualified(ArrayRef<NominalTypeDecl *> typeDecls,
tracker->addUsedMember({current, member.getBaseName()},isLookupCascading);

// Make sure we've resolved implicit members, if we need them.
if (ctx.getLegacyGlobalTypeChecker()) {
if (ctx.areSemanticQueriesEnabled()) {
current->synthesizeSemanticMembersIfNeeded(member);
installPropertyWrapperMembersIfNeeded(current, member);
}
Expand Down
13 changes: 1 addition & 12 deletions lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4494,10 +4494,6 @@ namespace {
outerClosure->setType(outerClosureTy);
cs.cacheType(outerClosure);

// The inner closure at least will definitely have a capture.
cs.getTypeChecker().ClosuresWithUncomputedCaptures.push_back(outerClosure);
cs.getTypeChecker().ClosuresWithUncomputedCaptures.push_back(closure);

// let outerApply = "\( outerClosure )( \(E) )"
auto outerApply = CallExpr::createImplicit(ctx, outerClosure, {E}, {});
outerApply->setType(closureTy);
Expand Down Expand Up @@ -5411,8 +5407,7 @@ Expr *ExprRewriter::coerceCallArguments(Expr *arg, AnyFunctionType *funcType,
arg, closureType->getResult(),
locator.withPathElement(ConstraintLocator::AutoclosureResult));

convertedArg = TypeChecker::buildAutoClosureExpr(dc, arg, closureType);
cs.cacheExprTypes(convertedArg);
convertedArg = cs.buildAutoClosureExpr(arg, closureType);
} else {
convertedArg = coerceToType(
arg, paramType,
Expand Down Expand Up @@ -7269,12 +7264,6 @@ namespace {
ClosuresToTypeCheck.push_back(closure);
}

// Don't try to register captures if constraint system is used to
// produce diagnostics for one of the sub-expressions.
if (!cs.Options.contains(
ConstraintSystemFlags::SubExpressionDiagnostics))
cs.getTypeChecker().ClosuresWithUncomputedCaptures.push_back(closure);

return { false, closure };
}

Expand Down
2 changes: 0 additions & 2 deletions lib/Sema/CSDiagnostics.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,6 @@ class FailureDiagnostic {
InFlightDiagnostic emitDiagnostic(ArgTypes &&... Args) const;

protected:
TypeChecker &getTypeChecker() const { return CS.getTypeChecker(); }

DeclContext *getDC() const { return CS.DC; }

ASTContext &getASTContext() const { return CS.getASTContext(); }
Expand Down
7 changes: 3 additions & 4 deletions lib/Sema/CSGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2135,7 +2135,7 @@ namespace {
if (!ty || ty->is<TypeVariableType>())
ty = CS.createTypeVariable(CS.getConstraintLocator(locator),
TVO_CanBindToNoEscape);
return CS.getTypeChecker().getOptionalType(var->getLoc(), ty);
return TypeChecker::getOptionalType(var->getLoc(), ty);
case ReferenceOwnershipOptionality::Allowed:
case ReferenceOwnershipOptionality::Disallowed:
break;
Expand Down Expand Up @@ -2852,7 +2852,7 @@ namespace {
/// diagnosing ill-formed standard libraries, so it really isn't
/// worth QoI efforts.
Type getOptionalType(SourceLoc optLoc, Type valueTy) {
auto optTy = CS.getTypeChecker().getOptionalType(optLoc, valueTy);
auto optTy = TypeChecker::getOptionalType(optLoc, valueTy);
if (!optTy ||
TypeChecker::requireOptionalIntrinsics(CS.getASTContext(), optLoc))
return Type();
Expand Down Expand Up @@ -3863,8 +3863,7 @@ getMemberDecls(InterestedMemberKind Kind) {
ResolvedMemberResult
swift::resolveValueMember(DeclContext &DC, Type BaseTy, DeclName Name) {
ResolvedMemberResult Result;
assert(DC.getASTContext().getLegacyGlobalTypeChecker() &&
"Must have type checker to make global query!");
assert(DC.getASTContext().areSemanticQueriesEnabled());
ConstraintSystem CS(&DC, None);

// Look up all members of BaseTy with the given Name.
Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/CSSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6071,7 +6071,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
auto innerTV = createTypeVariable(locator,
TVO_CanBindToLValue |
TVO_CanBindToNoEscape);
Type optTy = getTypeChecker().getOptionalType(SourceLoc(), innerTV);
Type optTy = TypeChecker::getOptionalType(SourceLoc(), innerTV);
SmallVector<Constraint *, 2> optionalities;
auto nonoptionalResult = Constraint::createFixed(
*this, ConstraintKind::Bind,
Expand Down
34 changes: 34 additions & 0 deletions lib/Sema/ConstraintSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3474,3 +3474,37 @@ ConstraintSystem::isConversionEphemeral(ConversionRestrictionKind conversion,
return ConversionEphemeralness::NonEphemeral;
}
}

Expr *ConstraintSystem::buildAutoClosureExpr(Expr *expr,
FunctionType *closureType) {
auto &Context = DC->getASTContext();
bool isInDefaultArgumentContext = false;
if (auto *init = dyn_cast<Initializer>(DC))
isInDefaultArgumentContext =
init->getInitializerKind() == InitializerKind::DefaultArgument;

auto info = closureType->getExtInfo();
auto newClosureType = closureType;

if (isInDefaultArgumentContext && info.isNoEscape())
newClosureType = closureType->withExtInfo(info.withNoEscape(false))
->castTo<FunctionType>();

auto *closure = new (Context) AutoClosureExpr(
expr, newClosureType, AutoClosureExpr::InvalidDiscriminator, DC);

closure->setParameterList(ParameterList::createEmpty(Context));

Expr *result = closure;

if (!newClosureType->isEqual(closureType)) {
assert(isInDefaultArgumentContext);
assert(newClosureType
->withExtInfo(newClosureType->getExtInfo().withNoEscape(true))
->isEqual(closureType));
result = new (Context) FunctionConversionExpr(closure, closureType);
}

cacheExprTypes(result);
return result;
}
9 changes: 4 additions & 5 deletions lib/Sema/ConstraintSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -1671,11 +1671,6 @@ class ConstraintSystem {
ConstraintSystemOptions options);
~ConstraintSystem();

/// Retrieve the type checker associated with this constraint system.
TypeChecker &getTypeChecker() const {
return *Context.getLegacyGlobalTypeChecker();
}

/// Retrieve the constraint graph associated with this constraint system.
ConstraintGraph &getConstraintGraph() const { return CG; }

Expand Down Expand Up @@ -3026,6 +3021,10 @@ class ConstraintSystem {
ConstraintLocator *memberLocator,
bool includeInaccessibleMembers);

/// Build implicit autoclosure expression wrapping a given expression.
/// Given expression represents computed result of the closure.
Expr *buildAutoClosureExpr(Expr *expr, FunctionType *closureType);

private:
/// Determines whether or not a given conversion at a given locator requires
/// the creation of a temporary value that's only valid for a limited scope.
Expand Down
17 changes: 6 additions & 11 deletions lib/Sema/TypeCheckConstraints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2160,10 +2160,8 @@ Type TypeChecker::typeCheckExpression(Expr *&expr, DeclContext *dc,
ConstraintSystem *baseCS) {
auto &Context = dc->getASTContext();
FallbackDiagnosticListener diagListener(Context, options, listener);
auto *TC = Context.getLegacyGlobalTypeChecker();
assert(TC && "Must have a global type checker set");
return TC->typeCheckExpressionImpl(expr, dc, convertType, convertTypePurpose,
options, diagListener, baseCS);
return typeCheckExpressionImpl(expr, dc, convertType, convertTypePurpose,
options, diagListener, baseCS);
}

Type TypeChecker::typeCheckExpressionImpl(Expr *&expr, DeclContext *dc,
Expand Down Expand Up @@ -2308,24 +2306,21 @@ Type TypeChecker::typeCheckParameterDefault(Expr *&defaultValue,

if (isAutoClosure) {
class AutoClosureListener : public ExprTypeCheckListener {
DeclContext *DC;
FunctionType *ParamType;

public:
AutoClosureListener(DeclContext *DC, FunctionType *paramType)
: DC(DC), ParamType(paramType) {}
AutoClosureListener(FunctionType *paramType)
: ParamType(paramType) {}

Expr *appliedSolution(constraints::Solution &solution,
Expr *expr) override {
auto &cs = solution.getConstraintSystem();
auto *closure = TypeChecker::buildAutoClosureExpr(DC, expr, ParamType);
cs.cacheExprTypes(closure);
return closure;
return cs.buildAutoClosureExpr(expr, ParamType);
}
};

auto *fnType = paramType->castTo<FunctionType>();
AutoClosureListener listener(DC, fnType);
AutoClosureListener listener(fnType);
return typeCheckExpression(defaultValue, DC,
TypeLoc::withoutLoc(fnType->getResult()),
canFail ? CTP_DefaultParameter : CTP_CannotFail,
Expand Down
9 changes: 4 additions & 5 deletions lib/Sema/TypeCheckDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3265,8 +3265,6 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
}
}

// FIXME: Remove TypeChecker dependencies below.
auto &TC = *Ctx.getLegacyGlobalTypeChecker();
if (requiresDefinition(FD) && !FD->hasBody()) {
// Complain if we should have a body.
FD->diagnose(diag::func_decl_without_brace);
Expand All @@ -3276,7 +3274,8 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
} else if (shouldSkipBodyTypechecking(FD)) {
FD->setBodySkipped(FD->getBodySourceRange());
} else {
// Record the body.
// FIXME: Remove TypeChecker dependency.
auto &TC = *Ctx.getLegacyGlobalTypeChecker();
TC.definedFunctions.push_back(FD);
}

Expand Down Expand Up @@ -3595,8 +3594,6 @@ class DeclChecker : public DeclVisitor<DeclChecker> {

checkAccessControl(CD);

// FIXME: Remove TypeChecker dependencies below.
auto &TC = *Ctx.getLegacyGlobalTypeChecker();
if (requiresDefinition(CD) && !CD->hasBody()) {
// Complain if we should have a body.
CD->diagnose(diag::missing_initializer_def);
Expand All @@ -3606,6 +3603,8 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
} else if (shouldSkipBodyTypechecking(CD)) {
CD->setBodySkipped(CD->getBodySourceRange());
} else {
// FIXME: Remove TypeChecker dependency.
auto &TC = *Ctx.getLegacyGlobalTypeChecker();
TC.definedFunctions.push_back(CD);
}

Expand Down
35 changes: 0 additions & 35 deletions lib/Sema/TypeCheckExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -617,41 +617,6 @@ Expr *TypeChecker::buildRefExpr(ArrayRef<ValueDecl *> Decls,
return result;
}

Expr *TypeChecker::buildAutoClosureExpr(DeclContext *DC, Expr *expr,
FunctionType *closureType) {
auto &Context = DC->getASTContext();
bool isInDefaultArgumentContext = false;
if (auto *init = dyn_cast<Initializer>(DC))
isInDefaultArgumentContext =
init->getInitializerKind() == InitializerKind::DefaultArgument;

auto info = closureType->getExtInfo();
auto newClosureType = closureType;

if (isInDefaultArgumentContext && info.isNoEscape())
newClosureType = closureType->withExtInfo(info.withNoEscape(false))
->castTo<FunctionType>();

auto *closure = new (Context) AutoClosureExpr(
expr, newClosureType, AutoClosureExpr::InvalidDiscriminator, DC);

closure->setParameterList(ParameterList::createEmpty(Context));

// FIXME: Remove global type checker dependency.
auto *TC = Context.getLegacyGlobalTypeChecker();
TC->ClosuresWithUncomputedCaptures.push_back(closure);

if (!newClosureType->isEqual(closureType)) {
assert(isInDefaultArgumentContext);
assert(newClosureType
->withExtInfo(newClosureType->getExtInfo().withNoEscape(true))
->isEqual(closureType));
return new (Context) FunctionConversionExpr(closure, closureType);
}

return closure;
}

static Type lookupDefaultLiteralType(const DeclContext *dc,
StringRef name) {
auto &ctx = dc->getASTContext();
Expand Down
4 changes: 2 additions & 2 deletions lib/Sema/TypeCheckPropertyWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ AttachedPropertyWrapperTypeRequest::evaluate(Evaluator &evaluator,
return Type();

ASTContext &ctx = var->getASTContext();
if (!ctx.getLegacyGlobalTypeChecker())
if (!ctx.areSemanticQueriesEnabled())
return nullptr;

auto resolution =
Expand Down Expand Up @@ -527,7 +527,7 @@ PropertyWrapperBackingPropertyTypeRequest::evaluate(
return Type();

ASTContext &ctx = var->getASTContext();
if (!ctx.getLegacyGlobalTypeChecker())
if (!ctx.areSemanticQueriesEnabled())
return Type();

// If there's an initializer of some sort, checking it will determine the
Expand Down
4 changes: 3 additions & 1 deletion lib/Sema/TypeCheckStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ namespace {
ParentDC = CE;
CE->getBody()->walk(*this);
ParentDC = oldParentDC;

TypeChecker::computeCaptures(CE);
return { false, E };
}

Expand Down Expand Up @@ -148,7 +150,7 @@ namespace {
if (CE->hasSingleExpressionBody())
CE->getBody()->walk(ContextualizeClosures(CE));

// In neither case do we need to continue the *current* walk.
TypeChecker::computeCaptures(CE);
return { false, E };
}

Expand Down
9 changes: 1 addition & 8 deletions lib/Sema/TypeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,12 +302,6 @@ static void typeCheckFunctionsAndExternalDecls(SourceFile &SF, TypeChecker &TC)
}
} while (currentFunctionIdx < TC.definedFunctions.size());

// Compute captures for functions and closures we visited.
for (auto *closure : TC.ClosuresWithUncomputedCaptures) {
TypeChecker::computeCaptures(closure);
}
TC.ClosuresWithUncomputedCaptures.clear();

for (AbstractFunctionDecl *FD : llvm::reverse(TC.definedFunctions)) {
TypeChecker::computeCaptures(FD);
}
Expand Down Expand Up @@ -546,8 +540,7 @@ bool swift::performTypeLocChecking(ASTContext &Ctx, TypeLoc &T,
Optional<DiagnosticSuppression> suppression;
if (!ProduceDiagnostics)
suppression.emplace(Ctx.Diags);
assert(Ctx.getLegacyGlobalTypeChecker() &&
"Should have a TypeChecker registered");
assert(Ctx.areSemanticQueriesEnabled());
return TypeChecker::validateType(Ctx, T, resolution, options);
}

Expand Down
Loading