Bug 108372 - [1.5][compiler] Inner class of enclosing raw type don't works
Summary: [1.5][compiler] Inner class of enclosing raw type don't works
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.2   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.1.1   Edit
Assignee: Philipe Mulet CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-08-30 10:30 EDT by Rémi Forax CLA
Modified: 2005-09-26 12:03 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Rémi Forax CLA 2005-08-30 10:30:15 EDT
the following code doesn't compile because
inner is typed Foo<T>.Inner and not
Foo.Inner. It's works with Foo<?>.Inner

public class Foo<T> {
    private T t;
    private Foo.Inner[] inner;
    public Foo(T t) {
        this.t = t;
        inner = new Foo.Inner[10];
        //Type mismatch: cannot convert from Foo.Inner[] to Foo<T>.Inner[]
    }
    private class Inner {
    }
}

Rémi Forax
Comment 1 Olivier Thomann CLA 2005-08-30 10:36:14 EDT
If the Inner class is static, it works.
Comment 2 Rémi Forax CLA 2005-08-30 11:58:46 EDT
the following code with wildcard works in eclipse
but not in javac (not permitted by the grammar ??)

public class Foo<T> {
    private T t;
    private Foo<?>.Inner[] inner;
    public Foo(T t) {
        this.t = t;
        inner = new Foo<?>.Inner[10];
    }
    private class Inner {
    }
}

Rémi Forax
Comment 3 Olivier Thomann CLA 2005-08-30 12:21:31 EDT
I don't see why this would be forbidden by the grammar.

new Foo<?>.Inner[10]

can be seen as (I removed unused rules):

ArrayCreationExpression:
      new ClassOrInterfaceType DimExprs Dimsopt

where ClassOrInterfaceType is:

ClassOrInterfaceType:
        ClassType

ClassType:
        TypeDeclSpecifier TypeArgumentsopt

TypeDeclSpecifier:
        TypeName
        ClassOrInterfaceType . Identifier

TypeArguments:
        < ActualTypeArgumentList >

ActualTypeArgumentList: 
        ActualTypeArgument

ActualTypeArgument:
        Wildcard


Wildcard:
? WildcardBoundsOpt

So new Foo<?>.Inner[10] is:
'new' 
ClassOrInterfaceType
    (ClassOrInterfaceType(TypeName('Foo') TypeArguments('<?>')) '.' 
Identifier('Inner'))
DimExprs('[10]')

It might not be semantically valid, but I think it should be syntactically valid.
Comment 4 Philipe Mulet CLA 2005-09-05 06:23:01 EDT
Original problem only occurs in presence of array type ref: Foo.Inner[] due to
bug in these reference resolution.

Fixed in latest, releasing in 3.1.1 and 3.2 streams.
Added GenericTypeTest#test810.
Comment 5 Philipe Mulet CLA 2005-09-05 06:24:42 EDT
Actually, test is rather #test811
Comment 6 Philipe Mulet CLA 2005-09-05 06:56:34 EDT
Also tuned unchecked warning diagnosis to properly report unchecked warning for:
public class Foo<T> {
    private T t;
    private Foo<?>.Inner[] inner;
    public Foo(T t) {
        this.t = t;
        inner = new Foo.Inner[10];
    }
    private class Inner {
    }
}

We were missing it since tolerating unbound enclosing parameterized type.
Added GenericTypeTest#test812
Comment 7 Philipe Mulet CLA 2005-09-05 08:38:07 EDT
Re: comment 2, I believe it should be rejected. Not syntactically, but rather
since type Foo<?>.Inner isn't reifiable (JLS4.7), though the spec isn't quite
explicit on this scenario.

inner = new Foo<?>.Inner[10];
Comment 8 Philipe Mulet CLA 2005-09-05 10:22:29 EDT
Added GenericTypeTest#test813 for latter case, and tuned #isReifiable()
implementation to reject unbound parameterized enclosing types as well (only
tolerate innermost to be unbound).
Comment 9 Rémi Forax CLA 2005-09-05 11:20:17 EDT
I'm not agree with you, array of non reifiable type are not rejected
by the JLS.

List<?>[] list=new ArrayList<?>[5];
is legal so 
Foo<?>.Inner[] inner = new Foo<?>.Inner[10];
is legal too.
Comment 10 Rémi Forax CLA 2005-09-05 18:05:40 EDT
I reply to myself, since my last post, i have read the JLS

JLS 15.10 (page 426) :
  "An array creation expression creates an object that is a new array
   whose elements are of the type specified by the PrimitiveType or TypeName.
   It is a compiletime error if the TypeName does not denote
    a reifiable type (§4.7)"

  so TypeName must be a reifiable type.
  And in the footnote :
  "Note that the syntax ensures that the element type
   in an array creation  expression cannot be a parameterized type,
   other than an unbounded wildcard."

  then array of parametrized type with unbonded wilcard is legal.

JLS 4.7 
  "A type is reifiable if and only if one of the following holds:
   • It refers to a non-generic type declaration.
   • It is a parameterized type in which all type arguments
     are unbounded wildcards (§4.5.1).
   • It is a raw type (§4.8).
   • It is an array type (§10.1) whose component type is reifiable"

  using bullets 2 and 4, ArrayList<?> is a reifiable type.

The JLS is not clear about the fact that if B is an inner-class of A
and A<T> is a parametrized type then A<T>.B is a parametrized type.
But JLS 4.5 (p66) give Seq<String>.Zipper<Integer> as an example of
parametrized type.

In summary :
  Foo<T>.Inner is a parametrized type (JLS 4.5)
  Foo<?>.Inner is a parameterized type in which all type arguments
     are unbounded wildcards (JLS 4.5.1)
  Foo<?>.Inner is a reifable type (JLS 4.7)
  new Foo<?>.Inner[10] is legal (JLS 15.10)

so i think you can remove your patch.



  

   

Comment 11 Philipe Mulet CLA 2005-09-06 03:59:53 EDT
A parameterized type has arguments, like List<String>. As you said, the spec 4.7
is not telling about the enclosing type case:

Foo<?>.Inner

I ping'ed spec lead for confirmation, and based on his answer I will advise. I
will leave the change in for now, since it matches javac behavior for rejecting
the code.
Comment 12 Philipe Mulet CLA 2005-09-06 07:39:08 EDT
In case needing to tune the semantics for reifiable type, need to play with
TypeBinding#isReifiable() and/or #needsUncheckedConversion().

Comment 13 Philipe Mulet CLA 2005-09-07 04:46:17 EDT
From spec lead:
Indeed, we've found that the definition of reifiable types does not 
handle nested types the way one would like. As the spec stands, your 
example is not reifiable. But it really should be.
The exact definition needs to be worked out.


Will correct the implementation of #isReifiable() accordingly.
Comment 14 Philipe Mulet CLA 2005-09-07 09:12:38 EDT
Fixed
Comment 15 David Audel CLA 2005-09-21 10:51:02 EDT
Verified in I20050921-0010 for 3.2M2
Comment 16 David Audel CLA 2005-09-26 12:03:36 EDT
Verified using M20050923-1430 for 3.1.1