groovy

Need to supply hand-crafted constructor for enum having >1 field

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Minor Minor
  • Resolution: Won't Fix
  • Affects Version/s: 1.6.3
  • Fix Version/s: 1.7.5, 1.8-beta-2
  • Component/s: Compiler
  • Labels:
    None
  • Environment:
    Win7 / java 1.6.0_14
  • Number of attachments :
    0

Description

enum T {
  ALPHA(1, 2),
  BETA(3, 4),
  GAMMA(5, 6)
	
  def x
  def y
	
  @Override
  public String toString() {
    "{x: $x, y: $y}"
  }
}
	
println T.ALPHA

Didn’t work! Imagine my surprise! Gives:

Caught: java.lang.ExceptionInInitializerError
	at Test.class$(Test.groovy)
	at Test.$get$$class$T(Test.groovy)
	at Test.run(Test.groovy:20)

I tried a Groovy style constructor with named parameters:

enum T {
  ALPHA(x: 1, y: 2),
  BETA(x: 3, y: 4),
  GAMMA(x: 5, y: 6)
	
  def x
  def y
	
  @Override
  public String toString() {
    "{x: $x, y: $y}"
  }
}
	
println T.ALPHA

Didn’t work. One gets an almighty compiler error:

Information:Compilation completed with 1 error and 0 warnings
Information:1 error
Information:0 warnings
Error:BUG! exception in phase 'class generation' in source unit 'C:UsersBobDesktopAlexMaterialsrcTest.groovy' MapEntryExpression should not be visited here at
 org.codehaus.groovy.classgen.AsmClassGenerator.visitMapEntryExpression(AsmClassGenerator.java:3058)at
 org.codehaus.groovy.ast.expr.MapEntryExpression.visit(MapEntryExpression.java:37)at
 org.codehaus.groovy.classgen.AsmClassGenerator.visitAndAutoboxBoolean(AsmClassGenerator.java:4029)at
 org.codehaus.groovy.classgen.AsmClassGenerator.makeCallSite(AsmClassGenerator.java:1955)at
 org.codehaus.groovy.classgen.AsmClassGenerator.makeCall(AsmClassGenerator.java:1789)at
 org.codehaus.groovy.classgen.AsmClassGenerator.makeCall(AsmClassGenerator.java:1775)at
 org.codehaus.groovy.classgen.AsmClassGenerator.visitStaticMethodCallExpression(AsmClassGenerator.java:2334)at
 org.codehaus.groovy.ast.expr.StaticMethodCallExpression.visit(StaticMethodCallExpression.java:43)at
 org.codehaus.groovy.classgen.AsmClassGenerator.visitAndAutoboxBoolean(AsmClassGenerator.java:4029)at
 org.codehaus.groovy.classgen.AsmClassGenerator.visitCastExpression(AsmClassGenerator.java:1701)at
 org.codehaus.groovy.classgen.AsmClassGenerator.assignmentCastAndVisit(AsmClassGenerator.java:3968)at
 org.codehaus.groovy.classgen.AsmClassGenerator.evaluateEqual(AsmClassGenerator.java:3920)at
 org.codehaus.groovy.classgen.AsmClassGenerator.visitBinaryExpression(AsmClassGenerator.java:1324)at
 org.codehaus.groovy.ast.expr.BinaryExpression.visit(BinaryExpression.java:49)at
 org.codehaus.groovy.classgen.AsmClassGenerator.visitAndAutoboxBoolean(AsmClassGenerator.java:4029)at
 org.codehaus.groovy.classgen.AsmClassGenerator.visitExpressionStatement(AsmClassGenerator.java:1305)at
 org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:40)at
 org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:38)at
 org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:129)at
 org.codehaus.groovy.classgen.AsmClassGenerator.visitBlockStatement(AsmClassGenerator.java:665)at
 org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:52)at
 org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClassCodeContainer(ClassCodeVisitorSupport.java:73)at
 org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitConstructorOrMethod(ClassCodeVisitorSupport.java:80)at
 org.codehaus.groovy.classgen.AsmClassGenerator.visitStdMethod(AsmClassGenerator.java:542)at
 org.codehaus.groovy.classgen.AsmClassGenerator.visitConstructorOrMethod(AsmClassGenerator.java:518)at
 org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitMethod(ClassCodeVisitorSupport.java:88)at
 org.codehaus.groovy.classgen.AsmClassGenerator.visitMethod(AsmClassGenerator.java:622)at
 org.codehaus.groovy.ast.ClassNode.visitContents(ClassNode.java:1004)at
 org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClass(ClassCodeVisitorSupport.java:48)at
 org.codehaus.groovy.classgen.AsmClassGenerator.visitClass(AsmClassGenerator.java:243)at
 org.codehaus.groovy.control.CompilationUnit$10.call(CompilationUnit.java:717)at
 org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:924)at
 org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:462)at
 org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:443)at
 org.jetbrains.groovy.compiler.rt.MyCompilationUnits.compile(MyCompilationUnits.java:52)at
 org.jetbrains.groovy.compiler.rt.GroovycRunner.main(GroovycRunner.java:188)

It was just a guess/attempt...but was sort of 'logical'.

One HAS to supply a constructor:

enum T {
  ALPHA(1, 2),
  BETA(3, 4),
  GAMMA(5, 6)
	
  T(x, y) {
    this.x = x
    this.y = y
  }
	
  def x
  def y
	
  @Override
  public String toString() {
    "{x: $x, y: $y}"
  }
}
	
println T.ALPHA

It flies! Viz:

{x: 1, y: 2}

SO: a minor problem, with a workaround...but a surprise, nonetheless.

Not very 'groovy' though!

And not documented

I have written up a bit more (some alternative tests) at http://www.transentia.com.au/flatpress/index.php/2009/07/06/the-perils-of-being-a-smarty-pants/

Is this a regression of GROOVY-3276 ?

Issue Links

Activity

Hide
Roshan Dawrani added a comment -

What you have reported as a working example (the last one) in your JIRA is what was reported as the issue in GROOVY-3276. So, it was fixed that time and as per your JIRA, is working still. So, no regression there.

Anyway, I don't agree with your surprise number 1. I surely think that a constructor should be provided. However, if I were to guess (earlier), I would have guessed that 2nd one would work (constructor with named parameters).

Show
Roshan Dawrani added a comment - What you have reported as a working example (the last one) in your JIRA is what was reported as the issue in GROOVY-3276. So, it was fixed that time and as per your JIRA, is working still. So, no regression there. Anyway, I don't agree with your surprise number 1. I surely think that a constructor should be provided. However, if I were to guess (earlier), I would have guessed that 2nd one would work (constructor with named parameters).
Hide
alpheratz added a comment -

hmm?

Groovy classes gets a map-based default constructor supplied so that one doesn't need to hand-craft them.

I was expecting the same convenience with the enums, thus I didn't consider/understand 3276 to be fixed...

Maybe we should treat this as an enhancement request, then...rather than a bug: to support a groovy-style, automatic named parameters constructor.

Show
alpheratz added a comment - hmm? Groovy classes gets a map-based default constructor supplied so that one doesn't need to hand-craft them. I was expecting the same convenience with the enums, thus I didn't consider/understand 3276 to be fixed... Maybe we should treat this as an enhancement request, then...rather than a bug: to support a groovy-style, automatic named parameters constructor.
Hide
Roshan Dawrani added a comment -

3276 is not about named parameters. So, it is not about map-based default constructor. Issue reported in 3276 was that even if an enum had a constructor that accepted multiple parameters, the compiler was cribbing when an instance was created with those parameters (but without named parameters anywhere in the picture).

I would have also assumed that named parameters based constructor call would go through for enums as it does for regular classes. But that is about your 2nd surprise reported. To me also, that enhancement would make sense.

Your surprise #1 does not make much sense to me because even with regular classes, that convenience is not there.

class T {
	def x
	def y

	public String toString() {
	"{x: $x, y: $y}"
	}
}

new T(1, 2) // fails saying no matching constructor found
Show
Roshan Dawrani added a comment - 3276 is not about named parameters. So, it is not about map-based default constructor. Issue reported in 3276 was that even if an enum had a constructor that accepted multiple parameters, the compiler was cribbing when an instance was created with those parameters (but without named parameters anywhere in the picture). I would have also assumed that named parameters based constructor call would go through for enums as it does for regular classes. But that is about your 2nd surprise reported. To me also, that enhancement would make sense. Your surprise #1 does not make much sense to me because even with regular classes, that convenience is not there.
class T {
	def x
	def y

	public String toString() {
	"{x: $x, y: $y}"
	}
}

new T(1, 2) // fails saying no matching constructor found
Hide
Roshan Dawrani added a comment -

Only thing common between 3276 and 3613 is that both are about enums having more than 1 parameter in constructor but let, that alone, not mislead you about the underlying issue.

Show
Roshan Dawrani added a comment - Only thing common between 3276 and 3613 is that both are about enums having more than 1 parameter in constructor but let, that alone, not mislead you about the underlying issue.
Hide
alpheratz added a comment -

You are correct: I was wrong in getting excited about situation 1.

Thanks for taking the time to review this with me.

How do I/we progress the enhancement? make a new Jira request?

Show
alpheratz added a comment - You are correct: I was wrong in getting excited about situation 1. Thanks for taking the time to review this with me. How do I/we progress the enhancement? make a new Jira request?
Hide
Roshan Dawrani added a comment -

Since 1st issue you reported is not valid and 2nd is "as designed" as of now, I think it would be better if you open a separate enhancement JIRA for the 2nd part.

it would give the groovy-designers to have a clear look at the enhancement being requested and evaluate it.

Show
Roshan Dawrani added a comment - Since 1st issue you reported is not valid and 2nd is "as designed" as of now, I think it would be better if you open a separate enhancement JIRA for the 2nd part. it would give the groovy-designers to have a clear look at the enhancement being requested and evaluate it.

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved: