Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 337181 - [inline] returned value is not cast
Summary: [inline] returned value is not cast
Status: RESOLVED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.7   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: 3.7 M6   Edit
Assignee: Deepak Azad CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-02-15 00:59 EST by Deepak Azad CLA
Modified: 2011-02-26 02:01 EST (History)
1 user (show)

See Also:


Attachments
fix+tests (14.93 KB, patch)
2011-02-23 06:47 EST, Deepak Azad CLA
no flags Details | Diff
final fix + tests (18.18 KB, patch)
2011-02-26 02:01 EST, Deepak Azad CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Deepak Azad CLA 2011-02-15 00:59:09 EST
HEAD

-Inline foo()
- Expected: long much = (long) (1+1) * Integer.MAX_VALUE;
- Actual: long much = (1+1) * Integer.MAX_VALUE;
------------------------------------------------------------------
package p;

class A {
	void x() {
		long much = foo() * Integer.MAX_VALUE;
	}

	private long foo() {
		return 1 + 1;
	}
}
------------------------------------------------------------------

See also InlineTempTests#test36, InlineConstantTests#test32.
Comment 1 Deepak Azad CLA 2011-02-22 02:13:47 EST
The following also does not work
---------------------------------------------------------------------
package p;

class A {
    void x() {
        int a= foo().intValue();
        System.out.println(foo().intValue());
    }

    private Integer foo() {
        return 1 + 1;
    }    
}
---------------------------------------------------------------------

The code is not very smart..see CallInliner.needsExplicitCast(RefactoringStatus)
Comment 2 Markus Keller CLA 2011-02-22 06:42:59 EST
> The code is not very smart..see
> CallInliner.needsExplicitCast(RefactoringStatus)

Yes, it should use ASTNodes#getExplicitCast(Expression, Expression).
Comment 3 Deepak Azad CLA 2011-02-22 07:03:49 EST
(In reply to comment #2)
> Yes, it should use ASTNodes#getExplicitCast(Expression, Expression).
Yup, but even this is not perfect. See bug 337815.
Comment 4 Markus Keller CLA 2011-02-22 08:19:30 EST
> > Yes, it should use ASTNodes#getExplicitCast(Expression, Expression).
> Yup, but even this is not perfect. See bug 337815.

Nobody's perfect, but a least it's correct ;-)
[BTW: Unfortunately, the verb "cast" is irregular and the past is also "cast"]
Comment 5 Deepak Azad CLA 2011-02-23 06:47:37 EST
Created attachment 189588 [details]
fix+tests

Initially I just used ASTNodes#getExplicitCast(Expression, Expression) in CallInliner.needsExplicitCast(RefactoringStatus). This caused InlineMethodTests.testParameterizedType1() and InlineMethodTests.testParameterizedType2() to fail. My change resulted in an unnecessary cast in these cases. 

The problem is in Bindings.isSuperType(ITypeBinding, ITypeBinding, boolean), which does not really handle type arguments. My changes in Bindings.isSuperType(..) fix the failures in testParameterizedType1() and testParameterizedType2() and ALLJDTTests suite is green with this. But I am not sure if the changes are perfect, and also if the failures were legitimate, something like bug 337815 where we need the cast in some cases.
Comment 6 Markus Keller CLA 2011-02-24 14:25:52 EST
Bummer! We've opened Pandora's box.

InlineMethodTests.testParameterizedType1() can easily be translated into an equivalently failing test for Inline Local Variable:

        Vector<? extends Number> inline= new Vector<Integer>();
        Vector<? extends Number> var= inline;

Let me think a bit more on how to best proceed, but the changes in Bindings#isSuperType() are not OK.

This isn't about supertypes in the classical sense any more. I think we shouldn't touch the legacy isSuperType(.., .., true) any more and let it die (i.e. replace references whenever we need to fix something). These changes only make sense for TypeRules#canAssign(..), so the fixes should also go there.
This area is very complicated since generics cam into play, so any new code should be backed by references to the JLS3 that tell why the code is correct.
E.g. I don't buy the recursive isSuperType(..) calls on the type arguments (because e.g. a List<Integer> is not assignable to a List<Number>).


The changes in CallInliner are mostly fine. Only "parent.getNodeType() == ASTNode.METHOD_INVOCATION" is redundant here and should be removed:

ASTNode parent= fTargetNode.getParent();
if (parent.getNodeType() == ASTNode.METHOD_INVOCATION &&
    fTargetNode.getLocationInParent() == MethodInvocation.ARGUMENTS_PROPERTY) {
Comment 7 Markus Keller CLA 2011-02-25 15:25:06 EST
I've fixed the problems in TypeRules#canAssign(..) with bug 338271.

You can release your patch with the fix in CallInliner but without releasing Bindings.
Comment 8 Deepak Azad CLA 2011-02-26 02:01:11 EST
Created attachment 189875 [details]
final fix + tests

(In reply to comment #7)
> I've fixed the problems in TypeRules#canAssign(..) with bug 338271.
Thanks Markus!
 
> You can release your patch with the fix in CallInliner but without releasing
> Bindings.
Done, with few additional tests.
Comment 9 Deepak Azad CLA 2011-02-26 02:01:40 EST
Fixed in HEAD.