-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add reflect Symbol.info and ClassInfo #11664
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
Conversation
trait ClassInfoMethods: | ||
extension (self: ClassInfo) | ||
/** The prefix on which parents, decls, and selfType need to be rebased. */ | ||
def prefix: TypeRepr |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is prefix
here a different thing from qualifier
in TypeRef
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a similar qualification. We have used qualifier
in all the cases of the API, I will do the same here to be homogeneous. There is a similar case with NamedType
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nicolasstucki Right, although I wonder if it's not too late to name it prefix
everywhere instead of qualifier
, for consistency with Scala 2 and previous literature
Also fix TypeReprStructure printer for Binder to avoid cycles and remove workaround in TypeLambda. Fixes scala#11657
extension (self: ClassInfo) | ||
def qualifier: TypeRepr = self.prefix | ||
def decls: List[Symbol] = self.decls.toList | ||
def declaredParents: List[TypeRepr] = self.declaredParents |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't expose declaredParents
as it's just a less precise version of parents
: https://github.com/lampepfl/dotty/blob/0dbe9705ec6a319af2365de4e00d3f66154fc133/compiler/src/dotty/tools/dotc/core/Types.scala#L4536
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But then we would have to always go to the tree which is the thing we are trying to avoid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But then we would have to always go to the tree
No, we should expose Type#parents which doesn't involve trees.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
this += "TypeLambda(" ++= argNames += ", " ++= argBounds += ", _)" | ||
this += "TypeLambda(" ++= argNames += ", " ++= argBounds += ", " += resType += ")" | ||
case ClassInfo(prefix, cls, parents, decls, selfInfo) => | ||
this += "ClassInfo(" += prefix += ", cls/*" += cls.fullName += "*/, " ++= parents += ", decls, " += selfInfo += ")" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is cls
added by accident?
this += "ClassInfo(" += prefix += ", cls/*" += cls.fullName += "*/, " ++= parents += ", decls, " += selfInfo += ")" | |
this += "ClassInfo(" += prefix += ", /*" += cls.fullName += "*/, " ++= parents += ", decls, " += selfInfo += ")" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, we want to generate something like ClassInfo(X, cls /*...*/, ..., ...)
. If we remove the cls
it would not parse as valid scala code. The comment is there to hint at what is in that parameter but there is no structure to it.
@@ -3437,6 +3472,9 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching => | |||
trait SymbolMethods { | |||
extension (self: Symbol) | |||
|
|||
/** TypeRepr of the definitions of this symbol */ | |||
def info: TypeRepr | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we expose info
on symbols, logically we need to expose Type.asSeenFrom
as well to rebase the prefix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a document here saying
Warning: you may need to perform
asSeenFrom
in caseSymbol.info
contains parameterized types, such as class type parameter, types depend onthis
, etc.For example, if the owner of the current symbol is a class, using the following code to rebase the type:
symbol.info.asSeenFrom(prefix, symbol.owner)
What about a method like symbol.infoAsSeenFrom(prefix)
?
extension (self: ClassInfo) | ||
def qualifier: TypeRepr = self.prefix | ||
def decls: List[Symbol] = self.decls.toList | ||
def declaredParents: List[TypeRepr] = self.declaredParents |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But then we would have to always go to the tree
No, we should expose Type#parents which doesn't involve trees.
@@ -1695,6 +1695,8 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler | |||
dotc.core.Types.decorateTypeApplications(self).appliedTo(targ) | |||
def appliedTo(targs: List[TypeRepr]): TypeRepr = | |||
dotc.core.Types.decorateTypeApplications(self).appliedTo(targs) | |||
def asSeenFrom(pre: TypeRepr, clazz: Symbol): TypeRepr = | |||
self.asSeenFrom(pre, clazz) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already expose memberInfo
which calls asSeenFrom, in what situation would you need the raw asSeenFrom?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we expose symbol.info
, without asSeenFrom
, the info cannot be safely used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
symbol.info is the info of the symbol itself, I don't see what's unsafe about it, and if you want to see the info from some specific prefix you can do prefix.memberType(symbol)
. Are there situations where you need to use asSeenFrom
directly instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
symbol.info is the info of the symbol itself, I don't see what's unsafe about it, if you want to see the info from some specific prefix you can do prefix.memberType(symbol). Are there situations where you need to use asSeenFrom directly instead?
The concern is that users use symbol.info
without rebasing, resulting in error-prone macros. I see that we already have TypeEpr.memberType
, thus we don't need asSeenFrom
. However, it is good to add the following doc to Symbol.info
:
Warning:
Symbol.info
may contain parameterized types, such as class type parameter, types that depend onthis
, etc. The method callprefix.memberType(symbol)
can be used to get the concrete type of the symbol relative to a prefix.
The point of this was to make the API simpler to use, but by using |
Also fix TypeReprStructure printer for Binder to avoid cycles and remove workaround in TypeLambda.
Fixes #11657