- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
accessing field in constructor before declared
Wed, 2011-05-04, 02:53
I just spent hours tracking down a bug that resulted from accessing a field in a constructor before it was initialized. Here's a trivial example to illustrate what I mean:
class Test999 {
val foo = bar
val bar = 1
}
This compiles without warning, but should it? I think not.
--Russ P.
--
http://RussP.us
class Test999 {
val foo = bar
val bar = 1
}
This compiles without warning, but should it? I think not.
--Russ P.
--
http://RussP.us
Wed, 2011-05-04, 05:47
#2
Re: accessing field in constructor before declared
Thanks, Derek. I assume you mean a drop in run-time performance, not compilation time. Are you suggesting that the check for initialization must be done at run time? I'm probably naive, but I don't understand why the compiler can't just determine that the value is being accessed before it is initialized. If you do something like that in a non-constructor, it can tell. Why is it different for a constructor?
--Russ
On Tue, May 3, 2011 at 8:10 PM, Derek Williams <derek@nebvin.ca> wrote:
--
http://RussP.us
--Russ
On Tue, May 3, 2011 at 8:10 PM, Derek Williams <derek@nebvin.ca> wrote:
On Tue, May 3, 2011 at 7:53 PM, Russ Paielli <russ.paielli@gmail.com> wrote:
> This compiles without warning, but should it? I think not.
The compiler option you want is -Xcheckinit. It causes a drop in
performance to do the checking. This has been discussed many times on
this list so if you want more details it's probably best to search for
"checkinit"
--
Derek
--
http://RussP.us
Wed, 2011-05-04, 05:57
#3
Re: accessing field in constructor before declared
On Tue, May 3, 2011 at 10:34 PM, Russ Paielli wrote:
> Thanks, Derek. I assume you mean a drop in run-time performance, not
> compilation time. Are you suggesting that the check for initialization must
> be done at run time? I'm probably naive, but I don't understand why the
> compiler can't just determine that the value is being accessed before it is
> initialized. If you do something like that in a non-constructor, it can
> tell. Why is it different for a constructor?
Yes, runtime performance. And I'm no compiler expert, but I think this
is one of the best threads discussing the problem:
http://scala-programming-language.1934581.n4.nabble.com/scala-Initializa...
Wed, 2011-05-04, 09:37
#4
Re: accessing field in constructor before declared
My student works on a compiler plugin for this.
Its aim is to statically catch not only such trivial cases as in the
example, but also cases involving method calls and nheritance. We will
publish it when it is usable.
Regards,
Piotr
W dniu 2011-05-04 03:53, Russ Paielli pisze:
> I just spent hours tracking down a bug that resulted from accessing a
> field in a constructor before it was initialized. Here's a trivial
> example to illustrate what I mean:
>
> class Test999 {
>
> val foo = bar
> val bar = 1
> }
>
> This compiles without warning, but should it? I think not.
>
> --Russ P.
>
> --
> http://RussP.us
Wed, 2011-05-04, 10:17
#5
Re: accessing field in constructor before declared
On Wed, May 4, 2011 at 3:53 AM, Russ Paielli <russ.paielli@gmail.com> wrote:
I just spent hours tracking down a bug that resulted from accessing a field in a constructor before it was initialized. Here's a trivial example to illustrate what I mean:
class Test999 {
val foo = bar
val bar = 1
}
This compiles without warning, but should it? I think not.
Probably not, but overriding makes it tricky. What if you have a subclass that overrides bar as an early val?
scala> class Test1000 extends { override val bar = 10 } with Test999 defined class Test1000
scala> (new Test999).foo res2: Int = 0
scala> (new Test1000).foo res3: Int = 10
If the warning is issued for Test999, it may be a false-positive.
But I agree we should do better. A tool like the one mentioned by Piotr would be great. I'm also looking into work done by Eva Darulova (PhD student at EPFL, worked with Donna on this project) to tackle exactly this problem.
iulian
--Russ P.
--
http://RussP.us
--
« Je déteste la montagne, ça cache le paysage »
Alphonse Allais
Wed, 2011-05-04, 13:07
#6
Re: accessing field in constructor before declared
On Wed, May 4, 2011 at 4:12 AM, iulian dragos <jaguarul@gmail.com> wrote:
That should be no different, should it? Super-class construction is always done before sub-class construction, hence super-class construction should never rely on sub-class or non-final method calls in general.
Probably not, but overriding makes it tricky. What if you have a subclass that overrides bar as an early val?
That should be no different, should it? Super-class construction is always done before sub-class construction, hence super-class construction should never rely on sub-class or non-final method calls in general.
Wed, 2011-05-04, 13:57
#7
Re: accessing field in constructor before declared
On Wed, May 4, 2011 at 1:57 PM, Nils Kilden-Pedersen <nilskp@gmail.com> wrote:
On Wed, May 4, 2011 at 4:12 AM, iulian dragos <jaguarul@gmail.com> wrote:Probably not, but overriding makes it tricky. What if you have a subclass that overrides bar as an early val?
That should be no different, should it? Super-class construction is always done before sub-class construction, hence super-class construction should never rely on sub-class or non-final method calls in general.
If you have an early initializer section, then it runs before the super-class constructor (see my example). This is used as a means to pass parameters to trait constructors, that cannot have real parameters.
iulian
--
« Je déteste la montagne, ça cache le paysage »
Alphonse Allais
Wed, 2011-05-04, 14:07
#8
Re: accessing field in constructor before declared
Alternatively, use lazy vals...
On 4 May 2011 13:55, "iulian dragos" <jaguarul@gmail.com> wrote:> On Wed, May 4, 2011 at 1:57 PM, Nils Kilden-Pedersen <nilskp@gmail.com>wrote:
>
>> On Wed, May 4, 2011 at 4:12 AM, iulian dragos <jaguarul@gmail.com> wrote:
>>
>>> Probably not, but overriding makes it tricky. What if you have a subclass
>>> that overrides bar as an early val?
>>
>>
>> That should be no different, should it? Super-class construction is always
>> done before sub-class construction, hence super-class construction should
>> never rely on sub-class or non-final method calls in general.
>>
>
> If you have an early initializer section, then it runs before the
> super-class constructor (see my example). This is used as a means to pass
> parameters to trait constructors, that cannot have real parameters.
>
> iulian
>
>
>
>
> --
> « Je déteste la montagne, ça cache le paysage »
> Alphonse Allais
On Tue, May 3, 2011 at 7:53 PM, Russ Paielli wrote:
> This compiles without warning, but should it? I think not.
The compiler option you want is -Xcheckinit. It causes a drop in
performance to do the checking. This has been discussed many times on
this list so if you want more details it's probably best to search for
"checkinit"