Bug 183211 - [1.5][compiler] single static import for a field is ambiguous
Summary: [1.5][compiler] single static import for a field is ambiguous
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.3   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.4 M6   Edit
Assignee: Kent Johnson CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-04-19 11:46 EDT by Olivier Thomann CLA
Modified: 2008-03-26 03:22 EDT (History)
3 users (show)

See Also:


Attachments
Patch to fix the problem message (2.90 KB, patch)
2007-04-19 11:48 EDT, Olivier Thomann CLA
no flags Details | Diff
Proposed patch (5.00 KB, patch)
2008-03-18 21:38 EDT, Philipe Mulet CLA
no flags Details | Diff
Proposed patch with testcase (4.65 KB, patch)
2008-03-19 13:21 EDT, Kent Johnson CLA
no flags Details | Diff
New proposed patch (4.59 KB, patch)
2008-03-20 16:10 EDT, Kent Johnson CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Olivier Thomann CLA 2007-04-19 11:46:55 EDT
Using v_749, the following test case fails.

package p1;

import static p.C.s;

public class X {}

----------------------
package p;

interface I {
    String s = "";
}
class B {
    public static String s = "Hello, World!";
}
public class C extends B implements I {}

--------------------
We report:
----------
1. ERROR in D:\tests_sources\p1\X.java (at line 3)
	import static p.C.s;
	              ^^^^^
The field s is ambiguous
----------
1 problem (1 error)

This worked with M6. javac (1.5/1.6/1.7) also compiles it fine.
Comment 1 Olivier Thomann CLA 2007-04-19 11:48:50 EDT
Created attachment 64321 [details]
Patch to fix the problem message

Without this patch we report the error calling the field 'B' instead of 'i'
Comment 2 Olivier Thomann CLA 2007-04-19 11:55:32 EDT
I remove the regression from the title since we failed with M5 and M6.
So this is not a new problem.
Comment 3 Olivier Thomann CLA 2007-04-19 11:58:26 EDT
We have the same issue with types.
package p1;

import static p.C.B;

public class X {}

---------------------
package p;

interface I {
    class B {}
}
class D {
    public static class B {}
}
public class C extends D implements I {}

In this case we report the import for B as being not visible.
----------
1. ERROR in d:\tests_sources\p1\X.java (at line 3)
        import static p.C.B;
                      ^^^^^
The type p.C.B is not visible
----------

Both cases are ok with javac.
Comment 4 Olivier Thomann CLA 2007-04-19 13:16:15 EDT
Patch has been released to HEAD.
Code coverage showed that this path was never used in the ProblemReporter.
Comment 5 Olivier Thomann CLA 2007-04-19 13:24:54 EDT
In the case from comment 0, javac returns the field from I.
Comment 6 Kent Johnson CLA 2007-04-19 13:46:55 EDT
They complain when the type C implements 2 superinterfaces I & J that define the same field, but not a superclass & a superinterface?

Sounds fishy to me.
Comment 7 Olivier Thomann CLA 2007-04-19 13:50:25 EDT
Sounds buggy. We might want to check the specs carefully.
I don't see how they see more one field than the other.
Comment 8 Kent Johnson CLA 2007-04-23 14:26:41 EDT
javac does complain when C implements 2 interfaces:

package p;
interface I {
    String s = "";
}
interface J {
    String s = "";
}
public class C implements I, J {}

X.java:1: s is already defined in a static single-type import

Need to verify that the spec indicates that superinterfaces have precedence over superclasses
Comment 9 Kent Johnson CLA 2007-04-23 14:27:14 EDT
Reopening - didn't mean to close
Comment 10 Kent Johnson CLA 2007-04-23 16:10:04 EDT
Section 8.3.3.3 describes the case of a type X inheriting a field from 2 interfaces or a superclass & superinterace.

A simple reference to the field name within X in this case is reported as ambiguous.

What's the difference with a static import reference to the field thru the type X?

None that I can find, but then I cannot find any specific mention of a static import finding an inherited field.
Comment 11 Kent Johnson CLA 2007-05-01 12:55:45 EDT
From the original testcase in comment #0, if we add a reference to s in the type C :

package p;
interface I {
    String s = "";
}
class B {
    public static String s = "Hello, World!";
}
public class C extends B implements I {
    String myString = s;
}

javac reports an error since s is ambiguous.

If its ambiguous inside C, it should also be ambiguous to the static import statement in X.

Closing as Invalid
Comment 12 Olivier Thomann CLA 2007-05-01 15:21:04 EDT
Verified for 3.3M7.
Comment 13 Walter Harley CLA 2008-03-12 18:11:27 EDT
Adding some more details to this closed bug, in case this comes back to cause problems.

If we have:

Unit p1.M:
  package p1;
  interface I1 { int f = 1; }
  interface I2 { int f = 2; }
  class C { public static int f = 3; }
  class M extends C implements I1, I2 {}

Unit p2.Q:
  package p2;
  import static p1.M.f;
  class Q {
    public static void main(String[] args) {
      System.out.println("f = " + f);
    }
  }

javac will compile without complaints, and will output "f = 1".  If the import order on M is changed to "class M extends C implements I2, I1", then it will output "f = 2".  

As Kent noted, if f is accessed within class M, javac will flag it as ambiguous.

If the 'public' specifier is omitted from the definition of f on C, then Eclipse will still complain about f being ambiguous, and javac will complain that it can't find f at all:

  p2\Q.java:3: cannot find symbol
  symbol  : static f
  location: class p1.M
  import static p1.M.f;
  ^
  p2\Q.java:7: cannot find symbol
  symbol  : variable f
  location: class p2.Q
                  System.out.println("f equals " + f);
                                                   ^

If I2 is removed, and the 'public' specifier is omitted from C.f, then Eclipse will compile and run (and output "f = 1"), but javac will still complain that it can't find f at all.

Note that although adding 'public' to C.f lets javac compile, the value that is output is the value specified by I1.f (or I2.f if that is first in the interface list).

So it seems to me like the javac behavior is pretty random, perhaps reflecting a poorly designed language feature, but looking through Sun's bug database it also seems like the spec has had plenty of argument already.
Comment 14 Walter Harley CLA 2008-03-12 18:30:45 EDT
Actually, digging deeper, I am going to reopen this bug.  Sorry if it is just my confusion.

JLS section 7.5.3, "Single Static Import Declaration", says:

"Note that it is permissable for one single-static-import declaration to import several fields or types with the same name, or several methods with the same name and signature."

My reading is that the import statement itself is not considered ambiguous, although it may create a subsequent ambiguity when the field or type is referenced.  
Comment 15 Philipe Mulet CLA 2008-03-14 07:03:49 EDT
It indeed feels that the static import could be tolerated, though subsequent field references should be doomed... 
Comment 16 Philipe Mulet CLA 2008-03-18 21:34:29 EDT
Added StaticImportTest#test059-062
Comment 17 Philipe Mulet CLA 2008-03-18 21:38:21 EDT
Created attachment 92861 [details]
Proposed patch
Comment 18 Philipe Mulet CLA 2008-03-19 00:58:54 EDT
Released for 3.4M6.
Fixed
Comment 19 Kent Johnson CLA 2008-03-19 11:13:03 EDT
Now we differ on which field is chosen.

For example,

package p;
import static q.A.a;
public class X {
	public static void main(String[] s) {
		System.out.println(a);
	}
}


package q;
public class A extends B implements J, I {}
interface I { String a = "1"; }
interface J { String a = "2"; }
class B { public static String a = "3"; }


I still find it difficult to understand how any of these 3 fields can be picked over the others.

But we're not going to report an error, then we should probably pick the same field.
Comment 20 Kent Johnson CLA 2008-03-19 11:34:53 EDT
Reopening...
Comment 21 Kent Johnson CLA 2008-03-19 13:21:21 EDT
Created attachment 92938 [details]
Proposed patch with testcase
Comment 22 Kent Johnson CLA 2008-03-19 13:22:37 EDT
The latest patch reports ambiguous errors against each use of an ambiguous field but leaves the import statement alone.
Comment 23 Kent Johnson CLA 2008-03-19 14:47:04 EDT
Released new patch into HEAD for 3.4M6
Comment 24 Walter Harley CLA 2008-03-19 16:54:27 EDT
The latest change appears to have introduced a crashing bug (see bug 223253).

Also, the case mentioned in comment 3 (which is the same case that causes the crash) still does not seem to be fixed, based on some testing with ecj.jar.
Comment 25 Kent Johnson CLA 2008-03-20 11:00:45 EDT
And as for this case:

package p2;
interface I { class B {} }
class D {
	//public static class B {}
	//static class B {}
}
public class C extends D implements I {}
------------
package p1;
import static p.C.B;
public class X {}


javac reports an error when D.B is not visible and I.B doesn't exist.

So why is a non-visible member type from the class D an error, but a non-visible member type from the interface I is OK ?


I'm not convinced we want to match this strange behaviour.
Comment 26 Kent Johnson CLA 2008-03-20 11:56:09 EDT
We're going to close this one again Walter.

The above case is not one we want to match right now.
Comment 27 Kent Johnson CLA 2008-03-20 16:10:10 EDT
Created attachment 93065 [details]
New proposed patch

Now treat ambiguous member types and fields the same.

Only report the ambiguous error on a reference & not the static import statement.
Comment 28 Kent Johnson CLA 2008-03-20 16:11:03 EDT
Released new patch into HEAD for 3.4M6
Comment 29 Walter Harley CLA 2008-03-21 15:10:09 EDT
Latest version looks good.  Thanks!
Comment 30 Eric Jodet CLA 2008-03-26 03:22:26 EDT
Verified for 3.4M6 using build I20080324-1300