If you are using STC, then you can access INFERRED_TYPE node meta data for each 
expression.  If not, you need to engage an inferencing engine; 
Expression.getType will work only in the most trivial scenarios.

In order to blend several types into a common supertype, you can use 
WideningCategories.lowestUpperBound.

________________________________
From: MG <[email protected]>
Sent: Wednesday, September 23, 2026 3:45 PM
To: [email protected] <[email protected]>
Subject: Re: @Macro NULL_TO: Avoid/fix Object return type for generic arguments 
under static compilation ?

Ok, I had a bit of time to play around with this some more, and found that it 
works in principle if I cast the NULL_TO macro result to the "type of the input 
expressions". To find the type to cast to I currently do a find over the 
Expression[]


  1.  Ok, I had a bit of time to play around with this some more, and found 
that it works in principle if I cast the NULL_TO macro result to the "type of 
the input expressions".
  2.  To find the type to cast to I currently do a find over the Expression[] 
until I get the Expression#type is != Object-class-node.
  3.  That works inside a test, where I do e.g.:
final BigDecimal bd = NULL_TO(null, null, new BigDecimal(123.456), 
neverCalled())
  4.  ...but unfortunately it does not in the real world, where the NULL_TO 
parameters are often method parameters of the surrounding method - and their 
Expression#type alas seems always to be Object (?)
  5.  Question: How do I get the actual type of method parameters as given in 
the source code (hope they have not been erased at this point, since then I 
would be back to square one...) ?
     *   e.g. (nonsensical, just to show the problem):
void foo(BigDecimal x0, BigDecimal x1) {
    final BigDecimal x = NULL_TO(x0,  x1)  // still fails with "cannot assign 
Object to BigDecimal", since the Expression#type of the x0 and x1 Expression|s 
is a class node of type java.lang.Object...
}
  6.  Bonus question: What one evidently would want is not the type of one of 
the Expression|s passed to NULL_TO, but instead the common supertype of all the 
Expression|s - is there any accessible existing functionality to get that ?-)

Cheers,
mg


Am 22.09.2026 um 21:01 schrieb MG:
Hi guys,

first, congrats on Groovy 6.0.0 G-)

We are still on Groovy 4 (kind of dreading what IntelliJ Intellisense will do 
with a newer Groovy version, given how much code it incorrectly marks as 
"erronous" now), and I finally found the time to do a quick spike to create an 
early-out null-mapping macro, which tests only for !== null (no Groovy truth, 
because in 99% of cases that is not what we want) and takes an arbitrary number 
of arguments:

Examples:
final x = NULL_TO(x0(),x1(),x2(),x3(),x4()) // same as ternary/Elvis operator, 
x1(),etc is only evaluated, if x0() evaluates to null, etc
final sqe = NULL_TO(sqlExecutorIn, Global.sqe, createSqlExecutor()) // again, 
createSqlExecutor() is only called iff sqlExecutorIn and Global.sqe are both 
null

Macro stub:
static <T> T NULL_TO(T... args) { ... }

This works fine, the only problem is, that under static compilation the 
resulting return type of NULL_TO always seems to be Object (instead of generic 
type T), so I have to use an explicit type cast in these cases, which is 
decidedly un-Groovy.

Examples:

// If x0(), etc all have return type BigDecimal, fails later on when trying to 
use BigDecimal functionality on x under @CompileStatic without the cast
final x = (BigDecimal) NULL_TO(x0(),x1(),x2(),x3(),x4())

// Fails with "Object cannot be assigned to SqlExecutor" under @CompileStatic 
otherwise
final SqlExecutor sqe = (SqlExecutor) NULL_TO(sqlExecutorIn, Global.sqe, 
createSqlExecutor())

Comparing this to the existing named value macros, it seems return types only 
work if they are given explicitly, but not when they are generics... (?)
Is there a way to fix/improve this and avoid the cast (or equivalent "as ...") 
? Was this improved in newer Grooyv versions (I searched the Groovy Jira, but 
found nothing in the very small number of tickets that has "macro" in their 
summary) ?

Thanks, cheers,
mg

Reply via email to