[ 
https://issues.apache.org/jira/browse/GROOVY-10844?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17635489#comment-17635489
 ] 

Eric Milles edited comment on GROOVY-10844 at 12/27/22 3:48 PM:
----------------------------------------------------------------

Please provide a complete script (preferable) or project to demonstrate the 
issue.

Update: I had to make some guesses here.  I added a cast to the result of 
{{convertToRef}} and 3.0.14 STC is happy.  Otherwise, it does not like 
{{recover}} producing {{Ref.Uri}}.  4.0.7 runs fine without the cast.
{code:groovy}
@Grab('io.vavr:vavr:0.10.4')
import io.vavr.control.Try

interface Attachment {}
abstract class Ref {
  static class File extends Ref {
  }
  static class Uri extends Ref {
  }
}
class Spec {
  Attachment toAttachment(Ref ref) {
    println ref
    return null
  }
}

Map process(value) {
  return [foo:'bar']
}
// Is the return type here Ref or Ref.File?
Ref.File convertToRef(Map map) {
  return new Ref.File()
}

@groovy.transform.TypeChecked
def test(initialValue) {
  Spec spec = []
  Try.success(initialValue)
    .mapTry { process(it) }
    .map { (Ref) convertToRef(it) } // Ref.File extends Ref
    .recover { new Ref.Uri(/*it.href*/) } // Ref.Uri extends Ref -- "it" is 
Throwable
    .map(spec::toAttachment)
}

print test(null)
{code}


was (Author: emilles):
Please provide a complete script (preferable) or project to demonstrate the 
issue.

Update: I had to make some guesses here.  I added a cast to the result of 
{{convertToRef}} and STC is happy.  Otherwise, it does not like {{recover}} 
producing {{Ref.Uri}}.
{code:groovy}
@Grab('io.vavr:vavr:0.10.4')
import io.vavr.control.Try

interface Attachment {}
abstract class Ref {
  static class File extends Ref {
  }
  static class Uri extends Ref {
  }
}
class Spec {
  Attachment toAttachment(Ref ref) {
    println ref
    return null
  }
}

Map process(value) {
  return [foo:'bar']
}
// Is the return type here Ref or Ref.File?
Ref.File convertToRef(Map map) {
  return new Ref.File()
}

@groovy.transform.TypeChecked
def test(initialValue) {
  Spec spec = []
  Try.success(initialValue)
    .mapTry { process(it) }
    .map { (Ref) convertToRef(it) } // Ref.File extends Ref
    .recover { new Ref.Uri(/*it.href*/) } // Ref.Uri extends Ref -- "it" is 
Throwable
    .map(spec::toAttachment)
}

print test(null)
{code}

> STC mis-tracks generics in type hierarchy
> -----------------------------------------
>
>                 Key: GROOVY-10844
>                 URL: https://issues.apache.org/jira/browse/GROOVY-10844
>             Project: Groovy
>          Issue Type: Bug
>          Components: Static compilation, Static Type Checker
>    Affects Versions: 4.0.6
>            Reporter: Christopher Smith
>            Assignee: Eric Milles
>            Priority: Critical
>
> I have a Vavr {{Try}} pipeline of this form:
> {code:groovy}
> class AttachmentSpec {
>   // fields
>   Attachment toAttachment(Ref ref) { ... }
> }
> Try.success(initialValue)
>   .mapTry { process(it) } // returns a Map
>   .map { convertToRef(it) } // returns a Ref.File extends Ref
>   .recover { new Ref.Uri(it.href) } // Ref.Uri extends Ref
>   .map(spec::toAttachment)
> {code}
> On a failure in {{process}}, this pipeline should enter {{recover}} and 
> supply a {{Ref.Uri}}, then do the final {{map}}. However, this fails with a 
> {{ClassCastException: cannot convert Ref.Uri to Ref.File}}. Apparently, the 
> compiler infers {{Ref.Uri}} as the return value from the first {{map}} (which 
> is legitimate), but then it fails to produce a compile-time error when 
> {{recover}} presents a then-incompatible {{Ref.File}}. The compiler should 
> either (ideally) recognize that the desired type is superclass {{Ref}} or, 
> more simply but at least correctly, produce a compile-time error until a type 
> witness is inserted (and observed).



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to