Skip to content

Commit f1c0a49

Browse files
authored
Merge pull request swiftlang#34088 from slavapestov/constraint-solver-fixes-for-astscope
Fixes for expression type checking with parse-time name lookup disabled
2 parents 70859e8 + 6a82f24 commit f1c0a49

19 files changed

+399
-234
lines changed

include/swift/AST/ASTTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
SWIFT_TYPEID(ActorIsolation)
1919
SWIFT_TYPEID(AncestryFlags)
20+
SWIFT_TYPEID(BodyInitKind)
21+
SWIFT_TYPEID(BodyInitKindAndExpr)
2022
SWIFT_TYPEID(CtorInitializerKind)
2123
SWIFT_TYPEID(FunctionBuilderBodyPreCheck)
2224
SWIFT_TYPEID(GenericSignature)
@@ -35,6 +37,7 @@ SWIFT_TYPEID(TypePair)
3537
SWIFT_TYPEID(TypeWitnessAndDecl)
3638
SWIFT_TYPEID(Witness)
3739
SWIFT_TYPEID_NAMED(AbstractFunctionDecl *, AbstractFunctionDecl)
40+
SWIFT_TYPEID_NAMED(ApplyExpr *, ApplyExpr)
3841
SWIFT_TYPEID_NAMED(ClosureExpr *, ClosureExpr)
3942
SWIFT_TYPEID_NAMED(CodeCompletionCallbacksFactory *,
4043
CodeCompletionCallbacksFactory)

include/swift/AST/ASTTypeIDs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ namespace swift {
2424

2525
class AbstractFunctionDecl;
2626
class ActorIsolation;
27+
class ApplyExpr;
28+
enum class BodyInitKind;
29+
struct BodyInitKindAndExpr;
2730
class BraceStmt;
2831
class ClosureExpr;
2932
class CodeCompletionCallbacksFactory;

include/swift/AST/Decl.h

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -451,14 +451,7 @@ class alignas(1 << DeclAlignInBits) Decl {
451451
/// Whether we have computed the above.
452452
IsTransparentComputed : 1);
453453

454-
SWIFT_INLINE_BITFIELD(ConstructorDecl, AbstractFunctionDecl, 3+1+1,
455-
/// The body initialization kind (+1), or zero if not yet computed.
456-
///
457-
/// This value is cached but is not serialized, because it is a property
458-
/// of the definition of the constructor that is useful only to semantic
459-
/// analysis and SIL generation.
460-
ComputedBodyInitKind : 3,
461-
454+
SWIFT_INLINE_BITFIELD(ConstructorDecl, AbstractFunctionDecl, 1+1,
462455
/// Whether this constructor can fail, by building an Optional type.
463456
Failable : 1,
464457

@@ -6770,6 +6763,37 @@ enum class CtorInitializerKind {
67706763
Factory
67716764
};
67726765

6766+
/// Specifies the kind of initialization call performed within the body
6767+
/// of the constructor, e.g., self.init or super.init.
6768+
enum class BodyInitKind {
6769+
/// There are no calls to self.init or super.init.
6770+
None,
6771+
/// There is a call to self.init, which delegates to another (peer)
6772+
/// initializer.
6773+
Delegating,
6774+
/// There is a call to super.init, which chains to a superclass initializer.
6775+
Chained,
6776+
/// There are no calls to self.init or super.init explicitly in the body of
6777+
/// the constructor, but a 'super.init' call will be implicitly added
6778+
/// by semantic analysis.
6779+
ImplicitChained
6780+
};
6781+
6782+
struct BodyInitKindAndExpr {
6783+
BodyInitKind initKind;
6784+
ApplyExpr *initExpr;
6785+
6786+
BodyInitKindAndExpr() : initKind(BodyInitKind::None), initExpr(nullptr) {}
6787+
6788+
BodyInitKindAndExpr(BodyInitKind initKind, ApplyExpr *initExpr)
6789+
: initKind(initKind), initExpr(initExpr) {}
6790+
6791+
friend bool operator==(BodyInitKindAndExpr lhs, BodyInitKindAndExpr rhs) {
6792+
return (lhs.initKind == rhs.initKind &&
6793+
lhs.initExpr == rhs.initExpr);
6794+
}
6795+
};
6796+
67736797
/// ConstructorDecl - Declares a constructor for a type. For example:
67746798
///
67756799
/// \code
@@ -6818,38 +6842,11 @@ class ConstructorDecl : public AbstractFunctionDecl {
68186842

68196843
ParamDecl **getImplicitSelfDeclStorage() { return &SelfDecl; }
68206844

6821-
/// Specifies the kind of initialization call performed within the body
6822-
/// of the constructor, e.g., self.init or super.init.
6823-
enum class BodyInitKind {
6824-
/// There are no calls to self.init or super.init.
6825-
None,
6826-
/// There is a call to self.init, which delegates to another (peer)
6827-
/// initializer.
6828-
Delegating,
6829-
/// There is a call to super.init, which chains to a superclass initializer.
6830-
Chained,
6831-
/// There are no calls to self.init or super.init explicitly in the body of
6832-
/// the constructor, but a 'super.init' call will be implicitly added
6833-
/// by semantic analysis.
6834-
ImplicitChained
6835-
};
6836-
68376845
/// Determine whether the body of this constructor contains any delegating
68386846
/// or superclass initializations (\c self.init or \c super.init,
68396847
/// respectively) within its body.
6840-
///
6841-
/// \param diags If non-null, this check will ensure that the constructor
6842-
/// body is consistent in its use of delegation vs. chaining and emit any
6843-
/// diagnostics through the given diagnostic engine.
6844-
///
6845-
/// \param init If non-null and there is an explicit \c self.init or
6846-
/// \c super.init within the body, will be set to point at that
6847-
/// initializer.
6848-
BodyInitKind getDelegatingOrChainedInitKind(DiagnosticEngine *diags,
6849-
ApplyExpr **init = nullptr) const;
6850-
void clearCachedDelegatingOrChainedInitKind() {
6851-
Bits.ConstructorDecl.ComputedBodyInitKind = 0;
6852-
}
6848+
BodyInitKindAndExpr getDelegatingOrChainedInitKind() const;
6849+
void clearCachedDelegatingOrChainedInitKind();
68536850

68546851
/// Whether this constructor is required.
68556852
bool isRequired() const {

include/swift/AST/Evaluator.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,13 @@ class Evaluator {
322322
cache.insert({AnyRequest(request), std::move(output)});
323323
}
324324

325+
/// Do not introduce new callers of this function.
326+
template<typename Request,
327+
typename std::enable_if<!Request::hasExternalCache>::type* = nullptr>
328+
void clearCachedOutput(const Request &request) {
329+
cache.erase(AnyRequest(request));
330+
}
331+
325332
/// Clear the cache stored within this evaluator.
326333
///
327334
/// Note that this does not clear the caches of requests that use external

include/swift/AST/Expr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5793,6 +5793,7 @@ Expr *packSingleArgument(
57935793

57945794
void simple_display(llvm::raw_ostream &out, const ClosureExpr *CE);
57955795
void simple_display(llvm::raw_ostream &out, const DefaultArgumentExpr *expr);
5796+
void simple_display(llvm::raw_ostream &out, const Expr *expr);
57965797

57975798
SourceLoc extractNearestSourceLoc(const DefaultArgumentExpr *expr);
57985799

include/swift/AST/NameLookup.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,14 @@ class ASTScope {
684684
static void unqualifiedLookup(SourceFile *, SourceLoc,
685685
namelookup::AbstractASTScopeDeclConsumer &);
686686

687+
/// Lookup that only finds local declarations and does not trigger
688+
/// interface type computation.
689+
static void lookupLocalDecls(SourceFile *, DeclName, SourceLoc,
690+
SmallVectorImpl<ValueDecl *> &);
691+
692+
/// Returns the result if there is exactly one, nullptr otherwise.
693+
static ValueDecl *lookupSingleLocalDecl(SourceFile *, DeclName, SourceLoc);
694+
687695
/// Entry point to record the visible statement labels from the given
688696
/// point.
689697
///

include/swift/AST/TypeCheckRequests.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,29 @@ class InitKindRequest :
211211
CtorInitializerKind
212212
evaluate(Evaluator &evaluator, ConstructorDecl *decl) const;
213213

214+
public:
215+
// Caching.
216+
bool isCached() const { return true; }
217+
};
218+
219+
void simple_display(llvm::raw_ostream &out, BodyInitKind initKind);
220+
void simple_display(llvm::raw_ostream &out, BodyInitKindAndExpr initKindAndExpr);
221+
222+
/// Computes the kind of initializer call (self.init or super.init) performed
223+
/// in the body of a \c ConstructorDecl
224+
class BodyInitKindRequest :
225+
public SimpleRequest<BodyInitKindRequest,
226+
BodyInitKindAndExpr(ConstructorDecl *),
227+
RequestFlags::Cached> {
228+
public:
229+
using SimpleRequest::SimpleRequest;
230+
231+
private:
232+
friend SimpleRequest;
233+
234+
// Evaluation.
235+
BodyInitKindAndExpr evaluate(Evaluator &evaluator, ConstructorDecl *decl) const;
236+
214237
public:
215238
// Caching.
216239
bool isCached() const { return true; }

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ SWIFT_REQUEST(TypeChecker, InheritsSuperclassInitializersRequest,
121121
bool(ClassDecl *), SeparatelyCached, NoLocationInfo)
122122
SWIFT_REQUEST(TypeChecker, InitKindRequest,
123123
CtorInitializerKind(ConstructorDecl *), Cached, NoLocationInfo)
124+
SWIFT_REQUEST(TypeChecker, BodyInitKindRequest,
125+
BodyInitKindAndExpr(ConstructorDecl *), Cached,
126+
NoLocationInfo)
124127
SWIFT_REQUEST(TypeChecker, InterfaceTypeRequest,
125128
Type(ValueDecl *), SeparatelyCached, NoLocationInfo)
126129
SWIFT_REQUEST(TypeChecker, IsAccessorTransparentRequest, bool(AccessorDecl *),

lib/AST/Decl.cpp

Lines changed: 11 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -5463,8 +5463,8 @@ bool VarDecl::isSettable(const DeclContext *UseDC,
54635463
// If this is a convenience initializer (i.e. one that calls
54645464
// self.init), then let properties are never mutable in it. They are
54655465
// only mutable in designated initializers.
5466-
if (CD->getDelegatingOrChainedInitKind(nullptr) ==
5467-
ConstructorDecl::BodyInitKind::Delegating)
5466+
auto initKindAndExpr = CD->getDelegatingOrChainedInitKind();
5467+
if (initKindAndExpr.initKind == BodyInitKind::Delegating)
54685468
return false;
54695469

54705470
return true;
@@ -7522,7 +7522,6 @@ ConstructorDecl::ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
75227522
if (BodyParams)
75237523
setParameters(BodyParams);
75247524

7525-
Bits.ConstructorDecl.ComputedBodyInitKind = 0;
75267525
Bits.ConstructorDecl.HasStubImplementation = 0;
75277526
Bits.ConstructorDecl.Failable = Failable;
75287527

@@ -7750,169 +7749,17 @@ CtorInitializerKind ConstructorDecl::getInitKind() const {
77507749
CtorInitializerKind::Designated);
77517750
}
77527751

7753-
ConstructorDecl::BodyInitKind
7754-
ConstructorDecl::getDelegatingOrChainedInitKind(DiagnosticEngine *diags,
7755-
ApplyExpr **init) const {
7752+
BodyInitKindAndExpr
7753+
ConstructorDecl::getDelegatingOrChainedInitKind() const {
7754+
return evaluateOrDefault(getASTContext().evaluator,
7755+
BodyInitKindRequest{const_cast<ConstructorDecl *>(this)},
7756+
BodyInitKindAndExpr());
77567757
assert(hasBody() && "Constructor does not have a definition");
7758+
}
77577759

7758-
if (init)
7759-
*init = nullptr;
7760-
7761-
// If we already computed the result, return it.
7762-
if (Bits.ConstructorDecl.ComputedBodyInitKind) {
7763-
auto Kind = static_cast<BodyInitKind>(
7764-
Bits.ConstructorDecl.ComputedBodyInitKind - 1);
7765-
assert((Kind == BodyInitKind::None || !init) &&
7766-
"can't return cached result with the init expr");
7767-
return Kind;
7768-
}
7769-
7770-
7771-
struct FindReferenceToInitializer : ASTWalker {
7772-
const ConstructorDecl *Decl;
7773-
BodyInitKind Kind = BodyInitKind::None;
7774-
ApplyExpr *InitExpr = nullptr;
7775-
DiagnosticEngine *Diags;
7776-
7777-
FindReferenceToInitializer(const ConstructorDecl *decl,
7778-
DiagnosticEngine *diags)
7779-
: Decl(decl), Diags(diags) { }
7780-
7781-
bool walkToDeclPre(class Decl *D) override {
7782-
// Don't walk into further nominal decls.
7783-
return !isa<NominalTypeDecl>(D);
7784-
}
7785-
7786-
std::pair<bool, Expr*> walkToExprPre(Expr *E) override {
7787-
// Don't walk into closures.
7788-
if (isa<ClosureExpr>(E))
7789-
return { false, E };
7790-
7791-
// Look for calls of a constructor on self or super.
7792-
auto apply = dyn_cast<ApplyExpr>(E);
7793-
if (!apply)
7794-
return { true, E };
7795-
7796-
auto Callee = apply->getSemanticFn();
7797-
7798-
Expr *arg;
7799-
7800-
if (isa<OtherConstructorDeclRefExpr>(Callee)) {
7801-
arg = apply->getArg();
7802-
} else if (auto *CRE = dyn_cast<ConstructorRefCallExpr>(Callee)) {
7803-
arg = CRE->getArg();
7804-
} else if (auto *dotExpr = dyn_cast<UnresolvedDotExpr>(Callee)) {
7805-
if (dotExpr->getName().getBaseName() != DeclBaseName::createConstructor())
7806-
return { true, E };
7807-
7808-
arg = dotExpr->getBase();
7809-
} else {
7810-
// Not a constructor call.
7811-
return { true, E };
7812-
}
7813-
7814-
// Look for a base of 'self' or 'super'.
7815-
BodyInitKind myKind;
7816-
if (arg->isSuperExpr())
7817-
myKind = BodyInitKind::Chained;
7818-
else if (arg->isSelfExprOf(Decl, /*sameBase*/true))
7819-
myKind = BodyInitKind::Delegating;
7820-
else {
7821-
// We're constructing something else.
7822-
return { true, E };
7823-
}
7824-
7825-
if (Kind == BodyInitKind::None) {
7826-
Kind = myKind;
7827-
7828-
// If we're not emitting diagnostics, we're done.
7829-
if (!Diags)
7830-
return { false, nullptr };
7831-
7832-
InitExpr = apply;
7833-
return { true, E };
7834-
}
7835-
7836-
assert(Diags && "Failed to abort traversal early");
7837-
7838-
// If the kind changed, complain.
7839-
if (Kind != myKind) {
7840-
// The kind changed. Complain.
7841-
Diags->diagnose(E->getLoc(), diag::init_delegates_and_chains);
7842-
Diags->diagnose(InitExpr->getLoc(), diag::init_delegation_or_chain,
7843-
Kind == BodyInitKind::Chained);
7844-
}
7845-
7846-
return { true, E };
7847-
}
7848-
};
7849-
7850-
FindReferenceToInitializer finder(this, diags);
7851-
getBody()->walk(finder);
7852-
7853-
// get the kind out of the finder.
7854-
auto Kind = finder.Kind;
7855-
7856-
auto *NTD = getDeclContext()->getSelfNominalTypeDecl();
7857-
7858-
// Protocol extension and enum initializers are always delegating.
7859-
if (Kind == BodyInitKind::None) {
7860-
if (isa<ProtocolDecl>(NTD) || isa<EnumDecl>(NTD)) {
7861-
Kind = BodyInitKind::Delegating;
7862-
}
7863-
}
7864-
7865-
// Struct initializers that cannot see the layout of the struct type are
7866-
// always delegating. This occurs if the struct type is not fixed layout,
7867-
// and the constructor is either inlinable or defined in another module.
7868-
if (Kind == BodyInitKind::None && isa<StructDecl>(NTD)) {
7869-
// Note: This is specifically not using isFormallyResilient. We relax this
7870-
// rule for structs in non-resilient modules so that they can have inlinable
7871-
// constructors, as long as those constructors don't reference private
7872-
// declarations.
7873-
if (NTD->isResilient() &&
7874-
getResilienceExpansion() == ResilienceExpansion::Minimal) {
7875-
Kind = BodyInitKind::Delegating;
7876-
7877-
} else if (isa<ExtensionDecl>(getDeclContext())) {
7878-
const ModuleDecl *containingModule = getParentModule();
7879-
// Prior to Swift 5, cross-module initializers were permitted to be
7880-
// non-delegating. However, if the struct isn't fixed-layout, we have to
7881-
// be delegating because, well, we don't know the layout.
7882-
// A dynamic replacement is permitted to be non-delegating.
7883-
if (NTD->isResilient() ||
7884-
(containingModule->getASTContext().isSwiftVersionAtLeast(5) &&
7885-
!getAttrs().getAttribute<DynamicReplacementAttr>())) {
7886-
if (containingModule != NTD->getParentModule())
7887-
Kind = BodyInitKind::Delegating;
7888-
}
7889-
}
7890-
}
7891-
7892-
// If we didn't find any delegating or chained initializers, check whether
7893-
// the initializer was explicitly marked 'convenience'.
7894-
if (Kind == BodyInitKind::None && getAttrs().hasAttribute<ConvenienceAttr>())
7895-
Kind = BodyInitKind::Delegating;
7896-
7897-
// If we still don't know, check whether we have a class with a superclass: it
7898-
// gets an implicit chained initializer.
7899-
if (Kind == BodyInitKind::None) {
7900-
if (auto classDecl = getDeclContext()->getSelfClassDecl()) {
7901-
if (classDecl->hasSuperclass())
7902-
Kind = BodyInitKind::ImplicitChained;
7903-
}
7904-
}
7905-
7906-
// Cache the result if it is trustworthy.
7907-
if (diags) {
7908-
auto *mutableThis = const_cast<ConstructorDecl *>(this);
7909-
mutableThis->Bits.ConstructorDecl.ComputedBodyInitKind =
7910-
static_cast<unsigned>(Kind) + 1;
7911-
if (init)
7912-
*init = finder.InitExpr;
7913-
}
7914-
7915-
return Kind;
7760+
void ConstructorDecl::clearCachedDelegatingOrChainedInitKind() {
7761+
getASTContext().evaluator.clearCachedOutput(
7762+
BodyInitKindRequest{const_cast<ConstructorDecl *>(this)});
79167763
}
79177764

79187765
SourceRange DestructorDecl::getSourceRange() const {

0 commit comments

Comments
 (0)