Access alias name from within macro context

Is the a way to access the name of a type alias itself, rather than the type that this points to?

alias Foo = {a: Int32, b: String}
#     ^
#     |
#     this, instead of “NamedTuple(a: Int32, b: String)”

The use case that I’ve run into is providing friendly compile time errors with appropriate context.

An example scenario would be:

alias ExampleAlias = Int32

def foo(a : T.class) forall T
  {{ raise “message that references #{T.stringify}” }}
end

foo ExampleAlias
# Currently:
#   message that references “Int32”
#
# Ideal:
#   message that references “ExampleAlias”

This looks to potentially be blocked due to https://github.com/crystal-lang/crystal/pull/4995. Definitely makes sense to auto-resolve for most use cases as the types are equivalent, but that small amount of information is still useful for a human who’s debugging or exploring.

1 Like

AFAIK I can’t think of a way to do this since aliases don’t really exist since they get replaced with their definitions.

I.e. Int32 gets passed to your def, not the alias.

EDIT: Of course if the content is static you could juse hardcode the alias’ name in the error message.

That’s right, aliases get always automatically replaced by their type.

My advice: use record instead of alias h NamedTuple.

I will keep. saying this forever: never use NamedTuple. They exist to represent named arguments, nothing else. You’ll be happier, stronger, and have better relationship with the people that surround you if you stop using them.

4 Likes

Yet NamedTuples:

  • Can eventually allow a nicer subtyping than records
    • {a : Int32, b : String} < {a : Int32}
    • {a : S, b : String} < {a : T, b : String} if S < T
  • They are readonly after creation.

Those two guarantees allows nice patterns for code reuse and reduce interface.
And those guarantees will never land in record unless more features to the language are added.

Sorry, I can’t stop loving named tuples :see_no_evil:

4 Likes

They are readonly after creation

So are records. And records have a name, while aliasing a named tuple doesn’t.

Sorry, I can’t stop hating named tuples :see_no_evil: :stuck_out_tongue:

2 Likes

Haha. Sorry I said the NameT** word :slight_smile:

To seperate this discussion from a NamedTuple flame war*, there are use cases primitive / atomic type alias that you may not want to box where this still applies.

alias Id = Int32

If this is used as a type restriction, the compiler provides suggestions that reference the alias by name:

Error: no overload matches 'example' with type String

Overloads are:
 - example(id : Id)

If you try to reference the same type within a either the macro or runtime context though, that information is not accessible. Not so much of an issue when dealing with concrete types, but once you mix in generics the issue arises.

This is a minor thing with little functional impact, original question of “is this possible” answered - thank you for that.

* where @bcardiff is correct - NamedTuples are life