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

Disallow private opaque type aliases #14666

Merged
merged 6 commits into from Mar 14, 2022
Merged

Conversation

odersky
Copy link
Contributor

@odersky odersky commented Mar 11, 2022

Fixes #14660

odersky and others added 4 commits March 11, 2022 10:14
Co-authored-by: Jamie Thompson <bishbashboshjt@gmail.com>
A private opaque type alias is equivalent to a private type alias
@prolativ
Copy link
Contributor

prolativ commented Mar 11, 2022

Opaque types whose usage is limited to the scope where they are defined (and where they are not seen as opaque) indeed seem to make no sense so they can be disabled. But I think it makes sense to allow scoped private access like this

trait Foo:
  class Bar:
    private[Foo] opaque type Baz = Int
    
  def foo: Bar#Baz

Even when the current changes from this PR are applied the code snippet above crashes the compiler. Instead this should compile successfully.
Not sure about the situation when we make it private[Bar]. This seems equivalent to private without a scope modifier.

@adampauls
Copy link
Contributor

Sorry for butting in, why do private opaque types make no sense? Suppose I have a private method checkFoo(foo: Foo): CheckedFoo that checks an invariant and I want the compiler to make sure I never accidentally pass an unchecked Foo into a method expecting a CheckedFoo. Doesn't it seem reasonable to use an opaque type for this case? And if Foo itself private, won't trying to make a public type alias fail to compile because it leaks info about Foo?

@odersky
Copy link
Contributor Author

odersky commented Mar 11, 2022

@adampauls The idea is that private opaque gives you nothing extra over what private gives you.

@adampauls
Copy link
Contributor

It does remove the compiler's ability to type check for you right? private def acceptsFoo(foo: CheckedFoo) will compile if I pass a regular Foo to it?

@odersky
Copy link
Contributor Author

odersky commented Mar 11, 2022

@adampauls That's true whether Foo is opaque or not.

The hidden test is unreliable after typer, since we cannot guarantee that the
current owner is accurate.
@odersky
Copy link
Contributor Author

odersky commented Mar 11, 2022

We also needed to fix a problem when merging denotations with hidden symbols

The hidden test is unreliable after typer, since we cannot guarantee that the
current owner is accurate. This addresses the pos test.

@odersky
Copy link
Contributor Author

odersky commented Mar 11, 2022

In fact, to fix #14660, only the last commit is necessary. Forbidding private opaque combinations is optional. But I think it makes sense to do so, since opaque is redundant for private aliases.

@adampauls
Copy link
Contributor

adampauls commented Mar 11, 2022

Thanks, sorry I did not carefully RTFM. I had thought from a first read that the scope of transparency was the companion object of the type alias. If I want to make the equivalent of a private opaque type CheckedFoo = Foo, I can do

private object CheckedFooScope {
   opaque type CheckedFoo = Foo
   object CheckedFoo {
     def apply(foo: Foo): CheckedFoo = foo
   }
}
import CheckedFooScope.CheckedFoo

@@ -51,6 +51,8 @@ object o:
def id(x: o.T): o.T = x
```

Opaque type aliases cannot be `private` and cannot be overridden in subclasses.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should point out that private[OuterScope] is allowed however.
Another thing that might not be very clear here is that one can define an abstract type and then override (or implement) it with an opaque type

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that could be elsewhere, maybe in a tutorial. The doc here is a spec and conciseness is good. If we say however it can be private[X] the we'd have to go to all other places where we say private and include or exclude private X.

Copy link
Contributor

Choose a reason for hiding this comment

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

If it's consistent across the docs that private[Scope] is not private then it's OK

@prolativ prolativ assigned odersky and unassigned prolativ Mar 14, 2022
@odersky odersky merged commit 83fb072 into scala:main Mar 14, 2022
@odersky odersky deleted the fix-14660 branch March 14, 2022 11:12
@Kordyjan Kordyjan added this to the 3.1.3 milestone Aug 1, 2023
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.

Private opaque type in class
5 participants