-
Notifications
You must be signed in to change notification settings - Fork 1.1k
[WIP] Changes to Interpolation #4065
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
Previously we failed if a member of a TypeParamRef did not find anything in its upper constraint bound. We now look in the lower bound instead, and if something is found there, add a constraint to make sure that any future instantiation of the parameter has the same members.
We (probably) need ephemeral only if we actually compute the current instance type, and this instance type might be retracted later.
@@ -591,7 +591,13 @@ object Types { | |||
ctx.typerState.constraint.entry(tp) match { | |||
case bounds: TypeBounds if bounds ne next => | |||
ctx.typerState.ephemeral = true | |||
go(bounds.hi) |
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 discussed this with Martin on a whiteboard, so a memo (and possible comment).
If X >: List[T]
and x: X
and we typecheck x.filter(p)
, how should X
be instantiated? Here setting X
to its lower bound works, but might violate other constraints — ideally we'd just add some constraint X <: { def filter... }
, but since we don't have those, looking up List.filter
's definition class (say Traversable[T]
) and adding bound X <: Traversable[T]
is a more general solution.
This solution is not yet complete because some other ancestor of List[T]
which doesn't extend Traversable[T]
might have another overload of filter
. There might even be a realistic example where this happens, but I can't think of it.
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.
Yes, I think it makes sense to add this. Unfortunately, it is not enough. We still need to interpolate TypeVar results in some way when selecting because otherwise we might miss an implicit conversion. E.g.
Array(1, 2, 3).map(_ + 1).deep
The map operation with current stdlib leaves us with result type That
where
That >: Array[Int]
But to typecheck deep
we need to find an implicit conversion from the result to ArrayOps
. There is none from That
, but there is one from Array[Int]
.
Allow to define what gets shown as a result on a backtrace
The previous scheme created a `val showOp = <some closure>` value for each trace operation. It was unused if tracing was disabled. Still might be better to avoid its creation in the first place.
-Yshow-no-inline suppresses "inlined from" parts when printing trees. This is useful when one has deeply inlined structures, as is the case when looking at `trace`ed code.
Used for small, linked sets. Normal immutable sets are about as fast for 0 - 4 elements, but are not linked for larger sizes.
Superseded by #4080. |
This is an attempt to do rethink interpolation of type variables from the ground up. So far it's an experiment.