Skip to content

Commit e41cdfb

Browse files
authored
Merge pull request #63341 from hborla/generalize-macro-expansion-expr
[Macros] Generalize `MacroExpansionExpr` and use it for both freestanding and attached macros.
2 parents fe4df58 + e3cd34c commit e41cdfb

18 files changed

+91
-184
lines changed

include/swift/AST/Expr.h

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6051,16 +6051,19 @@ class TypeJoinExpr final : public Expr,
60516051
}
60526052
};
60536053

6054+
/// An invocation of a macro expansion, spelled with `#` for freestanding
6055+
/// macros or `@` for attached macros.
60546056
class MacroExpansionExpr final : public Expr {
60556057
private:
60566058
DeclContext *DC;
6057-
SourceLoc PoundLoc;
6059+
SourceLoc SigilLoc;
60586060
DeclNameRef MacroName;
60596061
DeclNameLoc MacroNameLoc;
60606062
SourceLoc LeftAngleLoc, RightAngleLoc;
60616063
ArrayRef<TypeRepr *> GenericArgs;
60626064
ArgumentList *ArgList;
60636065
Expr *Rewritten;
6066+
MacroRoles Roles;
60646067

60656068
/// The referenced macro.
60666069
ConcreteDeclRef macroRef;
@@ -6069,22 +6072,30 @@ class MacroExpansionExpr final : public Expr {
60696072
enum : unsigned { InvalidDiscriminator = 0xFFFF };
60706073

60716074
explicit MacroExpansionExpr(DeclContext *dc,
6072-
SourceLoc poundLoc, DeclNameRef macroName,
6075+
SourceLoc sigilLoc, DeclNameRef macroName,
60736076
DeclNameLoc macroNameLoc,
60746077
SourceLoc leftAngleLoc,
60756078
ArrayRef<TypeRepr *> genericArgs,
60766079
SourceLoc rightAngleLoc,
60776080
ArgumentList *argList,
6081+
MacroRoles roles,
60786082
bool isImplicit = false,
60796083
Type ty = Type())
60806084
: Expr(ExprKind::MacroExpansion, isImplicit, ty),
6081-
DC(dc), PoundLoc(poundLoc),
6085+
DC(dc), SigilLoc(sigilLoc),
60826086
MacroName(macroName), MacroNameLoc(macroNameLoc),
60836087
LeftAngleLoc(leftAngleLoc), RightAngleLoc(rightAngleLoc),
60846088
GenericArgs(genericArgs),
6085-
ArgList(argList),
6086-
Rewritten(nullptr) {
6089+
Rewritten(nullptr), Roles(roles) {
60876090
Bits.MacroExpansionExpr.Discriminator = InvalidDiscriminator;
6091+
6092+
// Macro expansions always have an argument list. If one is not provided, create
6093+
// an implicit one.
6094+
if (argList) {
6095+
ArgList = argList;
6096+
} else {
6097+
ArgList = ArgumentList::createImplicit(dc->getASTContext(), {});
6098+
}
60886099
}
60896100

60906101
DeclNameRef getMacroName() const { return MacroName; }
@@ -6102,7 +6113,9 @@ class MacroExpansionExpr final : public Expr {
61026113
ArgumentList *getArgs() const { return ArgList; }
61036114
void setArgs(ArgumentList *newArgs) { ArgList = newArgs; }
61046115

6105-
SourceLoc getLoc() const { return PoundLoc; }
6116+
MacroRoles getMacroRoles() const { return Roles; }
6117+
6118+
SourceLoc getLoc() const { return SigilLoc; }
61066119

61076120
ConcreteDeclRef getMacroRef() const { return macroRef; }
61086121
void setMacroRef(ConcreteDeclRef ref) { macroRef = ref; }

include/swift/AST/TypeCheckRequests.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3151,6 +3151,7 @@ class UnresolvedMacroReference {
31513151
return pointer.getOpaqueValue();
31523152
}
31533153

3154+
SourceLoc getSigilLoc() const;
31543155
DeclNameRef getMacroName() const;
31553156
DeclNameLoc getMacroNameLoc() const;
31563157
SourceRange getGenericArgsRange() const;

include/swift/Sema/CSFix.h

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -419,9 +419,6 @@ enum class FixKind : uint8_t {
419419
/// Macro without leading #.
420420
MacroMissingPound,
421421

422-
/// Macro that has parameters but was not provided with any arguments.
423-
MacroMissingArguments,
424-
425422
/// Allow function type actor mismatch e.g. `@MainActor () -> Void`
426423
/// vs.`@OtherActor () -> Void`
427424
AllowGlobalActorMismatch,
@@ -3271,32 +3268,6 @@ class MacroMissingPound final : public ConstraintFix {
32713268
}
32723269
};
32733270

3274-
class MacroMissingArguments final : public ConstraintFix {
3275-
MacroDecl *macro;
3276-
3277-
MacroMissingArguments(ConstraintSystem &cs, MacroDecl *macro,
3278-
ConstraintLocator *locator)
3279-
: ConstraintFix(cs, FixKind::MacroMissingArguments, locator),
3280-
macro(macro) { }
3281-
3282-
public:
3283-
std::string getName() const override { return "macro missing arguments"; }
3284-
3285-
bool diagnose(const Solution &solution, bool asNote = false) const override;
3286-
3287-
bool diagnoseForAmbiguity(CommonFixesArray commonFixes) const override {
3288-
return diagnose(*commonFixes.front().first);
3289-
}
3290-
3291-
static MacroMissingArguments *
3292-
create(ConstraintSystem &cs, MacroDecl *macro,
3293-
ConstraintLocator *locator);
3294-
3295-
static bool classof(ConstraintFix *fix) {
3296-
return fix->getKind() == FixKind::MacroMissingArguments;
3297-
}
3298-
};
3299-
33003271
/// Allow mismatch between function types global actors.
33013272
/// e.g. `@MainActor () -> Void` vs.`@OtherActor () -> Void`
33023273
class AllowGlobalActorMismatch final : public ContextualMismatch {

lib/AST/Expr.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2538,14 +2538,14 @@ TypeJoinExpr *TypeJoinExpr::create(ASTContext &ctx, DeclRefExpr *var,
25382538

25392539
SourceRange MacroExpansionExpr::getSourceRange() const {
25402540
SourceLoc endLoc;
2541-
if (ArgList)
2541+
if (ArgList && !ArgList->isImplicit())
25422542
endLoc = ArgList->getEndLoc();
25432543
else if (RightAngleLoc.isValid())
25442544
endLoc = RightAngleLoc;
25452545
else
25462546
endLoc = MacroNameLoc.getEndLoc();
25472547

2548-
return SourceRange(PoundLoc, endLoc);
2548+
return SourceRange(SigilLoc, endLoc);
25492549
}
25502550

25512551
unsigned MacroExpansionExpr::getDiscriminator() const {

lib/AST/TypeCheckRequests.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,6 +1676,16 @@ DeclNameRef UnresolvedMacroReference::getMacroName() const {
16761676
llvm_unreachable("Unhandled case");
16771677
}
16781678

1679+
SourceLoc UnresolvedMacroReference::getSigilLoc() const {
1680+
if (auto *med = pointer.dyn_cast<MacroExpansionDecl *>())
1681+
return med->getPoundLoc();
1682+
if (auto *mee = pointer.dyn_cast<MacroExpansionExpr *>())
1683+
return mee->getLoc();
1684+
if (auto *attr = pointer.dyn_cast<CustomAttr *>())
1685+
return attr->getRangeWithAt().Start;
1686+
llvm_unreachable("Unhandled case");
1687+
}
1688+
16791689
DeclNameLoc UnresolvedMacroReference::getMacroNameLoc() const {
16801690
if (auto *med = pointer.dyn_cast<MacroExpansionDecl *>())
16811691
return med->getMacroLoc();

lib/Parse/ParseExpr.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3367,7 +3367,8 @@ ParserResult<Expr> Parser::parseExprMacroExpansion(bool isExprBasic) {
33673367
status,
33683368
new (Context) MacroExpansionExpr(
33693369
CurDeclContext, poundLoc, macroNameRef, macroNameLoc, leftAngleLoc,
3370-
Context.AllocateCopy(genericArgs), rightAngleLoc, argList));
3370+
Context.AllocateCopy(genericArgs), rightAngleLoc, argList,
3371+
MacroRole::Expression));
33713372
}
33723373

33733374
/// parseExprCollection - Parse a collection literal expression.

lib/Sema/CSApply.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2985,7 +2985,7 @@ namespace {
29852985
auto expansion = new (ctx) MacroExpansionExpr(
29862986
dc, expr->getStartLoc(), DeclNameRef(macro->getName()),
29872987
DeclNameLoc(expr->getLoc()), SourceLoc(), { }, SourceLoc(),
2988-
nullptr, /*isImplicit=*/true, expandedType);
2988+
nullptr, MacroRole::Expression, /*isImplicit=*/true, expandedType);
29892989
expansion->setMacroRef(macroRef);
29902990
expansion->setRewritten(newExpr);
29912991
cs.cacheExprTypes(expansion);
@@ -5406,7 +5406,8 @@ namespace {
54065406
ConcreteDeclRef macroRef = resolveConcreteDeclRef(macro, locator);
54075407
E->setMacroRef(macroRef);
54085408

5409-
if (!cs.Options.contains(ConstraintSystemFlags::DisableMacroExpansions)) {
5409+
if (E->getMacroRoles().contains(MacroRole::Expression) &&
5410+
!cs.Options.contains(ConstraintSystemFlags::DisableMacroExpansions)) {
54105411
if (auto newExpr = expandMacroExpr(dc, E, macroRef, expandedType)) {
54115412
E->setRewritten(newExpr);
54125413
}

lib/Sema/CSDiagnostics.cpp

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4634,7 +4634,8 @@ ASTNode MissingArgumentsFailure::getAnchor() const {
46344634
}
46354635

46364636
SourceLoc MissingArgumentsFailure::getLoc() const {
4637-
if (auto *argList = getArgumentListFor(getLocator()))
4637+
auto *argList = getArgumentListFor(getLocator());
4638+
if (argList && !argList->isImplicit())
46384639
return argList->getLoc();
46394640
return FailureDiagnostic::getLoc();
46404641
}
@@ -4729,17 +4730,25 @@ bool MissingArgumentsFailure::diagnoseAsError() {
47294730

47304731
// TODO(diagnostics): We should be able to suggest this fix-it
47314732
// unconditionally.
4732-
if (args && args->empty()) {
4733-
SmallString<32> scratch;
4734-
llvm::raw_svector_ostream fixIt(scratch);
4733+
SmallString<32> scratch;
4734+
llvm::raw_svector_ostream fixIt(scratch);
4735+
auto appendMissingArgsToFix = [&]() {
47354736
interleave(
47364737
SynthesizedArgs,
47374738
[&](const SynthesizedArg &arg) {
47384739
forFixIt(fixIt, arg.param);
47394740
},
47404741
[&] { fixIt << ", "; });
4742+
};
47414743

4744+
if (args && args->empty() && !args->isImplicit()) {
4745+
appendMissingArgsToFix();
47424746
diag.fixItInsertAfter(args->getLParenLoc(), fixIt.str());
4747+
} else if (isExpr<MacroExpansionExpr>(getRawAnchor())) {
4748+
fixIt << "(";
4749+
appendMissingArgsToFix();
4750+
fixIt << ")";
4751+
diag.fixItInsertAfter(getRawAnchor().getEndLoc(), fixIt.str());
47434752
}
47444753

47454754
diag.flush();
@@ -8523,35 +8532,6 @@ bool AddMissingMacroPound::diagnoseAsError() {
85238532
return true;
85248533
}
85258534

8526-
bool AddMissingMacroArguments::diagnoseAsError() {
8527-
std::string argumentString;
8528-
{
8529-
llvm::raw_string_ostream out(argumentString);
8530-
out << "(";
8531-
llvm::interleave(
8532-
macro->parameterList->begin(), macro->parameterList->end(),
8533-
[&](ParamDecl *param) {
8534-
if (!param->getArgumentName().empty()) {
8535-
out << param->getArgumentName() << ": ";
8536-
}
8537-
8538-
out << "<#" << param->getInterfaceType().getString() << "#" << ">";
8539-
},
8540-
[&] {
8541-
out << ", ";
8542-
});
8543-
out << ")";
8544-
}
8545-
8546-
auto insertLoc = getRawAnchor().getEndLoc();
8547-
emitDiagnostic(diag::macro_expansion_missing_arguments, macro->getName())
8548-
.fixItInsertAfter(insertLoc, argumentString);
8549-
macro->diagnose(
8550-
diag::kind_declname_declared_here, macro->getDescriptiveKind(),
8551-
macro->getName());
8552-
return true;
8553-
}
8554-
85558535
bool GlobalActorFunctionMismatchFailure::diagnoseTupleElement() {
85568536
auto *locator = getLocator();
85578537
auto path = locator->getPath();

lib/Sema/CSDiagnostics.h

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2877,29 +2877,6 @@ class AddMissingMacroPound final : public FailureDiagnostic {
28772877
bool diagnoseAsError() override;
28782878
};
28792879

2880-
/// Diagnose situations where we end up type checking a reference to a macro
2881-
/// that has parameters, but was not provided any arguments.
2882-
///
2883-
/// \code
2884-
/// func print(_ value: Any)
2885-
/// @expression macro print<Value...>(_ value: Value...)
2886-
///
2887-
/// func test(e: E) {
2888-
/// #print
2889-
/// }
2890-
/// \endcode
2891-
class AddMissingMacroArguments final : public FailureDiagnostic {
2892-
MacroDecl *macro;
2893-
2894-
public:
2895-
AddMissingMacroArguments(const Solution &solution, MacroDecl *macro,
2896-
ConstraintLocator *locator)
2897-
: FailureDiagnostic(solution, locator),
2898-
macro(macro) { }
2899-
2900-
bool diagnoseAsError() override;
2901-
};
2902-
29032880
/// Diagnose function types global actor mismatches
29042881
/// e.g. `@MainActor () -> Void` vs.`@OtherActor () -> Void`
29052882
class GlobalActorFunctionMismatchFailure final : public ContextualFailure {

lib/Sema/CSFix.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2616,18 +2616,6 @@ MacroMissingPound::create(ConstraintSystem &cs, MacroDecl *macro,
26162616
return new (cs.getAllocator()) MacroMissingPound(cs, macro, locator);
26172617
}
26182618

2619-
bool MacroMissingArguments::diagnose(const Solution &solution,
2620-
bool asNote) const {
2621-
AddMissingMacroArguments failure(solution, macro, getLocator());
2622-
return failure.diagnose(asNote);
2623-
}
2624-
2625-
MacroMissingArguments *
2626-
MacroMissingArguments::create(ConstraintSystem &cs, MacroDecl *macro,
2627-
ConstraintLocator *locator) {
2628-
return new (cs.getAllocator()) MacroMissingArguments(cs, macro, locator);
2629-
}
2630-
26312619
bool AllowGlobalActorMismatch::diagnose(const Solution &solution,
26322620
bool asNote) const {
26332621
GlobalActorFunctionMismatchFailure failure(solution, getFromType(),

lib/Sema/CSGen.cpp

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,7 +1211,8 @@ namespace {
12111211

12121212
auto macroIdent = ctx.getIdentifier(kind);
12131213
auto macros = lookupMacros(
1214-
macroIdent, expr->getLoc(), FunctionRefKind::Unapplied);
1214+
macroIdent, expr->getLoc(), FunctionRefKind::Unapplied,
1215+
MacroRole::Expression);
12151216
if (!macros.empty()) {
12161217
// Introduce an overload set for the macro reference.
12171218
auto locator = CS.getConstraintLocator(expr);
@@ -3760,10 +3761,11 @@ namespace {
37603761
/// Lookup all macros with the given macro name.
37613762
SmallVector<OverloadChoice, 1>
37623763
lookupMacros(Identifier macroName, SourceLoc loc,
3763-
FunctionRefKind functionRefKind) {
3764+
FunctionRefKind functionRefKind,
3765+
MacroRoles roles) {
37643766
SmallVector<OverloadChoice, 1> choices;
37653767
auto results = TypeChecker::lookupMacros(
3766-
CurDC, DeclNameRef(macroName), loc, MacroRole::Expression);
3768+
CurDC, DeclNameRef(macroName), loc, roles);
37673769
for (const auto &result : results) {
37683770
OverloadChoice choice = OverloadChoice(Type(), result, functionRefKind);
37693771
choices.push_back(choice);
@@ -3782,19 +3784,14 @@ namespace {
37823784
auto &ctx = CS.getASTContext();
37833785
auto locator = CS.getConstraintLocator(expr);
37843786

3785-
// For calls, set up the argument list.
3786-
bool isCall = expr->getArgs() != nullptr;
3787-
if (isCall) {
3788-
CS.associateArgumentList(locator, expr->getArgs());
3789-
}
3787+
CS.associateArgumentList(locator, expr->getArgs());
37903788

37913789
// Look up the macros with this name.
37923790
auto macroIdent = expr->getMacroName().getBaseIdentifier();
3793-
FunctionRefKind functionRefKind = isCall ? FunctionRefKind::SingleApply
3794-
: FunctionRefKind::Unapplied;
3791+
FunctionRefKind functionRefKind = FunctionRefKind::SingleApply;
37953792
auto macros = lookupMacros(
37963793
macroIdent, expr->getMacroNameLoc().getBaseNameLoc(),
3797-
functionRefKind);
3794+
functionRefKind, expr->getMacroRoles());
37983795
if (macros.empty()) {
37993796
ctx.Diags.diagnose(expr->getMacroNameLoc(), diag::macro_undefined,
38003797
macroIdent)
@@ -3814,11 +3811,7 @@ namespace {
38143811
return Type();
38153812
}
38163813

3817-
// For non-calls, the type variable is the result.
3818-
if (!isCall)
3819-
return macroRefType;
3820-
3821-
// For calls, form the applicable-function constraint. The result type
3814+
// Form the applicable-function constraint. The result type
38223815
// is the result of that call.
38233816
SmallVector<AnyFunctionType::Param, 8> params;
38243817
getMatchingParams(expr->getArgs(), params);

lib/Sema/CSSimplify.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13944,7 +13944,6 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
1394413944
case FixKind::NotCompileTimeConst:
1394513945
case FixKind::RenameConflictingPatternVariables:
1394613946
case FixKind::MacroMissingPound:
13947-
case FixKind::MacroMissingArguments:
1394813947
case FixKind::AllowGlobalActorMismatch: {
1394913948
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
1395013949
}

0 commit comments

Comments
 (0)