diff --git a/Cargo.lock b/Cargo.lock index cedf44be85bda..ac0e6e9db969f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -282,7 +282,7 @@ dependencies = [ "cargo-test-support", "clap", "core-foundation", - "crates-io", + "crates-io 0.31.1", "crossbeam-utils 0.7.2", "crypto-hash", "curl", @@ -680,6 +680,21 @@ dependencies = [ "url 2.1.0", ] +[[package]] +name = "crates-io" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65949ecc100abd1df7d80740ee58afb599f2447c5011bbf5acb5a039a67607ca" +dependencies = [ + "anyhow", + "curl", + "percent-encoding 2.1.0", + "serde", + "serde_derive", + "serde_json", + "url 2.1.0", +] + [[package]] name = "crc32fast" version = "1.1.2" @@ -2376,6 +2391,18 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quickcheck" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44883e74aa97ad63db83c4bf8ca490f02b2fc02f92575e720c8551e843c945f" +dependencies = [ + "env_logger 0.7.1", + "log", + "rand 0.7.3", + "rand_core 0.5.1", +] + [[package]] name = "quine-mc_cluskey" version = "0.2.4" @@ -4170,6 +4197,24 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "semverver" +version = "0.1.46" +dependencies = [ + "anyhow", + "cargo", + "crates-io 0.32.0", + "curl", + "env_logger 0.7.1", + "log", + "quickcheck", + "rand 0.7.3", + "rustc-workspace-hack", + "semver 0.9.0", + "serde", + "serde_json", +] + [[package]] name = "serde" version = "1.0.99" diff --git a/Cargo.toml b/Cargo.toml index be15e50e2bcca..59ff0d06afe2c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ members = [ "src/tools/rustdoc-themes", "src/tools/unicode-table-generator", "src/tools/expand-yaml-anchors", + "src/tools/semverver", ] exclude = [ "build", @@ -69,6 +70,9 @@ cargo = { path = "src/tools/cargo" } # `rustfmt` executable are the same exact version). rustfmt-nightly = { path = "src/tools/rustfmt" } +# Cargo again but from `crates.io` (semverver uses that instead of a git dependency). +cargo = { path = "src/tools/cargo" } + # See comments in `src/tools/rustc-workspace-hack/README.md` for what's going on # here rustc-workspace-hack = { path = 'src/tools/rustc-workspace-hack' } diff --git a/config.toml.example b/config.toml.example index 2fa613755d64c..26e22a7ff6b56 100644 --- a/config.toml.example +++ b/config.toml.example @@ -207,7 +207,7 @@ # Installs chosen set of extended tools if `extended = true`. By default builds all. # If chosen tool failed to build the installation fails. If `extended = false`, this # option is ignored. -#tools = ["cargo", "rls", "clippy", "rustfmt", "analysis", "src"] +#tools = ["cargo", "rls", "clippy", "rustfmt", "analysis", "src", "semverver"] # Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose #verbose = 0 diff --git a/rustfmt.toml b/rustfmt.toml index c76a75fa07bb0..028c067dc3b27 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -30,6 +30,7 @@ ignore = [ "src/tools/rust-analyzer", "src/tools/rust-installer", "src/tools/rustfmt", + "src/tools/semverver", # We do not format this file as it is externally sourced and auto-generated. "src/libstd/sys/cloudabi/abi/cloudabi.rs", diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 3cbecbbaa06cb..8764d3e23ee81 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -372,6 +372,9 @@ impl<'a> Builder<'a> { tool::Rustdoc, tool::Clippy, tool::CargoClippy, + tool::Semverver, + tool::SemverPublic, + tool::CargoSemver, native::Llvm, native::Sanitizers, tool::Rustfmt, @@ -380,7 +383,7 @@ impl<'a> Builder<'a> { native::Lld ), Kind::Check | Kind::Clippy | Kind::Fix | Kind::Format => { - describe!(check::Std, check::Rustc, check::Rustdoc, check::Clippy) + describe!(check::Std, check::Rustc, check::Rustdoc, check::Clippy, check::Semverver) } Kind::Test => describe!( crate::toolstate::ToolStateCheck, @@ -426,6 +429,7 @@ impl<'a> Builder<'a> { test::RustdocJSNotStd, test::RustdocTheme, test::RustdocUi, + test::Semverver, // Run bootstrap close to the end as it's unlikely to fail test::Bootstrap, // Run run-make last, since these won't pass without make on Windows diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 0d38d2eebe793..9b209915b2f2f 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -196,11 +196,13 @@ macro_rules! tool_check_step { } tool_check_step!(Rustdoc, "src/tools/rustdoc", SourceType::InTree); -// Clippy is a hybrid. It is an external tool, but uses a git subtree instead -// of a submodule. Since the SourceType only drives the deny-warnings -// behavior, treat it as in-tree so that any new warnings in clippy will be -// rejected. +// Clippy and semverver are hybrids. They're external tools, but use git subtrees +// instead of submodules. Since the SourceType only drives the deny-warnings +// behavior, treat it as in-tree so that any new warnings will be rejected. tool_check_step!(Clippy, "src/tools/clippy", SourceType::InTree); +// FIXME(eddyb) use `InTree` here as per the comment above, when Cargo can build +// with deny-warnings + `-Wrust_2018_idioms` (which it can't today). +tool_check_step!(Semverver, "src/tools/semverver", SourceType::Submodule); /// Cargo's output path for the standard library in a given stage, compiled /// by a particular compiler for the specified target. diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 77bcc00d75b2b..cb4ed39528e90 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -559,6 +559,45 @@ impl Step for Clippy { } } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Semverver { + stage: u32, + host: Interned, +} + +impl Step for Semverver { + type Output = (); + const ONLY_HOSTS: bool = true; + const DEFAULT: bool = false; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/semverver") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(Semverver { stage: run.builder.top_stage, host: run.target }); + } + + /// Runs `cargo test` for semverver. + fn run(self, builder: &Builder<'_>) { + let stage = self.stage; + let host = self.host; + let compiler = builder.compiler(stage, host); + + builder + .ensure(tool::CargoSemver { compiler, target: self.host, extra_features: Vec::new() }) + .expect("in-tree tool"); + builder + .ensure(tool::Semverver { compiler, target: self.host, extra_features: Vec::new() }) + .expect("in-tree tool"); + builder + .ensure(tool::SemverPublic { compiler, target: self.host, extra_features: Vec::new() }) + .expect("in-tree tool"); + + // FIXME(eddyb) actually run tests from `src/tools/semverver`. + } +} + fn path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString { // Configure PATH to find the right rustc. NB. we have to use PATH // and not RUSTC because the Cargo test suite has tests that will diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 450b534d5dfdb..7dbb0f8ebf0b5 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -237,6 +237,7 @@ pub fn prepare_tool_cargo( || path.ends_with("clippy") || path.ends_with("miri") || path.ends_with("rustfmt") + || path.ends_with("semverver") { cargo.env("LIBZ_SYS_STATIC", "1"); features.push("rustc-workspace-hack/all-static".to_string()); @@ -604,6 +605,7 @@ macro_rules! tool_extended { |tools| { tools.iter().any(|tool| match tool.as_ref() { "clippy" => $tool_name == "clippy-driver", + "semverver" => $tool_name == "rust-semverver", x => $tool_name == x, }) }), @@ -659,6 +661,11 @@ tool_extended!((self, builder), }; Rustfmt, rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, {}; RustAnalyzer, rust_analyzer, "src/tools/rust-analyzer/crates/rust-analyzer", "rust-analyzer", stable=false, {}; + // FIXME(eddyb) use `in_tree=true` for semverver, when Cargo can build + // with deny-warnings + `-Wrust_2018_idioms` (which it can't today). + CargoSemver, semverver, "src/tools/semverver", "cargo-semver", stable=false, {}; + Semverver, semverver, "src/tools/semverver", "rust-semverver", stable=false, {}; + SemverPublic, semverver, "src/tools/semverver", "rust-semver-public", stable=false, {}; ); impl<'a> Builder<'a> { diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh index b4b23a245e0aa..fc13b3b492e05 100755 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh @@ -23,4 +23,4 @@ set -e # debugging: print out the saved toolstates cat /tmp/toolstate/toolstates.json python3 "$X_PY" test check-tools -python3 "$X_PY" test src/tools/clippy +python3 "$X_PY" test src/tools/clippy src/tools/semverver diff --git a/src/tools/semverver/.github/workflows/ci.yml b/src/tools/semverver/.github/workflows/ci.yml new file mode 100644 index 0000000000000..e1addbb824348 --- /dev/null +++ b/src/tools/semverver/.github/workflows/ci.yml @@ -0,0 +1,37 @@ +name: CI + +on: + pull_request: + types: [opened, synchronize, reopened] + push: + branches: + - master + +jobs: + build_and_test: + strategy: + fail-fast: false + matrix: + toolchain: + - x86_64-unknown-linux-gnu + - x86_64-apple-darwin + - x86_64-pc-windows-msvc + include: + - toolchain: x86_64-unknown-linux-gnu + builder: ubuntu-latest + os: linux + - toolchain: x86_64-apple-darwin + builder: macos-latest + os: macos + - toolchain: x86_64-pc-windows-msvc + builder: windows-latest + os: windows + + name: nightly - ${{ matrix.toolchain }} + runs-on: ${{ matrix.builder }} + + steps: + - uses: actions/checkout@v2 + + - name: Run tests + run: sh ci/run.sh ${{ matrix.os }} diff --git a/src/tools/semverver/.github/workflows/style.yml b/src/tools/semverver/.github/workflows/style.yml new file mode 100644 index 0000000000000..1adab1560eae0 --- /dev/null +++ b/src/tools/semverver/.github/workflows/style.yml @@ -0,0 +1,40 @@ +name: Style check + +on: + pull_request: + types: [opened, synchronize, reopened] + push: + branches: + - master + +jobs: + style_check: + strategy: + fail-fast: false + + name: Shellcheck + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Run tests + run: | + shellcheck --version + shellcheck ci/*.sh + + - name: Update nightly + run: | + rustup update nightly + + - name: rustfmt + run: | + if rustup component add rustfmt; then + cargo fmt --all -- --check + fi + + - name: Clippy + run: | + if rustup component add clippy rustc-dev; then + cargo clippy --all + fi diff --git a/src/tools/semverver/.gitignore b/src/tools/semverver/.gitignore new file mode 100644 index 0000000000000..2a2e51bd2b66a --- /dev/null +++ b/src/tools/semverver/.gitignore @@ -0,0 +1,5 @@ +target/ +**/*.rs.bk +Cargo.lock +*.rlib +tests/debug.sh diff --git a/src/tools/semverver/CONTRIBUTING.md b/src/tools/semverver/CONTRIBUTING.md new file mode 100644 index 0000000000000..e5739bc9a0a25 --- /dev/null +++ b/src/tools/semverver/CONTRIBUTING.md @@ -0,0 +1,38 @@ +# Contributing to semverver + +Want to help developing semverver? Cool! See below on how to do that. + +## Bug reports + +If you encounter any unwanted behaviour from the tool, such as crashes or other unexpected +output, or if you think you have found a bug, please open an issue in GitHub's issue +tracker. + +Please describe the steps to reproduce your problem, as well as what you expected to +happen, and what happened instead. It is also useful to include the output of your command +invocation(s) with the following environment: `RUST_LOG=debug RUST_BACKTRACE=full`. +Please paste it at https://gist.github.com if the output is longer than a 50 lines or so. + +## Feature requests + +If you want to see some functionality added to semverver, you can also open an issue. Make +sure to include what functionality you need exactly, why it is useful, and, depending on +the complexity and/or how related the functionality is to the core project goals, why you +think it should be implemented in semverver and not somewhere else. + +## Working on issues + +If you want to write code to make semverver better, please post in the issue(s) you want +to tackle, and if you already have an idea/proposed solution, you are welcome to summarize +it in case some discussion is necessary. + +Here are some guidelines you should try to stick to: + +* Please fork the repository on GitHub and create a feature branch in your fork. +* Try to keep your code stylistically similar to the already existing codebase. +* Commit your changes in compact, logically coupled chunks. +* Make sure `cargo test` passes after your changes. +* Run `rustfmt` on your code (for example by running `cargo fmt`). +* If possible, fix any issues `cargo clippy` might find in your code. +* Finally, make a pull request against the master branch on GitHub and wait for the CI to + find any outstanding issues. diff --git a/src/tools/semverver/Cargo.toml b/src/tools/semverver/Cargo.toml new file mode 100644 index 0000000000000..efe182cc48874 --- /dev/null +++ b/src/tools/semverver/Cargo.toml @@ -0,0 +1,47 @@ +[package] +name = "semverver" +description = "Automatic verification of SemVer adhrence in rust library crates" +repository = "https://github.com/rust-dev-tools/rust-semverver" +readme = "README.md" +keywords = ["semver", "plugin"] +categories = ["development-tools", "development-tools::cargo-plugins"] +version = "0.1.46" +authors = ["Inokentiy Babushkin "] +license-file = "LICENSE" +edition = "2018" + +[badges] +travis-ci = { repository = "rust-dev-tools/rust-semverver" } +appveyor = { repository = "rust-dev-tools/rust-semverver" } + +[[bin]] +name = "cargo-semver" +path = "src/bin/cargo_semver.rs" + +[[bin]] +name = "rust-semverver" +path = "src/bin/rust_semverver.rs" + +[[bin]] +name = "rust-semver-public" +path = "src/bin/rust_semver_public.rs" + +[dependencies] +cargo = "0.47" +crates-io = "0.32" +curl = "0.4.21" +env_logger = "0.7" +anyhow = "1.0.27" +log = "0.4" +rand = "0.7" +semver = "0.9" +serde = { version = "1.0.84", features = ["derive"] } +serde_json = "1.0.34" + +[dev-dependencies] +quickcheck = "0.9" + +# A noop dependency that changes in the Rust repository, it's a bit of a hack. +# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` +# for more information. +rustc-workspace-hack = "1.0.0" diff --git a/src/tools/semverver/LICENSE b/src/tools/semverver/LICENSE new file mode 100644 index 0000000000000..1220f8e7cac03 --- /dev/null +++ b/src/tools/semverver/LICENSE @@ -0,0 +1,30 @@ +Copyright Inokentiy Babushkin (c) 2017-2019 + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Inokentiy Babushkin nor the names of other + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/tools/semverver/README.md b/src/tools/semverver/README.md new file mode 100644 index 0000000000000..32f1810a16311 --- /dev/null +++ b/src/tools/semverver/README.md @@ -0,0 +1,277 @@ +# rust-semverver + +[![Travis Build Status](https://travis-ci.org/rust-dev-tools/rust-semverver.svg?branch=master)](https://travis-ci.org/rust-dev-tools/rust-semverver) +[![AppVeyor Build status](https://ci.appveyor.com/api/projects/status/qktm3ndv6cnbj01m?svg=true)](https://ci.appveyor.com/project/ibabushkin/rust-semverver) +[![Current Version](https://meritbadge.herokuapp.com/semverver)](https://crates.io/crates/semverver) + +`rust-semverver` is a tool to check semver-compliance in Rust library crates. The core of +the tool has been developed as a student project during the Google Summer of Code 2017. + +Details on the work done during GSoC 2017 can be found +[here](https://github.com/rust-dev-tools/rust-semverver/blob/master/doc/gsoc.md). + +## Background + +The approach taken is to compile both versions of the crate to `rlib`s and to link them as +dependencies of a third, empty, dummy crate. Then, a custom compiler driver is run on the +said dummy and all necessary analysis is performed in that context, where type information +and other resources are available. + +More information on the inner workings of the tool can be found +[here](https://github.com/rust-dev-tools/rust-semverver/blob/master/doc/impl_notes.md). + +## Installation + +The tool is implemented as a cargo plugin. As of now, it can be obtained from this git +repository and compiled from source or installed from +[crates.io](https://crates.io/crates/semverver). Keep in mind that only the newest version +of the nighly toolchain is supported at any given time. + +If you are already using Rust nightly and have successfully installed tools like +`cargo add` and `cargo clippy`, just do: + +```sh +$ rustup update nightly +$ rustup component add rustc-dev --toolchain nightly +$ cargo +nightly install semverver +``` + +You'd also need `cmake` for some dependencies, and a few common libraries (if you hit +build failures because of missing system-wide dependencies, please open an issue, so they +can be added here). + +You can also install the newest version of the tool from git: + +```sh +$ rustup update nightly +$ rustup component add rustc-dev --toolchain nightly +$ cargo +nightly install --git https://github.com/rust-dev-tools/rust-semverver +``` + +
+ + + Manual installation and more details + + +```sh +# using rustup is recommended +$ rustup update nightly +$ rustup default nightly + +$ git clone https://github.com/rust-dev-tools/rust-semverver +$ cd rust-semverver +$ cargo install +``` + +At this point, the current development version can be invoked using `cargo semver` in any +directory your project resides in. If you prefer not to install to `~/.cargo/bin`, you can +invoke it like so after building with a regular `cargo build`: + +```sh +$ PATH=/path/to/repo/target/debug:$PATH cargo semver +``` + +If you have built using `cargo build --release` instead, change the path to point to the +`release` subdirectory of the `target` directory. + +
+ +## Usage + +By default, running `cargo semver` in directory with a Cargo project will try to compare +the local version the one last published on crates.io, and display warnings or errors for +all changes found. + +Invoking `cargo semver -h` gives you the latest help message, which outlines how to use +the cargo plugin: + +```sh +$ cargo semver -h +usage: cargo semver [options] + +Options: + -h, --help print this message and exit + -V, --version print version information and exit + -e, --explain print detailed error explanations + -q, --quiet surpress regular cargo output, print only important + messages + --show-public print the public types in the current crate given by + -c or -C and exit + -d, --debug print command to debug and exit + -a, --api-guidelines + report only changes that are breaking according to the + API-guidelines + --features FEATURES + Space-separated list of features to activate + --all-features Activate all available features + --no-default-features + Do not activate the `default` feature + --compact Only output the suggested version on stdout for + further processing + -j, --json Output a JSON-formatted description of all collected + data on stdout. + -s, --stable-path PATH + use local path as stable/old crate + -c, --current-path PATH + use local path as current/new crate + -S, --stable-pkg NAME:VERSION + use a `name:version` string as stable/old crate + -C, --current-pkg NAME:VERSION + use a `name:version` string as current/new crate + --target + Build for the target triple +``` + +This means that you can compare any two crates' specified versions, as long as they are +available on crates.io or present on your filesystem. + +### CI setup + +Assuming you use a CI provider that gives you access to cargo, you can use the following +snippet to check your build for semver compliance, and enforce that version bumps are +carried out correctly with regards to the current version of your crate on crates.io: + +```sh +# install a current version of rust-semverver +cargo install semverver +# fetch the version in the manifest of your crate (adapt this to your usecase if needed) +eval "current_version=$(grep -e '^version = .*$' Cargo.toml | cut -d ' ' -f 3)" +# run the semver checks and output them for convenience +cargo semver | tee semver_out +# fail the build if necessary +(head -n 1 semver_out | grep "\-> $current_version") || (echo "versioning mismatch" && return 1) +``` + +Make sure you do the above with access to a nightly toolchain. Check your CI provider's +documentation on how to do that. + +### JSON output + +By passing the `-j` flag, all output on standard out is formatted as a machine-readable +JSON blob. This can be useful for integration with other tools, and always generates all +possible output (ignoring other output-related flags). The output format is defined as +follows: + +The top level object contains the keys `old_version`, `new_version` and `changes`. The +former two hold a version number in the format `major.minor.patch`, the latter an object +describing changes between the crate versions, which contains two arrays in the keys +`path_changes` and `changes`. + +The `path_changes` array contains objects describing item additions and removals, which +have the following keys: + +* `name`: The name of the item. +* `def_span`: An object describing the location of the item in one of the crates. +* `additions`: An array of spans that describe locations where the item has been added. +* `removals`: An array of spans that describe locations where the item has been removed. + +An example object might look like this: + +```json +{ + "name": "NFT_META_CGROUP", + "def_span": { + "file": "/path/to/libc-0.2.48/src/unix/notbsd/linux/other/mod.rs", + "line_lo": 776, + "line_hi": 776, + "col_lo": 0, + "col_hi": 40 + }, + "additions": [ + { + "file": "/path/to/libc-0.2.48/src/lib.rs", + "line_lo": 195, + "line_hi": 195, + "col_lo": 16, + "col_hi": 23 + } + ], + "removals": [] +} +``` + + +The `changes` array contains objects describing all other changes, which have the +following keys: + +* `name`: The name of the item +* `max_category`: the most severe change category for this item, as a string. + * Possible values are `Patch`, `NonBreaking`, `TechnicallyBreaking`, and `Breaking`. +* `new_span`: an object describing the location of the item in the new crate (see example). +* `changes`: an array of 2-element sequences containing an error message and an optional + sub-span (`null` if none is present) + +An example object might look like this: + +```json +{ + "name": " as new::prelude::Stream>", + "max_category": "TechnicallyBreaking", + "new_span": { + "file": "/path/to/tokio-0.1.17/src/util/enumerate.rs", + "line_lo": 46, + "line_hi": 63, + "col_lo": 0, + "col_hi": 1 + }, + "changes": [ + [ + "trait impl generalized or newly added", + null + ] + ] +} +``` + +For reference, all objects describing spans have the same keys: + +* `file`: A file name. +* `line_lo`: The line the span starts on. +* `line_hi`: The line the span ends on. +* `col_lo`: The column the span starts on. +* `col_hi`: The column the span ends on. + +## Functionality + +The guideline used to implement semver compatibility is the [API evolution +RFC](https://github.com/rust-lang/rfcs/blob/master/text/1105-api-evolution.md), which +applies the principles of semantic versioning to the Rust language's semantics. According +to the RFC, most changes are already recognized correctly, even though some type checks +still behave incorrectly in edge-cases. A longterm goal is to fix this in the compiler. + +At the time of writing, the following types of changes are recognized and classified +correctly: + +* items moving from `pub` to non-`pub` and vice-versa +* items changing their kind, i.e. from a `struct` to an `enum` +* additions and removals of region parameters to and from an item's declaration +* additions and removals of (possibly defaulted) type parameters to and from an item's + declaration +* changes to the variance of type and region parameters +* additions and removals of enum variants +* additions and removals of enum variant- or struct fields +* changes from tuple structs or variants to struct variants and vice-versa +* changes to a function or method's constness +* additions and removals of a self-parameter on methods +* additions and removals of (posslibly defaulted) trait items +* correct handling of "sealed" traits +* changes to the unsafety of a trait +* type changes of all toplevel items, as well as associated items in inherent impls and + trait definitions +* additions and removals of inherent impls or methods contained therein +* additions and removals of trait impls + +Keep in mind however that the results presented to the user are merely an approximation of +the required versioning policy. + +## Contributing + +Please see +[CONTRIBUTING.md](https://github.com/rust-dev-tools/rust-semverver/blob/master/CONTRIBUTING.md). + +## License + +`rust-semverver` is distributed under the terms of the 3-clause BSD license. + +See LICENSE for details. diff --git a/src/tools/semverver/build.rs b/src/tools/semverver/build.rs new file mode 100644 index 0000000000000..4c9b6c19d6bc7 --- /dev/null +++ b/src/tools/semverver/build.rs @@ -0,0 +1,6 @@ +// This does nothing. +// It is only there because cargo will only set the $OUT_DIR env variable +// for tests if there is a build script. +fn main() { + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/src/tools/semverver/ci/run.sh b/src/tools/semverver/ci/run.sh new file mode 100755 index 0000000000000..bf17dd4098ff3 --- /dev/null +++ b/src/tools/semverver/ci/run.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env sh + +set -ex + +OS=${1} + +export RUST_BACKTRACE=full +#export RUST_TEST_NOCAPTURE=1 + +rustup update nightly + +cargo +nightly install rustup-toolchain-install-master +if [ "${OS}" = "windows" ]; then + rustup-toolchain-install-master -f -n master -c rustc-dev -c llvm-tools -i x86_64-pc-windows-msvc +else + rustup-toolchain-install-master -f -n master -c rustc-dev -c llvm-tools +fi +rustup override set master + +cargo build +cargo test --verbose -- --nocapture + +case "${OS}" in + *"linux"*) + TEST_TARGET=x86_64-unknown-linux-gnu cargo test --verbose -- --nocapture + ;; + *"windows"*) + TEST_TARGET=x86_64-pc-windows-msvc cargo test --verbose -- --nocapture + ;; + *"macos"*) + TEST_TARGET=x86_64-apple-darwin cargo test --verbose -- --nocapture + ;; +esac + +# install +mkdir -p ~/rust/cargo/bin +cp target/debug/cargo-semver ~/rust/cargo/bin +cp target/debug/rust-semverver ~/rust/cargo/bin + +# become semververver +# +# Note: Because we rely on rust nightly building the previously published +# semver can often fail. To avoid failing the build we first check +# if we can compile the previously published version. +if cargo install --root "$(mktemp -d)" semverver > /dev/null 2>/dev/null; then + PATH=~/rust/cargo/bin:$PATH cargo semver | tee semver_out + current_version="$(grep -e '^version = .*$' Cargo.toml | cut -d ' ' -f 3)" + current_version="${current_version%\"}" + current_version="${current_version#\"}" + result="$(head -n 1 semver_out)" + if echo "$result" | grep -- "-> $current_version"; then + echo "version ok" + exit 0 + else + echo "versioning mismatch" + cat semver_out + echo "versioning mismatch" + exit 1 + fi +else + echo 'Failed to check semver-compliance of semverver. Failed to compiled previous version.' >&2 +fi diff --git a/src/tools/semverver/doc/gsoc.md b/src/tools/semverver/doc/gsoc.md new file mode 100644 index 0000000000000..0f6ae3e59b09c --- /dev/null +++ b/src/tools/semverver/doc/gsoc.md @@ -0,0 +1,62 @@ +# Notes on work done during GSoC 2017 (by twk/ibabushkin) +The toplevel [README](https://github.com/ibabushkin/rust-semverver/blob/master/README.md) +outlines the functionality and usage of the project. This document complements it by +gathering references to the work that has been done during the Google Summer of Code 2017 +and which eventually led to the current working state of the project. + +## Completion status +All core functionality has been implemented. There are still some bugs present, whose +fixes depend on changes to [`rustc`](https://github.com/rust-lang/rust) that are currently +underway and possibly not yet merged at the time of submission. + +See [this issue](https://github.com/ibabushkin/rust-semverver/issues/24) for a very rough +description of the problem and [this rust PR](https://github.com/rust-lang/rust/pull/43847) +as a reference to the fixes needed. + +However, with the language being under active development and other changes taking place, +the project will need some future work: More bugfixes, and handling of new language +features might require a similar kind of development work as the one that took place over +the course of the program. Other possible enhancements are listed in the issue tracker: + +* Checks for not directly code-related changes to a crate: + [#8](https://github.com/ibabushkin/rust-semverver/issues/8) +* Recursive checking of dependencies: + [#12](https://github.com/ibabushkin/rust-semverver/issues/12) +* Blacklisting modules and/or silencing analysis: + [#22](https://github.com/ibabushkin/rust-semverver/issues/22) +* An automated tool checking all crates on `crates.io`: + [#27](https://github.com/ibabushkin/rust-semverver/issues/27) + +On a different front, the cargo plugin could need some technical improvements to improve +usability and code quality. + +An overview of the functionality, and it's implementation can be found +[here](https://github.com/ibabushkin/rust-semverver/blob/master/doc/impl_notes.md). + +## Progress made +The project provided a very through and challenging walkthrough to the internal working of +`rustc` and it's surrounding infrastructure. I had the opportunity to learn to approach +problems differently and in the context of a wider-reaching, larger project, which has +it's own priorities and forces a different approach. In that context, the provided +functionality is a stepping stone to maintain a codebase in and interact with the wider +rust internals community. + +## List of references +* [this repository](https://github.com/ibabushkin/rust-semverver) contains the main body + of code written. +* multiple pull requests to the main rust repository: + * [#42507](https://github.com/rust-lang/rust/pull/42507) -- Fixes span translation in + metadata decoding. Had to be amended by later changes to incorporate spans in error + messages properly. + * [#42593](https://github.com/rust-lang/rust/pull/42593) -- Implements the encoding of a + reference to the source code in crate metadata, together with a lazy loading scheme. + This provides for the source code to be rendered in error messages. + * [#43128](https://github.com/rust-lang/rust/pull/43128) -- Allows to fold over type + errors - which is a facility we then use. + * [#43598](https://github.com/rust-lang/rust/pull/43598) -- A trivial oneliner to make + an internal datatype more versatile for our purposes. + * [#43739](https://github.com/rust-lang/rust/pull/43739) -- A fix to encode a more + suited span in crate metadata for module items. + * [#43847](https://github.com/rust-lang/rust/pull/43847) -- Not yet merged at the time + of writing. Intends to allow for encoding of macro expansion information in crate + metadata. diff --git a/src/tools/semverver/doc/impl_notes.md b/src/tools/semverver/doc/impl_notes.md new file mode 100644 index 0000000000000..0c7a47a1ec04f --- /dev/null +++ b/src/tools/semverver/doc/impl_notes.md @@ -0,0 +1,139 @@ +# Implementation Notes +This document provides a high-level overview over the project's structure and +implementation, together with explanations of the various implementation decisions that +have been taken. + +The toplevel directory of the repository is structured according to cargo's conventions: + +* `src` contains the main project source code. +* `tests` contains integration tests (more on these in their dedicated section). +* only one crate, `semverver` is provided. It provides two binaries, whose functionality + is elaborated later on. The actual functionality is currently not exposed as a library, + but this change is trivial to implement. +* `doc` contains documentation. +* A cargo manifest and lockfile, license, and toplevel readme with an overview is placed + at the toplevel directory. + +## Source code structure +Inside the `src` subdirectory, the main functionality can be found inside the `semcheck` +directory, while the `bin` directory contains the two executables provided by the crate. + +### Execution overview +The provided binaries are a cargo plugin and a custom rustc driver, respectively, and +allow to analyze local and remote crate pairs for semver compatibility. + +A typical invocation, assuming that both binaries are on the user's `PATH`, is performed +by invoking `cargo semver` in a source code repository that can be built with cargo. This +invokes cargo's plugin mechanism, that then passes a set of command line arguments to +`cargo-semver`. This is the binary responsible to determine and compile the analysis +targets, whose inner workings are currently quite simplistic and allow for any combination +of "local" and "remote" crates - that is, source code repositories available through the +filesystem and from `crates.io`, defaulting to the current directory and the last +published version on `crates.io`, respectively. When a fitting pair of crates has been +compiled, the compiler driver, located in the `rust-semverver` binary, is invoked on a +dummy crate linking both versions as `old` and `new`. All further analysis is performed in +the compiler driver. + +To be more precise, the compiler driver runs the regular compilation machinery up to the +type checking phase and passes control to our analysis code, aborting the compilation +afterwards. + +This overall design has been chosen because it allows us to work on the data structures +representing parts of both the old and the new crate from the same compiler instance, +which simplifies the process by a great margin. Also, type information on all items being +analyzed is vital and has to be without any contradiction - so basing the analysis on +successfully compiled code is natural. The drawback, however, is that the needed +information is only available in a slightly manipulated form, since it has been encoded in +library metadata and decoded afterwards. This required some changes to the compiler's +metadata handling that have been mostly upstreamed by now. Another weak point is the +performance penalty imposed by two compilations and an analysis run on the target crate, +but this is very hard to circumvent, as is the necessity of using a nightly rust compiler +to use the tool - much alike to `rust-clippy`. + +### Analysis overview +The actual analysis is separated in multiple passes, whose main entry point is the +`run_analysis` function in the `traverse` submodule in `semverver::semcheck`. These passes +are structured as follows: + +1. Named items are matched up and checked for structural changes in a module traversal + scheme. Structural changes are changes to ADT structure, or additions and removals of + items, type and region parameters, changes to item visibility and (re)export structure, + and similar miscellaneous changes to the code being analyzed. +2. Not yet matched hidden items are opportunistically matched based on their usage in + public items' types. This is implemented in the `mismatch` submodule. +3. All items which haven't undergone breaking changes are checked for changes to their + trait bounds and (if applicable) types. This requires a translation of the analyzed old + item into the new crate using the previously established correspondence between items. + That mechanism is implemented in the `translate` submodule, and used very intensively + throughout the last two passes. Translation is based on item correspondence, which is + kept track of in the `mapping` submodule. +4. Inherent items and trait impls are matched up, if possible. This, too requires the + translation of bounds and types of the old item. However, to determine non-breaking + changes, bounds checks are generally performed in both direction, which is why the + translation machinery is largely agnostic to the distinction between target and source. + +During these four passes, all changes are recorded in a specialized data structure that +then allows to filter items to be analyzed further and to render changes using the items' +source spans, ultimately leading to deterministic output. The implementation is found in +the `changes` submodule. + +### Type checks implementation +Checking the types of a matching pair of items is one of the most important and most +complicated features of `rust-semverver`. Type checks are performed for type aliases, +constants, statics, ADT fields, and function signatures. This is implemented using the +type inference machinery of rustc and a custom `TypeComparisonContext`, located in +in the `typeck` module, that performs the necessary heavy lifting when given two types. + +The general process is to translate one of the types to allow for comparison, and to use +inference variables for items that usually invoke inference mechanisms in the compiler, +like functions. Then, an equality check on the two types is performed, and a possible +error is lifted and registered in the change store. If such a type check succeeds without +error, bounds checks can be performed *in the same context*, even though they can be +performed without a type check where appropriate. + +### Bounds checks implementation +Checking the bounds of a matching pair of items is performed for all items that are +subject to type changes, as well as trait definitions, using the already mentioned +`TypeComparisonContext`. The underlying mechanism is also used to match inherent, and -- +to a lesser extend -- trait impls. + +Bounds checks work in a similar manner to type checks. One of the items, in these case the +set of bounds, gets translated, and passed to an inference context. However, to properly +recognize all changes to trait bounds, this analysis step has to be performed in both +directions, to catch both loosening and tightening of bounds. + +### Trait impl matching +All trait impls are matched up in both directions, to determine whether impls for specific +types have been added or removed (note that in this context, an impl refers to the +*existence of a trait implementation matching a given type, not a specific trait impl*. If +no match is found when checking an old impl, this implies that an impl has been removed, +and that it has been addded when a new impl has no old matching counterpart. + +The actual matching is performed using the trait system. The translated bounds and trait +definition of the impl being checked are registered in a specialized `BoundContext`, which +is wrapping a fulfillment context that determines whether any matching impl exists. + +### Inherent impl matching +Matching inherent impls roughly follows the same principles as checking trait impls. +However, there are a few vital differences, since different inherent impls of the same +type don't need to declare the same set of associated items. Thus, each associated item is +kept track of to determine the set of impls it is present in. Each of these impls needs to +be matched in the other crate, to find a matching associated item in each. Then, regular +type and structural checks are performed on the matching items. + +The actual impl matching is performed based on the trait bounds on the inherent impls, as +described in a previous section. + +## Tests +The change recording structure has a suite of unit tests to ensure correct behaviour with +regards to change categorization and storage, according to the usual convention, these +unit tests are located in the same file as the implementation. Various invariants are +tested using `quickcheck`, others are exercised as plain examples. + +Most of the functionality, however, especially the analysis implementation, is tested +using an evergrowing integration test suite, which records the analysis results for mockup +crates, normalizes the output with regards to paths and similar information contained, and +compares it to a previously recorded version using `git`. Currently, regular crates are +supported in a limited fashion in this set of tests as well. However, to use this +functionality to the full extend, some changes to the compiler have yet to be upstreamed +at the time of writing. diff --git a/src/tools/semverver/rust-toolchain b/src/tools/semverver/rust-toolchain new file mode 100644 index 0000000000000..bf867e0ae5b6c --- /dev/null +++ b/src/tools/semverver/rust-toolchain @@ -0,0 +1 @@ +nightly diff --git a/src/tools/semverver/src/bin/cargo_semver.rs b/src/tools/semverver/src/bin/cargo_semver.rs new file mode 100644 index 0000000000000..600af2aafb6ed --- /dev/null +++ b/src/tools/semverver/src/bin/cargo_semver.rs @@ -0,0 +1,564 @@ +#![feature(rustc_private)] +#![feature(set_stdio)] +#![allow(clippy::too_many_lines)] + +extern crate curl; +#[macro_use] +extern crate serde; +extern crate rustc_session; +extern crate serde_json; + +use cargo::core::{Package, PackageId, Source, SourceId, Workspace}; +use cargo::sources::RegistrySource; +use curl::easy::Easy; +use log::debug; +use rand::Rng; +use rustc_session::getopts; +use std::collections::HashSet; +use std::{ + env, + fs::File, + io::BufReader, + io::Write, + path::{Path, PathBuf}, + process::{Command, Stdio}, +}; + +pub type Result = cargo::util::CargoResult; + +#[derive(Debug, Deserialize)] +struct Invocation { + package_name: String, + target_kind: Vec, + outputs: Vec, +} + +#[derive(Debug, Deserialize)] +struct BuildPlan { + invocations: Vec, +} + +/// Main entry point. +/// +/// Parse CLI arguments, handle their semantics, and provide for proper error handling. +fn main() { + if env_logger::try_init().is_err() { + eprintln!("ERROR: could not initialize logger"); + } + + let mut config = match cargo::Config::default() { + Ok(cfg) => cfg, + Err(e) => panic!("can't obtain cargo config: {:?}", e), + }; + + let opts = cli::options(); + + let matches = match cli::parse_args(&opts) { + Ok(m) => m, + Err(f) => cli::exit_with_error(&config, f.into()), + }; + + if matches.opt_present("h") { + cli::print_help(&opts); + return; + } + + if matches.opt_present("V") { + cli::print_version(); + return; + } + + if let Err(e) = cli::validate_args(&matches) { + cli::exit_with_error(&config, e); + } + + let config_res = config.configure( + 0, // verbose + matches.opt_present("q"), // quiet + None, // color + false, // frozen + false, // locked + matches.opt_present("offline"), + &None, // target_dir + &[], // unstable_flags + &[], // cli_config + ); + + if let Err(e) = config_res { + cli::exit_with_error(&config, e); + } + + if let Err(e) = run(&config, &matches) { + cli::exit_with_error(&config, e); + } +} + +/// Obtain two versions of the same crate, the "current" version, and the +/// "stable" version, compile them both into `rlib`s, and report the breaking +/// introduced in the "current" version with respect to the "stable" version. +// TODO: possibly reduce the complexity by finding where some info can be taken from directly +fn run(config: &cargo::Config, matches: &getopts::Matches) -> Result<()> { + use cargo::util::important_paths::find_root_manifest_for_wd; + debug!("running cargo-semver"); + + let explain = matches.opt_present("e"); + let compact = matches.opt_present("compact"); + let json = matches.opt_present("json"); + + // Obtain WorkInfo for the "current" + let current = if let Some(name_and_version) = matches.opt_str("C") { + // -C "name:version" requires fetching the appropriate package: + WorkInfo::remote(config, &PackageNameAndVersion::parse(&name_and_version)?)? + } else if let Some(path) = matches.opt_str("c").map(PathBuf::from) { + // -c "local_path": + WorkInfo::local(config, &find_root_manifest_for_wd(&path)?)? + } else { + // default: if neither -c / -C are used, use the workspace at the + // current working directory: + WorkInfo::local(config, &find_root_manifest_for_wd(config.cwd())?)? + }; + let name = current.package.name().to_owned(); + + // TODO: JSON output here + if matches.opt_present("show-public") { + let (current_rlib, current_deps_output) = + current.rlib_and_dep_output(config, &name, true, matches)?; + + let mut child = Command::new("rust-semver-public"); + child + .arg("--crate-type=lib") + .args(&["--extern", &*format!("new={}", current_rlib.display())]) + .args(&[format!("-L{}", current_deps_output.display())]); + + if let Some(target) = matches.opt_str("target") { + child.args(&["--target", &target]); + } + + let mut child = child + .arg("-") + .stdin(Stdio::piped()) + .spawn() + .map_err(|e| anyhow::Error::msg(format!("could not spawn rustc: {}", e)))?; + + if let Some(ref mut stdin) = child.stdin { + stdin.write_fmt(format_args!( + "#[allow(unused_extern_crates)] \ + extern crate new;" + ))?; + } else { + return Err(anyhow::Error::msg( + "could not pipe to rustc (wtf?)".to_owned(), + )); + } + + let exit_status = child + .wait() + .map_err(|e| anyhow::Error::msg(format!("failed to wait for rustc: {}", e)))?; + + return if exit_status.success() { + Ok(()) + } else { + Err(anyhow::Error::msg("rustc-semver-public errored".to_owned())) + }; + } + + // Obtain WorkInfo for the "stable" version + let (stable, stable_version) = if let Some(name_and_version) = matches.opt_str("S") { + // -S "name:version" requires fetching the appropriate package: + let info = PackageNameAndVersion::parse(&name_and_version)?; + let version = info.version.to_owned(); + let work_info = WorkInfo::remote(config, &info)?; + (work_info, version) + } else if let Some(path) = matches.opt_str("s") { + // -s "local_path": + let work_info = WorkInfo::local(config, &PathBuf::from(path))?; + let version = format!("{}", work_info.package.version()); + (work_info, version) + } else { + // default: if neither -s / -S are used, use the current's crate name to find the + // latest stable version of the crate on crates.io and use that one: + let stable_crate = find_on_crates_io(&name)?; + let info = PackageNameAndVersion { + name: &name, + version: &stable_crate.max_version, + }; + let work_info = WorkInfo::remote(config, &info)?; + (work_info, stable_crate.max_version.clone()) + }; + + let (current_rlib, current_deps_output) = + current.rlib_and_dep_output(config, &name, true, matches)?; + let (stable_rlib, stable_deps_output) = + stable.rlib_and_dep_output(config, &name, false, matches)?; + + if matches.opt_present("d") { + println!( + "--extern old={} -L{} --extern new={} -L{}", + stable_rlib.display(), + stable_deps_output.display(), + current_rlib.display(), + current_deps_output.display() + ); + return Ok(()); + } + + debug!("running rust-semverver on compiled crates"); + + let mut child = Command::new("rust-semverver"); + child + .arg("--crate-type=lib") + .args(&["--extern", &*format!("old={}", stable_rlib.display())]) + .args(&[format!("-L{}", stable_deps_output.display())]) + .args(&["--extern", &*format!("new={}", current_rlib.display())]) + .args(&[format!("-L{}", current_deps_output.display())]); + + if let Some(target) = matches.opt_str("target") { + child.args(&["--target", &target]); + } + + let child = child + .arg("-") + .stdin(Stdio::piped()) + .env("RUST_SEMVER_CRATE_VERSION", stable_version) + .env("RUST_SEMVER_VERBOSE", format!("{}", explain)) + .env("RUST_SEMVER_COMPACT", format!("{}", compact)) + .env("RUST_SEMVER_JSON", format!("{}", json)) + .env( + "RUST_SEMVER_API_GUIDELINES", + if matches.opt_present("a") { + "true" + } else { + "false" + }, + ); + + let mut child = child + .spawn() + .map_err(|e| anyhow::Error::msg(format!("could not spawn rustc: {}", e)))?; + + if let Some(ref mut stdin) = child.stdin { + // The order of the `extern crate` declaration is important here: it will later + // be used to select the `old` and `new` crates. + stdin.write_fmt(format_args!( + "#[allow(unused_extern_crates)] \ + extern crate old; \ + #[allow(unused_extern_crates)] \ + extern crate new;" + ))?; + } else { + return Err(anyhow::Error::msg( + "could not pipe to rustc (wtf?)".to_owned(), + )); + } + + let exit_status = child + .wait() + .map_err(|e| anyhow::Error::msg(format!("failed to wait for rustc: {}", e)))?; + + if exit_status.success() { + Ok(()) + } else { + Err(anyhow::Error::msg("rustc-semverver errored".to_owned())) + } +} + +/// CLI utils +mod cli { + use cargo::util::CliError; + use rustc_session::getopts; + + /// CLI options + pub fn options() -> getopts::Options { + let mut opts = getopts::Options::new(); + + opts.optflag("h", "help", "print this message and exit"); + opts.optflag("V", "version", "print version information and exit"); + opts.optflag("e", "explain", "print detailed error explanations"); + opts.optflag( + "q", + "quiet", + "surpress regular cargo output, print only important messages", + ); + opts.optflag( + "", + "show-public", + "print the public types in the current crate given by -c or -C and exit", + ); + opts.optflag("d", "debug", "print command to debug and exit"); + opts.optflag( + "a", + "api-guidelines", + "report only changes that are breaking according to the API-guidelines", + ); + opts.optopt( + "", + "features", + "Space-separated list of features to activate", + "FEATURES", + ); + opts.optflag("", "all-features", "Activate all available features"); + opts.optflag( + "", + "no-default-features", + "Do not activate the `default` feature", + ); + opts.optflag( + "", + "compact", + "Only output the suggested version on stdout for further processing", + ); + opts.optflag( + "j", + "json", + "Output a JSON-formatted description of all collected data on stdout.", + ); + opts.optopt( + "s", + "stable-path", + "use local path as stable/old crate", + "PATH", + ); + opts.optopt( + "c", + "current-path", + "use local path as current/new crate", + "PATH", + ); + opts.optopt( + "S", + "stable-pkg", + "use a `name:version` string as stable/old crate", + "NAME:VERSION", + ); + opts.optopt( + "C", + "current-pkg", + "use a `name:version` string as current/new crate", + "NAME:VERSION", + ); + opts.optflag("", "offline", "Run without accessing the network."); + opts.optopt("", "target", "Build for the target triple", ""); + opts + } + + /// Parse CLI arguments + pub fn parse_args(opts: &getopts::Options) -> Result { + let args: Vec = std::env::args().skip(1).collect(); + opts.parse(&args) + } + + /// Validate CLI arguments + pub fn validate_args(matches: &getopts::Matches) -> Result<(), anyhow::Error> { + if (matches.opt_present("s") && matches.opt_present("S")) + || matches.opt_count("s") > 1 + || matches.opt_count("S") > 1 + { + let msg = "at most one of `-s,--stable-path` and `-S,--stable-pkg` allowed"; + return Err(anyhow::Error::msg(msg.to_owned())); + } + + if (matches.opt_present("c") && matches.opt_present("C")) + || matches.opt_count("c") > 1 + || matches.opt_count("C") > 1 + { + let msg = "at most one of `-c,--current-path` and `-C,--current-pkg` allowed"; + return Err(anyhow::Error::msg(msg.to_owned())); + } + + Ok(()) + } + + /// Print a help message + pub fn print_help(opts: &getopts::Options) { + // FIXME: pass remaining options to cargo + let brief = "usage: cargo semver [options]"; + print!("{}", opts.usage(brief)); + } + + /// Print a version message. + pub fn print_version() { + println!("{}", env!("CARGO_PKG_VERSION")); + } + + /// Exit with error `e`. + pub fn exit_with_error(config: &cargo::Config, e: anyhow::Error) -> ! { + config + .shell() + .set_verbosity(cargo::core::shell::Verbosity::Normal); + cargo::exit_with_error(CliError::new(e, 1), &mut config.shell()); + } +} + +/// A package's name and version. +pub struct PackageNameAndVersion<'a> { + /// The crate's name. + pub name: &'a str, + /// The package's version, as a semver-string. + pub version: &'a str, +} + +impl<'a> PackageNameAndVersion<'a> { + /// Parses the string "name:version" into `Self` + pub fn parse(s: &'a str) -> Result { + let err = || { + anyhow::Error::msg(format!( + "spec has to be of form `name:version` but is `{}`", + s + )) + }; + let mut split = s.split(':'); + let name = split.next().ok_or_else(err)?; + let version = split.next().ok_or_else(err)?; + if split.next().is_some() { + Err(err()) + } else { + Ok(Self { name, version }) + } + } +} + +/// A specification of a package and it's workspace. +pub struct WorkInfo<'a> { + /// The package to be compiled. + pub package: Package, + /// The package's workspace. + workspace: Workspace<'a>, +} + +impl<'a> WorkInfo<'a> { + /// Construct a package/workspace pair for the `manifest_path` + pub fn local(config: &'a cargo::Config, manifest_path: &Path) -> Result> { + let workspace = Workspace::new(&manifest_path, config)?; + let package = workspace.load(&manifest_path)?; + Ok(Self { package, workspace }) + } + + /// Construct a package/workspace pair by fetching the package of a + /// specified `PackageNameAndVersion` from the `source`. + pub fn remote( + config: &'a cargo::Config, + &PackageNameAndVersion { name, version }: &PackageNameAndVersion, + ) -> Result> { + let source = { + let source_id = SourceId::crates_io(&config)?; + let mut source = RegistrySource::remote(source_id, &HashSet::new(), config); + + debug!("source id loaded: {:?}", source_id); + + if !config.offline() { + let _lock = config.acquire_package_cache_lock()?; + source.update()?; + } + + Box::new(source) + }; + + // TODO: fall back to locally cached package instance, or better yet, search for it + // first. + let package_id = PackageId::new(name, version, source.source_id())?; + debug!("(remote) package id: {:?}", package_id); + + let package = source.download_now(package_id, config)?; + let workspace = Workspace::ephemeral(package.clone(), config, None, false)?; + + Ok(Self { package, workspace }) + } + + /// Obtain the paths to the produced rlib and the dependency output directory. + pub fn rlib_and_dep_output( + &self, + config: &'a cargo::Config, + name: &str, + current: bool, + matches: &getopts::Matches, + ) -> Result<(PathBuf, PathBuf)> { + let mut opts = + cargo::ops::CompileOptions::new(config, cargo::core::compiler::CompileMode::Build)?; + // we need the build plan to find our build artifacts + opts.build_config.build_plan = true; + + if let Some(target) = matches.opt_str("target") { + let target = cargo::core::compiler::CompileTarget::new(&target); + if let Ok(target) = target { + let kind = cargo::core::compiler::CompileKind::Target(target); + opts.build_config.requested_kinds = vec![kind]; + } + } + + if let Some(s) = matches.opt_str("features") { + opts.features = s.split(' ').map(str::to_owned).collect(); + } + + opts.all_features = matches.opt_present("all-features"); + opts.no_default_features = matches.opt_present("no-default-features"); + + env::set_var( + "RUSTFLAGS", + format!("-C metadata={}", if current { "new" } else { "old" }), + ); + + let mut outdir = env::temp_dir(); + // The filename is randomized to avoid clashes when multiple cargo-semver instances are running. + outdir.push(&format!( + "cargo_semver_{}_{}_{}", + name, + current, + rand::thread_rng().gen::() + )); + + // redirection gang + let outfile = File::create(&outdir)?; + let old_stdio = std::io::set_print(Some(Box::new(outfile))); + + let _ = cargo::ops::compile(&self.workspace, &opts)?; + + std::io::set_print(old_stdio); + + // actually compile things now + opts.build_config.build_plan = false; + + let compilation = cargo::ops::compile(&self.workspace, &opts)?; + env::remove_var("RUSTFLAGS"); + + let build_plan: BuildPlan = serde_json::from_reader(BufReader::new(File::open(&outdir)?))?; + + // TODO: handle multiple outputs gracefully + for i in &build_plan.invocations { + if let Some(kind) = i.target_kind.get(0) { + if kind.contains("lib") && i.package_name == name { + // FIXME(eddyb) handle multiple targets. + return Ok((i.outputs[0].clone(), compilation.deps_output.into_iter().next().unwrap().1)); + } + } + } + + Err(anyhow::Error::msg("lost build artifact".to_owned())) + } +} + +/// Given a `crate_name`, try to locate the corresponding crate on `crates.io`. +/// +/// If no crate with the exact name is present, error out. +pub fn find_on_crates_io(crate_name: &str) -> Result { + let mut handle = Easy::new(); + handle.useragent(&format!("rust-semverver {}", env!("CARGO_PKG_VERSION")))?; + let mut registry = + crates_io::Registry::new_handle("https://crates.io".to_owned(), None, handle); + + registry + .search(crate_name, 1) + .map_err(|e| { + anyhow::Error::msg(format!( + "failed to retrieve search results from the registry: {}", + e + )) + }) + .and_then(|(mut crates, _)| { + crates + .drain(..) + .find(|krate| krate.name == crate_name) + .ok_or_else(|| { + anyhow::Error::msg(format!("failed to find a matching crate `{}`", crate_name)) + }) + }) +} diff --git a/src/tools/semverver/src/bin/rust_semver_public.rs b/src/tools/semverver/src/bin/rust_semver_public.rs new file mode 100644 index 0000000000000..088ba17fcc921 --- /dev/null +++ b/src/tools/semverver/src/bin/rust_semver_public.rs @@ -0,0 +1,123 @@ +#![feature(rustc_private)] + +extern crate rustc_driver; +extern crate rustc_interface; +extern crate rustc_middle; +extern crate rustc_span; + +use log::debug; +use rustc_driver::{Callbacks, Compilation}; +use rustc_interface::{interface, Queries}; +use rustc_span::source_map::Pos; +use semverver::run_traversal; +use std::{ + path::Path, + process::{exit, Command}, +}; + +/// Display semverver version. +fn show_version() { + println!(env!("CARGO_PKG_VERSION")); +} + +/// Main routine. +/// +/// Find the sysroot before passing our args to the custom compiler driver we register. +fn main() { + rustc_driver::init_rustc_env_logger(); + + debug!("running rust-semver-public compiler driver"); + + exit( + { + use std::env; + + struct PubCallbacks; + + impl Callbacks for PubCallbacks { + fn after_analysis<'tcx>(&mut self, _compiler: &interface::Compiler, queries: &'tcx Queries<'tcx>) -> Compilation { + debug!("running rust-semver-public after_analysis callback"); + + queries.global_ctxt().unwrap().peek_mut().enter(|tcx| { + let krate = tcx + .crates() + .iter() + .flat_map(|crate_num| { + let def_id = crate_num.as_def_id(); + + match tcx.extern_crate(def_id) { + Some(extern_crate) if extern_crate.is_direct() && extern_crate.span.data().lo.to_usize() > 0 => Some(def_id), + _ => None, + } + }) + .next(); + + if let Some(krate_def_id) = krate { + debug!("running semver analysis"); + run_traversal(tcx, krate_def_id); + } else { + tcx.sess.err("could not find `new` crate"); + } + }); + + debug!("rust-semver-public after_analysis callback finished!"); + + Compilation::Stop + } + } + + if env::args().any(|a| a == "--version" || a == "-V") { + show_version(); + exit(0); + } + + let sys_root = option_env!("SYSROOT") + .map(String::from) + .or_else(|| env::var("SYSROOT").ok()) + .or_else(|| { + let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); + let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); + home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain))) + }) + .or_else(|| { + Command::new("rustc") + .arg("--print") + .arg("sysroot") + .output() + .ok() + .and_then(|out| String::from_utf8(out.stdout).ok()) + .map(|s| s.trim().to_owned()) + }) + .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); + + // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. + // We're invoking the compiler programmatically, so we ignore this/ + let mut orig_args: Vec = env::args().collect(); + if orig_args.len() <= 1 { + std::process::exit(1); + } + + if Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref()) { + // we still want to be able to invoke it normally though + orig_args.remove(1); + } + + // this conditional check for the --sysroot flag is there so users can call + // `clippy_driver` directly + // without having to pass --sysroot or anything + let args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { + orig_args + } else { + orig_args + .into_iter() + .chain(Some("--sysroot".to_owned())) + .chain(Some(sys_root)) + .collect() + }; + + let args = args; + rustc_driver::run_compiler(&args, &mut PubCallbacks, None, None) + } + .map_or_else(|_| 1, |_| 0), + ) +} diff --git a/src/tools/semverver/src/bin/rust_semverver.rs b/src/tools/semverver/src/bin/rust_semverver.rs new file mode 100644 index 0000000000000..600d78d72334a --- /dev/null +++ b/src/tools/semverver/src/bin/rust_semverver.rs @@ -0,0 +1,151 @@ +#![feature(rustc_private)] + +extern crate rustc_driver; +extern crate rustc_errors; +extern crate rustc_interface; +extern crate rustc_metadata; +extern crate rustc_middle; +extern crate rustc_span; + +use log::debug; +use rustc_driver::{Callbacks, Compilation}; +use rustc_interface::{interface, Queries}; +use rustc_span::source_map::Pos; +use semverver::run_analysis; +use std::{ + path::Path, + process::{exit, Command}, +}; + +/// Display semverver version. +fn show_version() { + println!(env!("CARGO_PKG_VERSION")); +} + +/// Main routine. +/// +/// Find the sysroot before passing our args to the custom compiler driver we register. +fn main() { + env_logger::init_from_env("RUSTC_LOG"); + + debug!("running rust-semverver compiler driver"); + exit( + { + use std::env; + + struct SemverCallbacks; + + impl Callbacks for SemverCallbacks { + fn after_analysis<'tcx>(&mut self, _compiler: &interface::Compiler, queries: &'tcx Queries<'tcx>) -> Compilation { + debug!("running rust-semverver after_analysis callback"); + + let verbose = + env::var("RUST_SEMVER_VERBOSE") == Ok("true".to_string()); + let compact = + env::var("RUST_SEMVER_COMPACT") == Ok("true".to_string()); + let json = + env::var("RUST_SEMVER_JSON") == Ok("true".to_string()); + let api_guidelines = + env::var("RUST_SEMVER_API_GUIDELINES") == Ok("true".to_string()); + let version = if let Ok(ver) = env::var("RUST_SEMVER_CRATE_VERSION") { + ver + } else { + "no_version".to_owned() + }; + + queries.global_ctxt().unwrap().peek_mut().enter(|tcx| { + // To select the old and new crates we look at the position of the + // declaration in the source file. The first one will be the `old` + // and the other will be `new`. This is unfortunately a bit hacky... + // See issue #64 for details. + + let mut crates: Vec<_> = tcx + .crates() + .iter() + .flat_map(|crate_num| { + let def_id = crate_num.as_def_id(); + + match tcx.extern_crate(def_id) { + Some(extern_crate) if extern_crate.is_direct() && extern_crate.span.data().lo.to_usize() > 0 => + Some((extern_crate.span.data().lo.to_usize(), def_id)), + _ => None, + } + }) + .collect(); + + crates.sort_by_key(|&(span_lo, _)| span_lo); + + if let [(_, old_def_id), (_, new_def_id)] = *crates.as_slice() { + debug!("running semver analysis"); + let changes = run_analysis(tcx, old_def_id, new_def_id); + if json { + changes.output_json(tcx.sess, &version); + } else { + changes.output(tcx.sess, &version, verbose, compact, api_guidelines); + } + } else { + tcx.sess.err("could not find `old` and `new` crates"); + } + }); + + debug!("rust-semverver after_analysis callback finished!"); + + Compilation::Stop + } + } + + if env::args().any(|a| a == "--version" || a == "-V") { + show_version(); + exit(0); + } + + let sys_root = option_env!("SYSROOT") + .map(String::from) + .or_else(|| env::var("SYSROOT").ok()) + .or_else(|| { + let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); + let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); + home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain))) + }) + .or_else(|| { + Command::new("rustc") + .arg("--print") + .arg("sysroot") + .output() + .ok() + .and_then(|out| String::from_utf8(out.stdout).ok()) + .map(|s| s.trim().to_owned()) + }) + .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); + + // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. + // We're invoking the compiler programmatically, so we ignore this/ + let mut orig_args: Vec = env::args().collect(); + if orig_args.len() <= 1 { + std::process::exit(1); + } + + if Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref()) { + // we still want to be able to invoke it normally though + orig_args.remove(1); + } + + // this conditional check for the --sysroot flag is there so users can call + // `clippy_driver` directly + // without having to pass --sysroot or anything + let args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { + orig_args + } else { + orig_args + .into_iter() + .chain(Some("--sysroot".to_owned())) + .chain(Some(sys_root)) + .collect() + }; + + let args = args; + rustc_driver::run_compiler(&args, &mut SemverCallbacks, None, None) + } + .map_or_else(|_| 1, |_| 0), + ) +} diff --git a/src/tools/semverver/src/changes.rs b/src/tools/semverver/src/changes.rs new file mode 100644 index 0000000000000..ae418b1ff0dbe --- /dev/null +++ b/src/tools/semverver/src/changes.rs @@ -0,0 +1,1676 @@ +//! Change representation. +//! +//! This module provides data types to represent, store and record changes found in various +//! analysis passes. We distinguish between path changes and regular changes, which represent +//! changes to the export structure of the crate and to specific items, respectively. The +//! ordering of changes and output generation is performed using the span information contained +//! in these data structures. This means that we try to use the old span only when no other span +//! is available, which leads to (complete) removals being displayed first. Matters are further +//! complicated by the fact that we still group changes by the item they refer to, even if it's +//! path changes. + +use rustc_hir::def_id::DefId; +use rustc_middle::ty::{error::TypeError, Predicate}; +use rustc_session::Session; +use rustc_span::symbol::Symbol; +use rustc_span::{FileName, Span}; +use semver::Version; +use std::{ + cmp::Ordering, + collections::{BTreeMap, BTreeSet, HashMap}, + fmt, +}; + +use serde::ser::{SerializeSeq, SerializeStruct, Serializer}; +use serde::Serialize; + +/// The categories we use when analyzing changes between crate versions. +/// +/// These directly correspond to the semantic versioning spec, with the exception that some +/// breaking changes are categorized as "technically breaking" - that is, [1] defines them as +/// non-breaking when introduced to the standard libraries, because they only cause breakage in +/// exotic and/or unlikely scenarios, while we have a separate category for them. +/// +/// [1]: https://github.com/rust-lang/rfcs/blob/master/text/1105-api-evolution.md +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize)] +pub enum ChangeCategory { + /// A patch-level change - no change to the public API of a crate. + Patch, + /// A non-breaking, backwards-compatible change. + NonBreaking, + /// A breaking change that only causes breakage in well-known exotic cases. + TechnicallyBreaking, + /// A breaking, backwards-incompatible change. + Breaking, +} + +pub use self::ChangeCategory::*; + +impl<'a> Default for ChangeCategory { + fn default() -> Self { + Patch + } +} + +impl<'a> fmt::Display for ChangeCategory { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let desc = match *self { + Patch => "patch", + NonBreaking => "non-breaking", + TechnicallyBreaking => "technically breaking", + Breaking => "breaking", + }; + + write!(f, "{}", desc) + } +} + +pub struct RSymbol(pub Symbol); + +impl Serialize for RSymbol { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&format!("{}", self.0)) + } +} + +struct RSpan<'a>(&'a Session, &'a Span); + +impl<'a> Serialize for RSpan<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let lo = self.0.source_map().lookup_char_pos(self.1.lo()); + let hi = self.0.source_map().lookup_char_pos(self.1.hi()); + + assert!(lo.file.name == hi.file.name); + let file_name = if let FileName::Real(ref name) = lo.file.name { + format!("{}", name.local_path().display()) + } else { + "no file name".to_owned() + }; + + let mut state = serializer.serialize_struct("Span", 5)?; + state.serialize_field("file", &file_name)?; + state.serialize_field("line_lo", &lo.line)?; + state.serialize_field("line_hi", &hi.line)?; + state.serialize_field("col_lo", &lo.col.0)?; + state.serialize_field("col_hi", &hi.col.0)?; + state.end() + } +} + +/// Different ways to refer to a changed item. +/// +/// Used in the header of a change description to identify an item that was subject to change. +pub enum Name { + /// The changed item's name. + Symbol(RSymbol), + /// A textutal description of the item, used for trait impls. + ImplDesc(String), +} + +impl Name { + pub fn symbol(symbol: Symbol) -> Self { + Self::Symbol(RSymbol(symbol)) + } +} + +impl fmt::Display for Name { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Self::Symbol(ref name) => write!(f, "`{}`", name.0), + Self::ImplDesc(ref desc) => write!(f, "`{}`", desc), + } + } +} + +impl Serialize for Name { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match *self { + Self::Symbol(ref name) => serializer.serialize_str(&format!("{}", name.0)), + Self::ImplDesc(ref desc) => serializer.serialize_str(desc), + } + } +} + +/// A change record of newly introduced or removed paths to an item. +/// +/// NB: `Eq` and `Ord` instances are constructed to only regard the span of the associated item +/// definition. All other spans are only present for later display of the change record. +pub struct PathChange { + /// The name of the item - this doesn't use `Name` because this change structure only gets + /// generated for removals and additions of named items, not impls. + name: RSymbol, + /// The definition span of the item. + def_span: Span, + /// The set of spans of added exports of the item. + additions: BTreeSet, + /// The set of spans of removed exports of the item. + removals: BTreeSet, +} + +impl PathChange { + /// Construct a new empty path change record for an item. + fn new(name: Symbol, def_span: Span) -> Self { + Self { + name: RSymbol(name), + def_span, + additions: BTreeSet::new(), + removals: BTreeSet::new(), + } + } + + /// Insert a new span addition or deletion into an existing path change record. + fn insert(&mut self, span: Span, add: bool) { + if add { + self.additions.insert(span); + } else { + self.removals.insert(span); + } + } + + /// Get the change's category. + pub fn to_category(&self) -> ChangeCategory { + if !self.removals.is_empty() { + Breaking + } else if self.additions.is_empty() { + Patch + } else { + TechnicallyBreaking + } + } + + /// Get the change item's definition span. + pub fn span(&self) -> &Span { + &self.def_span + } + + /// Report the change in a structured manner, using rustc's error reporting capabilities. + fn report(&self, session: &Session) { + let cat = self.to_category(); + if cat == Patch { + return; + } + + let msg = format!("path changes to `{}`", self.name.0); + let mut builder = if cat == Breaking { + session.struct_span_err(self.def_span, &msg) + } else { + session.struct_span_warn(self.def_span, &msg) + }; + + for removed_span in &self.removals { + if *removed_span == self.def_span { + builder.warn("removed definition (breaking)"); + } else { + builder.span_warn(*removed_span, "removed path (breaking)"); + } + } + + for added_span in &self.additions { + if *added_span == self.def_span { + builder.note("added definition (technically breaking)"); + } else { + builder.span_note(*added_span, "added path (technically breaking)"); + } + } + + builder.emit(); + } +} + +impl PartialEq for PathChange { + fn eq(&self, other: &Self) -> bool { + self.span() == other.span() + } +} + +impl Eq for PathChange {} + +impl PartialOrd for PathChange { + fn partial_cmp(&self, other: &Self) -> Option { + self.span().partial_cmp(other.span()) + } +} + +impl Ord for PathChange { + fn cmp(&self, other: &Self) -> Ordering { + self.span().cmp(other.span()) + } +} + +struct RPathChange<'a>(&'a Session, &'a PathChange); + +impl<'a> Serialize for RPathChange<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut state = serializer.serialize_struct("PathChange", 4)?; + state.serialize_field("name", &self.1.name)?; + state.serialize_field("def_span", &RSpan(self.0, &self.1.def_span))?; + + let additions: Vec<_> = self.1.additions.iter().map(|s| RSpan(self.0, s)).collect(); + + state.serialize_field("additions", &additions)?; + + let removals: Vec<_> = self.1.removals.iter().map(|s| RSpan(self.0, s)).collect(); + + state.serialize_field("removals", &removals)?; + + state.end() + } +} + +/// The types of changes we identify between items present in both crate versions. +#[derive(Clone, Debug)] +pub enum ChangeType<'tcx> { + /// An item has been made public. + ItemMadePublic, + /// An item has been made private. + ItemMadePrivate, + /// An item has changed it's kind. + KindDifference, + /// A `static` item changed it's mutablity. + StaticMutabilityChanged { now_mut: bool }, + /// The variance of a type or region parameter has gone from invariant to co- or + /// contravariant or to bivariant. + VarianceLoosened, + /// The variance of a type or region parameter has gone from bivariant to co- or + /// contravariant or to invariant. + VarianceTightened, + /// The variance of a type or region parameter has changed from covariant to contravariant + /// or vice-versa. + VarianceChanged { now_contravariant: bool }, + /// A region parameter has been added to an item. + RegionParameterAdded, + /// A region parameter has been removed from an item. + RegionParameterRemoved, + /// A possibly defaulted type parameter has been added to an item. + TypeParameterAdded { defaulted: bool }, + /// A possibly defaulted type parameter has been removed from an item. + TypeParameterRemoved { defaulted: bool }, + /// A variant has been added to an enum. + VariantAdded, + /// A variant has been removed from an enum. + VariantRemoved, + /// A possibly public field has been added to a variant or struct. + /// + /// This also records whether all fields are public were public before the change. + VariantFieldAdded { + public: bool, + total_public: bool, + is_enum: bool, + }, + /// A possibly public field has been removed from a variant or struct. + /// + /// This also records whether all fields were public before the change. + VariantFieldRemoved { + public: bool, + total_public: bool, + is_enum: bool, + }, + /// A variant or struct has changed it's style. + /// + /// The style could have been changed from a tuple variant/struct to a regular + /// struct/struct variant or vice versa. Whether all fields were private prior to the change + /// is also recorded. + VariantStyleChanged { + now_struct: bool, + total_private: bool, + is_enum: bool, + }, + /// A function has changed it's constness. + FnConstChanged { now_const: bool }, + /// A method either gained or lost a `self` parameter. + MethodSelfChanged { now_self: bool }, + /// A trait's definition added a possibly defaulted item. + TraitItemAdded { defaulted: bool, sealed_trait: bool }, + /// A trait's definition removed a possibly defaulted item. + TraitItemRemoved { defaulted: bool }, + /// A trait's definition changed it's unsafety. + TraitUnsafetyChanged { now_unsafe: bool }, + /// An item's type has changed. + TypeChanged { error: TypeError<'tcx> }, + /// An item's (trait) bounds have been tightened. + BoundsTightened { pred: Predicate<'tcx> }, + /// An item's (trait) bounds have been loosened. + /// + /// This includes information on whether the affected item is a trait definition, since + /// removing trait bounds on those is *breaking* (as it invalidates the assumption that a + /// supertrait is implemented for each type implementing the traits). + BoundsLoosened { + pred: Predicate<'tcx>, + trait_def: bool, + }, + /// A trait impl has been specialized or removed for some type(s). + TraitImplTightened, + /// A trait impl has been generalized or newly added for some type(s). + TraitImplLoosened, + /// An associated item has been newly added to some inherent impls. + AssociatedItemAdded, + /// An associated item has been removed from some inherent impls. + AssociatedItemRemoved, + /// An unknown change we don't yet explicitly handle. + Unknown, +} + +pub use self::ChangeType::*; + +impl<'tcx> ChangeType<'tcx> { + /// Get the change type's category. + pub fn to_category(&self) -> ChangeCategory { + // TODO: slightly messy and unreadable. + match *self { + ItemMadePrivate | + KindDifference | + StaticMutabilityChanged { now_mut: false } | + VarianceTightened | + VarianceChanged { .. } | + RegionParameterAdded | + RegionParameterRemoved | + TypeParameterAdded { defaulted: false } | + TypeParameterRemoved { .. } | + VariantAdded | + VariantRemoved | + VariantFieldAdded { public: true, .. } | + VariantFieldAdded { public: false, total_public: true, .. } | + VariantFieldRemoved { public: true, .. } | + VariantFieldRemoved { public: false, is_enum: true, .. } | + VariantStyleChanged { .. } | + TypeChanged { .. } | + FnConstChanged { now_const: false } | + MethodSelfChanged { now_self: false } | + TraitItemAdded { defaulted: false, sealed_trait: false } | + TraitItemRemoved { .. } | + TraitUnsafetyChanged { .. } | + BoundsTightened { .. } | + BoundsLoosened { trait_def: true, .. } | + TraitImplTightened | + AssociatedItemRemoved | + Unknown => Breaking, + MethodSelfChanged { now_self: true } | + TraitItemAdded { .. } | // either defaulted or sealed + BoundsLoosened { trait_def: false, .. } | + TraitImplLoosened | + AssociatedItemAdded | + ItemMadePublic => TechnicallyBreaking, + StaticMutabilityChanged { now_mut: true } | + VarianceLoosened | + TypeParameterAdded { defaulted: true } | + VariantFieldAdded { public: false, .. } | + VariantFieldRemoved { public: false, .. } | + FnConstChanged { now_const: true } => NonBreaking, + } + } + + /// Get a detailed explanation of a change, and why it is categorized as-is. + fn explanation(&self) -> &'static str { + match *self { + ItemMadePublic => { + "Adding an item to a module's public interface is generally a non-breaking +change, except in the special case of wildcard imports in user code, where +they can cause nameclashes. Thus, the change is classified as \"technically +breaking\"." + } + ItemMadePrivate => { + "Removing an item from a module's public interface is a breaking change." + } + KindDifference => { + "Changing the \"kind\" of an item between versions is a breaking change, +because the usage of the old and new version of the item need not be +compatible." + } + StaticMutabilityChanged { now_mut: true } => { + "Making a static item mutable is a non-breaking change, because any (old) +user code is guaranteed to use them in a read-only fashion." + } + StaticMutabilityChanged { now_mut: false } => { + "Making a static item immutable is a breaking change, because any (old) +user code that tries to mutate them will break." + } + VarianceLoosened => { + "The variance of a type or region parameter in an item loosens if an invariant +parameter becomes co-, contra- or bivariant, or a co- or contravariant parameter becomes +bivariant. See https://doc.rust-lang.org/nomicon/subtyping.html for an explanation of the +concept of variance in Rust." + } + VarianceTightened => { + "The variance of a type or region parameter in an item tightens if a variant +parameter becomes co-, contra- or invariant, or a co- or contravairant parameter becomes +invariant. See https://doc.rust-lang.org/nomicon/subtyping.html for an explanation of the +concept of variance in Rust." + } + VarianceChanged { .. } => { + "Switching the variance of a type or region parameter is breaking if it is +changed from covariant to contravariant, or vice-versa. +See https://doc.rust-lang.org/nomicon/subtyping.html for an explanation of the concept of +variance in Rust." + } + RegionParameterAdded => { + "Adding a new region parameter is a breaking change, because it can break +explicit type annotations, as well as prevent region inference working as +before." + } + RegionParameterRemoved => { + "Removing a region parameter is a breaking change, because it can break +explicit type annotations, as well as prevent region inference working as +before." + } + TypeParameterAdded { defaulted: true } => { + "Adding a new defaulted type parameter is a non-breaking change, because +all old references to the item are still valid, provided that no type +errors appear." + } + TypeParameterAdded { defaulted: false } => { + "Adding a new non-defaulted type parameter is a breaking change, because +old references to the item become invalid in cases where the type parameter +can't be inferred." + } + TypeParameterRemoved { .. } => { + "Removing any type parameter, defaulted or not, is a breaking change, +because old references to the item are become invalid if the type parameter +is instantiated in a manner not compatible with the new type of the item." + } + VariantAdded => { + "Adding a new enum variant is a breaking change, because a match expression +on said enum can become non-exhaustive." + } + VariantRemoved => { + "Removing an enum variant is a braking change, because every old reference +to the removed variant is rendered invalid." + } + VariantFieldAdded { .. } => { + "Adding a field to an enum variant or struct is breaking, as matches on the +variant or struct are invalidated. In case of structs, this only holds for +public fields, or the first private field being added." + } + VariantFieldRemoved { .. } => { + "Removing a field from an enum variant or struct is breaking, as matches on the +variant are invalidated. In case of structs, this only holds for public fields." + } + VariantStyleChanged { .. } => { + "Changing the style of a variant is a breaking change, since most old +references to it are rendered invalid: pattern matches and value +construction needs to use the other constructor syntax, respectively." + } + FnConstChanged { now_const: true } => { + "Making a function const is a non-breaking change, because a const function +can appear anywhere a regular function is expected." + } + FnConstChanged { now_const: false } => { + "Making a const function non-const is a breaking change, because values +assigned to constants can't be determined by expressions containing +non-const functions." + } + MethodSelfChanged { now_self: true } => { + "Adding a self parameter to a method is a breaking change in some specific +situations: When user code implements it's own trait on the type the +method is implemented on, the new method could cause a nameclash with a +trait method, thus breaking user code. Because this is a rather special +case, this change is classified as \"technically breaking\"." + } + MethodSelfChanged { now_self: false } => { + "Removing a self parameter from a method is a breaking change, because +all method invocations using the method syntax become invalid." + } + TraitItemAdded { + defaulted: true, .. + } => { + "Adding a new defaulted trait item is a breaking change in some specific +situations: The new trait item could cause a name clash with traits +defined in user code. Because this is a rather special case, this change +is classified as \"technically breaking\"." + } + TraitItemAdded { + sealed_trait: true, .. + } => { + "Adding a new trait item is a non-breaking change, when user code can't +provide implementations of the trait, i.e. if the trait is sealed by +inheriting from an unnamable (crate-local) item." + } + TraitItemAdded { .. } => + // neither defaulted or sealed + { + "Adding a new non-defaulted trait item is a breaking change, because all +implementations of the trait in user code become invalid." + } + TraitItemRemoved { .. } => { + "Removing a trait item is a breaking change, because all old references +to the item become invalid." + } + TraitUnsafetyChanged { .. } => { + "Changing the unsafety of a trait is a breaking change, because all +implementations become invalid." + } + TypeChanged { .. } => { + "Changing the type of an item is a breaking change, because user code +using the item becomes type-incorrect." + } + BoundsTightened { .. } => { + "Tightening the bounds of a lifetime or type parameter is a breaking +change, because all old references instantiating the parameter with a +type or lifetime not fulfilling the bound are rendered invalid." + } + BoundsLoosened { + trait_def: true, .. + } => { + "Loosening the bounds of a lifetime or type parameter in a trait +definition is a breaking change, because the assumption in user code +that the bound in question hold is violated, potentially invalidating +trait implementation or usage." + } + BoundsLoosened { + trait_def: false, .. + } => { + "Loosening the bounds of a lifetime or type parameter in a non-trait +definition is a non-breaking change, because all old references to the +item would remain valid." + } + TraitImplTightened => { + "Effectively removing a trait implementation for a (possibly +parametrized) type is a breaking change, as all old references to trait +methods on the type become invalid." + } + TraitImplLoosened => { + "Effectively adding a trait implementation for a (possibly +parametrized) type is a breaking change in some specific situations, +as name clashes with other trait implementations in user code can be +caused." + } + AssociatedItemAdded => { + "Adding a new item to an inherent impl is a breaking change in some +specific situations, for example if this causes name clashes with a trait +method. This is rare enough to only be considered \"technically +breaking\"." + } + AssociatedItemRemoved => { + "Removing an item from an inherent impl is a breaking change, as all old +references to it become invalid." + } + Unknown => "No explanation for unknown changes.", + } + } +} + +impl<'a> fmt::Display for ChangeType<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let desc = match *self { + ItemMadePublic => "item made public", + ItemMadePrivate => "item made private", + KindDifference => "item kind changed", + StaticMutabilityChanged { now_mut: true } => "static item made mutable", + StaticMutabilityChanged { now_mut: false } => "static item made immutable", + VarianceLoosened => "variance loosened", + VarianceTightened => "variance tightened", + VarianceChanged { + now_contravariant: true, + } => "variance changed from co- to contravariant", + VarianceChanged { + now_contravariant: false, + } => "variance changed from contra- to covariant", + RegionParameterAdded => "region parameter added", + RegionParameterRemoved => "region parameter removed", + TypeParameterAdded { defaulted: true } => "defaulted type parameter added", + TypeParameterAdded { defaulted: false } => "type parameter added", + TypeParameterRemoved { defaulted: true } => "defaulted type parameter removed", + TypeParameterRemoved { defaulted: false } => "type parameter removed", + VariantAdded => "enum variant added", + VariantRemoved => "enum variant removed", + VariantFieldAdded { + public: true, + total_public: true, + is_enum: true, + } => "public field added to variant with no private fields", + VariantFieldAdded { + public: true, + total_public: true, + is_enum: false, + } => "public field added to struct with no private fields", + VariantFieldAdded { + public: true, + total_public: false, + is_enum: true, + } => "public field added to variant with private fields", + VariantFieldAdded { + public: true, + total_public: false, + is_enum: false, + } => "public field added to struct with private fields", + VariantFieldAdded { + public: false, + total_public: true, + is_enum: true, + } => "private field added to variant with no private fields", + VariantFieldAdded { + public: false, + total_public: true, + is_enum: false, + } => "private field added to struct with no private fields", + VariantFieldAdded { + public: false, + total_public: false, + is_enum: true, + } => "private field added to variant with private fields", + VariantFieldAdded { + public: false, + total_public: false, + is_enum: false, + } => "private field added to struct with private fields", + VariantFieldRemoved { + public: true, + total_public: true, + is_enum: true, + } => "public field removed from variant with no private fields", + VariantFieldRemoved { + public: true, + total_public: true, + is_enum: false, + } => "public field removed from struct with no private fields", + VariantFieldRemoved { + public: true, + total_public: false, + is_enum: true, + } => "public field removed from variant with private fields", + VariantFieldRemoved { + public: true, + total_public: false, + is_enum: false, + } => "public field removed from struct with private fields", + VariantFieldRemoved { + public: false, + total_public: true, + is_enum: true, + } => "private field removed from variant with no private fields", + VariantFieldRemoved { + public: false, + total_public: true, + is_enum: false, + } => "private field removed from struct with no private fields", + VariantFieldRemoved { + public: false, + total_public: false, + is_enum: true, + } => "private field removed from variant with private fields", + VariantFieldRemoved { + public: false, + total_public: false, + is_enum: false, + } => "private field removed from struct with private fields", + VariantStyleChanged { + now_struct: true, + total_private: true, + is_enum: true, + } => "variant with no public fields changed to a struct variant", + VariantStyleChanged { + now_struct: true, + total_private: true, + is_enum: false, + } => "tuple struct with no public fields changed to a regular struct", + VariantStyleChanged { + now_struct: true, + total_private: false, + is_enum: true, + } => "variant with public fields changed to a struct variant", + VariantStyleChanged { + now_struct: true, + total_private: false, + is_enum: false, + } => "tuple struct with public fields changed to a regular struct", + VariantStyleChanged { + now_struct: false, + total_private: true, + is_enum: true, + } => "variant with no public fields changed to a tuple variant", + VariantStyleChanged { + now_struct: false, + total_private: true, + is_enum: false, + } => "struct with no public fields changed to a tuple struct", + VariantStyleChanged { + now_struct: false, + total_private: false, + is_enum: true, + } => "variant with public fields changed to a tuple variant", + VariantStyleChanged { + now_struct: false, + total_private: false, + is_enum: false, + } => "struct with public fields changed to a tuple struct", + FnConstChanged { now_const: true } => "fn item made const", + FnConstChanged { now_const: false } => "fn item made non-const", + MethodSelfChanged { now_self: true } => "added self-argument to method", + MethodSelfChanged { now_self: false } => "removed self-argument from method", + TraitItemAdded { + defaulted: true, .. + } => "added defaulted item to trait", + TraitItemAdded { + defaulted: false, + sealed_trait: true, + } => "added item to sealed trait", + TraitItemAdded { .. } => "added item to trait", + TraitItemRemoved { defaulted: true } => "removed defaulted item from trait", + TraitItemRemoved { defaulted: false } => "removed item from trait", + TraitUnsafetyChanged { now_unsafe: true } => "trait made unsafe", + TraitUnsafetyChanged { now_unsafe: false } => "trait no longer unsafe", + TypeChanged { ref error } => return write!(f, "type error: {}", error), + BoundsTightened { ref pred } => return write!(f, "added bound: `{}`", pred), + BoundsLoosened { + ref pred, + trait_def, + } => { + if trait_def { + return write!(f, "removed bound on trait definition: `{}`", pred); + } else { + return write!(f, "removed bound: `{}`", pred); + } + } + TraitImplTightened => "trait impl specialized or removed", + TraitImplLoosened => "trait impl generalized or newly added", + AssociatedItemAdded => "added item in inherent impl", + AssociatedItemRemoved => "removed item in inherent impl", + Unknown => "unknown change", + }; + write!(f, "{}", desc) + } +} + +impl<'tcx> Serialize for ChangeType<'tcx> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&format!("{}", self)) + } +} + +/// A change record of an item present in both crate versions. +/// +/// NB: `Eq` and `Ord` instances are constucted to only regard the *new* span of the associated +/// item definition. This allows us to sort them by appearance in the *new* source. +pub struct Change<'tcx> { + /// The types of changes affecting the item, with optional subspans. + changes: Vec<(ChangeType<'tcx>, Option)>, + /// The most severe change category already recorded for the item. + max: ChangeCategory, + /// The name of the item. + name: Name, + /// The new definition span of the item. + new_span: Span, + /// Whether to output changes. Used to distinguish all-private items. + output: bool, +} + +impl<'tcx> Change<'tcx> { + /// Construct a new empty change record for an item. + fn new(name: Name, span: Span, output: bool) -> Change<'tcx> { + Change { + changes: Vec::new(), + max: ChangeCategory::default(), + name, + new_span: span, + output, + } + } + + /// Insert another change type into an existing path change record. + fn insert(&mut self, type_: ChangeType<'tcx>, span: Option) { + let cat = type_.to_category(); + + if cat > self.max { + self.max = cat; + } + + self.changes.push((type_, span)); + } + + /// Check whether a trait item contains breaking changes preventing further analysis of it's + /// child items. + /// + /// NB: The invariant that the item in question is actually a trait item isn't checked. + fn trait_item_breaking(&self) -> bool { + for change in &self.changes { + match change.0 { + ItemMadePrivate + | KindDifference + | RegionParameterRemoved + | TypeParameterRemoved { .. } + | VariantAdded + | VariantRemoved + | VariantFieldAdded { .. } + | VariantFieldRemoved { .. } + | VariantStyleChanged { .. } + | TypeChanged { .. } + | FnConstChanged { now_const: false } + | MethodSelfChanged { now_self: false } + | Unknown => return true, + StaticMutabilityChanged { .. } + | RegionParameterAdded + | MethodSelfChanged { now_self: true } + | TraitItemAdded { .. } + | TraitItemRemoved { .. } + | ItemMadePublic + | VarianceLoosened + | VarianceTightened + | VarianceChanged { .. } + | TypeParameterAdded { .. } + | TraitUnsafetyChanged { .. } + | FnConstChanged { now_const: true } + | BoundsTightened { .. } + | BoundsLoosened { .. } + | TraitImplTightened + | TraitImplLoosened + | AssociatedItemAdded + | AssociatedItemRemoved => (), + } + } + + false + } + + /// Get the change's category. + fn to_category(&self) -> ChangeCategory { + self.max + } + + /// Get the new span of the change item. + fn new_span(&self) -> &Span { + &self.new_span + } + + /// Report the change in a structured manner, using rustc's error reporting capabilities. + fn report(&self, session: &Session, verbose: bool) { + if self.max == Patch || !self.output { + return; + } + + let msg = format!("{} changes in {}", self.max, self.name); + let mut builder = if self.max == Breaking { + session.struct_span_err(self.new_span, &msg) + } else { + session.struct_span_warn(self.new_span, &msg) + }; + + for change in &self.changes { + let cat = change.0.to_category(); + let sub_msg = if verbose { + format!("{} ({}):\n{}", change.0, cat, change.0.explanation()) + } else { + format!("{} ({})", change.0, cat) + }; + + if let Some(span) = change.1 { + if cat == Breaking { + builder.span_warn(span, &sub_msg); + } else { + builder.span_note(span, &sub_msg); + } + } else if cat == Breaking { + // change.1 == None from here on. + builder.warn(&sub_msg); + } else { + builder.note(&sub_msg); + } + } + + builder.emit(); + } +} + +impl<'tcx> PartialEq for Change<'tcx> { + fn eq(&self, other: &Change) -> bool { + self.new_span() == other.new_span() + } +} + +impl<'tcx> Eq for Change<'tcx> {} + +impl<'tcx> PartialOrd for Change<'tcx> { + fn partial_cmp(&self, other: &Change<'tcx>) -> Option { + self.new_span().partial_cmp(other.new_span()) + } +} + +impl<'tcx> Ord for Change<'tcx> { + fn cmp(&self, other: &Change<'tcx>) -> Ordering { + self.new_span().cmp(other.new_span()) + } +} + +struct RChange<'a, 'tcx>(&'a Session, &'a Change<'tcx>); + +impl<'a, 'tcx> Serialize for RChange<'a, 'tcx> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut state = serializer.serialize_struct("Change", 4)?; + state.serialize_field("name", &self.1.name)?; + state.serialize_field("max_category", &self.1.max)?; + state.serialize_field("new_span", &RSpan(self.0, &self.1.new_span))?; + + let changes: Vec<_> = self + .1 + .changes + .iter() + .map(|(t, s)| (t, s.as_ref().map(|s| RSpan(self.0, s)))) + .collect(); + + state.serialize_field("changes", &changes)?; + state.end() + } +} + +/// The total set of changes recorded for two crate versions. +#[derive(Default)] +pub struct ChangeSet<'tcx> { + /// The set of currently recorded path changes. + path_changes: HashMap, + /// The set of currently recorded regular changes. + changes: HashMap>, + /// The mapping of spans to changes, for ordering purposes. + spans: BTreeMap, + /// The most severe change category already recorded. + max: ChangeCategory, +} + +impl<'tcx> ChangeSet<'tcx> { + /// Add a new path change entry for the given item. + pub fn new_path_change(&mut self, old: DefId, name: Symbol, def_span: Span) { + self.spans.entry(def_span).or_insert_with(|| old); + self.path_changes + .entry(old) + .or_insert_with(|| PathChange::new(name, def_span)); + } + + /// Add a new path addition to an already existing entry. + pub fn add_path_addition(&mut self, old: DefId, span: Span) { + self.add_path(old, span, true); + } + + /// Add a new path removal to an already existing entry. + pub fn add_path_removal(&mut self, old: DefId, span: Span) { + self.add_path(old, span, false); + } + + /// Add a new path change to an already existing entry. + fn add_path(&mut self, old: DefId, span: Span, add: bool) { + let cat = if add { TechnicallyBreaking } else { Breaking }; + + if cat > self.max { + self.max = cat; + } + + self.path_changes.get_mut(&old).unwrap().insert(span, add); + } + + /// Add a new change entry for the given item pair. + pub fn new_change( + &mut self, + old_def_id: DefId, + new_def_id: DefId, + name: Symbol, + old_span: Span, + new_span: Span, + output: bool, + ) { + let change = Change::new(Name::symbol(name), new_span, output); + + self.spans.insert(old_span, old_def_id); + self.spans.insert(new_span, new_def_id); + self.changes.insert(old_def_id, change); + } + + /// Add a new change entry for the given trait impl. + pub fn new_change_impl(&mut self, def_id: DefId, desc: String, span: Span) { + let change = Change::new(Name::ImplDesc(desc), span, true); + + self.spans.insert(span, def_id); + self.changes.insert(def_id, change); + } + + /// Add a new change to an already existing entry. + pub fn add_change(&mut self, type_: ChangeType<'tcx>, old: DefId, span: Option) { + let cat = type_.to_category(); + + if cat > self.max && self.get_output(old) { + self.max = cat; + } + + self.changes.get_mut(&old).unwrap().insert(type_, span); + } + + /// Check whether the changes associated with a `DefId` will be reported. + pub fn get_output(&self, old: DefId) -> bool { + self.changes.get(&old).map_or(true, |change| change.output) + } + + /// Set up reporting for the changes associated with a given `DefId`. + pub fn set_output(&mut self, old: DefId) { + let max = &mut self.max; + if let Some(change) = self.changes.get_mut(&old) { + let cat = change.to_category(); + + if cat > *max { + *max = cat; + } + + change.output = true; + } + } + + /// Check whether an item with the given id has undergone breaking changes. + /// + /// The expected `DefId` is obviously an *old* one. + pub fn item_breaking(&self, old: DefId) -> bool { + // we only care about items that were present in both versions. + self.changes + .get(&old) + .map_or(false, |change| change.to_category() == Breaking) + } + + /// Check whether a trait item contains breaking changes preventing further analysis of it's + /// child items. + pub fn trait_item_breaking(&self, old: DefId) -> bool { + self.changes + .get(&old) + .map_or(false, Change::trait_item_breaking) + } + + fn get_new_version(&self, version: &str) -> Option { + if let Ok(mut new_version) = Version::parse(version) { + if new_version.major == 0 { + new_version.increment_patch(); + } else { + match self.max { + Patch => new_version.increment_patch(), + NonBreaking | TechnicallyBreaking => new_version.increment_minor(), + Breaking => new_version.increment_major(), + } + } + + Some(format!("{}", new_version)) + } else { + None + } + } + + pub fn output_json(&self, session: &Session, version: &str) { + #[derive(Serialize)] + struct Output<'a, 'tcx> { + old_version: String, + new_version: String, + changes: RChangeSet<'a, 'tcx>, + } + + let new_version = self + .get_new_version(version) + .unwrap_or_else(|| "parse error".to_owned()); + + let output = Output { + old_version: version.to_owned(), + new_version, + changes: RChangeSet(session, self), + }; + + println!("{}", serde_json::to_string(&output).unwrap()); + } + + /// Format the contents of a change set for user output. + pub fn output( + &self, + session: &Session, + version: &str, + verbose: bool, + compact: bool, + api_guidelines: bool, + ) { + if let Some(new_version) = self.get_new_version(version) { + if compact { + println!("{}", new_version); + } else { + println!( + "version bump: {} -> ({}) -> {}", + version, self.max, new_version + ); + } + } else { + println!("max change: {}, could not parse {}", self.max, version); + } + + for key in self.spans.values() { + if let Some(change) = self.path_changes.get(key) { + if api_guidelines { + match change.to_category() { + Patch | Breaking => change.report(session), + _ => (), + } + } else { + change.report(session); + } + } + + if let Some(change) = self.changes.get(key) { + if api_guidelines { + match change.to_category() { + Patch | Breaking => change.report(session, verbose), + _ => (), + } + } else { + change.report(session, verbose); + } + } + } + } +} + +struct RPathChanges<'a>(&'a Session, Vec<&'a PathChange>); + +impl<'a> Serialize for RPathChanges<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut seq = serializer.serialize_seq(Some(self.1.len()))?; + + for e in &self.1 { + seq.serialize_element(&RPathChange(self.0, &e))?; + } + + seq.end() + } +} + +struct RChangeSet<'a, 'tcx>(&'a Session, &'a ChangeSet<'tcx>); + +impl<'a, 'tcx> Serialize for RChangeSet<'a, 'tcx> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut state = serializer.serialize_struct("ChangeSet", 3)?; + + let path_changes: Vec<_> = self.1.path_changes.values().collect(); + state.serialize_field("path_changes", &RPathChanges(self.0, path_changes))?; + + let changes: Vec<_> = self + .1 + .changes + .values() + .filter_map(|c| { + if c.output && !c.changes.is_empty() { + Some(RChange(self.0, c)) + } else { + None + } + }) + .collect(); + state.serialize_field("changes", &changes)?; + + state.serialize_field("max_category", &self.1.max)?; + state.end() + } +} + +#[cfg(test)] +pub mod tests { + pub use super::*; + extern crate quickcheck; + use quickcheck::*; + + use rustc_hir::def_id::DefId; + + use std::cmp::{max, min}; + + use rustc_span::hygiene::SyntaxContext; + use rustc_span::symbol::Interner; + use rustc_span::BytePos; + + /// A wrapper for `Span` that can be randomly generated. + #[derive(Clone, Debug)] + pub struct Span_(u32, u32); + + impl Span_ { + pub fn inner(self) -> Span { + Span::new(BytePos(self.0), BytePos(self.1), SyntaxContext::root()) + } + } + + impl Arbitrary for Span_ { + fn arbitrary(g: &mut G) -> Span_ { + let a: u32 = Arbitrary::arbitrary(g); + let b: u32 = Arbitrary::arbitrary(g); + Span_(min(a, b), max(a, b)) + } + } + + /// A wrapper for `DefId` that can be randomly generated. + #[derive(Clone, Debug)] + pub struct DefId_(DefId); + + impl DefId_ { + pub fn inner(self) -> DefId { + self.0 + } + } + + impl Arbitrary for DefId_ { + fn arbitrary(g: &mut G) -> DefId_ { + use rustc_hir::def_id::{CrateNum, DefIndex}; + + let a: u32 = Arbitrary::arbitrary(g); + let b: u32 = Arbitrary::arbitrary(g); + DefId_(DefId { + krate: CrateNum::new(a as usize), + index: DefIndex::from(b), + }) + } + } + + /// a rip-off of the real `ChangeType` that can be randomly generated. + #[derive(Clone, Debug)] + pub enum ChangeType_ { + ItemMadePublic, + ItemMadePrivate, + KindDifference, + RegionParameterAdded, + RegionParameterRemoved, + TypeParameterAdded { + defaulted: bool, + }, + TypeParameterRemoved { + defaulted: bool, + }, + VariantAdded, + VariantRemoved, + VariantFieldAdded { + public: bool, + total_public: bool, + is_enum: bool, + }, + VariantFieldRemoved { + public: bool, + total_public: bool, + is_enum: bool, + }, + VariantStyleChanged { + now_struct: bool, + total_private: bool, + is_enum: bool, + }, + FnConstChanged { + now_const: bool, + }, + MethodSelfChanged { + now_self: bool, + }, + TraitItemAdded { + defaulted: bool, + sealed_trait: bool, + }, + TraitItemRemoved { + defaulted: bool, + }, + TraitUnsafetyChanged { + now_unsafe: bool, + }, + Unknown, + } + + impl ChangeType_ { + fn inner<'a>(&self) -> ChangeType<'a> { + match *self { + ChangeType_::ItemMadePublic => ItemMadePublic, + ChangeType_::ItemMadePrivate => ItemMadePrivate, + ChangeType_::KindDifference => KindDifference, + ChangeType_::RegionParameterAdded => RegionParameterAdded, + ChangeType_::RegionParameterRemoved => RegionParameterRemoved, + ChangeType_::TypeParameterAdded { defaulted } => TypeParameterAdded { defaulted }, + ChangeType_::TypeParameterRemoved { defaulted } => { + TypeParameterRemoved { defaulted } + } + ChangeType_::VariantAdded => VariantAdded, + ChangeType_::VariantRemoved => VariantRemoved, + ChangeType_::VariantFieldAdded { + public, + total_public, + is_enum, + } => VariantFieldAdded { + public, + total_public, + is_enum, + }, + ChangeType_::VariantFieldRemoved { + public, + total_public, + is_enum, + } => VariantFieldRemoved { + public, + total_public, + is_enum, + }, + ChangeType_::VariantStyleChanged { + now_struct, + total_private, + is_enum, + } => VariantStyleChanged { + now_struct, + total_private, + is_enum, + }, + ChangeType_::FnConstChanged { now_const } => FnConstChanged { now_const }, + ChangeType_::MethodSelfChanged { now_self } => MethodSelfChanged { now_self }, + ChangeType_::TraitItemAdded { + defaulted, + sealed_trait, + } => TraitItemAdded { + defaulted, + sealed_trait, + }, + ChangeType_::TraitItemRemoved { defaulted } => TraitItemRemoved { defaulted }, + ChangeType_::TraitUnsafetyChanged { now_unsafe } => { + TraitUnsafetyChanged { now_unsafe } + } + ChangeType_::Unknown => Unknown, + } + } + } + + impl Arbitrary for ChangeType_ { + fn arbitrary(g: &mut G) -> ChangeType_ { + use self::ChangeType_::*; + use rand::seq::SliceRandom; + + let b1 = Arbitrary::arbitrary(g); + let b2 = Arbitrary::arbitrary(g); + + [ + ItemMadePublic, + ItemMadePrivate, + KindDifference, + RegionParameterAdded, + RegionParameterRemoved, + TypeParameterAdded { defaulted: b1 }, + TypeParameterRemoved { defaulted: b1 }, + VariantAdded, + VariantRemoved, + VariantFieldAdded { + public: b1, + total_public: b2, + is_enum: b2, + }, + VariantFieldRemoved { + public: b1, + total_public: b2, + is_enum: b2, + }, + VariantStyleChanged { + now_struct: b1, + total_private: b2, + is_enum: b2, + }, + FnConstChanged { now_const: b1 }, + MethodSelfChanged { now_self: b1 }, + TraitItemAdded { + defaulted: b1, + sealed_trait: b2, + }, + TraitItemRemoved { defaulted: b1 }, + TraitUnsafetyChanged { now_unsafe: b1 }, + Unknown, + ] + .choose(g) + .unwrap() + .clone() + } + } + + /// A wrapper type used to construct `Change`s. + pub type Change_ = ( + DefId_, + DefId_, + Span_, + Span_, + bool, + Vec<(ChangeType_, Option)>, + ); + + /// Construct `Change`s from things that can be generated. + fn build_change<'a>( + s1: Span, + output: bool, + changes: Vec<(ChangeType_, Option)>, + ) -> Change<'a> { + let mut interner = Interner::default(); + let mut change = Change::new(Name::Symbol(RSymbol(interner.intern("test"))), s1, output); + + for (type_, span) in changes { + change.insert(type_.inner(), span.map(|s| s.inner())); + } + + change + } + + /// A wrapper type used to construct `PathChange`s. + pub type PathChange_ = (DefId_, Span_, Vec<(bool, Span_)>); + + /// Construct `PathChange`s from things that can be generated. + fn build_path_change(s1: Span, spans: Vec<(bool, Span)>) -> PathChange { + let mut interner = Interner::default(); + let mut change = PathChange::new(interner.intern("test"), s1); + + for (add, span) in spans { + change.insert(span, add); + } + + change + } + + quickcheck! { + /// The `Ord` instance of `PathChange` is transitive. + fn ord_pchange_transitive(c1: PathChange_, c2: PathChange_, c3: PathChange_) -> bool { + let s1 = c1.2.iter().map(|&(add, ref s)| (add, s.clone().inner())).collect(); + let s2 = c2.2.iter().map(|&(add, ref s)| (add, s.clone().inner())).collect(); + let s3 = c3.2.iter().map(|&(add, ref s)| (add, s.clone().inner())).collect(); + + let ch1 = build_path_change(c1.1.inner(), s1); + let ch2 = build_path_change(c2.1.inner(), s2); + let ch3 = build_path_change(c3.1.inner(), s3); + + let mut res = true; + + if ch1 < ch2 && ch2 < ch3 { + res &= ch1 < ch3; + } + + if ch1 == ch2 && ch2 == ch3 { + res &= ch1 == ch3; + } + + if ch1 > ch2 && ch2 > ch3 { + res &= ch1 > ch3; + } + + res + } + + /// The `Ord` instance of `Change` is transitive. + fn ord_change_transitive(c1: Change_, c2: Change_, c3: Change_) -> bool { + let ch1 = build_change(c1.3.inner(), c1.4, c1.5); + let ch2 = build_change(c2.3.inner(), c2.4, c2.5); + let ch3 = build_change(c3.3.inner(), c3.4, c3.5); + + let mut res = true; + + if ch1 < ch2 && ch2 < ch3 { + res &= ch1 < ch3; + } + + if ch1 == ch2 && ch2 == ch3 { + res &= ch1 == ch3; + } + + if ch1 > ch2 && ch2 > ch3 { + res &= ch1 > ch3; + } + + res + } + + /// The maximal change category for a change set with regular changes only gets computed + /// correctly. + fn max_pchange(changes: Vec) -> bool { + let mut set = ChangeSet::default(); + + let mut interner = Interner::default(); + let name = interner.intern("test"); + + let max = changes + .iter() + .flat_map(|change| change.2.iter()) + .map(|&(c, _)| if c { TechnicallyBreaking } else { Breaking }) + .max() + .unwrap_or(Patch); + + for &(ref did, ref span, ref spans) in &changes { + let def_id = did.clone().inner(); + set.new_path_change(def_id, name, span.clone().inner()); + + for &(add, ref span) in spans { + if add { + set.add_path_addition(def_id, span.clone().inner()); + } else { + set.add_path_removal(def_id, span.clone().inner()); + } + } + } + + set.max == max + } + + /// The maximal change category for a change set with path changes only gets computed + /// correctly. + fn max_change(changes: Vec) -> bool { + let mut set = ChangeSet::default(); + + let mut interner = Interner::default(); + let name = interner.intern("test"); + + let max = changes + .iter() + .filter(|change| change.4) + .flat_map(|change| change.5.iter()) + .map(|&(ref type_, _)| type_.inner().to_category()) + .max() + .unwrap_or(Patch); + + for &(ref o_def_id, ref n_def_id, ref o_span, ref n_span, out, ref sub) in &changes { + let old_def_id = o_def_id.clone().inner(); + set.new_change(old_def_id, + n_def_id.clone().inner(), + name, + o_span.clone().inner(), + n_span.clone().inner(), + out); + + for &(ref type_, ref span_) in sub { + set.add_change(type_.clone().inner(), + old_def_id, + span_.clone().map(|s| s.inner())); + } + } + + set.max == max + } + + fn max_pchange_or_change(pchanges: Vec, changes: Vec) -> bool { + let mut set = ChangeSet::default(); + + let mut interner = Interner::default(); + let name = interner.intern("test"); + + let max = pchanges + .iter() + .flat_map(|change| change.2.iter()) + .map(|&(c, _)| if c { TechnicallyBreaking } else { Breaking }) + .chain(changes + .iter() + .filter(|change| change.4) + .flat_map(|change| change.5.iter()) + .map(|&(ref type_, _)| type_.inner().to_category())) + .max() + .unwrap_or(Patch); + + for &(ref did, ref span, ref spans) in &pchanges { + let def_id = did.clone().inner(); + set.new_path_change(def_id, name, span.clone().inner()); + + for &(add, ref span) in spans { + if add { + set.add_path_addition(def_id, span.clone().inner()); + } else { + set.add_path_removal(def_id, span.clone().inner()); + } + } + } + + for &(ref o_def_id, ref n_def_id, ref o_span, ref n_span, out, ref sub) in &changes { + let old_def_id = o_def_id.clone().inner(); + set.new_change(old_def_id, + n_def_id.clone().inner(), + name, + o_span.clone().inner(), + n_span.clone().inner(), + out); + + for &(ref type_, ref span_) in sub { + set.add_change(type_.clone().inner(), + old_def_id, + span_.clone().map(|s| s.inner())); + } + } + + set.max == max + } + + /// Difference in spans implies difference in `PathChange`s. + fn pchange_span_neq(c1: PathChange_, c2: PathChange_) -> bool { + let v1 = c1.2.iter().map(|&(add, ref s)| (add, s.clone().inner())).collect(); + let v2 = c2.2.iter().map(|&(add, ref s)| (add, s.clone().inner())).collect(); + + let s1 = c1.1.clone().inner(); + let s2 = c2.1.clone().inner(); + + if s1 != s2 { + let ch1 = build_path_change(s1, v1); + let ch2 = build_path_change(s2, v2); + + ch1 != ch2 + } else { + true + } + } + + /// Difference in spans implies difference in `Change`s. + fn bchange_span_neq(c1: Change_, c2: Change_) -> bool { + let s1 = c1.3.clone().inner(); + let s2 = c2.3.clone().inner(); + + if s1 != s2 { + let ch1 = build_change(c1.3.inner(), c1.4, c1.5); + let ch2 = build_change(c2.3.inner(), c2.4, c2.5); + + ch1 != ch2 + } else { + true + } + } + } +} diff --git a/src/tools/semverver/src/lib.rs b/src/tools/semverver/src/lib.rs new file mode 100644 index 0000000000000..9c603a7669210 --- /dev/null +++ b/src/tools/semverver/src/lib.rs @@ -0,0 +1,23 @@ +#![feature(rustc_private)] +#![allow(clippy::similar_names)] +#![allow(clippy::single_match_else)] +#![allow(clippy::too_many_lines)] +#![deny(warnings)] +extern crate rustc_ast; +extern crate rustc_hir; +extern crate rustc_infer; +extern crate rustc_middle; +extern crate rustc_mir; +extern crate rustc_session; +extern crate rustc_span; +extern crate rustc_trait_selection; +extern crate rustc_traits; + +mod changes; +mod mapping; +mod mismatch; +mod translate; +mod traverse; +mod typeck; + +pub use self::traverse::{run_analysis, run_traversal}; diff --git a/src/tools/semverver/src/mapping.rs b/src/tools/semverver/src/mapping.rs new file mode 100644 index 0000000000000..9de89d1dd7682 --- /dev/null +++ b/src/tools/semverver/src/mapping.rs @@ -0,0 +1,424 @@ +//! The implementation of various map data structures. +//! +//! This module provides facilities to record item correspondence of various kinds, as well as a +//! map used to temporarily match up unsorted item sequences' elements by name. + +use rustc_hir::{ + def::Res, + def_id::{CrateNum, DefId}, + HirId, +}; +use rustc_middle::{ + hir::exports::Export, + ty::{AssocKind, GenericParamDef, GenericParamDefKind}, +}; +use rustc_span::symbol::Symbol; +use std::collections::{BTreeSet, HashMap, HashSet, VecDeque}; +use std::hash::{Hash, Hasher}; + +/// A description of an item found in an inherent impl. +#[derive(Debug, PartialEq)] +pub struct InherentEntry { + /// The parent item's `DefId`. + pub parent_def_id: DefId, + /// The kind of the item. + pub kind: AssocKind, + /// The item's name. + pub name: Symbol, +} + +impl Eq for InherentEntry {} + +fn assert_impl_eq() {} + +#[allow(dead_code)] +fn assert_inherent_entry_members_impl_eq() { + assert_impl_eq::(); + + // FIXME derive Eq again once AssocKind impls Eq again. + // assert_impl_eq::(); + + assert_impl_eq::(); +} + +#[allow(clippy::derive_hash_xor_eq)] +impl Hash for InherentEntry { + fn hash(&self, hasher: &mut H) { + self.parent_def_id.hash(hasher); + + // FIXME derive Hash again once AssocKind derives Hash again. + match self.kind { + AssocKind::Const => 0_u8.hash(hasher), + AssocKind::Fn => 1_u8.hash(hasher), + AssocKind::Type => 2_u8.hash(hasher), + } + + self.name.hash(hasher); + } +} + +/// A set of pairs of impl- and item `DefId`s for inherent associated items. +pub type InherentImplSet = BTreeSet<(DefId, DefId)>; + +/// A mapping from old to new `DefId`s, as well as associated definitions, if applicable. +/// +/// Definitions and simple `DefId` mappings are kept separate to record both kinds of +/// correspondence losslessly. The *access* to the stored data happens through the same API, +/// however. A reverse mapping is also included, but only for `DefId` lookup. +#[cfg_attr(feature = "cargo-clippy", allow(clippy::module_name_repetitions))] +pub struct IdMapping { + /// The old crate. + old_crate: CrateNum, + /// The new crate. + new_crate: CrateNum, + /// Toplevel items' old `DefId` mapped to old and new `Res`. + toplevel_mapping: HashMap, + /// The set of items that have been removed or added and thus have no corresponding item in + /// the other crate. + non_mapped_items: HashSet, + /// Trait items' old `DefId` mapped to old and new `Res`, and the enclosing trait's `DefId`. + trait_item_mapping: HashMap, + /// The set of private traits in both crates. + private_traits: HashSet, + /// Other items' old `DefId` mapped to new `DefId`. + internal_mapping: HashMap, + /// Children mapping, allowing us to enumerate descendants in `AdtDef`s. + child_mapping: HashMap>, + /// New `DefId`s mapped to their old counterparts. + reverse_mapping: HashMap, + /// Type parameters' `DefId`s mapped to their definitions. + type_params: HashMap, + /// Map from inherent impls' descriptors to the impls they are declared in. + inherent_items: HashMap, +} + +impl IdMapping { + /// Construct a new mapping with the given crate information. + pub fn new(old_crate: CrateNum, new_crate: CrateNum) -> Self { + Self { + old_crate, + new_crate, + toplevel_mapping: HashMap::new(), + non_mapped_items: HashSet::new(), + trait_item_mapping: HashMap::new(), + private_traits: HashSet::new(), + internal_mapping: HashMap::new(), + child_mapping: HashMap::new(), + reverse_mapping: HashMap::new(), + type_params: HashMap::new(), + inherent_items: HashMap::new(), + } + } + + /// Register two exports representing the same item across versions. + pub fn add_export(&mut self, old: Res, new: Res) -> bool { + let (old_def_id, new_def_id) = + if let (Some(old_def_id), Some(new_def_id)) = (old.opt_def_id(), new.opt_def_id()) { + (old_def_id, new_def_id) + } else { + return false; + }; + + if !self.in_old_crate(old_def_id) || self.toplevel_mapping.contains_key(&old_def_id) { + return false; + } + + self.toplevel_mapping.insert(old_def_id, (old, new)); + self.reverse_mapping.insert(new_def_id, old_def_id); + + true + } + + /// Register that an old item has no corresponding new item. + pub fn add_non_mapped(&mut self, def_id: DefId) { + self.non_mapped_items.insert(def_id); + } + + /// Add any trait item's old and new `DefId`s. + pub fn add_trait_item(&mut self, old: Res, new: Res, old_trait: DefId) { + let old_def_id = old.def_id(); + + assert!(self.in_old_crate(old_def_id)); + + self.trait_item_mapping + .insert(old_def_id, (old, new, old_trait)); + self.reverse_mapping.insert(new.def_id(), old_def_id); + } + + /// Add a private trait's `DefId`. + pub fn add_private_trait(&mut self, trait_def_id: DefId) { + self.private_traits.insert(trait_def_id); + } + + /// Add any other item's old and new `DefId`s. + pub fn add_internal_item(&mut self, old: DefId, new: DefId) { + assert!( + !self.internal_mapping.contains_key(&old), + "bug: overwriting {:?} => {:?} with {:?}!", + old, + self.internal_mapping[&old], + new + ); + assert!(self.in_old_crate(old)); + assert!(self.in_new_crate(new)); + + self.internal_mapping.insert(old, new); + self.reverse_mapping.insert(new, old); + } + + /// Add any other item's old and new `DefId`s, together with a parent entry. + pub fn add_subitem(&mut self, old_parent: DefId, old: DefId, new: DefId) { + // NB: we rely on the asserts in `add_internal_item` here. + self.add_internal_item(old, new); + self.child_mapping + .entry(old_parent) + .or_insert_with(Default::default) + .insert(old); + } + + /// Record that a `DefId` represents a type parameter. + pub fn add_type_param(&mut self, param: &GenericParamDef) { + match param.kind { + GenericParamDefKind::Lifetime => unreachable!(), + GenericParamDefKind::Type { .. } => (), + GenericParamDefKind::Const => unreachable!(), + }; + + self.type_params.insert(param.def_id, param.clone()); + } + + /// Get the type parameter represented by a given `DefId`. + pub fn get_type_param(&self, did: &DefId) -> &GenericParamDef { + &self.type_params[did] + } + + /// Check whether a `DefId` represents a non-mapped defaulted type parameter. + pub fn is_non_mapped_defaulted_type_param(&self, def_id: DefId) -> bool { + self.non_mapped_items.contains(&def_id) + && self + .type_params + .get(&def_id) + .map_or(false, |def| match def.kind { + GenericParamDefKind::Type { has_default, .. } => has_default, + _ => unreachable!(), + }) + } + + /// Record an item from an inherent impl. + pub fn add_inherent_item( + &mut self, + parent_def_id: DefId, + kind: AssocKind, + name: Symbol, + impl_def_id: DefId, + item_def_id: DefId, + ) { + self.inherent_items + .entry(InherentEntry { + parent_def_id, + kind, + name, + }) + .or_insert_with(Default::default) + .insert((impl_def_id, item_def_id)); + } + + /// Get the impl data for an inherent item. + pub fn get_inherent_impls(&self, inherent_entry: &InherentEntry) -> Option<&InherentImplSet> { + self.inherent_items.get(inherent_entry) + } + + /// Get the new `DefId` associated with the given old one. + pub fn get_new_id(&self, old: DefId) -> Option { + assert!(!self.in_new_crate(old)); + + if self.in_old_crate(old) { + if let Some(new) = self.toplevel_mapping.get(&old) { + Some(new.1.def_id()) + } else if let Some(new) = self.trait_item_mapping.get(&old) { + Some(new.1.def_id()) + } else if let Some(new_def_id) = self.internal_mapping.get(&old) { + Some(*new_def_id) + } else { + None + } + } else { + Some(old) + } + } + + /// Get the old `DefId` associated with the given new one. + pub fn get_old_id(&self, new: DefId) -> Option { + assert!(!self.in_old_crate(new)); + + if self.in_new_crate(new) { + self.reverse_mapping.get(&new).cloned() + } else { + Some(new) + } + } + + /// Return the `DefId` of the trait a given item belongs to. + pub fn get_trait_def(&self, item_def_id: DefId) -> Option { + self.trait_item_mapping.get(&item_def_id).map(|t| t.2) + } + + /// Check whether the given `DefId` is a private trait. + pub fn is_private_trait(&self, trait_def_id: DefId) -> bool { + self.private_traits.contains(&trait_def_id) + } + + /// Check whether an old `DefId` is present in the mappings. + pub fn contains_old_id(&self, old: DefId) -> bool { + self.toplevel_mapping.contains_key(&old) + || self.trait_item_mapping.contains_key(&old) + || self.internal_mapping.contains_key(&old) + } + + /// Check whether a new `DefId` is present in the mappings. + pub fn contains_new_id(&self, new: DefId) -> bool { + self.reverse_mapping.contains_key(&new) + } + + /// Construct a queue of toplevel item pairs' `DefId`s. + pub fn toplevel_queue(&self) -> VecDeque<(Res, Res)> { + self.toplevel_mapping.values().copied().collect() + } + + /// Iterate over the toplevel and trait item pairs. + pub fn items<'a>(&'a self) -> impl Iterator + 'a { + self.toplevel_mapping + .values() + .cloned() + .chain(self.trait_item_mapping.values().map(|&(o, n, _)| (o, n))) + } + + /// Iterate over the item pairs of all children of a given item. + pub fn children_of<'a>( + &'a self, + parent: DefId, + ) -> Option + 'a> { + self.child_mapping + .get(&parent) + .map(|m| m.iter().map(move |old| (*old, self.internal_mapping[old]))) + } + + /// Iterate over all items in inherent impls. + pub fn inherent_impls(&self) -> impl Iterator { + self.inherent_items.iter() + } + + /// Check whether a `DefId` belongs to an item in the old crate. + pub fn in_old_crate(&self, did: DefId) -> bool { + self.old_crate == did.krate + } + + /// Get the old crate's `CrateNum`. + pub fn get_old_crate(&self) -> CrateNum { + self.old_crate + } + + /// Check whether a `DefId` belongs to an item in the new crate. + pub fn in_new_crate(&self, did: DefId) -> bool { + self.new_crate == did.krate + } + + /// Get the new crate's `CrateNum`. + pub fn get_new_crate(&self) -> CrateNum { + self.new_crate + } +} + +/// An export that could be missing from one of the crate versions. +type OptionalExport = Option>; + +/// A mapping from names to pairs of old and new exports. +/// +/// Both old and new exports can be missing. Allows for reuse of the `HashMap`s used for storage. +#[derive(Default)] +#[cfg_attr(feature = "cargo-clippy", allow(clippy::module_name_repetitions))] +pub struct NameMapping { + /// The exports in the type namespace. + type_map: HashMap, + /// The exports in the value namespace. + value_map: HashMap, + /// The exports in the macro namespace. + macro_map: HashMap, +} + +impl NameMapping { + /// Insert a single export in the appropriate map, at the appropriate position. + fn insert(&mut self, item: Export, old: bool) { + use rustc_hir::def::DefKind::*; + use rustc_hir::def::Res::*; + + let map = match item.res { + Def(kind, _) => match kind { + Mod | + Struct | + Union | + Enum | + Variant | + Trait | + TyAlias | + ForeignTy | + TraitAlias | // TODO: will need some handling later on + AssocTy | + TyParam | + OpaqueTy => Some(&mut self.type_map), + Fn | + Const | + ConstParam | + Static | + Ctor(_, _) | + AssocFn | + AssocConst => Some(&mut self.value_map), + Macro(_) => Some(&mut self.macro_map), + // They are not namespaced. + ExternCrate | + Use | + ForeignMod | + AnonConst | + Field | + LifetimeParam | + GlobalAsm | + Impl | + Closure | + Generator => None, + }, + PrimTy(_) | SelfTy(_, _) => Some(&mut self.type_map), + SelfCtor(_) | Local(_) => Some(&mut self.value_map), + _ => None, + }; + + if let Some(map) = map { + if old { + map.entry(item.ident.name).or_insert((None, None)).0 = Some(item); + } else { + map.entry(item.ident.name).or_insert((None, None)).1 = Some(item); + }; + } + } + + /// Add all items from two vectors of old/new exports. + pub fn add(&mut self, old_items: Vec>, new_items: Vec>) { + for item in old_items { + self.insert(item, true); + } + + for item in new_items { + self.insert(item, false); + } + } + + /// Drain the item pairs being stored. + pub fn drain<'a>( + &'a mut self, + ) -> impl Iterator>, Option>)> + 'a { + self.type_map + .drain() + .chain(self.value_map.drain()) + .chain(self.macro_map.drain()) + .map(|t| t.1) + } +} diff --git a/src/tools/semverver/src/mismatch.rs b/src/tools/semverver/src/mismatch.rs new file mode 100644 index 0000000000000..9b83e30dc1c01 --- /dev/null +++ b/src/tools/semverver/src/mismatch.rs @@ -0,0 +1,310 @@ +//! The logic for the second analysis pass collecting mismatched non-public items to match them. +//! +//! Any two items' types found in the same place which are not matched with other items yet are +//! are treated as renamed instances of the same item (as long as they are both unknown to us at +//! the time of analysis). Thus, we may match them up to avoid some false positives. + +use crate::mapping::IdMapping; +use log::debug; +use rustc_hir::def::{DefKind, Res}; +use rustc_middle::ty::{ + self, + relate::{Relate, RelateResult, TypeRelation}, + subst::SubstsRef, + ParamEnv, Ty, TyCtxt, + Visibility::Public, +}; +use std::collections::{HashMap, HashSet, VecDeque}; + +/// A relation searching for items appearing at the same spot in a type. +/// +/// Keeps track of item pairs found that way that correspond to item matchings not yet known. +/// This allows to match up some items that aren't exported, and which possibly even differ in +/// their names across versions. +#[cfg_attr(feature = "cargo-clippy", allow(clippy::module_name_repetitions))] +pub struct MismatchRelation<'a, 'tcx> { + /// The type context used. + tcx: TyCtxt<'tcx>, + /// The queue of found item pairings to be processed. + item_queue: VecDeque<(Res, Res)>, + /// The id mapping to use. + id_mapping: &'a mut IdMapping, + /// Type cache holding all old types currently being processed to avoid loops. + current_old_types: HashSet>, + /// Type cache holding all new types currently being processed to avoid loops. + current_new_types: HashSet>, +} + +impl<'a, 'tcx> MismatchRelation<'a, 'tcx> { + /// Construct a new mismtach type relation. + pub fn new(tcx: TyCtxt<'tcx>, id_mapping: &'a mut IdMapping) -> Self { + Self { + tcx, + item_queue: id_mapping.toplevel_queue(), + id_mapping, + current_old_types: HashSet::default(), + current_new_types: HashSet::default(), + } + } + + /// Process the next pair of `DefId`s in the queue. + pub fn process(&mut self) { + // use rustc_middle::hir::def::DefKind::*; + + while let Some((old_res, new_res)) = self.item_queue.pop_front() { + debug!( + "processing mismatch item pair, remaining: {}", + self.item_queue.len() + ); + debug!("old: {:?}, new: {:?}", old_res, new_res); + + // FIXME: this is odd, see if we can lift the restriction on traits + let (old_def_id, new_def_id) = match (old_res, new_res) { + (Res::Def(k1, o), Res::Def(k2, n)) => { + match k1 { + DefKind::Trait | DefKind::Macro(_) => continue, + _ => (), + }; + + match k2 { + DefKind::Trait | DefKind::Macro(_) => continue, + _ => (), + }; + + (o, n) + } + _ => continue, + }; + + let old_ty = self.tcx.type_of(old_def_id); + let new_ty = self.tcx.type_of(new_def_id); + debug!("relating item pair"); + let _ = self.relate(old_ty, new_ty); + } + } + + /// Ensure that the pair of given `SubstsRef`s is suitable to be related. + fn check_substs(&self, a_substs: SubstsRef<'tcx>, b_substs: SubstsRef<'tcx>) -> bool { + use rustc_middle::ty::subst::GenericArgKind::*; + + for (a, b) in a_substs.iter().zip(b_substs) { + match (a.unpack(), b.unpack()) { + (Lifetime(_), Type(_)) | (Type(_), Lifetime(_)) => return false, + _ => (), + } + } + + true + } +} + +impl<'a, 'tcx> TypeRelation<'tcx> for MismatchRelation<'a, 'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn param_env(&self) -> ParamEnv<'tcx> { + ParamEnv::empty() + } + + fn tag(&self) -> &'static str { + "Mismatch" + } + + fn a_is_expected(&self) -> bool { + true + } + + fn relate_with_variance>( + &mut self, + _: ty::Variance, + a: T, + b: T, + ) -> RelateResult<'tcx, T> { + self.relate(a, b) + } + + fn relate>(&mut self, a: T, b: T) -> RelateResult<'tcx, T> { + debug!("relate: mismatch relation: a: {:?}, b: {:?}", a, b); + Relate::relate(self, a, b) + } + + // Allow this since that lint is too pedantic here. + #[allow(clippy::similar_names)] + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + use rustc_middle::ty::TyKind; + + if self.current_old_types.contains(a) || self.current_new_types.contains(b) { + return Ok(self.tcx.ty_error()); + } + + self.current_old_types.insert(a); + self.current_new_types.insert(b); + + debug!("tys: mismatch relation: a: {:?}, b: {:?}", a, b); + let matching = match (&a.kind, &b.kind) { + (&TyKind::Adt(a_def, a_substs), &TyKind::Adt(b_def, b_substs)) => { + if self.check_substs(a_substs, b_substs) { + let _ = self.relate_item_substs(a_def.did, a_substs, b_substs)?; + let a_adt = self.tcx.adt_def(a_def.did); + let b_adt = self.tcx.adt_def(b_def.did); + + let b_fields: HashMap<_, _> = b_adt.all_fields().map(|f| (f.did, f)).collect(); + + for field in a_adt.all_fields().filter(|f| f.vis == Public) { + let a_field_ty = field.ty(self.tcx, a_substs); + + if let Some(b_field) = self + .id_mapping + .get_new_id(field.did) + .and_then(|did| b_fields.get(&did)) + { + let b_field_ty = b_field.ty(self.tcx, b_substs); + + let _ = self.relate(a_field_ty, b_field_ty)?; + } + } + + let a = if a_def.is_struct() { + Res::Def(DefKind::Struct, a_def.did) + } else if a_def.is_union() { + Res::Def(DefKind::Union, a_def.did) + } else { + Res::Def(DefKind::Enum, a_def.did) + }; + + let b = if b_def.is_struct() { + Res::Def(DefKind::Struct, b_def.did) + } else if b_def.is_union() { + Res::Def(DefKind::Union, b_def.did) + } else { + Res::Def(DefKind::Enum, b_def.did) + }; + + Some((a, b)) + } else { + None + } + } + (&TyKind::Array(a_t, _), &TyKind::Array(b_t, _)) + | (&TyKind::Slice(a_t), &TyKind::Slice(b_t)) => { + let _ = self.relate(a_t, b_t)?; + None + } + (&TyKind::RawPtr(a_mt), &TyKind::RawPtr(b_mt)) => { + let _ = self.relate(a_mt, b_mt)?; + None + } + (&TyKind::Ref(a_r, a_ty, _), &TyKind::Ref(b_r, b_ty, _)) => { + let _ = self.relate(a_r, b_r)?; + let _ = self.relate(a_ty, b_ty)?; + None + } + (&TyKind::FnDef(a_def_id, a_substs), &TyKind::FnDef(b_def_id, b_substs)) => { + if self.check_substs(a_substs, b_substs) { + let a_sig = a.fn_sig(self.tcx); + let b_sig = b.fn_sig(self.tcx); + let _ = self.relate_item_substs(a_def_id, a_substs, b_substs)?; + let _ = self.relate(a_sig.skip_binder(), b_sig.skip_binder())?; + } + + let a = Res::Def(DefKind::Fn, a_def_id); + let b = Res::Def(DefKind::Fn, b_def_id); + + Some((a, b)) + } + (&TyKind::FnPtr(a_fty), &TyKind::FnPtr(b_fty)) => { + let _ = self.relate(a_fty, b_fty)?; + None + } + (&TyKind::Dynamic(a_obj, a_r), &TyKind::Dynamic(b_obj, b_r)) => { + let _ = self.relate(a_r, b_r)?; + let a = a_obj.principal(); + let b = b_obj.principal(); + + if let (Some(a), Some(b)) = (a, b) { + if self.check_substs(a.skip_binder().substs, b.skip_binder().substs) { + let _ = self.relate(a.skip_binder().substs, b.skip_binder().substs)?; + let a = Res::Def(DefKind::Trait, a.skip_binder().def_id); + let b = Res::Def(DefKind::Trait, b.skip_binder().def_id); + Some((a, b)) + } else { + None + } + } else { + None + } + } + (&TyKind::Tuple(as_), &TyKind::Tuple(bs)) => { + let _ = as_.iter().zip(bs).map(|(a, b)| self.relate(a, b)); + None + } + (&TyKind::Projection(a_data), &TyKind::Projection(b_data)) => { + let _ = self.relate(a_data, b_data)?; + + let a = Res::Def(DefKind::AssocTy, a_data.item_def_id); + let b = Res::Def(DefKind::AssocTy, b_data.item_def_id); + + Some((a, b)) + } + (&TyKind::Opaque(_a_def_id, a_substs), &TyKind::Opaque(_b_def_id, b_substs)) => { + if self.check_substs(a_substs, b_substs) { + let _ = ty::relate::relate_substs(self, None, a_substs, b_substs)?; + } + + // TODO: we are talking impl trait here, so we can build a Res for that or the + // associated type + // Some((a_def_id, b_def_id)) + None + } + (&TyKind::Infer(_), _) | (_, &TyKind::Infer(_)) => { + // As the original function this is ripped off of, we don't handle these cases. + panic!("var types encountered in MismatchRelation::tys") + } + _ => None, + }; + + self.current_old_types.remove(a); + self.current_new_types.remove(b); + + if let Some((old, new)) = matching { + let old_def_id = old.def_id(); + let new_def_id = new.def_id(); + + if !self.id_mapping.contains_old_id(old_def_id) + && self.id_mapping.in_old_crate(old_def_id) + { + self.id_mapping.add_internal_item(old_def_id, new_def_id); + self.item_queue.push_back((old, new)); + } + } + + Ok(self.tcx.ty_error()) + } + + fn regions( + &mut self, + a: ty::Region<'tcx>, + _: ty::Region<'tcx>, + ) -> RelateResult<'tcx, ty::Region<'tcx>> { + Ok(a) + } + + fn consts( + &mut self, + a: &'tcx ty::Const<'tcx>, + _: &'tcx ty::Const<'tcx>, + ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { + Ok(a) // TODO + } + + fn binders>( + &mut self, + a: ty::Binder, + b: ty::Binder, + ) -> RelateResult<'tcx, ty::Binder> { + Ok(ty::Binder::bind( + self.relate(a.skip_binder(), b.skip_binder())?, + )) + } +} diff --git a/src/tools/semverver/src/translate.rs b/src/tools/semverver/src/translate.rs new file mode 100644 index 0000000000000..944ed0acbdea3 --- /dev/null +++ b/src/tools/semverver/src/translate.rs @@ -0,0 +1,577 @@ +//! The translation machinery used to lift items into the context of the other crate for +//! comparison and inference. + +use crate::mapping::{IdMapping, InherentEntry}; +use log::{debug, info}; +use rustc_hir::def_id::DefId; +use rustc_infer::infer::InferCtxt; +use rustc_middle::ty::{ + fold::{BottomUpFolder, TypeFoldable, TypeFolder}, + subst::{GenericArg, InternalSubsts, SubstsRef}, + GenericParamDefKind, ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt, +}; +use std::collections::HashMap; + +/// The context in which `DefId` translation happens. +pub struct TranslationContext<'a, 'tcx> { + /// The type context to use. + tcx: TyCtxt<'tcx>, + /// The id mapping to use. + id_mapping: &'a IdMapping, + /// Whether to translate type and region parameters. + translate_params: bool, + /// Elementary operation to decide whether to translate a `DefId`. + needs_translation: fn(&IdMapping, DefId) -> bool, + /// Elementary operation to translate a `DefId`. + translate_orig: fn(&IdMapping, DefId) -> Option, +} + +impl<'a, 'tcx> TranslationContext<'a, 'tcx> { + /// Construct a translation context translating to the new crate's `DefId`s. + pub fn target_new( + tcx: TyCtxt<'tcx>, + id_mapping: &'a IdMapping, + translate_params: bool, + ) -> TranslationContext<'a, 'tcx> { + TranslationContext { + tcx, + id_mapping, + translate_params, + needs_translation: IdMapping::in_old_crate, + translate_orig: IdMapping::get_new_id, + } + } + + /// Construct a translation context translating to the old crate's `DefId`s. + pub fn target_old( + tcx: TyCtxt<'tcx>, + id_mapping: &'a IdMapping, + translate_params: bool, + ) -> TranslationContext<'a, 'tcx> { + TranslationContext { + tcx, + id_mapping, + translate_params, + needs_translation: IdMapping::in_new_crate, + translate_orig: IdMapping::get_old_id, + } + } + + /// Construct a type parameter index map for translation. + fn construct_index_map(&self, orig_def_id: DefId) -> HashMap { + let mut index_map = HashMap::new(); + let orig_generics = self.tcx.generics_of(orig_def_id); + + for param in &orig_generics.params { + if let GenericParamDefKind::Type { .. } = param.kind { + index_map.insert(param.index, param.def_id); + } + } + + if let Some(did) = orig_generics.parent { + let parent_generics = self.tcx.generics_of(did); + + for param in &parent_generics.params { + if let GenericParamDefKind::Type { .. } = param.kind { + index_map.insert(param.index, param.def_id); + } + } + } + + index_map + } + + /// Check whether a `DefId` needs translation. + fn needs_translation(&self, def_id: DefId) -> bool { + (self.needs_translation)(self.id_mapping, def_id) + } + + /// Translate a `DefId`. + fn translate_orig(&self, def_id: DefId) -> DefId { + (self.translate_orig)(self.id_mapping, def_id).unwrap_or_else(|| { + info!("not mapped: {:?}", def_id); + def_id + }) + } + + /// Translate the `DefId` and substs of an item. + fn translate_orig_substs( + &self, + index_map: &HashMap, + orig_def_id: DefId, + orig_substs: SubstsRef<'tcx>, + ) -> Option<(DefId, SubstsRef<'tcx>)> { + use rustc_middle::ty::subst::GenericArgKind; + use rustc_middle::ty::ReEarlyBound; + use std::cell::Cell; + + debug!( + "translating w/ substs: did: {:?}, substs: {:?}", + orig_def_id, orig_substs + ); + + let target_def_id = (self.translate_orig)(self.id_mapping, orig_def_id); + + if let Some(target_def_id) = target_def_id { + let success = Cell::new(true); + + let target_substs = + InternalSubsts::for_item(self.tcx, target_def_id, |def, _| match def.kind { + GenericParamDefKind::Lifetime => GenericArg::from(if !success.get() { + self.tcx + .mk_region(ReEarlyBound(def.to_early_bound_region_data())) + } else if let Some(GenericArgKind::Lifetime(region)) = + orig_substs.get(def.index as usize).map(|k| k.unpack()) + { + self.translate_region(region) + } else { + success.set(false); + self.tcx + .mk_region(ReEarlyBound(def.to_early_bound_region_data())) + }), + GenericParamDefKind::Type { .. } => { + if !success.get() { + self.tcx.mk_param_from_def(def) + } else if let Some(GenericArgKind::Type(type_)) = + orig_substs.get(def.index as usize).map(|k| k.unpack()) + { + self.translate(index_map, &GenericArg::from(type_)) + } else if self + .id_mapping + .is_non_mapped_defaulted_type_param(def.def_id) + { + GenericArg::from(self.tcx.type_of(def.def_id)) + } else if self.tcx.generics_of(target_def_id).has_self && def.index == 0 { + self.tcx.mk_param_from_def(def) + } else { + success.set(false); + self.tcx.mk_param_from_def(def) + } + } + GenericParamDefKind::Const => unreachable!(), + }); + + if success.get() { + return Some((target_def_id, target_substs)); + } + } + + None + } + + /// Fold a structure, translating all `DefId`s reachable by the folder. + fn translate>(&self, index_map: &HashMap, orig: &T) -> T { + use rustc_middle::ty::ExistentialPredicate::*; + use rustc_middle::ty::TyKind; + use rustc_middle::ty::TypeAndMut; + use rustc_middle::ty::{AdtDef, Binder, ExistentialProjection, ExistentialTraitRef}; + + orig.fold_with(&mut BottomUpFolder { + tcx: self.tcx, + ty_op: |ty| { + match ty.kind { + TyKind::Adt(&AdtDef { ref did, .. }, substs) + if self.needs_translation(*did) => + { + // we fold bottom-up, so the code above is invalid, as it assumes the + // substs (that have been folded already) are yet untranslated + if let Some(target_def_id) = (self.translate_orig)(self.id_mapping, *did) { + let target_adt = self.tcx.adt_def(target_def_id); + self.tcx.mk_adt(target_adt, substs) + } else { + ty + } + } + TyKind::Ref(region, ty, mutbl) => { + let ty_and_mut = TypeAndMut { ty, mutbl }; + self.tcx.mk_ref(self.translate_region(region), ty_and_mut) + } + TyKind::FnDef(did, substs) => { + // TODO: this might be buggy as *technically* the substs are + // already translated (see TyKind::Adt for a possible fix) + if let Some((target_def_id, target_substs)) = + self.translate_orig_substs(index_map, did, substs) + { + self.tcx.mk_fn_def(target_def_id, target_substs) + } else { + ty + } + } + TyKind::Dynamic(preds, region) => { + // hacky error catching mechanism + use rustc_hir::def_id::CRATE_DEF_INDEX; + use std::cell::Cell; + + let success = Cell::new(true); + let err_pred = AutoTrait(DefId::local(CRATE_DEF_INDEX)); + + let res: Vec<_> = preds + .iter() + .map(|p| { + match p.skip_binder() { + Trait(existential_trait_ref) => { + let trait_ref = Binder::bind(existential_trait_ref) + .with_self_ty(self.tcx, self.tcx.ty_error()); + let did = trait_ref.skip_binder().def_id; + let substs = trait_ref.skip_binder().substs; + + // TODO: here, the substs could also be already translated + if let Some((target_def_id, target_substs)) = + self.translate_orig_substs(index_map, did, substs) + { + let target_trait_ref = TraitRef { + def_id: target_def_id, + substs: target_substs, + }; + Trait(ExistentialTraitRef::erase_self_ty( + self.tcx, + target_trait_ref, + )) + } else { + success.set(false); + err_pred + } + } + Projection(existential_projection) => { + let projection_pred = Binder::bind(existential_projection) + .with_self_ty(self.tcx, self.tcx.ty_error()); + let item_def_id = + projection_pred.skip_binder().projection_ty.item_def_id; + let substs = + projection_pred.skip_binder().projection_ty.substs; + + // TODO: here, the substs could also be already translated + if let Some((target_def_id, target_substs)) = self + .translate_orig_substs(index_map, item_def_id, substs) + { + Projection(ExistentialProjection { + item_def_id: target_def_id, + // TODO: should be it's own method in rustc + substs: self.tcx.intern_substs(&target_substs[1..]), + ty, + }) + } else { + success.set(false); + err_pred + } + } + AutoTrait(did) => AutoTrait(self.translate_orig(did)), + } + }) + .collect(); + + if success.get() { + let target_preds = self.tcx.mk_existential_predicates(res.iter()); + self.tcx.mk_dynamic(Binder::bind(target_preds), region) + } else { + ty + } + } + TyKind::Projection(proj) => { + if let Some((target_def_id, target_substs)) = + self.translate_orig_substs(index_map, proj.item_def_id, proj.substs) + { + self.tcx.mk_projection(target_def_id, target_substs) + } else { + ty + } + } + TyKind::Opaque(did, substs) => { + if let Some((target_def_id, target_substs)) = + self.translate_orig_substs(index_map, did, substs) + { + self.tcx.mk_opaque(target_def_id, target_substs) + } else { + ty + } + } + TyKind::Param(param) => { + // FIXME: we should check `has_self` if this gets used again! + if param.index != 0 && self.translate_params { + // `Self` is special + let orig_def_id = index_map[¶m.index]; + if self.needs_translation(orig_def_id) { + use rustc_middle::ty::subst::GenericArgKind; + + let target_def_id = self.translate_orig(orig_def_id); + debug!("translating type param: {:?}", param); + let type_param = self.id_mapping.get_type_param(&target_def_id); + debug!("translated type param: {:?}", type_param); + match self.tcx.mk_param_from_def(&type_param).unpack() { + GenericArgKind::Type(param_t) => param_t, + _ => unreachable!(), + } + } else { + ty + } + } else { + ty + } + } + _ => ty, + } + }, + lt_op: |region| self.translate_region(region), + ct_op: |konst| konst, // TODO: translate consts + }) + } + + /// Translate a region. + fn translate_region(&self, region: Region<'tcx>) -> Region<'tcx> { + use rustc_middle::ty::BoundRegion::BrNamed; + use rustc_middle::ty::RegionKind::*; + use rustc_middle::ty::{EarlyBoundRegion, FreeRegion}; + + if !self.translate_params { + return region; + } + + self.tcx.mk_region(match *region { + ReEarlyBound(early) => { + let target_early = EarlyBoundRegion { + def_id: self.translate_orig(early.def_id), + index: early.index, + name: early.name, + }; + + ReEarlyBound(target_early) + } + ReFree(FreeRegion { + scope, + bound_region, + }) => ReFree(FreeRegion { + scope: self.translate_orig(scope), + bound_region: match bound_region { + BrNamed(def_id, name) => BrNamed(self.translate_orig(def_id), name), + reg => reg, + }, + }), + reg => reg, + }) + } + + /// Translate an item's type. + pub fn translate_item_type(&self, orig_def_id: DefId, orig: Ty<'tcx>) -> Ty<'tcx> { + self.translate(&self.construct_index_map(orig_def_id), &orig) + } + + /// Translate a predicate using a type parameter index map. + fn translate_predicate( + &self, + index_map: &HashMap, + predicate: Predicate<'tcx>, + ) -> Option> { + use rustc_middle::ty::{ + Binder, OutlivesPredicate, PredicateKind, ProjectionPredicate, ProjectionTy, + SubtypePredicate, ToPredicate, TraitPredicate, + }; + + Some(match predicate.kind() { + PredicateKind::Trait(trait_predicate, constness) => PredicateKind::Trait( + Binder::bind( + if let Some((target_def_id, target_substs)) = self.translate_orig_substs( + index_map, + trait_predicate.skip_binder().trait_ref.def_id, + trait_predicate.skip_binder().trait_ref.substs, + ) { + TraitPredicate { + trait_ref: TraitRef { + def_id: target_def_id, + substs: target_substs, + }, + } + } else { + return None; + }, + ), + *constness, + ) + .to_predicate(self.tcx), + PredicateKind::RegionOutlives(region_outlives_predicate) => { + PredicateKind::RegionOutlives(region_outlives_predicate.map_bound(|r_pred| { + let l = self.translate_region(r_pred.0); + let r = self.translate_region(r_pred.1); + OutlivesPredicate(l, r) + })) + .to_predicate(self.tcx) + } + PredicateKind::TypeOutlives(type_outlives_predicate) => { + PredicateKind::TypeOutlives(type_outlives_predicate.map_bound(|r_pred| { + let l = self.translate(index_map, &r_pred.0); + let r = self.translate_region(r_pred.1); + OutlivesPredicate(l, r) + })) + .to_predicate(self.tcx) + } + PredicateKind::Projection(projection_predicate) => { + PredicateKind::Projection(Binder::bind( + if let Some((target_def_id, target_substs)) = self.translate_orig_substs( + index_map, + projection_predicate.skip_binder().projection_ty.item_def_id, + projection_predicate.skip_binder().projection_ty.substs, + ) { + ProjectionPredicate { + projection_ty: ProjectionTy { + substs: target_substs, + item_def_id: target_def_id, + }, + ty: self.translate(index_map, &projection_predicate.skip_binder().ty), + } + } else { + return None; + }, + )) + .to_predicate(self.tcx) + } + PredicateKind::WellFormed(ty) => { + PredicateKind::WellFormed(self.translate(index_map, &ty)).to_predicate(self.tcx) + } + PredicateKind::ObjectSafe(did) => { + PredicateKind::ObjectSafe(self.translate_orig(*did)).to_predicate(self.tcx) + } + PredicateKind::ClosureKind(did, substs, kind) => PredicateKind::ClosureKind( + self.translate_orig(*did), + self.translate(index_map, &substs), + *kind, + ) + .to_predicate(self.tcx), + PredicateKind::Subtype(subtype_predicate) => { + PredicateKind::Subtype(subtype_predicate.map_bound(|s_pred| { + let l = self.translate(index_map, &s_pred.a); + let r = self.translate(index_map, &s_pred.b); + SubtypePredicate { + a_is_expected: s_pred.a_is_expected, + a: l, + b: r, + } + })) + .to_predicate(self.tcx) + } + PredicateKind::ConstEvaluatable(orig_did, orig_substs) => { + if let Some((target_def_id, target_substs)) = + self.translate_orig_substs(index_map, *orig_did, orig_substs) + { + PredicateKind::ConstEvaluatable(target_def_id, target_substs) + .to_predicate(self.tcx) + } else { + return None; + } + } + PredicateKind::ConstEquate(c1, c2) => PredicateKind::ConstEquate( + self.translate(index_map, &c1), + self.translate(index_map, &c2), + ) + .to_predicate(self.tcx), + }) + } + + /// Translate a slice of predicates in the context of an item. + fn translate_predicates( + &self, + orig_def_id: DefId, + orig_preds: &[Predicate<'tcx>], + ) -> Option>> { + let index_map = self.construct_index_map(orig_def_id); + let mut target_preds = Vec::with_capacity(orig_preds.len()); + + for orig_pred in orig_preds { + if let Some(target_pred) = self.translate_predicate(&index_map, *orig_pred) { + target_preds.push(target_pred); + } else { + return None; + } + } + + Some(target_preds) + } + + /// Translate a `ParamEnv` in the context of an item. + pub fn translate_param_env( + &self, + orig_def_id: DefId, + param_env: ParamEnv<'tcx>, + ) -> Option> { + self.translate_predicates(orig_def_id, param_env.caller_bounds) + .map(|target_preds| ParamEnv { + caller_bounds: self.tcx.intern_predicates(&target_preds), + ..param_env + }) + } + + /// Translate a `TraitRef` in the context of an item. + pub fn translate_trait_ref( + &self, + orig_def_id: DefId, + orig_trait_ref: &TraitRef<'tcx>, + ) -> TraitRef<'tcx> { + let index_map = self.construct_index_map(orig_def_id); + TraitRef { + def_id: self.translate_orig(orig_trait_ref.def_id), + substs: self.translate(&index_map, &orig_trait_ref.substs), + } + } + + /// Translate an `InherentEntry`. + pub fn translate_inherent_entry(&self, orig_entry: &InherentEntry) -> Option { + (self.translate_orig)(self.id_mapping, orig_entry.parent_def_id).map(|parent_def_id| { + InherentEntry { + parent_def_id, + kind: orig_entry.kind, + name: orig_entry.name, + } + }) + } + + /// Check whether a given `DefId` can be translated. + pub fn can_translate(&self, def_id: DefId) -> bool { + (self.translate_orig)(self.id_mapping, def_id).is_some() + } +} + +/// A type folder that removes inference artifacts. +/// +/// Used to lift type errors and predicates to wrap them in an error type. +#[derive(Clone)] +pub struct InferenceCleanupFolder<'a, 'tcx: 'a> { + /// The inference context used. + infcx: &'a InferCtxt<'a, 'tcx>, +} + +impl<'a, 'tcx> InferenceCleanupFolder<'a, 'tcx> { + /// Construct a new folder. + pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self { + InferenceCleanupFolder { infcx } + } +} + +impl<'a, 'tcx> TypeFolder<'tcx> for InferenceCleanupFolder<'a, 'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.infcx.tcx + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + use rustc_middle::ty::TyKind; + use rustc_middle::ty::TypeAndMut; + + let t1 = ty.super_fold_with(self); + match t1.kind { + TyKind::Ref(region, ty, mutbl) if region.needs_infer() => { + let ty_and_mut = TypeAndMut { ty, mutbl }; + self.infcx + .tcx + .mk_ref(self.infcx.tcx.lifetimes.re_erased, ty_and_mut) + } + TyKind::Infer(_) => self.infcx.tcx.ty_error(), + _ => t1, + } + } + + fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> { + let r1 = r.super_fold_with(self); + if r1.needs_infer() { + self.infcx.tcx.lifetimes.re_erased + } else { + r1 + } + } +} diff --git a/src/tools/semverver/src/traverse.rs b/src/tools/semverver/src/traverse.rs new file mode 100644 index 0000000000000..5191318abfa37 --- /dev/null +++ b/src/tools/semverver/src/traverse.rs @@ -0,0 +1,1348 @@ +//! The traversal logic collecting changes in between crate versions. +//! +//! The changes get collected in multiple passes, and recorded in a `ChangeSet`. +//! The initial pass matches items by name in the module hierarchy, registering item removal +//! and addition, as well as structural changes to ADTs, type- or region parameters, and +//! function signatures. The second pass then proceeds to find non-public items that are named +//! differently, yet are compatible in their usage. The third pass now uses the information +//! collected in the previous passes to compare the types and/or trait bounds of all item pairs +//! that have been matched. Trait and inherent impls can't be matched by name, and are processed +//! in a fourth pass that uses trait bounds to find matching impls. + +use crate::{ + changes::{ChangeSet, ChangeType}, + mapping::{IdMapping, NameMapping}, + mismatch::MismatchRelation, + translate::TranslationContext, + typeck::{BoundContext, TypeComparisonContext}, +}; +use log::{debug, info}; +use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res, Res::Def}; +use rustc_hir::def_id::DefId; +use rustc_hir::hir_id::HirId; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_middle::{ + hir::exports::Export, + ty::{ + subst::{InternalSubsts, Subst}, + AssocItem, GenericParamDef, GenericParamDefKind, Generics, TraitRef, Ty, TyCtxt, TyKind, + TypeAndMut, Visibility, + Visibility::Public, + }, +}; +use rustc_mir::const_eval::is_const_fn; +use std::collections::{BTreeMap, HashSet, VecDeque}; + +/// The main entry point to our analysis passes. +/// +/// Set up the necessary data structures and run the analysis passes and call the actual passes. +pub fn run_analysis(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { + let mut changes = ChangeSet::default(); + let mut id_mapping = IdMapping::new(old.krate, new.krate); + + // first pass + debug!("first pass started"); + diff_structure(&mut changes, &mut id_mapping, tcx, old, new); + + // second pass + debug!("second pass started"); + { + let mut mismatch = MismatchRelation::new(tcx, &mut id_mapping); + debug!("constructed mismatch relation"); + mismatch.process(); + } + + // third pass + debug!("third pass started"); + for (old, new) in id_mapping.items() { + diff_types(&mut changes, &id_mapping, tcx, old, new); + } + + // fourth pass on impls + debug!("fourth pass started"); + diff_inherent_impls(&mut changes, &id_mapping, tcx); + diff_trait_impls(&mut changes, &id_mapping, tcx); + + changes +} + +// Get the visibility of the inner item, given the outer item's visibility. +fn get_vis(outer_vis: Visibility, def: Export) -> Visibility { + if outer_vis == Public { + def.vis + } else { + outer_vis + } +} + +pub fn run_traversal(tcx: TyCtxt, new: DefId) { + use rustc_hir::def::DefKind::*; + let mut visited = HashSet::new(); + let mut mod_queue = VecDeque::new(); + + // Start off with the root module. + mod_queue.push_back((new, Vec::new(), Public)); + + // Pull a module from the queue, with its global visibility. + while let Some((new_def_id, idents, new_vis)) = mod_queue.pop_front() { + for item in tcx.item_children(new_def_id).to_vec() { + let n_vis = get_vis(new_vis, item); + match item.res { + Def(Mod, n_def_id) => { + if visited.insert(n_def_id) { + let mut idents = idents.clone(); + idents.push(format!("{}", item.ident)); + + mod_queue.push_back((n_def_id, idents, n_vis)); + } + } + Def(n_kind, _) if n_vis == Public => { + match n_kind { + TyAlias | Struct | Union | Enum | Trait => { + let mut idents = idents.clone(); + idents.push(format!("{}", item.ident)); + + println!("{}", idents.join("::")); + } + _ => (), + }; + } + _ => (), + } + } + } +} + +// Below functions constitute the first pass of analysis, in which module structure, ADT +// structure, public and private status of items, and generics are examined for changes. + +/// Given two crate root modules, compare their exports and structure. +/// +/// Traverse the two root modules in an interleaved manner, matching up pairs of modules +/// from the two crate versions and compare for changes. Matching children get processed +/// in the same fashion. +#[cfg_attr(feature = "cargo-clippy", allow(clippy::cognitive_complexity))] +fn diff_structure<'tcx>( + changes: &mut ChangeSet, + id_mapping: &mut IdMapping, + tcx: TyCtxt<'tcx>, + old: DefId, + new: DefId, +) { + use rustc_hir::def::DefKind::*; + + let mut visited = HashSet::new(); + let mut children = NameMapping::default(); + let mut mod_queue = VecDeque::new(); + let mut traits = Vec::new(); + // Additions and removals are processed with a delay to avoid creating multiple path change + // entries. This is necessary, since the order in which added or removed paths are found wrt + // each other and their item's definition can't be relied upon. + let mut removals = Vec::new(); + let mut additions = Vec::new(); + + // Start off with the root module pair. + mod_queue.push_back((old, new, Public, Public)); + + // Pull a matched module pair from the queue, with the modules' global visibility. + while let Some((old_def_id, new_def_id, old_vis, new_vis)) = mod_queue.pop_front() { + children.add( + tcx.item_children(old_def_id).to_vec(), // TODO: clean up + tcx.item_children(new_def_id).to_vec(), + ); + + for items in children.drain() { + match items { + // an item pair is found + (Some(o), Some(n)) => { + if let (Def(Mod, o_def_id), Def(Mod, n_def_id)) = (o.res, n.res) { + if visited.insert((o_def_id, n_def_id)) { + let o_vis = get_vis(old_vis, o); + let n_vis = get_vis(new_vis, n); + + if o_vis != n_vis { + changes.new_change( + o_def_id, + n_def_id, + o.ident.name, + tcx.def_span(o_def_id), + tcx.def_span(n_def_id), + true, + ); + + // this seemingly overly complex condition is needed to handle + // `Restricted` visibility correctly. + if o_vis == Public && n_vis != Public { + changes.add_change(ChangeType::ItemMadePrivate, o_def_id, None); + } else if o_vis != Public && n_vis == Public { + changes.add_change(ChangeType::ItemMadePublic, o_def_id, None); + } + } + + mod_queue.push_back((o_def_id, n_def_id, o_vis, n_vis)); + } + } else if id_mapping.add_export(o.res, n.res) { + // struct constructors are weird/hard - let's go shopping! + if let (Def(Ctor(CtorOf::Struct, _), _), Def(Ctor(CtorOf::Struct, _), _)) = + (o.res, n.res) + { + continue; + } + + let o_def_id = o.res.def_id(); + let n_def_id = n.res.def_id(); + let o_vis = get_vis(old_vis, o); + let n_vis = get_vis(new_vis, n); + + let output = o_vis == Public || n_vis == Public; + changes.new_change( + o_def_id, + n_def_id, + o.ident.name, + tcx.def_span(o_def_id), + tcx.def_span(n_def_id), + output, + ); + + if o_vis == Public && n_vis != Public { + changes.add_change(ChangeType::ItemMadePrivate, o_def_id, None); + } else if o_vis != Public && n_vis == Public { + changes.add_change(ChangeType::ItemMadePublic, o_def_id, None); + } + + let (o_kind, n_kind) = match (o.res, n.res) { + (Res::Def(o_kind, _), Res::Def(n_kind, _)) => (o_kind, n_kind), + _ => { + // a non-matching item pair (seriously broken though) - + // register the change and abort further analysis of it + // changes.add_change(ChangeType::KindDifference, o_def_id, None); + continue; + } + }; + + match (o_kind, n_kind) { + // TODO: update comment + // matching items we don't care about because they are either + // impossible to encounter at this stage (Mod, AssocTy, PrimTy, + // TyParam, SelfTy, Ctor, AssocConst, Local, Upvar, + // Variant, Method, Err), whose analysis is out scope + // for us (GlobalAsm), or which don't requite further + // analysis at this stage (Const). + (Mod, Mod) + | (AssocTy, AssocTy) + | (TyParam, TyParam) + | (Ctor(CtorOf::Struct, _), Ctor(CtorOf::Struct, _)) + | (Ctor(CtorOf::Variant, _), Ctor(CtorOf::Variant, _)) + | (AssocConst, AssocConst) + | (Variant, Variant) + | (Const, Const) + | (AssocFn, AssocFn) + | (Macro(_), Macro(_)) + | (TraitAlias, TraitAlias) + | (ForeignTy, ForeignTy) + | (ConstParam, ConstParam) => {} + // statics are subject to mutability comparison + (Static, Static) => { + let old_mut = tcx.is_mutable_static(o_def_id); + let new_mut = tcx.is_mutable_static(n_def_id); + if old_mut != new_mut { + let change_type = + ChangeType::StaticMutabilityChanged { now_mut: new_mut }; + + changes.add_change(change_type, o_def_id, None); + } + } + // functions can declare generics and have structural properties + // that need to be compared + (Fn, Fn) => { + diff_generics(changes, id_mapping, tcx, true, o_def_id, n_def_id); + diff_fn(changes, tcx, o.res, n.res); + } + // type aliases can declare generics, too + (TyAlias, TyAlias) => { + diff_generics(changes, id_mapping, tcx, false, o_def_id, n_def_id); + } + // ADTs can declare generics and have lots of structural properties + // to check, most notably the number and name of variants and/or + // fields + (Struct, Struct) | (Union, Union) | (Enum, Enum) => { + diff_generics(changes, id_mapping, tcx, false, o_def_id, n_def_id); + diff_adts(changes, id_mapping, tcx, o.res, n.res); + } + // trait definitions can declare generics and require us to check + // for trait item addition and removal, as well as changes to their + // kinds and defaultness + (Trait, Trait) => { + if o_vis != Public { + debug!("private trait: {:?}", o_def_id); + id_mapping.add_private_trait(o_def_id); + } + + if n_vis != Public { + debug!("private trait: {:?}", n_def_id); + id_mapping.add_private_trait(n_def_id); + } + + diff_generics(changes, id_mapping, tcx, false, o_def_id, n_def_id); + traits.push((o_def_id, n_def_id, output)); + } + // a non-matching item pair - register the change and abort further + // analysis of it + _ => { + changes.add_change(ChangeType::KindDifference, o_def_id, None); + } + } + } + } + // only an old item is found + (Some(o), None) => { + // struct constructors are weird/hard - let's go shopping! + if let Def(Ctor(CtorOf::Struct, _), _) = o.res { + continue; + } + + if get_vis(old_vis, o) == Public { + // delay the handling of removals until the id mapping is complete + removals.push(o); + } + } + // only a new item is found + (None, Some(n)) => { + // struct constructors are weird/hard - let's go shopping! + if let Def(Ctor(CtorOf::Struct, _), _) = n.res { + continue; + } + + if get_vis(new_vis, n) == Public { + debug!("addition: {:?} ({:?})", new_vis, n); + // delay the handling of additions until the id mapping is complete + additions.push(n); + } + } + (None, None) => unreachable!(), + } + } + } + + // finally, process item additions and removals + for n in additions { + let n_def_id = n.res.def_id(); + + if !id_mapping.contains_new_id(n_def_id) { + id_mapping.add_non_mapped(n_def_id); + } + + changes.new_path_change(n_def_id, n.ident.name, tcx.def_span(n_def_id)); + changes.add_path_addition(n_def_id, n.span); + } + + for o in removals { + let o_def_id = o.res.def_id(); + + // reuse an already existing path change entry, if possible + if id_mapping.contains_old_id(o_def_id) { + let n_def_id = id_mapping.get_new_id(o_def_id).unwrap(); + changes.new_path_change(n_def_id, o.ident.name, tcx.def_span(n_def_id)); + changes.add_path_removal(n_def_id, o.span); + } else { + id_mapping.add_non_mapped(o_def_id); + changes.new_path_change(o_def_id, o.ident.name, tcx.def_span(o_def_id)); + changes.add_path_removal(o_def_id, o.span); + } + } + + for (o_def_id, n_def_id, output) in traits { + diff_traits(changes, id_mapping, tcx, o_def_id, n_def_id, output); + } +} + +/// Given two fn items, perform structural checks. +fn diff_fn<'tcx>(changes: &mut ChangeSet, tcx: TyCtxt<'tcx>, old: Res, new: Res) { + let old_def_id = old.def_id(); + let new_def_id = new.def_id(); + + let old_const = is_const_fn(tcx, old_def_id); + let new_const = is_const_fn(tcx, new_def_id); + + if old_const != new_const { + changes.add_change( + ChangeType::FnConstChanged { + now_const: new_const, + }, + old_def_id, + None, + ); + } +} + +/// Given two method items, perform structural checks. +fn diff_method<'tcx>(changes: &mut ChangeSet, tcx: TyCtxt<'tcx>, old: AssocItem, new: AssocItem) { + if old.fn_has_self_parameter != new.fn_has_self_parameter { + changes.add_change( + ChangeType::MethodSelfChanged { + now_self: new.fn_has_self_parameter, + }, + old.def_id, + None, + ); + } + + let old_pub = old.vis == Public; + let new_pub = new.vis == Public; + + if old_pub && !new_pub { + changes.add_change(ChangeType::ItemMadePrivate, old.def_id, None); + } else if !old_pub && new_pub { + changes.add_change(ChangeType::ItemMadePublic, old.def_id, None); + } + + diff_fn( + changes, + tcx, + Def(DefKind::Fn, old.def_id), + Def(DefKind::Fn, new.def_id), + ); +} + +/// Given two ADT items, perform structural checks. +/// +/// This establishes the needed correspondence between non-toplevel items such as enum variants, +/// struct- and enum fields etc. +fn diff_adts(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, old: Res, new: Res) { + use rustc_hir::def::DefKind::*; + + let old_def_id = old.def_id(); + let new_def_id = new.def_id(); + + let (old_def, new_def) = match (old, new) { + (Def(Struct, _), Def(Struct, _)) + | (Def(Union, _), Def(Union, _)) + | (Def(Enum, _), Def(Enum, _)) => (tcx.adt_def(old_def_id), tcx.adt_def(new_def_id)), + _ => return, + }; + + let is_enum = match old { + Def(Enum, _) => true, + _ => false, + }; + + let mut variants = BTreeMap::new(); + let mut fields = BTreeMap::new(); + + for variant in &old_def.variants { + variants.entry(variant.ident.name).or_insert((None, None)).0 = Some(variant); + } + + for variant in &new_def.variants { + variants.entry(variant.ident.name).or_insert((None, None)).1 = Some(variant); + } + + for items in variants.values() { + match *items { + (Some(old), Some(new)) => { + for field in &old.fields { + fields.entry(field.ident.name).or_insert((None, None)).0 = Some(field); + } + + for field in &new.fields { + fields.entry(field.ident.name).or_insert((None, None)).1 = Some(field); + } + + let mut total_private = true; + let mut total_public = true; + + for items2 in fields.values() { + if let Some(o) = items2.0 { + let public = o.vis == Public; + total_public &= public; + total_private &= !public; + } + } + + if old.ctor_kind != new.ctor_kind { + let c = ChangeType::VariantStyleChanged { + now_struct: new.ctor_kind == CtorKind::Fictive, + total_private, + is_enum, + }; + changes.add_change(c, old_def_id, Some(tcx.def_span(new.def_id))); + + continue; + } + + for items2 in fields.values() { + match *items2 { + (Some(o), Some(n)) => { + if o.vis == Public && n.vis == Public { + id_mapping.add_subitem(old_def_id, o.did, n.did); + } else if o.vis != Public && n.vis == Public { + changes.add_change( + ChangeType::ItemMadePublic, + old_def_id, + Some(tcx.def_span(n.did)), + ); + } else if o.vis == Public && n.vis != Public { + changes.add_change( + ChangeType::ItemMadePrivate, + old_def_id, + Some(tcx.def_span(n.did)), + ); + } + } + (Some(o), None) => { + let c = ChangeType::VariantFieldRemoved { + public: o.vis == Public, + total_public, + is_enum, + }; + changes.add_change(c, old_def_id, Some(tcx.def_span(o.did))); + } + (None, Some(n)) => { + let c = ChangeType::VariantFieldAdded { + public: n.vis == Public, + total_public, + is_enum, + }; + changes.add_change(c, old_def_id, Some(tcx.def_span(n.did))); + } + (None, None) => unreachable!(), + } + } + + fields.clear(); + } + (Some(old), None) => { + changes.add_change( + ChangeType::VariantRemoved, + old_def_id, + Some(tcx.def_span(old.def_id)), + ); + } + (None, Some(new)) => { + changes.add_change( + ChangeType::VariantAdded, + old_def_id, + Some(tcx.def_span(new.def_id)), + ); + } + (None, None) => unreachable!(), + } + } + + for impl_def_id in tcx.inherent_impls(old_def_id).iter() { + for item_def_id in tcx.associated_item_def_ids(*impl_def_id).iter() { + let item = tcx.associated_item(*item_def_id); + id_mapping.add_inherent_item( + old_def_id, + item.kind, + item.ident.name, + *impl_def_id, + *item_def_id, + ); + } + } + + for impl_def_id in tcx.inherent_impls(new_def_id).iter() { + for item_def_id in tcx.associated_item_def_ids(*impl_def_id).iter() { + let item = tcx.associated_item(*item_def_id); + id_mapping.add_inherent_item( + new_def_id, + item.kind, + item.ident.name, + *impl_def_id, + *item_def_id, + ); + } + } +} + +/// Given two trait items, perform structural checks. +/// +/// This establishes the needed correspondence between non-toplevel items found in the trait +/// definition. +fn diff_traits<'tcx>( + changes: &mut ChangeSet, + id_mapping: &mut IdMapping, + tcx: TyCtxt<'tcx>, + old: DefId, + new: DefId, + output: bool, +) { + use rustc_hir::Unsafety::Unsafe; + use rustc_middle::ty::subst::GenericArgKind::Type; + use rustc_middle::ty::{ParamTy, PredicateKind, TyS}; + + debug!( + "diff_traits: old: {:?}, new: {:?}, output: {:?}", + old, new, output + ); + + let old_unsafety = tcx.trait_def(old).unsafety; + let new_unsafety = tcx.trait_def(new).unsafety; + + if old_unsafety != new_unsafety { + let change_type = ChangeType::TraitUnsafetyChanged { + now_unsafe: new_unsafety == Unsafe, + }; + + changes.add_change(change_type, old, None); + } + + let mut old_sealed = false; + let old_param_env = tcx.param_env(old); + + for bound in old_param_env.caller_bounds { + if let PredicateKind::Trait(pred, _) = *bound.kind() { + let trait_ref = pred.skip_binder().trait_ref; + + debug!("trait_ref substs (old): {:?}", trait_ref.substs); + + if id_mapping.is_private_trait(trait_ref.def_id) && trait_ref.substs.len() == 1 { + if let Type(&TyS { + kind: TyKind::Param(ParamTy { index: 0, .. }), + .. + }) = trait_ref.substs[0].unpack() + { + old_sealed = true; + } + } + } + } + + let mut items = BTreeMap::new(); + + for old_def_id in tcx.associated_item_def_ids(old).iter() { + let item = tcx.associated_item(*old_def_id); + items.entry(item.ident.name).or_insert((None, None)).0 = Some(item); + // tcx.describe_def(*old_def_id).map(|d| (d, item)); + } + + for new_def_id in tcx.associated_item_def_ids(new).iter() { + let item = tcx.associated_item(*new_def_id); + items.entry(item.ident.name).or_insert((None, None)).1 = Some(item); + // tcx.describe_def(*new_def_id).map(|d| (d, item)); + } + + for (name, item_pair) in &items { + match *item_pair { + (Some(old_item), Some(new_item)) => { + let old_def_id = old_item.def_id; + let new_def_id = new_item.def_id; + let old_res = Res::Def(old_item.kind.as_def_kind(), old_def_id); + let new_res = Res::Def(new_item.kind.as_def_kind(), new_def_id); + + id_mapping.add_trait_item(old_res, new_res, old); + changes.new_change( + old_def_id, + new_def_id, + *name, + tcx.def_span(old_def_id), + tcx.def_span(new_def_id), + output, + ); + + diff_generics(changes, id_mapping, tcx, true, old_def_id, new_def_id); + diff_method(changes, tcx, *old_item, *new_item); + } + (Some(old_item), None) => { + let change_type = ChangeType::TraitItemRemoved { + defaulted: old_item.defaultness.has_value(), + }; + changes.add_change(change_type, old, Some(tcx.def_span(old_item.def_id))); + id_mapping.add_non_mapped(old_item.def_id); + } + (None, Some(new_item)) => { + let change_type = ChangeType::TraitItemAdded { + defaulted: new_item.defaultness.has_value(), + sealed_trait: old_sealed, + }; + changes.add_change(change_type, old, Some(tcx.def_span(new_item.def_id))); + id_mapping.add_non_mapped(new_item.def_id); + } + (None, None) => unreachable!(), + } + } +} + +/// Given two items, compare their type and region parameter sets. +fn diff_generics( + changes: &mut ChangeSet, + id_mapping: &mut IdMapping, + tcx: TyCtxt, + is_fn: bool, + old: DefId, + new: DefId, +) { + use rustc_middle::ty::Variance; + use rustc_middle::ty::Variance::*; + use std::cmp::max; + + fn diff_variance<'tcx>(old_var: Variance, new_var: Variance) -> Option> { + match (old_var, new_var) { + (Covariant, Covariant) + | (Invariant, Invariant) + | (Contravariant, Contravariant) + | (Bivariant, Bivariant) => None, + (Invariant, _) | (_, Bivariant) => Some(ChangeType::VarianceLoosened), + (_, Invariant) | (Bivariant, _) => Some(ChangeType::VarianceTightened), + (Covariant, Contravariant) => Some(ChangeType::VarianceChanged { + now_contravariant: true, + }), + (Contravariant, Covariant) => Some(ChangeType::VarianceChanged { + now_contravariant: false, + }), + } + } + + // guarantee that the return value's kind is `GenericParamDefKind::Lifetime` + fn get_region_from_params(gen: &Generics, idx: usize) -> Option<&GenericParamDef> { + let param = gen.params.get(idx)?; + + match param.kind { + GenericParamDefKind::Lifetime => Some(param), + _ => None, + } + } + + // guarantee that the return value's kind is `GenericParamDefKind::Type` + fn get_type_from_params(gen: &Generics, idx: usize) -> Option<&GenericParamDef> { + let param = &gen.params.get(idx)?; + + match param.kind { + GenericParamDefKind::Type { .. } => Some(param), + _ => None, + } + } + + debug!("diff_generics: old: {:?}, new: {:?}", old, new); + + let mut found = Vec::new(); + + let old_gen = tcx.generics_of(old); + let new_gen = tcx.generics_of(new); + + let old_var = tcx.variances_of(old); + let new_var = tcx.variances_of(new); + + let old_count = old_gen.own_counts(); + let new_count = new_gen.own_counts(); + + let self_add = if old_gen.has_self && new_gen.has_self { + 1 + } else if !old_gen.has_self && !new_gen.has_self { + 0 + } else { + unreachable!() + }; + + // TODO: we might need to track the number of parameters in the parent. + + debug!("old_gen: {:?}, new_gen: {:?}", old_gen, new_gen); + debug!( + "old_count.lifetimes: {:?}, new_count.lifetimes: {:?}", + old_count.lifetimes, new_count.lifetimes + ); + + for i in 0..max(old_count.lifetimes, new_count.lifetimes) { + match ( + get_region_from_params(old_gen, i + self_add), + get_region_from_params(new_gen, i + self_add), + ) { + (Some(old_region), Some(new_region)) => { + // type aliases don't have inferred variance, so we have to ignore that. + if let (Some(old_var), Some(new_var)) = (old_var.get(i), new_var.get(i)) { + if let Some(t) = diff_variance(*old_var, *new_var) { + found.push(t) + }; + } + + id_mapping.add_internal_item(old_region.def_id, new_region.def_id); + } + (Some(_), None) => { + found.push(ChangeType::RegionParameterRemoved); + } + (None, Some(_)) => { + found.push(ChangeType::RegionParameterAdded); + } + (None, None) => unreachable!(), + } + } + + for i in 0..max(old_count.types, new_count.types) { + let pair = if i == 0 && self_add == 1 { + ( + get_type_from_params(old_gen, 0), + get_type_from_params(new_gen, 0), + ) + } else { + ( + get_type_from_params(old_gen, old_count.lifetimes + i), + get_type_from_params(new_gen, new_count.lifetimes + i), + ) + }; + + match pair { + (Some(old_type), Some(new_type)) => { + // type aliases don't have inferred variance, so we have to ignore that. + if let (Some(old_var), Some(new_var)) = ( + old_var.get(old_count.lifetimes + i), + new_var.get(new_count.lifetimes + i), + ) { + if let Some(t) = diff_variance(*old_var, *new_var) { + found.push(t) + }; + } + + let old_default = match old_type.kind { + GenericParamDefKind::Type { has_default, .. } => has_default, + _ => unreachable!(), + }; + let new_default = match new_type.kind { + GenericParamDefKind::Type { has_default, .. } => has_default, + _ => unreachable!(), + }; + + if old_default && !new_default { + found.push(ChangeType::TypeParameterRemoved { defaulted: true }); + found.push(ChangeType::TypeParameterAdded { defaulted: false }); + } else if !old_default && new_default { + found.push(ChangeType::TypeParameterRemoved { defaulted: false }); + found.push(ChangeType::TypeParameterAdded { defaulted: true }); + } + + debug!( + "in item {:?} / {:?}:\n type param pair: {:?}, {:?}", + old, new, old_type, new_type + ); + + id_mapping.add_internal_item(old_type.def_id, new_type.def_id); + id_mapping.add_type_param(old_type); + id_mapping.add_type_param(new_type); + } + (Some(old_type), None) => { + let old_default = match old_type.kind { + GenericParamDefKind::Type { has_default, .. } => has_default, + _ => unreachable!(), + }; + + found.push(ChangeType::TypeParameterRemoved { + defaulted: old_default, + }); + id_mapping.add_type_param(old_type); + id_mapping.add_non_mapped(old_type.def_id); + } + (None, Some(new_type)) => { + let new_default = match new_type.kind { + GenericParamDefKind::Type { has_default, .. } => has_default, + _ => unreachable!(), + }; + + found.push(ChangeType::TypeParameterAdded { + defaulted: new_default || is_fn, + }); + id_mapping.add_type_param(new_type); + id_mapping.add_non_mapped(new_type.def_id); + } + (None, None) => unreachable!(), + } + } + + for change_type in found.drain(..) { + changes.add_change(change_type, old, None); + } +} + +// Below functions constitute the third pass of analysis, in which the types and/or trait bounds +// of matching items are compared for changes. + +/// Given two items, compare their types. +fn diff_types<'tcx>( + changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, + tcx: TyCtxt<'tcx>, + old: Res, + new: Res, +) { + use rustc_hir::def::DefKind::*; + + let old_def_id = old.def_id(); + let new_def_id = new.def_id(); + + // bail out of analysis of already broken items + if changes.item_breaking(old_def_id) + || id_mapping + .get_trait_def(old_def_id) + .map_or(false, |did| changes.trait_item_breaking(did)) + { + return; + } + + match old { + // type aliases, consts and statics just need their type to be checked + Def(TyAlias, _) | Def(Const, _) | Def(Static, _) => { + cmp_types( + changes, + id_mapping, + tcx, + old_def_id, + new_def_id, + tcx.type_of(old_def_id), + tcx.type_of(new_def_id), + ); + } + // functions and methods require us to compare their signatures, not types + Def(Fn, _) | Def(AssocFn, _) => { + let old_fn_sig = tcx.type_of(old_def_id).fn_sig(tcx); + let new_fn_sig = tcx.type_of(new_def_id).fn_sig(tcx); + + cmp_types( + changes, + id_mapping, + tcx, + old_def_id, + new_def_id, + tcx.mk_fn_ptr(old_fn_sig), + tcx.mk_fn_ptr(new_fn_sig), + ); + } + // ADTs' types are compared field-wise + Def(Struct, _) | Def(Enum, _) | Def(Union, _) => { + if let Some(children) = id_mapping.children_of(old_def_id) { + for (o_def_id, n_def_id) in children { + let o_ty = tcx.type_of(o_def_id); + let n_ty = tcx.type_of(n_def_id); + + cmp_types(changes, id_mapping, tcx, old_def_id, new_def_id, o_ty, n_ty); + } + } + } + // a trait definition has no type, so only it's trait bounds are compared + Def(Trait, _) => { + cmp_bounds(changes, id_mapping, tcx, old_def_id, new_def_id); + } + _ => (), + } +} + +/// Compare two types and their trait bounds, possibly registering the resulting change. +fn cmp_types<'tcx>( + changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, + tcx: TyCtxt<'tcx>, + orig_def_id: DefId, + target_def_id: DefId, + orig: Ty<'tcx>, + target: Ty<'tcx>, +) { + info!( + "comparing types and bounds of {:?} / {:?}:\n {:?} / {:?}", + orig_def_id, target_def_id, orig, target + ); + + tcx.infer_ctxt().enter(|infcx| { + let compcx = TypeComparisonContext::target_new(&infcx, id_mapping, false); + + let orig_substs = InternalSubsts::identity_for_item(infcx.tcx, target_def_id); + let orig = compcx.forward_trans.translate_item_type(orig_def_id, orig); + // let orig = orig.subst(infcx.tcx, orig_substs); + + // functions need inference, other items can declare defaulted type parameters + let target_substs = if target.is_fn() { + compcx.compute_target_infer_substs(target_def_id) + } else { + compcx.compute_target_default_substs(target_def_id) + }; + let target = target.subst(infcx.tcx, target_substs); + + let target_param_env = infcx + .tcx + .param_env(target_def_id) + .subst(infcx.tcx, target_substs); + + if let Some(err) = + compcx.check_type_error(tcx, target_def_id, target_param_env, orig, target) + { + changes.add_change(ChangeType::TypeChanged { error: err }, orig_def_id, None); + } else { + // check the bounds if no type error has been found + compcx.check_bounds_bidirectional( + changes, + tcx, + orig_def_id, + target_def_id, + orig_substs, + target_substs, + ); + } + }); +} + +/// Compare the trait bounds of two items, possibly registering the resulting change. +fn cmp_bounds<'tcx>( + changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, + tcx: TyCtxt<'tcx>, + orig_def_id: DefId, + target_def_id: DefId, +) { + info!( + "comparing bounds of {:?} / {:?}", + orig_def_id, target_def_id + ); + + tcx.infer_ctxt().enter(|infcx| { + let compcx = TypeComparisonContext::target_new(&infcx, id_mapping, true); + + let orig_substs = InternalSubsts::identity_for_item(infcx.tcx, target_def_id); + let target_substs = compcx.compute_target_default_substs(target_def_id); + + compcx.check_bounds_bidirectional( + changes, + tcx, + orig_def_id, + target_def_id, + orig_substs, + target_substs, + ); + }) +} + +// Below functions constitute the fourth pass of analysis, in which impls are matched up based on +// their trait bounds and compared for changes, if applicable. + +/// Compare the inherent implementations of all matching items. +fn diff_inherent_impls<'tcx>( + changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, + tcx: TyCtxt<'tcx>, +) { + debug!("diffing inherent impls"); + + let to_new = TranslationContext::target_new(tcx, id_mapping, false); + let to_old = TranslationContext::target_old(tcx, id_mapping, false); + + for (orig_item, orig_impls) in id_mapping.inherent_impls() { + // determine where the item comes from + let (forward_trans, err_type) = if id_mapping.in_old_crate(orig_item.parent_def_id) { + (&to_new, ChangeType::AssociatedItemRemoved) + } else if id_mapping.in_new_crate(orig_item.parent_def_id) { + (&to_old, ChangeType::AssociatedItemAdded) + } else { + unreachable!() + }; + + // determine item visibility + let parent_output = changes.get_output(orig_item.parent_def_id); + + // for each original impl the item is present in, ... + for &(orig_impl_def_id, orig_item_def_id) in orig_impls { + let orig_assoc_item = tcx.associated_item(orig_item_def_id); + + let item_span = tcx.def_span(orig_item_def_id); + changes.new_change( + orig_item_def_id, + orig_item_def_id, + orig_item.name, + item_span, + item_span, + parent_output && orig_assoc_item.vis == Public, + ); + + // ... determine the set of target impls that serve as candidates + let target_impls = if let Some(impls) = forward_trans + .translate_inherent_entry(orig_item) + .and_then(|item| id_mapping.get_inherent_impls(&item)) + { + impls + } else { + changes.add_change(err_type.clone(), orig_item_def_id, None); + continue; + }; + + // if any of the candidates matches, the item is compatible across versions + let match_found = + target_impls + .iter() + .any(|&(target_impl_def_id, target_item_def_id)| { + let target_assoc_item = tcx.associated_item(target_item_def_id); + + if parent_output && target_assoc_item.vis == Public { + changes.set_output(orig_item.parent_def_id); + } + + match_inherent_impl( + changes, + id_mapping, + tcx, + orig_impl_def_id, + target_impl_def_id, + *orig_assoc_item, + *target_assoc_item, + ) + }); + + // otherwise, it has been essentially added/removed + if !match_found { + changes.add_change(err_type.clone(), orig_item_def_id, None); + } + } + } +} + +// There doesn't seem to be a way to get the visibility of impl traits from rustc +// (CC rust-lang/rust#61464), so we implement the logic here. Note that this implementation is far +// from perfect and will cause false positives in some cases (see comment in the inner function). +#[allow(clippy::let_and_return)] +#[allow(clippy::match_same_arms)] +fn is_impl_trait_public<'tcx>(tcx: TyCtxt<'tcx>, impl_def_id: DefId) -> bool { + fn type_visibility(tcx: TyCtxt, ty: Ty) -> Visibility { + match ty.kind { + TyKind::Adt(def, _) => tcx.visibility(def.did), + + TyKind::Array(t, _) + | TyKind::Slice(t) + | TyKind::RawPtr(TypeAndMut { ty: t, .. }) + | TyKind::Ref(_, t, _) => type_visibility(tcx, t), + + TyKind::Bool + | TyKind::Char + | TyKind::Int(_) + | TyKind::Uint(_) + | TyKind::Float(_) + | TyKind::Str + | TyKind::Never => Visibility::Public, + + // FIXME We assume everything else is public which is, of course, not always the case. + // This means we will have false positives. We need to improve this. + _ => Visibility::Public, + } + } + + let trait_ref: TraitRef<'tcx> = tcx.impl_trait_ref(impl_def_id).unwrap(); + let trait_def_id = trait_ref.def_id; + + if tcx.visibility(trait_def_id) != Visibility::Public { + return false; + } + + // Check if all input types of the trait implementation are public (including `Self`). + let is_public = trait_ref + .substs + .types() + .map(|t| type_visibility(tcx, t)) + .all(|v| v == Visibility::Public); + + is_public +} + +/// Compare the implementations of all matching traits. +fn diff_trait_impls<'tcx>( + changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, + tcx: TyCtxt<'tcx>, +) { + debug!("diffing trait impls"); + + let to_new = TranslationContext::target_new(tcx, id_mapping, false); + let to_old = TranslationContext::target_old(tcx, id_mapping, false); + + for old_impl_def_id in tcx + .all_trait_implementations(id_mapping.get_old_crate()) + .iter() + { + let old_trait_def_id = tcx.impl_trait_ref(*old_impl_def_id).unwrap().def_id; + + if !to_new.can_translate(old_trait_def_id) || !is_impl_trait_public(tcx, *old_impl_def_id) { + continue; + } + + if !match_trait_impl(tcx, &to_new, *old_impl_def_id) { + changes.new_change_impl( + *old_impl_def_id, + tcx.def_path_str(*old_impl_def_id), + tcx.def_span(*old_impl_def_id), + ); + changes.add_change(ChangeType::TraitImplTightened, *old_impl_def_id, None); + } + } + + for new_impl_def_id in tcx + .all_trait_implementations(id_mapping.get_new_crate()) + .iter() + { + let new_trait_def_id = tcx.impl_trait_ref(*new_impl_def_id).unwrap().def_id; + + if !to_old.can_translate(new_trait_def_id) || !is_impl_trait_public(tcx, *new_impl_def_id) { + continue; + } + + if !match_trait_impl(tcx, &to_old, *new_impl_def_id) { + changes.new_change_impl( + *new_impl_def_id, + tcx.def_path_str(*new_impl_def_id), + tcx.def_span(*new_impl_def_id), + ); + changes.add_change(ChangeType::TraitImplLoosened, *new_impl_def_id, None); + } + } +} + +/// Compare an item pair in two inherent implementations and indicate whether the target one is +/// compatible with the original one. +fn match_inherent_impl<'tcx>( + changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, + tcx: TyCtxt<'tcx>, + orig_impl_def_id: DefId, + target_impl_def_id: DefId, + orig_item: AssocItem, + target_item: AssocItem, +) -> bool { + use rustc_middle::ty::AssocKind; + + debug!( + "match_inherent_impl: orig_impl/item: {:?}/{:?}, target_impl/item: {:?}/{:?}", + orig_impl_def_id, orig_item, target_impl_def_id, target_item + ); + + let orig_item_def_id = orig_item.def_id; + let target_item_def_id = target_item.def_id; + + tcx.infer_ctxt().enter(|infcx| { + let (compcx, register_errors) = if id_mapping.in_old_crate(orig_impl_def_id) { + ( + TypeComparisonContext::target_new(&infcx, id_mapping, false), + true, + ) + } else { + ( + TypeComparisonContext::target_old(&infcx, id_mapping, false), + false, + ) + }; + + let orig_substs = InternalSubsts::identity_for_item(infcx.tcx, target_item_def_id); + let orig_self = compcx + .forward_trans + .translate_item_type(orig_impl_def_id, infcx.tcx.type_of(orig_impl_def_id)); + + let target_substs = compcx.compute_target_infer_substs(target_item_def_id); + let target_self = infcx + .tcx + .type_of(target_impl_def_id) + .subst(infcx.tcx, target_substs); + + let target_param_env = infcx.tcx.param_env(target_impl_def_id); + + let error = compcx.check_type_error( + tcx, + target_impl_def_id, + target_param_env, + orig_self, + target_self, + ); + + if error.is_some() { + // `Self` on the impls isn't equal - no impl match. + return false; + } + + let orig_param_env = compcx + .forward_trans + .translate_param_env(orig_impl_def_id, tcx.param_env(orig_impl_def_id)); + + if let Some(orig_param_env) = orig_param_env { + let errors = + compcx.check_bounds_error(tcx, orig_param_env, target_impl_def_id, target_substs); + if errors.is_some() { + // The bounds on the impls have been tightened - no impl match. + return false; + } + } else { + // The bounds could not have been translated - no impl match. + return false; + } + + // at this point we have an impl match, so the return value is always `true`. + + if !register_errors { + // checking backwards, impls match. + return true; + } + + // prepare the item type for comparison, as we do for toplevel items' types + let (orig, target) = match (orig_item.kind, target_item.kind) { + (AssocKind::Const, AssocKind::Const) | (AssocKind::Type, AssocKind::Type) => ( + infcx.tcx.type_of(orig_item_def_id), + infcx.tcx.type_of(target_item_def_id), + ), + (AssocKind::Fn, AssocKind::Fn) => { + diff_method(changes, tcx, orig_item, target_item); + let orig_sig = infcx.tcx.type_of(orig_item_def_id).fn_sig(tcx); + let target_sig = infcx.tcx.type_of(target_item_def_id).fn_sig(tcx); + (tcx.mk_fn_ptr(orig_sig), tcx.mk_fn_ptr(target_sig)) + } + _ => unreachable!(), + }; + + let orig = compcx + .forward_trans + .translate_item_type(orig_item_def_id, orig); + let target = target.subst(infcx.tcx, target_substs); + + let error = + compcx.check_type_error(tcx, target_item_def_id, target_param_env, orig, target); + + if let Some(err) = error { + changes.add_change( + ChangeType::TypeChanged { error: err }, + orig_item_def_id, + None, + ); + } else { + // check the bounds if no type error has been found + compcx.check_bounds_bidirectional( + changes, + tcx, + orig_item_def_id, + target_item_def_id, + orig_substs, + target_substs, + ); + } + + true + }) +} + +/// Compare two implementations and indicate whether the target one is compatible with the +/// original one. +fn match_trait_impl<'a, 'tcx>( + tcx: TyCtxt<'tcx>, + trans: &TranslationContext<'a, 'tcx>, + orig_def_id: DefId, +) -> bool { + debug!("matching: {:?}", orig_def_id); + + tcx.infer_ctxt().enter(|infcx| { + let old_param_env = + if let Some(env) = trans.translate_param_env(orig_def_id, tcx.param_env(orig_def_id)) { + env + } else { + return false; + }; + + debug!("env: {:?}", old_param_env); + + let orig = tcx.impl_trait_ref(orig_def_id).unwrap(); + debug!("trait ref: {:?}", orig); + debug!( + "translated ref: {:?}", + trans.translate_trait_ref(orig_def_id, &orig) + ); + + let mut bound_cx = BoundContext::new(&infcx, old_param_env); + bound_cx.register_trait_ref(trans.translate_trait_ref(orig_def_id, &orig)); + bound_cx.get_errors().is_none() + }) +} diff --git a/src/tools/semverver/src/typeck.rs b/src/tools/semverver/src/typeck.rs new file mode 100644 index 0000000000000..91a16b4f25719 --- /dev/null +++ b/src/tools/semverver/src/typeck.rs @@ -0,0 +1,353 @@ +//! The type and predicate checking logic used to compare types of corresponding items. +//! +//! Multiple context structures are provided that modularize the needed functionality to allow +//! for code reuse across analysis steps. + +use crate::{ + changes::ChangeSet, + mapping::IdMapping, + translate::{InferenceCleanupFolder, TranslationContext}, +}; +use log::debug; +use rustc_hir::def_id::DefId; +use rustc_infer::infer::InferCtxt; +use rustc_infer::traits::{FulfillmentError, Obligation, TraitEngine}; +use rustc_middle::{ + traits::ObligationCause, + ty::{ + error::TypeError, + fold::TypeFoldable, + subst::{GenericArg, InternalSubsts, SubstsRef}, + GenericParamDefKind, ParamEnv, Predicate, PredicateKind, ToPredicate, TraitRef, Ty, TyCtxt, + }, +}; +use rustc_trait_selection::traits::FulfillmentContext; + +/// The context in which bounds analysis happens. +pub struct BoundContext<'a, 'tcx: 'a> { + /// The inference context to use. + infcx: &'a InferCtxt<'a, 'tcx>, + /// The fulfillment context to use. + fulfill_cx: FulfillmentContext<'tcx>, + /// The param env to be assumed. + given_param_env: ParamEnv<'tcx>, +} + +impl<'a, 'tcx> BoundContext<'a, 'tcx> { + /// Construct a new bound context. + pub fn new(infcx: &'a InferCtxt<'a, 'tcx>, given_param_env: ParamEnv<'tcx>) -> Self { + BoundContext { + infcx, + fulfill_cx: FulfillmentContext::new(), + given_param_env, + } + } + + /// Register the bounds of an item. + pub fn register(&mut self, checked_def_id: DefId, substs: SubstsRef<'tcx>) { + use rustc_infer::traits::Normalized; + use rustc_trait_selection::traits::{normalize, SelectionContext}; + + let cause = ObligationCause::dummy(); + let mut selcx = SelectionContext::new(self.infcx); + let predicates = self + .infcx + .tcx + .predicates_of(checked_def_id) + .instantiate(self.infcx.tcx, substs); + let Normalized { value, obligations } = + normalize(&mut selcx, self.given_param_env, cause.clone(), &predicates); + + for obligation in obligations { + self.fulfill_cx + .register_predicate_obligation(self.infcx, obligation); + } + + for predicate in value.predicates { + let obligation = Obligation::new(cause.clone(), self.given_param_env, predicate); + self.fulfill_cx + .register_predicate_obligation(self.infcx, obligation); + } + } + + /// Register the trait bound represented by a `TraitRef`. + pub fn register_trait_ref(&mut self, checked_trait_ref: TraitRef<'tcx>) { + use rustc_hir::Constness; + use rustc_middle::ty::{Binder, TraitPredicate}; + + let predicate = PredicateKind::Trait( + Binder::bind(TraitPredicate { + trait_ref: checked_trait_ref, + }), + Constness::NotConst, + ) + .to_predicate(self.infcx.tcx); + let obligation = Obligation::new(ObligationCause::dummy(), self.given_param_env, predicate); + self.fulfill_cx + .register_predicate_obligation(self.infcx, obligation); + } + + /// Return inference errors, if any. + pub fn get_errors(&mut self) -> Option>> { + if let Err(err) = self.fulfill_cx.select_all_or_error(self.infcx) { + debug!("err: {:?}", err); + Some(err) + } else { + None + } + } +} + +/// The context in which types and their bounds can be compared. +pub struct TypeComparisonContext<'a, 'tcx: 'a> { + /// The inference context to use. + infcx: &'a InferCtxt<'a, 'tcx>, + /// The index mapping to use. + id_mapping: &'a IdMapping, + /// The folder to clean up found errors of inference artifacts. + folder: InferenceCleanupFolder<'a, 'tcx>, + /// The translation context translating from original to target items. + pub forward_trans: TranslationContext<'a, 'tcx>, + /// The translation context translating from target to original items. + pub backward_trans: TranslationContext<'a, 'tcx>, + /// Whether we are checking a trait definition. + checking_trait_def: bool, +} + +impl<'a, 'tcx> TypeComparisonContext<'a, 'tcx> { + /// Construct a new context where the original item is old. + pub fn target_new( + infcx: &'a InferCtxt<'a, 'tcx>, + id_mapping: &'a IdMapping, + checking_trait_def: bool, + ) -> Self { + let forward_trans = TranslationContext::target_new(infcx.tcx, id_mapping, false); + let backward_trans = TranslationContext::target_old(infcx.tcx, id_mapping, false); + TypeComparisonContext::from_trans( + infcx, + id_mapping, + forward_trans, + backward_trans, + checking_trait_def, + ) + } + + /// Construct a new context where the original item is new. + pub fn target_old( + infcx: &'a InferCtxt<'a, 'tcx>, + id_mapping: &'a IdMapping, + checking_trait_def: bool, + ) -> Self { + let forward_trans = TranslationContext::target_old(infcx.tcx, id_mapping, false); + let backward_trans = TranslationContext::target_new(infcx.tcx, id_mapping, false); + TypeComparisonContext::from_trans( + infcx, + id_mapping, + forward_trans, + backward_trans, + checking_trait_def, + ) + } + + /// Construct a new context given a pair of translation contexts. + fn from_trans( + infcx: &'a InferCtxt<'a, 'tcx>, + id_mapping: &'a IdMapping, + forward_trans: TranslationContext<'a, 'tcx>, + backward_trans: TranslationContext<'a, 'tcx>, + checking_trait_def: bool, + ) -> Self { + TypeComparisonContext { + infcx, + id_mapping, + folder: InferenceCleanupFolder::new(infcx), + forward_trans, + backward_trans, + checking_trait_def, + } + } + + /// Construct a set of subsitutions for an item, which replaces all region and type variables + /// with inference variables, with the exception of `Self`. + pub fn compute_target_infer_substs(&self, target_def_id: DefId) -> SubstsRef<'tcx> { + use rustc_span::DUMMY_SP; + + let has_self = self.infcx.tcx.generics_of(target_def_id).has_self; + + InternalSubsts::for_item(self.infcx.tcx, target_def_id, |def, _| { + if def.index == 0 && has_self { + // `Self` is special + self.infcx.tcx.mk_param_from_def(def) + } else { + self.infcx.var_for_def(DUMMY_SP, def) + } + }) + } + + /// Construct a set of subsitutions for an item, which normalizes defaults. + pub fn compute_target_default_substs(&self, target_def_id: DefId) -> SubstsRef<'tcx> { + use rustc_middle::ty::ReEarlyBound; + + InternalSubsts::for_item(self.infcx.tcx, target_def_id, |def, _| match def.kind { + GenericParamDefKind::Lifetime => GenericArg::from( + self.infcx + .tcx + .mk_region(ReEarlyBound(def.to_early_bound_region_data())), + ), + GenericParamDefKind::Type { .. } => { + if self + .id_mapping + .is_non_mapped_defaulted_type_param(def.def_id) + { + GenericArg::from(self.infcx.tcx.type_of(def.def_id)) + } else { + self.infcx.tcx.mk_param_from_def(def) + } + } + GenericParamDefKind::Const => unreachable!(), + }) + } + + /// Check for type mismatches in a pair of items. + pub fn check_type_error<'tcx2>( + &self, + lift_tcx: TyCtxt<'tcx2>, + target_def_id: DefId, + target_param_env: ParamEnv<'tcx>, + orig: Ty<'tcx>, + target: Ty<'tcx>, + ) -> Option> { + use rustc_infer::infer::outlives::env::OutlivesEnvironment; + use rustc_infer::infer::{InferOk, RegionckMode}; + use rustc_middle::ty::Lift; + + let error = self + .infcx + .at(&ObligationCause::dummy(), target_param_env) + .eq(orig, target) + .map(|InferOk { obligations: o, .. }| { + assert_eq!(o, vec![]); + }); + + if let Err(err) = error { + let outlives_env = OutlivesEnvironment::new(target_param_env); + + // The old code here added the bounds from the target param env by hand. However, at + // least the explicit bounds are added when the OutlivesEnvironment is created. This + // seems to work, but in case it stops to do so, the below code snippets should be + // of help to implement the old behaviour. + // + // outlives_env.add_outlives_bounds(None, target_param_env.caller_bounds.iter()....) + // free_regions.relate_free_regions_from_predicates(target_param_env.caller_bounds); + // ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r_a, r_b))) => { + // self.relate_regions(r_b, r_a); + // } + + self.infcx.resolve_regions_and_report_errors( + target_def_id, + &outlives_env, + RegionckMode::default(), + ); + + let err = self + .infcx + .resolve_vars_if_possible(&err) + .fold_with(&mut self.folder.clone()) + .lift_to_tcx(lift_tcx) + .unwrap(); + + Some(err) + } else { + None + } + } + + /// Check for trait bound mismatches in a pair of items. + pub fn check_bounds_error<'tcx2>( + &self, + lift_tcx: TyCtxt<'tcx2>, + orig_param_env: ParamEnv<'tcx>, + target_def_id: DefId, + target_substs: SubstsRef<'tcx>, + ) -> Option>> { + use rustc_middle::ty::Lift; + debug!( + "check_bounds_error: orig env: {:?}, target did: {:?}, target substs: {:?}", + orig_param_env, target_def_id, target_substs + ); + + let mut bound_cx = BoundContext::new(self.infcx, orig_param_env); + bound_cx.register(target_def_id, target_substs); + + bound_cx.get_errors().map(|errors| { + errors + .iter() + .map(|err| { + self.infcx + .resolve_vars_if_possible(&err.obligation.predicate) + .fold_with(&mut self.folder.clone()) + .lift_to_tcx(lift_tcx) + .unwrap() + }) + .collect() + }) + } + + /// Check the bounds on an item in both directions and register changes found. + pub fn check_bounds_bidirectional<'tcx2>( + &self, + changes: &mut ChangeSet<'tcx2>, + lift_tcx: TyCtxt<'tcx2>, + orig_def_id: DefId, + target_def_id: DefId, + orig_substs: SubstsRef<'tcx>, + target_substs: SubstsRef<'tcx>, + ) { + use crate::changes::ChangeType::{BoundsLoosened, BoundsTightened}; + + let tcx = self.infcx.tcx; + + let orig_param_env = self + .forward_trans + .translate_param_env(orig_def_id, tcx.param_env(orig_def_id)); + + let orig_param_env = if let Some(env) = orig_param_env { + env + } else { + return; + }; + + if let Some(errors) = + self.check_bounds_error(lift_tcx, orig_param_env, target_def_id, target_substs) + { + for err in errors { + let err_type = BoundsTightened { pred: err }; + + changes.add_change(err_type, orig_def_id, None); + } + } + + let target_param_env = self + .backward_trans + .translate_param_env(target_def_id, tcx.param_env(target_def_id)); + + let target_param_env = if let Some(env) = target_param_env { + env + } else { + return; + }; + + if let Some(errors) = + self.check_bounds_error(lift_tcx, target_param_env, orig_def_id, orig_substs) + { + for err in errors { + let err_type = BoundsLoosened { + pred: err, + trait_def: self.checking_trait_def, + }; + + changes.add_change(err_type, orig_def_id, None); + } + } + } +} diff --git a/src/tools/semverver/tests/cases/addition/new.rs b/src/tools/semverver/tests/cases/addition/new.rs new file mode 100644 index 0000000000000..5c6c42226c1c5 --- /dev/null +++ b/src/tools/semverver/tests/cases/addition/new.rs @@ -0,0 +1,21 @@ +pub struct Abc; + +pub struct Bcd; + +pub mod a { + +} + +pub mod b { + #[allow(dead_code)] + pub struct Cde; +} + +mod c { + #[allow(dead_code)] + pub struct Def; +} + +pub mod d { + +} diff --git a/src/tools/semverver/tests/cases/addition/old.rs b/src/tools/semverver/tests/cases/addition/old.rs new file mode 100644 index 0000000000000..39a077e8f6421 --- /dev/null +++ b/src/tools/semverver/tests/cases/addition/old.rs @@ -0,0 +1,14 @@ +#[allow(dead_code)] +struct Bcd; + +mod b { + +} + +mod c { + +} + +mod d { + +} diff --git a/src/tools/semverver/tests/cases/addition/stdout b/src/tools/semverver/tests/cases/addition/stdout new file mode 100644 index 0000000000000..3f8c0cbd5474a --- /dev/null +++ b/src/tools/semverver/tests/cases/addition/stdout @@ -0,0 +1,58 @@ +version bump: 1.0.0 -> (technically breaking) -> 1.1.0 +warning: technically breaking changes in `Bcd` + --> addition/new.rs:3:1 + | +3 | pub struct Bcd; + | ^^^^^^^^^^^^^^^ + | + = note: item made public (technically breaking) + +warning: technically breaking changes in `b` + --> addition/new.rs:9:1 + | +9 | / pub mod b { +10 | | #[allow(dead_code)] +11 | | pub struct Cde; +12 | | } + | |_^ + | + = note: item made public (technically breaking) + +warning: technically breaking changes in `d` + --> addition/new.rs:19:1 + | +19 | / pub mod d { +20 | | +21 | | } + | |_^ + | + = note: item made public (technically breaking) + +warning: path changes to `Abc` + --> addition/new.rs:1:1 + | +1 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + +warning: path changes to `a` + --> addition/new.rs:5:1 + | +5 | / pub mod a { +6 | | +7 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `Cde` + --> addition/new.rs:11:5 + | +11 | pub struct Cde; + | ^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + +warning: 6 warnings emitted + diff --git a/src/tools/semverver/tests/cases/addition/stdout_api_guidelines b/src/tools/semverver/tests/cases/addition/stdout_api_guidelines new file mode 100644 index 0000000000000..045662d9257f7 --- /dev/null +++ b/src/tools/semverver/tests/cases/addition/stdout_api_guidelines @@ -0,0 +1 @@ +version bump: 1.0.0 -> (technically breaking) -> 1.1.0 diff --git a/src/tools/semverver/tests/cases/addition_path/new.rs b/src/tools/semverver/tests/cases/addition_path/new.rs new file mode 100644 index 0000000000000..974eedc5f59ae --- /dev/null +++ b/src/tools/semverver/tests/cases/addition_path/new.rs @@ -0,0 +1,25 @@ +pub mod a { + pub struct Abc; +} + +pub mod b { + pub use a::*; +} + +pub mod c { + pub use a::Abc; +} + +pub use self::a::Abc; + +pub mod d { + +} + +mod e { + +} + +mod f { + pub use a::Abc; +} diff --git a/src/tools/semverver/tests/cases/addition_path/old.rs b/src/tools/semverver/tests/cases/addition_path/old.rs new file mode 100644 index 0000000000000..552dd103cce41 --- /dev/null +++ b/src/tools/semverver/tests/cases/addition_path/old.rs @@ -0,0 +1,15 @@ +pub mod a { + pub struct Abc; +} + +pub mod b { + +} + +pub mod c { + +} + +mod f { + +} diff --git a/src/tools/semverver/tests/cases/addition_path/stdout b/src/tools/semverver/tests/cases/addition_path/stdout new file mode 100644 index 0000000000000..3ea7ba7fda263 --- /dev/null +++ b/src/tools/semverver/tests/cases/addition_path/stdout @@ -0,0 +1,35 @@ +version bump: 1.0.0 -> (technically breaking) -> 1.1.0 +warning: path changes to `Abc` + --> addition_path/new.rs:2:5 + | +2 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> addition_path/new.rs:6:13 + | +6 | pub use a::*; + | ^^^^ +note: added path (technically breaking) + --> addition_path/new.rs:10:13 + | +10 | pub use a::Abc; + | ^^^^^^ +note: added path (technically breaking) + --> addition_path/new.rs:13:9 + | +13 | pub use self::a::Abc; + | ^^^^^^^^^^^^ + +warning: path changes to `d` + --> addition_path/new.rs:15:1 + | +15 | / pub mod d { +16 | | +17 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: 2 warnings emitted + diff --git a/src/tools/semverver/tests/cases/addition_path/stdout_api_guidelines b/src/tools/semverver/tests/cases/addition_path/stdout_api_guidelines new file mode 100644 index 0000000000000..045662d9257f7 --- /dev/null +++ b/src/tools/semverver/tests/cases/addition_path/stdout_api_guidelines @@ -0,0 +1 @@ +version bump: 1.0.0 -> (technically breaking) -> 1.1.0 diff --git a/src/tools/semverver/tests/cases/addition_use/new.rs b/src/tools/semverver/tests/cases/addition_use/new.rs new file mode 100644 index 0000000000000..014b777d8fff8 --- /dev/null +++ b/src/tools/semverver/tests/cases/addition_use/new.rs @@ -0,0 +1,8 @@ +pub struct Abc; + +pub trait Bcd {} + +pub struct Def<'a> { + pub field1: Abc, + pub field2: &'a dyn Bcd, +} diff --git a/src/tools/semverver/tests/cases/addition_use/old.rs b/src/tools/semverver/tests/cases/addition_use/old.rs new file mode 100644 index 0000000000000..0f3c61ee435b0 --- /dev/null +++ b/src/tools/semverver/tests/cases/addition_use/old.rs @@ -0,0 +1,4 @@ +pub struct Def<'a> { + pub field1: (), + pub field2: &'a (), +} diff --git a/src/tools/semverver/tests/cases/addition_use/stdout b/src/tools/semverver/tests/cases/addition_use/stdout new file mode 100644 index 0000000000000..b15dcadf04ca1 --- /dev/null +++ b/src/tools/semverver/tests/cases/addition_use/stdout @@ -0,0 +1,31 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +error: breaking changes in `Def` + --> addition_use/new.rs:5:1 + | +5 | / pub struct Def<'a> { +6 | | pub field1: Abc, +7 | | pub field2: &'a dyn Bcd, +8 | | } + | |_^ + | + = warning: type error: expected `()`, found struct `new::Abc` (breaking) + = warning: type error: expected `()`, found trait object `dyn new::Bcd` (breaking) + +warning: path changes to `Abc` + --> addition_use/new.rs:1:1 + | +1 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + +warning: path changes to `Bcd` + --> addition_use/new.rs:3:1 + | +3 | pub trait Bcd {} + | ^^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + +error: aborting due to previous error; 2 warnings emitted + diff --git a/src/tools/semverver/tests/cases/addition_use/stdout_api_guidelines b/src/tools/semverver/tests/cases/addition_use/stdout_api_guidelines new file mode 100644 index 0000000000000..2b815c4bd4e92 --- /dev/null +++ b/src/tools/semverver/tests/cases/addition_use/stdout_api_guidelines @@ -0,0 +1,15 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +error: breaking changes in `Def` + --> addition_use/new.rs:5:1 + | +5 | / pub struct Def<'a> { +6 | | pub field1: Abc, +7 | | pub field2: &'a dyn Bcd, +8 | | } + | |_^ + | + = warning: type error: expected `()`, found struct `new::Abc` (breaking) + = warning: type error: expected `()`, found trait object `dyn new::Bcd` (breaking) + +error: aborting due to previous error + diff --git a/src/tools/semverver/tests/cases/bounds/new.rs b/src/tools/semverver/tests/cases/bounds/new.rs new file mode 100644 index 0000000000000..e35f3d7f2531e --- /dev/null +++ b/src/tools/semverver/tests/cases/bounds/new.rs @@ -0,0 +1,11 @@ +pub struct Abc { + pub a: A, +} + +pub struct Def { + pub d: A, +} + +pub fn abc(_: A) {} + +pub fn def(_: A) {} diff --git a/src/tools/semverver/tests/cases/bounds/old.rs b/src/tools/semverver/tests/cases/bounds/old.rs new file mode 100644 index 0000000000000..9e96307b71ca8 --- /dev/null +++ b/src/tools/semverver/tests/cases/bounds/old.rs @@ -0,0 +1,11 @@ +pub struct Abc { + pub a: A, +} + +pub struct Def { + pub d: A, +} + +pub fn abc(_: A) {} + +pub fn def(_: A) {} diff --git a/src/tools/semverver/tests/cases/bounds/stdout b/src/tools/semverver/tests/cases/bounds/stdout new file mode 100644 index 0000000000000..61cff1c07e4b8 --- /dev/null +++ b/src/tools/semverver/tests/cases/bounds/stdout @@ -0,0 +1,39 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +error: breaking changes in `Abc` + --> bounds/new.rs:1:1 + | +1 | / pub struct Abc { +2 | | pub a: A, +3 | | } + | |_^ + | + = warning: added bound: `A: std::clone::Clone` (breaking) + +warning: technically breaking changes in `Def` + --> bounds/new.rs:5:1 + | +5 | / pub struct Def { +6 | | pub d: A, +7 | | } + | |_^ + | + = note: removed bound: `A: std::clone::Clone` (technically breaking) + +error: breaking changes in `abc` + --> bounds/new.rs:9:1 + | +9 | pub fn abc(_: A) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: added bound: `A: std::clone::Clone` (breaking) + +warning: technically breaking changes in `def` + --> bounds/new.rs:11:1 + | +11 | pub fn def(_: A) {} + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: removed bound: `A: std::clone::Clone` (technically breaking) + +error: aborting due to 2 previous errors; 2 warnings emitted + diff --git a/src/tools/semverver/tests/cases/circular/new.rs b/src/tools/semverver/tests/cases/circular/new.rs new file mode 100644 index 0000000000000..db2735f7f52bb --- /dev/null +++ b/src/tools/semverver/tests/cases/circular/new.rs @@ -0,0 +1,6 @@ +use std::rc::Rc; + +#[allow(dead_code)] +struct Abc { + member: Option>, +} diff --git a/src/tools/semverver/tests/cases/circular/old.rs b/src/tools/semverver/tests/cases/circular/old.rs new file mode 100644 index 0000000000000..db2735f7f52bb --- /dev/null +++ b/src/tools/semverver/tests/cases/circular/old.rs @@ -0,0 +1,6 @@ +use std::rc::Rc; + +#[allow(dead_code)] +struct Abc { + member: Option>, +} diff --git a/src/tools/semverver/tests/cases/circular/stdout b/src/tools/semverver/tests/cases/circular/stdout new file mode 100644 index 0000000000000..f8c2af4c949b7 --- /dev/null +++ b/src/tools/semverver/tests/cases/circular/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/src/tools/semverver/tests/cases/consts/new.rs b/src/tools/semverver/tests/cases/consts/new.rs new file mode 100644 index 0000000000000..05808e455ae0b --- /dev/null +++ b/src/tools/semverver/tests/cases/consts/new.rs @@ -0,0 +1,9 @@ +pub const A: u16 = 0; + +pub static B: u16 = 1; + +pub const C: u8 = 1; + +pub static D: bool = true; + +pub static mut E: bool = true; diff --git a/src/tools/semverver/tests/cases/consts/old.rs b/src/tools/semverver/tests/cases/consts/old.rs new file mode 100644 index 0000000000000..4afed7b450b4a --- /dev/null +++ b/src/tools/semverver/tests/cases/consts/old.rs @@ -0,0 +1,9 @@ +pub const A: u8 = 0; + +pub static B: u8 = 1; + +pub const C: u8 = 0; + +pub static mut D: bool = true; + +pub static E: bool = true; diff --git a/src/tools/semverver/tests/cases/consts/stdout b/src/tools/semverver/tests/cases/consts/stdout new file mode 100644 index 0000000000000..36f2432a874aa --- /dev/null +++ b/src/tools/semverver/tests/cases/consts/stdout @@ -0,0 +1,35 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +error: breaking changes in `A` + --> consts/new.rs:1:1 + | +1 | pub const A: u16 = 0; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected `u8`, found `u16` (breaking) + +error: breaking changes in `B` + --> consts/new.rs:3:1 + | +3 | pub static B: u16 = 1; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected `u8`, found `u16` (breaking) + +error: breaking changes in `D` + --> consts/new.rs:7:1 + | +7 | pub static D: bool = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: static item made immutable (breaking) + +warning: non-breaking changes in `E` + --> consts/new.rs:9:1 + | +9 | pub static mut E: bool = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: static item made mutable (non-breaking) + +error: aborting due to 3 previous errors; 1 warning emitted + diff --git a/src/tools/semverver/tests/cases/enums/new.rs b/src/tools/semverver/tests/cases/enums/new.rs new file mode 100644 index 0000000000000..2b56e9fade29f --- /dev/null +++ b/src/tools/semverver/tests/cases/enums/new.rs @@ -0,0 +1,26 @@ +pub enum Abc { + Abc, +} + +pub enum Bcd { + +} + +pub enum Cde { + Abc, + Bcd, +} + +pub enum Def { + Abc, +} + +pub enum Efg { + Abc(u8), + Bcd, + Cde { f: u8 }, + Def, + Efg { f: u8 }, + Fgh { f: u16 }, + Ghi { g: u8 }, +} diff --git a/src/tools/semverver/tests/cases/enums/old.rs b/src/tools/semverver/tests/cases/enums/old.rs new file mode 100644 index 0000000000000..da5906a57e043 --- /dev/null +++ b/src/tools/semverver/tests/cases/enums/old.rs @@ -0,0 +1,26 @@ +pub enum Abc { + +} + +pub enum Bcd { + Abc, +} + +pub enum Cde { + Abc, +} + +pub enum Def { + Abc, + Bcd, +} + +pub enum Efg { + Abc, + Bcd(u8), + Cde, + Def { f: u8 }, + Efg(u8), + Fgh { f: u8 }, + Ghi { f: u8 }, +} diff --git a/src/tools/semverver/tests/cases/enums/stdout b/src/tools/semverver/tests/cases/enums/stdout new file mode 100644 index 0000000000000..5464c9721526c --- /dev/null +++ b/src/tools/semverver/tests/cases/enums/stdout @@ -0,0 +1,108 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +error: breaking changes in `Abc` + --> enums/new.rs:1:1 + | +1 | / pub enum Abc { +2 | | Abc, +3 | | } + | |_^ + | +warning: enum variant added (breaking) + --> enums/new.rs:2:5 + | +2 | Abc, + | ^^^ + +error: breaking changes in `Bcd` + --> enums/new.rs:5:1 + | +5 | / pub enum Bcd { +6 | | +7 | | } + | |_^ + | +warning: enum variant removed (breaking) + --> enums/old.rs:6:5 + | +6 | Abc, + | ^^^ + +error: breaking changes in `Cde` + --> enums/new.rs:9:1 + | +9 | / pub enum Cde { +10 | | Abc, +11 | | Bcd, +12 | | } + | |_^ + | +warning: enum variant added (breaking) + --> enums/new.rs:11:5 + | +11 | Bcd, + | ^^^ + +error: breaking changes in `Def` + --> enums/new.rs:14:1 + | +14 | / pub enum Def { +15 | | Abc, +16 | | } + | |_^ + | +warning: enum variant removed (breaking) + --> enums/old.rs:15:5 + | +15 | Bcd, + | ^^^ + +error: breaking changes in `Efg` + --> enums/new.rs:18:1 + | +18 | / pub enum Efg { +19 | | Abc(u8), +20 | | Bcd, +21 | | Cde { f: u8 }, +... | +25 | | Ghi { g: u8 }, +26 | | } + | |_^ + | +warning: variant with no public fields changed to a tuple variant (breaking) + --> enums/new.rs:19:5 + | +19 | Abc(u8), + | ^^^^^^^ +warning: variant with no public fields changed to a tuple variant (breaking) + --> enums/new.rs:20:5 + | +20 | Bcd, + | ^^^ +warning: variant with no public fields changed to a struct variant (breaking) + --> enums/new.rs:21:5 + | +21 | Cde { f: u8 }, + | ^^^^^^^^^^^^^ +warning: variant with no public fields changed to a tuple variant (breaking) + --> enums/new.rs:22:5 + | +22 | Def, + | ^^^ +warning: variant with no public fields changed to a struct variant (breaking) + --> enums/new.rs:23:5 + | +23 | Efg { f: u8 }, + | ^^^^^^^^^^^^^ +warning: private field removed from variant with private fields (breaking) + --> enums/old.rs:25:11 + | +25 | Ghi { f: u8 }, + | ^^^^^ +note: private field added to variant with private fields (non-breaking) + --> enums/new.rs:25:11 + | +25 | Ghi { g: u8 }, + | ^^^^^ + +error: aborting due to 5 previous errors + diff --git a/src/tools/semverver/tests/cases/func/new.rs b/src/tools/semverver/tests/cases/func/new.rs new file mode 100644 index 0000000000000..9239b474a6d8f --- /dev/null +++ b/src/tools/semverver/tests/cases/func/new.rs @@ -0,0 +1,30 @@ +#![feature(const_fn)] +pub fn abc() {} + +pub fn bcd(_: u8) {} + +pub fn cde() -> u16 { + 0xcde +} + +pub fn def() {} + +pub fn efg(a: A, _: A) -> A { + a +} + +pub fn fgh(a: u8, _: u16) -> u8 { + a +} + +pub fn ghi(a: u8, _: u8) -> u16 { + a as u16 +} + +pub const fn hij() -> u8 { + 0 +} + +pub fn ijk() -> u8 { + 0 +} diff --git a/src/tools/semverver/tests/cases/func/old.rs b/src/tools/semverver/tests/cases/func/old.rs new file mode 100644 index 0000000000000..a26077476b075 --- /dev/null +++ b/src/tools/semverver/tests/cases/func/old.rs @@ -0,0 +1,28 @@ +#![feature(const_fn)] +pub fn abc() {} + +pub fn bcd() {} + +pub fn cde() {} + +pub fn def(_: u8) {} + +pub fn efg(a: u8, _: u8) -> u8 { + a +} + +pub fn fgh(a: u8, _: u8) -> u8 { + a +} + +pub fn ghi(a: u8, _: u8) -> u8 { + a +} + +pub fn hij() -> u8 { + 0 +} + +pub const fn ijk() -> u8 { + 0 +} diff --git a/src/tools/semverver/tests/cases/func/stdout b/src/tools/semverver/tests/cases/func/stdout new file mode 100644 index 0000000000000..0cefacd6075e4 --- /dev/null +++ b/src/tools/semverver/tests/cases/func/stdout @@ -0,0 +1,79 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +error: breaking changes in `bcd` + --> func/new.rs:4:1 + | +4 | pub fn bcd(_: u8) {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: incorrect number of function parameters (breaking) + +error: breaking changes in `cde` + --> func/new.rs:6:1 + | +6 | / pub fn cde() -> u16 { +7 | | 0xcde +8 | | } + | |_^ + | + = warning: type error: expected `()`, found `u16` (breaking) + +error: breaking changes in `def` + --> func/new.rs:10:1 + | +10 | pub fn def() {} + | ^^^^^^^^^^^^^^^ + | + = warning: type error: incorrect number of function parameters (breaking) + +warning: non-breaking changes in `efg` + --> func/new.rs:12:1 + | +12 | / pub fn efg(a: A, _: A) -> A { +13 | | a +14 | | } + | |_^ + | + = note: defaulted type parameter added (non-breaking) + +error: breaking changes in `fgh` + --> func/new.rs:16:1 + | +16 | / pub fn fgh(a: u8, _: u16) -> u8 { +17 | | a +18 | | } + | |_^ + | + = warning: type error: expected `u8`, found `u16` (breaking) + +error: breaking changes in `ghi` + --> func/new.rs:20:1 + | +20 | / pub fn ghi(a: u8, _: u8) -> u16 { +21 | | a as u16 +22 | | } + | |_^ + | + = warning: type error: expected `u8`, found `u16` (breaking) + +warning: non-breaking changes in `hij` + --> func/new.rs:24:1 + | +24 | / pub const fn hij() -> u8 { +25 | | 0 +26 | | } + | |_^ + | + = note: fn item made const (non-breaking) + +error: breaking changes in `ijk` + --> func/new.rs:28:1 + | +28 | / pub fn ijk() -> u8 { +29 | | 0 +30 | | } + | |_^ + | + = warning: fn item made non-const (breaking) + +error: aborting due to 6 previous errors; 2 warnings emitted + diff --git a/src/tools/semverver/tests/cases/func_local_items/new.rs b/src/tools/semverver/tests/cases/func_local_items/new.rs new file mode 100644 index 0000000000000..8f8963a3adc46 --- /dev/null +++ b/src/tools/semverver/tests/cases/func_local_items/new.rs @@ -0,0 +1,6 @@ +pub fn abc() { + #[allow(dead_code)] + struct Something(); + + () +} diff --git a/src/tools/semverver/tests/cases/func_local_items/old.rs b/src/tools/semverver/tests/cases/func_local_items/old.rs new file mode 100644 index 0000000000000..5d42ef3f7a157 --- /dev/null +++ b/src/tools/semverver/tests/cases/func_local_items/old.rs @@ -0,0 +1,6 @@ +pub fn abc() { + #[allow(dead_code)] + struct SomethingElse(); + + () +} diff --git a/src/tools/semverver/tests/cases/func_local_items/stdout b/src/tools/semverver/tests/cases/func_local_items/stdout new file mode 100644 index 0000000000000..f8c2af4c949b7 --- /dev/null +++ b/src/tools/semverver/tests/cases/func_local_items/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/src/tools/semverver/tests/cases/infer/new.rs b/src/tools/semverver/tests/cases/infer/new.rs new file mode 100644 index 0000000000000..1067118189f91 --- /dev/null +++ b/src/tools/semverver/tests/cases/infer/new.rs @@ -0,0 +1,20 @@ +mod a { + pub trait Def { + + } + + pub struct Opq; +} + +pub fn a(a: A) -> A { + a +} + +pub fn b() -> a::Opq { + a::Opq +} + +pub struct Hij<'a> { + pub field: &'a dyn a::Def, + pub field2: ::std::rc::Rc, +} diff --git a/src/tools/semverver/tests/cases/infer/old.rs b/src/tools/semverver/tests/cases/infer/old.rs new file mode 100644 index 0000000000000..6ef1267587eca --- /dev/null +++ b/src/tools/semverver/tests/cases/infer/old.rs @@ -0,0 +1,20 @@ +mod a { + pub trait Abc { + + } + + pub struct Klm; +} + +pub fn a(a: A) -> A { + a +} + +pub fn b() -> a::Klm { + a::Klm +} + +pub struct Hij<'a> { + pub field: &'a dyn a::Abc, + pub field2: ::std::rc::Rc, +} diff --git a/src/tools/semverver/tests/cases/infer/stdout b/src/tools/semverver/tests/cases/infer/stdout new file mode 100644 index 0000000000000..f8c2af4c949b7 --- /dev/null +++ b/src/tools/semverver/tests/cases/infer/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/src/tools/semverver/tests/cases/infer_regress/new.rs b/src/tools/semverver/tests/cases/infer_regress/new.rs new file mode 100644 index 0000000000000..86aafa21b9875 --- /dev/null +++ b/src/tools/semverver/tests/cases/infer_regress/new.rs @@ -0,0 +1,3 @@ +pub fn abc(_: A) { } + +pub struct Abc(pub A, pub ()); diff --git a/src/tools/semverver/tests/cases/infer_regress/old.rs b/src/tools/semverver/tests/cases/infer_regress/old.rs new file mode 100644 index 0000000000000..e6def43b4d539 --- /dev/null +++ b/src/tools/semverver/tests/cases/infer_regress/old.rs @@ -0,0 +1,5 @@ +pub fn abc(a: A) -> A { + a +} + +pub struct Abc(pub A, pub A); diff --git a/src/tools/semverver/tests/cases/infer_regress/stdout b/src/tools/semverver/tests/cases/infer_regress/stdout new file mode 100644 index 0000000000000..82a0c8cfc1a7a --- /dev/null +++ b/src/tools/semverver/tests/cases/infer_regress/stdout @@ -0,0 +1,20 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +error: breaking changes in `abc` + --> infer_regress/new.rs:1:1 + | +1 | pub fn abc(_: A) { } + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: variance loosened (non-breaking) + = warning: type error: expected type parameter `A`, found `()` (breaking) + +error: breaking changes in `Abc` + --> infer_regress/new.rs:3:1 + | +3 | pub struct Abc(pub A, pub ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected type parameter `A`, found `()` (breaking) + +error: aborting due to 2 previous errors + diff --git a/src/tools/semverver/tests/cases/inherent_impls/new.rs b/src/tools/semverver/tests/cases/inherent_impls/new.rs new file mode 100644 index 0000000000000..0b0e506c59d80 --- /dev/null +++ b/src/tools/semverver/tests/cases/inherent_impls/new.rs @@ -0,0 +1,40 @@ +#[allow(dead_code)] +pub struct Abc { } + +#[allow(dead_code)] +impl Abc { + const A: u8 = 3; + + pub fn abc(&self) -> u8 { + 0 + } + + fn def(&self) { } + + pub fn ghi(&self, _: A) -> u8 { + 0 + } +} + +#[allow(dead_code)] +pub struct Def { + field: A, +} + +#[allow(dead_code)] +impl Def { + pub fn def(&self) -> u16 { + 0 + } + + pub fn abc() { } + + fn abc2() { } +} + +#[allow(dead_code)] +impl Def { + pub fn def(&self) -> u8 { + 0 + } +} diff --git a/src/tools/semverver/tests/cases/inherent_impls/old.rs b/src/tools/semverver/tests/cases/inherent_impls/old.rs new file mode 100644 index 0000000000000..26b10adb934eb --- /dev/null +++ b/src/tools/semverver/tests/cases/inherent_impls/old.rs @@ -0,0 +1,40 @@ +#[allow(dead_code)] +pub struct Abc { } + +#[allow(dead_code)] +impl Abc { + const A: u8 = 3; + + pub fn abc(&self) -> u8 { + 0 + } + + fn def(&self) { } + + pub fn ghi(&self, a: A) -> A { + a + } +} + +#[allow(dead_code)] +pub struct Def { + field: A, +} + +#[allow(dead_code)] +impl Def { + pub fn def(&self) -> u8 { + 0 + } +} + +#[allow(dead_code)] +impl Def { + pub fn def(&self) -> u8 { + 0 + } + + pub fn ghi() { } + + fn ghi2() { } +} diff --git a/src/tools/semverver/tests/cases/inherent_impls/stdout b/src/tools/semverver/tests/cases/inherent_impls/stdout new file mode 100644 index 0000000000000..1756d63cefc03 --- /dev/null +++ b/src/tools/semverver/tests/cases/inherent_impls/stdout @@ -0,0 +1,59 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +error: breaking changes in `ghi` + --> inherent_impls/old.rs:14:5 + | +14 | / pub fn ghi(&self, a: A) -> A { +15 | | a +16 | | } + | |_____^ + | + = warning: type error: expected type parameter `A`, found `u8` (breaking) + +error: breaking changes in `def` + --> inherent_impls/old.rs:26:5 + | +26 | / pub fn def(&self) -> u8 { +27 | | 0 +28 | | } + | |_____^ + | + = warning: removed item in inherent impl (breaking) + +error: breaking changes in `def` + --> inherent_impls/old.rs:33:5 + | +33 | / pub fn def(&self) -> u8 { +34 | | 0 +35 | | } + | |_____^ + | + = warning: type error: expected `u8`, found `u16` (breaking) + +error: breaking changes in `ghi` + --> inherent_impls/old.rs:37:5 + | +37 | pub fn ghi() { } + | ^^^^^^^^^^^^^^^^ + | + = warning: removed item in inherent impl (breaking) + +warning: technically breaking changes in `abc` + --> inherent_impls/new.rs:30:5 + | +30 | pub fn abc() { } + | ^^^^^^^^^^^^^^^^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in `def` + --> inherent_impls/new.rs:37:5 + | +37 | / pub fn def(&self) -> u8 { +38 | | 0 +39 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + +error: aborting due to 4 previous errors; 2 warnings emitted + diff --git a/src/tools/semverver/tests/cases/issue_34/new.rs b/src/tools/semverver/tests/cases/issue_34/new.rs new file mode 100644 index 0000000000000..33434b195e990 --- /dev/null +++ b/src/tools/semverver/tests/cases/issue_34/new.rs @@ -0,0 +1,11 @@ +use std::marker::PhantomData; + +pub fn missing_field<'de, V, E>() -> Result { + #[allow(dead_code)] + struct MissingFieldDeserializer(PhantomData); + + impl Deserializer for MissingFieldDeserializer {} + unimplemented!() +} + +pub trait Deserializer {} diff --git a/src/tools/semverver/tests/cases/issue_34/old.rs b/src/tools/semverver/tests/cases/issue_34/old.rs new file mode 100644 index 0000000000000..33434b195e990 --- /dev/null +++ b/src/tools/semverver/tests/cases/issue_34/old.rs @@ -0,0 +1,11 @@ +use std::marker::PhantomData; + +pub fn missing_field<'de, V, E>() -> Result { + #[allow(dead_code)] + struct MissingFieldDeserializer(PhantomData); + + impl Deserializer for MissingFieldDeserializer {} + unimplemented!() +} + +pub trait Deserializer {} diff --git a/src/tools/semverver/tests/cases/issue_34/stdout b/src/tools/semverver/tests/cases/issue_34/stdout new file mode 100644 index 0000000000000..f8c2af4c949b7 --- /dev/null +++ b/src/tools/semverver/tests/cases/issue_34/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/src/tools/semverver/tests/cases/issue_50/new.rs b/src/tools/semverver/tests/cases/issue_50/new.rs new file mode 100644 index 0000000000000..1c5995ed73f6a --- /dev/null +++ b/src/tools/semverver/tests/cases/issue_50/new.rs @@ -0,0 +1,16 @@ +pub trait TypedArrayElement { + type Element; +} + +pub struct CreateWith<'a, T: 'a>(&'a T); + +pub fn create(_: CreateWith) { } + +/* #[allow(dead_code)] +pub struct TypedArray { + computed: T::Element, +} + +impl TypedArray { + pub unsafe fn create(_: CreateWith) { } +} */ diff --git a/src/tools/semverver/tests/cases/issue_50/old.rs b/src/tools/semverver/tests/cases/issue_50/old.rs new file mode 100644 index 0000000000000..1c5995ed73f6a --- /dev/null +++ b/src/tools/semverver/tests/cases/issue_50/old.rs @@ -0,0 +1,16 @@ +pub trait TypedArrayElement { + type Element; +} + +pub struct CreateWith<'a, T: 'a>(&'a T); + +pub fn create(_: CreateWith) { } + +/* #[allow(dead_code)] +pub struct TypedArray { + computed: T::Element, +} + +impl TypedArray { + pub unsafe fn create(_: CreateWith) { } +} */ diff --git a/src/tools/semverver/tests/cases/issue_50/stdout b/src/tools/semverver/tests/cases/issue_50/stdout new file mode 100644 index 0000000000000..f8c2af4c949b7 --- /dev/null +++ b/src/tools/semverver/tests/cases/issue_50/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/src/tools/semverver/tests/cases/kind_change/new.rs b/src/tools/semverver/tests/cases/kind_change/new.rs new file mode 100644 index 0000000000000..8f2ac73a32a86 --- /dev/null +++ b/src/tools/semverver/tests/cases/kind_change/new.rs @@ -0,0 +1,3 @@ +pub enum Abc { + +} diff --git a/src/tools/semverver/tests/cases/kind_change/old.rs b/src/tools/semverver/tests/cases/kind_change/old.rs new file mode 100644 index 0000000000000..c7b09689bf4ef --- /dev/null +++ b/src/tools/semverver/tests/cases/kind_change/old.rs @@ -0,0 +1 @@ +pub struct Abc; diff --git a/src/tools/semverver/tests/cases/kind_change/stdout b/src/tools/semverver/tests/cases/kind_change/stdout new file mode 100644 index 0000000000000..f8d9d0dd81207 --- /dev/null +++ b/src/tools/semverver/tests/cases/kind_change/stdout @@ -0,0 +1,13 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +error: breaking changes in `Abc` + --> kind_change/new.rs:1:1 + | +1 | / pub enum Abc { +2 | | +3 | | } + | |_^ + | + = warning: item kind changed (breaking) + +error: aborting due to previous error + diff --git a/src/tools/semverver/tests/cases/macros/new.rs b/src/tools/semverver/tests/cases/macros/new.rs new file mode 100644 index 0000000000000..58c04fcf36594 --- /dev/null +++ b/src/tools/semverver/tests/cases/macros/new.rs @@ -0,0 +1,26 @@ +#![feature(decl_macro)] +pub struct Item; + +pub macro foo() { Item } + +#[macro_export] +macro_rules! bar { + () => { + Item + } +} + +pub macro baz() { Item } + +pub macro quux1() { Item } + +#[macro_export] +macro_rules! quux2 { + () => { + Item + } +} + +pub fn abc() -> Item { + bar!() +} diff --git a/src/tools/semverver/tests/cases/macros/old.rs b/src/tools/semverver/tests/cases/macros/old.rs new file mode 100644 index 0000000000000..fd850798fd152 --- /dev/null +++ b/src/tools/semverver/tests/cases/macros/old.rs @@ -0,0 +1,26 @@ +#![feature(decl_macro)] +pub struct Item; + +pub macro foo() { Item } + +pub macro bar() { Item } + +#[macro_export] +macro_rules! baz { + () => { + Item + } +} + +pub macro qux1() { Item } + +#[macro_export] +macro_rules! qux2 { + () => { + Item + } +} + +pub fn abc() -> Item { + bar!() +} diff --git a/src/tools/semverver/tests/cases/macros/stdout b/src/tools/semverver/tests/cases/macros/stdout new file mode 100644 index 0000000000000..d279b2dd98f8a --- /dev/null +++ b/src/tools/semverver/tests/cases/macros/stdout @@ -0,0 +1,43 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +error: path changes to `qux1` + --> macros/old.rs:15:1 + | +15 | pub macro qux1() { Item } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: removed definition (breaking) + +error: path changes to `qux2` + --> macros/old.rs:18:1 + | +18 | / macro_rules! qux2 { +19 | | () => { +20 | | Item +21 | | } +22 | | } + | |_^ + | + = warning: removed definition (breaking) + +warning: path changes to `quux1` + --> macros/new.rs:15:1 + | +15 | pub macro quux1() { Item } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + +warning: path changes to `quux2` + --> macros/new.rs:18:1 + | +18 | / macro_rules! quux2 { +19 | | () => { +20 | | Item +21 | | } +22 | | } + | |_^ + | + = note: added definition (technically breaking) + +error: aborting due to 2 previous errors; 2 warnings emitted + diff --git a/src/tools/semverver/tests/cases/max_priv/new.rs b/src/tools/semverver/tests/cases/max_priv/new.rs new file mode 100644 index 0000000000000..5fee028301763 --- /dev/null +++ b/src/tools/semverver/tests/cases/max_priv/new.rs @@ -0,0 +1,2 @@ +#[allow(dead_code)] +const A: u16 = 0; diff --git a/src/tools/semverver/tests/cases/max_priv/old.rs b/src/tools/semverver/tests/cases/max_priv/old.rs new file mode 100644 index 0000000000000..60c0e3ce84f2e --- /dev/null +++ b/src/tools/semverver/tests/cases/max_priv/old.rs @@ -0,0 +1,2 @@ +#[allow(dead_code)] +const A: u8 = 0; diff --git a/src/tools/semverver/tests/cases/max_priv/stdout b/src/tools/semverver/tests/cases/max_priv/stdout new file mode 100644 index 0000000000000..f8c2af4c949b7 --- /dev/null +++ b/src/tools/semverver/tests/cases/max_priv/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/src/tools/semverver/tests/cases/mix/new.rs b/src/tools/semverver/tests/cases/mix/new.rs new file mode 100644 index 0000000000000..553516bd87ccd --- /dev/null +++ b/src/tools/semverver/tests/cases/mix/new.rs @@ -0,0 +1,10 @@ +pub mod a { + pub enum Abc {} + pub struct Def; +} + +pub mod b { + pub use a::Abc; +} + +pub use self::a::Def; diff --git a/src/tools/semverver/tests/cases/mix/old.rs b/src/tools/semverver/tests/cases/mix/old.rs new file mode 100644 index 0000000000000..f9f33b93b541f --- /dev/null +++ b/src/tools/semverver/tests/cases/mix/old.rs @@ -0,0 +1,10 @@ +pub mod a { + pub struct Abc; + pub enum Def {} +} + +pub mod b { + +} + +pub use self::a::Abc; diff --git a/src/tools/semverver/tests/cases/mix/stdout b/src/tools/semverver/tests/cases/mix/stdout new file mode 100644 index 0000000000000..3f3a942e0cac4 --- /dev/null +++ b/src/tools/semverver/tests/cases/mix/stdout @@ -0,0 +1,47 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +error: breaking changes in `Abc` + --> mix/new.rs:2:5 + | +2 | pub enum Abc {} + | ^^^^^^^^^^^^^^^ + | + = warning: item kind changed (breaking) + +error: breaking changes in `Def` + --> mix/new.rs:3:5 + | +3 | pub struct Def; + | ^^^^^^^^^^^^^^^ + | + = warning: item kind changed (breaking) + +error: path changes to `Abc` + --> mix/new.rs:2:5 + | +2 | pub enum Abc {} + | ^^^^^^^^^^^^^^^ + | +warning: removed path (breaking) + --> mix/old.rs:10:9 + | +10 | pub use self::a::Abc; + | ^^^^^^^^^^^^ +note: added path (technically breaking) + --> mix/new.rs:7:13 + | +7 | pub use a::Abc; + | ^^^^^^ + +warning: path changes to `Def` + --> mix/new.rs:3:5 + | +3 | pub struct Def; + | ^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> mix/new.rs:10:9 + | +10 | pub use self::a::Def; + | ^^^^^^^^^^^^ + +error: aborting due to 3 previous errors; 1 warning emitted diff --git a/src/tools/semverver/tests/cases/pathologic_paths/new.rs b/src/tools/semverver/tests/cases/pathologic_paths/new.rs new file mode 100644 index 0000000000000..bd4c1d7f02959 --- /dev/null +++ b/src/tools/semverver/tests/cases/pathologic_paths/new.rs @@ -0,0 +1,17 @@ +#![recursion_limit="128"] +macro_rules! blow { + () => {}; + (_ $($rest:tt)*) => { + pub mod a { blow!($($rest)*); } + pub mod b { pub use super::a::*; } + } +} + +blow!(_ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _); diff --git a/src/tools/semverver/tests/cases/pathologic_paths/old.rs b/src/tools/semverver/tests/cases/pathologic_paths/old.rs new file mode 100644 index 0000000000000..8b137891791fe --- /dev/null +++ b/src/tools/semverver/tests/cases/pathologic_paths/old.rs @@ -0,0 +1 @@ + diff --git a/src/tools/semverver/tests/cases/pathologic_paths/stdout b/src/tools/semverver/tests/cases/pathologic_paths/stdout new file mode 100644 index 0000000000000..d9aae39fb923e --- /dev/null +++ b/src/tools/semverver/tests/cases/pathologic_paths/stdout @@ -0,0 +1,19 @@ +version bump: 1.0.0 -> (technically breaking) -> 1.1.0 +warning: path changes to `a` + --> pathologic_paths/new.rs:5:9 + | +5 | pub mod a { blow!($($rest)*); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + +warning: path changes to `b` + --> pathologic_paths/new.rs:6:9 + | +6 | pub mod b { pub use super::a::*; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + +warning: 2 warnings emitted + diff --git a/src/tools/semverver/tests/cases/pub_use/new.rs b/src/tools/semverver/tests/cases/pub_use/new.rs new file mode 100644 index 0000000000000..b892cbe0ef453 --- /dev/null +++ b/src/tools/semverver/tests/cases/pub_use/new.rs @@ -0,0 +1,7 @@ +pub mod a { + pub struct Abc; +} + +pub mod b { + pub use a::*; +} diff --git a/src/tools/semverver/tests/cases/pub_use/old.rs b/src/tools/semverver/tests/cases/pub_use/old.rs new file mode 100644 index 0000000000000..0ef477c4a4ab1 --- /dev/null +++ b/src/tools/semverver/tests/cases/pub_use/old.rs @@ -0,0 +1,5 @@ +pub mod a { + pub struct Abc; +} + +pub use a as b; diff --git a/src/tools/semverver/tests/cases/pub_use/stdout b/src/tools/semverver/tests/cases/pub_use/stdout new file mode 100644 index 0000000000000..f8c2af4c949b7 --- /dev/null +++ b/src/tools/semverver/tests/cases/pub_use/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/src/tools/semverver/tests/cases/regions/new.rs b/src/tools/semverver/tests/cases/regions/new.rs new file mode 100644 index 0000000000000..a87db392d40d4 --- /dev/null +++ b/src/tools/semverver/tests/cases/regions/new.rs @@ -0,0 +1,19 @@ +#![allow(type_alias_bounds)] + +pub type A = fn(&bool); + +pub type B = for<'a> fn(&'a bool); + +pub type C<'a, 'b> = (&'b u8, &'a u16); + +pub type D = ::IntoIter; + +pub type E = T; + +pub fn abc(_: &bool) { } + +pub fn def(_: bool) { } + +pub fn efg(_: &str) { } + +pub fn fgh(_: &'static str) { } diff --git a/src/tools/semverver/tests/cases/regions/old.rs b/src/tools/semverver/tests/cases/regions/old.rs new file mode 100644 index 0000000000000..07d02bff24dd2 --- /dev/null +++ b/src/tools/semverver/tests/cases/regions/old.rs @@ -0,0 +1,19 @@ +#![allow(type_alias_bounds)] + +pub type A = for<'a> fn(&'a bool); + +pub type B = fn(&bool); + +pub type C<'a, 'b> = (&'a u8, &'b u16); + +pub type D = ::Item; + +pub type E = ::Item; + +pub fn abc(_: bool) { } + +pub fn def(_: &bool) { } + +pub fn efg(_: &'static str) { } + +pub fn fgh(_: &str) { } diff --git a/src/tools/semverver/tests/cases/regions/stdout b/src/tools/semverver/tests/cases/regions/stdout new file mode 100644 index 0000000000000..3f3ac0d275d7a --- /dev/null +++ b/src/tools/semverver/tests/cases/regions/stdout @@ -0,0 +1,51 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +error: breaking changes in `D` + --> regions/new.rs:9:1 + | +9 | pub type D = ::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected std::iter::IntoIterator::Item, found std::iter::IntoIterator::IntoIter (breaking) + +error: breaking changes in `E` + --> regions/new.rs:11:1 + | +11 | pub type E = T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected associated type, found type parameter `T` (breaking) + +error: breaking changes in `abc` + --> regions/new.rs:13:1 + | +13 | pub fn abc(_: &bool) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected `bool`, found `&bool` (breaking) + +error: breaking changes in `def` + --> regions/new.rs:15:1 + | +15 | pub fn def(_: bool) { } + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected `&bool`, found `bool` (breaking) + +error: breaking changes in `efg` + --> regions/new.rs:17:1 + | +17 | pub fn efg(_: &str) { } + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected bound lifetime parameter, found concrete lifetime (breaking) + +error: breaking changes in `fgh` + --> regions/new.rs:19:1 + | +19 | pub fn fgh(_: &'static str) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected bound lifetime parameter, found concrete lifetime (breaking) + +error: aborting due to 6 previous errors + diff --git a/src/tools/semverver/tests/cases/removal/new.rs b/src/tools/semverver/tests/cases/removal/new.rs new file mode 100644 index 0000000000000..39a077e8f6421 --- /dev/null +++ b/src/tools/semverver/tests/cases/removal/new.rs @@ -0,0 +1,14 @@ +#[allow(dead_code)] +struct Bcd; + +mod b { + +} + +mod c { + +} + +mod d { + +} diff --git a/src/tools/semverver/tests/cases/removal/old.rs b/src/tools/semverver/tests/cases/removal/old.rs new file mode 100644 index 0000000000000..5c6c42226c1c5 --- /dev/null +++ b/src/tools/semverver/tests/cases/removal/old.rs @@ -0,0 +1,21 @@ +pub struct Abc; + +pub struct Bcd; + +pub mod a { + +} + +pub mod b { + #[allow(dead_code)] + pub struct Cde; +} + +mod c { + #[allow(dead_code)] + pub struct Def; +} + +pub mod d { + +} diff --git a/src/tools/semverver/tests/cases/removal/stdout b/src/tools/semverver/tests/cases/removal/stdout new file mode 100644 index 0000000000000..187fe489cb402 --- /dev/null +++ b/src/tools/semverver/tests/cases/removal/stdout @@ -0,0 +1,57 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +error: path changes to `Abc` + --> removal/old.rs:1:1 + | +1 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + | + = warning: removed definition (breaking) + +error: breaking changes in `Bcd` + --> removal/new.rs:2:1 + | +2 | struct Bcd; + | ^^^^^^^^^^^ + | + = warning: item made private (breaking) + +error: path changes to `a` + --> removal/old.rs:5:1 + | +5 | / pub mod a { +6 | | +7 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: breaking changes in `b` + --> removal/new.rs:4:1 + | +4 | / mod b { +5 | | +6 | | } + | |_^ + | + = warning: item made private (breaking) + +error: path changes to `Cde` + --> removal/old.rs:11:5 + | +11 | pub struct Cde; + | ^^^^^^^^^^^^^^^ + | + = warning: removed definition (breaking) + +error: breaking changes in `d` + --> removal/new.rs:12:1 + | +12 | / mod d { +13 | | +14 | | } + | |_^ + | + = warning: item made private (breaking) + +error: aborting due to 6 previous errors + diff --git a/src/tools/semverver/tests/cases/removal_path/new.rs b/src/tools/semverver/tests/cases/removal_path/new.rs new file mode 100644 index 0000000000000..d4c860740fea5 --- /dev/null +++ b/src/tools/semverver/tests/cases/removal_path/new.rs @@ -0,0 +1,15 @@ +pub mod a { + pub struct Abc; +} + +pub mod b { + +} + +pub mod c { + +} + +mod d { + +} diff --git a/src/tools/semverver/tests/cases/removal_path/old.rs b/src/tools/semverver/tests/cases/removal_path/old.rs new file mode 100644 index 0000000000000..15ce872a6b5d3 --- /dev/null +++ b/src/tools/semverver/tests/cases/removal_path/old.rs @@ -0,0 +1,17 @@ +pub mod a { + pub struct Abc; +} + +pub mod b { + pub use a::*; +} + +pub mod c { + pub use a::Abc; +} + +pub use self::a::Abc; + +mod d { + pub use a::Abc; +} diff --git a/src/tools/semverver/tests/cases/removal_path/stdout b/src/tools/semverver/tests/cases/removal_path/stdout new file mode 100644 index 0000000000000..1e47844de748e --- /dev/null +++ b/src/tools/semverver/tests/cases/removal_path/stdout @@ -0,0 +1,24 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +error: path changes to `Abc` + --> removal_path/new.rs:2:5 + | +2 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + | +warning: removed path (breaking) + --> removal_path/old.rs:6:13 + | +6 | pub use a::*; + | ^^^^ +warning: removed path (breaking) + --> removal_path/old.rs:10:13 + | +10 | pub use a::Abc; + | ^^^^^^ +warning: removed path (breaking) + --> removal_path/old.rs:13:9 + | +13 | pub use self::a::Abc; + | ^^^^^^^^^^^^ + +error: aborting due to previous error diff --git a/src/tools/semverver/tests/cases/removal_use/new.rs b/src/tools/semverver/tests/cases/removal_use/new.rs new file mode 100644 index 0000000000000..0f3c61ee435b0 --- /dev/null +++ b/src/tools/semverver/tests/cases/removal_use/new.rs @@ -0,0 +1,4 @@ +pub struct Def<'a> { + pub field1: (), + pub field2: &'a (), +} diff --git a/src/tools/semverver/tests/cases/removal_use/old.rs b/src/tools/semverver/tests/cases/removal_use/old.rs new file mode 100644 index 0000000000000..014b777d8fff8 --- /dev/null +++ b/src/tools/semverver/tests/cases/removal_use/old.rs @@ -0,0 +1,8 @@ +pub struct Abc; + +pub trait Bcd {} + +pub struct Def<'a> { + pub field1: Abc, + pub field2: &'a dyn Bcd, +} diff --git a/src/tools/semverver/tests/cases/removal_use/stdout b/src/tools/semverver/tests/cases/removal_use/stdout new file mode 100644 index 0000000000000..deed1be939f48 --- /dev/null +++ b/src/tools/semverver/tests/cases/removal_use/stdout @@ -0,0 +1,31 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +error: path changes to `Abc` + --> removal_use/old.rs:1:1 + | +1 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + | + = warning: removed definition (breaking) + +error: path changes to `Bcd` + --> removal_use/old.rs:3:1 + | +3 | pub trait Bcd {} + | ^^^^^^^^^^^^^^^^ + | + = warning: removed definition (breaking) + +error: breaking changes in `Def` + --> removal_use/new.rs:1:1 + | +1 | / pub struct Def<'a> { +2 | | pub field1: (), +3 | | pub field2: &'a (), +4 | | } + | |_^ + | + = warning: type error: expected struct `old::Abc`, found `()` (breaking) + = warning: type error: expected trait object `dyn old::Bcd`, found `()` (breaking) + +error: aborting due to 3 previous errors + diff --git a/src/tools/semverver/tests/cases/sealed_traits/new.rs b/src/tools/semverver/tests/cases/sealed_traits/new.rs new file mode 100644 index 0000000000000..0b12d071f7d50 --- /dev/null +++ b/src/tools/semverver/tests/cases/sealed_traits/new.rs @@ -0,0 +1,7 @@ +pub trait PublicTrait : private::PrivateTrait { + fn abc(&self) -> bool; +} + +mod private { + pub trait PrivateTrait { } +} diff --git a/src/tools/semverver/tests/cases/sealed_traits/old.rs b/src/tools/semverver/tests/cases/sealed_traits/old.rs new file mode 100644 index 0000000000000..7df0fde4e799d --- /dev/null +++ b/src/tools/semverver/tests/cases/sealed_traits/old.rs @@ -0,0 +1,5 @@ +pub trait PublicTrait : private::PrivateTrait { } + +mod private { + pub trait PrivateTrait { } +} diff --git a/src/tools/semverver/tests/cases/sealed_traits/stdout b/src/tools/semverver/tests/cases/sealed_traits/stdout new file mode 100644 index 0000000000000..4192b297d505f --- /dev/null +++ b/src/tools/semverver/tests/cases/sealed_traits/stdout @@ -0,0 +1,17 @@ +version bump: 1.0.0 -> (technically breaking) -> 1.1.0 +warning: technically breaking changes in `PublicTrait` + --> sealed_traits/new.rs:1:1 + | +1 | / pub trait PublicTrait : private::PrivateTrait { +2 | | fn abc(&self) -> bool; +3 | | } + | |_^ + | +note: added item to sealed trait (technically breaking) + --> sealed_traits/new.rs:2:5 + | +2 | fn abc(&self) -> bool; + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/src/tools/semverver/tests/cases/structs/new.rs b/src/tools/semverver/tests/cases/structs/new.rs new file mode 100644 index 0000000000000..ff1cae4de375c --- /dev/null +++ b/src/tools/semverver/tests/cases/structs/new.rs @@ -0,0 +1,28 @@ +#![allow(dead_code)] +pub struct Abc { + field: B, +} + +pub struct Def { + pub field: A, +} + +pub struct Def2 { + pub field: A, +} + +pub struct Efg { + pub field: u16, +} + +pub struct Fgh { + pub field: u8, +} + +pub struct Ghi { + field: u8, +} + +pub struct Hij { + field: u8, +} diff --git a/src/tools/semverver/tests/cases/structs/old.rs b/src/tools/semverver/tests/cases/structs/old.rs new file mode 100644 index 0000000000000..e06b3a578b3d9 --- /dev/null +++ b/src/tools/semverver/tests/cases/structs/old.rs @@ -0,0 +1,26 @@ +#![allow(dead_code)] +pub struct Abc { + field: A, +} + +pub struct Def { + field: u8, +} + +pub struct Def2 { + pub field: u8, +} + +pub struct Efg { + pub field: u8, +} + +pub struct Fgh { + field: u8, +} + +pub struct Ghi { + pub field: u8, +} + +pub struct Hij(u8); diff --git a/src/tools/semverver/tests/cases/structs/stdout b/src/tools/semverver/tests/cases/structs/stdout new file mode 100644 index 0000000000000..537021b38cde3 --- /dev/null +++ b/src/tools/semverver/tests/cases/structs/stdout @@ -0,0 +1,83 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: technically breaking changes in `Def` + --> structs/new.rs:6:1 + | +6 | / pub struct Def { +7 | | pub field: A, +8 | | } + | |_^ + | + = note: defaulted type parameter added (non-breaking) +note: item made public (technically breaking) + --> structs/new.rs:7:5 + | +7 | pub field: A, + | ^^^^^^^^^^^^ + +error: breaking changes in `Def2` + --> structs/new.rs:10:1 + | +10 | / pub struct Def2 { +11 | | pub field: A, +12 | | } + | |_^ + | + = note: defaulted type parameter added (non-breaking) + = warning: type error: expected `u8`, found `u16` (breaking) + +error: breaking changes in `Efg` + --> structs/new.rs:14:1 + | +14 | / pub struct Efg { +15 | | pub field: u16, +16 | | } + | |_^ + | + = warning: type error: expected `u8`, found `u16` (breaking) + +warning: technically breaking changes in `Fgh` + --> structs/new.rs:18:1 + | +18 | / pub struct Fgh { +19 | | pub field: u8, +20 | | } + | |_^ + | +note: item made public (technically breaking) + --> structs/new.rs:19:5 + | +19 | pub field: u8, + | ^^^^^^^^^^^^^ + +error: breaking changes in `Ghi` + --> structs/new.rs:22:1 + | +22 | / pub struct Ghi { +23 | | field: u8, +24 | | } + | |_^ + | +warning: item made private (breaking) + --> structs/new.rs:23:5 + | +23 | field: u8, + | ^^^^^^^^^ + +error: breaking changes in `Hij` + --> structs/new.rs:26:1 + | +26 | / pub struct Hij { +27 | | field: u8, +28 | | } + | |_^ + | +warning: tuple struct with no public fields changed to a regular struct (breaking) + --> structs/new.rs:26:1 + | +26 | / pub struct Hij { +27 | | field: u8, +28 | | } + | |_^ + +error: aborting due to 4 previous errors; 2 warnings emitted + diff --git a/src/tools/semverver/tests/cases/swap/new.rs b/src/tools/semverver/tests/cases/swap/new.rs new file mode 100644 index 0000000000000..2ee685eb5ef46 --- /dev/null +++ b/src/tools/semverver/tests/cases/swap/new.rs @@ -0,0 +1,7 @@ +pub mod a { + pub use super::b::Abc; +} + +pub mod b { + pub struct Abc; +} diff --git a/src/tools/semverver/tests/cases/swap/old.rs b/src/tools/semverver/tests/cases/swap/old.rs new file mode 100644 index 0000000000000..8cc7e4a0538c7 --- /dev/null +++ b/src/tools/semverver/tests/cases/swap/old.rs @@ -0,0 +1,7 @@ +pub mod a { + pub struct Abc; +} + +pub mod b { + pub use super::a::Abc; +} diff --git a/src/tools/semverver/tests/cases/swap/stdout b/src/tools/semverver/tests/cases/swap/stdout new file mode 100644 index 0000000000000..f8c2af4c949b7 --- /dev/null +++ b/src/tools/semverver/tests/cases/swap/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/src/tools/semverver/tests/cases/trait_impls/new.rs b/src/tools/semverver/tests/cases/trait_impls/new.rs new file mode 100644 index 0000000000000..691a526965329 --- /dev/null +++ b/src/tools/semverver/tests/cases/trait_impls/new.rs @@ -0,0 +1,17 @@ +use std::cell::Cell; + +pub struct Def; + +pub trait Abc { } + +impl Abc for Option { } + +impl Abc for Def { } + +impl Abc for Box { } + +impl Abc for Box { } + +impl Abc for () { } + +impl Abc for Cell<(bool, T)> { } diff --git a/src/tools/semverver/tests/cases/trait_impls/old.rs b/src/tools/semverver/tests/cases/trait_impls/old.rs new file mode 100644 index 0000000000000..c3d64c6d460aa --- /dev/null +++ b/src/tools/semverver/tests/cases/trait_impls/old.rs @@ -0,0 +1,15 @@ +pub struct Def; + +pub trait Abc { } + +impl Abc for Option { } + +impl Abc for Def { } + +impl Abc for Vec { } + +impl Clone for Def { + fn clone(&self) -> Def { + Def + } +} diff --git a/src/tools/semverver/tests/cases/trait_impls/stdout b/src/tools/semverver/tests/cases/trait_impls/stdout new file mode 100644 index 0000000000000..d4ce24bbde0b9 --- /dev/null +++ b/src/tools/semverver/tests/cases/trait_impls/stdout @@ -0,0 +1,55 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +error: breaking changes in ` as old::Abc>` + --> trait_impls/old.rs:9:1 + | +9 | impl Abc for Vec { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `` + --> trait_impls/old.rs:11:1 + | +11 | / impl Clone for Def { +12 | | fn clone(&self) -> Def { +13 | | Def +14 | | } +15 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +warning: technically breaking changes in ` as new::Abc>` + --> trait_impls/new.rs:11:1 + | +11 | impl Abc for Box { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Abc>` + --> trait_impls/new.rs:13:1 + | +13 | impl Abc for Box { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `<() as new::Abc>` + --> trait_impls/new.rs:15:1 + | +15 | impl Abc for () { } + | ^^^^^^^^^^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Abc>` + --> trait_impls/new.rs:17:1 + | +17 | impl Abc for Cell<(bool, T)> { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +error: aborting due to 2 previous errors; 4 warnings emitted + diff --git a/src/tools/semverver/tests/cases/trait_objects/new.rs b/src/tools/semverver/tests/cases/trait_objects/new.rs new file mode 100644 index 0000000000000..12130d827590b --- /dev/null +++ b/src/tools/semverver/tests/cases/trait_objects/new.rs @@ -0,0 +1,13 @@ +#![feature(unboxed_closures)] + +pub trait Abc { } + +pub struct Def; + +impl Abc for Def { } + +pub fn a(_: &dyn Abc) { } + +pub trait A { } + +pub type Something = dyn A<()>; diff --git a/src/tools/semverver/tests/cases/trait_objects/old.rs b/src/tools/semverver/tests/cases/trait_objects/old.rs new file mode 100644 index 0000000000000..12130d827590b --- /dev/null +++ b/src/tools/semverver/tests/cases/trait_objects/old.rs @@ -0,0 +1,13 @@ +#![feature(unboxed_closures)] + +pub trait Abc { } + +pub struct Def; + +impl Abc for Def { } + +pub fn a(_: &dyn Abc) { } + +pub trait A { } + +pub type Something = dyn A<()>; diff --git a/src/tools/semverver/tests/cases/trait_objects/stdout b/src/tools/semverver/tests/cases/trait_objects/stdout new file mode 100644 index 0000000000000..f8c2af4c949b7 --- /dev/null +++ b/src/tools/semverver/tests/cases/trait_objects/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/src/tools/semverver/tests/cases/traits/new.rs b/src/tools/semverver/tests/cases/traits/new.rs new file mode 100644 index 0000000000000..a82c7958369c7 --- /dev/null +++ b/src/tools/semverver/tests/cases/traits/new.rs @@ -0,0 +1,48 @@ +pub trait Abc { + type A; + fn test(&self) -> u8; + fn test3(&self) -> u8; + fn test4() -> u8 { + 0 + } + fn test6() -> u8 { + 0 + } + fn test7() -> u16; + fn test8(_: &Self) -> u8; + fn test9(&self) -> u8; +} + +pub trait Bcd {} + +pub trait Cde {} + +pub trait Def { + // The method is not broken - the impls are, but calls should work as expected, as + // long as a proper impl is presented. Maybe this will need some more careful handling. + fn def(&self, a: B) -> bool; +} + +pub trait Efg { + fn efg(&self, a: A) -> bool; +} + +mod fgh { + pub trait Fgh { + fn fgh(&self) -> u8; + } +} + +pub trait Ghi { } + +pub trait Hij { + type A; +} + +pub trait Klm : Clone { } + +pub trait Nop { } + +pub trait Qrs { } + +pub trait Tuv { } diff --git a/src/tools/semverver/tests/cases/traits/old.rs b/src/tools/semverver/tests/cases/traits/old.rs new file mode 100644 index 0000000000000..cf392b4aecfee --- /dev/null +++ b/src/tools/semverver/tests/cases/traits/old.rs @@ -0,0 +1,46 @@ +pub trait Abc { + type A; + fn test(&self) -> u8; + fn test2(&self) -> u8; + fn test4() -> u8 { + 0 + } + fn test5() -> u8 { + 0 + } + fn test7() -> u8; + fn test8(&self) -> u8; + fn test9(_: &Self) -> u8; +} + +pub trait Bcd {} + +pub trait Cde {} + +pub trait Def { + fn def(&self, a: A) -> bool; +} + +pub trait Efg { + fn efg(&self, a: B) -> bool; +} + +mod fgh { + pub trait Fgh { + fn fgh(&self) -> bool; + } +} + +pub trait Ghi { + type A; +} + +pub trait Hij { } + +pub trait Klm { } + +pub trait Nop : Clone { } + +pub trait Qrs { } + +pub trait Tuv { } diff --git a/src/tools/semverver/tests/cases/traits/stdout b/src/tools/semverver/tests/cases/traits/stdout new file mode 100644 index 0000000000000..864a1ac743fdc --- /dev/null +++ b/src/tools/semverver/tests/cases/traits/stdout @@ -0,0 +1,160 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +error: breaking changes in `Abc` + --> traits/new.rs:1:1 + | +1 | / pub trait Abc { +2 | | type A; +3 | | fn test(&self) -> u8; +4 | | fn test3(&self) -> u8; +... | +13 | | fn test9(&self) -> u8; +14 | | } + | |_^ + | +warning: removed item from trait (breaking) + --> traits/old.rs:4:5 + | +4 | fn test2(&self) -> u8; + | ^^^^^^^^^^^^^^^^^^^^^^ +warning: removed defaulted item from trait (breaking) + --> traits/old.rs:8:5 + | +8 | / fn test5() -> u8 { +9 | | 0 +10 | | } + | |_____^ +warning: added item to trait (breaking) + --> traits/new.rs:4:5 + | +4 | fn test3(&self) -> u8; + | ^^^^^^^^^^^^^^^^^^^^^^ +note: added defaulted item to trait (technically breaking) + --> traits/new.rs:8:5 + | +8 | / fn test6() -> u8 { +9 | | 0 +10 | | } + | |_____^ + +error: breaking changes in `test7` + --> traits/new.rs:11:5 + | +11 | fn test7() -> u16; + | ^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected `u8`, found `u16` (breaking) + +error: breaking changes in `test8` + --> traits/new.rs:12:5 + | +12 | fn test8(_: &Self) -> u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: removed self-argument from method (breaking) + +warning: technically breaking changes in `test9` + --> traits/new.rs:13:5 + | +13 | fn test9(&self) -> u8; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: added self-argument to method (technically breaking) + +error: breaking changes in `Bcd` + --> traits/new.rs:16:1 + | +16 | pub trait Bcd {} + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: type parameter added (breaking) + +error: breaking changes in `Cde` + --> traits/new.rs:18:1 + | +18 | pub trait Cde {} + | ^^^^^^^^^^^^^^^^ + | + = warning: type parameter removed (breaking) + +error: breaking changes in `Def` + --> traits/new.rs:20:1 + | +20 | / pub trait Def { +21 | | // The method is not broken - the impls are, but calls should work as expected, as +22 | | // long as a proper impl is presented. Maybe this will need some more careful handling. +23 | | fn def(&self, a: B) -> bool; +24 | | } + | |_^ + | + = warning: type parameter added (breaking) + +error: breaking changes in `Efg` + --> traits/new.rs:26:1 + | +26 | / pub trait Efg { +27 | | fn efg(&self, a: A) -> bool; +28 | | } + | |_^ + | + = warning: type parameter removed (breaking) + +error: breaking changes in `Ghi` + --> traits/new.rs:36:1 + | +36 | pub trait Ghi { } + | ^^^^^^^^^^^^^^^^^ + | +warning: removed item from trait (breaking) + --> traits/old.rs:35:5 + | +35 | type A; + | ^^^^^^^ + +error: breaking changes in `Hij` + --> traits/new.rs:38:1 + | +38 | / pub trait Hij { +39 | | type A; +40 | | } + | |_^ + | +warning: added item to trait (breaking) + --> traits/new.rs:39:5 + | +39 | type A; + | ^^^^^^^ + +error: breaking changes in `Klm` + --> traits/new.rs:42:1 + | +42 | pub trait Klm : Clone { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: added bound: `Self: std::clone::Clone` (breaking) + +error: breaking changes in `Nop` + --> traits/new.rs:44:1 + | +44 | pub trait Nop { } + | ^^^^^^^^^^^^^^^^^ + | + = warning: removed bound on trait definition: `Self: std::clone::Clone` (breaking) + +error: breaking changes in `Qrs` + --> traits/new.rs:46:1 + | +46 | pub trait Qrs { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: added bound: `A: std::clone::Clone` (breaking) + +error: breaking changes in `Tuv` + --> traits/new.rs:48:1 + | +48 | pub trait Tuv { } + | ^^^^^^^^^^^^^^^^^^^^ + | + = warning: removed bound on trait definition: `A: std::clone::Clone` (breaking) + +error: aborting due to 13 previous errors; 1 warning emitted + diff --git a/src/tools/semverver/tests/cases/ty_alias/new.rs b/src/tools/semverver/tests/cases/ty_alias/new.rs new file mode 100644 index 0000000000000..be5430c0828e2 --- /dev/null +++ b/src/tools/semverver/tests/cases/ty_alias/new.rs @@ -0,0 +1,9 @@ +#![allow(type_alias_bounds)] + +pub type A = u16; +pub type B<'a, 'b : 'a, T> = (&'a T, &'b T); +pub type C = T; +pub type D<'a, T, U=Box> = (&'a T, U); +pub type E<'a, T, U> = (&'a T, U); +pub type F<'a> = &'a u8; +pub type G<'a> = &'a u8; diff --git a/src/tools/semverver/tests/cases/ty_alias/old.rs b/src/tools/semverver/tests/cases/ty_alias/old.rs new file mode 100644 index 0000000000000..432730d792b22 --- /dev/null +++ b/src/tools/semverver/tests/cases/ty_alias/old.rs @@ -0,0 +1,9 @@ +#![allow(type_alias_bounds)] + +pub type A = u8; +pub type B<'a, T> = &'a T; +pub type C<'a, T> = &'a T; +pub type D<'a, T> = &'a T; +pub type E<'a, T> = &'a T; +pub type F<'a, U=u8> = &'a U; +pub type G<'a, T> = &'a T; diff --git a/src/tools/semverver/tests/cases/ty_alias/stdout b/src/tools/semverver/tests/cases/ty_alias/stdout new file mode 100644 index 0000000000000..6f61d37cfe281 --- /dev/null +++ b/src/tools/semverver/tests/cases/ty_alias/stdout @@ -0,0 +1,60 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +error: breaking changes in `A` + --> ty_alias/new.rs:3:1 + | +3 | pub type A = u16; + | ^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected `u8`, found `u16` (breaking) + +error: breaking changes in `B` + --> ty_alias/new.rs:4:1 + | +4 | pub type B<'a, 'b : 'a, T> = (&'a T, &'b T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: region parameter added (breaking) + +error: breaking changes in `C` + --> ty_alias/new.rs:5:1 + | +5 | pub type C = T; + | ^^^^^^^^^^^^^^^^^^ + | + = warning: region parameter removed (breaking) + +error: breaking changes in `D` + --> ty_alias/new.rs:6:1 + | +6 | pub type D<'a, T, U=Box> = (&'a T, U); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defaulted type parameter added (non-breaking) + = warning: type error: expected `&T`, found tuple (breaking) + +error: breaking changes in `E` + --> ty_alias/new.rs:7:1 + | +7 | pub type E<'a, T, U> = (&'a T, U); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type parameter added (breaking) + +error: breaking changes in `F` + --> ty_alias/new.rs:8:1 + | +8 | pub type F<'a> = &'a u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: defaulted type parameter removed (breaking) + +error: breaking changes in `G` + --> ty_alias/new.rs:9:1 + | +9 | pub type G<'a> = &'a u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type parameter removed (breaking) + +error: aborting due to 7 previous errors + diff --git a/src/tools/semverver/tests/debug.rs b/src/tools/semverver/tests/debug.rs new file mode 100644 index 0000000000000..54e7ac587353a --- /dev/null +++ b/src/tools/semverver/tests/debug.rs @@ -0,0 +1,59 @@ +use std::{env, fs::File, io::Write, path::Path}; + +#[test] +fn debug() { + if let Ok(path) = env::var("LD_LIBRARY_PATH") { + let mut dump = + File::create(Path::new("tests/debug.sh")).expect("could not create dump file"); + + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + let metadata = dump + .metadata() + .expect("could not access dump file metadata"); + let mut permissions = metadata.permissions(); + permissions.set_mode(0o755); + let _ = dump.set_permissions(permissions); + } + + let _ = writeln!( + dump, + r#"#!/usr/bin/env sh +export PATH=./target/debug:$PATH +export LD_LIBRARY_PATH={} +export RUST_BACKTRACE=full +export RUST_SEMVER_CRATE_VERSION=1.0.0 + +if [ "$1" = "-s" ]; then + shift + arg_str="set args --crate-type=lib $(cargo semver -d "$@") tests/helper/test.rs" +else + if [ "$1" != "-S" ]; then + rustc --crate-type=lib -o "$1/libold.rlib" "$1/old.rs" + rustc --crate-type=lib -o "$1/libnew.rlib" "$1/new.rs" + del=1 + else + del=0 + shift + fi + arg_str="set args --crate-type=lib --extern old=$1/libold.rlib --extern new=$1/libnew.rlib tests/helper/test.rs" +fi + +export RUST_LOG=debug + +if [ -n "$RUST_SRC_PATH" ]; then + src_str="set substitute-path /checkout $RUST_SRC_PATH" +else + src_str="set substitute-path /checkout $(rustc --print sysroot)/lib/rustlib/src/rust" +fi + +rust-gdb ./target/debug/rust-semverver -iex "$arg_str" -iex "$src_str" + +if [ $del = 1 ]; then + rm "$1/lib*.rlib" +fi"#, + path + ); + } +} diff --git a/src/tools/semverver/tests/examples.rs b/src/tools/semverver/tests/examples.rs new file mode 100644 index 0000000000000..226b6bf769e2d --- /dev/null +++ b/src/tools/semverver/tests/examples.rs @@ -0,0 +1,228 @@ +mod features { + use std::{ + env, + fs::{read_to_string, File}, + io::Write, + path::Path, + process::{Command, Stdio}, + str, + }; + + fn test_example2(name: &str, path: &Path, expected_path: &Path, expected_result: bool) { + let old_rlib = path.join("libold.rlib").to_str().unwrap().to_owned(); + let new_rlib = path.join("libnew.rlib").to_str().unwrap().to_owned(); + + let target_args = std::env::var("TEST_TARGET").map(|t| ["--target".to_string(), t]); + + let mut cmd = Command::new("rustc"); + cmd.args(&["--crate-type=lib", "-o", &old_rlib]) + .arg(path.join("old.rs")) + .env("RUST_BACKTRACE", "full") + .stdin(Stdio::null()); + + if let Ok(target_args) = &target_args { + cmd.args(target_args); + } + + let rustc_old_result = cmd.status().expect("could not run rustc on old").success(); + assert!(rustc_old_result, "couldn't compile old"); + + let mut cmd = Command::new("rustc"); + cmd.args(&["--crate-type=lib", "-o", &new_rlib]) + .arg(path.join("new.rs")) + .env("RUST_BACKTRACE", "full") + .stdin(Stdio::null()); + + if let Ok(target_args) = &target_args { + cmd.args(target_args); + } + + let rustc_new_result = cmd.status().expect("could not run rustc on new").success(); + assert!(rustc_new_result, "couldn't compile new"); + + let mut cmd = Command::new( + Path::new(".") + .join("target") + .join("debug") + .join("rust-semverver") + .to_str() + .unwrap(), + ); + cmd.args(&[ + "--crate-type=lib", + "-Zverbose", + "--extern", + &format!("old={}", old_rlib), + "--extern", + &format!("new={}", new_rlib), + Path::new("tests") + .join("helper") + .join("test.rs") + .to_str() + .unwrap(), + ]) + .env("RUST_BACKTRACE", "full") + .env("RUST_SEMVER_CRATE_VERSION", "1.0.0") + .stdin(Stdio::null()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()); + + if let Ok(target_args) = &target_args { + cmd.args(target_args); + } + + if expected_path + .to_str() + .unwrap() + .contains("stdout_api_guidelines") + { + cmd.env("RUST_SEMVER_API_GUIDELINES", "true"); + } + + let expected_output = read_to_string(&expected_path) + .expect(&format!( + "could not read expected output from file {}", + expected_path.display() + )) + .lines() + .map(|l| l.trim_end()) + .map(|l| l.to_string() + "\n") + .collect::() + .trim_end() + .to_string(); + + let output = cmd.output().expect("could not run rust-semverver"); + + let new_output = { + let stdout: &str = str::from_utf8(&output.stdout) + .expect("could not read line from rust-semverver output") + .trim_end(); + let stderr: &str = str::from_utf8(&output.stderr) + .expect("could not read line from rust-semverver output") + .trim_end(); + + stdout + .lines() + .chain(stderr.lines()) + .map(|l| l.trim_end()) + .map(|line| { + // sanitize paths for reproducibility + match line.find("-->") { + Some(idx) => { + let (start, end) = line.split_at(idx); + match end.find(name) { + Some(idx) => format!("{}--> {}", start, end.split_at(idx).1), + None => line.to_string(), + } + } + None => line.to_string(), + } + }) + .map(|l| { + if cfg!(target_os = "windows") { + l.replace('\\', "/") + } else { + l + } + }) + .map(|l| l + "\n") + .collect::() + .trim_end() + .to_string() + }; + + if expected_output != new_output { + eprintln!("rust-semverver failed to produce the expected result"); + + let new_path = Path::new(&env::var("OUT_DIR").unwrap()).join(name); + let mut new_file = File::create(&new_path).unwrap(); + new_file.write_all(new_output.as_bytes()).unwrap(); + + match std::env::var_os("CI") { + None => { + eprintln!( + "For details, try this command:\n\n diff {} {}\n\n", + expected_path.display(), + new_path.display() + ); + } + Some(_) => { + eprintln!("=== Expected output ==="); + eprintln!("{}", expected_output); + eprintln!("=== End of expected output ==="); + eprintln!("=== Actual output ==="); + eprintln!("{}", new_output); + eprintln!("=== End of actual output ==="); + } + }; + + panic!("unexpected output diff"); + } + + assert_eq!( + output.status.success(), + expected_result, + "rust-semverver returned an unexpected exit status" + ); + + Command::new("rm") + .args(&[&old_rlib, &new_rlib]) + .status() + .expect("could not run rm"); + } + + macro_rules! test { + ($name:ident => $result:literal) => { + #[test] + fn $name() { + let path = Path::new("tests").join("cases").join(stringify!($name)); + test_example2(stringify!($name), &path, &path.join("stdout"), $result); + + if path.join("stdout_api_guidelines").exists() { + eprintln!("api-guidelines"); + test_example2(stringify!($name), &path, &path.join("stdout_api_guidelines"), $result); + } + } + }; + ($($name:ident => $result:literal),*) => { + $(test!($name => $result);)* + }; + ($($name:ident => $result:literal,)*) => { + $(test!($name => $result);)* + }; + } + + test! { + addition => true, + addition_path => true, + addition_use => false, + bounds => false, + circular => true, + consts => false, + enums => false, + func => false, + func_local_items => true, + infer => true, + infer_regress => false, + inherent_impls => false, + issue_34 => true, + issue_50 => true, + kind_change => false, + macros => false, + max_priv => true, + mix => false, + pathologic_paths => true, + pub_use => true, + regions => false, + removal => false, + removal_path => false, + removal_use => false, + sealed_traits => true, + structs => false, + swap => true, + traits => false, + trait_impls => false, + trait_objects => true, + ty_alias => false, + } +} diff --git a/src/tools/semverver/tests/full.rs b/src/tools/semverver/tests/full.rs new file mode 100644 index 0000000000000..c6cf564c5faa7 --- /dev/null +++ b/src/tools/semverver/tests/full.rs @@ -0,0 +1,174 @@ +mod full { + use log::{log_enabled, Level}; + use std::{ + env, + fs::{read_to_string, File}, + io::Write, + path::{Path, PathBuf}, + process::{Command, Stdio}, + str, + }; + + fn test_full(crate_name: &str, old_version: &str, new_version: &str, expected_result: bool) { + // Add target dir to PATH so cargo-semver will call the right rust-semverver + if let Some(path) = env::var_os("PATH") { + let mut paths = env::split_paths(&path).collect::>(); + let current_dir = env::current_dir().expect("could not determine current dir"); + paths.insert(0, current_dir.join("target/debug")); + let new_path = env::join_paths(paths).unwrap(); + env::set_var("PATH", &new_path); + } else { + eprintln!("no path!"); + } + + let mut cmd = Command::new("./target/debug/cargo-semver"); + cmd.args(&[ + "-S", + &format!("{}:{}", crate_name, old_version), + "-C", + &format!("{}:{}", crate_name, new_version), + "-q", + ]) + .env("RUST_BACKTRACE", "full") + .stdin(Stdio::null()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()); + + if let Ok(target) = std::env::var("TEST_TARGET") { + cmd.args(&["--target", &target]); + } + + let output = cmd.output().expect("could not run cargo semver"); + + // Choose solution depending on the platform + let file_ext = if cfg!(target_os = "macos") { + "osx" + } else if cfg!(target_os = "linux") { + "linux" + } else if cfg!(all(target_os = "windows", target_env = "msvc")) { + "windows_msvc" + } else { + eprintln!("full tests are not available in this target"); + return; + }; + + let filename = format!( + "{}-{}-{}.{}", + crate_name, old_version, new_version, file_ext + ); + + let expected_path = { + let mut buf = PathBuf::new(); + + buf.push("tests"); + buf.push("full_cases"); + buf.push(&filename); + + buf + }; + + let expected_output = read_to_string(&expected_path) + .expect(&format!( + "could not read expected output from file {}", + expected_path.display() + )) + .lines() + .map(|l| l.trim_end()) + .map(|l| l.to_string() + "\n") + .collect::() + .trim_end() + .to_string(); + + let new_output = { + let stdout: &str = str::from_utf8(&output.stdout) + .expect("could not read line from rust-semverver output") + .trim_end(); + let stderr: &str = str::from_utf8(&output.stderr) + .expect("could not read line from rust-semverver output") + .trim_end(); + + stdout + .lines() + .chain(stderr.lines()) + .map(|l| l.trim_end()) + .skip_while(|line| + // skip everything before the first important bit of info + !line.starts_with("version bump") && + // ...unless debugging is enabled + !log_enabled!(Level::Debug)) + .map(|line| { + // sanitize paths for reproducibility + match line.find("-->") { + Some(idx) => { + let (start, end) = line.split_at(idx); + match end.find(crate_name) { + Some(idx) => format!("{}--> {}", start, end.split_at(idx).1), + None => line.to_string(), + } + } + None => line.to_string(), + } + }) + .map(|l| l + "\n") + .collect::() + .trim_end() + .to_string() + }; + + if expected_output != new_output { + eprintln!("cargo-semver failed to produce the expected output"); + + let new_path = Path::new(&env::var("OUT_DIR").unwrap()).join(filename); + let mut new_file = File::create(&new_path).unwrap(); + new_file.write_all(new_output.as_bytes()).unwrap(); + + match std::env::var_os("CI") { + None => { + eprintln!( + "For details, try this command:\n\n diff {} {}\n\n", + expected_path.display(), + new_path.display() + ); + } + Some(_) => { + eprintln!("=== Expected output ==="); + eprintln!("{}", expected_output); + eprintln!("=== End of expected output ==="); + eprintln!("=== Actual output ==="); + eprintln!("{}", new_output); + eprintln!("=== End of actual output ==="); + } + }; + + panic!("unexpected output diff"); + } + + assert_eq!( + output.status.success(), + expected_result, + "cargo-semver returned unexpected exit status {}", + output.status + ); + } + + macro_rules! full_test { + ($name:ident, $crate_name:expr, + $old_version:expr, $new_version:expr, + $result:expr) => { + #[test] + fn $name() { + test_full($crate_name, $old_version, $new_version, $result); + } + }; + } + + full_test!(log, "log", "0.3.4", "0.3.8", true); + // the libc API on windows did *not* change between these versions + full_test!(libc0, "libc", "0.2.28", "0.2.31", cfg!(windows)); + full_test!(libc1, "libc", "0.2.47", "0.2.48", true); + full_test!(rmpv, "rmpv", "0.4.0", "0.4.1", false); + // full_test!(mozjs, "mozjs", "0.2.0", "0.3.0"); + // full_test!(rand, "rand", "0.3.10", "0.3.16"); + // full_test!(serde_pre, "serde", "0.7.0", "1.0.0"); + // full_test!(serde_post, "serde", "1.0.0", "1.0.8"); +} diff --git a/src/tools/semverver/tests/full_cases/libc-0.2.28-0.2.31.linux b/src/tools/semverver/tests/full_cases/libc-0.2.28-0.2.31.linux new file mode 100644 index 0000000000000..a79756a6812f4 --- /dev/null +++ b/src/tools/semverver/tests/full_cases/libc-0.2.28-0.2.31.linux @@ -0,0 +1,870 @@ +version bump: 0.2.28 -> (breaking) -> 0.2.29 +error: path changes to `forkpty` + --> libc-0.2.28/src/unix/notbsd/mod.rs:1035:5 + | +1035 | / pub fn forkpty(amaster: *mut ::c_int, +1036 | | name: *mut ::c_char, +1037 | | termp: *const termios, +1038 | | winp: *const ::winsize) -> ::pid_t; + | |___________________________________________________^ + | +warning: removed path (breaking) + --> libc-0.2.28/src/lib.rs:275:17 + | +275 | pub use unix::*; + | ^^^^^^^ + +error: breaking changes in `PTRACE_O_EXITKILL` + --> libc-0.2.31/src/unix/notbsd/mod.rs:738:1 + | +738 | pub const PTRACE_O_EXITKILL: ::c_int = 0x00100000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected `u32`, found `i32` (breaking) + +error: breaking changes in `PTRACE_O_TRACECLONE` + --> libc-0.2.31/src/unix/notbsd/mod.rs:733:1 + | +733 | pub const PTRACE_O_TRACECLONE: ::c_int = 0x00000008; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected `u32`, found `i32` (breaking) + +error: breaking changes in `PTRACE_O_TRACEEXEC` + --> libc-0.2.31/src/unix/notbsd/mod.rs:734:1 + | +734 | pub const PTRACE_O_TRACEEXEC: ::c_int = 0x00000010; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected `u32`, found `i32` (breaking) + +error: breaking changes in `PTRACE_O_TRACEEXIT` + --> libc-0.2.31/src/unix/notbsd/mod.rs:736:1 + | +736 | pub const PTRACE_O_TRACEEXIT: ::c_int = 0x00000040; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected `u32`, found `i32` (breaking) + +error: breaking changes in `PTRACE_O_TRACEFORK` + --> libc-0.2.31/src/unix/notbsd/mod.rs:731:1 + | +731 | pub const PTRACE_O_TRACEFORK: ::c_int = 0x00000002; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected `u32`, found `i32` (breaking) + +error: breaking changes in `PTRACE_O_TRACESYSGOOD` + --> libc-0.2.31/src/unix/notbsd/mod.rs:730:1 + | +730 | pub const PTRACE_O_TRACESYSGOOD: ::c_int = 0x00000001; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected `u32`, found `i32` (breaking) + +error: breaking changes in `PTRACE_O_TRACEVFORK` + --> libc-0.2.31/src/unix/notbsd/mod.rs:732:1 + | +732 | pub const PTRACE_O_TRACEVFORK: ::c_int = 0x00000004; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected `u32`, found `i32` (breaking) + +error: breaking changes in `PTRACE_O_TRACEVFORKDONE` + --> libc-0.2.31/src/unix/notbsd/mod.rs:735:1 + | +735 | pub const PTRACE_O_TRACEVFORKDONE: ::c_int = 0x00000020; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected `u32`, found `i32` (breaking) + +error: breaking changes in `PTRACE_O_TRACESECCOMP` + --> libc-0.2.31/src/unix/notbsd/mod.rs:737:1 + | +737 | pub const PTRACE_O_TRACESECCOMP: ::c_int = 0x00000080; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected `u32`, found `i32` (breaking) + +error: breaking changes in `PTRACE_O_SUSPEND_SECCOMP` + --> libc-0.2.31/src/unix/notbsd/mod.rs:739:1 + | +739 | pub const PTRACE_O_SUSPEND_SECCOMP: ::c_int = 0x00200000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected `u32`, found `i32` (breaking) + +warning: path changes to `INADDR_LOOPBACK` + --> libc-0.2.31/src/unix/mod.rs:227:1 + | +227 | pub const INADDR_LOOPBACK: in_addr_t = 2130706433; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `INADDR_ANY` + --> libc-0.2.31/src/unix/mod.rs:228:1 + | +228 | pub const INADDR_ANY: in_addr_t = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `INADDR_BROADCAST` + --> libc-0.2.31/src/unix/mod.rs:229:1 + | +229 | pub const INADDR_BROADCAST: in_addr_t = 4294967295; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `INADDR_NONE` + --> libc-0.2.31/src/unix/mod.rs:230:1 + | +230 | pub const INADDR_NONE: in_addr_t = 4294967295; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `F_CANCELLK` + --> libc-0.2.31/src/unix/notbsd/mod.rs:214:1 + | +214 | pub const F_CANCELLK: ::c_int = 1029; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `F_ADD_SEALS` + --> libc-0.2.31/src/unix/notbsd/mod.rs:218:1 + | +218 | pub const F_ADD_SEALS: ::c_int = 1033; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `F_GET_SEALS` + --> libc-0.2.31/src/unix/notbsd/mod.rs:219:1 + | +219 | pub const F_GET_SEALS: ::c_int = 1034; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `F_SEAL_SEAL` + --> libc-0.2.31/src/unix/notbsd/mod.rs:221:1 + | +221 | pub const F_SEAL_SEAL: ::c_int = 0x0001; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `F_SEAL_SHRINK` + --> libc-0.2.31/src/unix/notbsd/mod.rs:222:1 + | +222 | pub const F_SEAL_SHRINK: ::c_int = 0x0002; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `F_SEAL_GROW` + --> libc-0.2.31/src/unix/notbsd/mod.rs:223:1 + | +223 | pub const F_SEAL_GROW: ::c_int = 0x0004; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `F_SEAL_WRITE` + --> libc-0.2.31/src/unix/notbsd/mod.rs:224:1 + | +224 | pub const F_SEAL_WRITE: ::c_int = 0x0008; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `MADV_FREE` + --> libc-0.2.31/src/unix/notbsd/mod.rs:418:1 + | +418 | pub const MADV_FREE: ::c_int = 8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `MADV_SOFT_OFFLINE` + --> libc-0.2.31/src/unix/notbsd/mod.rs:429:1 + | +429 | pub const MADV_SOFT_OFFLINE: ::c_int = 101; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `PTRACE_O_MASK` + --> libc-0.2.31/src/unix/notbsd/mod.rs:740:1 + | +740 | pub const PTRACE_O_MASK: ::c_int = 0x003000ff; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `PTRACE_EVENT_FORK` + --> libc-0.2.31/src/unix/notbsd/mod.rs:743:1 + | +743 | pub const PTRACE_EVENT_FORK: ::c_int = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `PTRACE_EVENT_VFORK` + --> libc-0.2.31/src/unix/notbsd/mod.rs:744:1 + | +744 | pub const PTRACE_EVENT_VFORK: ::c_int = 2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `PTRACE_EVENT_CLONE` + --> libc-0.2.31/src/unix/notbsd/mod.rs:745:1 + | +745 | pub const PTRACE_EVENT_CLONE: ::c_int = 3; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `PTRACE_EVENT_EXEC` + --> libc-0.2.31/src/unix/notbsd/mod.rs:746:1 + | +746 | pub const PTRACE_EVENT_EXEC: ::c_int = 4; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `PTRACE_EVENT_VFORK_DONE` + --> libc-0.2.31/src/unix/notbsd/mod.rs:747:1 + | +747 | pub const PTRACE_EVENT_VFORK_DONE: ::c_int = 5; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `PTRACE_EVENT_EXIT` + --> libc-0.2.31/src/unix/notbsd/mod.rs:748:1 + | +748 | pub const PTRACE_EVENT_EXIT: ::c_int = 6; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `PTRACE_EVENT_SECCOMP` + --> libc-0.2.31/src/unix/notbsd/mod.rs:749:1 + | +749 | pub const PTRACE_EVENT_SECCOMP: ::c_int = 7; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `statfs64` + --> libc-0.2.31/src/unix/notbsd/mod.rs:882:5 + | +882 | pub fn statfs64(path: *const ::c_char, buf: *mut statfs64) -> ::c_int; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `fstatfs64` + --> libc-0.2.31/src/unix/notbsd/mod.rs:884:5 + | +884 | pub fn fstatfs64(fd: ::c_int, buf: *mut statfs64) -> ::c_int; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `statvfs64` + --> libc-0.2.31/src/unix/notbsd/mod.rs:885:5 + | +885 | pub fn statvfs64(path: *const ::c_char, buf: *mut statvfs64) -> ::c_int; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `fstatvfs64` + --> libc-0.2.31/src/unix/notbsd/mod.rs:886:5 + | +886 | pub fn fstatvfs64(fd: ::c_int, buf: *mut statvfs64) -> ::c_int; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IFF_LOWER_UP` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:629:1 + | +629 | pub const IFF_LOWER_UP: ::c_int = 0x10000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IFF_DORMANT` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:630:1 + | +630 | pub const IFF_DORMANT: ::c_int = 0x20000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IFF_ECHO` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:631:1 + | +631 | pub const IFF_ECHO: ::c_int = 0x40000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_HOPOPTS` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:683:1 + | +683 | pub const IPPROTO_HOPOPTS: ::c_int = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_IGMP` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:686:1 + | +686 | pub const IPPROTO_IGMP: ::c_int = 2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_IPIP` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:688:1 + | +688 | pub const IPPROTO_IPIP: ::c_int = 4; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_EGP` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:691:1 + | +691 | pub const IPPROTO_EGP: ::c_int = 8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_PUP` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:693:1 + | +693 | pub const IPPROTO_PUP: ::c_int = 12; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_IDP` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:696:1 + | +696 | pub const IPPROTO_IDP: ::c_int = 22; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_TP` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:698:1 + | +698 | pub const IPPROTO_TP: ::c_int = 29; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_DCCP` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:700:1 + | +700 | pub const IPPROTO_DCCP: ::c_int = 33; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_ROUTING` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:703:1 + | +703 | pub const IPPROTO_ROUTING: ::c_int = 43; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_FRAGMENT` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:705:1 + | +705 | pub const IPPROTO_FRAGMENT: ::c_int = 44; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_RSVP` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:707:1 + | +707 | pub const IPPROTO_RSVP: ::c_int = 46; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_GRE` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:709:1 + | +709 | pub const IPPROTO_GRE: ::c_int = 47; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_ESP` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:711:1 + | +711 | pub const IPPROTO_ESP: ::c_int = 50; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_AH` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:713:1 + | +713 | pub const IPPROTO_AH: ::c_int = 51; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_NONE` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:716:1 + | +716 | pub const IPPROTO_NONE: ::c_int = 59; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_DSTOPTS` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:718:1 + | +718 | pub const IPPROTO_DSTOPTS: ::c_int = 60; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_MTP` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:719:1 + | +719 | pub const IPPROTO_MTP: ::c_int = 92; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_BEETPH` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:720:1 + | +720 | pub const IPPROTO_BEETPH: ::c_int = 94; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_ENCAP` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:722:1 + | +722 | pub const IPPROTO_ENCAP: ::c_int = 98; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_PIM` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:724:1 + | +724 | pub const IPPROTO_PIM: ::c_int = 103; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_COMP` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:726:1 + | +726 | pub const IPPROTO_COMP: ::c_int = 108; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_SCTP` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:728:1 + | +728 | pub const IPPROTO_SCTP: ::c_int = 132; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_MH` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:729:1 + | +729 | pub const IPPROTO_MH: ::c_int = 135; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_UDPLITE` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:730:1 + | +730 | pub const IPPROTO_UDPLITE: ::c_int = 136; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_MPLS` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:731:1 + | +731 | pub const IPPROTO_MPLS: ::c_int = 137; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_MAX` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:734:1 + | +734 | pub const IPPROTO_MAX: ::c_int = 256; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `TFD_CLOEXEC` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:970:1 + | +970 | pub const TFD_CLOEXEC: ::c_int = O_CLOEXEC; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `TFD_NONBLOCK` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:971:1 + | +971 | pub const TFD_NONBLOCK: ::c_int = O_NONBLOCK; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `TFD_TIMER_ABSTIME` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:972:1 + | +972 | pub const TFD_TIMER_ABSTIME: ::c_int = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `timerfd_create` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:1148:5 + | +1148 | pub fn timerfd_create(clockid: ::c_int, flags: ::c_int) -> ::c_int; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `timerfd_gettime` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:1149:5 + | +1149 | / pub fn timerfd_gettime(fd: ::c_int, +1150 | | curr_value: *mut itimerspec) -> ::c_int; + | |___________________________________________________________________^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `timerfd_settime` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:1151:5 + | +1151 | / pub fn timerfd_settime(fd: ::c_int, +1152 | | flags: ::c_int, +1153 | | new_value: *const itimerspec, +1154 | | old_value: *mut itimerspec) -> ::c_int; + | |__________________________________________________________________^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `getgrgid_r` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:1385:5 + | +1385 | / pub fn getgrgid_r(uid: ::uid_t, +1386 | | grp: *mut ::group, +1387 | | buf: *mut ::c_char, +1388 | | buflen: ::size_t, +1389 | | result: *mut *mut ::group) -> ::c_int; + | |____________________________________________________________^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `getgrnam_r` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:1398:5 + | +1398 | / pub fn getgrnam_r(name: *const ::c_char, +1399 | | grp: *mut ::group, +1400 | | buf: *mut ::c_char, +1401 | | buflen: ::size_t, +1402 | | result: *mut *mut ::group) -> ::c_int; + | |____________________________________________________________^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `getgrouplist` + --> libc-0.2.31/src/unix/notbsd/linux/mod.rs:1436:5 + | +1436 | / pub fn getgrouplist(user: *const ::c_char, +1437 | | group: ::gid_t, +1438 | | groups: *mut ::gid_t, +1439 | | ngroups: *mut ::c_int) -> ::c_int; + | |__________________________________________________________^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +error: aborting due to 11 previous errors; 63 warnings emitted + +error: rustc-semverver errored diff --git a/src/tools/semverver/tests/full_cases/libc-0.2.28-0.2.31.osx b/src/tools/semverver/tests/full_cases/libc-0.2.28-0.2.31.osx new file mode 100644 index 0000000000000..eac71b884c4f4 --- /dev/null +++ b/src/tools/semverver/tests/full_cases/libc-0.2.28-0.2.31.osx @@ -0,0 +1,2372 @@ +version bump: 0.2.28 -> (breaking) -> 0.2.29 +error: path changes to `fexecve` + --> libc-0.2.28/src/unix/mod.rs:452:5 + | +452 | / pub fn fexecve(fd: ::c_int, argv: *const *const c_char, +453 | | envp: *const *const c_char) +454 | | -> ::c_int; + | |______________________________^ + | +warning: removed path (breaking) + --> libc-0.2.28/src/lib.rs:275:17 + | +275 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `INADDR_LOOPBACK` + --> libc-0.2.31/src/unix/mod.rs:227:1 + | +227 | pub const INADDR_LOOPBACK: in_addr_t = 2130706433; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `INADDR_ANY` + --> libc-0.2.31/src/unix/mod.rs:228:1 + | +228 | pub const INADDR_ANY: in_addr_t = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `INADDR_BROADCAST` + --> libc-0.2.31/src/unix/mod.rs:229:1 + | +229 | pub const INADDR_BROADCAST: in_addr_t = 4294967295; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `INADDR_NONE` + --> libc-0.2.31/src/unix/mod.rs:230:1 + | +230 | pub const INADDR_NONE: in_addr_t = 4294967295; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `getgrgid_r` + --> libc-0.2.31/src/unix/bsd/mod.rs:463:5 + | +463 | / pub fn getgrgid_r(uid: ::uid_t, +464 | | grp: *mut ::group, +465 | | buf: *mut ::c_char, +466 | | buflen: ::size_t, +467 | | result: *mut *mut ::group) -> ::c_int; + | |____________________________________________________________^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `getgrnam_r` + --> libc-0.2.31/src/unix/bsd/mod.rs:476:5 + | +476 | / pub fn getgrnam_r(name: *const ::c_char, +477 | | grp: *mut ::group, +478 | | buf: *mut ::c_char, +479 | | buflen: ::size_t, +480 | | result: *mut *mut ::group) -> ::c_int; + | |____________________________________________________________^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_FLAGS_FIXED` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:604:1 + | +604 | pub const VM_FLAGS_FIXED: ::c_int = 0x0000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_FLAGS_ANYWHERE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:605:1 + | +605 | pub const VM_FLAGS_ANYWHERE: ::c_int = 0x0001; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_FLAGS_PURGABLE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:606:1 + | +606 | pub const VM_FLAGS_PURGABLE: ::c_int = 0x0002; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_FLAGS_RANDOM_ADDR` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:607:1 + | +607 | pub const VM_FLAGS_RANDOM_ADDR: ::c_int = 0x0008; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_FLAGS_NO_CACHE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:608:1 + | +608 | pub const VM_FLAGS_NO_CACHE: ::c_int = 0x0010; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_FLAGS_RESILIENT_CODESIGN` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:609:1 + | +609 | pub const VM_FLAGS_RESILIENT_CODESIGN: ::c_int = 0x0020; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_FLAGS_RESILIENT_MEDIA` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:610:1 + | +610 | pub const VM_FLAGS_RESILIENT_MEDIA: ::c_int = 0x0040; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_FLAGS_OVERWRITE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:611:1 + | +611 | pub const VM_FLAGS_OVERWRITE: ::c_int = 0x4000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_FLAGS_SUPERPAGE_MASK` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:612:1 + | +612 | pub const VM_FLAGS_SUPERPAGE_MASK: ::c_int = 0x70000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_FLAGS_RETURN_DATA_ADDR` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:613:1 + | +613 | pub const VM_FLAGS_RETURN_DATA_ADDR: ::c_int = 0x100000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_FLAGS_RETURN_4K_DATA_ADDR` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:614:1 + | +614 | pub const VM_FLAGS_RETURN_4K_DATA_ADDR: ::c_int = 0x800000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_FLAGS_ALIAS_MASK` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:615:1 + | +615 | pub const VM_FLAGS_ALIAS_MASK: ::c_int = 0xFF000000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_FLAGS_USER_ALLOCATE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:616:1 + | +616 | / pub const VM_FLAGS_USER_ALLOCATE: ::c_int = VM_FLAGS_FIXED | VM_FLAGS_ANYWHERE | +617 | | VM_FLAGS_PURGABLE | +618 | | VM_FLAGS_RANDOM_ADDR | +619 | | VM_FLAGS_NO_CACHE | +620 | | VM_FLAGS_OVERWRITE | +621 | | VM_FLAGS_SUPERPAGE_MASK | +622 | | VM_FLAGS_ALIAS_MASK; + | |________________________________________________________________^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_FLAGS_USER_MAP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:623:1 + | +623 | / pub const VM_FLAGS_USER_MAP: ::c_int = VM_FLAGS_USER_ALLOCATE | +624 | | VM_FLAGS_RETURN_4K_DATA_ADDR | +625 | | VM_FLAGS_RETURN_DATA_ADDR; + | |_________________________________________________________________^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_FLAGS_USER_REMAP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:626:1 + | +626 | / pub const VM_FLAGS_USER_REMAP: ::c_int = VM_FLAGS_FIXED | VM_FLAGS_ANYWHERE | +627 | | VM_FLAGS_RANDOM_ADDR | +628 | | VM_FLAGS_OVERWRITE | +629 | | VM_FLAGS_RETURN_DATA_ADDR | +630 | | VM_FLAGS_RESILIENT_CODESIGN; + | |____________________________________________________________________^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_FLAGS_SUPERPAGE_SHIFT` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:632:1 + | +632 | pub const VM_FLAGS_SUPERPAGE_SHIFT: ::c_int = 16; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `SUPERPAGE_NONE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:633:1 + | +633 | pub const SUPERPAGE_NONE: ::c_int = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `SUPERPAGE_SIZE_ANY` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:634:1 + | +634 | pub const SUPERPAGE_SIZE_ANY: ::c_int = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_FLAGS_SUPERPAGE_NONE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:635:1 + | +635 | / pub const VM_FLAGS_SUPERPAGE_NONE: ::c_int = SUPERPAGE_NONE << +636 | | VM_FLAGS_SUPERPAGE_SHIFT; + | |______________________________________________________________________^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_FLAGS_SUPERPAGE_SIZE_ANY` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:637:1 + | +637 | / pub const VM_FLAGS_SUPERPAGE_SIZE_ANY: ::c_int = SUPERPAGE_SIZE_ANY << +638 | | VM_FLAGS_SUPERPAGE_SHIFT; + | |__________________________________________________________________________^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `SUPERPAGE_SIZE_2MB` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:639:1 + | +639 | pub const SUPERPAGE_SIZE_2MB: ::c_int = 2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_FLAGS_SUPERPAGE_SIZE_2MB` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:640:1 + | +640 | / pub const VM_FLAGS_SUPERPAGE_SIZE_2MB: ::c_int = SUPERPAGE_SIZE_2MB << +641 | | VM_FLAGS_SUPERPAGE_SHIFT; + | |__________________________________________________________________________^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_MALLOC` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:643:1 + | +643 | pub const VM_MEMORY_MALLOC: ::c_int = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_MALLOC_SMALL` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:644:1 + | +644 | pub const VM_MEMORY_MALLOC_SMALL: ::c_int = 2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_MALLOC_LARGE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:645:1 + | +645 | pub const VM_MEMORY_MALLOC_LARGE: ::c_int = 3; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_MALLOC_HUGE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:646:1 + | +646 | pub const VM_MEMORY_MALLOC_HUGE: ::c_int = 4; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_SBRK` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:647:1 + | +647 | pub const VM_MEMORY_SBRK: ::c_int = 5; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_REALLOC` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:648:1 + | +648 | pub const VM_MEMORY_REALLOC: ::c_int = 6; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_MALLOC_TINY` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:649:1 + | +649 | pub const VM_MEMORY_MALLOC_TINY: ::c_int = 7; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_MALLOC_LARGE_REUSABLE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:650:1 + | +650 | pub const VM_MEMORY_MALLOC_LARGE_REUSABLE: ::c_int = 8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_MALLOC_LARGE_REUSED` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:651:1 + | +651 | pub const VM_MEMORY_MALLOC_LARGE_REUSED: ::c_int = 9; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_ANALYSIS_TOOL` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:652:1 + | +652 | pub const VM_MEMORY_ANALYSIS_TOOL: ::c_int = 10; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_MALLOC_NANO` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:653:1 + | +653 | pub const VM_MEMORY_MALLOC_NANO: ::c_int = 11; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_MACH_MSG` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:654:1 + | +654 | pub const VM_MEMORY_MACH_MSG: ::c_int = 20; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_IOKIT` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:655:1 + | +655 | pub const VM_MEMORY_IOKIT: ::c_int = 21; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_STACK` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:656:1 + | +656 | pub const VM_MEMORY_STACK: ::c_int = 30; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_GUARD` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:657:1 + | +657 | pub const VM_MEMORY_GUARD: ::c_int = 31; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_SHARED_PMAP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:658:1 + | +658 | pub const VM_MEMORY_SHARED_PMAP: ::c_int = 32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_DYLIB` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:659:1 + | +659 | pub const VM_MEMORY_DYLIB: ::c_int = 33; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_OBJC_DISPATCHERS` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:660:1 + | +660 | pub const VM_MEMORY_OBJC_DISPATCHERS: ::c_int = 34; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_UNSHARED_PMAP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:661:1 + | +661 | pub const VM_MEMORY_UNSHARED_PMAP: ::c_int = 35; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_APPKIT` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:662:1 + | +662 | pub const VM_MEMORY_APPKIT: ::c_int = 40; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_FOUNDATION` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:663:1 + | +663 | pub const VM_MEMORY_FOUNDATION: ::c_int = 41; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_COREGRAPHICS` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:664:1 + | +664 | pub const VM_MEMORY_COREGRAPHICS: ::c_int = 42; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_CORESERVICES` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:665:1 + | +665 | pub const VM_MEMORY_CORESERVICES: ::c_int = 43; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_CARBON` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:666:1 + | +666 | pub const VM_MEMORY_CARBON: ::c_int = VM_MEMORY_CORESERVICES; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_JAVA` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:667:1 + | +667 | pub const VM_MEMORY_JAVA: ::c_int = 44; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_COREDATA` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:668:1 + | +668 | pub const VM_MEMORY_COREDATA: ::c_int = 45; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_COREDATA_OBJECTIDS` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:669:1 + | +669 | pub const VM_MEMORY_COREDATA_OBJECTIDS: ::c_int = 46; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_ATS` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:670:1 + | +670 | pub const VM_MEMORY_ATS: ::c_int = 50; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_LAYERKIT` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:671:1 + | +671 | pub const VM_MEMORY_LAYERKIT: ::c_int = 51; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_CGIMAGE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:672:1 + | +672 | pub const VM_MEMORY_CGIMAGE: ::c_int = 52; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_TCMALLOC` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:673:1 + | +673 | pub const VM_MEMORY_TCMALLOC: ::c_int = 53; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_COREGRAPHICS_DATA` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:674:1 + | +674 | pub const VM_MEMORY_COREGRAPHICS_DATA: ::c_int = 54; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_COREGRAPHICS_SHARED` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:675:1 + | +675 | pub const VM_MEMORY_COREGRAPHICS_SHARED: ::c_int = 55; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_COREGRAPHICS_FRAMEBUFFERS` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:676:1 + | +676 | pub const VM_MEMORY_COREGRAPHICS_FRAMEBUFFERS: ::c_int = 56; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_COREGRAPHICS_BACKINGSTORES` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:677:1 + | +677 | pub const VM_MEMORY_COREGRAPHICS_BACKINGSTORES: ::c_int = 57; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_COREGRAPHICS_XALLOC` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:678:1 + | +678 | pub const VM_MEMORY_COREGRAPHICS_XALLOC: ::c_int = 58; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_COREGRAPHICS_MISC` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:679:1 + | +679 | pub const VM_MEMORY_COREGRAPHICS_MISC: ::c_int = VM_MEMORY_COREGRAPHICS; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_DYLD` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:680:1 + | +680 | pub const VM_MEMORY_DYLD: ::c_int = 60; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_DYLD_MALLOC` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:681:1 + | +681 | pub const VM_MEMORY_DYLD_MALLOC: ::c_int = 61; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_SQLITE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:682:1 + | +682 | pub const VM_MEMORY_SQLITE: ::c_int = 62; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_JAVASCRIPT_CORE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:683:1 + | +683 | pub const VM_MEMORY_JAVASCRIPT_CORE: ::c_int = 63; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:684:1 + | +684 | pub const VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR: ::c_int = 64; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:685:1 + | +685 | pub const VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE: ::c_int = 65; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_GLSL` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:686:1 + | +686 | pub const VM_MEMORY_GLSL: ::c_int = 66; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_OPENCL` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:687:1 + | +687 | pub const VM_MEMORY_OPENCL: ::c_int = 67; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_COREIMAGE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:688:1 + | +688 | pub const VM_MEMORY_COREIMAGE: ::c_int = 68; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:689:1 + | +689 | pub const VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS: ::c_int = 69; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_IMAGEIO` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:690:1 + | +690 | pub const VM_MEMORY_IMAGEIO: ::c_int = 70; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_COREPROFILE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:691:1 + | +691 | pub const VM_MEMORY_COREPROFILE: ::c_int = 71; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_ASSETSD` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:692:1 + | +692 | pub const VM_MEMORY_ASSETSD: ::c_int = 72; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_OS_ALLOC_ONCE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:693:1 + | +693 | pub const VM_MEMORY_OS_ALLOC_ONCE: ::c_int = 73; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_LIBDISPATCH` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:694:1 + | +694 | pub const VM_MEMORY_LIBDISPATCH: ::c_int = 74; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_ACCELERATE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:695:1 + | +695 | pub const VM_MEMORY_ACCELERATE: ::c_int = 75; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_COREUI` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:696:1 + | +696 | pub const VM_MEMORY_COREUI: ::c_int = 76; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_COREUIFILE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:697:1 + | +697 | pub const VM_MEMORY_COREUIFILE: ::c_int = 77; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_GENEALOGY` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:698:1 + | +698 | pub const VM_MEMORY_GENEALOGY: ::c_int = 78; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_RAWCAMERA` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:699:1 + | +699 | pub const VM_MEMORY_RAWCAMERA: ::c_int = 79; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_CORPSEINFO` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:700:1 + | +700 | pub const VM_MEMORY_CORPSEINFO: ::c_int = 80; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_ASL` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:701:1 + | +701 | pub const VM_MEMORY_ASL: ::c_int = 81; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_SWIFT_RUNTIME` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:702:1 + | +702 | pub const VM_MEMORY_SWIFT_RUNTIME: ::c_int = 82; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_SWIFT_METADATA` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:703:1 + | +703 | pub const VM_MEMORY_SWIFT_METADATA: ::c_int = 83; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_DHMM` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:704:1 + | +704 | pub const VM_MEMORY_DHMM: ::c_int = 84; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_SCENEKIT` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:705:1 + | +705 | pub const VM_MEMORY_SCENEKIT: ::c_int = 86; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_SKYWALK` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:706:1 + | +706 | pub const VM_MEMORY_SKYWALK: ::c_int = 87; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_APPLICATION_SPECIFIC_1` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:707:1 + | +707 | pub const VM_MEMORY_APPLICATION_SPECIFIC_1: ::c_int = 240; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `VM_MEMORY_APPLICATION_SPECIFIC_16` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:708:1 + | +708 | pub const VM_MEMORY_APPLICATION_SPECIFIC_16: ::c_int = 255; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_HOPOPTS` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1049:1 + | +1049 | pub const IPPROTO_HOPOPTS: ::c_int = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_IGMP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1052:1 + | +1052 | pub const IPPROTO_IGMP: ::c_int = 2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_GGP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1054:1 + | +1054 | pub const IPPROTO_GGP: ::c_int = 3; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_IPIP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1056:1 + | +1056 | pub const IPPROTO_IPIP: ::c_int = 4; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_ST` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1059:1 + | +1059 | pub const IPPROTO_ST: ::c_int = 7; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_EGP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1061:1 + | +1061 | pub const IPPROTO_EGP: ::c_int = 8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_PIGP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1063:1 + | +1063 | pub const IPPROTO_PIGP: ::c_int = 9; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_RCCMON` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1065:1 + | +1065 | pub const IPPROTO_RCCMON: ::c_int = 10; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_NVPII` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1067:1 + | +1067 | pub const IPPROTO_NVPII: ::c_int = 11; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_PUP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1069:1 + | +1069 | pub const IPPROTO_PUP: ::c_int = 12; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_ARGUS` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1071:1 + | +1071 | pub const IPPROTO_ARGUS: ::c_int = 13; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_EMCON` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1073:1 + | +1073 | pub const IPPROTO_EMCON: ::c_int = 14; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_XNET` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1075:1 + | +1075 | pub const IPPROTO_XNET: ::c_int = 15; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_CHAOS` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1077:1 + | +1077 | pub const IPPROTO_CHAOS: ::c_int = 16; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_MUX` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1080:1 + | +1080 | pub const IPPROTO_MUX: ::c_int = 18; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_MEAS` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1082:1 + | +1082 | pub const IPPROTO_MEAS: ::c_int = 19; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_HMP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1084:1 + | +1084 | pub const IPPROTO_HMP: ::c_int = 20; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_PRM` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1086:1 + | +1086 | pub const IPPROTO_PRM: ::c_int = 21; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_IDP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1088:1 + | +1088 | pub const IPPROTO_IDP: ::c_int = 22; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_TRUNK1` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1090:1 + | +1090 | pub const IPPROTO_TRUNK1: ::c_int = 23; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_TRUNK2` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1092:1 + | +1092 | pub const IPPROTO_TRUNK2: ::c_int = 24; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_LEAF1` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1094:1 + | +1094 | pub const IPPROTO_LEAF1: ::c_int = 25; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_LEAF2` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1096:1 + | +1096 | pub const IPPROTO_LEAF2: ::c_int = 26; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_RDP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1098:1 + | +1098 | pub const IPPROTO_RDP: ::c_int = 27; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_IRTP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1100:1 + | +1100 | pub const IPPROTO_IRTP: ::c_int = 28; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_TP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1102:1 + | +1102 | pub const IPPROTO_TP: ::c_int = 29; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_BLT` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1104:1 + | +1104 | pub const IPPROTO_BLT: ::c_int = 30; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_NSP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1106:1 + | +1106 | pub const IPPROTO_NSP: ::c_int = 31; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_INP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1108:1 + | +1108 | pub const IPPROTO_INP: ::c_int = 32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_SEP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1110:1 + | +1110 | pub const IPPROTO_SEP: ::c_int = 33; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_3PC` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1112:1 + | +1112 | pub const IPPROTO_3PC: ::c_int = 34; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_IDPR` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1114:1 + | +1114 | pub const IPPROTO_IDPR: ::c_int = 35; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_XTP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1116:1 + | +1116 | pub const IPPROTO_XTP: ::c_int = 36; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_DDP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1118:1 + | +1118 | pub const IPPROTO_DDP: ::c_int = 37; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_CMTP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1120:1 + | +1120 | pub const IPPROTO_CMTP: ::c_int = 38; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_TPXX` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1122:1 + | +1122 | pub const IPPROTO_TPXX: ::c_int = 39; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_IL` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1124:1 + | +1124 | pub const IPPROTO_IL: ::c_int = 40; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_SDRP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1127:1 + | +1127 | pub const IPPROTO_SDRP: ::c_int = 42; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_ROUTING` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1129:1 + | +1129 | pub const IPPROTO_ROUTING: ::c_int = 43; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_FRAGMENT` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1131:1 + | +1131 | pub const IPPROTO_FRAGMENT: ::c_int = 44; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_IDRP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1133:1 + | +1133 | pub const IPPROTO_IDRP: ::c_int = 45; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_RSVP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1135:1 + | +1135 | pub const IPPROTO_RSVP: ::c_int = 46; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_GRE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1137:1 + | +1137 | pub const IPPROTO_GRE: ::c_int = 47; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_MHRP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1139:1 + | +1139 | pub const IPPROTO_MHRP: ::c_int = 48; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_BHA` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1141:1 + | +1141 | pub const IPPROTO_BHA: ::c_int = 49; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_ESP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1143:1 + | +1143 | pub const IPPROTO_ESP: ::c_int = 50; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_AH` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1145:1 + | +1145 | pub const IPPROTO_AH: ::c_int = 51; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_INLSP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1147:1 + | +1147 | pub const IPPROTO_INLSP: ::c_int = 52; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_SWIPE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1149:1 + | +1149 | pub const IPPROTO_SWIPE: ::c_int = 53; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_NHRP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1151:1 + | +1151 | pub const IPPROTO_NHRP: ::c_int = 54; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_NONE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1155:1 + | +1155 | pub const IPPROTO_NONE: ::c_int = 59; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_DSTOPTS` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1157:1 + | +1157 | pub const IPPROTO_DSTOPTS: ::c_int = 60; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_AHIP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1159:1 + | +1159 | pub const IPPROTO_AHIP: ::c_int = 61; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_CFTP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1161:1 + | +1161 | pub const IPPROTO_CFTP: ::c_int = 62; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_HELLO` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1163:1 + | +1163 | pub const IPPROTO_HELLO: ::c_int = 63; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_SATEXPAK` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1165:1 + | +1165 | pub const IPPROTO_SATEXPAK: ::c_int = 64; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_KRYPTOLAN` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1167:1 + | +1167 | pub const IPPROTO_KRYPTOLAN: ::c_int = 65; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_RVD` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1169:1 + | +1169 | pub const IPPROTO_RVD: ::c_int = 66; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_IPPC` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1171:1 + | +1171 | pub const IPPROTO_IPPC: ::c_int = 67; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_ADFS` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1173:1 + | +1173 | pub const IPPROTO_ADFS: ::c_int = 68; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_SATMON` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1175:1 + | +1175 | pub const IPPROTO_SATMON: ::c_int = 69; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_VISA` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1177:1 + | +1177 | pub const IPPROTO_VISA: ::c_int = 70; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_IPCV` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1179:1 + | +1179 | pub const IPPROTO_IPCV: ::c_int = 71; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_CPNX` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1181:1 + | +1181 | pub const IPPROTO_CPNX: ::c_int = 72; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_CPHB` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1183:1 + | +1183 | pub const IPPROTO_CPHB: ::c_int = 73; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_WSN` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1185:1 + | +1185 | pub const IPPROTO_WSN: ::c_int = 74; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_PVP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1187:1 + | +1187 | pub const IPPROTO_PVP: ::c_int = 75; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_BRSATMON` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1189:1 + | +1189 | pub const IPPROTO_BRSATMON: ::c_int = 76; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_ND` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1191:1 + | +1191 | pub const IPPROTO_ND: ::c_int = 77; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_WBMON` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1193:1 + | +1193 | pub const IPPROTO_WBMON: ::c_int = 78; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_WBEXPAK` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1195:1 + | +1195 | pub const IPPROTO_WBEXPAK: ::c_int = 79; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_EON` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1197:1 + | +1197 | pub const IPPROTO_EON: ::c_int = 80; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_VMTP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1199:1 + | +1199 | pub const IPPROTO_VMTP: ::c_int = 81; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_SVMTP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1201:1 + | +1201 | pub const IPPROTO_SVMTP: ::c_int = 82; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_VINES` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1203:1 + | +1203 | pub const IPPROTO_VINES: ::c_int = 83; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_TTP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1205:1 + | +1205 | pub const IPPROTO_TTP: ::c_int = 84; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_IGP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1207:1 + | +1207 | pub const IPPROTO_IGP: ::c_int = 85; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_DGP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1209:1 + | +1209 | pub const IPPROTO_DGP: ::c_int = 86; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_TCF` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1211:1 + | +1211 | pub const IPPROTO_TCF: ::c_int = 87; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_IGRP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1213:1 + | +1213 | pub const IPPROTO_IGRP: ::c_int = 88; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_OSPFIGP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1215:1 + | +1215 | pub const IPPROTO_OSPFIGP: ::c_int = 89; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_SRPC` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1217:1 + | +1217 | pub const IPPROTO_SRPC: ::c_int = 90; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_LARP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1219:1 + | +1219 | pub const IPPROTO_LARP: ::c_int = 91; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_MTP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1221:1 + | +1221 | pub const IPPROTO_MTP: ::c_int = 92; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_AX25` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1223:1 + | +1223 | pub const IPPROTO_AX25: ::c_int = 93; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_IPEIP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1225:1 + | +1225 | pub const IPPROTO_IPEIP: ::c_int = 94; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_MICP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1227:1 + | +1227 | pub const IPPROTO_MICP: ::c_int = 95; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_SCCSP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1229:1 + | +1229 | pub const IPPROTO_SCCSP: ::c_int = 96; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_ETHERIP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1231:1 + | +1231 | pub const IPPROTO_ETHERIP: ::c_int = 97; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_ENCAP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1233:1 + | +1233 | pub const IPPROTO_ENCAP: ::c_int = 98; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_APES` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1235:1 + | +1235 | pub const IPPROTO_APES: ::c_int = 99; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_GMTP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1237:1 + | +1237 | pub const IPPROTO_GMTP: ::c_int = 100; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_PIM` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1241:1 + | +1241 | pub const IPPROTO_PIM: ::c_int = 103; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_IPCOMP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1243:1 + | +1243 | pub const IPPROTO_IPCOMP: ::c_int = 108; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_PGM` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1245:1 + | +1245 | pub const IPPROTO_PGM: ::c_int = 113; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_SCTP` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1247:1 + | +1247 | pub const IPPROTO_SCTP: ::c_int = 132; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_DIVERT` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1252:1 + | +1252 | pub const IPPROTO_DIVERT: ::c_int = 254; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_MAX` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1255:1 + | +1255 | pub const IPPROTO_MAX: ::c_int = 256; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `IPPROTO_DONE` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:1257:1 + | +1257 | pub const IPPROTO_DONE: ::c_int = 257; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +warning: path changes to `getgrouplist` + --> libc-0.2.31/src/unix/bsd/apple/mod.rs:2122:5 + | +2122 | / pub fn getgrouplist(name: *const ::c_char, +2123 | | basegid: ::c_int, +2124 | | groups: *mut ::c_int, +2125 | | ngroups: *mut ::c_int) -> ::c_int; + | |__________________________________________________________^ + | +note: added path (technically breaking) + --> libc-0.2.31/src/lib.rs:284:17 + | +284 | pub use unix::*; + | ^^^^^^^ + +error: aborting due to previous error; 194 warnings emitted + +error: rustc-semverver errored diff --git a/src/tools/semverver/tests/full_cases/libc-0.2.28-0.2.31.windows_msvc b/src/tools/semverver/tests/full_cases/libc-0.2.28-0.2.31.windows_msvc new file mode 100644 index 0000000000000..d4b8e6342fa42 --- /dev/null +++ b/src/tools/semverver/tests/full_cases/libc-0.2.28-0.2.31.windows_msvc @@ -0,0 +1 @@ +version bump: 0.2.28 -> (patch) -> 0.2.29 \ No newline at end of file diff --git a/src/tools/semverver/tests/full_cases/libc-0.2.47-0.2.48.linux b/src/tools/semverver/tests/full_cases/libc-0.2.47-0.2.48.linux new file mode 100644 index 0000000000000..0588e9104e1c2 --- /dev/null +++ b/src/tools/semverver/tests/full_cases/libc-0.2.47-0.2.48.linux @@ -0,0 +1 @@ +version bump: 0.2.47 -> (patch) -> 0.2.48 diff --git a/src/tools/semverver/tests/full_cases/libc-0.2.47-0.2.48.osx b/src/tools/semverver/tests/full_cases/libc-0.2.47-0.2.48.osx new file mode 100644 index 0000000000000..0588e9104e1c2 --- /dev/null +++ b/src/tools/semverver/tests/full_cases/libc-0.2.47-0.2.48.osx @@ -0,0 +1 @@ +version bump: 0.2.47 -> (patch) -> 0.2.48 diff --git a/src/tools/semverver/tests/full_cases/libc-0.2.47-0.2.48.windows_msvc b/src/tools/semverver/tests/full_cases/libc-0.2.47-0.2.48.windows_msvc new file mode 100644 index 0000000000000..0588e9104e1c2 --- /dev/null +++ b/src/tools/semverver/tests/full_cases/libc-0.2.47-0.2.48.windows_msvc @@ -0,0 +1 @@ +version bump: 0.2.47 -> (patch) -> 0.2.48 diff --git a/src/tools/semverver/tests/full_cases/log-0.3.4-0.3.8.linux b/src/tools/semverver/tests/full_cases/log-0.3.4-0.3.8.linux new file mode 100644 index 0000000000000..e77b51cc8b98d --- /dev/null +++ b/src/tools/semverver/tests/full_cases/log-0.3.4-0.3.8.linux @@ -0,0 +1,161 @@ +version bump: 0.3.4 -> (technically breaking) -> 0.3.5 +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:266:27 + | +266 | #[derive(Copy, Eq, Debug, Hash)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:410:27 + | +410 | #[derive(Copy, Eq, Debug, Hash)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> log-0.3.8/src/lib.rs:517:10 + | +517 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::marker::StructuralEq>` + --> log-0.3.8/src/lib.rs:552:10 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::marker::StructuralPartialEq>` + --> log-0.3.8/src/lib.rs:552:14 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::Ord>` + --> log-0.3.8/src/lib.rs:552:25 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::PartialOrd>` + --> log-0.3.8/src/lib.rs:552:30 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::hash::Hash>` + --> log-0.3.8/src/lib.rs:552:42 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> log-0.3.8/src/lib.rs:552:48 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:30 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:34 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:45 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:50 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:62 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: path changes to `set_logger_raw` + --> log-0.3.8/src/lib.rs:713:1 + | +713 | / pub unsafe fn set_logger_raw(make_logger: M) -> Result<(), SetLoggerError> +714 | | where M: FnOnce(MaxLogLevelFilter) -> *const Log { +715 | | if STATE.compare_and_swap(UNINITIALIZED, INITIALIZING, +716 | | Ordering::SeqCst) != UNINITIALIZED { +... | +722 | | Ok(()) +723 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `shutdown_logger` + --> log-0.3.8/src/lib.rs:736:1 + | +736 | / pub fn shutdown_logger() -> Result, ShutdownLoggerError> { +737 | | shutdown_logger_raw().map(|l| unsafe { mem::transmute(l) }) +738 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `shutdown_logger_raw` + --> log-0.3.8/src/lib.rs:754:1 + | +754 | / pub fn shutdown_logger_raw() -> Result<*const Log, ShutdownLoggerError> { +755 | | // Set the global log level to stop other thread from logging +756 | | MAX_LOG_LEVEL_FILTER.store(0, Ordering::SeqCst); +757 | | +... | +772 | | } +773 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `ShutdownLoggerError` + --> log-0.3.8/src/lib.rs:797:1 + | +797 | pub struct ShutdownLoggerError(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + +warning: 18 warnings emitted + diff --git a/src/tools/semverver/tests/full_cases/log-0.3.4-0.3.8.osx b/src/tools/semverver/tests/full_cases/log-0.3.4-0.3.8.osx new file mode 100644 index 0000000000000..e77b51cc8b98d --- /dev/null +++ b/src/tools/semverver/tests/full_cases/log-0.3.4-0.3.8.osx @@ -0,0 +1,161 @@ +version bump: 0.3.4 -> (technically breaking) -> 0.3.5 +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:266:27 + | +266 | #[derive(Copy, Eq, Debug, Hash)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:410:27 + | +410 | #[derive(Copy, Eq, Debug, Hash)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> log-0.3.8/src/lib.rs:517:10 + | +517 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::marker::StructuralEq>` + --> log-0.3.8/src/lib.rs:552:10 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::marker::StructuralPartialEq>` + --> log-0.3.8/src/lib.rs:552:14 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::Ord>` + --> log-0.3.8/src/lib.rs:552:25 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::PartialOrd>` + --> log-0.3.8/src/lib.rs:552:30 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::hash::Hash>` + --> log-0.3.8/src/lib.rs:552:42 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> log-0.3.8/src/lib.rs:552:48 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:30 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:34 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:45 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:50 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:62 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: path changes to `set_logger_raw` + --> log-0.3.8/src/lib.rs:713:1 + | +713 | / pub unsafe fn set_logger_raw(make_logger: M) -> Result<(), SetLoggerError> +714 | | where M: FnOnce(MaxLogLevelFilter) -> *const Log { +715 | | if STATE.compare_and_swap(UNINITIALIZED, INITIALIZING, +716 | | Ordering::SeqCst) != UNINITIALIZED { +... | +722 | | Ok(()) +723 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `shutdown_logger` + --> log-0.3.8/src/lib.rs:736:1 + | +736 | / pub fn shutdown_logger() -> Result, ShutdownLoggerError> { +737 | | shutdown_logger_raw().map(|l| unsafe { mem::transmute(l) }) +738 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `shutdown_logger_raw` + --> log-0.3.8/src/lib.rs:754:1 + | +754 | / pub fn shutdown_logger_raw() -> Result<*const Log, ShutdownLoggerError> { +755 | | // Set the global log level to stop other thread from logging +756 | | MAX_LOG_LEVEL_FILTER.store(0, Ordering::SeqCst); +757 | | +... | +772 | | } +773 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `ShutdownLoggerError` + --> log-0.3.8/src/lib.rs:797:1 + | +797 | pub struct ShutdownLoggerError(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + +warning: 18 warnings emitted + diff --git a/src/tools/semverver/tests/full_cases/log-0.3.4-0.3.8.windows_msvc b/src/tools/semverver/tests/full_cases/log-0.3.4-0.3.8.windows_msvc new file mode 100644 index 0000000000000..ecd8f1c4bf6e7 --- /dev/null +++ b/src/tools/semverver/tests/full_cases/log-0.3.4-0.3.8.windows_msvc @@ -0,0 +1,161 @@ +version bump: 0.3.4 -> (technically breaking) -> 0.3.5 +warning: technically breaking changes in `` + --> log-0.3.8\src\lib.rs:266:27 + | +266 | #[derive(Copy, Eq, Debug, Hash)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8\src\lib.rs:410:27 + | +410 | #[derive(Copy, Eq, Debug, Hash)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> log-0.3.8\src\lib.rs:517:10 + | +517 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::marker::StructuralEq>` + --> log-0.3.8\src\lib.rs:552:10 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::marker::StructuralPartialEq>` + --> log-0.3.8\src\lib.rs:552:14 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::Ord>` + --> log-0.3.8\src\lib.rs:552:25 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::PartialOrd>` + --> log-0.3.8\src\lib.rs:552:30 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::hash::Hash>` + --> log-0.3.8\src\lib.rs:552:42 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> log-0.3.8\src\lib.rs:552:48 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8\src\lib.rs:604:30 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8\src\lib.rs:604:34 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8\src\lib.rs:604:45 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8\src\lib.rs:604:50 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8\src\lib.rs:604:62 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: path changes to `set_logger_raw` + --> log-0.3.8\src\lib.rs:713:1 + | +713 | / pub unsafe fn set_logger_raw(make_logger: M) -> Result<(), SetLoggerError> +714 | | where M: FnOnce(MaxLogLevelFilter) -> *const Log { +715 | | if STATE.compare_and_swap(UNINITIALIZED, INITIALIZING, +716 | | Ordering::SeqCst) != UNINITIALIZED { +... | +722 | | Ok(()) +723 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `shutdown_logger` + --> log-0.3.8\src\lib.rs:736:1 + | +736 | / pub fn shutdown_logger() -> Result, ShutdownLoggerError> { +737 | | shutdown_logger_raw().map(|l| unsafe { mem::transmute(l) }) +738 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `shutdown_logger_raw` + --> log-0.3.8\src\lib.rs:754:1 + | +754 | / pub fn shutdown_logger_raw() -> Result<*const Log, ShutdownLoggerError> { +755 | | // Set the global log level to stop other thread from logging +756 | | MAX_LOG_LEVEL_FILTER.store(0, Ordering::SeqCst); +757 | | +... | +772 | | } +773 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `ShutdownLoggerError` + --> log-0.3.8\src\lib.rs:797:1 + | +797 | pub struct ShutdownLoggerError(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + +warning: 18 warnings emitted + diff --git a/src/tools/semverver/tests/full_cases/rand-0.3.10-0.3.16 b/src/tools/semverver/tests/full_cases/rand-0.3.10-0.3.16 new file mode 100644 index 0000000000000..7c0633c785842 --- /dev/null +++ b/src/tools/semverver/tests/full_cases/rand-0.3.10-0.3.16 @@ -0,0 +1,316 @@ +version bump: 0.3.10 -> (technically breaking) -> 0.4.0 +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/lib.rs:647:10 + | +647 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/lib.rs:667:10 + | +667 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/lib.rs:727:17 + | +727 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/lib.rs:817:10 + | +817 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/lib.rs:835:10 + | +835 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/lib.rs:840:23 + | +840 | #[derive(Copy, Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/lib.rs:903:10 + | +903 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/lib.rs:918:17 + | +918 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/distributions/mod.rs:56:10 + | +56 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/distributions/mod.rs:83:23 + | +83 | #[derive(Copy, Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/distributions/mod.rs:116:10 + | +116 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/distributions/range.rs:49:23 + | +49 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:52:23 + | +52 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:57:23 + | +57 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:78:23 + | +78 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:88:23 + | +88 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:200:23 + | +200 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:205:23 + | +205 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:258:23 + | +258 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:302:23 + | +302 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/normal.rs:36:23 + | +36 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/normal.rs:91:23 + | +91 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/normal.rs:139:23 + | +139 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/exponential.rs:37:23 + | +37 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/exponential.rs:74:23 + | +74 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/isaac.rs:264:1 + | +264 | / impl fmt::Debug for IsaacRng { +265 | | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +266 | | write!(f, "IsaacRng {{}}") +267 | | } +268 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/isaac.rs:513:1 + | +513 | / impl fmt::Debug for Isaac64Rng { +514 | | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +515 | | write!(f, "Isaac64Rng {{}}") +516 | | } +517 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/chacha.rs:29:23 + | +29 | #[derive(Copy, Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/reseeding.rs:24:10 + | +24 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/reseeding.rs:136:23 + | +136 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::rand_impls::` + --> rand_impls.rs:223:9 + | +223 | / impl Rand for [T; $n] where T: Rand { +224 | | #[inline] +225 | | fn rand(_rng: &mut R) -> [T; $n] { +226 | | [_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*] +227 | | } +228 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::rand_impls::` + --> rand_impls.rs:231:9 + | +231 | / impl Rand for [T; $n] { +232 | | fn rand(_rng: &mut R) -> [T; $n] { [] } +233 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/os.rs:50:1 + | +50 | / impl fmt::Debug for OsRng { +51 | | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +52 | | write!(f, "OsRng {{}}") +53 | | } +54 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/read.rs:33:10 + | +33 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `Rng` + --> rand-0.3.16/src/lib.rs:324:1 + | +324 | / pub trait Rng { +325 | | /// Return the next random u32. +326 | | /// +327 | | /// This rarely needs to be called directly, prefer `r.gen()` to +... | +594 | | } +595 | | } + | |_^ + | +note: added defaulted item to trait (technically breaking) + --> rand-0.3.16/src/lib.rs:560:5 + | +560 | / fn choose_mut<'a, T>(&mut self, values: &'a mut [T]) -> Option<&'a mut T> where Self: Sized { +561 | | if values.is_empty() { +562 | | None +563 | | } else { +... | +566 | | } +567 | | } + | |_____^ + diff --git a/src/tools/semverver/tests/full_cases/rmpv-0.4.0-0.4.1.linux b/src/tools/semverver/tests/full_cases/rmpv-0.4.0-0.4.1.linux new file mode 100644 index 0000000000000..92383e1215909 --- /dev/null +++ b/src/tools/semverver/tests/full_cases/rmpv-0.4.0-0.4.1.linux @@ -0,0 +1,111 @@ +version bump: 0.4.0 -> (breaking) -> 0.4.1 +error: breaking changes in `>` + --> rmpv-0.4.0/src/decode/mod.rs:60:1 + | +60 | / impl From for Error { +61 | | fn from(err: MarkerReadError) -> Error { +62 | | Error::InvalidMarkerRead(err.0) +63 | | } +64 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `>` + --> rmpv-0.4.0/src/decode/mod.rs:66:1 + | +66 | / impl From for Error { +67 | | fn from(err: ValueReadError) -> Error { +68 | | match err { +69 | | ValueReadError::InvalidMarkerRead(err) => Error::InvalidMarkerRead(err), +... | +75 | | } +76 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `write_value` + --> rmpv-0.4.1/src/encode/value.rs:15:1 + | +15 | / pub fn write_value(wr: &mut W, val: &Value) -> Result<(), Error> +16 | | where W: Write +17 | | { +18 | | match *val { +... | +69 | | Ok(()) +70 | | } + | |_^ + | + = warning: type error: expected enum `old::encode::Error`, found enum `new::encode::Error` (breaking) + +error: breaking changes in `write_value_ref` + --> rmpv-0.4.1/src/encode/value_ref.rs:27:1 + | +27 | / pub fn write_value_ref(wr: &mut W, val: &ValueRef) -> Result<(), Error> +28 | | where W: Write +29 | | { +30 | | match *val { +... | +81 | | Ok(()) +82 | | } + | |_^ + | + = warning: type error: expected enum `old::encode::Error`, found enum `new::encode::Error` (breaking) + +warning: technically breaking changes in `as_ref` + --> rmpv-0.4.1/src/lib.rs:253:5 + | +253 | / pub fn as_ref(&self) -> Utf8StringRef { +254 | | match self.s { +255 | | Ok(ref s) => Utf8StringRef { s: Ok(s.as_str()) }, +256 | | Err((ref buf, err)) => Utf8StringRef { s: Err((&buf[..], err)) }, +257 | | } +258 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in `as_ref` + --> rmpv-0.4.1/src/lib.rs:448:5 + | +448 | / pub fn as_ref(&self) -> ValueRef { +449 | | match self { +450 | | &Value::Nil => ValueRef::Nil, +451 | | &Value::Boolean(val) => ValueRef::Boolean(val), +... | +464 | | } +465 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in `>` + --> rmpv-0.4.1/src/decode/mod.rs:60:1 + | +60 | / impl From for Error { +61 | | fn from(err: MarkerReadError) -> Error { +62 | | Error::InvalidMarkerRead(err.0) +63 | | } +64 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> rmpv-0.4.1/src/decode/mod.rs:66:1 + | +66 | / impl From for Error { +67 | | fn from(err: ValueReadError) -> Error { +68 | | match err { +69 | | ValueReadError::InvalidMarkerRead(err) => Error::InvalidMarkerRead(err), +... | +75 | | } +76 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +error: aborting due to 4 previous errors; 4 warnings emitted + +error: rustc-semverver errored diff --git a/src/tools/semverver/tests/full_cases/rmpv-0.4.0-0.4.1.osx b/src/tools/semverver/tests/full_cases/rmpv-0.4.0-0.4.1.osx new file mode 100644 index 0000000000000..92383e1215909 --- /dev/null +++ b/src/tools/semverver/tests/full_cases/rmpv-0.4.0-0.4.1.osx @@ -0,0 +1,111 @@ +version bump: 0.4.0 -> (breaking) -> 0.4.1 +error: breaking changes in `>` + --> rmpv-0.4.0/src/decode/mod.rs:60:1 + | +60 | / impl From for Error { +61 | | fn from(err: MarkerReadError) -> Error { +62 | | Error::InvalidMarkerRead(err.0) +63 | | } +64 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `>` + --> rmpv-0.4.0/src/decode/mod.rs:66:1 + | +66 | / impl From for Error { +67 | | fn from(err: ValueReadError) -> Error { +68 | | match err { +69 | | ValueReadError::InvalidMarkerRead(err) => Error::InvalidMarkerRead(err), +... | +75 | | } +76 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `write_value` + --> rmpv-0.4.1/src/encode/value.rs:15:1 + | +15 | / pub fn write_value(wr: &mut W, val: &Value) -> Result<(), Error> +16 | | where W: Write +17 | | { +18 | | match *val { +... | +69 | | Ok(()) +70 | | } + | |_^ + | + = warning: type error: expected enum `old::encode::Error`, found enum `new::encode::Error` (breaking) + +error: breaking changes in `write_value_ref` + --> rmpv-0.4.1/src/encode/value_ref.rs:27:1 + | +27 | / pub fn write_value_ref(wr: &mut W, val: &ValueRef) -> Result<(), Error> +28 | | where W: Write +29 | | { +30 | | match *val { +... | +81 | | Ok(()) +82 | | } + | |_^ + | + = warning: type error: expected enum `old::encode::Error`, found enum `new::encode::Error` (breaking) + +warning: technically breaking changes in `as_ref` + --> rmpv-0.4.1/src/lib.rs:253:5 + | +253 | / pub fn as_ref(&self) -> Utf8StringRef { +254 | | match self.s { +255 | | Ok(ref s) => Utf8StringRef { s: Ok(s.as_str()) }, +256 | | Err((ref buf, err)) => Utf8StringRef { s: Err((&buf[..], err)) }, +257 | | } +258 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in `as_ref` + --> rmpv-0.4.1/src/lib.rs:448:5 + | +448 | / pub fn as_ref(&self) -> ValueRef { +449 | | match self { +450 | | &Value::Nil => ValueRef::Nil, +451 | | &Value::Boolean(val) => ValueRef::Boolean(val), +... | +464 | | } +465 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in `>` + --> rmpv-0.4.1/src/decode/mod.rs:60:1 + | +60 | / impl From for Error { +61 | | fn from(err: MarkerReadError) -> Error { +62 | | Error::InvalidMarkerRead(err.0) +63 | | } +64 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> rmpv-0.4.1/src/decode/mod.rs:66:1 + | +66 | / impl From for Error { +67 | | fn from(err: ValueReadError) -> Error { +68 | | match err { +69 | | ValueReadError::InvalidMarkerRead(err) => Error::InvalidMarkerRead(err), +... | +75 | | } +76 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +error: aborting due to 4 previous errors; 4 warnings emitted + +error: rustc-semverver errored diff --git a/src/tools/semverver/tests/full_cases/rmpv-0.4.0-0.4.1.windows_msvc b/src/tools/semverver/tests/full_cases/rmpv-0.4.0-0.4.1.windows_msvc new file mode 100644 index 0000000000000..6164e8b4e0e4e --- /dev/null +++ b/src/tools/semverver/tests/full_cases/rmpv-0.4.0-0.4.1.windows_msvc @@ -0,0 +1,111 @@ +version bump: 0.4.0 -> (breaking) -> 0.4.1 +error: breaking changes in `>` + --> rmpv-0.4.0\src\decode\mod.rs:60:1 + | +60 | / impl From for Error { +61 | | fn from(err: MarkerReadError) -> Error { +62 | | Error::InvalidMarkerRead(err.0) +63 | | } +64 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `>` + --> rmpv-0.4.0\src\decode\mod.rs:66:1 + | +66 | / impl From for Error { +67 | | fn from(err: ValueReadError) -> Error { +68 | | match err { +69 | | ValueReadError::InvalidMarkerRead(err) => Error::InvalidMarkerRead(err), +... | +75 | | } +76 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `write_value` + --> rmpv-0.4.1\src\encode\value.rs:15:1 + | +15 | / pub fn write_value(wr: &mut W, val: &Value) -> Result<(), Error> +16 | | where W: Write +17 | | { +18 | | match *val { +... | +69 | | Ok(()) +70 | | } + | |_^ + | + = warning: type error: expected enum `old::encode::Error`, found enum `new::encode::Error` (breaking) + +error: breaking changes in `write_value_ref` + --> rmpv-0.4.1\src\encode\value_ref.rs:27:1 + | +27 | / pub fn write_value_ref(wr: &mut W, val: &ValueRef) -> Result<(), Error> +28 | | where W: Write +29 | | { +30 | | match *val { +... | +81 | | Ok(()) +82 | | } + | |_^ + | + = warning: type error: expected enum `old::encode::Error`, found enum `new::encode::Error` (breaking) + +warning: technically breaking changes in `as_ref` + --> rmpv-0.4.1\src\lib.rs:253:5 + | +253 | / pub fn as_ref(&self) -> Utf8StringRef { +254 | | match self.s { +255 | | Ok(ref s) => Utf8StringRef { s: Ok(s.as_str()) }, +256 | | Err((ref buf, err)) => Utf8StringRef { s: Err((&buf[..], err)) }, +257 | | } +258 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in `as_ref` + --> rmpv-0.4.1\src\lib.rs:448:5 + | +448 | / pub fn as_ref(&self) -> ValueRef { +449 | | match self { +450 | | &Value::Nil => ValueRef::Nil, +451 | | &Value::Boolean(val) => ValueRef::Boolean(val), +... | +464 | | } +465 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in `>` + --> rmpv-0.4.1\src\decode\mod.rs:60:1 + | +60 | / impl From for Error { +61 | | fn from(err: MarkerReadError) -> Error { +62 | | Error::InvalidMarkerRead(err.0) +63 | | } +64 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> rmpv-0.4.1\src\decode\mod.rs:66:1 + | +66 | / impl From for Error { +67 | | fn from(err: ValueReadError) -> Error { +68 | | match err { +69 | | ValueReadError::InvalidMarkerRead(err) => Error::InvalidMarkerRead(err), +... | +75 | | } +76 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +error: aborting due to 4 previous errors; 4 warnings emitted + +error: rustc-semverver errored diff --git a/src/tools/semverver/tests/full_cases/serde-0.7.0-1.0.0 b/src/tools/semverver/tests/full_cases/serde-0.7.0-1.0.0 new file mode 100644 index 0000000000000..5ed8205391387 --- /dev/null +++ b/src/tools/semverver/tests/full_cases/serde-0.7.0-1.0.0 @@ -0,0 +1,4122 @@ +version bump: 0.7.0 -> (breaking) -> 1.0.0 +warning: path changes to `forward_to_deserialize_any` + --> serde-1.0.0/src/macros.rs:128:1 + | +128 | / macro_rules! forward_to_deserialize_any { +129 | | (<$visitor:ident: Visitor<$lifetime:tt>> $($func:ident)*) => { +130 | | $(forward_to_deserialize_any_helper!{$func<$lifetime, $visitor>})* +131 | | }; +... | +135 | | }; +136 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `forward_to_deserialize_any_method` + --> serde-1.0.0/src/macros.rs:140:1 + | +140 | / macro_rules! forward_to_deserialize_any_method { +141 | | ($func:ident<$l:tt, $v:ident>($($arg:ident : $ty:ty),*)) => { +142 | | #[inline] +143 | | fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::export::Result<$v::Value, Self::Error> +... | +152 | | }; +153 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `forward_to_deserialize_any_helper` + --> serde-1.0.0/src/macros.rs:157:1 + | +157 | / macro_rules! forward_to_deserialize_any_helper { +158 | | (bool<$l:tt, $v:ident>) => { +159 | | forward_to_deserialize_any_method!{deserialize_bool<$l, $v>()} +160 | | }; +... | +241 | | }; +242 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `SerializeSeq` + --> serde-1.0.0/src/ser/mod.rs:1404:1 + | +1404 | / pub trait SerializeSeq { +1405 | | /// Must match the `Ok` type of our `Serializer`. +1406 | | type Ok; +1407 | | +... | +1417 | | fn end(self) -> Result; +1418 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `SerializeTuple` + --> serde-1.0.0/src/ser/mod.rs:1491:1 + | +1491 | / pub trait SerializeTuple { +1492 | | /// Must match the `Ok` type of our `Serializer`. +1493 | | type Ok; +1494 | | +... | +1504 | | fn end(self) -> Result; +1505 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `SerializeTupleStruct` + --> serde-1.0.0/src/ser/mod.rs:1526:1 + | +1526 | / pub trait SerializeTupleStruct { +1527 | | /// Must match the `Ok` type of our `Serializer`. +1528 | | type Ok; +1529 | | +... | +1539 | | fn end(self) -> Result; +1540 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `SerializeTupleVariant` + --> serde-1.0.0/src/ser/mod.rs:1574:1 + | +1574 | / pub trait SerializeTupleVariant { +1575 | | /// Must match the `Ok` type of our `Serializer`. +1576 | | type Ok; +1577 | | +... | +1587 | | fn end(self) -> Result; +1588 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `SerializeMap` + --> serde-1.0.0/src/ser/mod.rs:1629:1 + | +1629 | / pub trait SerializeMap { +1630 | | /// Must match the `Ok` type of our `Serializer`. +1631 | | type Ok; +1632 | | +... | +1687 | | fn end(self) -> Result; +1688 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `SerializeStruct` + --> serde-1.0.0/src/ser/mod.rs:1713:1 + | +1713 | / pub trait SerializeStruct { +1714 | | /// Must match the `Ok` type of our `Serializer`. +1715 | | type Ok; +1716 | | +... | +1730 | | fn end(self) -> Result; +1731 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `SerializeStructVariant` + --> serde-1.0.0/src/ser/mod.rs:1758:1 + | +1758 | / pub trait SerializeStructVariant { +1759 | | /// Must match the `Ok` type of our `Serializer`. +1760 | | type Ok; +1761 | | +... | +1775 | | fn end(self) -> Result; +1776 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: technically breaking changes in `new::ser::impls::` + --> serde-1.0.0/src/ser/impls.rs:73:1 + | +73 | / impl Serialize for CStr { +74 | | #[inline] +75 | | fn serialize(&self, serializer: S) -> Result +76 | | where +... | +80 | | } +81 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::` + --> serde-1.0.0/src/ser/impls.rs:84:1 + | +84 | / impl Serialize for CString { +85 | | #[inline] +86 | | fn serialize(&self, serializer: S) -> Result +87 | | where +... | +91 | | } +92 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::` + --> serde-1.0.0/src/ser/impls.rs:127:1 + | +127 | / impl Serialize for [T; 0] { +128 | | #[inline] +129 | | fn serialize(&self, serializer: S) -> Result +130 | | where +... | +134 | | } +135 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::>` + --> serde-1.0.0/src/ser/impls.rs:182:9 + | +182 | / impl Serialize for $ty +183 | | where +184 | | T: Serialize $(+ $tbound1 $(+ $tbound2)*)*, +185 | | $($typaram: $bound,)* +... | +193 | | } +194 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::>` + --> serde-1.0.0/src/ser/impls.rs:219:1 + | +219 | / impl Serialize for ops::Range +220 | | where +221 | | Idx: Serialize, +222 | | { +... | +232 | | } +233 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::` + --> serde-1.0.0/src/ser/impls.rs:252:13 + | +252 | / impl<$($name),+> Serialize for ($($name,)+) +253 | | where +254 | | $($name: Serialize,)+ +255 | | { +... | +266 | | } +267 | | } + | |_____________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::>` + --> serde-1.0.0/src/ser/impls.rs:295:9 + | +295 | / impl Serialize for $ty +296 | | where +297 | | K: Serialize $(+ $kbound1 $(+ $kbound2)*)*, +298 | | V: Serialize, +... | +307 | | } +308 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::>` + --> serde-1.0.0/src/ser/impls.rs:354:1 + | +354 | / impl Serialize for Cell +355 | | where +356 | | T: Serialize + Copy, +357 | | { +... | +363 | | } +364 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::>` + --> serde-1.0.0/src/ser/impls.rs:366:1 + | +366 | / impl Serialize for RefCell +367 | | where +368 | | T: Serialize, +369 | | { +... | +375 | | } +376 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::>` + --> serde-1.0.0/src/ser/impls.rs:379:1 + | +379 | / impl Serialize for Mutex +380 | | where +381 | | T: Serialize, +382 | | { +... | +391 | | } +392 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::>` + --> serde-1.0.0/src/ser/impls.rs:395:1 + | +395 | / impl Serialize for RwLock +396 | | where +397 | | T: Serialize, +398 | | { +... | +407 | | } +408 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::` + --> serde-1.0.0/src/ser/impls.rs:433:1 + | +433 | / impl Serialize for Duration { +434 | | fn serialize(&self, serializer: S) -> Result +435 | | where +436 | | S: Serializer, +... | +443 | | } +444 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::` + --> serde-1.0.0/src/ser/impls.rs:475:1 + | +475 | / impl Serialize for net::IpAddr { +476 | | fn serialize(&self, serializer: S) -> Result +477 | | where +478 | | S: Serializer, +... | +484 | | } +485 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::` + --> serde-1.0.0/src/ser/impls.rs:574:1 + | +574 | / impl Serialize for OsStr { +575 | | #[cfg(unix)] +576 | | fn serialize(&self, serializer: S) -> Result +577 | | where +... | +592 | | } +593 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::` + --> serde-1.0.0/src/ser/impls.rs:596:1 + | +596 | / impl Serialize for OsString { +597 | | fn serialize(&self, serializer: S) -> Result +598 | | where +599 | | S: Serializer, +... | +602 | | } +603 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: path changes to `Impossible` + --> serde-1.0.0/src/ser/impossible.rs:71:1 + | +71 | / pub struct Impossible { +72 | | void: Void, +73 | | ok: PhantomData, +74 | | error: PhantomData, +75 | | } + | |_^ + | +note: added path (technically breaking) + --> serde-1.0.0/src/ser/mod.rs:121:9 + | +121| pub use self::impossible::Impossible; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: path changes to `Error` + --> serde-1.0.0/src/de/mod.rs:151:9 + | +151 | / pub trait Error: Sized $(+ $($supertrait)::+)* { +152 | | /// Raised when there is general error when deserializing a type. +153 | | /// +154 | | /// The message should not be capitalized and should not end with a period. +... | +268 | | } +269 | | } + | |_________^ + | +warning: removed path (breaking) + --> serde-0.7.0/src/lib.rs:27:41 + | +27 | pub use de::{Deserialize, Deserializer, Error}; + | ^^^^^ + +warning: path changes to `Unexpected` + --> serde-1.0.0/src/de/mod.rs:307:1 + | +307 | / pub enum Unexpected<'a> { +308 | | /// The input contained a boolean value that was not expected. +309 | | Bool(bool), +310 | | +... | +367 | | Other(&'a str), +368 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `Expected` + --> serde-1.0.0/src/de/mod.rs:443:1 + | +443 | / pub trait Expected { +444 | | /// Format an explanation of what data was being expected. Same signature as +445 | | /// the `Display` and `Debug` traits. +446 | | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result; +447 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `DeserializeOwned` + --> serde-1.0.0/src/de/mod.rs:529:1 + | +529 | pub trait DeserializeOwned: for<'de> Deserialize<'de> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + +warning: path changes to `DeserializeSeed` + --> serde-1.0.0/src/de/mod.rs:679:1 + | +679 | / pub trait DeserializeSeed<'de>: Sized { +680 | | /// The type produced by using this seed. +681 | | type Value; +682 | | +... | +687 | | D: Deserializer<'de>; +688 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `SeqAccess` + --> serde-1.0.0/src/de/mod.rs:1417:1 + | +1417 | / pub trait SeqAccess<'de> { +1418 | | /// The error type that can be returned if some error occurs during +1419 | | /// deserialization. +1420 | | type Error: Error; +... | +1448 | | } +1449 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `MapAccess` + --> serde-1.0.0/src/de/mod.rs:1484:1 + | +1484 | / pub trait MapAccess<'de> { +1485 | | /// The error type that can be returned if some error occurs during +1486 | | /// deserialization. +1487 | | type Error: Error; +... | +1586 | | } +1587 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `EnumAccess` + --> serde-1.0.0/src/de/mod.rs:1661:1 + | +1661 | / pub trait EnumAccess<'de>: Sized { +1662 | | /// The error type that can be returned if some error occurs during +1663 | | /// deserialization. +1664 | | type Error: Error; +... | +1687 | | } +1688 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `VariantAccess` + --> serde-1.0.0/src/de/mod.rs:1693:1 + | +1693 | / pub trait VariantAccess<'de>: Sized { +1694 | | /// The error type that can be returned if some error occurs during +1695 | | /// deserialization. Must match the error type of our `EnumAccess`. +1696 | | type Error: Error; +... | +1872 | | V: Visitor<'de>; +1873 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `IntoDeserializer` + --> serde-1.0.0/src/de/mod.rs:1905:1 + | +1905 | / pub trait IntoDeserializer<'de, E: Error = value::Error> { +1906 | | /// The type of the deserializer being converted into. +1907 | | type Deserializer: Deserializer<'de, Error = E>; +1908 | | +1909 | | /// Convert this value into a deserializer. +1910 | | fn into_deserializer(self) -> Self::Deserializer; +1911 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: technically breaking changes in `` + --> serde-1.0.0/src/de/value.rs:78:1 + | +78 | / impl ser::Error for Error { +79 | | fn custom(msg: T) -> Self +80 | | where +81 | | T: Display, +... | +84 | | } +85 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::clone::Clone>` + --> serde-1.0.0/src/de/value.rs:120:10 + | +120 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> serde-1.0.0/src/de/value.rs:120:17 + | +120 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::clone::Clone>` + --> serde-1.0.0/src/de/value.rs:158:18 + | +158 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> serde-1.0.0/src/de/value.rs:158:25 + | +158 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::clone::Clone>` + --> serde-1.0.0/src/de/value.rs:215:10 + | +215 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> serde-1.0.0/src/de/value.rs:215:17 + | +215 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::clone::Clone>` + --> serde-1.0.0/src/de/value.rs:287:10 + | +287 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> serde-1.0.0/src/de/value.rs:287:17 + | +287 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::clone::Clone>` + --> serde-1.0.0/src/de/value.rs:360:10 + | +360 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> serde-1.0.0/src/de/value.rs:360:17 + | +360 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: path changes to `CowStrDeserializer` + --> serde-1.0.0/src/de/value.rs:437:1 + | +437 | / pub struct CowStrDeserializer<'a, E> { +438 | | value: Cow<'a, str>, +439 | | marker: PhantomData, +440 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.0/src/de/value.rs:458:1 + | +458 | / impl<'de, 'a, E> de::Deserializer<'de> for CowStrDeserializer<'a, E> +459 | | where +460 | | E: de::Error, +461 | | { +... | +492 | | } +493 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::clone::Clone>` + --> serde-1.0.0/src/de/value.rs:514:10 + | +514 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> serde-1.0.0/src/de/value.rs:514:17 + | +514 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new` + --> serde-1.0.0/src/de/value.rs:526:5 + | +526 | / pub fn new(iter: I) -> Self { +527 | | SeqDeserializer { +528 | | iter: iter.fuse(), +529 | | count: 0, +530 | | marker: PhantomData, +531 | | } +532 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in `end` + --> serde-1.0.0/src/de/value.rs:542:5 + | +542 | / pub fn end(mut self) -> Result<(), E> { +543 | | let mut remaining = 0; +544 | | while self.iter.next().is_some() { +545 | | remaining += 1; +... | +553 | | } +554 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.0/src/de/value.rs:557:1 + | +557 | / impl<'de, I, T, E> de::Deserializer<'de> for SeqDeserializer +558 | | where +559 | | I: Iterator, +560 | | T: IntoDeserializer<'de, E>, +... | +578 | | } +579 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: path changes to `SeqAccessDeserializer` + --> serde-1.0.0/src/de/value.rs:664:1 + | +664 | / pub struct SeqAccessDeserializer { +665 | | seq: A, +666 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.0/src/de/value.rs:675:1 + | +675 | / impl<'de, A> de::Deserializer<'de> for SeqAccessDeserializer +676 | | where +677 | | A: de::SeqAccess<'de>, +678 | | { +... | +692 | | } +693 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new` + --> serde-1.0.0/src/de/value.rs:716:5 + | +716 | / pub fn new(iter: I) -> Self { +717 | | MapDeserializer { +718 | | iter: iter.fuse(), +719 | | value: None, +... | +723 | | } +724 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in `end` + --> serde-1.0.0/src/de/value.rs:735:5 + | +735 | / pub fn end(mut self) -> Result<(), E> { +736 | | let mut remaining = 0; +737 | | while self.iter.next().is_some() { +738 | | remaining += 1; +... | +746 | | } +747 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.0/src/de/value.rs:766:1 + | +766 | / impl<'de, I, E> de::Deserializer<'de> for MapDeserializer<'de, I, E> +767 | | where +768 | | I: Iterator, +769 | | I::Item: private::Pair, +... | +810 | | } +811 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::clone::Clone>` + --> serde-1.0.0/src/de/value.rs:900:1 + | +900 | / impl<'de, I, E> Clone for MapDeserializer<'de, I, E> +901 | | where +902 | | I: Iterator + Clone, +903 | | I::Item: private::Pair, +... | +914 | | } +915 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> serde-1.0.0/src/de/value.rs:918:1 + | +918 | / impl<'de, I, E> Debug for MapDeserializer<'de, I, E> +919 | | where +920 | | I: Iterator + Debug, +921 | | I::Item: private::Pair, +... | +933 | | } +934 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.0/src/de/value.rs:940:1 + | +940 | / impl<'de, A, B, E> de::Deserializer<'de> for PairDeserializer +941 | | where +942 | | A: IntoDeserializer<'de, E>, +943 | | B: IntoDeserializer<'de, E>, +... | +988 | | } +989 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: path changes to `MapAccessDeserializer` + --> serde-1.0.0/src/de/value.rs:1071:1 + | +1071 | / pub struct MapAccessDeserializer { +1072 | | map: A, +1073 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.0/src/de/value.rs:1082:1 + | +1082 | / impl<'de, A> de::Deserializer<'de> for MapAccessDeserializer +1083 | | where +1084 | | A: de::MapAccess<'de>, +1085 | | { +... | +1099 | | } +1100 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: path changes to `IgnoredAny` + --> serde-1.0.0/src/de/ignored_any.rs:107:1 + | +107 | pub struct IgnoredAny; + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> serde-1.0.0/src/de/mod.rs:132:9 + | +132 | pub use self::ignored_any::IgnoredAny; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: technically breaking changes in `>` + --> serde-1.0.0/src/de/ignored_any.rs:109:1 + | +109 | / impl<'de> Visitor<'de> for IgnoredAny { +110 | | type Value = IgnoredAny; +111 | | +112 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +204 | | } +205 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> serde-1.0.0/src/de/ignored_any.rs:207:1 + | +207 | / impl<'de> Deserialize<'de> for IgnoredAny { +208 | | #[inline] +209 | | fn deserialize(deserializer: D) -> Result +210 | | where +... | +214 | | } +215 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for f32>::deserialize::PrimitiveVisitor as new::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:117:17 + | +117 | / impl<'de> Visitor<'de> for PrimitiveVisitor { +118 | | type Value = $ty; +119 | | +120 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +126 | | )* +127 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> serde-1.0.0/src/de/impls.rs:271:1 + | +271 | / impl<'a> Visitor<'a> for StrVisitor { +272 | | type Value = &'a str; +273 | | +274 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +290 | | } +291 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for &'a str>` + --> serde-1.0.0/src/de/impls.rs:293:1 + | +293 | / impl<'de: 'a, 'a> Deserialize<'de> for &'a str { +294 | | fn deserialize(deserializer: D) -> Result +295 | | where +296 | | D: Deserializer<'de>, +... | +299 | | } +300 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> serde-1.0.0/src/de/impls.rs:306:1 + | +306 | / impl<'a> Visitor<'a> for BytesVisitor { +307 | | type Value = &'a [u8]; +308 | | +309 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +325 | | } +326 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for &'a [u8]>` + --> serde-1.0.0/src/de/impls.rs:328:1 + | +328 | / impl<'de: 'a, 'a> Deserialize<'de> for &'a [u8] { +329 | | fn deserialize(deserializer: D) -> Result +330 | | where +331 | | D: Deserializer<'de>, +... | +334 | | } +335 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> serde-1.0.0/src/de/impls.rs:343:1 + | +343 | / impl<'de> Visitor<'de> for CStringVisitor { +344 | | type Value = CString; +345 | | +346 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +390 | | } +391 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::ffi::CString>` + --> serde-1.0.0/src/de/impls.rs:394:1 + | +394 | / impl<'de> Deserialize<'de> for CString { +395 | | fn deserialize(deserializer: D) -> Result +396 | | where +397 | | D: Deserializer<'de>, +... | +400 | | } +401 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:472:1 + | +472 | / impl<'de, T> Visitor<'de> for PhantomDataVisitor { +473 | | type Value = PhantomData; +474 | | +475 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +485 | | } +486 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::marker::PhantomData>` + --> serde-1.0.0/src/de/impls.rs:488:1 + | +488 | / impl<'de, T> Deserialize<'de> for PhantomData { +489 | | fn deserialize(deserializer: D) -> Result, D::Error> +490 | | where +491 | | D: Deserializer<'de>, +... | +495 | | } +496 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::collections::HashSet>` + --> serde-1.0.0/src/de/impls.rs:509:9 + | +509 | / impl<'de, T $(, $typaram)*> Deserialize<'de> for $ty +510 | | where +511 | | T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*, +512 | | $($typaram: $bound1 $(+ $bound2)*,)* +... | +550 | | } +551 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::collections::VecDeque>::deserialize::SeqVisitor as new::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:522:17 + | +522 | / impl<'de, T $(, $typaram)*> Visitor<'de> for SeqVisitor +523 | | where +524 | | T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*, +525 | | $($typaram: $bound1 $(+ $bound2)*,)* +... | +545 | | } +546 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:615:1 + | +615 | / impl<'de, T> Visitor<'de> for ArrayVisitor<[T; 0]> { +616 | | type Value = [T; 0]; +617 | | +618 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +628 | | } +629 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for [T; 0]>` + --> serde-1.0.0/src/de/impls.rs:632:1 + | +632 | / impl<'de, T> Deserialize<'de> for [T; 0] { +633 | | fn deserialize(deserializer: D) -> Result<[T; 0], D::Error> +634 | | where +635 | | D: Deserializer<'de>, +... | +638 | | } +639 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:644:13 + | +644 | / impl<'de, T> Visitor<'de> for ArrayVisitor<[T; $len]> +645 | | where +646 | | T: Deserialize<'de>, +647 | | { +... | +667 | | } +668 | | } + | |_____________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:735:13 + | +735 | / impl<'de, $($name: Deserialize<'de>),+> Visitor<'de> for $visitor<$($name,)+> { +736 | | type Value = ($($name,)+); +737 | | +738 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +756 | | } +757 | | } + | |_____________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)>` + --> serde-1.0.0/src/de/impls.rs:759:13 + | +759 | / impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) { +760 | | #[inline] +761 | | fn deserialize(deserializer: D) -> Result<($($name,)+), D::Error> +762 | | where +... | +766 | | } +767 | | } + | |_____________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::collections::HashMap>` + --> serde-1.0.0/src/de/impls.rs:801:9 + | +801 | / impl<'de, K, V $(, $typaram)*> Deserialize<'de> for $ty +802 | | where +803 | | K: Deserialize<'de> $(+ $kbound1 $(+ $kbound2)*)*, +804 | | V: Deserialize<'de>, +... | +844 | | } +845 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::collections::HashMap>::deserialize::MapVisitor as new::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:815:17 + | +815 | / impl<'de, K, V $(, $typaram)*> Visitor<'de> for MapVisitor +816 | | where +817 | | K: Deserialize<'de> $(+ $kbound1 $(+ $kbound2)*)*, +818 | | V: Deserialize<'de>, +... | +839 | | } +840 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::net::IpAddr>` + --> serde-1.0.0/src/de/impls.rs:868:9 + | +868 | / impl<'de> Deserialize<'de> for $ty { +869 | | fn deserialize(deserializer: D) -> Result +870 | | where +871 | | D: Deserializer<'de>, +... | +875 | | } +876 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> serde-1.0.0/src/de/impls.rs:952:1 + | +952 | / impl<'de> Deserialize<'de> for OsStringKind { +953 | | fn deserialize(deserializer: D) -> Result +954 | | where +955 | | D: Deserializer<'de>, +... | +1006 | | } +1007 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `<>::deserialize::KindVisitor as new::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:959:9 + | +959 | / impl<'de> Visitor<'de> for KindVisitor { +960 | | type Value = OsStringKind; +961 | | +962 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1002 | | } +1003 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> serde-1.0.0/src/de/impls.rs:1013:1 + | +1013 | / impl<'de> Visitor<'de> for OsStringVisitor { +1014 | | type Value = OsString; +1015 | | +1016 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1047 | | } +1048 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::ffi::OsString>` + --> serde-1.0.0/src/de/impls.rs:1051:1 + | +1051 | / impl<'de> Deserialize<'de> for OsString { +1052 | | fn deserialize(deserializer: D) -> Result +1053 | | where +1054 | | D: Deserializer<'de>, +... | +1057 | | } +1058 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::boxed::Box<[T]>>` + --> serde-1.0.0/src/de/impls.rs:1076:1 + | +1076 | / impl<'de, T> Deserialize<'de> for Box<[T]> +1077 | | where +1078 | | T: Deserialize<'de>, +1079 | | { +... | +1085 | | } +1086 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::boxed::Box>` + --> serde-1.0.0/src/de/impls.rs:1089:1 + | +1089 | / impl<'de> Deserialize<'de> for Box { +1090 | | fn deserialize(deserializer: D) -> Result +1091 | | where +1092 | | D: Deserializer<'de>, +... | +1095 | | } +1096 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::cell::Cell>` + --> serde-1.0.0/src/de/impls.rs:1141:1 + | +1141 | / impl<'de, T> Deserialize<'de> for Cell +1142 | | where +1143 | | T: Deserialize<'de> + Copy, +1144 | | { +... | +1150 | | } +1151 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::cell::RefCell>` + --> serde-1.0.0/src/de/impls.rs:1153:1 + | +1153 | / impl<'de, T> Deserialize<'de> for RefCell +1154 | | where +1155 | | T: Deserialize<'de>, +1156 | | { +... | +1162 | | } +1163 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::sync::Mutex>` + --> serde-1.0.0/src/de/impls.rs:1166:1 + | +1166 | / impl<'de, T> Deserialize<'de> for Mutex +1167 | | where +1168 | | T: Deserialize<'de>, +1169 | | { +... | +1175 | | } +1176 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::sync::RwLock>` + --> serde-1.0.0/src/de/impls.rs:1179:1 + | +1179 | / impl<'de, T> Deserialize<'de> for RwLock +1180 | | where +1181 | | T: Deserialize<'de>, +1182 | | { +... | +1188 | | } +1189 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::time::Duration>` + --> serde-1.0.0/src/de/impls.rs:1202:1 + | +1202 | / impl<'de> Deserialize<'de> for Duration { +1203 | | fn deserialize(deserializer: D) -> Result +1204 | | where +1205 | | D: Deserializer<'de>, +... | +1324 | | } +1325 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::time::Duration>::deserialize::Field as new::Deserialize<'de>>` + --> serde-1.0.0/src/de/impls.rs:1216:9 + | +1216 | / impl<'de> Deserialize<'de> for Field { +1217 | | fn deserialize(deserializer: D) -> Result +1218 | | where +1219 | | D: Deserializer<'de>, +... | +1257 | | } +1258 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `< for std::time::Duration>::deserialize::Field as new::Deserialize<'de>>::deserialize::FieldVisitor as new::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:1223:17 + | +1223 | / impl<'de> Visitor<'de> for FieldVisitor { +1224 | | type Value = Field; +1225 | | +1226 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1253 | | } +1254 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::time::Duration>::deserialize::DurationVisitor as new::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:1262:9 + | +1262 | / impl<'de> Visitor<'de> for DurationVisitor { +1263 | | type Value = Duration; +1264 | | +1265 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1319 | | } +1320 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::ops::Range>` + --> serde-1.0.0/src/de/impls.rs:1338:1 + | +1338 | / impl<'de, Idx> Deserialize<'de> for ops::Range +1339 | | where +1340 | | Idx: Deserialize<'de>, +1341 | | { +... | +1468 | | } +1469 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::ops::Range>::deserialize::Field as new::Deserialize<'de>>` + --> serde-1.0.0/src/de/impls.rs:1355:9 + | +1355 | / impl<'de> Deserialize<'de> for Field { +1356 | | fn deserialize(deserializer: D) -> Result +1357 | | where +1358 | | D: Deserializer<'de>, +... | +1396 | | } +1397 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `< for std::ops::Range>::deserialize::Field as new::Deserialize<'de>>::deserialize::FieldVisitor as new::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:1362:17 + | +1362 | / impl<'de> Visitor<'de> for FieldVisitor { +1363 | | type Value = Field; +1364 | | +1365 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1392 | | } +1393 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::ops::Range>::deserialize::RangeVisitor as new::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:1403:9 + | +1403 | / impl<'de, Idx> Visitor<'de> for RangeVisitor +1404 | | where +1405 | | Idx: Deserialize<'de>, +1406 | | { +... | +1463 | | } +1464 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::result::Result>::deserialize::Field as new::Deserialize<'de>>` + --> serde-1.0.0/src/de/impls.rs:1513:9 + | +1513 | / impl<'de> Deserialize<'de> for Field { +1514 | | #[inline] +1515 | | fn deserialize(deserializer: D) -> Result +1516 | | where +... | +1572 | | } +1573 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `< for std::result::Result>::deserialize::Field as new::Deserialize<'de>>::deserialize::FieldVisitor as new::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:1521:17 + | +1521 | / impl<'de> Visitor<'de> for FieldVisitor { +1522 | | type Value = Field; +1523 | | +1524 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1568 | | } +1569 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::result::Result>::deserialize::ResultVisitor as new::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:1577:9 + | +1577 | / impl<'de, T, E> Visitor<'de> for ResultVisitor +1578 | | where +1579 | | T: Deserialize<'de>, +1580 | | E: Deserialize<'de>, +... | +1596 | | } +1597 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: path changes to `export` + --> serde-1.0.0/src/export.rs:9:1 + | +9 | / pub use lib::clone::Clone; +10 | | pub use lib::convert::{From, Into}; +11 | | pub use lib::default::Default; +12 | | pub use lib::fmt::{self, Formatter}; +... | +40 | | } +41 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `private` + --> serde-1.0.0/src/private/mod.rs:9:1 + | +9 | / mod macros; +10 | | +11 | | pub mod ser; +12 | | pub mod de; + | |___________^ + | + = note: added definition (technically breaking) + +warning: path changes to `__private_serialize` + --> serde-1.0.0/src/private/macros.rs:11:1 + | +11 | / macro_rules! __private_serialize { +12 | | () => { +13 | | trait Serialize { +14 | | fn serialize(&self, serializer: S) -> Result +... | +18 | | }; +19 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `__private_deserialize` + --> serde-1.0.0/src/private/macros.rs:23:1 + | +23 | / macro_rules! __private_deserialize { +24 | | () => { +25 | | trait Deserialize<'de>: Sized { +26 | | fn deserialize(deserializer: D) -> Result +... | +30 | | }; +31 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `__serialize_unimplemented` + --> serde-1.0.0/src/private/macros.rs:36:1 + | +36 | / macro_rules! __serialize_unimplemented { +37 | | ($($func:ident)*) => { +38 | | $( +39 | | __serialize_unimplemented_helper!($func); +40 | | )* +41 | | }; +42 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `__serialize_unimplemented_method` + --> serde-1.0.0/src/private/macros.rs:46:1 + | +46 | / macro_rules! __serialize_unimplemented_method { +47 | | ($func:ident $(<$t:ident>)* ($($arg:ty),*) -> $ret:ident) => { +48 | | fn $func $(<$t: ?Sized + $crate::Serialize>)* (self $(, _: $arg)*) -> $crate::export::Result { +49 | | unimplemented!() +50 | | } +51 | | }; +52 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `__serialize_unimplemented_helper` + --> serde-1.0.0/src/private/macros.rs:56:1 + | +56 | / macro_rules! __serialize_unimplemented_helper { +57 | | (bool) => { +58 | | __serialize_unimplemented_method!(serialize_bool(bool) -> Ok); +59 | | }; +... | +147 | | }; +148 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: technically breaking changes in ` as new::Serializer>` + --> serde-1.0.0/src/private/ser.rs:107:1 + | +107 | / impl Serializer for TaggedSerializer +108 | | where +109 | | S: Serializer, +110 | | { +... | +336 | | } +337 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> serde-1.0.0/src/private/ser.rs:344:1 + | +344 | / impl ser::Error for Error { +345 | | fn custom(_: T) -> Self +346 | | where +347 | | T: Display, +... | +350 | | } +351 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> serde-1.0.0/src/private/ser.rs:491:5 + | +491 | / impl Serialize for Content { +492 | | fn serialize(&self, serializer: S) -> Result +493 | | where +494 | | S: Serializer, +... | +570 | | } +571 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Serializer>` + --> serde-1.0.0/src/private/ser.rs:583:5 + | +583 | / impl Serializer for ContentSerializer +584 | | where +585 | | E: ser::Error, +586 | | { +... | +803 | | } +804 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.0/src/private/de.rs:30:5 + | +30 | / impl<'de, E> Deserializer<'de> for MissingFieldDeserializer +31 | | where +32 | | E: Error, +33 | | { +... | +54 | | } +55 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> serde-1.0.0/src/private/de.rs:68:5 + | +68 | / impl<'a> Visitor<'a> for CowStrVisitor { +69 | | type Value = Cow<'a, str>; +70 | | +71 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +124 | | } +125 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> serde-1.0.0/src/private/de.rs:137:5 + | +137 | / impl<'a> Visitor<'a> for CowBytesVisitor { +138 | | type Value = Cow<'a, [u8]>; +139 | | +140 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +184 | | } +185 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> serde-1.0.0/src/private/de.rs:290:5 + | +290 | / impl<'de> Deserialize<'de> for Content { +291 | | fn deserialize(deserializer: D) -> Result +292 | | where +293 | | D: Deserializer<'de>, +... | +298 | | } +299 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> serde-1.0.0/src/private/de.rs:303:5 + | +303 | / impl<'de> Visitor<'de> for ContentVisitor { +304 | | type Value = Content; +305 | | +306 | | fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +... | +477 | | } +478 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> serde-1.0.0/src/private/de.rs:511:5 + | +511 | / impl<'de> Visitor<'de> for TagOrContentVisitor { +512 | | type Value = TagOrContent; +513 | | +514 | | fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +... | +731 | | } +732 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::Visitor<'de>>` + --> serde-1.0.0/src/private/de.rs:775:5 + | +775 | / impl<'de, T> Visitor<'de> for TaggedContentVisitor +776 | | where +777 | | T: Deserialize<'de>, +778 | | { +... | +817 | | } +818 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> serde-1.0.0/src/private/de.rs:845:5 + | +845 | / impl<'de> Visitor<'de> for TagOrContentFieldVisitor { +846 | | type Value = TagOrContentField; +847 | | +848 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +863 | | } +864 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.0/src/private/de.rs:874:5 + | +874 | / impl<'de, E> Deserializer<'de> for ContentDeserializer +875 | | where +876 | | E: de::Error, +877 | | { +... | +999 | | } +1000 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.0/src/private/de.rs:1125:5 + | +1125 | / impl<'de, E> de::Deserializer<'de> for SeqDeserializer +1126 | | where +1127 | | E: de::Error, +1128 | | { +... | +1154 | | } +1155 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.0/src/private/de.rs:1237:5 + | +1237 | / impl<'de, E> de::Deserializer<'de> for MapDeserializer +1238 | | where +1239 | | E: de::Error, +1240 | | { +... | +1255 | | } +1256 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.0/src/private/de.rs:1266:5 + | +1266 | / impl<'de, 'a, E> Deserializer<'de> for ContentRefDeserializer<'a, E> +1267 | | where +1268 | | E: de::Error, +1269 | | { +... | +1391 | | } +1392 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.0/src/private/de.rs:1517:5 + | +1517 | / impl<'de, 'a, E> de::Deserializer<'de> for SeqRefDeserializer<'a, E> +1518 | | where +1519 | | E: de::Error, +1520 | | { +... | +1546 | | } +1547 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.0/src/private/de.rs:1630:5 + | +1630 | / impl<'de, 'a, E> de::Deserializer<'de> for MapRefDeserializer<'a, E> +1631 | | where +1632 | | E: de::Error, +1633 | | { +... | +1648 | | } +1649 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::Visitor<'de>>` + --> serde-1.0.0/src/private/de.rs:1691:5 + | +1691 | / impl<'de, 'a> Visitor<'de> for InternallyTaggedUnitVisitor<'a> { +1692 | | type Value = (); +1693 | | +1694 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1703 | | } +1704 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::Visitor<'de>>` + --> serde-1.0.0/src/private/de.rs:1724:5 + | +1724 | / impl<'de, 'a> Visitor<'de> for UntaggedUnitVisitor<'a> { +1725 | | type Value = (); +1726 | | +1727 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1736 | | } +1737 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.0/src/private/de.rs:1788:1 + | +1788 | / impl<'de, 'a, E> Deserializer<'de> for StrDeserializer<'a, E> +1789 | | where +1790 | | E: Error, +1791 | | { +... | +1805 | | } +1806 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.0/src/private/de.rs:1827:1 + | +1827 | / impl<'de, 'a, E> Deserializer<'de> for BytesDeserializer<'a, E> +1828 | | where +1829 | | E: Error, +1830 | | { +... | +1844 | | } +1845 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +error: path changes to `bytes` + --> serde-0.7.0/src/bytes.rs:1:1 + | +1 | / //! Helper module to enable serializing bytes more efficiently +2 | | +3 | | use std::ops; +4 | | use std::fmt; +... | +215 | | result +216 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: breaking changes in ` as old::Serialize>` + --> serde-0.7.0/src/bytes.rs:52:1 + | +52 | / impl<'a> ser::Serialize for Bytes<'a> { +53 | | #[inline] +54 | | fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> +55 | | where S: ser::Serializer +... | +58 | | } +59 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `` + --> serde-0.7.0/src/bytes.rs:139:1 + | +139 | / impl ser::Serialize for ByteBuf { +140 | | fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> +141 | | where S: ser::Serializer +142 | | { +143 | | serializer.serialize_bytes(&self) +144 | | } +145 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `` + --> serde-0.7.0/src/bytes.rs:150:1 + | +150 | / impl de::Visitor for ByteBufVisitor { +151 | | type Value = ByteBuf; +152 | | +153 | | #[inline] +... | +194 | | } +195 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `` + --> serde-0.7.0/src/bytes.rs:197:1 + | +197 | / impl de::Deserialize for ByteBuf { +198 | | #[inline] +199 | | fn deserialize(deserializer: &mut D) -> Result +200 | | where D: de::Deserializer +... | +203 | | } +204 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `Error` + --> serde-1.0.0/src/de/mod.rs:151:9 + | +151 | / pub trait Error: Sized $(+ $($supertrait)::+)* { +152 | | /// Raised when there is general error when deserializing a type. +153 | | /// +154 | | /// The message should not be capitalized and should not end with a period. +... | +268 | | } +269 | | } + | |_________^ + | +note: added defaulted item to trait (technically breaking) + --> serde-1.0.0/src/de/mod.rs:266:13 + | +266 | / fn duplicate_field(field: &'static str) -> Self { +267 | | Error::custom(format_args!("duplicate field `{}`", field)) +268 | | } + | |_____________^ +warning: removed item from trait (breaking) + --> serde-0.7.0/src/de/mod.rs:18:5 + | +18 | fn end_of_stream() -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: breaking changes in `custom` + --> serde-1.0.0/src/de/mod.rs:180:13 + | +180 | / fn custom(msg: T) -> Self +181 | | where +182 | | T: Display; + | |___________________________^ + | + = warning: added bound: `T: std::fmt::Display` (breaking) + = note: removed bound: `std::string::String: std::convert::From` (technically breaking) + +error: breaking changes in `invalid_type` + --> serde-1.0.0/src/de/mod.rs:197:13 + | +197 | / fn invalid_type(unexp: Unexpected, exp: &Expected) -> Self { +198 | | Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp)) +199 | | } + | |_____________^ + | + = warning: type error: incorrect number of function parameters (breaking) + +error: breaking changes in `invalid_value` + --> serde-1.0.0/src/de/mod.rs:214:13 + | +214 | / fn invalid_value(unexp: Unexpected, exp: &Expected) -> Self { +215 | | Error::custom(format_args!("invalid value: {}, expected {}", unexp, exp)) +216 | | } + | |_____________^ + | + = warning: type error: incorrect number of function parameters (breaking) + +error: breaking changes in `invalid_length` + --> serde-1.0.0/src/de/mod.rs:227:13 + | +227 | / fn invalid_length(len: usize, exp: &Expected) -> Self { +228 | | Error::custom(format_args!("invalid length {}, expected {}", len, exp)) +229 | | } + | |_____________^ + | + = warning: type error: incorrect number of function parameters (breaking) + +error: breaking changes in `unknown_variant` + --> serde-1.0.0/src/de/mod.rs:233:13 + | +233 | / fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self { +234 | | if expected.is_empty() { +235 | | Error::custom(format_args!("unknown variant `{}`, there are no variants", +236 | | variant)) +... | +241 | | } +242 | | } + | |_____________^ + | + = warning: type error: incorrect number of function parameters (breaking) + +error: breaking changes in `unknown_field` + --> serde-1.0.0/src/de/mod.rs:246:13 + | +246 | / fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self { +247 | | if expected.is_empty() { +248 | | Error::custom(format_args!("unknown field `{}`, there are no fields", +249 | | field)) +... | +254 | | } +255 | | } + | |_____________^ + | + = warning: type error: incorrect number of function parameters (breaking) + +error: path changes to `Type` + --> serde-0.7.0/src/de/mod.rs:54:1 + | +54 | / pub enum Type { +55 | | /// Represents a `bool` type. +56 | | Bool, +57 | | +... | +149 | | Bytes, +150 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: breaking changes in `Deserialize` + --> serde-1.0.0/src/de/mod.rs:496:1 + | +496 | / pub trait Deserialize<'de>: Sized { +497 | | /// Deserialize this value from the given Serde deserializer. +498 | | /// +499 | | /// See the [Implementing `Deserialize`][impl-deserialize] section of the +... | +505 | | D: Deserializer<'de>; +506 | | } + | |_^ + | + = warning: region parameter added (breaking) + +error: breaking changes in `deserialize` + --> serde-1.0.0/src/de/mod.rs:503:5 + | +503 | / fn deserialize(deserializer: D) -> Result +504 | | where +505 | | D: Deserializer<'de>; + | |_____________________________^ + | + = warning: type error: expected old::Deserializer::Error, found new::Deserializer::Error (breaking) + +error: breaking changes in `Deserializer` + --> serde-1.0.0/src/de/mod.rs:795:1 + | +795 | / pub trait Deserializer<'de>: Sized { +796 | | /// The error type that can be returned if some error occurs during +797 | | /// deserialization. +798 | | type Error: Error; +... | +1012 | | V: Visitor<'de>; +1013 | | } + | |_^ + | + = warning: region parameter added (breaking) +warning: added item to trait (breaking) + --> serde-1.0.0/src/de/mod.rs:809:5 + | +809 | / fn deserialize_any(self, visitor: V) -> Result +810 | | where +811 | | V: Visitor<'de>; + | |________________________^ +warning: removed item from trait (breaking) + --> serde-0.7.0/src/de/mod.rs:180:5 + | +180 | / fn deserialize(&mut self, visitor: V) -> Result +181 | | where V: Visitor; + | |_________________________^ +warning: added item to trait (breaking) + --> serde-1.0.0/src/de/mod.rs:913:5 + | +913 | / fn deserialize_byte_buf(self, visitor: V) -> Result +914 | | where +915 | | V: Visitor<'de>; + | |________________________^ +warning: added item to trait (breaking) + --> serde-1.0.0/src/de/mod.rs:1002:5 + | +1002 | / fn deserialize_identifier(self, visitor: V) -> Result +1003 | | where +1004 | | V: Visitor<'de>; + | |________________________^ +warning: removed defaulted item from trait (breaking) + --> serde-0.7.0/src/de/mod.rs:193:5 + | +193 | / fn deserialize_usize(&mut self, visitor: V) -> Result +194 | | where V: Visitor, +195 | | { +196 | | self.deserialize_u64(visitor) +197 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> serde-0.7.0/src/de/mod.rs:233:5 + | +233 | / fn deserialize_isize(&mut self, visitor: V) -> Result +234 | | where V: Visitor, +235 | | { +236 | | self.deserialize_i64(visitor) +237 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> serde-0.7.0/src/de/mod.rs:343:5 + | +343 | / fn deserialize_fixed_size_array(&mut self, +344 | | _len: usize, +345 | | visitor: V) -> Result +346 | | where V: Visitor, +347 | | { +348 | | self.deserialize(visitor) +349 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> serde-0.7.0/src/de/mod.rs:420:5 + | +420 | / fn deserialize_struct_field(&mut self, visitor: V) -> Result +421 | | where V: Visitor, +422 | | { +423 | | self.deserialize(visitor) +424 | | } + | |_____^ + +error: breaking changes in `deserialize_bool` + --> serde-1.0.0/src/de/mod.rs:814:5 + | +814 | / fn deserialize_bool(self, visitor: V) -> Result +815 | | where +816 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_u8` + --> serde-1.0.0/src/de/mod.rs:839:5 + | +839 | / fn deserialize_u8(self, visitor: V) -> Result +840 | | where +841 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_u16` + --> serde-1.0.0/src/de/mod.rs:844:5 + | +844 | / fn deserialize_u16(self, visitor: V) -> Result +845 | | where +846 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_u32` + --> serde-1.0.0/src/de/mod.rs:849:5 + | +849 | / fn deserialize_u32(self, visitor: V) -> Result +850 | | where +851 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_u64` + --> serde-1.0.0/src/de/mod.rs:854:5 + | +854 | / fn deserialize_u64(self, visitor: V) -> Result +855 | | where +856 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_i8` + --> serde-1.0.0/src/de/mod.rs:819:5 + | +819 | / fn deserialize_i8(self, visitor: V) -> Result +820 | | where +821 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_i16` + --> serde-1.0.0/src/de/mod.rs:824:5 + | +824 | / fn deserialize_i16(self, visitor: V) -> Result +825 | | where +826 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_i32` + --> serde-1.0.0/src/de/mod.rs:829:5 + | +829 | / fn deserialize_i32(self, visitor: V) -> Result +830 | | where +831 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_i64` + --> serde-1.0.0/src/de/mod.rs:834:5 + | +834 | / fn deserialize_i64(self, visitor: V) -> Result +835 | | where +836 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_f32` + --> serde-1.0.0/src/de/mod.rs:859:5 + | +859 | / fn deserialize_f32(self, visitor: V) -> Result +860 | | where +861 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_f64` + --> serde-1.0.0/src/de/mod.rs:864:5 + | +864 | / fn deserialize_f64(self, visitor: V) -> Result +865 | | where +866 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_char` + --> serde-1.0.0/src/de/mod.rs:869:5 + | +869 | / fn deserialize_char(self, visitor: V) -> Result +870 | | where +871 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_str` + --> serde-1.0.0/src/de/mod.rs:880:5 + | +880 | / fn deserialize_str(self, visitor: V) -> Result +881 | | where +882 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_string` + --> serde-1.0.0/src/de/mod.rs:891:5 + | +891 | / fn deserialize_string(self, visitor: V) -> Result +892 | | where +893 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_unit` + --> serde-1.0.0/src/de/mod.rs:927:5 + | +927 | / fn deserialize_unit(self, visitor: V) -> Result +928 | | where +929 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_option` + --> serde-1.0.0/src/de/mod.rs:922:5 + | +922 | / fn deserialize_option(self, visitor: V) -> Result +923 | | where +924 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_seq` + --> serde-1.0.0/src/de/mod.rs:952:5 + | +952 | / fn deserialize_seq(self, visitor: V) -> Result +953 | | where +954 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_bytes` + --> serde-1.0.0/src/de/mod.rs:902:5 + | +902 | / fn deserialize_bytes(self, visitor: V) -> Result +903 | | where +904 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_map` + --> serde-1.0.0/src/de/mod.rs:974:5 + | +974 | / fn deserialize_map(self, visitor: V) -> Result +975 | | where +976 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_unit_struct` + --> serde-1.0.0/src/de/mod.rs:933:5 + | +933 | / fn deserialize_unit_struct( +934 | | self, +935 | | name: &'static str, +936 | | visitor: V, +937 | | ) -> Result +938 | | where +939 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_newtype_struct` + --> serde-1.0.0/src/de/mod.rs:943:5 + | +943 | / fn deserialize_newtype_struct( +944 | | self, +945 | | name: &'static str, +946 | | visitor: V, +947 | | ) -> Result +948 | | where +949 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_tuple_struct` + --> serde-1.0.0/src/de/mod.rs:964:5 + | +964 | / fn deserialize_tuple_struct( +965 | | self, +966 | | name: &'static str, +967 | | len: usize, +... | +970 | | where +971 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_struct` + --> serde-1.0.0/src/de/mod.rs:980:5 + | +980 | / fn deserialize_struct( +981 | | self, +982 | | name: &'static str, +983 | | fields: &'static [&'static str], +... | +986 | | where +987 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_tuple` + --> serde-1.0.0/src/de/mod.rs:958:5 + | +958 | / fn deserialize_tuple(self, len: usize, visitor: V) -> Result +959 | | where +960 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_enum` + --> serde-1.0.0/src/de/mod.rs:991:5 + | +991 | / fn deserialize_enum( +992 | | self, +993 | | name: &'static str, +994 | | variants: &'static [&'static str], +... | +997 | | where +998 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_ignored_any` + --> serde-1.0.0/src/de/mod.rs:1010:5 + | +1010 | / fn deserialize_ignored_any(self, visitor: V) -> Result +1011 | | where +1012 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `Visitor` + --> serde-1.0.0/src/de/mod.rs:1048:1 + | +1048 | / pub trait Visitor<'de>: Sized { +1049 | | /// The value produced by this visitor. +1050 | | type Value; +1051 | | +... | +1408 | | } +1409 | | } + | |_^ + | + = warning: region parameter added (breaking) +warning: added item to trait (breaking) + --> serde-1.0.0/src/de/mod.rs:1074:5 + | +1074 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: added defaulted item to trait (technically breaking) + --> serde-1.0.0/src/de/mod.rs:1242:5 + | +1242 | / fn visit_borrowed_str(self, v: &'de str) -> Result +1243 | | where +1244 | | E: Error, +1245 | | { +1246 | | self.visit_str(v) +1247 | | } + | |_____^ +note: added defaulted item to trait (technically breaking) + --> serde-1.0.0/src/de/mod.rs:1301:5 + | +1301 | / fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result +1302 | | where +1303 | | E: Error, +1304 | | { +1305 | | self.visit_bytes(v) +1306 | | } + | |_____^ +note: added defaulted item to trait (technically breaking) + --> serde-1.0.0/src/de/mod.rs:1402:5 + | +1402 | / fn visit_enum(self, data: A) -> Result +1403 | | where +1404 | | A: EnumAccess<'de>, +1405 | | { +1406 | | let _ = data; +1407 | | Err(Error::invalid_type(Unexpected::Enum, &self)) +1408 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> serde-0.7.0/src/de/mod.rs:508:5 + | +508 | / fn visit_usize(&mut self, v: usize) -> Result +509 | | where E: Error, +510 | | { +511 | | self.visit_u64(v as u64) +512 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> serde-0.7.0/src/de/mod.rs:473:5 + | +473 | / fn visit_isize(&mut self, v: isize) -> Result +474 | | where E: Error, +475 | | { +476 | | self.visit_i64(v as i64) +477 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> serde-0.7.0/src/de/mod.rs:592:5 + | +592 | / fn visit_unit_struct(&mut self, _name: &'static str) -> Result +593 | | where E: Error, +594 | | { +595 | | self.visit_unit() +596 | | } + | |_____^ + +error: breaking changes in `visit_bool` + --> serde-1.0.0/src/de/mod.rs:1079:5 + | +1079 | / fn visit_bool(self, v: bool) -> Result +1080 | | where +1081 | | E: Error, +1082 | | { +1083 | | Err(Error::invalid_type(Unexpected::Bool(v), &self)) +1084 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_i8` + --> serde-1.0.0/src/de/mod.rs:1091:5 + | +1091 | / fn visit_i8(self, v: i8) -> Result +1092 | | where +1093 | | E: Error, +1094 | | { +1095 | | self.visit_i64(v as i64) +1096 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_i16` + --> serde-1.0.0/src/de/mod.rs:1103:5 + | +1103 | / fn visit_i16(self, v: i16) -> Result +1104 | | where +1105 | | E: Error, +1106 | | { +1107 | | self.visit_i64(v as i64) +1108 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_i32` + --> serde-1.0.0/src/de/mod.rs:1115:5 + | +1115 | / fn visit_i32(self, v: i32) -> Result +1116 | | where +1117 | | E: Error, +1118 | | { +1119 | | self.visit_i64(v as i64) +1120 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_i64` + --> serde-1.0.0/src/de/mod.rs:1125:5 + | +1125 | / fn visit_i64(self, v: i64) -> Result +1126 | | where +1127 | | E: Error, +1128 | | { +1129 | | Err(Error::invalid_type(Unexpected::Signed(v), &self)) +1130 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_u8` + --> serde-1.0.0/src/de/mod.rs:1137:5 + | +1137 | / fn visit_u8(self, v: u8) -> Result +1138 | | where +1139 | | E: Error, +1140 | | { +1141 | | self.visit_u64(v as u64) +1142 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_u16` + --> serde-1.0.0/src/de/mod.rs:1149:5 + | +1149 | / fn visit_u16(self, v: u16) -> Result +1150 | | where +1151 | | E: Error, +1152 | | { +1153 | | self.visit_u64(v as u64) +1154 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_u32` + --> serde-1.0.0/src/de/mod.rs:1161:5 + | +1161 | / fn visit_u32(self, v: u32) -> Result +1162 | | where +1163 | | E: Error, +1164 | | { +1165 | | self.visit_u64(v as u64) +1166 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_u64` + --> serde-1.0.0/src/de/mod.rs:1171:5 + | +1171 | / fn visit_u64(self, v: u64) -> Result +1172 | | where +1173 | | E: Error, +1174 | | { +1175 | | Err(Error::invalid_type(Unexpected::Unsigned(v), &self)) +1176 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_f32` + --> serde-1.0.0/src/de/mod.rs:1183:5 + | +1183 | / fn visit_f32(self, v: f32) -> Result +1184 | | where +1185 | | E: Error, +1186 | | { +1187 | | self.visit_f64(v as f64) +1188 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_f64` + --> serde-1.0.0/src/de/mod.rs:1193:5 + | +1193 | / fn visit_f64(self, v: f64) -> Result +1194 | | where +1195 | | E: Error, +1196 | | { +1197 | | Err(Error::invalid_type(Unexpected::Float(v), &self)) +1198 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_char` + --> serde-1.0.0/src/de/mod.rs:1207:5 + | +1207 | / fn visit_char(self, v: char) -> Result +1208 | | where +1209 | | E: Error, +1210 | | { +1211 | | self.visit_str(utf8::encode(v).as_str()) +1212 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_str` + --> serde-1.0.0/src/de/mod.rs:1225:5 + | +1225 | / fn visit_str(self, v: &str) -> Result +1226 | | where +1227 | | E: Error, +1228 | | { +1229 | | Err(Error::invalid_type(Unexpected::Str(v), &self)) +1230 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_string` + --> serde-1.0.0/src/de/mod.rs:1266:5 + | +1266 | / fn visit_string(self, v: String) -> Result +1267 | | where +1268 | | E: Error, +1269 | | { +1270 | | self.visit_str(&v) +1271 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_unit` + --> serde-1.0.0/src/de/mod.rs:1356:5 + | +1356 | / fn visit_unit(self) -> Result +1357 | | where +1358 | | E: Error, +1359 | | { +1360 | | Err(Error::invalid_type(Unexpected::Unit, &self)) +1361 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_none` + --> serde-1.0.0/src/de/mod.rs:1335:5 + | +1335 | / fn visit_none(self) -> Result +1336 | | where +1337 | | E: Error, +1338 | | { +1339 | | Err(Error::invalid_type(Unexpected::Option, &self)) +1340 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_some` + --> serde-1.0.0/src/de/mod.rs:1345:5 + | +1345 | / fn visit_some(self, deserializer: D) -> Result +1346 | | where +1347 | | D: Deserializer<'de>, +1348 | | { +1349 | | let _ = deserializer; +1350 | | Err(Error::invalid_type(Unexpected::Option, &self)) +1351 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_newtype_struct` + --> serde-1.0.0/src/de/mod.rs:1369:5 + | +1369 | / fn visit_newtype_struct(self, deserializer: D) -> Result +1370 | | where +1371 | | D: Deserializer<'de>, +1372 | | { +1373 | | let _ = deserializer; +1374 | | Err(Error::invalid_type(Unexpected::NewtypeStruct, &self)) +1375 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_seq` + --> serde-1.0.0/src/de/mod.rs:1380:5 + | +1380 | / fn visit_seq(self, seq: A) -> Result +1381 | | where +1382 | | A: SeqAccess<'de>, +1383 | | { +1384 | | let _ = seq; +1385 | | Err(Error::invalid_type(Unexpected::Seq, &self)) +1386 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_map` + --> serde-1.0.0/src/de/mod.rs:1391:5 + | +1391 | / fn visit_map(self, map: A) -> Result +1392 | | where +1393 | | A: MapAccess<'de>, +1394 | | { +1395 | | let _ = map; +1396 | | Err(Error::invalid_type(Unexpected::Map, &self)) +1397 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_bytes` + --> serde-1.0.0/src/de/mod.rs:1284:5 + | +1284 | / fn visit_bytes(self, v: &[u8]) -> Result +1285 | | where +1286 | | E: Error, +1287 | | { +1288 | | let _ = v; +1289 | | Err(Error::invalid_type(Unexpected::Bytes(v), &self)) +1290 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_byte_buf` + --> serde-1.0.0/src/de/mod.rs:1325:5 + | +1325 | / fn visit_byte_buf(self, v: Vec) -> Result +1326 | | where +1327 | | E: Error, +1328 | | { +1329 | | self.visit_bytes(&v) +1330 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: path changes to `SeqVisitor` + --> serde-0.7.0/src/de/mod.rs:654:1 + | +654 | / pub trait SeqVisitor { +655 | | /// The error type that can be returned if some error occurs during deserialization. +656 | | type Error: Error; +657 | | +... | +670 | | } +671 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: path changes to `MapVisitor` + --> serde-0.7.0/src/de/mod.rs:699:1 + | +699 | / pub trait MapVisitor { +700 | | /// The error type that can be returned if some error occurs during deserialization. +701 | | type Error: Error; +702 | | +... | +742 | | } +743 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: path changes to `EnumVisitor` + --> serde-0.7.0/src/de/mod.rs:785:1 + | +785 | / pub trait EnumVisitor { +786 | | /// The value produced by this visitor. +787 | | type Value; +788 | | +... | +791 | | where V: VariantVisitor; +792 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: path changes to `VariantVisitor` + --> serde-0.7.0/src/de/mod.rs:798:1 + | +798 | / pub trait VariantVisitor { +799 | | /// The error type that can be returned if some error occurs during deserialization. +800 | | type Error: Error; +801 | | +... | +837 | | } +838 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: breaking changes in `impls` + --> serde-1.0.0/src/de/impls.rs:9:1 + | +9 | / use lib::*; +10 | | +11 | | use de::{Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess, +12 | | Visitor}; +... | +1602 | | } +1603 | | } + | |_^ + | + = warning: item made private (breaking) + +error: breaking changes in `UnitVisitor` + --> serde-1.0.0/src/de/impls.rs:24:1 + | +24 | struct UnitVisitor; + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: item made private (breaking) + +error: breaking changes in `BoolVisitor` + --> serde-1.0.0/src/de/impls.rs:52:1 + | +52 | struct BoolVisitor; + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: item made private (breaking) + +error: breaking changes in ` as old::de::Visitor>` + --> serde-0.7.0/src/de/impls.rs:135:1 + | +135 | / impl Visitor for PrimitiveVisitor +136 | | where T: Deserialize + FromPrimitive + str::FromStr +137 | | { +138 | | type Value = T; +... | +160 | | } +161 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::Visitor>` + --> serde-0.7.0/src/de/impls.rs:281:1 + | +281 | / impl< +282 | | T: Deserialize, +283 | | > Visitor for OptionVisitor { +284 | | type Value = Option; +... | +305 | | } +306 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::>` + --> serde-0.7.0/src/de/impls.rs:308:1 + | +308 | / impl Deserialize for Option where T: Deserialize { +309 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> +310 | | where D: Deserializer, +311 | | { +312 | | deserializer.deserialize_option(OptionVisitor { marker: PhantomData }) +313 | | } +314 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `PhantomDataVisitor` + --> serde-1.0.0/src/de/impls.rs:468:1 + | +468 | / struct PhantomDataVisitor { +469 | | marker: PhantomData, +470 | | } + | |_^ + | + = warning: item made private (breaking) + +error: breaking changes in ` as old::de::Visitor>` + --> serde-0.7.0/src/de/impls.rs:323:1 + | +323 | / impl Visitor for PhantomDataVisitor where T: Deserialize { +324 | | type Value = PhantomData; +325 | | +326 | | #[inline] +... | +331 | | } +332 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::>` + --> serde-0.7.0/src/de/impls.rs:334:1 + | +334 | / impl Deserialize for PhantomData where T: Deserialize { +335 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> +336 | | where D: Deserializer, +337 | | { +... | +340 | | } +341 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: path changes to `LinkedListVisitor` + --> serde-0.7.0/src/de/impls.rs:356:9 + | +356 | / pub struct $visitor_name { +357 | | marker: PhantomData, +358 | | } + | |_________^ + | + = warning: removed definition (breaking) + +error: breaking changes in ` as old::de::Visitor>` + --> serde-0.7.0/src/de/impls.rs:369:9 + | +369 | / impl Visitor for $visitor_name +370 | | where T: $($constraints +)*, +371 | | { +372 | | type Value = $ty; +... | +394 | | } +395 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::>` + --> serde-0.7.0/src/de/impls.rs:397:9 + | +397 | / impl Deserialize for $ty +398 | | where T: $($constraints +)*, +399 | | { +400 | | fn deserialize(deserializer: &mut D) -> Result<$ty, D::Error> +... | +404 | | } +405 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::Visitor>` + --> serde-0.7.0/src/de/impls.rs:488:1 + | +488 | / impl Visitor for ArrayVisitor0 where T: Deserialize + Default { +489 | | type Value = [T; 0]; +490 | | +491 | | #[inline] +... | +504 | | } +505 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::` + --> serde-0.7.0/src/de/impls.rs:507:1 + | +507 | / impl Deserialize for [T; 0] +508 | | where T: Deserialize + Default +509 | | { +510 | | fn deserialize(deserializer: &mut D) -> Result<[T; 0], D::Error> +... | +514 | | } +515 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::Visitor>` + --> serde-0.7.0/src/de/impls.rs:533:13 + | +533 | / impl Visitor for $visitor where T: Deserialize { +534 | | type Value = [T; $len]; +535 | | +536 | | #[inline] +... | +550 | | } +551 | | } + | |_____________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::` + --> serde-0.7.0/src/de/impls.rs:553:13 + | +553 | / impl Deserialize for [T; $len] +554 | | where T: Deserialize, +555 | | { +556 | | fn deserialize(deserializer: &mut D) -> Result<[T; $len], D::Error> +... | +560 | | } +561 | | } + | |_____________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `TupleVisitor10` + --> serde-1.0.0/src/de/impls.rs:725:13 + | +725 | / struct $visitor<$($name,)+> { +726 | | marker: PhantomData<($($name,)+)>, +727 | | } + | |_____________^ + | + = warning: item made private (breaking) + +error: breaking changes in `new` + --> serde-0.7.0/src/de/impls.rs:624:17 + | +624 | / pub fn new() -> Self { +625 | | $visitor { marker: PhantomData } +626 | | } + | |_________________^ + | + = warning: removed item in inherent impl (breaking) + +error: breaking changes in ` as old::de::Visitor>` + --> serde-0.7.0/src/de/impls.rs:630:13 + | +630 | / impl< +631 | | $($name: Deserialize,)+ +632 | | > Visitor for $visitor<$($name,)+> { +633 | | type Value = ($($name,)+); +... | +650 | | } +651 | | } + | |_____________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::` + --> serde-0.7.0/src/de/impls.rs:653:13 + | +653 | / impl< +654 | | $($name: Deserialize),+ +655 | | > Deserialize for ($($name,)+) { +656 | | #[inline] +... | +661 | | } +662 | | } + | |_____________^ + | + = warning: trait impl specialized or removed (breaking) + +error: path changes to `HashMapVisitor` + --> serde-0.7.0/src/de/impls.rs:695:9 + | +695 | / pub struct $visitor_name { +696 | | marker: PhantomData<$ty>, +697 | | } + | |_________^ + | + = warning: removed definition (breaking) + +error: breaking changes in ` as old::de::Visitor>` + --> serde-0.7.0/src/de/impls.rs:708:9 + | +708 | / impl Visitor for $visitor_name +709 | | where K: $($constraints +)*, +710 | | V: Deserialize, +711 | | { +... | +734 | | } +735 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::>` + --> serde-0.7.0/src/de/impls.rs:737:9 + | +737 | / impl Deserialize for $ty +738 | | where K: $($constraints +)*, +739 | | V: Deserialize, +740 | | { +... | +745 | | } +746 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::>` + --> serde-0.7.0/src/de/impls.rs:875:1 + | +875 | / impl Deserialize for Box { +876 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> +877 | | where D: Deserializer, +878 | | { +... | +881 | | } +882 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::>` + --> serde-0.7.0/src/de/impls.rs:884:1 + | +884 | / impl Deserialize for Arc { +885 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> +886 | | where D: Deserializer, +887 | | { +... | +890 | | } +891 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::>` + --> serde-0.7.0/src/de/impls.rs:893:1 + | +893 | / impl Deserialize for Rc { +894 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> +895 | | where D: Deserializer, +896 | | { +... | +899 | | } +900 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::>` + --> serde-0.7.0/src/de/impls.rs:902:1 + | +902 | / impl<'a, T: ?Sized> Deserialize for Cow<'a, T> where T: ToOwned, T::Owned: Deserialize, { +903 | | #[inline] +904 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> +905 | | where D: Deserializer, +... | +909 | | } +910 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::>` + --> serde-0.7.0/src/de/impls.rs:930:1 + | +930 | / impl Deserialize for Result where T: Deserialize, E: Deserialize { +931 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> +932 | | where D: Deserializer { +933 | | enum Field { +... | +1009 | | } +1010 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `>::deserialize::Field as old::Deserialize>` + --> serde-0.7.0/src/de/impls.rs:938:9 + | +938 | / impl Deserialize for Field { +939 | | #[inline] +940 | | fn deserialize(deserializer: &mut D) -> Result +941 | | where D: Deserializer +... | +979 | | } +980 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `<>::deserialize::Field as old::Deserialize>::deserialize::FieldVisitor as old::de::Visitor>` + --> serde-0.7.0/src/de/impls.rs:945:17 + | +945 | / impl ::de::Visitor for FieldVisitor { +946 | | type Value = Field; +947 | | +948 | | fn visit_usize(&mut self, value: usize) -> Result where E: Error { +... | +975 | | } +976 | | } + | |_________________^ + | + = warning: trait impl specialized or removed (breaking) + +error: path changes to `IgnoredAny` + --> serde-0.7.0/src/de/impls.rs:1016:1 + | +1016 | pub struct IgnoredAny; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: removed definition (breaking) + +error: breaking changes in `` + --> serde-0.7.0/src/de/impls.rs:1018:1 + | +1018 | / impl Deserialize for IgnoredAny { +1019 | | #[inline] +1020 | | fn deserialize(deserializer: &mut D) -> Result +1021 | | where D: Deserializer, +... | +1113 | | } +1114 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `<::deserialize::IgnoredAnyVisitor as old::de::Visitor>` + --> serde-0.7.0/src/de/impls.rs:1025:9 + | +1025 | / impl Visitor for IgnoredAnyVisitor { +1026 | | type Value = IgnoredAny; +1027 | | +1028 | | #[inline] +... | +1108 | | } +1109 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `Error` + --> serde-1.0.0/src/de/value.rs:50:1 + | +50 | / pub struct Error { +51 | | err: ErrorImpl, +52 | | } + | |_^ + | + = warning: item kind changed (breaking) + +error: path changes to `ValueDeserializer` + --> serde-0.7.0/src/de/value.rs:93:1 + | +93 | / pub trait ValueDeserializer { +94 | | /// The actual deserializer type. +95 | | type Deserializer: de::Deserializer; +96 | | +97 | | /// Convert this value into a deserializer. +98 | | fn into_deserializer(self) -> Self::Deserializer; +99 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: breaking changes in `UnitDeserializer` + --> serde-1.0.0/src/de/value.rs:121:1 + | +121 | / pub struct UnitDeserializer { +122 | | marker: PhantomData, +123 | | } + | |_^ + | +warning: variant with no public fields changed to a struct variant (breaking) + --> serde-1.0.0/src/de/value.rs:121:1 + | +121 | / pub struct UnitDeserializer { +122 | | marker: PhantomData, +123 | | } + | |_^ + +error: breaking changes in `I8Deserializer` + --> serde-1.0.0/src/de/value.rs:159:9 + | +159 | / pub struct $name { +160 | | value: $ty, +161 | | marker: PhantomData +162 | | } + | |_________^ + | +warning: variant with no public fields changed to a struct variant (breaking) + --> serde-1.0.0/src/de/value.rs:159:9 + | +159 | / pub struct $name { +160 | | value: $ty, +161 | | marker: PhantomData +162 | | } + | |_________^ + +error: breaking changes in `StrDeserializer` + --> serde-1.0.0/src/de/value.rs:288:1 + | +288 | / pub struct StrDeserializer<'a, E> { +289 | | value: &'a str, +290 | | marker: PhantomData, +291 | | } + | |_^ + | +warning: variant with no public fields changed to a struct variant (breaking) + --> serde-1.0.0/src/de/value.rs:288:1 + | +288 | / pub struct StrDeserializer<'a, E> { +289 | | value: &'a str, +290 | | marker: PhantomData, +291 | | } + | |_^ + +error: breaking changes in `StringDeserializer` + --> serde-1.0.0/src/de/value.rs:361:1 + | +361 | / pub struct StringDeserializer { +362 | | value: String, +363 | | marker: PhantomData, +364 | | } + | |_^ + | +warning: variant with no public fields changed to a struct variant (breaking) + --> serde-1.0.0/src/de/value.rs:361:1 + | +361 | / pub struct StringDeserializer { +362 | | value: String, +363 | | marker: PhantomData, +364 | | } + | |_^ + +error: breaking changes in `SeqDeserializer` + --> serde-1.0.0/src/de/value.rs:515:1 + | +515 | / pub struct SeqDeserializer { +516 | | iter: iter::Fuse, +517 | | count: usize, +518 | | marker: PhantomData, +519 | | } + | |_^ + | +warning: variant field removed from variant with private fields (breaking) + --> serde-0.7.0/src/de/value.rs:298:5 + | +298 | len: usize, + | ^^^^^^^^^^ +warning: variant field added to variant with private fields (breaking) + --> serde-1.0.0/src/de/value.rs:517:5 + | +517 | count: usize, + | ^^^^^^^^^^^^ + +error: breaking changes in `new` + --> serde-0.7.0/src/de/value.rs:306:5 + | +306 | / pub fn new(iter: I, len: usize) -> Self { +307 | | SeqDeserializer { +308 | | iter: iter, +309 | | len: len, +310 | | marker: PhantomData, +311 | | } +312 | | } + | |_____^ + | + = warning: removed item in inherent impl (breaking) + +error: breaking changes in ` as old::Deserializer>` + --> serde-0.7.0/src/de/value.rs:315:1 + | +315 | / impl de::Deserializer for SeqDeserializer +316 | | where I: Iterator, +317 | | T: ValueDeserializer, +318 | | E: de::Error, +... | +326 | | } +327 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: path changes to `SeqVisitorDeserializer` + --> serde-0.7.0/src/de/value.rs:403:1 + | +403 | / pub struct SeqVisitorDeserializer { +404 | | visitor: V_, +405 | | marker: PhantomData, +406 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: breaking changes in ` as old::Deserializer>` + --> serde-0.7.0/src/de/value.rs:421:1 + | +421 | / impl de::Deserializer for SeqVisitorDeserializer +422 | | where V_: de::SeqVisitor, +423 | | E: de::Error, +424 | | { +... | +429 | | } +430 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `MapDeserializer` + --> serde-1.0.0/src/de/value.rs:698:1 + | +698 | / pub struct MapDeserializer<'de, I, E> +699 | | where +700 | | I: Iterator, +701 | | I::Item: private::Pair, +... | +707 | | error: PhantomData, +708 | | } + | |_^ + | + = warning: region parameter added (breaking) + = warning: type parameter removed (breaking) + = warning: type parameter removed (breaking) +warning: variant field removed from variant with private fields (breaking) + --> serde-0.7.0/src/de/value.rs:443:5 + | +443 | len: usize, + | ^^^^^^^^^^ +warning: variant field removed from variant with private fields (breaking) + --> serde-0.7.0/src/de/value.rs:444:5 + | +444 | marker: PhantomData, + | ^^^^^^^^^^^^^^^^^^^^^^ +warning: variant field added to variant with private fields (breaking) + --> serde-1.0.0/src/de/value.rs:705:5 + | +705 | count: usize, + | ^^^^^^^^^^^^ +warning: variant field added to variant with private fields (breaking) + --> serde-1.0.0/src/de/value.rs:707:5 + | +707 | error: PhantomData, + | ^^^^^^^^^^^^^^^^^^^^^ +warning: variant field added to variant with private fields (breaking) + --> serde-1.0.0/src/de/value.rs:706:5 + | +706 | lifetime: PhantomData<&'de ()>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: breaking changes in `new` + --> serde-0.7.0/src/de/value.rs:454:5 + | +454 | / pub fn new(iter: I, len: usize) -> Self { +455 | | MapDeserializer { +456 | | iter: iter, +457 | | value: None, +... | +460 | | } +461 | | } + | |_____^ + | + = warning: removed item in inherent impl (breaking) + +error: breaking changes in ` as old::Deserializer>` + --> serde-0.7.0/src/de/value.rs:464:1 + | +464 | / impl de::Deserializer for MapDeserializer +465 | | where I: Iterator, +466 | | K: ValueDeserializer, +467 | | V: ValueDeserializer, +... | +476 | | } +477 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: path changes to `MapVisitorDeserializer` + --> serde-0.7.0/src/de/value.rs:559:1 + | +559 | / pub struct MapVisitorDeserializer { +560 | | visitor: V_, +561 | | marker: PhantomData, +562 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: breaking changes in ` as old::Deserializer>` + --> serde-0.7.0/src/de/value.rs:577:1 + | +577 | / impl de::Deserializer for MapVisitorDeserializer +578 | | where V_: de::MapVisitor, +579 | | E: de::Error, +580 | | { +... | +585 | | } +586 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: path changes to `BytesDeserializer` + --> serde-0.7.0/src/de/value.rs:601:1 + | +601 | pub struct BytesDeserializer<'a, E> (Option<&'a [u8]>, PhantomData); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: removed definition (breaking) + +error: breaking changes in ` as old::Deserializer>` + --> serde-0.7.0/src/de/value.rs:603:1 + | +603 | / impl<'a, E> de::Deserializer for BytesDeserializer<'a, E> +604 | | where E: de::Error +605 | | { +606 | | type Error = E; +... | +615 | | } +616 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: path changes to `ByteBufDeserializer` + --> serde-0.7.0/src/de/value.rs:632:1 + | +632 | pub struct ByteBufDeserializer(Option>, PhantomData); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: removed definition (breaking) + +error: breaking changes in ` as old::Deserializer>` + --> serde-0.7.0/src/de/value.rs:634:1 + | +634 | / impl de::Deserializer for ByteBufDeserializer +635 | | where E: de::Error, +636 | | { +637 | | type Error = E; +... | +646 | | } +647 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: path changes to `iter` + --> serde-0.7.0/src/iter.rs:1:1 + | +1 | / //! Module that contains helper iterators. +2 | | +3 | | use std::io; +4 | | use std::iter::Peekable; +... | +60 | | } +61 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: breaking changes in `Error` + --> serde-1.0.0/src/ser/mod.rs:130:9 + | +130 | / pub trait Error: Sized $(+ $($supertrait)::+)* { +131 | | /// Used when a [`Serialize`] implementation encounters any error +132 | | /// while serializing a type. +133 | | /// +... | +167 | | T: Display; +168 | | } + | |_________^ + | +warning: removed defaulted item from trait (breaking) + --> serde-0.7.0/src/ser/mod.rs:16:5 + | +16 | / fn invalid_value(msg: &str) -> Self { +17 | | Error::custom(format!("invalid value: {}", msg)) +18 | | } + | |_____^ + +error: breaking changes in `custom` + --> serde-1.0.0/src/ser/mod.rs:165:13 + | +165 | / fn custom(msg: T) -> Self +166 | | where +167 | | T: Display; + | |___________________________^ + | + = warning: added bound: `T: std::fmt::Display` (breaking) + = note: removed bound: `std::string::String: std::convert::From` (technically breaking) + +error: breaking changes in `serialize` + --> serde-1.0.0/src/ser/mod.rs:236:5 + | +236 | / fn serialize(&self, serializer: S) -> Result +237 | | where +238 | | S: Serializer; + | |______________________^ + | + = warning: type error: expected (), found associated type (breaking) + +error: breaking changes in `Serializer` + --> serde-1.0.0/src/ser/mod.rs:310:1 + | +310 | / pub trait Serializer: Sized { +311 | | /// The output type produced by this `Serializer` during successful +312 | | /// serialization. Most serializers that produce text or binary output +313 | | /// should set `Ok = ()` and serialize into an [`io::Write`] or buffer +... | +1364 | | T: Display; +1365 | | } + | |_^ + | +warning: added item to trait (breaking) + --> serde-1.0.0/src/ser/mod.rs:319:5 + | +319 | type Ok; + | ^^^^^^^^ +warning: added item to trait (breaking) + --> serde-1.0.0/src/ser/mod.rs:328:5 + | +328 | type SerializeSeq: SerializeSeq; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: added item to trait (breaking) + --> serde-1.0.0/src/ser/mod.rs:334:5 + | +334 | type SerializeTuple: SerializeTuple; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: added item to trait (breaking) + --> serde-1.0.0/src/ser/mod.rs:340:5 + | +340 | type SerializeTupleStruct: SerializeTupleStruct; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: added item to trait (breaking) + --> serde-1.0.0/src/ser/mod.rs:346:5 + | +346 | type SerializeTupleVariant: SerializeTupleVariant; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: added item to trait (breaking) + --> serde-1.0.0/src/ser/mod.rs:352:5 + | +352 | type SerializeMap: SerializeMap; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: added item to trait (breaking) + --> serde-1.0.0/src/ser/mod.rs:358:5 + | +358 | type SerializeStruct: SerializeStruct; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: added item to trait (breaking) + --> serde-1.0.0/src/ser/mod.rs:364:5 + | +364 | type SerializeStructVariant: SerializeStructVariant; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: added defaulted item to trait (technically breaking) + --> serde-1.0.0/src/ser/mod.rs:1243:5 + | +1243 | / fn collect_seq(self, iter: I) -> Result +1244 | | where +1245 | | I: IntoIterator, +1246 | | ::Item: Serialize, +... | +1253 | | serializer.end() +1254 | | } + | |_____^ +note: added defaulted item to trait (technically breaking) + --> serde-1.0.0/src/ser/mod.rs:1281:5 + | +1281 | / fn collect_map(self, iter: I) -> Result +1282 | | where +1283 | | K: Serialize, +1284 | | V: Serialize, +... | +1292 | | serializer.end() +1293 | | } + | |_____^ +note: added defaulted item to trait (technically breaking) + --> serde-1.0.0/src/ser/mod.rs:1325:5 + | +1325 | / fn collect_str(self, value: &T) -> Result +1326 | | where +1327 | | T: Display, +1328 | | { +... | +1332 | | self.serialize_str(&string) +1333 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> serde-0.7.0/src/ser/mod.rs:43:5 + | +43 | / fn serialize_isize(&mut self, v: isize) -> Result<(), Self::Error> { +44 | | self.serialize_i64(v as i64) +45 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> serde-0.7.0/src/ser/mod.rs:75:5 + | +75 | / fn serialize_usize(&mut self, v: usize) -> Result<(), Self::Error> { +76 | | self.serialize_u64(v as u64) +77 | | } + | |_____^ +warning: removed item from trait (breaking) + --> serde-0.7.0/src/ser/mod.rs:200:5 + | +200 | / fn serialize_seq_elt(&mut self, value: T) -> Result<(), Self::Error> +201 | | where T: Serialize; + | |___________________________^ +warning: removed defaulted item from trait (breaking) + --> serde-0.7.0/src/ser/mod.rs:217:5 + | +217 | / fn serialize_tuple_elt(&mut self, value: T) -> Result<(), Self::Error> +218 | | where T: Serialize +219 | | { +220 | | self.serialize_seq_elt(value) +221 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> serde-0.7.0/src/ser/mod.rs:227:5 + | +227 | / fn serialize_fixed_size_array(&mut self, visitor: V) -> Result<(), Self::Error> +228 | | where V: SeqVisitor, +229 | | { +230 | | self.serialize_seq(visitor) +231 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> serde-0.7.0/src/ser/mod.rs:249:5 + | +249 | / fn serialize_tuple_struct_elt(&mut self, value: T) -> Result<(), Self::Error> +250 | | where T: Serialize +251 | | { +252 | | self.serialize_tuple_elt(value) +253 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> serde-0.7.0/src/ser/mod.rs:273:5 + | +273 | / fn serialize_tuple_variant_elt(&mut self, value: T) -> Result<(), Self::Error> +274 | | where T: Serialize +275 | | { +276 | | self.serialize_tuple_struct_elt(value) +277 | | } + | |_____^ +warning: removed item from trait (breaking) + --> serde-0.7.0/src/ser/mod.rs:287:5 + | +287 | / fn serialize_map_elt(&mut self, key: K, value: V) -> Result<(), Self::Error> +288 | | where K: Serialize, +289 | | V: Serialize; + | |___________________________^ +warning: removed defaulted item from trait (breaking) + --> serde-0.7.0/src/ser/mod.rs:307:5 + | +307 | / fn serialize_struct_elt(&mut self, +308 | | key: &'static str, +309 | | value: V) -> Result<(), Self::Error> +310 | | where V: Serialize, +311 | | { +312 | | self.serialize_map_elt(key, value) +313 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> serde-0.7.0/src/ser/mod.rs:333:5 + | +333 | / fn serialize_struct_variant_elt(&mut self, +334 | | key: &'static str, +335 | | value: V) -> Result<(), Self::Error> +336 | | where V: Serialize, +337 | | { +338 | | self.serialize_struct_elt(key, value) +339 | | } + | |_____^ + +error: breaking changes in `serialize_bool` + --> serde-1.0.0/src/ser/mod.rs:386:5 + | +386 | fn serialize_bool(self, v: bool) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_i8` + --> serde-1.0.0/src/ser/mod.rs:412:5 + | +412 | fn serialize_i8(self, v: i8) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_i16` + --> serde-1.0.0/src/ser/mod.rs:438:5 + | +438 | fn serialize_i16(self, v: i16) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_i32` + --> serde-1.0.0/src/ser/mod.rs:464:5 + | +464 | fn serialize_i32(self, v: i32) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_i64` + --> serde-1.0.0/src/ser/mod.rs:486:5 + | +486 | fn serialize_i64(self, v: i64) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_u8` + --> serde-1.0.0/src/ser/mod.rs:512:5 + | +512 | fn serialize_u8(self, v: u8) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_u16` + --> serde-1.0.0/src/ser/mod.rs:538:5 + | +538 | fn serialize_u16(self, v: u16) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_u32` + --> serde-1.0.0/src/ser/mod.rs:564:5 + | +564 | fn serialize_u32(self, v: u32) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_u64` + --> serde-1.0.0/src/ser/mod.rs:586:5 + | +586 | fn serialize_u64(self, v: u64) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_f32` + --> serde-1.0.0/src/ser/mod.rs:612:5 + | +612 | fn serialize_f32(self, v: f32) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_f64` + --> serde-1.0.0/src/ser/mod.rs:634:5 + | +634 | fn serialize_f64(self, v: f64) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_char` + --> serde-1.0.0/src/ser/mod.rs:659:5 + | +659 | fn serialize_char(self, v: char) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_str` + --> serde-1.0.0/src/ser/mod.rs:681:5 + | +681 | fn serialize_str(self, v: &str) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_bytes` + --> serde-1.0.0/src/ser/mod.rs:721:5 + | +721 | fn serialize_bytes(self, v: &[u8]) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_unit` + --> serde-1.0.0/src/ser/mod.rs:811:5 + | +811 | fn serialize_unit(self) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_unit_struct` + --> serde-1.0.0/src/ser/mod.rs:830:5 + | +830 | fn serialize_unit_struct(self, name: &'static str) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_unit_variant` + --> serde-1.0.0/src/ser/mod.rs:857:5 + | +857 | / fn serialize_unit_variant( +858 | | self, +859 | | name: &'static str, +860 | | variant_index: u32, +861 | | variant: &'static str, +862 | | ) -> Result; + | |_______________________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_newtype_struct` + --> serde-1.0.0/src/ser/mod.rs:883:5 + | +883 | / fn serialize_newtype_struct( +884 | | self, +885 | | name: &'static str, +886 | | value: &T, +887 | | ) -> Result +888 | | where +889 | | T: Serialize; + | |_____________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_newtype_variant` + --> serde-1.0.0/src/ser/mod.rs:916:5 + | +916 | / fn serialize_newtype_variant( +917 | | self, +918 | | name: &'static str, +919 | | variant_index: u32, +... | +923 | | where +924 | | T: Serialize; + | |_____________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_none` + --> serde-1.0.0/src/ser/mod.rs:754:5 + | +754 | fn serialize_none(self) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_some` + --> serde-1.0.0/src/ser/mod.rs:787:5 + | +787 | / fn serialize_some(self, value: &T) -> Result +788 | | where +789 | | T: Serialize; + | |_____________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_seq` + --> serde-1.0.0/src/ser/mod.rs:970:5 + | +970 | fn serialize_seq(self, len: Option) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type parameter removed (breaking) + +error: breaking changes in `serialize_tuple` + --> serde-1.0.0/src/ser/mod.rs:1023:5 + | +1023 | fn serialize_tuple(self, len: usize) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type parameter removed (breaking) + +error: breaking changes in `serialize_tuple_struct` + --> serde-1.0.0/src/ser/mod.rs:1049:5 + | +1049 | / fn serialize_tuple_struct( +1050 | | self, +1051 | | name: &'static str, +1052 | | len: usize, +1053 | | ) -> Result; + | |_________________________________________________________^ + | + = warning: type parameter removed (breaking) + +error: breaking changes in `serialize_tuple_variant` + --> serde-1.0.0/src/ser/mod.rs:1093:5 + | +1093 | / fn serialize_tuple_variant( +1094 | | self, +1095 | | name: &'static str, +1096 | | variant_index: u32, +1097 | | variant: &'static str, +1098 | | len: usize, +1099 | | ) -> Result; + | |__________________________________________________________^ + | + = warning: type parameter removed (breaking) + +error: breaking changes in `serialize_map` + --> serde-1.0.0/src/ser/mod.rs:1145:5 + | +1145 | fn serialize_map(self, len: Option) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type parameter removed (breaking) + +error: breaking changes in `serialize_struct` + --> serde-1.0.0/src/ser/mod.rs:1175:5 + | +1175 | / fn serialize_struct( +1176 | | self, +1177 | | name: &'static str, +1178 | | len: usize, +1179 | | ) -> Result; + | |____________________________________________________^ + | + = warning: type parameter removed (breaking) + +error: breaking changes in `serialize_struct_variant` + --> serde-1.0.0/src/ser/mod.rs:1212:5 + | +1212 | / fn serialize_struct_variant( +1213 | | self, +1214 | | name: &'static str, +1215 | | variant_index: u32, +1216 | | variant: &'static str, +1217 | | len: usize, +1218 | | ) -> Result; + | |___________________________________________________________^ + | + = warning: type parameter removed (breaking) + +error: path changes to `SeqVisitor` + --> serde-0.7.0/src/ser/mod.rs:344:1 + | +344 | / pub trait SeqVisitor { +345 | | /// Serializes a sequence item in the serializer. +346 | | /// +347 | | /// This returns `Ok(Some(()))` when there are more items to serialize, or `Ok(None)` when +... | +356 | | } +357 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: path changes to `MapVisitor` + --> serde-0.7.0/src/ser/mod.rs:361:1 + | +361 | / pub trait MapVisitor { +362 | | /// Serializes a map item in the serializer. +363 | | /// +364 | | /// This returns `Ok(Some(()))` when there are more items to serialize, or `Ok(None)` when +... | +373 | | } +374 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: breaking changes in `impls` + --> serde-1.0.0/src/ser/impls.rs:9:1 + | +9 | / use lib::*; +10 | | +11 | | use ser::{Serialize, SerializeTuple, Serializer}; +12 | | +... | +602 | | } +603 | | } + | |_^ + | + = warning: item made private (breaking) + +error: path changes to `SeqIteratorVisitor` + --> serde-0.7.0/src/ser/impls.rs:157:1 + | +157 | / pub struct SeqIteratorVisitor { +158 | | iter: Iter, +159 | | len: Option, +160 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: path changes to `TupleVisitor2` + --> serde-0.7.0/src/ser/impls.rs:377:13 + | +377 | / pub struct $TupleVisitor<'a, $($T: 'a),+> { +378 | | tuple: &'a ($($T,)+), +379 | | state: u8, +380 | | } + | |_____________^ + | + = warning: removed definition (breaking) + +error: path changes to `MapIteratorVisitor` + --> serde-0.7.0/src/ser/impls.rs:557:1 + | +557 | / pub struct MapIteratorVisitor { +558 | | iter: Iter, +559 | | len: Option, +560 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: breaking changes in `old::ser::impls::>` + --> serde-0.7.0/src/ser/impls.rs:654:1 + | +654 | / impl Serialize for Rc where T: Serialize, { +655 | | #[inline] +656 | | fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> +657 | | where S: Serializer, +... | +660 | | } +661 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::ser::impls::>` + --> serde-0.7.0/src/ser/impls.rs:663:1 + | +663 | / impl Serialize for Arc where T: Serialize, { +664 | | #[inline] +665 | | fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> +666 | | where S: Serializer, +... | +669 | | } +670 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + diff --git a/src/tools/semverver/tests/full_cases/serde-1.0.0-1.0.8 b/src/tools/semverver/tests/full_cases/serde-1.0.0-1.0.8 new file mode 100644 index 0000000000000..b8971ff445623 --- /dev/null +++ b/src/tools/semverver/tests/full_cases/serde-1.0.0-1.0.8 @@ -0,0 +1,1305 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: path changes to `BorrowedStrDeserializer` + --> serde-1.0.8/src/de/value.rs:361:1 + | +361 | / pub struct BorrowedStrDeserializer<'de, E> { +362 | | value: &'de str, +363 | | marker: PhantomData, +364 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.8/src/de/value.rs:376:1 + | +376 | / impl<'de, E> de::Deserializer<'de> for BorrowedStrDeserializer<'de, E> +377 | | where +378 | | E: de::Error, +379 | | { +... | +407 | | } +408 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::EnumAccess<'de>>` + --> serde-1.0.8/src/de/value.rs:410:1 + | +410 | / impl<'de, E> de::EnumAccess<'de> for BorrowedStrDeserializer<'de, E> +411 | | where +412 | | E: de::Error, +413 | | { +... | +422 | | } +423 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: path changes to `BorrowedBytesDeserializer` + --> serde-1.0.8/src/de/value.rs:585:1 + | +585 | / pub struct BorrowedBytesDeserializer<'de, E> { +586 | | value: &'de [u8], +587 | | marker: PhantomData, +588 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.8/src/de/value.rs:600:1 + | +600 | / impl<'de, E> de::Deserializer<'de> for BorrowedBytesDeserializer<'de, E> +601 | | where +602 | | E: de::Error, +603 | | { +... | +617 | | } +618 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for i8>::deserialize::PrimitiveVisitor as new::de::Visitor<'de>>` + --> serde-1.0.8/src/de/impls.rs:117:17 + | +117 | / impl<'de> Visitor<'de> for PrimitiveVisitor { +118 | | type Value = $ty; +119 | | +120 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +126 | | )* +127 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::collections::VecDeque>::deserialize::SeqVisitor as new::de::Visitor<'de>>` + --> serde-1.0.8/src/de/impls.rs:522:17 + | +522 | / impl<'de, T $(, $typaram)*> Visitor<'de> for SeqVisitor +523 | | where +524 | | T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*, +525 | | $($typaram: $bound1 $(+ $bound2)*,)* +... | +545 | | } +546 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::collections::BTreeMap>::deserialize::MapVisitor as new::de::Visitor<'de>>` + --> serde-1.0.8/src/de/impls.rs:815:17 + | +815 | / impl<'de, K, V $(, $typaram)*> Visitor<'de> for MapVisitor +816 | | where +817 | | K: Deserialize<'de> $(+ $kbound1 $(+ $kbound2)*)*, +818 | | V: Deserialize<'de>, +... | +839 | | } +840 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> serde-1.0.8/src/de/impls.rs:904:1 + | +904 | / impl<'a> Visitor<'a> for PathVisitor { +905 | | type Value = &'a Path; +906 | | +907 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +925 | | } +926 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for &'a std::path::Path>` + --> serde-1.0.8/src/de/impls.rs:929:1 + | +929 | / impl<'de: 'a, 'a> Deserialize<'de> for &'a Path { +930 | | fn deserialize(deserializer: D) -> Result +931 | | where +932 | | D: Deserializer<'de>, +... | +935 | | } +936 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `<>::deserialize::KindVisitor as new::de::Visitor<'de>>` + --> serde-1.0.8/src/de/impls.rs:997:9 + | +997 | / impl<'de> Visitor<'de> for KindVisitor { +998 | | type Value = OsStringKind; +999 | | +1000 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1040 | | } +1041 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::time::Duration>::deserialize::Field as new::Deserialize<'de>>` + --> serde-1.0.8/src/de/impls.rs:1254:9 + | +1254 | / impl<'de> Deserialize<'de> for Field { +1255 | | fn deserialize(deserializer: D) -> Result +1256 | | where +1257 | | D: Deserializer<'de>, +... | +1295 | | } +1296 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `< for std::time::Duration>::deserialize::Field as new::Deserialize<'de>>::deserialize::FieldVisitor as new::de::Visitor<'de>>` + --> serde-1.0.8/src/de/impls.rs:1261:17 + | +1261 | / impl<'de> Visitor<'de> for FieldVisitor { +1262 | | type Value = Field; +1263 | | +1264 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1291 | | } +1292 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::time::Duration>::deserialize::DurationVisitor as new::de::Visitor<'de>>` + --> serde-1.0.8/src/de/impls.rs:1300:9 + | +1300 | / impl<'de> Visitor<'de> for DurationVisitor { +1301 | | type Value = Duration; +1302 | | +1303 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1357 | | } +1358 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::ops::Range>::deserialize::Field as new::Deserialize<'de>>` + --> serde-1.0.8/src/de/impls.rs:1393:9 + | +1393 | / impl<'de> Deserialize<'de> for Field { +1394 | | fn deserialize(deserializer: D) -> Result +1395 | | where +1396 | | D: Deserializer<'de>, +... | +1434 | | } +1435 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `< for std::ops::Range>::deserialize::Field as new::Deserialize<'de>>::deserialize::FieldVisitor as new::de::Visitor<'de>>` + --> serde-1.0.8/src/de/impls.rs:1400:17 + | +1400 | / impl<'de> Visitor<'de> for FieldVisitor { +1401 | | type Value = Field; +1402 | | +1403 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1430 | | } +1431 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::ops::Range>::deserialize::RangeVisitor as new::de::Visitor<'de>>` + --> serde-1.0.8/src/de/impls.rs:1441:9 + | +1441 | / impl<'de, Idx> Visitor<'de> for RangeVisitor +1442 | | where +1443 | | Idx: Deserialize<'de>, +1444 | | { +... | +1501 | | } +1502 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::result::Result>::deserialize::Field as new::Deserialize<'de>>` + --> serde-1.0.8/src/de/impls.rs:1553:9 + | +1553 | / impl<'de> Deserialize<'de> for Field { +1554 | | #[inline] +1555 | | fn deserialize(deserializer: D) -> Result +1556 | | where +... | +1612 | | } +1613 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `< for std::result::Result>::deserialize::Field as new::Deserialize<'de>>::deserialize::FieldVisitor as new::de::Visitor<'de>>` + --> serde-1.0.8/src/de/impls.rs:1561:17 + | +1561 | / impl<'de> Visitor<'de> for FieldVisitor { +1562 | | type Value = Field; +1563 | | +1564 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1608 | | } +1609 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::result::Result>::deserialize::ResultVisitor as new::de::Visitor<'de>>` + --> serde-1.0.8/src/de/impls.rs:1617:9 + | +1617 | / impl<'de, T, E> Visitor<'de> for ResultVisitor +1618 | | where +1619 | | T: Deserialize<'de>, +1620 | | E: Deserialize<'de>, +... | +1636 | | } +1637 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.8/src/private/de.rs:31:5 + | +31 | / impl<'de, E> Deserializer<'de> for MissingFieldDeserializer +32 | | where +33 | | E: Error, +34 | | { +... | +55 | | } +56 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> serde-1.0.8/src/private/de.rs:69:5 + | +69 | / impl<'a> Visitor<'a> for CowStrVisitor { +70 | | type Value = Cow<'a, str>; +71 | | +72 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +125 | | } +126 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> serde-1.0.8/src/private/de.rs:138:5 + | +138 | / impl<'a> Visitor<'a> for CowBytesVisitor { +139 | | type Value = Cow<'a, [u8]>; +140 | | +141 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +185 | | } +186 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new` + --> serde-1.0.8/src/private/de.rs:806:9 + | +806 | / pub fn new(name: &'static str) -> Self { +807 | | TaggedContentVisitor { +808 | | tag_name: name, +809 | | value: PhantomData, +810 | | } +811 | | } + | |_________^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in ` as new::de::DeserializeSeed<'de>>` + --> serde-1.0.8/src/private/de.rs:814:5 + | +814 | / impl<'de, T> DeserializeSeed<'de> for TaggedContentVisitor<'de, T> +815 | | where +816 | | T: Deserialize<'de>, +817 | | { +... | +827 | | } +828 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::Visitor<'de>>` + --> serde-1.0.8/src/private/de.rs:830:5 + | +830 | / impl<'de, T> Visitor<'de> for TaggedContentVisitor<'de, T> +831 | | where +832 | | T: Deserialize<'de>, +833 | | { +... | +872 | | } +873 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: path changes to `TagContentOtherField` + --> serde-1.0.8/src/private/de.rs:925:5 + | +925 | / pub enum TagContentOtherField { +926 | | Tag, +927 | | Content, +928 | | Other, +929 | | } + | |_____^ + | +note: added path (technically breaking) + --> serde-1.0.8/src/private/de.rs:19:25 + | +19 | TagContentOtherField, TagContentOtherFieldVisitor, + | ^^^^^^^^^^^^^^^^^^^^ + +warning: path changes to `TagContentOtherFieldVisitor` + --> serde-1.0.8/src/private/de.rs:932:5 + | +932 | / pub struct TagContentOtherFieldVisitor { +933 | | pub tag: &'static str, +934 | | pub content: &'static str, +935 | | } + | |_____^ + | +note: added path (technically breaking) + --> serde-1.0.8/src/private/de.rs:19:47 + | +19 | TagContentOtherField, TagContentOtherFieldVisitor, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: technically breaking changes in `>` + --> serde-1.0.8/src/private/de.rs:937:5 + | +937 | / impl<'de> DeserializeSeed<'de> for TagContentOtherFieldVisitor { +938 | | type Value = TagContentOtherField; +939 | | +940 | | fn deserialize(self, deserializer: D) -> Result +... | +945 | | } +946 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> serde-1.0.8/src/private/de.rs:948:5 + | +948 | / impl<'de> Visitor<'de> for TagContentOtherFieldVisitor { +949 | | type Value = TagContentOtherField; +950 | | +951 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +966 | | } +967 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.8/src/private/de.rs:977:5 + | +977 | / impl<'de, E> Deserializer<'de> for ContentDeserializer<'de, E> +978 | | where +979 | | E: de::Error, +980 | | { +... | +1104 | | } +1105 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new` + --> serde-1.0.8/src/private/de.rs:1109:9 + | +1109 | / pub fn new(content: Content<'de>) -> Self { +1110 | | ContentDeserializer { +1111 | | content: content, +1112 | | err: PhantomData, +1113 | | } +1114 | | } + | |_________^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in ` as new::de::EnumAccess<'de>>` + --> serde-1.0.8/src/private/de.rs:1126:5 + | +1126 | / impl<'de, E> de::EnumAccess<'de> for EnumDeserializer<'de, E> +1127 | | where +1128 | | E: de::Error, +1129 | | { +... | +1143 | | } +1144 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::VariantAccess<'de>>` + --> serde-1.0.8/src/private/de.rs:1154:5 + | +1154 | / impl<'de, E> de::VariantAccess<'de> for VariantDeserializer<'de, E> +1155 | | where +1156 | | E: de::Error, +1157 | | { +... | +1207 | | } +1208 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.8/src/private/de.rs:1230:5 + | +1230 | / impl<'de, E> de::Deserializer<'de> for SeqDeserializer<'de, E> +1231 | | where +1232 | | E: de::Error, +1233 | | { +... | +1259 | | } +1260 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::SeqAccess<'de>>` + --> serde-1.0.8/src/private/de.rs:1262:5 + | +1262 | / impl<'de, E> de::SeqAccess<'de> for SeqDeserializer<'de, E> +1263 | | where +1264 | | E: de::Error, +1265 | | { +... | +1283 | | } +1284 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::MapAccess<'de>>` + --> serde-1.0.8/src/private/de.rs:1308:5 + | +1308 | / impl<'de, E> de::MapAccess<'de> for MapDeserializer<'de, E> +1309 | | where +1310 | | E: de::Error, +1311 | | { +... | +1339 | | } +1340 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.8/src/private/de.rs:1342:5 + | +1342 | / impl<'de, E> de::Deserializer<'de> for MapDeserializer<'de, E> +1343 | | where +1344 | | E: de::Error, +1345 | | { +... | +1360 | | } +1361 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.8/src/private/de.rs:1371:5 + | +1371 | / impl<'de, 'a, E> Deserializer<'de> for ContentRefDeserializer<'a, 'de, E> +1372 | | where +1373 | | E: de::Error, +1374 | | { +... | +1498 | | } +1499 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new` + --> serde-1.0.8/src/private/de.rs:1503:9 + | +1503 | / pub fn new(content: &'a Content<'de>) -> Self { +1504 | | ContentRefDeserializer { +1505 | | content: content, +1506 | | err: PhantomData, +1507 | | } +1508 | | } + | |_________^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in ` as new::de::EnumAccess<'de>>` + --> serde-1.0.8/src/private/de.rs:1520:5 + | +1520 | / impl<'de, 'a, E> de::EnumAccess<'de> for EnumRefDeserializer<'a, 'de, E> +1521 | | where +1522 | | E: de::Error, +1523 | | { +... | +1537 | | } +1538 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::VariantAccess<'de>>` + --> serde-1.0.8/src/private/de.rs:1548:5 + | +1548 | / impl<'de, 'a, E> de::VariantAccess<'de> for VariantRefDeserializer<'a, 'de, E> +1549 | | where +1550 | | E: de::Error, +1551 | | { +... | +1601 | | } +1602 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.8/src/private/de.rs:1624:5 + | +1624 | / impl<'de, 'a, E> de::Deserializer<'de> for SeqRefDeserializer<'a, 'de, E> +1625 | | where +1626 | | E: de::Error, +1627 | | { +... | +1653 | | } +1654 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::SeqAccess<'de>>` + --> serde-1.0.8/src/private/de.rs:1656:5 + | +1656 | / impl<'de, 'a, E> de::SeqAccess<'de> for SeqRefDeserializer<'a, 'de, E> +1657 | | where +1658 | | E: de::Error, +1659 | | { +... | +1677 | | } +1678 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::MapAccess<'de>>` + --> serde-1.0.8/src/private/de.rs:1702:5 + | +1702 | / impl<'de, 'a, E> de::MapAccess<'de> for MapRefDeserializer<'a, 'de, E> +1703 | | where +1704 | | E: de::Error, +1705 | | { +... | +1734 | | } +1735 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> serde-1.0.8/src/private/de.rs:1737:5 + | +1737 | / impl<'de, 'a, E> de::Deserializer<'de> for MapRefDeserializer<'a, 'de, E> +1738 | | where +1739 | | E: de::Error, +1740 | | { +... | +1755 | | } +1756 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::IntoDeserializer<'de, E>>` + --> serde-1.0.8/src/private/de.rs:1758:5 + | +1758 | / impl<'de, E> de::IntoDeserializer<'de, E> for ContentDeserializer<'de, E> +1759 | | where +1760 | | E: de::Error, +1761 | | { +... | +1766 | | } +1767 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::IntoDeserializer<'de, E>>` + --> serde-1.0.8/src/private/de.rs:1769:5 + | +1769 | / impl<'de, 'a, E> de::IntoDeserializer<'de, E> for ContentRefDeserializer<'a, 'de, E> +1770 | | where +1771 | | E: de::Error, +1772 | | { +... | +1777 | | } +1778 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +error: breaking changes in ` for f32>::deserialize::PrimitiveVisitor as old::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:117:17 + | +117 | / impl<'de> Visitor<'de> for PrimitiveVisitor { +118 | | type Value = $ty; +119 | | +120 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +126 | | )* +127 | | } + | |_________________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` for std::collections::VecDeque>::deserialize::SeqVisitor as old::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:522:17 + | +522 | / impl<'de, T $(, $typaram)*> Visitor<'de> for SeqVisitor +523 | | where +524 | | T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*, +525 | | $($typaram: $bound1 $(+ $bound2)*,)* +... | +545 | | } +546 | | } + | |_________________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` for std::collections::HashMap>::deserialize::MapVisitor as old::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:815:17 + | +815 | / impl<'de, K, V $(, $typaram)*> Visitor<'de> for MapVisitor +816 | | where +817 | | K: Deserialize<'de> $(+ $kbound1 $(+ $kbound2)*)*, +818 | | V: Deserialize<'de>, +... | +839 | | } +840 | | } + | |_________________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `<>::deserialize::KindVisitor as old::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:959:9 + | +959 | / impl<'de> Visitor<'de> for KindVisitor { +960 | | type Value = OsStringKind; +961 | | +962 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1002 | | } +1003 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` for std::time::Duration>::deserialize::Field as old::Deserialize<'de>>` + --> serde-1.0.0/src/de/impls.rs:1216:9 + | +1216 | / impl<'de> Deserialize<'de> for Field { +1217 | | fn deserialize(deserializer: D) -> Result +1218 | | where +1219 | | D: Deserializer<'de>, +... | +1257 | | } +1258 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `< for std::time::Duration>::deserialize::Field as old::Deserialize<'de>>::deserialize::FieldVisitor as old::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:1223:17 + | +1223 | / impl<'de> Visitor<'de> for FieldVisitor { +1224 | | type Value = Field; +1225 | | +1226 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1253 | | } +1254 | | } + | |_________________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` for std::time::Duration>::deserialize::DurationVisitor as old::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:1262:9 + | +1262 | / impl<'de> Visitor<'de> for DurationVisitor { +1263 | | type Value = Duration; +1264 | | +1265 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1319 | | } +1320 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` for std::ops::Range>::deserialize::Field as old::Deserialize<'de>>` + --> serde-1.0.0/src/de/impls.rs:1355:9 + | +1355 | / impl<'de> Deserialize<'de> for Field { +1356 | | fn deserialize(deserializer: D) -> Result +1357 | | where +1358 | | D: Deserializer<'de>, +... | +1396 | | } +1397 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `< for std::ops::Range>::deserialize::Field as old::Deserialize<'de>>::deserialize::FieldVisitor as old::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:1362:17 + | +1362 | / impl<'de> Visitor<'de> for FieldVisitor { +1363 | | type Value = Field; +1364 | | +1365 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1392 | | } +1393 | | } + | |_________________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` for std::ops::Range>::deserialize::RangeVisitor as old::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:1403:9 + | +1403 | / impl<'de, Idx> Visitor<'de> for RangeVisitor +1404 | | where +1405 | | Idx: Deserialize<'de>, +1406 | | { +... | +1463 | | } +1464 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` for std::result::Result>::deserialize::Field as old::Deserialize<'de>>` + --> serde-1.0.0/src/de/impls.rs:1513:9 + | +1513 | / impl<'de> Deserialize<'de> for Field { +1514 | | #[inline] +1515 | | fn deserialize(deserializer: D) -> Result +1516 | | where +... | +1572 | | } +1573 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `< for std::result::Result>::deserialize::Field as old::Deserialize<'de>>::deserialize::FieldVisitor as old::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:1521:17 + | +1521 | / impl<'de> Visitor<'de> for FieldVisitor { +1522 | | type Value = Field; +1523 | | +1524 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1568 | | } +1569 | | } + | |_________________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` for std::result::Result>::deserialize::ResultVisitor as old::de::Visitor<'de>>` + --> serde-1.0.0/src/de/impls.rs:1577:9 + | +1577 | / impl<'de, T, E> Visitor<'de> for ResultVisitor +1578 | | where +1579 | | T: Deserialize<'de>, +1580 | | E: Deserialize<'de>, +... | +1596 | | } +1597 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::Deserializer<'de>>` + --> serde-1.0.0/src/private/de.rs:30:5 + | +30 | / impl<'de, E> Deserializer<'de> for MissingFieldDeserializer +31 | | where +32 | | E: Error, +33 | | { +... | +54 | | } +55 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `>` + --> serde-1.0.0/src/private/de.rs:68:5 + | +68 | / impl<'a> Visitor<'a> for CowStrVisitor { +69 | | type Value = Cow<'a, str>; +70 | | +71 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +124 | | } +125 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `>` + --> serde-1.0.0/src/private/de.rs:137:5 + | +137 | / impl<'a> Visitor<'a> for CowBytesVisitor { +138 | | type Value = Cow<'a, [u8]>; +139 | | +140 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +184 | | } +185 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `Content` + --> serde-1.0.8/src/private/de.rs:236:5 + | +236 | / pub enum Content<'de> { +237 | | Bool(bool), +238 | | +239 | | U8(u8), +... | +264 | | Map(Vec<(Content<'de>, Content<'de>)>), +265 | | } + | |_____^ + | + = warning: region parameter added (breaking) +warning: enum variant added (breaking) + --> serde-1.0.8/src/private/de.rs:254:9 + | +254 | Str(&'de str), + | ^^^^^^^^^^^^^ +warning: enum variant added (breaking) + --> serde-1.0.8/src/private/de.rs:255:9 + | +255 | ByteBuf(Vec), + | ^^^^^^^^^^^^^^^^ + +error: breaking changes in `>` + --> serde-1.0.0/src/private/de.rs:290:5 + | +290 | / impl<'de> Deserialize<'de> for Content { +291 | | fn deserialize(deserializer: D) -> Result +292 | | where +293 | | D: Deserializer<'de>, +... | +298 | | } +299 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `>` + --> serde-1.0.0/src/private/de.rs:303:5 + | +303 | / impl<'de> Visitor<'de> for ContentVisitor { +304 | | type Value = Content; +305 | | +306 | | fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +... | +477 | | } +478 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `>` + --> serde-1.0.0/src/private/de.rs:498:5 + | +498 | / impl<'de> DeserializeSeed<'de> for TagOrContentVisitor { +499 | | type Value = TagOrContent; +500 | | +501 | | fn deserialize(self, deserializer: D) -> Result +... | +508 | | } +509 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `>` + --> serde-1.0.0/src/private/de.rs:511:5 + | +511 | / impl<'de> Visitor<'de> for TagOrContentVisitor { +512 | | type Value = TagOrContent; +513 | | +514 | | fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +... | +731 | | } +732 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `TaggedContentVisitor` + --> serde-1.0.8/src/private/de.rs:798:5 + | +798 | / pub struct TaggedContentVisitor<'de, T> { +799 | | tag_name: &'static str, +800 | | value: PhantomData>, +801 | | } + | |_____^ + | + = warning: region parameter added (breaking) +warning: variant field added to variant with private fields (breaking) + --> serde-1.0.8/src/private/de.rs:800:9 + | +800 | value: PhantomData>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: variant field removed from variant with private fields (breaking) + --> serde-1.0.0/src/private/de.rs:745:9 + | +745 | tag: PhantomData, + | ^^^^^^^^^^^^^^^^^^^ + +error: breaking changes in `new` + --> serde-1.0.0/src/private/de.rs:751:9 + | +751 | / pub fn new(name: &'static str) -> Self { +752 | | TaggedContentVisitor { +753 | | tag_name: name, +754 | | tag: PhantomData, +755 | | } +756 | | } + | |_________^ + | + = warning: removed item in inherent impl (breaking) + +error: breaking changes in ` as old::de::DeserializeSeed<'de>>` + --> serde-1.0.0/src/private/de.rs:759:5 + | +759 | / impl<'de, T> DeserializeSeed<'de> for TaggedContentVisitor +760 | | where +761 | | T: Deserialize<'de>, +762 | | { +... | +772 | | } +773 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::Visitor<'de>>` + --> serde-1.0.0/src/private/de.rs:775:5 + | +775 | / impl<'de, T> Visitor<'de> for TaggedContentVisitor +776 | | where +777 | | T: Deserialize<'de>, +778 | | { +... | +817 | | } +818 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `ContentDeserializer` + --> serde-1.0.8/src/private/de.rs:970:5 + | +970 | / pub struct ContentDeserializer<'de, E> { +971 | | content: Content<'de>, +972 | | err: PhantomData, +973 | | } + | |_____^ + | + = warning: region parameter added (breaking) + +error: breaking changes in ` as old::Deserializer<'de>>` + --> serde-1.0.0/src/private/de.rs:874:5 + | +874 | / impl<'de, E> Deserializer<'de> for ContentDeserializer +875 | | where +876 | | E: de::Error, +877 | | { +... | +999 | | } +1000 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `new` + --> serde-1.0.0/src/private/de.rs:1004:9 + | +1004 | / pub fn new(content: Content) -> Self { +1005 | | ContentDeserializer { +1006 | | content: content, +1007 | | err: PhantomData, +1008 | | } +1009 | | } + | |_________^ + | + = warning: removed item in inherent impl (breaking) + +error: breaking changes in ` as old::de::EnumAccess<'de>>` + --> serde-1.0.0/src/private/de.rs:1021:5 + | +1021 | / impl<'de, E> de::EnumAccess<'de> for EnumDeserializer +1022 | | where +1023 | | E: de::Error, +1024 | | { +... | +1038 | | } +1039 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::VariantAccess<'de>>` + --> serde-1.0.0/src/private/de.rs:1049:5 + | +1049 | / impl<'de, E> de::VariantAccess<'de> for VariantDeserializer +1050 | | where +1051 | | E: de::Error, +1052 | | { +... | +1102 | | } +1103 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::Deserializer<'de>>` + --> serde-1.0.0/src/private/de.rs:1125:5 + | +1125 | / impl<'de, E> de::Deserializer<'de> for SeqDeserializer +1126 | | where +1127 | | E: de::Error, +1128 | | { +... | +1154 | | } +1155 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::SeqAccess<'de>>` + --> serde-1.0.0/src/private/de.rs:1157:5 + | +1157 | / impl<'de, E> de::SeqAccess<'de> for SeqDeserializer +1158 | | where +1159 | | E: de::Error, +1160 | | { +... | +1178 | | } +1179 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::MapAccess<'de>>` + --> serde-1.0.0/src/private/de.rs:1203:5 + | +1203 | / impl<'de, E> de::MapAccess<'de> for MapDeserializer +1204 | | where +1205 | | E: de::Error, +1206 | | { +... | +1234 | | } +1235 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::Deserializer<'de>>` + --> serde-1.0.0/src/private/de.rs:1237:5 + | +1237 | / impl<'de, E> de::Deserializer<'de> for MapDeserializer +1238 | | where +1239 | | E: de::Error, +1240 | | { +... | +1255 | | } +1256 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `ContentRefDeserializer` + --> serde-1.0.8/src/private/de.rs:1364:5 + | +1364 | / pub struct ContentRefDeserializer<'a, 'de: 'a, E> { +1365 | | content: &'a Content<'de>, +1366 | | err: PhantomData, +1367 | | } + | |_____^ + | + = warning: region parameter added (breaking) + +error: breaking changes in ` as old::Deserializer<'de>>` + --> serde-1.0.0/src/private/de.rs:1266:5 + | +1266 | / impl<'de, 'a, E> Deserializer<'de> for ContentRefDeserializer<'a, E> +1267 | | where +1268 | | E: de::Error, +1269 | | { +... | +1391 | | } +1392 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `new` + --> serde-1.0.0/src/private/de.rs:1396:9 + | +1396 | / pub fn new(content: &'a Content) -> Self { +1397 | | ContentRefDeserializer { +1398 | | content: content, +1399 | | err: PhantomData, +1400 | | } +1401 | | } + | |_________^ + | + = warning: removed item in inherent impl (breaking) + +error: breaking changes in ` as old::de::EnumAccess<'de>>` + --> serde-1.0.0/src/private/de.rs:1413:5 + | +1413 | / impl<'de, 'a, E> de::EnumAccess<'de> for EnumRefDeserializer<'a, E> +1414 | | where +1415 | | E: de::Error, +1416 | | { +... | +1430 | | } +1431 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::VariantAccess<'de>>` + --> serde-1.0.0/src/private/de.rs:1441:5 + | +1441 | / impl<'de, 'a, E> de::VariantAccess<'de> for VariantRefDeserializer<'a, E> +1442 | | where +1443 | | E: de::Error, +1444 | | { +... | +1494 | | } +1495 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::Deserializer<'de>>` + --> serde-1.0.0/src/private/de.rs:1517:5 + | +1517 | / impl<'de, 'a, E> de::Deserializer<'de> for SeqRefDeserializer<'a, E> +1518 | | where +1519 | | E: de::Error, +1520 | | { +... | +1546 | | } +1547 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::SeqAccess<'de>>` + --> serde-1.0.0/src/private/de.rs:1549:5 + | +1549 | / impl<'de, 'a, E> de::SeqAccess<'de> for SeqRefDeserializer<'a, E> +1550 | | where +1551 | | E: de::Error, +1552 | | { +... | +1570 | | } +1571 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::MapAccess<'de>>` + --> serde-1.0.0/src/private/de.rs:1595:5 + | +1595 | / impl<'de, 'a, E> de::MapAccess<'de> for MapRefDeserializer<'a, E> +1596 | | where +1597 | | E: de::Error, +1598 | | { +... | +1627 | | } +1628 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::Deserializer<'de>>` + --> serde-1.0.0/src/private/de.rs:1630:5 + | +1630 | / impl<'de, 'a, E> de::Deserializer<'de> for MapRefDeserializer<'a, E> +1631 | | where +1632 | | E: de::Error, +1633 | | { +... | +1648 | | } +1649 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::IntoDeserializer<'de, E>>` + --> serde-1.0.0/src/private/de.rs:1651:5 + | +1651 | / impl<'de, E> de::IntoDeserializer<'de, E> for ContentDeserializer +1652 | | where +1653 | | E: de::Error, +1654 | | { +... | +1659 | | } +1660 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::IntoDeserializer<'de, E>>` + --> serde-1.0.0/src/private/de.rs:1662:5 + | +1662 | / impl<'de, 'a, E> de::IntoDeserializer<'de, E> for ContentRefDeserializer<'a, E> +1663 | | where +1664 | | E: de::Error, +1665 | | { +... | +1670 | | } +1671 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + diff --git a/src/tools/semverver/tests/helper/test.rs b/src/tools/semverver/tests/helper/test.rs new file mode 100644 index 0000000000000..c7485a8a40348 --- /dev/null +++ b/src/tools/semverver/tests/helper/test.rs @@ -0,0 +1,4 @@ +#[allow(unused_extern_crates)] +extern crate old; +#[allow(unused_extern_crates)] +extern crate new; diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index b4aafb815fc6b..83dac87479dde 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -59,6 +59,7 @@ fn filter_dirs(path: &Path) -> bool { "src/tools/rust-analyzer", "src/tools/rust-installer", "src/tools/rustfmt", + "src/tools/semverver", "src/doc/book", // Filter RLS output directories "target/rls",