Skip to content

Restore some form of Reflection.Type.apply(clazz: Class[_]) #9850

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
gzoller opened this issue Sep 22, 2020 · 11 comments · Fixed by #9851
Closed

Restore some form of Reflection.Type.apply(clazz: Class[_]) #9850

gzoller opened this issue Sep 22, 2020 · 11 comments · Fixed by #9851
Milestone

Comments

@gzoller
Copy link
Contributor

gzoller commented Sep 22, 2020

This method was removed roughly 7 days ago with a commit.

I used this to create a Type as a bridge between Tasty Inspection and Reflection. In my Inspection code I called Type.apply(clazz) then used the Type in the same code I share with Reflection.

I see the commit provided Type.ofErasedClass(clazz: Class[_]) in the CompilerInterface but didn't expose it in Reflection.

Please expose ofErasedClass() in Reflection.

This change did break my application code with no clear workaround.

@sjrd
Copy link
Member

sjrd commented Sep 23, 2020

Are you aware that the method that existed before is unsound, as it only works for classes that do not have any type parameters? If yes, why was that not an issue in your application?

@gzoller
Copy link
Contributor Author

gzoller commented Sep 23, 2020

I was aware. My use case needs to marshal a Type from the class. My library creates high level abstractions of the low-level reflected type information, which involves identifying and resolving the type parameters. Specifically, in my nomenclature, RType.inTermsOf[SomeTrait[Int]]( aClass ), where aClass is a parameterized class extending SomeTrait. I get the type information via macros, reflecting on SomeTrait, then “sew” this knowledge into the class, which as you said, is a Type missing its type params. Actually, that’s not quite true. It actually works fine...the problem being the parameter types are erased, but... it does retain the type symbols where they’re supposed to be, which is useful.

Short answer: you’re right, this call can’t successfully marshal a complete parameterized Type from a class by itself, but it can be used with an ancestor (parameterized) reference type to build the complete picture.

If there is some other way to construct a Type from a class, I’m open to that, and understand that type parameters are my problem. Aside from that shortcoming, the Type is usful to obtain all the other information we need to learn from the class.

@sjrd
Copy link
Member

sjrd commented Sep 23, 2020

Short answer: you’re right, this call can’t successfully marshal a complete parameterized Type from a class by itself, but it can be used with an ancestor (parameterized) reference type to build the complete picture.

That is still not possible in cases like

trait SomeTrait[A]

class AClass[A, B] extends SomeTrait[A]

The only thing you're ever able to recover is A, but not B.

@nicolasstucki Is a Type supposed to be able to represent a type constructor without its type parameters?

@nicolasstucki
Copy link
Contributor

Yes, Type can represent type constructors at it has a <: AnyKind bound. We can write Type.of[AClass].

@sjrd
Copy link
Member

sjrd commented Sep 23, 2020

Then perhaps we could reintroduce this feature but with a more explicit name like Type.typeConstructorOf(aClass). So that it doesn't give the wrong idea to people that it's a *-kinded type.

WDYT? Would that make sense?

@nicolasstucki
Copy link
Contributor

It looks ok to me. I will open a PR for it.

@gzoller
Copy link
Contributor Author

gzoller commented Sep 23, 2020

sjrd: Yes if your reference trait doesn’t define all if the class’ parameters, as in your example, then those params left undefined will remain in the class as a type symbol in my system with an actual type of Any—they won’t resolve. This actually makes sense—the caller didn’t specify, and if the reference trait is “narrower” than the class, perhaps that’s all the caller needed, but that’s their responsibility.

@gzoller
Copy link
Contributor Author

gzoller commented Sep 23, 2020

And I’m great with a more descriptive name. There’s a pr open for this, so if you guys agree on a new name, I can change it in Reflection and with your blessing merge the code. Let me know if you also want to mirror the new name in CompilerInterface or leave the one that’s already there.

@nicolasstucki
Copy link
Contributor

You can change the definition in Reflection only. I'm working on a PR that will remove those indirections in the CompilerInterface and I will take care of cleaning the internals there.

@gzoller
Copy link
Contributor Author

gzoller commented Sep 23, 2020

ok, shall I use the existing name, ofErasedClass? That’s what’s in the pr now.

@sjrd
Copy link
Member

sjrd commented Sep 23, 2020

ofErasedClass still suggests to me that it will somehow summon a fully-defined Type out of an erased Class. That's why I suggested typeConstructorOf, which makes it clear that the result is only a type constructor, not a *-kinded type.

@Kordyjan Kordyjan added this to the 3.0.0 milestone Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants