Bug 95638 - [1.5][compiler] Possibly incorrect Bounds Mismatch errors for complicated bounds
Summary: [1.5][compiler] Possibly incorrect Bounds Mismatch errors for complicated bounds
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows 2000
: P3 normal (vote)
Target Milestone: 3.1 RC1   Edit
Assignee: Philipe Mulet CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-05-17 15:47 EDT by Kory Markevich CLA
Modified: 2005-05-31 05:37 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 Kory Markevich CLA 2005-05-17 15:47:14 EDT
I'm not sure if the Eclipse compiler is correct or if javac is.

Found in 3.1M7.  The following code, each in their own file:

public class Key< Environment, T extends Type< Environment, T, K, S >, K extends
Key< Environment, T, K, S >, S extends State< S > > { }

public class State< S extends State > { }

public class Type< Environment, T extends Type< Environment, T, K, S >, K
extends Key< Environment, T, K, S >, S extends State< S > > { }

public class Store< Environment, T extends Type< Environment, T, K, S >, K
extends Key< Environment, T, K, S >, S extends State< S > > { }

public class Test< Environment >
{
    List< Store< Environment, ?, ? extends Key< Environment, ?, ?, ? >, ?
extends State< ? > > > stores;
}

Compiles without error or warning using javac -Xlint:all.  Eclipse generates an
error in Test:

Severity	Description	Resource	In Folder	Location	Creation Time
2	Bound mismatch: The type ? extends Key<Environment,?,?,?> is not a valid
substitute for the bounded parameter <K extends Key<Environment,T,K,S>> of the
type Store<Environment,T,K,S>	Test.java	BugTest/src	line 5	May 17, 2005 12:34:01 PM
Comment 1 Philipe Mulet CLA 2005-05-18 06:33:55 EDT
Simpler testcase:
class Key<E extends Key<E>> {}
class Store<A, B extends Key<B>> {}

public class X<T> {
	Store<T, ? extends Key<T>> store;
}
Comment 2 Philipe Mulet CLA 2005-05-18 06:53:03 EDT
Even simpler:
class Key<E extends Key<E>> {}
class Store<F extends Key<F>> {}

public class X<T> {
	Store<? extends Key<T>> store;
}

Now appears the origin of the compiler diagnostic.
Key requires its argument E to be a subtype of Key<E>.
However, when used in store field definition, Key<T> is wrong since T has no
bound, and doesn't meet expectation (subtype of Key<E>).
In order to compile it clear, you should do:

class Key<E extends Key<E>> {}
class Store<F extends Key<F>> {}

public class X<T extends Key<T>> {
	Store<? extends Key<T>> store;
}

I believe this is rather a bug in javac.
Comment 3 Kory Markevich CLA 2005-05-18 13:44:21 EDT
Unfortunately by eliminating Environment your examples changed the meaning.  This:

class Key< E, K extends Key< E, K > > { }

class Store< E, K extends Key< E, K > > { }

class X< E > {
    Store< E, ? > store1;
    Store< E, ? extends Key< E, ? > > store2;
}

is more in line with what I was trying to accomplish.  Unfortunately store1's
type is not restrictive enough; it doesn't indicate that all the Key's have type
Key< E, ? >.  store2 adds this information, but generates the same bug as I
reported above.

Now store2 isn't perfect either, as the fact that the two ?'s should be equal
isn't evident.  However this could be realized by looking at Store's
restrictions, could it not?  I'm not sure what the JLS says about cases like this.

Further your examples introduced T which fixes the type of the Key being used,
while I'm trying to range over many subtypes.  Perhaps this simply isn't
expressible with java's type system, but it seems that my store2 example does at
least get close.
Comment 4 Philipe Mulet CLA 2005-05-18 16:22:27 EDT
I simplified the example as long as I could preserve the discrepancy between
javac and us. Also, renaming type variables (and uses) has no effect on
semantics, I was trying to better separate the various cases.

When adding a bound onto T, I fixed the simplified issue for us; in a way which
suggests javac failed a bound check (when bound was missing).

I will look into your simpler example
Comment 5 Philipe Mulet CLA 2005-05-18 17:13:44 EDT
Problem is that both wildcards may represent a different type, which could burn
the bound check. javac seems to miss this case.

If you make both be the same type, by introducing an extra type parameter, then
we will compile it clean. I was guessing you could hide it from the outside, by
using a member type ?

class Key<E, K extends Key<E, K>> {}
class Store<E, K extends Key<E, K>> {}
class X<E> {
	class Y <F extends Key<E, F>> {
		Store<E, F> store;
	}
}
}
Comment 6 Philipe Mulet CLA 2005-05-19 18:28:14 EDT
Last thinking is that your scenario would be valid, and our diagnostic wrong.
Comment 7 Philipe Mulet CLA 2005-05-26 09:30:11 EDT
Added GenericTypeTest#test673-675,679-681.
Comment 8 Philipe Mulet CLA 2005-05-26 09:45:39 EDT
Changed bound check to better reflect capture mechanism, performing an
intersection check.
Also removed unnecessary bounds from wildcard, since these are only held on by
the actual capture.

Fixed
Comment 9 Frederic Fusier CLA 2005-05-27 10:42:53 EDT
Unfortunately, it seems that test case of comment 0 produce an NPE...
Select Type in"..., T extends Type<Environment,..." and hit F3
=> Error Excuting Command... Reason NPE

Stack trace:
java.lang.NullPointerException
	at
org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding.boundCheck(TypeVariableBinding.java:112)
	at
org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding.boundCheck(ParameterizedTypeBinding.java:59)
	at
org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference.checkBounds(ParameterizedSingleTypeReference.java:40)
	at
org.eclipse.jdt.internal.compiler.ast.TypeParameter.checkBounds(TypeParameter.java:36)
	at
org.eclipse.jdt.internal.compiler.lookup.ClassScope.checkParameterizedTypeBounds(ClassScope.java:699)
	at
org.eclipse.jdt.internal.compiler.lookup.ClassScope.connectTypeHierarchy(ClassScope.java:886)
	at
org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope.connectTypeHierarchy(CompilationUnitScope.java:254)
	at
org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.completeTypeBindings(LookupEnvironment.java:249)
	at org.eclipse.jdt.internal.codeassist.impl.Engine.accept(Engine.java:92)
	at
org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.askForType(LookupEnvironment.java:131)
	at
org.eclipse.jdt.internal.compiler.lookup.PackageBinding.getTypeOrPackage(PackageBinding.java:178)
	at org.eclipse.jdt.internal.compiler.lookup.Scope.getTypeOrPackage(Scope.java:2491)
	at org.eclipse.jdt.internal.compiler.lookup.Scope.getType(Scope.java:2237)
	at
org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference.internalResolveType(ParameterizedSingleTypeReference.java:99)
	at
org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference.resolveType(ParameterizedSingleTypeReference.java:209)
	at
org.eclipse.jdt.internal.codeassist.select.SelectionOnParameterizedSingleTypeReference.resolveType(SelectionOnParameterizedSingleTypeReference.java:30)
	at
org.eclipse.jdt.internal.compiler.lookup.Scope.connectTypeVariables(Scope.java:402)
	at
org.eclipse.jdt.internal.compiler.lookup.ClassScope.connectTypeHierarchy(ClassScope.java:880)
	at
org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope.connectTypeHierarchy(CompilationUnitScope.java:254)
	at
org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.completeTypeBindings(LookupEnvironment.java:249)
	at
org.eclipse.jdt.internal.codeassist.SelectionEngine.select(SelectionEngine.java:657)
	at org.eclipse.jdt.internal.core.Openable.codeSelect(Openable.java:165)
	at
org.eclipse.jdt.internal.core.CompilationUnit.codeSelect(CompilationUnit.java:314)
	at
org.eclipse.jdt.internal.core.CompilationUnit.codeSelect(CompilationUnit.java:308)
	at
org.eclipse.jdt.internal.ui.actions.SelectionConverter.codeResolve(SelectionConverter.java:219)
	at
org.eclipse.jdt.internal.ui.actions.SelectionConverter.codeResolve(SelectionConverter.java:153)
	at
org.eclipse.jdt.internal.ui.actions.SelectionConverter.codeResolve(SelectionConverter.java:162)
	at org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:128)
	at
org.eclipse.jdt.ui.actions.SelectionDispatchAction.dispatchRun(SelectionDispatchAction.java:226)
	at
org.eclipse.jdt.ui.actions.SelectionDispatchAction.run(SelectionDispatchAction.java:198)
	at org.eclipse.jface.action.Action.runWithEvent(Action.java:996)
	at org.eclipse.ui.commands.ActionHandler.execute(ActionHandler.java:182)
	at
org.eclipse.ui.internal.handlers.LegacyHandlerWrapper.execute(LegacyHandlerWrapper.java:108)
	at org.eclipse.core.commands.Command.execute(Command.java:311)
	at
org.eclipse.core.commands.ParameterizedCommand.execute(ParameterizedCommand.java:396)
	at
org.eclipse.ui.internal.keys.WorkbenchKeyboard.executeCommand(WorkbenchKeyboard.java:459)
	at org.eclipse.ui.internal.keys.WorkbenchKeyboard.press(WorkbenchKeyboard.java:781)
	at
org.eclipse.ui.internal.keys.WorkbenchKeyboard.processKeyEvent(WorkbenchKeyboard.java:828)
	at
org.eclipse.ui.internal.keys.WorkbenchKeyboard.filterKeySequenceBindings(WorkbenchKeyboard.java:550)
	at
org.eclipse.ui.internal.keys.WorkbenchKeyboard.access$3(WorkbenchKeyboard.java:493)
	at
org.eclipse.ui.internal.keys.WorkbenchKeyboard$KeyDownFilter.handleEvent(WorkbenchKeyboard.java:117)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:66)
	at org.eclipse.swt.widgets.Display.filterEvent(Display.java:788)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:843)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:868)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:853)
	at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:881)
	at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:877)
	at org.eclipse.swt.widgets.Widget.wmKeyDown(Widget.java:1469)
	at org.eclipse.swt.widgets.Control.WM_KEYDOWN(Control.java:3348)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:3067)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:3553)
	at org.eclipse.swt.internal.win32.OS.DispatchMessageW(Native Method)
	at org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:1650)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:2560)
	at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:1694)
	at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:1658)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:366)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:143)
	at org.eclipse.ui.internal.ide.IDEApplication.run(IDEApplication.java:103)
	at
org.eclipse.core.internal.runtime.PlatformActivator$1.run(PlatformActivator.java:226)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:375)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:162)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:324)
	at org.eclipse.core.launcher.Main.invokeFramework(Main.java:334)
	at org.eclipse.core.launcher.Main.basicRun(Main.java:278)
	at org.eclipse.core.launcher.Main.run(Main.java:973)
	at org.eclipse.core.launcher.Main.main(Main.java:948)
Comment 10 Kory Markevich CLA 2005-05-27 13:14:10 EDT
To be fair, that looks the same as bug 95481.  Unfortunately 95481 was marked as
RC2, which sucks since two small, simple files reduce the JDT to functionality
barely above Notepad. :(
Comment 11 Philipe Mulet CLA 2005-05-30 11:15:07 EDT
Closing, other issue is separate and got addressed indpendantly in bug 95481.
Frederic - pls verify the original defect.
Comment 12 Frederic Fusier CLA 2005-05-31 05:37:42 EDT
Verified with build I20050527-1300 that there's no compile error.