anchor.diff:  }
   --------------------------------------
   
  -==== Java-inspired changes (under investigation)
  -
  -The following are being explored as candidate changes for Groovy 4:
  -
  -* Switch expressions
  -link:https://openjdk.java.net/jeps/354[JEP 354: Switch Expressions (Second Preview)]
  -link:https://openjdk.java.net/jeps/361[JEP 361: Switch Expressions]
  +An example of guarded patterns being considered for Java:
  +
  +[source,java]
  +--------------------------------------
  +static void testTriangle(Shape s) {
  +    switch (s) {
  +        case null ->
  +            System.out.println("Null!");
  +        case Triangle t && (t.calculateArea() > 100) ->
  +            System.out.println("Large triangle");
  +        case Triangle t ->
  +            System.out.println("Small triangle");
  +        default ->
  +            System.out.println("Non-triangle");
  +    }
  +}
  +--------------------------------------
  +
  +Another destructuring example:
  +
  +[source,java]
  +--------------------------------------
  +int eval(Expr n) {
  +     return switch(n) {
  +         case IntExpr(int i) -> i;
  +         case NegExpr(Expr n) -> -eval(n);
  +         case AddExpr(Expr left, Expr right) -> eval(left) + eval(right);
  +         case MulExpr(Expr left, Expr right) -> eval(left) * eval(right);
  +         default -> throw new IllegalStateException();
  +     };
  +}
  +--------------------------------------
  +
  +We should consider the currently proposed nested record pattern when exploring our
  +destructuring options, e.g.:
  +
  +[source,java]
  +--------------------------------------
  +static void printColorOfUpperLeftPoint(Rectangle r) {
  +    if (r instanceof Rectangle(ColoredPoint(Point p, Color c), ColoredPoint lr)) {
  +        System.out.println(c);
  +    }
  +}
  +--------------------------------------
  +
  +=== Other Java-inspired enhancements
   
   * Module definitions written in Groovy (i.e. module-info.groovy)
   link:https://issues.apache.org/jira/browse/GROOVY-9273[GROOVY-9273]
  
positive.code: === Legacy package removal
  
  The Java Platform Module System (JPMS) requires that classes in distinct modules
  have distinct package names. Groovy has its own "modules" but these haven't
  historically been structured according to the above requirement.
  
  Groovy 3 provided duplicate versions of numerous classes (in old and new packages)
  to allow Groovy users to migrate towards the new JPMS compliant package names.
  See the link:http://groovy-lang.org/releasenotes/groovy-3.0.html#Groovy3.0releasenotes-Splitpackages[Groovy 3 release notes]
  for more details.
  In short, time to stop using `groovy.util.XmlSlurper` and start using `groovy.xml.XmlSlurper`.
  Similarly, you should now be using `groovy.xml.XmlParser`, `groovy.ant.AntBuilder`, `groovy.test.GroovyTestCase`
  and the other classes mentioned in the prior mentioned Groovy 3 release notes.
  
negative.code: The range will exclude the left or right-most values for such ranges.
  link:https://issues.apache.org/jira/browse/GROOVY-9649[GROOVY-9649]
  
  === JSR308 improvements (incubating)
  
  Groovy has been improving JSR-308 support over recent versions.
  In Groovy 4.0, additional support has been added. In particular,
  type annotations are now supported on generic types. This is useful
  for users of tools like the link:https://jqwik.net/[Jqwik] property-based testing library
  and technologies like the link:https://beanvalidation.org/2.0/[Bean Validation 2] framework.
  Here is an example of a Jqwik test:
  
  [source,groovy]
  --------------------------------------
  @Grab('net.jqwik:jqwik:1.5.1')
  import net.jqwik.api.*
  import net.jqwik.api.constraints.*
  
  class PropertyBasedTests {
      @Property
      def uniqueInList(@ForAll @Size(5) @UniqueElements List<@IntRange(min = 0, max = 10) Integer> aList) {
          assert aList.size() == aList.toSet().size()
          assert aList.every{ anInt -> anInt >= 0 && anInt <= 10 }
      }
  }
  --------------------------------------
  
  In earlier versions of Groovy, the `@Forall`, `@Size`, and `@UniqueElements` annotations
  were handled, but the `@IntRange` annotation on the `List` generic type didn't appear in the
  generated bytecode and now does.
  
  Here is a Bean Validation 2 framework example:
  
  [source,groovy]
  --------------------------------------
  @Grab('org.hibernate.validator:hibernate-validator:7.0.1.Final')
  @Grab('org.hibernate.validator:hibernate-validator-cdi:7.0.1.Final')
  @Grab('org.glassfish:jakarta.el:4.0.0')
  import jakarta.validation.constraints.*
  import jakarta.validation.*
  import groovy.transform.*
  
  @Canonical
  class Car {
      @NotNull @Size(min = 2, max = 14) String make
      @Min(1L) int seats
      List<@NotBlank String> owners
  }
  
  def validator = Validation.buildDefaultValidatorFactory().validator
  
  def violations = validator.validate(new Car(make: 'T', seats: 1))
  assert violations*.message == ['size must be between 2 and 14']
  
  violations = validator.validate(new Car(make: 'Tesla', owners: ['']))
  assert violations*.message.toSet() == ['must be greater than or equal to 1', 'must not be blank'] as Set
  
  violations = validator.validate(new Car(make: 'Tesla', owners: ['Elon'], seats: 2))
  assert !violations
  --------------------------------------
  
  Again, all annotations except the `@NonBlank` annotation on the `List` generic type
  were previously supported, and now `@NonBlank` will appear in the bytecode too.
  
  This feature is marked as incubating. The generated bytecode is not expected to change
  but some minor details of the AST representation of the annotations during compilation
  may change slightly before the feature leaves incubating status.
  
  In addition, type annotations that appear in code,
  e.g. local variable types, cast expression types, catch block exception types,
  are still work in progress.
  
  [[Groovy4.0-ongoing]]
  == On-going work
  
  === Enhanced switch (under investigation)
  
  Groovy has always had a very powerful switch statement.
  The statement could be made more powerful, e.g. support destructuring,
  and could be supported in contexts where expressions are expected.
  
  As inspiration, Java has made, or is investigating future enhancements
  including switch expressions and other related enhancements:
  link:https://openjdk.java.net/jeps/354[JEP 354: Switch Expressions (Second Preview)]
  link:https://openjdk.java.net/jeps/361[JEP 361: Switch Expressions]
  link:https://openjdk.java.net/jeps/405[JEP 405: Record Patterns & Array Patterns (Preview)]
  link:https://openjdk.java.net/jeps/406[JEP 406: Pattern Matching for switch (Preview)]
  We should investigate these proposals both in terms of enhancing the existing Groovy switch
  but also in terms of deciding which syntax from Java we might like to support in the future.
  
  Other languages like Python are also improving their switch statements:
  https://www.python.org/dev/peps/pep-0622/[PEP 622 -- Structural Pattern Matching].
  We should investigate whether any features of their design make sense for Groovy's dynamic nature.
  
  As an example of destructuring, instead of the following existing code:
  
  [source,groovy]
  --------------------------------------
  