Skip to content

Commit 1aa9075

Browse files
committed
[Macros] Use the macro recorded in the constraint system for expansion.
Rather than lookup up the macro by name again during constraint application, use the overload choice for the macro as recorded in the constraint system to apply the correct macro.
1 parent 5ab6b72 commit 1aa9075

File tree

6 files changed

+155
-112
lines changed

6 files changed

+155
-112
lines changed

include/swift/Sema/ConstraintSystem.h

-8
Original file line numberDiff line numberDiff line change
@@ -4906,14 +4906,6 @@ class ConstraintSystem {
49064906
ConstraintLocator *locator,
49074907
OpenedTypeMap *replacements = nullptr);
49084908

4909-
#if SWIFT_SWIFT_PARSER
4910-
/// Retrieve the opened type of a macro with the given name.
4911-
///
4912-
/// \returns The opened type of the macro with this name, or the null \c Type
4913-
/// if no such macro exists.
4914-
Type getTypeOfMacroReference(Identifier macroName, Expr *anchor);
4915-
#endif
4916-
49174909
/// Retrieve a list of generic parameter types solver has "opened" (replaced
49184910
/// with a type variable) at the given location.
49194911
ArrayRef<OpenedType> getOpenedTypes(ConstraintLocator *locator) const {

lib/Sema/CSApply.cpp

+18-7
Original file line numberDiff line numberDiff line change
@@ -2975,14 +2975,20 @@ namespace {
29752975
#if SWIFT_SWIFT_PARSER
29762976
auto &ctx = cs.getASTContext();
29772977
if (ctx.LangOpts.hasFeature(Feature::BuiltinMacros)) {
2978-
auto kind = MagicIdentifierLiteralExpr::getKindString(expr->getKind())
2979-
.drop_front();
29802978
auto expandedType = solution.simplifyType(solution.getType(expr));
29812979
cs.setType(expr, expandedType);
29822980

2983-
if (auto newExpr = expandMacroExpr(dc, expr, kind, expandedType)) {
2981+
auto locator = cs.getConstraintLocator(expr);
2982+
auto overload = solution.getOverloadChoice(locator);
2983+
2984+
auto macro = cast<MacroDecl>(overload.choice.getDecl());
2985+
// FIXME: use the macro for expansion!
2986+
// FIXME: form a proper ConcreteDeclRef for the macro expansion!
2987+
2988+
ConcreteDeclRef macroRef = resolveConcreteDeclRef(macro, locator);
2989+
if (auto newExpr = expandMacroExpr(dc, expr, macroRef, expandedType)) {
29842990
auto expansion = new (ctx) MacroExpansionExpr(
2985-
expr->getStartLoc(), DeclNameRef(ctx.getIdentifier(kind)),
2991+
expr->getStartLoc(), DeclNameRef(macro->getName()),
29862992
DeclNameLoc(expr->getLoc()), nullptr, /*isImplicit=*/true,
29872993
expandedType);
29882994
expansion->setRewritten(newExpr);
@@ -5392,11 +5398,16 @@ namespace {
53925398
#if SWIFT_SWIFT_PARSER
53935399
auto &ctx = cs.getASTContext();
53945400
if (ctx.LangOpts.hasFeature(Feature::Macros)) {
5395-
auto macroIdent = E->getMacroName().getBaseIdentifier();
53965401
auto expandedType = solution.simplifyType(solution.getType(E));
53975402
cs.setType(E, expandedType);
5398-
if (auto newExpr = expandMacroExpr(
5399-
dc, E, macroIdent.str(), expandedType)) {
5403+
5404+
auto locator = cs.getConstraintLocator(E);
5405+
auto overload = solution.getOverloadChoice(locator);
5406+
5407+
auto macro = cast<MacroDecl>(overload.choice.getDecl());
5408+
ConcreteDeclRef macroRef = resolveConcreteDeclRef(macro, locator);
5409+
5410+
if (auto newExpr = expandMacroExpr(dc, E, macroRef, expandedType)) {
54005411
E->setRewritten(newExpr);
54015412
cs.cacheExprTypes(E);
54025413
return E;

lib/Sema/CSGen.cpp

+71-34
Original file line numberDiff line numberDiff line change
@@ -1200,17 +1200,23 @@ namespace {
12001200
if (!protocol)
12011201
return Type();
12021202

1203-
auto openedType = CS.getTypeOfMacroReference(
1204-
ctx.getIdentifier(kind), expr);
1205-
if (!openedType)
1206-
return Type();
1207-
1208-
CS.addConstraint(ConstraintKind::LiteralConformsTo, openedType,
1209-
protocol->getDeclaredInterfaceType(),
1210-
CS.getConstraintLocator(expr));
1211-
1212-
return openedType;
1203+
auto macroIdent = ctx.getIdentifier(kind);
1204+
auto macros = lookupMacros(macroIdent, FunctionRefKind::Unapplied);
1205+
if (!macros.empty()) {
1206+
// Introduce an overload set for the macro reference.
1207+
auto locator = CS.getConstraintLocator(expr);
1208+
auto macroRefType = Type(CS.createTypeVariable(locator, 0));
1209+
CS.addOverloadSet(macroRefType, macros, CurDC, locator);
1210+
1211+
// FIXME: Can this be encoded in the macro definition somehow?
1212+
CS.addConstraint(ConstraintKind::LiteralConformsTo, macroRefType,
1213+
protocol->getDeclaredInterfaceType(),
1214+
CS.getConstraintLocator(expr));
1215+
1216+
return macroRefType;
1217+
}
12131218
}
1219+
12141220
// Fall through to use old implementation.
12151221
#endif
12161222

@@ -3629,41 +3635,72 @@ namespace {
36293635
return resultTy;
36303636
}
36313637

3638+
/// Lookup all macros with the given macro name.
3639+
SmallVector<OverloadChoice, 1>
3640+
lookupMacros(Identifier macroName, FunctionRefKind functionRefKind) {
3641+
auto req = MacroLookupRequest{macroName, CS.DC->getParentModule()};
3642+
auto macros = evaluateOrDefault(
3643+
CS.getASTContext().evaluator, req, { });
3644+
if (macros.empty())
3645+
return { };
3646+
3647+
// FIXME: At some point, we need to check for function-like macros without
3648+
// arguments and vice-versa.
3649+
3650+
3651+
SmallVector<OverloadChoice, 1> choices;
3652+
for (auto macro : macros) {
3653+
OverloadChoice choice = OverloadChoice(Type(), macro, functionRefKind);
3654+
choices.push_back(choice);
3655+
}
3656+
return choices;
3657+
}
3658+
36323659
Type visitMacroExpansionExpr(MacroExpansionExpr *expr) {
36333660
#if SWIFT_SWIFT_PARSER
36343661
auto &ctx = CS.getASTContext();
36353662
if (ctx.LangOpts.hasFeature(Feature::Macros)) {
3663+
// Look up the macros with this name.
36363664
auto macroIdent = expr->getMacroName().getBaseIdentifier();
3637-
auto refType = CS.getTypeOfMacroReference(macroIdent, expr);
3638-
if (!refType) {
3665+
bool isCall = expr->getArgs() != nullptr;
3666+
FunctionRefKind functionRefKind = isCall ? FunctionRefKind::SingleApply
3667+
: FunctionRefKind::Unapplied;
3668+
auto macros = lookupMacros(macroIdent, functionRefKind);
3669+
if (macros.empty()) {
36393670
ctx.Diags.diagnose(expr->getMacroNameLoc(), diag::macro_undefined,
36403671
macroIdent)
36413672
.highlight(expr->getMacroNameLoc().getSourceRange());
36423673
return Type();
36433674
}
3644-
if (expr->getArgs()) {
3645-
CS.associateArgumentList(CS.getConstraintLocator(expr), expr->getArgs());
3646-
// FIXME: Do we have object-like vs. function-like macros?
3647-
if (auto fnType = dyn_cast<FunctionType>(refType.getPointer())) {
3648-
SmallVector<AnyFunctionType::Param, 8> params;
3649-
getMatchingParams(expr->getArgs(), params);
3650-
3651-
Type resultType = CS.createTypeVariable(
3652-
CS.getConstraintLocator(expr, ConstraintLocator::FunctionResult),
3653-
TVO_CanBindToNoEscape);
3654-
3655-
CS.addConstraint(
3656-
ConstraintKind::ApplicableFunction,
3657-
FunctionType::get(params, resultType),
3658-
fnType,
3659-
CS.getConstraintLocator(
3660-
expr, ConstraintLocator::ApplyFunction));
3661-
3662-
return resultType;
3663-
}
3664-
}
36653675

3666-
return refType;
3676+
// Introduce an overload set for the macro reference.
3677+
auto locator = CS.getConstraintLocator(expr);
3678+
auto macroRefType = Type(CS.createTypeVariable(locator, 0));
3679+
CS.addOverloadSet(macroRefType, macros, CurDC, locator);
3680+
3681+
// For non-calls, the type variable is the result.
3682+
if (!isCall)
3683+
return macroRefType;
3684+
3685+
// For calls, set up the argument list and form the applicable-function
3686+
// constraint. The result type is the result of that call.
3687+
CS.associateArgumentList(locator, expr->getArgs());
3688+
3689+
SmallVector<AnyFunctionType::Param, 8> params;
3690+
getMatchingParams(expr->getArgs(), params);
3691+
3692+
Type resultType = CS.createTypeVariable(
3693+
CS.getConstraintLocator(expr, ConstraintLocator::FunctionResult),
3694+
TVO_CanBindToNoEscape);
3695+
3696+
CS.addConstraint(
3697+
ConstraintKind::ApplicableFunction,
3698+
FunctionType::get(params, resultType),
3699+
macroRefType,
3700+
CS.getConstraintLocator(
3701+
expr, ConstraintLocator::ApplyFunction));
3702+
3703+
return resultType;
36673704
}
36683705
#endif
36693706
return Type();

lib/Sema/ConstraintSystem.cpp

+23-20
Original file line numberDiff line numberDiff line change
@@ -1606,6 +1606,29 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value,
16061606
return { type, type, type, type };
16071607
}
16081608

1609+
// Unqualified reference to a macro.
1610+
if (auto macro = dyn_cast<MacroDecl>(value)) {
1611+
Type macroType = macro->getInterfaceType();
1612+
1613+
// Remove argument labels when we have a function-like macro.
1614+
if (isa<AnyFunctionType>(macroType.getPointer()))
1615+
macroType = macroType->removeArgumentLabels(1);
1616+
1617+
// Open any the generic types.
1618+
OpenedTypeMap replacements;
1619+
openGeneric(macro->getParentModule(), macro->getGenericSignature(),
1620+
locator, replacements);
1621+
1622+
// If we opened up any type variables, record the replacements.
1623+
recordOpenedTypes(locator, replacements);
1624+
1625+
Type openedType = openType(macroType, replacements);
1626+
1627+
// FIXME: Should we use replaceParamErrorTypeByPlaceholder() here?
1628+
1629+
return { openedType, openedType, openedType, openedType };
1630+
}
1631+
16091632
// Only remaining case: unqualified reference to a property.
16101633
auto *varDecl = cast<VarDecl>(value);
16111634

@@ -2471,26 +2494,6 @@ ConstraintSystem::getTypeOfMemberReference(
24712494
return { origOpenedType, openedType, origType, type };
24722495
}
24732496

2474-
#if SWIFT_SWIFT_PARSER
2475-
Type ConstraintSystem::getTypeOfMacroReference(Identifier macroName,
2476-
Expr *anchor) {
2477-
auto req = MacroLookupRequest{macroName, DC->getParentModule()};
2478-
auto macros = evaluateOrDefault(getASTContext().evaluator, req, { });
2479-
if (macros.empty())
2480-
return Type();
2481-
2482-
// FIXME: Handle macro overloading.
2483-
auto macro = macros.front();
2484-
2485-
// Open any the generic types.
2486-
OpenedTypeMap replacements;
2487-
openGeneric(macro->getParentModule(), macro->getGenericSignature(),
2488-
getConstraintLocator(anchor), replacements);
2489-
2490-
return openType(macro->getInterfaceType(), replacements);
2491-
}
2492-
#endif
2493-
24942497
Type ConstraintSystem::getEffectiveOverloadType(ConstraintLocator *locator,
24952498
const OverloadChoice &overload,
24962499
bool allowMembers,

lib/Sema/TypeCheckMacros.cpp

+41-41
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ ArrayRef<MacroDecl *> MacroLookupRequest::evaluate(
331331

332332
#if SWIFT_SWIFT_PARSER
333333
Expr *swift::expandMacroExpr(
334-
DeclContext *dc, Expr *expr, StringRef macroName, Type expandedType
334+
DeclContext *dc, Expr *expr, ConcreteDeclRef macroRef, Type expandedType
335335
) {
336336
ASTContext &ctx = dc->getASTContext();
337337
SourceManager &sourceMgr = ctx.SourceMgr;
@@ -348,53 +348,53 @@ Expr *swift::expandMacroExpr(
348348
// Evaluate the macro.
349349
NullTerminatedStringRef evaluatedSource;
350350

351-
// FIXME: The caller should tell us what macro is being expanded, so we
352-
// don't do this lookup again.
353-
354-
// Built-in macros go through `MacroSystem` in Swift Syntax linked to this
355-
// compiler.
356-
if (auto *macro = swift_ASTGen_lookupMacro(macroName.str().c_str())) {
357-
auto astGenSourceFile = sourceFile->exportedSourceFile;
358-
if (!astGenSourceFile)
359-
return nullptr;
360-
361-
const char *evaluatedSourceAddress;
362-
ptrdiff_t evaluatedSourceLength;
363-
swift_ASTGen_evaluateMacro(
364-
astGenSourceFile, expr->getStartLoc().getOpaquePointerValue(),
365-
&evaluatedSourceAddress, &evaluatedSourceLength);
366-
if (!evaluatedSourceAddress)
367-
return nullptr;
368-
evaluatedSource = NullTerminatedStringRef(evaluatedSourceAddress,
369-
(size_t)evaluatedSourceLength);
370-
swift_ASTGen_destroyMacro(macro);
371-
}
372-
// Other macros go through a compiler plugin.
373-
else {
374-
auto mee = cast<MacroExpansionExpr>(expr);
375-
auto *plugin = ctx.getLoadedPlugin(macroName);
376-
assert(plugin && "Should have been checked during earlier type checking");
377-
auto bufferID = sourceFile->getBufferID();
378-
auto sourceFileText = sourceMgr.getEntireTextForBuffer(*bufferID);
379-
auto evaluated = plugin->invokeRewrite(
380-
/*targetModuleName*/ dc->getParentModule()->getName().str(),
381-
/*filePath*/ sourceFile->getFilename(),
382-
/*sourceFileText*/ sourceFileText,
383-
/*range*/ Lexer::getCharSourceRangeFromSourceRange(
384-
sourceMgr, mee->getSourceRange()),
385-
ctx);
386-
if (evaluated)
387-
evaluatedSource = *evaluated;
388-
else
389-
return nullptr;
351+
MacroDecl *macro = cast<MacroDecl>(macroRef.getDecl());
352+
353+
switch (macro->implementationKind) {
354+
case MacroDecl::ImplementationKind::Builtin: {
355+
// Builtin macros are handled via ASTGen.
356+
auto astGenSourceFile = sourceFile->exportedSourceFile;
357+
if (!astGenSourceFile)
358+
return nullptr;
359+
360+
// FIXME: Tell ASTGen which macro to use.
361+
const char *evaluatedSourceAddress;
362+
ptrdiff_t evaluatedSourceLength;
363+
swift_ASTGen_evaluateMacro(
364+
astGenSourceFile, expr->getStartLoc().getOpaquePointerValue(),
365+
&evaluatedSourceAddress, &evaluatedSourceLength);
366+
if (!evaluatedSourceAddress)
367+
return nullptr;
368+
evaluatedSource = NullTerminatedStringRef(evaluatedSourceAddress,
369+
(size_t)evaluatedSourceLength);
370+
break;
371+
}
372+
373+
case MacroDecl::ImplementationKind::Plugin: {
374+
auto *plugin = (CompilerPlugin *)macro->opaqueHandle;
375+
auto bufferID = sourceFile->getBufferID();
376+
auto sourceFileText = sourceMgr.getEntireTextForBuffer(*bufferID);
377+
auto evaluated = plugin->invokeRewrite(
378+
/*targetModuleName*/ dc->getParentModule()->getName().str(),
379+
/*filePath*/ sourceFile->getFilename(),
380+
/*sourceFileText*/ sourceFileText,
381+
/*range*/ Lexer::getCharSourceRangeFromSourceRange(
382+
sourceMgr, expr->getSourceRange()),
383+
ctx);
384+
if (evaluated)
385+
evaluatedSource = *evaluated;
386+
else
387+
return nullptr;
388+
break;
389+
}
390390
}
391391

392392
// Figure out a reasonable name for the macro expansion buffer.
393393
std::string bufferName;
394394
{
395395
llvm::raw_string_ostream out(bufferName);
396396

397-
out << "Macro expansion of #" << macroName;
397+
out << "Macro expansion of #" << macro->getName();
398398
if (auto bufferID = sourceFile->getBufferID()) {
399399
unsigned startLine, startColumn;
400400
std::tie(startLine, startColumn) =

lib/Sema/TypeCheckMacros.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
#ifndef SWIFT_SEMA_TYPECHECKMACROS_H
1717
#define SWIFT_SEMA_TYPECHECKMACROS_H
1818

19+
#include "swift/AST/ConcreteDeclRef.h"
1920
#include "swift/AST/Type.h"
20-
#include "llvm/ADT/StringRef.h"
2121

2222
namespace swift {
2323

@@ -32,7 +32,7 @@ class TypeRepr;
3232
/// \returns the type-checked replacement expression, or NULL if the
3333
// macro could not be expanded.
3434
Expr *expandMacroExpr(
35-
DeclContext *dc, Expr *expr, StringRef macroName, Type expandedType);
35+
DeclContext *dc, Expr *expr, ConcreteDeclRef macroRef, Type expandedType);
3636

3737
#endif // SWIFT_SWIFT_PARSER
3838

0 commit comments

Comments
 (0)