Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

manifests + intersection types violate val-binding abstraction #4110

Closed
scabug opened this issue Dec 24, 2010 · 4 comments
Closed

manifests + intersection types violate val-binding abstraction #4110

scabug opened this issue Dec 24, 2010 · 4 comments
Assignees

Comments

@scabug
Copy link

scabug commented Dec 24, 2010

=== What steps will reproduce the problem (please be specific and use wikiformatting)? ===

I expect that code such as

  func(<expression>)

should always be equivalent to

  val name = <expression>
  func(name)

(in the abscence of call-by-name arguments)

but this can be violated by manifests and intersection types:

scala> def inferredType[T : Manifest](v : T) = manifest[T]
inferredType: [T](v: T)(implicit evidence$$1: Manifest[T])Manifest[T]

scala> trait A
defined trait A

scala> trait B                                            
defined trait B

scala> inferredType(new A with B)
res0: scala.reflect.Manifest[_ <: java.lang.Object with A with B] = $$anon$$1

scala> val name = new A with B
name: java.lang.Object with A with B = $$anon$$1@88e83d

scala> inferredType(name)        
res1: Manifest[java.lang.Object with A with B] = Object with A with B

=== What is the expected behavior? ===
the manifest that is passed in as an implicit parameter should match the inferred type eg:

scala> inferredType(new A with B)
res0: Manifest[java.lang.Object with A with B] = Object with A with B

=== What do you see instead? ===
A manifest for a anonymous class.

=== Why is this relevant? ===
a Manifest for a anonymous type fails to capture some type system features, eg:

scala> trait Parametrized[T]  
defined trait Parametrized

scala> trait Mixin 
defined trait Mixin

scala> val obj = new AnyRef
obj: java.lang.Object = java.lang.Object@1172fb9

scala> inferredType(new Parametrized[obj.type] with Mixin)
res2: scala.reflect.Manifest[_ <: java.lang.Object with Parametrized[obj.type] with Mixin] = $$anon$$1

a Manifest for the anonymous class doesn't capture the singleton type

=== What versions of the following are you using? ===

  • Scala: 2.8.1
  • Java: NI
  • Operating system: NI
@scabug
Copy link
Author

scabug commented Dec 24, 2010

Imported From: https://issues.scala-lang.org/browse/SI-4110?orig=1
Reporter: AlexK (alexk)

@scabug
Copy link
Author

scabug commented Jan 6, 2011

@adriaanm said:
test case:

object Test extends Application {
  def inferredType[T : Manifest](v : T) = println(manifest[T])

  trait A
  trait B
  inferredType(new A with B)

  val name = new A with B
  inferredType(name)
}

the relevant fragment (abridged) after typer (with -Ydebug -uniqid):
(note the type argument to inferredType in the very first line!)

    inferredType[anonymous class $$anon$$13406]({
      final class $$anon$$13406 extends Object with A with B ;
      new $$anon$$13406.this()
    })(Manifest.classType[anonymous class $$anon$$13406](classOf[Test$$$$<local Test>$$$$anon]));

    private[this] val name: Object with A with B{} = {
      final class $$anon$$9257 extends Object with A with B ;
      new $$anon$$9257.this()
    };
    inferredType[Object with A with B{}](name)(Manifest.intersectionType[Object with A with B{}](Manifest.Object, Manifest.classType[A](classOf[Test$$$$A]), Manifest.classType[B](classOf[Test$$$$B])))

question: is the symbol $$anon$$13406 supposed to be in scope in inferredType's type argument??
(probably not)

@scabug
Copy link
Author

scabug commented Jan 6, 2011

@adriaanm said:
note that the existentials from the original report stem from the REPL -- replaying his transcript with debugging output:

val res0: Manifest[$$anon$$34941] forSome { type $$anon$$34941 <: Object with A with B{} } = 
  inferredType[anonymous class $$anon$$34870]({
      final class $$anon$$34870 extends Object with A with B
      new $$anon$$34870.this()
    })(Manifest.classType[anonymous class $$anon$$34870](classOf[line4$$object$$$$$$iw$$$$iw$$res0 $$$$anon]));

the RHS is essentially the same as in a full scalac run, but the computed type for res0 is packed to get rid of the reference to the anonymous class

Martin, I'm reassigning to you for a hint or two on how to tackle this

@scabug
Copy link
Author

scabug commented Jun 27, 2011

Commit Message Bot (anonymous) said:
(extempore in r25161) Don't infer anonymous classes. The type is widened as little as
possible, just far enough to avoid all kinds of undesirable consequences
which accompany the preservation of too much type information. (The
problems are akin to inferring the singleton type too freely.)

// Example of code which did not compile, but now does
class A
class B[T <: A](cons: T)
object C extends B(new A {})

Closes #4110, #3048. I already ran this by moors, so review by odersky.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants