Bug 176591 - [1.5][compiler] Java compiler erroneously reports a type mismatch
Summary: [1.5][compiler] Java compiler erroneously reports a type mismatch
Status: RESOLVED INVALID
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.2.2   Edit
Hardware: PC All
: P3 normal (vote)
Target Milestone: 3.3 M6   Edit
Assignee: Maxime Daniel CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-03-07 05:54 EST by Alexander Veit CLA
Modified: 2007-03-15 05:34 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Alexander Veit CLA 2007-03-07 05:54:42 EST
Build ID: Build id: M20070212-1330

Steps To Reproduce:
With compiler compliance level 5.0,

public Set<String> getTypedSet()
{
  return true ? Collections.emptySet() : null;
}

leads to "Type mismatch: cannot convert from Set<Object> to Set<String>".


More information:

public Set<String> getTypedSet()
{
  return Collections.emptySet();
}

works.
Comment 1 Maxime Daniel CLA 2007-03-07 08:35:43 EST
Reproduced with 3.3 M5eh.

javac (1.5.0_11, 6_01_b03, 7_b06) behaves as we do.

The reason is that the conditional expression prevents us to infer the type parameter for <T> Set<T> emptySet(). I'll double-check the spec.

Note that the following test case provides a workaround:
class X {
  public Set<String> getTypedSet()
  {
    return true ? Collections.<String>emptySet() : null;
  }
}

While the following fails as well:
class X {
  public Set<String> getTypedSet()
  {
    return true ? Collections.emptySet() : Collections.emptySet();
  }
}
Comment 2 Alexander Veit CLA 2007-03-07 08:44:49 EST
It's not exactly clear what's going on. Both

public Set<String> getTypedSet()
{
  if (true)
    return Collections.emptySet();
  else
    return null;
}

and

public Set<String> getTypedSet()
{
  Set<String> s;
		
  if (true)
    s = Collections.emptySet();
  else
    s = null;

  return s;
}

work.
Comment 3 Maxime Daniel CLA 2007-03-07 09:51:54 EST
In the examples of comment #2, the 'return <expression>' gives a clue that the expression should be of type Set<String>, which enables to infer the type parameter (T) as String. The same for the assignment to s.
In the initial test case, the ternary operator "filters the clue out" somehow. I will search the spec for an explanation of that point, around the rules for type inference. (Since javac behaves as we do, I would expect the spec to tell us right.) 
Comment 4 Maxime Daniel CLA 2007-03-09 14:40:08 EST
More formally, JLS 3 § 15.12.2.8 tells us that if a method, for which type inference has provided no type parameter after considering the types of the argument expressions, is in a context into which it will be subject to assignment conversion to a type S, then its parameter types are inferred using a S >> R constraint, where R stands for the method return type (it's a bit more complex than that in general, but this will do for this case). Else (if it will not be subject to assignment conversion), the type parameters are inferred 'under the assumption that the method result was assigned to a variable of type Object.'.
§ 5.2 tells us that assignment conversion occurs when an expression is assigned to a variable. It tells us nothing regarding either the return statement or the ?: conditional operator. $ 14.17 tells us that the expression of a return must assignable to the type of the enclosing method. Which tends to support the view that 'return <exp>' puts exp in a context into which it will be subject to an assignment conversion.
Having said that, nothing in the spec commands that, placing 'e1 ? e2 : e3' in a context into which it will be subject to assignment conversion to a type S implies that e2 and e3 be placed in a context into which they would be subject to assignment conversion to the said type S. While we would be tempted to make that move on simple cases, the rules given in § 15.25 that command the ?: expression type are quite complex on non-trivial cases (they can involve applying lub to capture conversions of boxing conversions). My understanding is that the spec does not require that the property 'S >> e1 ? e2 : e3 imply S >> e2 and S >> e3' be leveraged at type inference time, leaving us with Object >> e2.

Except if anything more positive can be found in the spec that would invalidate that analysis, given the fact that the reference implementation behaves as we do, I would support closing this bug as invalid.

Philippe, Kent, what do you think?
Comment 5 Maxime Daniel CLA 2007-03-15 04:22:11 EDT
Given noone vetos my proposal, closing as INVALID.
Comment 6 Philipe Mulet CLA 2007-03-15 04:54:18 EDT
Comment 4 is accurate, our behavior is mandated by the spec. Note that cast expressions are not providing clues for inference either (I am arguing about this with them already).

Maxime - can you pls add a regression test still ?
Comment 7 Maxime Daniel CLA 2007-03-15 05:34:17 EDT
Released GenericTypeTest#1109 and 1110 in HEAD.