Menu

#52 [nullness] Access to field via nullable reference

open
nobody
None
5
2007-07-09
2007-07-09
No

This code doesn't compiled:

class Exchanger
{
?Holder first = null;

void exchange( Holder h )
{
if( first != null )
{
h.other = first.self;
first.other = h.self;
}
}
}

class Holder
{
int self = 0;
int other = 0;
}

with error:

D:\home\eao197\tmp\nice\optional_field_bug>nicec --jar test1.jar test1
nice.lang: parsing
test1: parsing
test1: typechecking

D:\home\eao197\tmp\nice\optional_field_bug\test1\t.nice: line 9, column 23:
Arguments (?test1.Holder) do not fit:
nice.lang.int test1.Holder.self
compilation failed with 1 error

Nice version is:

D:\home\eao197\tmp\nice\optional_field_bug>nicec --version
Nice compiler version 0.9.12 (build 2006.01.26, 12:43:13 UTC)
Compiled using JDK 1.4.2_08
Copyright (C) 2003 Daniel Bonniot
Visit the Nice homepage: http://nice.sourceforge.net

Discussion

  • Daniel Bonniot

    Daniel Bonniot - 2007-11-25

    Logged In: YES
    user_id=88952
    Originator: NO

    (sorry for the last response)

    The current behaviour is deliberate. It would be unsafe to allow this code in general, since it might be possible to your program has multiple threads, and another thread modifies the field's value to null between the test and the use.

    A simple workaround is to start your function with:
    let first = this.first;

    Then the rest is dealing with an immutable, local copy of the field, and the code is safe.

    I reclassify as a feature request, since we could still improve the situation:
    1. allow this for final fields (might already work)
    2. give a better error message,
    3. change to semantic to mean exactly what happens when doing the workaround. This would be what people want 99% of the time, and even in multi-threaded situations, it might be good. But not when we *expect* the value to change. So this needs to be thought about more...

     
  • Yauheni Akhotnikau

    Logged In: YES
    user_id=163552
    Originator: YES

    If that behaviour is deliberate then I don't understand why this code is allowed:

    class Exchanger
    {
    Holder first = new Holder( self: 0, other: 0 );

    void exchange( Holder h )
    {
    h.other = first.self;
    first.other = h.self;
    }
    }

    class Holder
    {
    int self = 0;
    int other = 0;
    }

    There could be another thread which could modify Exchanger.first attribute.

    I think it is a mistake to mix thread safety (which should be archived by 'synchronized' and some sort of immutable data structures) and optional references.

    Anyway better error messages is neccessary here.

     

Log in to post a comment.

MongoDB Logo MongoDB