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

Inference of Dependent Function Types gives "Unspecified Error" #5526

Closed
b-studios opened this issue Nov 27, 2018 · 3 comments
Closed

Inference of Dependent Function Types gives "Unspecified Error" #5526

b-studios opened this issue Nov 27, 2018 · 3 comments

Comments

@b-studios
Copy link
Contributor

The following code example leads to an "unspecified error":

trait A
  
def foo[E](f: (a: A) => (a.type, E)): E = {
  val a = new A {}
  f(a)._2
}

foo { a => (a, ()) }

It does type check when annotating the call to foo:

foo[Unit] { a => (a, ()) }

Also, removing the dependent function type from foo does typecheck:

def foo[E](f: (a: A) => (A, E)): E 

This might be related to #4130, but extracted to a separate issue since it might be fixable, independently.

@b-studios
Copy link
Contributor Author

Here is part of the problem analysis, cross-posted at #4130:

I tried to understand the problem a bit better and learnt the following things:

  • the unspecified error is raised here in Typer
  • The check has been introduced long before path-dependent function types existed
  • checking whether the following tree is fully defined fails:
    scala AppliedType(TypeRef(...,class Tuple2),List(TermRef(NoPrefix,val a), TypeVar(TypeParamRef(E))))
    However, this is not a problem when replacing a.type in (a: A) => (a.type, E) by A to yield (a: A) => (A, E).

Further analysis showed that it goes back to Namer.

While typechecking the non-dependent variant of foo takes the case of TypedSplice(tpt) and isFullyDefined fails, the dependent variant falls into DependentTypeTree.

I am currently preparing a fix and will open a PR soon

@b-studios
Copy link
Contributor Author

The fix I had in mind was to call typedAheadExpr in Namer, i.e.

case DependentTypeTree(tpFun) =>
  val tpe = tpFun(paramss.head)
  if (!isFullyDefined(tpe, ForceDegree.none)) {
    typedAheadExpr(mdef.rhs, tpe).tpe
  } else {
    tpe
  }

However, it is not general enough. The following example still does not typecheck:

trait F[A, -E]
def empty[A](value: A): F[A, Any] = ???

def hof[R](f: (p: AnyRef) => F[R, p.type]): F[R, Any] = ???

hof { p =>
  empty(42)
}

Again, annotating hof[Int] or dropping the path dependent type allows successful type checking.

@odersky
Copy link
Contributor

odersky commented Dec 17, 2018

With ff284d4 the second test case checks as well. Not sure what caused this, though. Maybe the increased force degree in Typer?

odersky added a commit that referenced this issue Dec 17, 2018
Fix #5526: Better type inference for dependent function types
nicolasstucki pushed a commit to dotty-staging/dotty that referenced this issue Jan 5, 2019
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

3 participants