Skip to content

@stableABI SIP. #654

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 2 commits into from
Feb 13, 2017
Merged

@stableABI SIP. #654

merged 2 commits into from
Feb 13, 2017

Conversation

DarkDimius
Copy link
Contributor

@DarkDimius DarkDimius commented Jan 13, 2017

TLDR:
This is intended to be @tailrec - like annotation that will fail compilation in case emitted methods or their signatures are different from those written by users. In order for @stableabi compatible class to succeed compilation there should be: no methods synthesized and no signatures changed.

The intended use-case is providing binary compatibility across major Scala versions by ensuring that a class or a trait is compiled as written by developer.

UPD: changed name of the annotation and the SIP.


__Dmitry Petrashko__

__first submitted 13 February 2017__
Copy link
Member

Choose a reason for hiding this comment

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

It's currently January, not February yet ;-)

@densh
Copy link
Contributor

densh commented Jan 13, 2017

This seems to be a replacement for java-defined interfaces, why not name it @interface to make crystal clear what it means? Binary compatibility is quite a broad term.

@jvican jvican requested a review from xeno-by January 13, 2017 14:44
will be compatible across major version of Scala.

## Use Cases
Dotty currently uses java defined interfaces as public API for SBT in order to ensure binary compatibility.
Copy link
Member

Choose a reason for hiding this comment

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

Actually dotty-interfaces is not used by sbt at all. dotty-sbt-bridge depends on dotty itself, and sbt will automatically compile it from source against the current version of dotty (this is nothing new, the same thing happens with the scalac sbt bridge).
However, dotty-interfaces is used by IntelliJ IDEA.

@DarkDimius
Copy link
Contributor Author

@densh, it does not only apply to interfaces. It also applies to classes.

Given that there's an assumption that this feature is rarely used and only used by advanced users, I'd prefer not to give it a common name such as @interface.

@milessabin
Copy link
Contributor

I'm not clear on the benefits of adding to the language specification for such an apparently narrow use case. Are there any concrete examples of where this might be useful other than the SBT bridge? If not then I'm not sure why a Java shim or some other ad hoc approach isn't adequate and appropriate.

FWIW, it seems that the criteria for @binaryCompatible more or less correspond to those for a direct unencoded mapping to Java language artefacts, so maybe @java would be a better name?

@DarkDimius
Copy link
Contributor Author

@milessabin thanks for your comment.

FWIW, it seems that the criteria for @binaryCompatible more or less correspond to those for a direct unencoded mapping to Java language artefacts, so maybe @java would be a better name?

Inside the bodies of methods one can use all the features of Scala, as they won't be seen in the binary API observed from outside. I think I should be explicit about it and include examples that illustrate this. Thank you for pointing this out.

@travisbrown
Copy link

👍, but also 👍 to reconsidering the name. In the cases where I've personally wanted something like this, the goal has been ease of Java interop in a multi-language codebase, not primarily binary compatibility as I think most people would understand it.

@dragos
Copy link

dragos commented Jan 14, 2017

I think this would be a very useful, but I agree with previous commenters that the name should be more specific. Something that suggests that only platform signatures are being used.

@aalleexxeeii
Copy link

Do you mean absolutely any synthetic construct? For instance, should bit-fields for lazy values be considered as those? Or stuff like MODULE$?


## Introduction ##

Scala is a language which evolves fast and thus made a decision to only promise binary compatibility across minor releases.
Copy link
Contributor

@xeno-by xeno-by Jan 17, 2017

Choose a reason for hiding this comment

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

This is a very apt description. I wonder whether there are publications/talks that provide more context on the matter.

Copy link
Contributor

@xeno-by xeno-by Jan 17, 2017

Choose a reason for hiding this comment

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

What's a minor release and what's a major release? There are different conventions that people follow in our community.

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'll add a link defining both terms. Thank you.


Scala is a language which evolves fast and thus made a decision to only promise binary compatibility across minor releases.
At the same time, there is a demand to develop APIs that live longer than a major release cycle of Scala.
This SIP introduces an annotation `@binaryCompatible` that checks that `what you write is what you get`.
Copy link
Contributor

Choose a reason for hiding this comment

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

I agree with other commenters that a different name would be beneficial. To me, saying that something is binary compatible, immediately raises the question "with what?". This annotation doesn't answer that question.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

While I agree that the @binaryCompatible name isn't perfect, I didn't yet find a better one.
As this annotation is intended to be rarely used and only by advanced users, I don't think we should concentrate that much on the name, but I welcome name suggestions.

that would be locally compiled.

There's also a use-case of defining a class which is supposed to be also used from Java.
`@binaryCompatible` will ensure that there are no not-expected methods that would show up in members of a class or an interface.
Copy link
Contributor

Choose a reason for hiding this comment

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

s/not-expected/unexpected/

As long as signatures of methods in source is not changed, `@binaryCompatible` annotated class
will be compatible across major version of Scala.

## Use Cases
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we number these use cases, i.e. have this section look as follows:

1) Use case 1 
<explanation>

2) Use case 2
<explanation>

etc


## Overview ##
In order for a class or a trait to succeed compilation with the `@binaryCompatible` annotation it has to be:
- defined on the top level;
Copy link
Contributor

@xeno-by xeno-by Jan 17, 2017

Choose a reason for hiding this comment

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

Why limit this to just top-level classes? If I recall correctly, MiMa also flags changes to nested classes and synthetic stuff generated for things like new {} and old-style lambdas.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why limit this to just top-level classes?

  1. Allowing to define @stableABI inner classes will most likely fail compilation due to second reason, as they will get successors synthesized to access the outer class;
  2. there are several subtleties in how outer class can affect compilation of inner class, eg by converting private method to public;
  3. use-case of an inner class can be easily handled by defining a top-level supper class and making inner class extend it;

In order to have a more user-friendly behavior than 1 & 2, and given presence of a simple workaround, I've decided to prohibit it.

- defined on the top level;
- use a subset of Scala that during compilation does not require changes to public API of the class, including
- synthesizing new members, either concrete or abstract;
- changing binary signatures of existing members, either concrete or abstract;
Copy link
Contributor

@xeno-by xeno-by Jan 17, 2017

Choose a reason for hiding this comment

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

Are changes to the public API of class's companion also prohibited?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added.

check which is sufficient to promise binary compatibility.

## Overview ##
In order for a class or a trait to succeed compilation with the `@binaryCompatible` annotation it has to be:
Copy link
Contributor

Choose a reason for hiding this comment

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

What about objects?


## Features that will fail compilation with `@binaryCompatible`
The features listed below have complex encodings that may change in future versions. We prefer not to compromise on them.
Most of those features can be simulated in a binary compatible way by writing a verbose re-impelemtation
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo.

- default arguments;
- default methods. See Addendum;
- constant types(both explicit and inferred);
- inline.
Copy link
Contributor

Choose a reason for hiding this comment

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

Why exclude inline?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The idea is that @stableABI classes don't need @scalaSignature or @tasty to compile against. In order for inline to work, we'll need to be able to read the trees from those sections and make assumptions about those trees, that can be dependent on compiler version.

I propose to go conservative route here, we'll have an opportunity to allow more features later, but we won't have an opportunity to remove them.

## Compilation scheme ##
No modification of typer or any existing phase is planned. The current proposed scheme introduces a late phase that runs before the very bytecode emission that checks that:
- classes and traits annotated as `@binaryCompatible` are on the top level;
- no non-private members where introduced inside classes and traits annotated as `@binaryCompatible` by compiler using phase travel;
Copy link
Contributor

Choose a reason for hiding this comment

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

What's phase travel?

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 don't think Compilation scheme section needs explanation of common terms used inside both compilers.

At the same time, there is a demand to develop APIs that live longer than a major release cycle of Scala.
This SIP introduces an annotation `@binaryCompatible` that checks that `what you write is what you get`.
It will fail compilation in case emitted methods or their signatures
are different from those written by users.
Copy link
Contributor

Choose a reason for hiding this comment

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

s/users/authors/


__first submitted 13 January 2017__

## Introduction ##
Copy link
Contributor

@xeno-by xeno-by Jan 17, 2017

Choose a reason for hiding this comment

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

I think that this document would benefit from the definitions of the following terms:

  1. Binary compatibility (both the intransitive and transitive variations used in the text below)
  2. Public API
  3. Binary signature
  4. The notion of signatures being different from those written by their authors.

I'd suggest having a small example that introduces and illustrates these notions.

@DarkDimius
Copy link
Contributor Author

@xeno-by, thank you for your through review.

As most questions are asking about definitions of terms, I think I'll introduce a new section that defines terms used in this SIP. It's indeed harder to follow than most sips as current writing assumes knowledge of both compiler internals and JVM spec.

@DarkDimius
Copy link
Contributor Author

DarkDimius commented Jan 17, 2017

Speaking of the name, I welcome suggestions. @interop is the best alternative I came up with.
My personal opinion is that the current name isn't that bad considering that this annotation is for very advanced users(framework authors) and should be rarely used.

@DarkDimius
Copy link
Contributor Author

Just had a Dotty meeting, which was also joined by @retronym.
It seems that everyone present on the meeting has converged on the name @stableABI.

@DarkDimius DarkDimius changed the title @binaryCompatible SIP. @stableABI SIP. Feb 10, 2017
@olafurpg
Copy link
Contributor

olafurpg commented Feb 10, 2017

FWIW. With @stableABI, I imagine it might become popular to release small libraries without cross compilation. A hypothetical example if Function and Tuple were to get stable ABIs, libraries such as geny could take advantage of this.

@DarkDimius
Copy link
Contributor Author

The CI seems to fail, without reporting any errors.
@heathermiller @jvican, could you please help with getting this merged?
Afaik it should be discussed tomorrow on the SIP meeting, so it would be nice to get it in.

@heathermiller
Copy link
Member

It won't be displayed even if the CI succeeds. The GitHub pages builds are also timing out and failing. So until we can move this site to chara/alaska, or fix #607, this page can't be displayed on the site.

@DarkDimius
Copy link
Contributor Author

@heathermiller, ouch. Thanks for having a look.

@jvican
Copy link
Member

jvican commented Feb 13, 2017

Hey @DarkDimius, a fix is on the way #684. When we merge it, can you rebase your changes so that Travis doesn't time out?

@jvican
Copy link
Member

jvican commented Feb 13, 2017

Can you please rebase on top of #685?

@DarkDimius
Copy link
Contributor Author

@jvican thank you for the ping. Rebased.

@jvican jvican merged commit aa988a6 into scala:master Feb 13, 2017
@xeno-by
Copy link
Contributor

xeno-by commented Feb 13, 2017

I'm a bit confused about the current name for the annotation. Is it @stableABI or @binaryCompatible? From what I can see, the PR title has been updated, but the SIP text hasn't.

@DarkDimius
Copy link
Contributor Author

@xeno-by thanks for pinging. Apperantly when fixing the repo we've rebased and merged the wrong version. #691 is the up-to-date one and the one that was reviewed in this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.