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

Try fix #1786: support use package object as value #1787

Merged
merged 1 commit into from
Dec 14, 2016

Conversation

liufengyun
Copy link
Contributor

Try fix #1786: support use package object as value.

@sjrd
Copy link
Member

sjrd commented Dec 13, 2016

Does this still prevent

val m = scala.meta

? Is there a neg test somewhere against that?

@liufengyun
Copy link
Contributor Author

Thanks @sjrd . We auto convert scala.meta to scala.meta.package when it's used as a value?

@sjrd
Copy link
Member

sjrd commented Dec 13, 2016

My point is: val m = scala.meta should not be allowed. But if you directly apply it, as in val m = scala.meta { something }, then it's equivalent to calling val m = scala.meta.apply { something }, and that should be allowed.

val m = scala.meta should not be allowed because it would be inconsistent whether the package has a package object or not. For example, if package foo.bar does not have a package object, then val b = foo.bar is technically unimplementable, so must be forbidden. For consistency, so should it be forbidden when foo.bar has a package object.

@DarkDimius
Copy link
Contributor

@liufengyun we already have checks that ensure that java static classes cannot be assigned to variables or passed as arguments. We can use the same infrastructure as restrictions on package are the same.

@liufengyun
Copy link
Contributor Author

If we allow scala.meta { something } but disallow val m = scala.meta, it seems to break hierarchical typing. It also has consistency issue, as we allow both meta { ... } and val m = meta.

if package foo.bar does not have a package object, then val b = foo.bar is technically unimplementable

What if we only do the auto conversion if the package object indeed exists?

@sjrd
Copy link
Member

sjrd commented Dec 13, 2016

What if we only do the auto conversion if the package object indeed exists?

That's precisely what I am against, because it's ultra-inconsistent.

as we allow both meta { ... } and val m = meta

That's not normal. val m = meta shouldn't be allowed either if meta is a package or package object.

As @DarkDimius pointed out, the same kind of restrictions apply to Java static objects, so hierarchical typing is already broken (and has been since the dawn of time).

@liufengyun
Copy link
Contributor Author

Got it, thanks @sjrd @DarkDimius . I'll update the PR soon.

@odersky
Copy link
Contributor

odersky commented Dec 13, 2016

val m = scala.meta should not be allowed because it would be inconsistent whether the package has a package object or not. For example, if package foo.bar does not have a package object, then val b = foo.bar is technically unimplementable, so must be forbidden. For consistency, so should it be forbidden when foo.bar has a package object.

I tend to agree with this point of view. What is the motivation for allowing package objects as values?

@odersky
Copy link
Contributor

odersky commented Dec 13, 2016

Note that I think you can get the package object

foo.bar.package

as a value. That's OK, as this is a real object. By contrast.

foo.bar

is the package, which contains all members of the package object and all members defined in the package. If I write

val m = foo.bar

There's no way that afterwards m.C would select a class defined in package foo.bar bit missing from foo.bar.package.

So I think we should not allow packages which have package objects as values.

@liufengyun
Copy link
Contributor Author

@odersky The motivation is following code:

package object meta {
  def apply(x: Int): Int = x * x
}

class Test {
  def f = meta { 5 + 4 }
}

Of course, scala.meta could define a method def meta(x: Int): Int, but it doesn't look very nice.

I see the argument for against use package object as value. What about just adapt foo.bar {...} to foo.bar.package.apply {...} in the context of application, while disallow other usages?

@odersky
Copy link
Contributor

odersky commented Dec 13, 2016 via email

@liufengyun
Copy link
Contributor Author

Thanks for the tip @odersky , that's an incredibly simple fix! It's done now.

I didn't notice ctx.makePackageObjPrefixExplicit. I thought we have to manually adapt scala.meta {...} to scala.meta.package {...} before the apply adaption.

@odersky
Copy link
Contributor

odersky commented Dec 14, 2016

LGTM

@odersky odersky merged commit 19bc03c into scala:master Dec 14, 2016
@liufengyun liufengyun deleted the fix-i1786 branch December 14, 2016 15:16
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.

Use package object as value
4 participants