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

GADT parameter ordering is not recorded during registration #15868

Open
Linyxus opened this issue Aug 16, 2022 · 0 comments
Open

GADT parameter ordering is not recorded during registration #15868

Linyxus opened this issue Aug 16, 2022 · 0 comments

Comments

@Linyxus
Copy link
Contributor

Linyxus commented Aug 16, 2022

If we have a function def[A <: B]foo(...) = ..., the ordering A <: B are not properly recorded if B has been instantiated. Instead, A <: B will be recorded as a /non-param bound/ of A.

Compiler version

The main branch

Minimized code

enum Tag[A]:
  case Data[A]() extends Tag[A]

def foo0[A](e: Tag[A]) = e.match {
  case _: Tag.Data[a] =>

    def bar[C >: Int <: a]() =
      val t1: a = 0  // fails
}

def foo1[A, C >: Int <: A]() =
  val t1: A = 0  // works

Output

-- [E007] Type Mismatch Error: issues/gadt-inst-dep.scala:8:18 -------------------------------------------------------------------------------------------------------------------------------------------
8 |      val t1: a = 0  // fails
  |                  ^
  |                  Found:    (0 : Int)
  |                  Required: a
  |
  |                  where:    a is a type in method foo0 which is an alias of A
  |
  | longer explanation available when compiling with `-explain`

Expectation

The code should compile without error.

In foo0 and foo1 we introduce the type parameter C with bounds >: Int <: a (or A). In foo1 the ordering between C and A is properly handled (so the bound >: Int gets propagated to A), but it is not the case in foo0. The main difference between foo0 and foo1 is that a in foo0 has been instantiated.

The reason why the ordering is not recorded in foo0 is that when processing the newly-defined type parameter C, the OrderingConstraint class will check whether a is a constrained parameter by calling constraint.contains(a). However, since the a has been instantiated and the related type lambda gets removed in the constraint, constraint.contains(a) returns false. So OrderingConstraint will keep a in the non-param bounds of C, without recording the orderings.

This is an issue discovered while developing #14754. #14754 already contains a fix for this issue that tries to check whether a has been instantiated and strips the type variable to its instance if possible. See this commit.

@Linyxus Linyxus added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Aug 16, 2022
@dwijnand dwijnand added area:gadt stat:needs triage Every issue needs to have an "area" and "itype" label and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Aug 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants