How much sanitization can the compiler do for you?

I'm trying out my first macro. It's declared as:

@freestanding(expression)
public macro myMacro(_ value: StaticString) -> UInt32 =
  #externalMacro(module: "MyMacros", type: "MyMacro")

When I started playing with the results, I noticed that some cases I prepared for never ran, because the compiler sanitized the input first.

  • No arguments
  • Multiple arguments
  • Not a string literal
  • Contains string interpolation

Is it safe to permanently remove my code for those contingencies?

1 Like

In general, you should be able to safely assume that the inputs to the macro are valid with respect to the signature, so the compiler will verify that there is a single StaticString argument before it calls your implementation.

You don't have a guarantee that you're getting a string literal, though. This is valid:

let x: StaticString = "blah"
_ = #myMacro(x)

AFAIK there's no way from outside the macro to require that only a string literal be passed to it; it's the same problem as "enforce that an arbitrary function argument is only a string literal". You'll have to do that validation inside your macro.

1 Like

So an explicit StringLiteralExprSyntax check is enough?

StringLiteralExprSyntax check + StaticString argument ought to be enough today.

Given discussion about various shapes of compile-time expressions that have happened on the forum, I can imagine a future world where StaticString could be extended to support interpolations if the interpolations are all compile-time expressions.

You're probably better off just explicitly writing what you actually mean: take a String argument and have the macro validate that it only contains literal segments, instead of mixing different features to sort of mimic what you want.

Actually, the test didn't accept your indirection trick. The compiler gave "The argument is not a string."

Can you post the full example?

If you mean that your macro rejected it, that's right—that's what I was pointing out, that you're not guaranteed to get a "literal" by just using StaticString on its own.

The error text is from my code.

Right. Your original question was whether you could remove the code for the question of "not a string literal" and my answer was "no", because someone can indirect a StaticString through a variable.

I'm assuming that the reason you want a string literal is to inspect it inside the macro implementation, meaning that the indirection would prevent that.

This is weird. The macro template package has both a test file and a driver file. The test file does go through my code, but the driver file sometimes uses the compiler's built-in macro checker.