Skip to content

extension method involving opaque type fails #15255

@erikerlandson

Description

@erikerlandson

Compiler version

3.1.2

Minimized code

package fails {
    opaque type Fails[V] = V

    object Fails:
        def lift[V](v: V): Fails[V] = v

        extension[V](f: Fails[V])
            def value: V = f

    // defining this method at same level as opaque type `Fails` will not work
    extension[V](v: V)
        def asFails: Fails[V] = Fails.lift(v)
}

Output

Welcome to Scala 3.1.2 (11.0.15, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.
                                                                                                                                                                                                                
scala> import coulomb.fails.*
                                                                                                          
// lifting using "asFails" method yields a strange type with "quantity$package" in it  
// the type should be "coulomb.fails.Fails[Int]" - see next example                                                                                                    
scala> val f = 7.asFails
val f: coulomb.fails.quantity$package.Fails[Int] = 7
                                                                                                                                
// invoking the "value" method causes a failure                                                                                
scala> f.value
-- [E008] Not Found Error: -----------------------------------------------------
1 |f.value
  |^^^^^^^
  |value value is not a member of coulomb.fails.quantity$package.Fails[Int]
1 error found
                                                                                                      
// lifting this way will work - note the correct type                                                                                                          
scala> val f2 = Fails.lift(7)
val f2: coulomb.fails.Fails[Int] = 7
                                                                            
// value method works:                                                                                                                                    
scala> f2.value
val res0: Int = 7

Expectation

I would expect both "asFail" and "Fail.lift" to work correctly and "value" method to work correctly

For comparison, defining the external lifter at a different level will work properly:

package works {
    opaque type Works[V] = V

    object Works:
        def lift[V](v: V): Works[V] = v

        extension[V](w: Works[V])
            def value: V = w

    object syntax:
        // defining external lift in subobject "syntax" does work
        extension[V](v: V)
            def asWorks: Works[V] = Works.lift(v)
}
Welcome to Scala 3.1.2 (11.0.15, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.
                                                                                                                                                                                                                
scala> import coulomb.works.*, coulomb.works.syntax.*
                                                                                                                                                                                                                
scala> val w = 7.asWorks
val w: coulomb.works.Works[Int] = 7
                                                                                                                                                                                                                
scala> w.value
val res0: Int = 7
                                                                                                                                                                                                                
scala> val w2 = Works.lift(7)
val w2: coulomb.works.Works[Int] = 7
                                                                                                                                                                                                                
scala> w2.value
val res1: Int = 7

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions