| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
It’s almost 1am, so I’m only scratching the surface, mechanistically
applying the renames that I’ve written down in my notebook:
* typeSignature => info
* declarations => decls
* nme/tpnme => termNames/typeNames
* paramss => paramLists
* allOverriddenSymbols => overrides
Some explanation is in order so that I don’t get crucified :)
1) No information loss happens when abbreviating `typeSignature` and `declarations`.
We already have contractions in a number of our public APIs (e.g. `typeParams`),
and I think it’s fine to shorten words as long as people can understand
the shortened versions without a background in scalac.
2) I agree with Simon that `nme` and `tpnme` are cryptic. I think it would
be thoughtful of us to provide newcomers with better names. To offset
the increase in mouthfulness, I’ve moved `MethodSymbol.isConstructor`
to `Symbol.isConstructor`, which covers the most popular use case for nme’s.
3) I also agree that putting `paramss` is a lot to ask of our users.
The double-“s” convention is very neat, but let’s admit that it’s just
weird for the newcomers. I think `paramLists` is a good compromise here.
4) `allOverriddenSymbols` is my personal complaint. I think it’s a mouthful
and a shorter name would be a much better fit for the public API.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When determining whether member `symLo` of `tpLo`
has a stronger type than member `symHi` of `tpHi`,
should we use memberType or memberInfo?
Well, memberType transforms (using `asSeenFrom`) `sym.tpe`,
whereas memberInfo performs the same transform on `sym.info`.
For term symbols, this ends up being the same thing (`sym.tpe == sym.info`).
For type symbols, however, the `.info` of an abstract type member
is defined by its bounds, whereas its `.tpe` is a `TypeRef` to that type symbol,
so that `sym.tpe <:< sym.info`, but not the other way around.
Thus, for the strongest (correct) result,
we should use `memberType` on the low side.
On the high side, we should use the result appropriate
for the right side of the `<:<` above (`memberInfo`).
I also optimized the method a little bit by avoiding calling memberType
if the symbol on the high side isn't eligble (e.g., it's a class).
PS: I had to add a workaround to reifyType, because
we now dealias a little less eagerly, which means
a type selection on refinement class symbols makes it to reify
this broke the t8104 tests.
I also had to update the run/t6992 test, which should now test the right thing.
Tests should be commented and/or use sensible names.
What is it testing? What is the expected outcome? We should not be left guessing.
|
|
Even though whitebox macros are supposed to be used to produce expansions
that refine advertised return types of their macro definitions, sometimes
those more precise types aren’t picked up by the typechecker.
It all started with Travis generating structural types with macros
and noticing that typer needs an extra nudge in order to make generated
members accessible to the outside world. I didn’t understand the mechanism
of the phenomenon back then, and after some time I just gave up.
Afterwards, when this issue had been brought up again in a different
StackOverflow question, we discussed it at reflection meeting, figured out
that typedBlock provides some special treatment to anonymous classes,
and it became clear that the first macro typecheck (the one that types
the expansion against the return type of the corresponding macro def)
is at fault here.
The thing is that if we have a block that stands for a desugard anonymous
class instantiation, and we typecheck it with expected type different from
WildcardType, then typer isn’t going to include decls of the anonymous class
in the resulting structural type: https://github.com/scala/scala/blob/master/src/compiler/scala/tools/nsc/typechecker/Typers.scala#L2350.
I tried to figure it out at https://groups.google.com/forum/#!topic/scala-internals/eXQt-BPm4i8,
but couldn’t dispel the mystery, so again I just gave up.
But today I had a profound WAT experience that finally tipped the scales.
It turns out that if we typecheck an if, providing a suitable pt, then
the resulting type of an if is going to be that pt, even though the lub
of the branch types might be more precise. I’m sure that reasons for this
behavior are also beyond my understanding, so I decided to sidestep this problem.
upd. Here’s Jason’s clarification: Doing thing differently would require
us to believe that "'Tis better to have lubbed and lost than never to have
lubbed at all." But the desire for efficiency trumps such sentimentality.
Now expansions of whitebox macros are first typechecked against outerPt,
the expected type that comes from the enclosing context, before being
typechecked against innerPt, the expected type that comes from the return
type of the macro def. This means that now outerPt provides the correct
expected type for the initial, most important typecheck, which makes
types more precise.
|