Skip to content

Commit b04d5d5

Browse files
committed
[ASTGen] Better handle pattern binding entries
Generate all entries, and ensure we introduce a PatternBindingInitializer context for non-local cases. Also use this opportunity to cleanup `PatternBindingDecl::create`.
1 parent f103655 commit b04d5d5

File tree

9 files changed

+121
-54
lines changed

9 files changed

+121
-54
lines changed

include/swift/AST/ASTBridging.h

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,13 @@ namespace swift {
265265
BridgedPattern Bridged##Id##Pattern_asPattern(Bridged##Id##Pattern pattern);
266266
#include "swift/AST/PatternNodes.def"
267267

268+
struct BridgedPatternBindingEntry {
269+
BridgedPattern pattern;
270+
BridgedSourceLoc equalLoc;
271+
BridgedNullableExpr init;
272+
BridgedNullablePatternBindingInitializer initContext;
273+
};
274+
268275
//===----------------------------------------------------------------------===//
269276
// MARK: Diagnostic Engine
270277
//===----------------------------------------------------------------------===//
@@ -371,17 +378,32 @@ void BridgedDiagnostic_fixItReplace(BridgedDiagnostic cDiag,
371378
SWIFT_NAME("BridgedDiagnostic.finish(self:)")
372379
void BridgedDiagnostic_finish(BridgedDiagnostic cDiag);
373380

381+
//===----------------------------------------------------------------------===//
382+
// MARK: DeclContexts
383+
//===----------------------------------------------------------------------===//
384+
385+
SWIFT_NAME("getter:BridgedDeclContext.isLocalContext(self:)")
386+
bool BridgedDeclContext_isLocalContext(BridgedDeclContext cDeclContext);
387+
388+
SWIFT_NAME("BridgedPatternBindingInitializer.create(declContext:)")
389+
BridgedPatternBindingInitializer
390+
BridgedPatternBindingInitializer_create(BridgedDeclContext cDeclContext);
391+
392+
SWIFT_NAME("getter:BridgedPatternBindingInitializer.asDeclContext(self:)")
393+
BridgedDeclContext BridgedPatternBindingInitializer_asDeclContext(
394+
BridgedPatternBindingInitializer cInit);
395+
374396
//===----------------------------------------------------------------------===//
375397
// MARK: Decls
376398
//===----------------------------------------------------------------------===//
377399

378400
SWIFT_NAME(
379401
"BridgedPatternBindingDecl.createParsed(_:declContext:bindingKeywordLoc:"
380-
"pattern:initializer:isStatic:isLet:)")
402+
"entries:isStatic:isLet:)")
381403
BridgedPatternBindingDecl BridgedPatternBindingDecl_createParsed(
382404
BridgedASTContext cContext, BridgedDeclContext cDeclContext,
383-
BridgedSourceLoc cBindingKeywordLoc, BridgedPattern pattern,
384-
BridgedExpr opaqueInitExpr, bool isStatic, bool isLet);
405+
BridgedSourceLoc cBindingKeywordLoc, BridgedArrayRef cBindingEntries,
406+
bool isStatic, bool isLet);
385407

386408
SWIFT_NAME("BridgedParamDecl.createParsed(_:declContext:specifierLoc:firstName:"
387409
"firstNameLoc:secondName:secondNameLoc:type:defaultValue:)")

include/swift/AST/ASTBridgingWrappers.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ AST_BRIDGING_WRAPPER_NULLABLE(TypeRepr)
7474
AST_BRIDGING_WRAPPER_NULLABLE(GenericParamList)
7575
AST_BRIDGING_WRAPPER_NULLABLE(TrailingWhereClause)
7676
AST_BRIDGING_WRAPPER_NULLABLE(ParameterList)
77+
AST_BRIDGING_WRAPPER_NULLABLE(PatternBindingInitializer)
7778
AST_BRIDGING_WRAPPER_NONNULL(TypeAttributes)
7879
AST_BRIDGING_WRAPPER_NONNULL(CustomAttribute)
7980

lib/AST/ASTBridging.cpp

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/Expr.h"
2121
#include "swift/AST/GenericParamList.h"
2222
#include "swift/AST/Identifier.h"
23+
#include "swift/AST/Initializer.h"
2324
#include "swift/AST/ParameterList.h"
2425
#include "swift/AST/ParseRequests.h"
2526
#include "swift/AST/Pattern.h"
@@ -324,36 +325,58 @@ void BridgedDiagnostic_finish(BridgedDiagnostic cDiag) {
324325
delete diag;
325326
}
326327

328+
//===----------------------------------------------------------------------===//
329+
// MARK: DeclContexts
330+
//===----------------------------------------------------------------------===//
331+
332+
bool BridgedDeclContext_isLocalContext(BridgedDeclContext cDeclContext) {
333+
return cDeclContext.unbridged()->isLocalContext();
334+
}
335+
336+
BridgedPatternBindingInitializer
337+
BridgedPatternBindingInitializer_create(BridgedDeclContext cDeclContext) {
338+
auto *dc = cDeclContext.unbridged();
339+
return new (dc->getASTContext()) PatternBindingInitializer(dc);
340+
}
341+
342+
BridgedDeclContext BridgedPatternBindingInitializer_asDeclContext(
343+
BridgedPatternBindingInitializer cInit) {
344+
return cInit.unbridged();
345+
}
346+
327347
//===----------------------------------------------------------------------===//
328348
// MARK: Decls
329349
//===----------------------------------------------------------------------===//
330350

331351
BridgedPatternBindingDecl BridgedPatternBindingDecl_createParsed(
332352
BridgedASTContext cContext, BridgedDeclContext cDeclContext,
333-
BridgedSourceLoc cBindingKeywordLoc, BridgedPattern cPattern,
334-
BridgedExpr initExpr, bool isStatic, bool isLet) {
353+
BridgedSourceLoc cBindingKeywordLoc, BridgedArrayRef cBindingEntries,
354+
bool isStatic, bool isLet) {
335355
ASTContext &context = cContext.unbridged();
336356
DeclContext *declContext = cDeclContext.unbridged();
337357

338-
Pattern *pattern = cPattern.unbridged();
358+
auto introducer = isLet ? VarDecl::Introducer::Let : VarDecl::Introducer::Var;
339359

340-
VarDecl::Introducer introducer =
341-
isLet ? VarDecl::Introducer::Let : VarDecl::Introducer::Var;
360+
SmallVector<PatternBindingEntry, 4> entries;
361+
for (auto &entry : cBindingEntries.unbridged<BridgedPatternBindingEntry>()) {
362+
auto *pattern = entry.pattern.unbridged();
363+
364+
// Configure all vars.
365+
pattern->forEachVariable([&](VarDecl *VD) {
366+
VD->setStatic(isStatic);
367+
VD->setIntroducer(introducer);
368+
});
369+
370+
entries.emplace_back(pattern, entry.equalLoc.unbridged(),
371+
entry.init.unbridged(), entry.initContext.unbridged());
372+
}
342373

343-
// Configure all vars.
344-
pattern->forEachVariable([&](VarDecl *VD) {
345-
VD->setStatic(isStatic);
346-
VD->setIntroducer(introducer);
347-
});
348-
349-
return PatternBindingDecl::create(context,
350-
/*StaticLoc=*/SourceLoc(),
351-
// FIXME: 'class' spelling kind.
352-
isStatic ? StaticSpellingKind::KeywordStatic
353-
: StaticSpellingKind::None,
354-
cBindingKeywordLoc.unbridged(), pattern,
355-
/*EqualLoc=*/SourceLoc(), // FIXME
356-
initExpr.unbridged(), declContext);
374+
return PatternBindingDecl::create(
375+
context,
376+
/*StaticLoc=*/SourceLoc(),
377+
// FIXME: 'class' spelling kind.
378+
isStatic ? StaticSpellingKind::KeywordStatic : StaticSpellingKind::None,
379+
cBindingKeywordLoc.unbridged(), entries, declContext);
357380
}
358381

359382
BridgedParamDecl BridgedParamDecl_createParsed(

lib/AST/Decl.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1919,26 +1919,26 @@ PatternBindingDecl::create(ASTContext &Ctx, SourceLoc StaticLoc,
19191919
/*ClangNode*/false);
19201920
auto PBD = ::new (D) PatternBindingDecl(StaticLoc, StaticSpelling, VarLoc,
19211921
PatternList.size(), Parent);
1922-
19231922
// Set up the patterns.
1924-
auto entries = PBD->getMutablePatternList();
1925-
unsigned elt = 0U-1;
1926-
for (auto pe : PatternList) {
1927-
++elt;
1928-
auto &newEntry = entries[elt];
1929-
newEntry = pe; // This should take care of initializer with flags
1930-
DeclContext *initContext = pe.getInitContext();
1923+
std::uninitialized_copy(PatternList.begin(), PatternList.end(),
1924+
PBD->getTrailingObjects<PatternBindingEntry>());
1925+
1926+
for (auto idx : range(PBD->getNumPatternEntries())) {
1927+
auto *initContext =
1928+
cast_or_null<PatternBindingInitializer>(PBD->getInitContext(idx));
19311929

19321930
// FIXME: We ought to reconsider this since it won't recontextualize any
19331931
// closures/decls present in the initialization expr. This currently should
19341932
// only affect implicit code though.
1935-
if (!initContext && !Parent->isLocalContext()) {
1936-
auto pbi = new (Ctx) PatternBindingInitializer(Parent);
1937-
pbi->setBinding(PBD, elt);
1938-
initContext = pbi;
1939-
}
1933+
if (!initContext && !Parent->isLocalContext())
1934+
initContext = new (Ctx) PatternBindingInitializer(Parent);
1935+
1936+
if (initContext)
1937+
initContext->setBinding(PBD, idx);
19401938

1941-
PBD->setPattern(elt, pe.getPattern(), initContext);
1939+
// We need to call setPattern to ensure the VarDecls in the pattern have
1940+
// the PatternBindingDecl set as their parent, and to setup the context.
1941+
PBD->setPattern(idx, PBD->getPattern(idx), initContext);
19421942
}
19431943
return PBD;
19441944
}

lib/ASTGen/Sources/ASTGen/ASTGen.swift

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -212,11 +212,13 @@ extension ASTGenVisitor {
212212
extension ASTGenVisitor {
213213
/// Replaces the current declaration context with `declContext` for the duration of its execution, and calls `body`.
214214
@inline(__always)
215-
func withDeclContext(_ declContext: BridgedDeclContext, _ body: () -> Void) {
215+
func withDeclContext<T>(_ declContext: BridgedDeclContext, _ body: () -> T) -> T {
216216
let oldDeclContext = self.declContext
217217
self.declContext = declContext
218-
body()
219-
self.declContext = oldDeclContext
218+
defer {
219+
self.declContext = oldDeclContext
220+
}
221+
return body()
220222
}
221223
}
222224

@@ -240,10 +242,6 @@ extension ASTGenVisitor {
240242
generate(decl: node.decl)
241243
}
242244

243-
func generate(initializerClause node: InitializerClauseSyntax) -> BridgedExpr {
244-
generate(expr: node.value)
245-
}
246-
247245
func generate(conditionElement node: ConditionElementSyntax) -> ASTNode {
248246
// FIXME: returning ASTNode is wrong, non-expression conditions are not ASTNode.
249247
switch node.condition {

lib/ASTGen/Sources/ASTGen/Bridge.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ extension BridgedNullablePattern: BridgedNullable {}
3333
extension BridgedNullableGenericParamList: BridgedNullable {}
3434
extension BridgedNullableTrailingWhereClause: BridgedNullable {}
3535
extension BridgedNullableParameterList: BridgedNullable {}
36+
extension BridgedNullablePatternBindingInitializer: BridgedNullable {}
3637

3738
/// Protocol that declares that there's a "Nullable" variation of the type.
3839
///
@@ -66,6 +67,9 @@ extension BridgedTrailingWhereClause: BridgedHasNullable {
6667
extension BridgedParameterList: BridgedHasNullable {
6768
typealias Nullable = BridgedNullableParameterList
6869
}
70+
extension BridgedPatternBindingInitializer: BridgedHasNullable {
71+
typealias Nullable = BridgedNullablePatternBindingInitializer
72+
}
6973

7074
public extension BridgedSourceLoc {
7175
/// Form a source location at the given absolute position in `buffer`.

lib/ASTGen/Sources/ASTGen/Decls.swift

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -288,19 +288,40 @@ extension ASTGenVisitor {
288288
// MARK: - AbstractStorageDecl
289289

290290
extension ASTGenVisitor {
291-
func generate(variableDecl node: VariableDeclSyntax) -> BridgedPatternBindingDecl {
292-
let pattern = generate(pattern: node.bindings.first!.pattern)
293-
let initializer = generate(initializerClause: node.bindings.first!.initializer!)
291+
func generate(patternBinding binding: PatternBindingSyntax) -> BridgedPatternBindingEntry {
292+
let pattern = generate(pattern: binding.pattern)
293+
let equalLoc = generateSourceLoc(binding.initializer?.equal)
294+
295+
var initExpr: BridgedExpr?
296+
var initContext: BridgedPatternBindingInitializer?
297+
if let initializer = binding.initializer {
298+
// Create a PatternBindingInitializer if we're not in a local context (this
299+
// ensures that property initializers are correctly treated as being in a
300+
// local context).
301+
if !self.declContext.isLocalContext {
302+
initContext = .create(declContext: self.declContext)
303+
}
304+
initExpr = withDeclContext(initContext?.asDeclContext ?? self.declContext) {
305+
generate(expr: initializer.value)
306+
}
307+
}
308+
return BridgedPatternBindingEntry(
309+
pattern: pattern,
310+
equalLoc: equalLoc,
311+
init: initExpr.asNullable,
312+
initContext: initContext.asNullable
313+
)
314+
}
294315

316+
func generate(variableDecl node: VariableDeclSyntax) -> BridgedPatternBindingDecl {
295317
let isStatic = false // TODO: compute this
296318
let isLet = node.bindingSpecifier.keywordKind == .let
297319

298320
return .createParsed(
299321
self.ctx,
300322
declContext: self.declContext,
301323
bindingKeywordLoc: self.generateSourceLoc(node.bindingSpecifier),
302-
pattern: pattern,
303-
initializer: initializer,
324+
entries: node.bindings.lazy.map(self.generate).bridgedArray(in: self),
304325
isStatic: isStatic,
305326
isLet: isLet
306327
)

lib/Parse/ParseDecl.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8364,12 +8364,6 @@ Parser::parseDeclVar(ParseDeclOptions Flags,
83648364
auto *PBD = PatternBindingDecl::create(Context, StaticLoc, StaticSpelling,
83658365
VarLoc, PBDEntries, BaseContext);
83668366

8367-
// Wire up any initializer contexts we needed.
8368-
for (unsigned i : indices(PBDEntries)) {
8369-
if (auto initContext = PBD->getInitContext(i))
8370-
cast<PatternBindingInitializer>(initContext)->setBinding(PBD, i);
8371-
}
8372-
83738367
// If we're setting up a TopLevelCodeDecl, configure it by setting up the
83748368
// body that holds PBD and we're done. The TopLevelCodeDecl is already set
83758369
// up in Decls to be returned to caller.

test/ASTGen/verify-parse.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ func test9(_ value: Any) { }
9898

9999
func test10<T>(t: T) where T: Proto1 {}
100100

101+
func test11() {
102+
var binding1 = 0, binding2 = ""
103+
}
104+
101105
protocol Proto1 {}
102106
protocol Proto2 {}
103107

0 commit comments

Comments
 (0)