Skip to content

Allow refinements that refine already refined types. #244

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

Merged
merged 1 commit into from
Nov 26, 2014

Conversation

odersky
Copy link
Contributor

@odersky odersky commented Nov 26, 2014

Previously, a double definition errorfor T was produced in a case like this:

 type T1 = C { T <: A }
 type T2 = T1 { T <: B }

This was caused by the way T1 was treated in the refinement class
that is used to typecheck the type. Desugaring of T2 with refinedTypeToClass
would give

 trait <refinement> extends T1 { type T <: B }

and normalizeToClassRefs would transform this to:

 trait <refinement> extends C { type T <: A; type T <: B }

Hence the double definition. The new scheme desugars the rhs of T2 to:

 trait <refinement> extends C { this: T1 => type T <: B }

which avoids the problem.

Also, added tests that #232 (fix/boundsPropagation) indeed considers all refinements
together when comparing refined types.

Supersedes #243. Review by @retronym please.

Previously, a double definition errorfor `T` was produced in a case like this:

     type T1 = C { T <: A }
     type T2 = T1 { T <: B }

This was caused by the way T1 was treated in the refinement class
that is used to typecheck the type. Desugaring of T2 with `refinedTypeToClass`
would give

     trait <refinement> extends T1 { type T <: B }

and `normalizeToClassRefs` would transform this to:

     trait <refinement> extends C { type T <: A; type T <: B }

Hence the double definition. The new scheme desugars the rhs of `T2` to:

     trait <refinement> extends C { this: T1 => type T <: B }

which avoids the problem.

Also, added tests that scala#232 (fix/boundsPropagation) indeed considers all refinements
together when comparing refined types.
case tp: RefinedType if tp.argInfos.nonEmpty => tp // parameterized class type
case tp: TypeRef if tp.symbol.isClass => tp // monomorphic class type
case tp: TypeProxy => stripToCore(tp.underlying)
case _ => defn.AnyType
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this changed intentionally from Object to Any? If so, why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that was intentional. It seems that Any is the more natural parent type for a purely structural type.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I remember this coming up as a rough edge between value classes and structural types:

scala> trait T extends Any { def t }
defined trait T

scala> def foo(c: { def t} ) = c.t
warning: there was one feature warning; re-run with -feature for details
foo: (c: AnyRef{def t: Unit})Unit

scala> def test(t: T) = foo(t)
<console>:9: error: type mismatch;
 found   : t.type (with underlying type T)
 required: AnyRef{def t: Unit}
       def test(t: T) = foo(t)
                            ^

It would be interesting to experiment with changing this in scalac and running the community build to find out how compatible it is.

@retronym
Copy link
Member

LGTM.

@odersky
Copy link
Contributor Author

odersky commented Nov 26, 2014

Yes, I think the reason for AnyRef parent for structural types is historical. Structural types came before value classes and were represented as traits. Since traits could not have an Any parent then, it was logical to pick AnyRef.

odersky added a commit that referenced this pull request Nov 26, 2014
Allow refinements that refine already refined types.
@odersky odersky merged commit b18ce86 into scala:master Nov 26, 2014
OlivierBlanvillain pushed a commit to OlivierBlanvillain/dotty that referenced this pull request Dec 12, 2016
@allanrenucci allanrenucci deleted the fix/refinementTypes-v2 branch December 14, 2017 19:22
tgodzik added a commit to tgodzik/scala3 that referenced this pull request Apr 29, 2025
Backport "Fix copy of annotation on @main methods" to 3.3 LTS
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants