You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[enhancement] introduction of some public form of Self-types for better HasThisType implementation (and to resolve this.type-upper-bounded-types vs Self-types contradiction)
#5880
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.
What I was also trying to achieve - is possibility "literally" see that.type <: that.This (not only inside HasThisType sub-class/sub-trait in form of this.type <: this.This, but anywhere in code where some val that: HasThisType is available). Approach#1 basically provides that that.type <: that.This overall good visibility in most straight and obvious way.
However it suffers on some regression issue#5876, and it basically inappropriate when one may wont to define parametrized ThisLike1[_] abstract/self-type instead of simple This-type.
On the other hand one could try to combine that approaches together (and use advantages of Self-type together with public visibility of >: this.type upper-bounded constraint). Then something like following could be written
Unfortunately that attempt currently does not lead to expected effect (see issues: issue#5879 and issue#5878)
But if aforementioned issues will be "positively resolved" (so that not by claiming that as "expected behavior", or by applying some patch which will prohibit such code constructs at all), one could think about some more generalized solution (e.g. think about some possibility to define some "publicly visible" Self-types)
What is actually proposed
Possibility to control "visibility" of Self-types constraint, allowing them to have protected visibility (by default, and what they basically have now) and public visibility (newly introduced, visibility which should allow to see this.type <: this.Self constraint not only inside of underlined class/trait body, but also from outside as well)
Demonstrating snippet could look like following:
traitAdvancedFoo[P1,P2,P3] {
// hypothetical publicly visible Self-type constraint
public this:P1withP2=>// hypothetically by default Self-type constraints need to have `protected` visibilityprotectedthis:P3=>typeT1=P1typeT2=P2typeT3=P3
}
Here, assuming that we have val that: AdvancedFoo[...], publicly visible Self-type need to be seen literally as that.type <: that.P1 with that.P2
(while P3-self-type constraint generally could be seen only as this.type <: this.P3)
Also it assumes that AdvancedFoo[P1,P2,P3] need to be transparently convertible to AdvancedFoo[P1,P2,P3] with P1 with P2 (and wise verse).
What is possible even now
For now one could rewrite aforementioned hypothetical code into real(compilable) code in following way:
(complete code snippet here, same code also used in issue#5877)
// `AdvancedFooSelf` represents "public" part of self typetypeAdvancedFooSelf[P1,P2,P3] =AdvancedFoo[P1,P2,P3] withP1withP2traitAdvancedFoo[P1,P2,P3] {
this:P1withP2withP3=>typeT1=P1typeT2=P2typeT3=P3// code to expose it self typetypeSelfB>:this.type<:AdvancedFoo[P1,P2,P3] withP1withP2// SelfB <: AdvancedFooSelf[P1,P2,P3]
inline
defself():this.typewithP1withP2=this// self(): AdvancedFooSelf[P1,P2,P3]
}
// explicit and implicit converters to "expose it self"
inline
defexposeItSelf[P1,P2,P3](that: AdvancedFoo[P1,P2,P3]): that.typewithP1withP2= that.self()
inline
defexposeItSelf1[P1,P2,P3](that: AdvancedFoo[P1,P2,P3]):AdvancedFooSelf[P1,P2,P3] = that.self()
inline
defexposeItSelf3[P1,P2,P3](that: AdvancedFoo[P1,P2,P3]):AdvancedFooSelf[P1,P2,P3] =that : that.SelfBobjectexposeItSelfImpl {
importscala.language.implicitConversionsimplicit
inline
defexpose[P1,P2,P3](that: AdvancedFoo[P1,P2,P3]): that.typewithP1withP2= that.self()
}
Here AdvancedFoo#self is used to somehow expose that AdvancedFoo[P1,P2,P3] ~=:=~ AdvancedFoo[P1,P2,P3] with P1 with P2
And exposeItSelf, exposeItSelf1, exposeItSelf3 shows how that conversions could be implemented in form of generic methods. exposeItSelfImpl.expose allows to install that conversion as implicit, so in that case signatures [P1,P2,P3](that: AdvancedFoo[P1,P2,P3]) could be adapted to signatures [P1,P2,P3](that: AdvancedFoo[P1,P2,P3] with P1 with P2)
automatically (by compiler itself)
Demonstration of that explicit/implicit conversion (showing different ways how to "adapt" generic signature) may look like following
(complete code snippet here, same code also used in issue#5877)
// target signature is `[P1,P2,P3](that: AdvancedFoo[P1,P2,P3] with P1 with P2)`// def doSmthWithSelfImpl[P1,P2,P3](that: AdvancedFoo[P1,P2,P3] with P1 with P2): Unit = ???defdoSmthWithSelfImpl[P1,P2,P3](that: AdvancedFooSelf[P1,P2,P3]):Unit= {
println(s"doSmthWithSelfImpl: that: $that")
}
// different ways of explicit and/or implicit signature adaptations// from `[P1,P2,P3](that: AdvancedFoo[P1,P2,P3])` to `[P1,P2,P3](that: AdvancedFoo[P1,P2,P3] with P1 with P2)`defdoSmthWithSelf[P1,P2,P3](that: AdvancedFoo[P1,P2,P3]):Unit= {
doSmthWithSelfImpl(exposeItSelf(that))
}
defdoSmthWithSelfUsingImplicits[P1,P2,P3](that: AdvancedFoo[P1,P2,P3]):Unit= {
importscala.language.implicitConversionsimportexposeItSelfImpl._
doSmthWithSelfImpl(that)
}
defdoSmthWithSelfWithWildcards(that: AdvancedFoo[_,_,_]):Unit= {
// explicit conversion - signature1
doSmthWithSelfImpl(exposeItSelf(that))
// explicit conversion - signature2
doSmthWithSelfImpl(exposeItSelf2(that))
// explicit conversion - signature1
doSmthWithSelfImpl(exposeItSelf3(that))
// implicit conversion
{
importscala.language.implicitConversionsimportexposeItSelfImpl._
doSmthWithSelfImpl(that)
}
}
The text was updated successfully, but these errors were encountered:
Thanks for opening these very detailed issues! I'm going to close this one right away given that this issue tracker is not the place for language change proposal. Unless you personally intent on prototyping an implementation on top of Dotty, it's very likely that nobody will work on this, making the issue essentially non actionable. I encourage you to move it to https://contributors.scala-lang.org/ which would be more appropriate for discussion.
Motivation
During my experiments with possible different implementations of
HasThisType
, I've basically end up with several approaches.approach#1
approach#1
What I was also trying to achieve - is possibility "literally" see
that.type <: that.This
(not only insideHasThisType
sub-class/sub-trait in form ofthis.type <: this.This
, but anywhere in code where someval that: HasThisType
is available).Approach#1 basically provides that
that.type <: that.This
overall good visibility in most straight and obvious way.However it suffers on some regression issue#5876, and it basically inappropriate when one may wont to define parametrized
ThisLike1[_]
abstract/self-type instead of simpleThis
-type.On the other hand one could try to combine that approaches together (and use advantages of Self-type together with public visibility of
>: this.type
upper-bounded constraint). Then something like following could be writtenUnfortunately that attempt currently does not lead to expected effect (see issues: issue#5879 and issue#5878)
But if aforementioned issues will be "positively resolved" (so that not by claiming that as "expected behavior", or by applying some patch which will prohibit such code constructs at all), one could think about some more generalized solution (e.g. think about some possibility to define some "publicly visible" Self-types)
What is actually proposed
Possibility to control "visibility" of Self-types constraint, allowing them to have
protected
visibility (by default, and what they basically have now) andpublic
visibility (newly introduced, visibility which should allow to seethis.type <: this.Self
constraint not only inside of underlined class/trait body, but also from outside as well)Demonstrating snippet could look like following:
Here, assuming that we have
val that: AdvancedFoo[...]
, publicly visible Self-type need to be seen literally asthat.type <: that.P1 with that.P2
(while
P3
-self-type constraint generally could be seen only asthis.type <: this.P3
)Also it assumes that
AdvancedFoo[P1,P2,P3]
need to be transparently convertible toAdvancedFoo[P1,P2,P3] with P1 with P2
(and wise verse).What is possible even now
For now one could rewrite aforementioned hypothetical code into real(compilable) code in following way:
(complete code snippet here, same code also used in issue#5877)
Here
AdvancedFoo#self
is used to somehow expose thatAdvancedFoo[P1,P2,P3] ~=:=~ AdvancedFoo[P1,P2,P3] with P1 with P2
And
exposeItSelf
,exposeItSelf1
,exposeItSelf3
shows how that conversions could be implemented in form of generic methods.exposeItSelfImpl.expose
allows to install that conversion as implicit, so in that case signatures[P1,P2,P3](that: AdvancedFoo[P1,P2,P3])
could be adapted to signatures[P1,P2,P3](that: AdvancedFoo[P1,P2,P3] with P1 with P2)
automatically (by compiler itself)
Demonstration of that explicit/implicit conversion (showing different ways how to "adapt" generic signature) may look like following
(complete code snippet here, same code also used in issue#5877)
The text was updated successfully, but these errors were encountered: