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

Failed type inference when path dependent types are used as type arguments #9469

Closed
scabug opened this issue Sep 14, 2015 · 7 comments
Closed
Assignees
Milestone

Comments

@scabug
Copy link

scabug commented Sep 14, 2015

I don't know if this is the right place to report it, but this code demonstrates an issue when path dependent types are used as type parameters for generic types:

	trait SubtypeOf[+T] {
		type Type <: T
	}

	def SubtypeOf[T] :SubtypeOf[T] = new SubtypeOf[T] { type Type = T }

	case class Owned[+P<:Owner](next :Option[P#R])

	class Owner {
		type This = this.type
		val R = SubtypeOf[Owned[This]]
		type R = R.Type

		def next(o :Owned[this.type]) :Owned[This] = o.next.get
	}

	object Owner extends Owner

	def compiles(o :Owned[Owner.type]) :Owned[Owner.type] = o.next.get

	def fails(o :Owned[Owner.type]) :Owned[Owner.type] = o.next.get.next.get

	def fix(o :Owned[Owner.type]) :Owned[Owner.type] = (o.next.get :Owned[Owner.type]).next.get

This is not as academic as it might look, the code is derived from an attempt to create 'type boxes' grouping declarations of related types. So Owned is in fact a couple of dozen classes forming a component tree, where properties of those classes can be of types declared by passed Owner. This way one can duplicate a component hierarchy to add minor changes by simply overriding a type definition in Owner. SubtypeOf is a workaround to allow 'overridable covariant type declarations', so that adding a new component hierarchy would require only overriding changed types, instead of defining all types from scratch.

@scabug
Copy link
Author

scabug commented Sep 14, 2015

Imported From: https://issues.scala-lang.org/browse/SI-9469?orig=1
Reporter: Marcin Mościcki (mmoscicki)
Affected Versions: 2.11.7
See #6161, #5294

@scabug
Copy link
Author

scabug commented Sep 16, 2015

@retronym said:
Here's the -Ytyper-debug trace for failed:

|    |    |-- o.next.get.next.get : pt=Test.Owned[Test.Owner.type] EXPRmode (site: method fails in Test2)
|    |    |    |-- o.next.get.next EXPRmode-POLYmode-QUALmode (site: method fails in Test2)
|    |    |    |    |-- o.next.get EXPRmode-POLYmode-QUALmode (site: method fails in Test2)
|    |    |    |    |    |-- o.next EXPRmode-POLYmode-QUALmode (site: method fails in Test2)
|    |    |    |    |    |    |-- o EXPRmode-POLYmode-QUALmode (site: method fails in Test2)
|    |    |    |    |    |    |    \-> o.type (with underlying type Test.Owned[Test.Owner.type])
|    |    |    |    |    |    \-> o.next.type (with underlying type Option[_2.R.Type forSome { val _2: Test.Owner.type }])
|    |    |    |    |    \-> _2.R.Type
|    |    |    |    \-> Option[_2.R.Type forSome { val _2: P }]
|    |    |    [search #1] start `=> A`, searching for adaptation to pt=_2.R.Type => Test.Owned[Test.Owner.type] (silent: method fails in Test2) implicits disabled
|    |    |    [search #2] start `=> A`, searching for adaptation to pt=(=> _2.R.Type) => Test.Owned[Test.Owner.type] (silent: method fails in Test2) implicits disabled
sandbox/test2.scala:3: error: type mismatch;
 found   : _2.R.Type where val _2: P
 required: Test.Owned[Test.Owner.type]
  def fails(o: Owned[Owner.type]): Owned[Owner.type] = o.next.get.next.get

This might well be the same bug as #5294

@scabug
Copy link
Author

scabug commented Sep 16, 2015

@retronym said:
A variation I tried (that also failed)

object Test {
  trait SubtypeOf[+T] {
    type Type <: T
  }

  class Owned[+P <: Owner with Singleton](val next: Option[P#R])

  class Owner {
    type This <: Owner with Singleton
    val R = SubtypeOf[Owned[This]]
    type R = R.Type

    def next(o: Owned[this.type]): Owned[This] = o.next.get
  }

  object Owner extends Owner {
    type This = this.type
  }

  def SubtypeOf[T]: SubtypeOf[T] = new SubtypeOf[T] { type Type = T }

  def compiles(o: Owned[Owner.type]): Owned[Owner.type] = o.next.get

  def fails(o: Owned[Owner.type]): Owned[Owner.type] = o.next.get.next.get

  def fix(o: Owned[Owner.type]): Owned[Owner.type] = (o.next.get: Owned[Owner.type]).next.get
}

@scabug
Copy link
Author

scabug commented Sep 16, 2015

@retronym said:
Indeed, both variants compile with my as-yet unmerged patch for #5294. I'm going to merge these tickets, and then see about merging that patch (IIRC it revealed a latent bug elsewhere in the compiler which also needs to be fixed... sigh)

scala/scala@f8a5551#commitcomment-11806426

@scabug scabug closed this as completed Sep 16, 2015
@scabug
Copy link
Author

scabug commented Nov 8, 2015

@paulp said:
You are correct, though the bug wasn't exactly latent. It is the bug underlying #6161. More to come elsewhere.

@scabug
Copy link
Author

scabug commented Nov 8, 2015

@retronym said (edited on Nov 9, 2015 12:07:39 AM UTC):
IIRC, the latent bug I was referring to was the subject of the second commit of scala/scala@2.12.x...retronym:ticket/5294, which was found by bootstrapping under the first commit.

@scabug
Copy link
Author

scabug commented Nov 9, 2015

@paulp said:
Ah. I was referring to the bug which causes the test failures still present.

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