Skip to content
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

[ASTGen] ParamDecl generation improvements #79456

Merged
merged 2 commits into from
Feb 19, 2025
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
15 changes: 13 additions & 2 deletions include/swift/AST/ASTBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,15 @@ SWIFT_NAME("getter:BridgedPatternBindingInitializer.asDeclContext(self:)")
BridgedDeclContext BridgedPatternBindingInitializer_asDeclContext(
BridgedPatternBindingInitializer cInit);

SWIFT_NAME("BridgedDefaultArgumentInitializer.create(declContext:index:)")
BridgedDefaultArgumentInitializer
BridgedDefaultArgumentInitializer_create(BridgedDeclContext cDeclContext,
size_t index);

SWIFT_NAME("getter:BridgedDefaultArgumentInitializer.asDeclContext(self:)")
BridgedDeclContext DefaultArgumentInitializer_asDeclContext(
BridgedDefaultArgumentInitializer cInit);

SWIFT_NAME("BridgedCustomAttributeInitializer.create(declContext:)")
BridgedCustomAttributeInitializer
BridgedCustomAttributeInitializer_create(BridgedDeclContext cDeclContext);
Expand Down Expand Up @@ -1302,13 +1311,15 @@ BridgedPatternBindingDecl BridgedPatternBindingDecl_createParsed(
BridgedVarDeclIntroducer cIntorducer, BridgedArrayRef cBindingEntries);

SWIFT_NAME("BridgedParamDecl.createParsed(_:declContext:specifierLoc:argName:"
"argNameLoc:paramName:paramNameLoc:type:defaultValue:)")
"argNameLoc:paramName:paramNameLoc:type:defaultValue:"
"defaultValueInitContext:)")
BridgedParamDecl BridgedParamDecl_createParsed(
BridgedASTContext cContext, BridgedDeclContext cDeclContext,
BridgedSourceLoc cSpecifierLoc, BridgedIdentifier cArgName,
BridgedSourceLoc cArgNameLoc, BridgedIdentifier cParamName,
BridgedSourceLoc cParamNameLoc, BridgedNullableTypeRepr type,
BridgedNullableExpr defaultValue);
BridgedNullableExpr defaultValue,
BridgedNullableDefaultArgumentInitializer cDefaultArgumentInitContext);

/// The various spellings of ownership modifier that can be used in source.
enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedParamSpecifier {
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/ASTBridgingWrappers.def
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ AST_BRIDGING_WRAPPER_NULLABLE(GenericParamList)
AST_BRIDGING_WRAPPER_NULLABLE(TrailingWhereClause)
AST_BRIDGING_WRAPPER_NULLABLE(ParameterList)
AST_BRIDGING_WRAPPER_NULLABLE(PatternBindingInitializer)
AST_BRIDGING_WRAPPER_NULLABLE(DefaultArgumentInitializer)
AST_BRIDGING_WRAPPER_NULLABLE(CustomAttributeInitializer)
AST_BRIDGING_WRAPPER_NONNULL(TypeAttributes)
AST_BRIDGING_WRAPPER_NONNULL(CustomAttribute)
Expand Down
20 changes: 11 additions & 9 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -6859,6 +6859,7 @@ class VarDecl : public AbstractStorageDecl {

/// A function parameter declaration.
class ParamDecl : public VarDecl {
friend class ParameterList;
friend class DefaultArgumentInitContextRequest;
friend class DefaultArgumentExprRequest;
friend class DefaultArgumentTypeRequest;
Expand All @@ -6885,15 +6886,17 @@ class ParamDecl : public VarDecl {

/// Stores the context for the default argument as well as a bit to
/// indicate whether the default expression has been type-checked.
llvm::PointerIntPair<Initializer *, 1, bool> InitContextAndIsTypeChecked;
llvm::PointerIntPair<DefaultArgumentInitializer *, 1, bool>
InitContextAndIsTypeChecked;

StringRef StringRepresentation;
CaptureInfo Captures;
};

/// Retrieve the cached initializer context for the parameter's default
/// argument without triggering a request.
std::optional<Initializer *> getCachedDefaultArgumentInitContext() const;
std::optional<DefaultArgumentInitializer *>
getCachedDefaultArgumentInitContext() const;

/// NOTE: This is stored using bits from TyReprAndFlags and
/// DefaultValueAndFlags.
Expand Down Expand Up @@ -7002,12 +7005,11 @@ class ParamDecl : public VarDecl {
DeclContext *Parent,
ParamSpecifier specifier = ParamSpecifier::Default);

static ParamDecl *createParsed(ASTContext &Context, SourceLoc specifierLoc,
SourceLoc argumentNameLoc,
Identifier argumentName,
SourceLoc parameterNameLoc,
Identifier parameterName, Expr *defaultValue,
DeclContext *dc);
static ParamDecl *createParsed(
ASTContext &Context, SourceLoc specifierLoc, SourceLoc argumentNameLoc,
Identifier argumentName, SourceLoc parameterNameLoc,
Identifier parameterName, Expr *defaultValue,
DefaultArgumentInitializer *defaultValueInitContext, DeclContext *dc);

/// Retrieve the argument (API) name for this function parameter.
Identifier getArgumentName() const {
Expand Down Expand Up @@ -7118,7 +7120,7 @@ class ParamDecl : public VarDecl {
/// Retrieve the initializer context for the parameter's default argument.
Initializer *getDefaultArgumentInitContext() const;

void setDefaultArgumentInitContext(Initializer *initContext);
void setDefaultArgumentInitContext(DefaultArgumentInitializer *initContext);

CaptureInfo getDefaultArgumentCaptureInfo() const;

Expand Down
10 changes: 8 additions & 2 deletions include/swift/AST/Initializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,18 +126,24 @@ class PatternBindingInitializer : public Initializer {
/// A default argument expression. The parent context is the function
/// (possibly a closure) for which this is a default argument.
class DefaultArgumentInitializer : public Initializer {
public:
explicit DefaultArgumentInitializer(DeclContext *parent, unsigned index)
: Initializer(InitializerKind::DefaultArgument, parent) {
SpareBits = index;
}

public:
static DefaultArgumentInitializer *create(DeclContext *parent,
unsigned index) {
return new (parent->getASTContext())
DefaultArgumentInitializer(parent, index);
}

unsigned getIndex() const { return SpareBits; }

/// Change the parent of this context. This is necessary because
/// the function signature is parsed before the function
/// declaration/expression itself is built.
void changeFunction(DeclContext *parent, ParameterList *paramLists);
void changeFunction(DeclContext *parent);

static bool classof(const DeclContext *DC) {
if (auto init = dyn_cast<Initializer>(DC))
Expand Down
10 changes: 5 additions & 5 deletions include/swift/AST/TypeCheckRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -3136,7 +3136,7 @@ class DistributedModuleIsAvailableRequest
/// Computes an initializer context for a parameter with a default argument.
class DefaultArgumentInitContextRequest
: public SimpleRequest<DefaultArgumentInitContextRequest,
Initializer *(ParamDecl *),
DefaultArgumentInitializer *(ParamDecl *),
RequestFlags::SeparatelyCached> {
public:
using SimpleRequest::SimpleRequest;
Expand All @@ -3145,14 +3145,14 @@ class DefaultArgumentInitContextRequest
friend SimpleRequest;

// Evaluation.
Initializer * evaluate(Evaluator &evaluator,
ParamDecl *param) const;
DefaultArgumentInitializer *evaluate(Evaluator &evaluator,
ParamDecl *param) const;

public:
// Separate caching.
bool isCached() const { return true; }
std::optional<Initializer *> getCachedResult() const;
void cacheResult(Initializer *init) const;
std::optional<DefaultArgumentInitializer *> getCachedResult() const;
void cacheResult(DefaultArgumentInitializer *init) const;
};

/// Computes the fully type-checked default argument expression for a given
Expand Down
8 changes: 3 additions & 5 deletions include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1504,7 +1504,6 @@ class Parser {
/// A structure for collecting information about the default
/// arguments of a context.
struct DefaultArgumentInfo {
llvm::SmallVector<DefaultArgumentInitializer *, 4> ParsedContexts;
unsigned NextIndex : 31;

/// Track whether or not one of the parameters in a signature's argument
Expand All @@ -1515,10 +1514,6 @@ class Parser {
/// all the arguments, not just those that have default arguments.
unsigned claimNextIndex() { return NextIndex++; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like claimNextIndex is unused?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would also be nice to see if we could remove HasDefaultArgument, seems like the diagnostic logic there could either be plumbed down or check the ParameterList itself

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, DefaultArgumentInfo does mostly nothing anymore. I guess HasDefaultArgument diagnostic can be sinked into TyoeCheckDeclPrimary. I will try it in followups, those diagnostics are needed in ASTGen mode too.


/// Set the parsed context of all default argument initializers to
/// the given function, enum case or subscript.
void setFunctionContext(DeclContext *DC, ParameterList *paramList);

DefaultArgumentInfo() {
NextIndex = 0;
HasDefaultArgument = false;
Expand Down Expand Up @@ -1567,6 +1562,9 @@ class Parser {
/// The default argument for this parameter.
Expr *DefaultArg = nullptr;

/// The default argument for this parameter.
DefaultArgumentInitializer *DefaultArgInitContext = nullptr;

/// True if we emitted a parse error about this parameter.
bool isInvalid = false;

Expand Down
6 changes: 4 additions & 2 deletions lib/AST/Bridging/DeclBridging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,13 @@ BridgedParamDecl BridgedParamDecl_createParsed(
BridgedSourceLoc cSpecifierLoc, BridgedIdentifier cArgName,
BridgedSourceLoc cArgNameLoc, BridgedIdentifier cParamName,
BridgedSourceLoc cParamNameLoc, BridgedNullableTypeRepr opaqueType,
BridgedNullableExpr opaqueDefaultValue) {
BridgedNullableExpr cDefaultArgument,
BridgedNullableDefaultArgumentInitializer cDefaultArgumentInitContext) {
auto *paramDecl = ParamDecl::createParsed(
cContext.unbridged(), cSpecifierLoc.unbridged(), cArgNameLoc.unbridged(),
cArgName.unbridged(), cParamNameLoc.unbridged(), cParamName.unbridged(),
opaqueDefaultValue.unbridged(), cDeclContext.unbridged());
cDefaultArgument.unbridged(), cDefaultArgumentInitContext.unbridged(),
cDeclContext.unbridged());

if (auto type = opaqueType.unbridged()) {
paramDecl->setTypeRepr(type);
Expand Down
11 changes: 11 additions & 0 deletions lib/AST/Bridging/DeclContextBridging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ BridgedDeclContext BridgedPatternBindingInitializer_asDeclContext(
return cInit.unbridged();
}

BridgedDefaultArgumentInitializer
BridgedDefaultArgumentInitializer_create(BridgedDeclContext cDeclContext,
size_t index) {
return DefaultArgumentInitializer::create(cDeclContext.unbridged(), index);
}

BridgedDeclContext DefaultArgumentInitializer_asDeclContext(
BridgedDefaultArgumentInitializer cInit) {
return cInit.unbridged();
}

BridgedCustomAttributeInitializer
BridgedCustomAttributeInitializer_create(BridgedDeclContext cDeclContext) {
return CustomAttributeInitializer::create(cDeclContext.unbridged());
Expand Down
50 changes: 24 additions & 26 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8686,27 +8686,30 @@ static DefaultArgumentKind computeDefaultArgumentKind(DeclContext *dc,
llvm_unreachable("Unhandled MagicIdentifierLiteralExpr in switch.");
}

ParamDecl *ParamDecl::createParsed(ASTContext &Context, SourceLoc specifierLoc,
SourceLoc argumentNameLoc,
Identifier argumentName,
SourceLoc parameterNameLoc,
Identifier parameterName, Expr *defaultValue,
DeclContext *dc) {
ParamDecl *ParamDecl::createParsed(
ASTContext &Context, SourceLoc specifierLoc, SourceLoc argumentNameLoc,
Identifier argumentName, SourceLoc parameterNameLoc,
Identifier parameterName, Expr *defaultValue,
DefaultArgumentInitializer *defaultValueInitContext, DeclContext *dc) {
auto *decl =
new (Context) ParamDecl(specifierLoc, argumentNameLoc, argumentName,
parameterNameLoc, parameterName, dc);

const auto kind = computeDefaultArgumentKind(dc, defaultValue);
if (kind == DefaultArgumentKind::Inherited) {
// The 'super' in inherited default arguments is a specifier rather than an
// expression.
// TODO: However, we may want to retain its location for diagnostics.
defaultValue = nullptr;
if (defaultValue) {
const auto kind = computeDefaultArgumentKind(dc, defaultValue);
if (kind == DefaultArgumentKind::Inherited) {
// The 'super' in inherited default arguments is a specifier rather than
// an expression.
// TODO: However, we may want to retain its location for diagnostics.
defaultValue = nullptr;
}
ASSERT(defaultValueInitContext);
decl->setDefaultExpr(defaultValue);
decl->setDefaultArgumentKind(kind);
if (defaultValue)
decl->setDefaultArgumentInitContext(defaultValueInitContext);
}

decl->setDefaultExpr(defaultValue);
decl->setDefaultArgumentKind(kind);

return decl;
}

Expand Down Expand Up @@ -8870,7 +8873,7 @@ AnyFunctionType::Param ParamDecl::toFunctionParam(Type type) const {
return AnyFunctionType::Param(type, label, flags, internalLabel);
}

std::optional<Initializer *>
std::optional<DefaultArgumentInitializer *>
ParamDecl::getCachedDefaultArgumentInitContext() const {
if (auto *defaultInfo = DefaultValueAndFlags.getPointer())
if (auto *init = defaultInfo->InitContextAndIsTypeChecked.getPointer())
Expand Down Expand Up @@ -9043,7 +9046,8 @@ CustomAttr *ValueDecl::getAttachedResultBuilder() const {
nullptr);
}

void ParamDecl::setDefaultArgumentInitContext(Initializer *initContext) {
void ParamDecl::setDefaultArgumentInitContext(
DefaultArgumentInitializer *initContext) {
auto oldContext = getCachedDefaultArgumentInitContext();
assert((!oldContext || oldContext == initContext) &&
"Cannot change init context after setting");
Expand Down Expand Up @@ -9246,15 +9250,9 @@ ParamDecl::setDefaultValueStringRepresentation(StringRef stringRepresentation) {
stringRepresentation;
}

void DefaultArgumentInitializer::changeFunction(
DeclContext *parent, ParameterList *paramList) {
if (parent->isLocalContext()) {
setParent(parent);
}

auto param = paramList->get(getIndex());
if (param->hasDefaultExpr() || param->getStoredProperty())
param->setDefaultArgumentInitContext(this);
void DefaultArgumentInitializer::changeFunction(DeclContext *parent) {
ASSERT(parent->isLocalContext());
setParent(parent);
}

/// Determine whether the given Swift type is an integral type, i.e.,
Expand Down
5 changes: 4 additions & 1 deletion lib/AST/Parameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,11 @@ ParameterList::create(const ASTContext &C, SourceLoc LParenLoc,
/// Change the DeclContext of any contained parameters to the specified
/// DeclContext.
void ParameterList::setDeclContextOfParamDecls(DeclContext *DC) {
for (auto P : *this)
for (ParamDecl *P : *this) {
P->setDeclContext(DC);
if (auto initContext = P->getCachedDefaultArgumentInitContext())
(*initContext)->changeFunction(DC);
}
}

/// Make a duplicate copy of this parameter list. This allocates copies of
Expand Down
5 changes: 3 additions & 2 deletions lib/AST/TypeCheckRequests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1404,13 +1404,14 @@ void HasCircularRawValueRequest::noteCycleStep(DiagnosticEngine &diags) const {
// DefaultArgumentInitContextRequest computation.
//----------------------------------------------------------------------------//

std::optional<Initializer *>
std::optional<DefaultArgumentInitializer *>
DefaultArgumentInitContextRequest::getCachedResult() const {
auto *param = std::get<0>(getStorage());
return param->getCachedDefaultArgumentInitContext();
}

void DefaultArgumentInitContextRequest::cacheResult(Initializer *init) const {
void DefaultArgumentInitContextRequest::cacheResult(
DefaultArgumentInitializer *init) const {
auto *param = std::get<0>(getStorage());
param->setDefaultArgumentInitContext(init);
}
Expand Down
4 changes: 4 additions & 0 deletions lib/ASTGen/Sources/ASTGen/Bridge.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ extension BridgedNullableGenericParamList: /*@retroactive*/ swiftASTGen.BridgedN
extension BridgedNullableTrailingWhereClause: /*@retroactive*/ swiftASTGen.BridgedNullable {}
extension BridgedNullableParameterList: /*@retroactive*/ swiftASTGen.BridgedNullable {}
extension BridgedNullablePatternBindingInitializer: /*@retroactive*/ swiftASTGen.BridgedNullable {}
extension BridgedNullableDefaultArgumentInitializer: /*@retroactive*/ swiftASTGen.BridgedNullable {}
extension BridgedNullableCustomAttributeInitializer: /*@retroactive*/ swiftASTGen.BridgedNullable {}
extension BridgedNullableArgumentList: /*@retroactive*/ swiftASTGen.BridgedNullable {}
extension BridgedNullableVarDecl: /*@retroactive*/ swiftASTGen.BridgedNullable {}
Expand Down Expand Up @@ -87,6 +88,9 @@ extension BridgedParameterList: BridgedHasNullable {
extension BridgedPatternBindingInitializer: BridgedHasNullable {
typealias Nullable = BridgedNullablePatternBindingInitializer
}
extension BridgedDefaultArgumentInitializer: BridgedHasNullable {
typealias Nullable = BridgedNullableDefaultArgumentInitializer
}
extension BridgedCustomAttributeInitializer: BridgedHasNullable {
typealias Nullable = BridgedNullableCustomAttributeInitializer
}
Expand Down
3 changes: 2 additions & 1 deletion lib/ASTGen/Sources/ASTGen/Exprs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,8 @@ extension ASTGenVisitor {
paramName: ctx.getDollarIdentifier(idx),
paramNameLoc: loc,
type: nil,
defaultValue: nil
defaultValue: nil,
defaultValueInitContext: nil
)
param.setSpecifier(.default)
param.setImplicit()
Expand Down
Loading