Bug 211037 - [infer type arguments] UnsupportedOperationException when class contains Object.getClass()
Summary: [infer type arguments] UnsupportedOperationException when class contains Obje...
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.3.1   Edit
Hardware: PC Windows Vista
: P3 major with 1 vote (vote)
Target Milestone: 3.4 RC3   Edit
Assignee: Markus Keller CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 190508 216661 (view as bug list)
Depends on: 234619
Blocks:
  Show dependency tree
 
Reported: 2007-11-27 04:32 EST by Faux CLA
Modified: 2008-05-30 03:02 EDT (History)
6 users (show)

See Also:
martinae: review+
benno.baumgartner: review+


Attachments
Fix (4.36 KB, patch)
2008-05-26 12:51 EDT, Markus Keller CLA
no flags Details | Diff
Fix 2 (fails) (7.90 KB, patch)
2008-05-29 08:56 EDT, Markus Keller CLA
no flags Details | Diff
Fix 3 (1.71 KB, patch)
2008-05-29 09:46 EDT, Markus Keller CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Faux CLA 2007-11-27 04:32:44 EST
When attempting to Infer Generic Type Arguments... (via. refactor menu) on a class that contains a call to Object.getClass(), an "unexpected exception" occours, and refactoring aborts.

This occoured in real-world code (I'm not even going to comment on the quality of the code, or whether the call to getClass() was even necessary) in JavaCC's org.javacc.parser.Options class:

https://javacc.dev.java.net/source/browse/javacc/src/org/javacc/parser/Options.java?rev=1.18&view=markup 

A far simpler test-case is reproduced below.

-- To reproduce:

1) Create or open any Java/JDT project.

2) Create a class that looks something like (or simply add the method to any other class):

class TrivialClass
{
	void irrelevant(Object someObject)
	{
		someObject.getClass();
	}
}

3) Right-click the editor (or use a hotkey etc.) -> Refactor -> Infer Generic Type Arguments...

4) The check-boxes on the dialog are irrelevant. Press "Preview >" or "OK".

5) Observe either:
5a) From Preview >:

A fatal error occoured while performing the refactoring.
Found problems:
An unexpected exception occurred while creating a change object. See the error log for more details.
No context information available.

5b) From OK:
An unexpected exception occurred while perfomring the refactoring. See the error log for more details.
See the error log for more details.

6) Look at the error log. (reproduced below)

-- Notes

 - It's incredibly hard to work out where problems like this happen, especially if you're running refactoring options on entire source trees. A helpful error message in case of unexpected situations would be nice, but is probably far too much work. :)

 - It doesn't happen if you replace Object with, say, Integer.

-- System:
- Eclipse:
Version: 3.3.1.1
Build id: M20071023-1652
x86 (x32) architecture.

- Java:
java version "1.6.0_03"
Java(TM) SE Runtime Environment (build 1.6.0_03-b05)
Java HotSpot(TM) Client VM (build 1.6.0_03-b05, mixed mode, sharing)

x86 (x32) architecture.

- Windows:
Vista.
Microsoft Windows [Version 6.0.6000]

x64 (x86_64) architecture/edition.

-- Full .log for OK:

!SESSION 2007-11-27 08:52:05.189 -----------------------------------------------
eclipse.buildId=M20071023-1652
java.version=1.6.0_03
java.vendor=Sun Microsystems Inc.
BootLoader constants: OS=win32, ARCH=x86, WS=win32, NL=en_GB
Command-line arguments:  -os win32 -ws win32 -arch x86

!ENTRY org.eclipse.ltk.ui.refactoring 4 10000 2007-11-27 08:53:16.334
!MESSAGE Internal Error
!STACK 0
java.lang.reflect.InvocationTargetException
	at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:350)
	at org.eclipse.ltk.internal.ui.refactoring.RefactoringWizardDialog2.run(RefactoringWizardDialog2.java:310)
	at org.eclipse.ltk.ui.refactoring.RefactoringWizard.internalPerformFinish(RefactoringWizard.java:553)
	at org.eclipse.ltk.ui.refactoring.UserInputWizardPage.performFinish(UserInputWizardPage.java:154)
	at org.eclipse.ltk.ui.refactoring.RefactoringWizard.performFinish(RefactoringWizard.java:619)
	at org.eclipse.ltk.internal.ui.refactoring.RefactoringWizardDialog2.okPressed(RefactoringWizardDialog2.java:439)
	at org.eclipse.jface.dialogs.Dialog.buttonPressed(Dialog.java:464)
	at org.eclipse.jface.dialogs.Dialog$2.widgetSelected(Dialog.java:616)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:227)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:66)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:938)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3682)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3293)
	at org.eclipse.jface.window.Window.runEventLoop(Window.java:820)
	at org.eclipse.jface.window.Window.open(Window.java:796)
	at org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation$1.run(RefactoringWizardOpenOperation.java:142)
	at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:67)
	at org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation.run(RefactoringWizardOpenOperation.java:154)
	at org.eclipse.jdt.internal.ui.refactoring.actions.RefactoringStarter.activate(RefactoringStarter.java:49)
	at org.eclipse.jdt.internal.corext.refactoring.RefactoringExecutionStarter.startInferTypeArgumentsRefactoring(RefactoringExecutionStarter.java:312)
	at org.eclipse.jdt.ui.actions.InferTypeArgumentsAction.run(InferTypeArgumentsAction.java:133)
	at org.eclipse.jdt.ui.actions.SelectionDispatchAction.dispatchRun(SelectionDispatchAction.java:272)
	at org.eclipse.jdt.ui.actions.SelectionDispatchAction.run(SelectionDispatchAction.java:244)
	at org.eclipse.jface.action.Action.runWithEvent(Action.java:498)
	at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:546)
	at org.eclipse.jface.action.ActionContributionItem.access$2(ActionContributionItem.java:490)
	at org.eclipse.jface.action.ActionContributionItem$5.handleEvent(ActionContributionItem.java:402)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:66)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:938)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3682)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3293)
	at org.eclipse.jdt.internal.ui.actions.QuickMenuAction.run(QuickMenuAction.java:75)
	at org.eclipse.jface.action.Action.runWithEvent(Action.java:498)
	at org.eclipse.jface.commands.ActionHandler.execute(ActionHandler.java:119)
	at org.eclipse.core.commands.Command.executeWithChecks(Command.java:475)
	at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:429)
	at org.eclipse.ui.internal.handlers.HandlerService.executeCommand(HandlerService.java:165)
	at org.eclipse.ui.internal.keys.WorkbenchKeyboard.executeCommand(WorkbenchKeyboard.java:470)
	at org.eclipse.ui.internal.keys.WorkbenchKeyboard.press(WorkbenchKeyboard.java:821)
	at org.eclipse.ui.internal.keys.WorkbenchKeyboard.processKeyEvent(WorkbenchKeyboard.java:879)
	at org.eclipse.ui.internal.keys.WorkbenchKeyboard.filterKeySequenceBindings(WorkbenchKeyboard.java:568)
	at org.eclipse.ui.internal.keys.WorkbenchKeyboard.access$3(WorkbenchKeyboard.java:510)
	at org.eclipse.ui.internal.keys.WorkbenchKeyboard$KeyDownFilter.handleEvent(WorkbenchKeyboard.java:126)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:66)
	at org.eclipse.swt.widgets.Display.filterEvent(Display.java:1141)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:937)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:962)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:947)
	at org.eclipse.swt.widgets.Control.traverse(Control.java:3385)
	at org.eclipse.swt.widgets.Control.translateMnemonic(Control.java:3229)
	at org.eclipse.swt.widgets.Composite.translateMnemonic(Composite.java:948)
	at org.eclipse.swt.widgets.Control.translateMnemonic(Control.java:3247)
	at org.eclipse.swt.widgets.Display.translateMnemonic(Display.java:4186)
	at org.eclipse.swt.widgets.Display.filterMessage(Display.java:1155)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3289)
	at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2389)
	at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2353)
	at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2219)
	at org.eclipse.ui.internal.Workbench$4.run(Workbench.java:466)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:289)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:461)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:106)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:169)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:106)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:76)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:363)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:176)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:508)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:447)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1173)
Caused by: java.lang.UnsupportedOperationException
	at org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.WildcardType.getSubTypes(WildcardType.java:39)
	at org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.SubTypesOfSingleton.isSingleton(SubTypesOfSingleton.java:226)
	at org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet.superTypes(TypeSet.java:163)
	at org.eclipse.jdt.internal.corext.refactoring.generics.InferTypeArgumentsConstraintsSolver.maintainSimpleConstraint(InferTypeArgumentsConstraintsSolver.java:248)
	at org.eclipse.jdt.internal.corext.refactoring.generics.InferTypeArgumentsConstraintsSolver.processConstraints(InferTypeArgumentsConstraintsSolver.java:224)
	at org.eclipse.jdt.internal.corext.refactoring.generics.InferTypeArgumentsConstraintsSolver.runSolver(InferTypeArgumentsConstraintsSolver.java:201)
	at org.eclipse.jdt.internal.corext.refactoring.generics.InferTypeArgumentsConstraintsSolver.solveConstraints(InferTypeArgumentsConstraintsSolver.java:128)
	at org.eclipse.jdt.internal.corext.refactoring.generics.InferTypeArgumentsRefactoring.checkFinalConditions(InferTypeArgumentsRefactoring.java:228)
	at org.eclipse.ltk.core.refactoring.CheckConditionsOperation.run(CheckConditionsOperation.java:83)
	at org.eclipse.ltk.core.refactoring.CreateChangeOperation.run(CreateChangeOperation.java:118)
	at org.eclipse.ltk.core.refactoring.PerformChangeOperation.run(PerformChangeOperation.java:209)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:1797)
	at org.eclipse.ltk.internal.ui.refactoring.WorkbenchRunnableAdapter.run(WorkbenchRunnableAdapter.java:87)
	at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:113)
Root exception:
java.lang.UnsupportedOperationException
	at org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.WildcardType.getSubTypes(WildcardType.java:39)
	at org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.SubTypesOfSingleton.isSingleton(SubTypesOfSingleton.java:226)
	at org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet.superTypes(TypeSet.java:163)
	at org.eclipse.jdt.internal.corext.refactoring.generics.InferTypeArgumentsConstraintsSolver.maintainSimpleConstraint(InferTypeArgumentsConstraintsSolver.java:248)
	at org.eclipse.jdt.internal.corext.refactoring.generics.InferTypeArgumentsConstraintsSolver.processConstraints(InferTypeArgumentsConstraintsSolver.java:224)
	at org.eclipse.jdt.internal.corext.refactoring.generics.InferTypeArgumentsConstraintsSolver.runSolver(InferTypeArgumentsConstraintsSolver.java:201)
	at org.eclipse.jdt.internal.corext.refactoring.generics.InferTypeArgumentsConstraintsSolver.solveConstraints(InferTypeArgumentsConstraintsSolver.java:128)
	at org.eclipse.jdt.internal.corext.refactoring.generics.InferTypeArgumentsRefactoring.checkFinalConditions(InferTypeArgumentsRefactoring.java:228)
	at org.eclipse.ltk.core.refactoring.CheckConditionsOperation.run(CheckConditionsOperation.java:83)
	at org.eclipse.ltk.core.refactoring.CreateChangeOperation.run(CreateChangeOperation.java:118)
	at org.eclipse.ltk.core.refactoring.PerformChangeOperation.run(PerformChangeOperation.java:209)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:1797)
	at org.eclipse.ltk.internal.ui.refactoring.WorkbenchRunnableAdapter.run(WorkbenchRunnableAdapter.java:87)
	at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:113)
Comment 1 Faux CLA 2007-11-27 04:43:27 EST
Duplicated with older Eclipse on linux:

-- Eclipse:
Version: 3.2.1
Build id: M20060921-0945 (Debian version: 3.2.1-4)

-- Java:
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) 64-Bit Server VM (build 1.6.0-b105, mixed mode)

-- Linux:
Linux ponies 2.6.22-2-amd64 #1 SMP Thu Aug 30 23:43:59 UTC 2007 x86_64 GNU/Linux
Debian: blend of stable and testing.
Comment 2 Jerome Lanneluc CLA 2007-11-27 04:53:32 EST
Moving to JDT/UI
Comment 3 Dani Megert CLA 2008-01-28 04:48:30 EST
*** Bug 216661 has been marked as a duplicate of this bug. ***
Comment 4 Dani Megert CLA 2008-01-28 04:48:43 EST
*** Bug 190508 has been marked as a duplicate of this bug. ***
Comment 5 Dani Megert CLA 2008-01-28 04:49:40 EST
See simple test case in bug 211037 comment 0.
Comment 6 Peter Larsen CLA 2008-03-14 09:00:39 EDT
I got the same one on 

OS: xp
Version: 3.4.0
Build id: I20080222-1622
Comment 7 Markus Keller CLA 2008-05-26 12:51:02 EDT
Created attachment 102002 [details]
Fix

This only happens with a 1.6 JRE, where Object#getClass() has return type Class<?>. In 1.5, the return type was Class<? extends Object>.

The fix makes UnboundWildcardType#getSubTypes() behave like ExtendsWildcardType#getSubTypes(), which is to return the bound (java.lang.Object in this case).

Since the problem only occurs with a 1.6 JRE but our test environment has not been updated to 1.6, the regression test does not really test the broken scenario. I've opened bug 233982 to update the test framework.
Comment 8 Markus Keller CLA 2008-05-28 08:59:04 EDT
Martin, shall we fix this for RC3?
Comment 9 Martin Aeschlimann CLA 2008-05-28 11:58:04 EDT
I'd rather see a fix targeted for 'getClass'...
Comment 10 Markus Keller CLA 2008-05-29 08:56:14 EDT
Created attachment 102622 [details]
Fix 2 (fails)

Here's another fix attempt. It currently fails because of bug 234609.
Comment 11 Markus Keller CLA 2008-05-29 09:46:44 EDT
Created attachment 102635 [details]
Fix 3

> I'd rather see a fix targeted for 'getClass'...

You're right. Actually, this is a problem in the AST, see bug 234619.
This patch is a minimal workaround that only applies for getClass(). It just omits the constraint for the type parameter, which in the end leaves the class raw. This is much better than the UnsupportedOperationException.
Comment 12 Martin Aeschlimann CLA 2008-05-29 10:10:35 EDT
patch is good, +1 for 3.4 RC3
Comment 13 Benno Baumgartner CLA 2008-05-29 11:07:03 EDT
+1
Comment 14 Markus Keller CLA 2008-05-29 11:15:06 EDT
Released Fix 3.
Comment 15 Dani Megert CLA 2008-05-30 03:02:58 EDT
Verified in I20080529-1806.