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

Problem inferring type parameter with Manifest context bound #4653

Closed
scabug opened this issue May 26, 2011 · 3 comments
Closed

Problem inferring type parameter with Manifest context bound #4653

scabug opened this issue May 26, 2011 · 3 comments
Assignees

Comments

@scabug
Copy link

scabug commented May 26, 2011

Remove the Manifest bound and the following code compiles, inferring the type argument to A to be Int. With the Manifest bound, it does not compile because the type argument to A is inferred to be Nothing.

object Test {
 case class A[T: Manifest](t: String)
 case class V[T](t: T)
 case class B[T](a: A[T]) { def x(v: V[T]): C[T] = C(a,v) }
 case class C[T](a: A[T], v: V[T])

 implicit def aToB[T](a: A[T]): B[T] = B(a)

 A("a") x V(3)
}

The error message is:

error: value x is not a member of test.A[Nothing]
	A("a") x V(3)
               ^
one error found

Changing Manifest to be another type constructor with an implicit in scope compiles:

object Test {
  case class Z[T](t: T)
  implicit def qq: Z[Int] = new Z(4)

  case class A[T: Z](t: String)
  ...
}

as does making the type parameter to A and V covariant:

case class A[+T: Manifest](t: String)
case class V[+T](t: T)
case class B[T](a: A[T]) { def x[T1 >: T](v: V[T1]): C[T1] = C(a,v) }

Unfortunately, I cannot make the type parameter for A covariant in the actual code.

@scabug
Copy link
Author

scabug commented May 26, 2011

Imported From: https://issues.scala-lang.org/browse/SI-4653?orig=1
Reporter: @harrah
Affected Versions: 2.9.0

@scabug
Copy link
Author

scabug commented Jun 15, 2011

@adriaanm said (edited on Jun 15, 2011 10:47:36 AM UTC):
I'm afraid this is an enhancement rather than a bug. Implicit views and implicit search do not chain this way. In the version with the manifest bound, the A("a") must be fully adapted (i.e., the implicit value for the manifest found), before the rest of the expression is even considered.

When you remove the manifest bound, the T type parameter survives as an undetermined type parameter until the x method call is type checked and its argument determines T to be Int. However, we don't delay the manifest search in the same way (though technically we could -- afaik, the spec is silent on the details).

The "delayed manifest search" interpretation would be more complicated to implement, as I think it would require the context tracking undetermined manifests along with the undetermined type parameters.

The implicit search for Manifest[T] and Z[T] are different in the sense that the qq implicit determines the T type parameter, whereas the manifest cannot be determined until the x method call has been type checked fully.

Concretely, the version with the manifest is more precisely approximated by

 case class Z[T](t: T)
 implicit def qq[T]: Z[T] = error("")
  
 case class A[T: Z](t: String)

As a workaround, can you push down the manifest bound to the definition of x and C?

object Test {
 case class A[T](t: String)
 case class V[T](t: T)
 case class B[T](a: A[T]) { def x(v: V[T])(implicit mani: Manifest[T]): C[T] = C(a,v) }
 case class C[T: Manifest](a: A[T], v: V[T])

 implicit def aToB[T](a: A[T]): B[T] = B(a)

 A("a") x V(3)
}

ps: I don't think your covariant variant achieves what you hoped for:

Test.this.aToB[T](Test.this.A.apply[Nothing]("a")(reflect.this.Manifest.Nothing)).x[Any](Test.this.V.apply[Int](3))

@scabug
Copy link
Author

scabug commented Jun 15, 2011

@adriaanm said:
Closed as duplicate of the enhancement that I'll open to describe the generalised problem.

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