Skip to content

Conversation

jrose-apple
Copy link
Contributor

We're committing to this as a forwards-compatible format, and in most cases probably backwards-compatible as well! Break it apart from the AST/SIL swiftmodule format, give it its own version number, and…probably not have any problems, because there's nothing complicated here.

@jrose-apple
Copy link
Contributor Author

@nkcsgexi, @akyrtzi, are you ready to commit to this? It's not important until textual interfaces are done, but it will be at that point. Is the current format something you're willing to use for the foreseeable future? (With additions allowed, plus careful changes.)

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test source compatibility

@nkcsgexi
Copy link
Contributor

Could you provide more context why do we need this version number while it's both forward and backward compatible?

@jrose-apple
Copy link
Contributor Author

SWIFTDOC_VERSION_MINOR isn't really important for forwards/backwards-compatibility, but it gives you the option to conditionalize behavior based on which version of the compiler generated the file. (For example, maybe in a newer format, an absent record indicates that a decl should be omitted from the generated interface, while in the older format it just means it has no comment.)

SWIFTDOC_VERSION_MAJOR is important in case you really do have to break compatibility some day. I suspect it won't actually go up at all, but if it does then how the rest of the file is processed can be conditionalized on the major version number.

This format is basically semantic versioning, but a file format isn't exactly the same thing as an API, so I didn't mention semver by name in the doc comment.

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 254efcdde0abafb05d3880b3fe945b3fbdefac4e

@nkcsgexi
Copy link
Contributor

Thanks for the clarification! Can we derive SWIFTDOC_VERSION_MINOR from the complier/module format version we're using rather than maintaining it separately? Does this change also imply that all tooling invocation should also specify SWIFTDOC_VERSION_MAJOR?

///
/// Be very careful when changing this block; it must remain stable. Adding new
/// records is okay---they will be ignored---but modifying existing ones must be
/// done carefully. You may need to update the version when you do so.
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the effect of adding a new 'field' at the end of an existing record, could you clarify it in the comments ?
Can we determine how many fields a record has at deserialization so we don't have to update and check for a version number ?

Copy link
Contributor Author

@jrose-apple jrose-apple Sep 21, 2018

Choose a reason for hiding this comment

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

You can kind of do that – see https://github.com/apple/swift/blob/bae3964c07a976ee0978c0c2400e23e3252e60e8/lib/Serialization/ModuleFile.cpp#L200-L216 – but BCRecordLayout doesn't support it. You have to read records manually in that case. Adding new records isn't really that expensive, though, so I don't think it's too much of a problem to do that instead.

For a stable format, the version number is supposed to be higher-level than just "did I change something". If it makes no difference, it's fine not to update it (and if you really don't want to use it, we could just drop the "minor" version entirely).

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 it's good that you added the minor version, as an extra thing we may find useful to check, I'm mainly trying to understand if we should update it when adding a new field.

Adding a new field would force us to switch to fully manually reading the record ? Would we be able to do a check and switch to using a different BCRecordLayout to deserialize that record, and could this check occur without needing to update the minor version ?

Pointing in the documentation to the example that you gave on how to manually check for the number of fields would be useful.

Copy link
Contributor Author

@jrose-apple jrose-apple Sep 21, 2018

Choose a reason for hiding this comment

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

It's unfortunately worse than that: adding a new field will break existing tools, because BCRecordLayout currently asserts that the number of fields matches exactly.

https://github.com/apple/swift-llvm/blob/4c0d911601d0effc3bb1881473853a0065b7cafb/include/llvm/Bitcode/RecordLayout.h#L261

We could change that, of course, or add a new API readIgnoringTrailingFields or something, but the point is that you can only add new fields if there aren't existing tools expecting a fixed number of fields.

///
/// Increment this value when making a backwards-compatible change that might
/// be interesting to test for. However, if old swiftdoc files are fully
/// compatible with the new change, you do not need to increment this.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm probably reading this paragraph wrong but it seems to contradict itself, could you rephrase for clarify, are you making a distinction between "backwards-compatible" and "fully compatible" ? If yes I'd recommend to define in details (and maybe with some examples) what you mean by each.

@jrose-apple
Copy link
Contributor Author

Thanks for the clarification! Can we derive SWIFTDOC_VERSION_MINOR from the complier/module format version we're using rather than maintaining it separately?

Unfortunately no. The goal here is to have a version number for a format that's stable across compiler versions. The binary swiftmodule format definitely isn't.

Does this change also imply that all tooling invocation should also specify SWIFTDOC_VERSION_MAJOR?

I'm not quite sure what you're asking here. The way the version checks are written, all our tools are compiled with exactly one expected major version for any swiftdoc they read. If that version ever changes, we'll have to decide how the new tools handle the differing major versions, but the old tools will correctly reject the newer generated files.

(It's also theoretically possible to decide what version to use when generating the file—say, if a user doesn't use any complicated features—but that's probably not something you'll need, especially since the way your deserialization is written will already ignore records it doesn't understand.)

@akyrtzi
Copy link
Contributor

akyrtzi commented Sep 21, 2018

@jrose-apple thanks so much for doing this! My main concern is for DocFormat.h to contain documentation with crystal clear instructions and directions on how to make changes and maintain compatibility, it should have no ambiguities.

@nkcsgexi
Copy link
Contributor

I'm not quite sure what you're asking here. The way the version checks are written, all our tools are compiled with exactly one expected major version for any swiftdoc they read. If that version ever changes, we'll have to decide how the new tools handle the differing major versions, but the old tools will correctly reject the newer generated files.

ah, so the versioning is entirely transparent to compiler clients like sourcekitd, and its purpose is to separate the evolution of doc-serialization with compiler and module format because in practice it's way more stable, right?

@jrose-apple
Copy link
Contributor Author

jrose-apple commented Sep 21, 2018

ah, so the versioning is entirely transparent to compiler clients like sourcekitd, and its purpose is to separate the evolution of doc-serialization with compiler and module format because in practice it's way more stable, right?

Yep, that sounds right to me!

My main concern is for DocFormat.h to contain documentation with crystal clear instructions and directions on how to make changes and maintain compatibility, it should have no ambiguities.

Agreed. I'll add more comments based on the discussions we're having now (once they've mostly wrapped up).

@jrose-apple jrose-apple force-pushed the stable-view branch 2 times, most recently from e40652e to ab731b8 Compare October 5, 2018 17:44
@jrose-apple
Copy link
Contributor Author

@akyrtzi @nkcsgexi How does this look?

@swift-ci Please smoke test

@jrose-apple jrose-apple force-pushed the stable-view branch 2 times, most recently from d8da38a to bc4fffd Compare October 5, 2018 18:26
@jrose-apple
Copy link
Contributor Author

@swift-ci Please smoke test

Copy link
Contributor

@akyrtzi akyrtzi left a comment

Choose a reason for hiding this comment

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

Love the detailed documentation!

Extract the common utilities into a SerializerBase class, and make a
new DocSerializer.
The functionality change in this commit is that the control block in a
swiftdoc file is validated rather than just being ignored. Tests in
following commit.
We're committing to this as a forwards-compatible format, and in most
cases probably backwards-compatible as well!
BCRecordLayout currently assumes that the layout described in source
always matches the layout in the bitstream being read. Since we want
swiftdocs to be a forward-compatible format, avoid using it for
deserialization.

(In the future, we may want to augment BCRecordLayout to handle
records with more fields than expected. For now, though, this is a
sufficient change.)
@jrose-apple
Copy link
Contributor Author

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 254efcdde0abafb05d3880b3fe945b3fbdefac4e

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 254efcdde0abafb05d3880b3fe945b3fbdefac4e

@jrose-apple jrose-apple merged commit 25c19bb into swiftlang:master Oct 24, 2018
@jrose-apple jrose-apple deleted the stable-view branch October 24, 2018 15:33
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.

4 participants