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<String>,
+}
+
+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 <twk@twki.de>"]
+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
+```
+
+<details>
+
+<summary>
+  Manual installation and more details
+</summary>
+
+```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 <args>
+```
+
+If you have built using `cargo build --release` instead, change the path to point to the
+`release` subdirectory of the `target` directory.
+
+</details>
+
+## 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 <TRIPLE>
+                        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": "<new::util::enumerate::Enumerate<T> 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<T> = cargo::util::CargoResult<T>;
+
+#[derive(Debug, Deserialize)]
+struct Invocation {
+    package_name: String,
+    target_kind: Vec<String>,
+    outputs: Vec<PathBuf>,
+}
+
+#[derive(Debug, Deserialize)]
+struct BuildPlan {
+    invocations: Vec<Invocation>,
+}
+
+/// 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", "<TRIPLE>");
+        opts
+    }
+
+    /// Parse CLI arguments
+    pub fn parse_args(opts: &getopts::Options) -> Result<getopts::Matches, getopts::Fail> {
+        let args: Vec<String> = 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<Self> {
+        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<WorkInfo<'a>> {
+        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<WorkInfo<'a>> {
+        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::<u32>()
+        ));
+
+        // 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<crates_io::Crate> {
+    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<String> = 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<String> = 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<String> = 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<String> = 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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        serializer.serialize_str(&format!("{}", self.0))
+    }
+}
+
+struct RSpan<'a>(&'a Session, &'a Span);
+
+impl<'a> Serialize for RSpan<'a> {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    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<Span>,
+    /// The set of spans of removed exports of the item.
+    removals: BTreeSet<Span>,
+}
+
+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<Ordering> {
+        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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    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<Span>)>,
+    /// 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<Span>) {
+        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<Ordering> {
+        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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    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<DefId, PathChange>,
+    /// The set of currently recorded regular changes.
+    changes: HashMap<DefId, Change<'tcx>>,
+    /// The mapping of spans to changes, for ordering purposes.
+    spans: BTreeMap<Span, DefId>,
+    /// 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<Span>) {
+        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<String> {
+        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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    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: Gen>(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: Gen>(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: Gen>(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<Span_>)>,
+    );
+
+    /// Construct `Change`s from things that can be generated.
+    fn build_change<'a>(
+        s1: Span,
+        output: bool,
+        changes: Vec<(ChangeType_, Option<Span_>)>,
+    ) -> 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<PathChange_>) -> 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<Change_>) -> 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<PathChange_>, changes: Vec<Change_>) -> 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<T: Eq>() {}
+
+#[allow(dead_code)]
+fn assert_inherent_entry_members_impl_eq() {
+    assert_impl_eq::<DefId>();
+
+    // FIXME derive Eq again once AssocKind impls Eq again.
+    // assert_impl_eq::<AssocKind>();
+
+    assert_impl_eq::<Symbol>();
+}
+
+#[allow(clippy::derive_hash_xor_eq)]
+impl Hash for InherentEntry {
+    fn hash<H: Hasher>(&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<DefId, (Res, Res)>,
+    /// The set of items that have been removed or added and thus have no corresponding item in
+    /// the other crate.
+    non_mapped_items: HashSet<DefId>,
+    /// Trait items' old `DefId` mapped to old and new `Res`, and the enclosing trait's `DefId`.
+    trait_item_mapping: HashMap<DefId, (Res, Res, DefId)>,
+    /// The set of private traits in both crates.
+    private_traits: HashSet<DefId>,
+    /// Other items' old `DefId` mapped to new `DefId`.
+    internal_mapping: HashMap<DefId, DefId>,
+    /// Children mapping, allowing us to enumerate descendants in `AdtDef`s.
+    child_mapping: HashMap<DefId, BTreeSet<DefId>>,
+    /// New `DefId`s mapped to their old counterparts.
+    reverse_mapping: HashMap<DefId, DefId>,
+    /// Type parameters' `DefId`s mapped to their definitions.
+    type_params: HashMap<DefId, GenericParamDef>,
+    /// Map from inherent impls' descriptors to the impls they are declared in.
+    inherent_items: HashMap<InherentEntry, InherentImplSet>,
+}
+
+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<DefId> {
+        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<DefId> {
+        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<DefId> {
+        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<Item = (Res, Res)> + '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<impl Iterator<Item = (DefId, DefId)> + '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<Item = (&InherentEntry, &InherentImplSet)> {
+        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<Export<HirId>>;
+
+/// 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<Symbol, (OptionalExport, OptionalExport)>,
+    /// The exports in the value namespace.
+    value_map: HashMap<Symbol, (OptionalExport, OptionalExport)>,
+    /// The exports in the macro namespace.
+    macro_map: HashMap<Symbol, (OptionalExport, OptionalExport)>,
+}
+
+impl NameMapping {
+    /// Insert a single export in the appropriate map, at the appropriate position.
+    fn insert(&mut self, item: Export<HirId>, 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<Export<HirId>>, new_items: Vec<Export<HirId>>) {
+        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<Item = (Option<Export<HirId>>, Option<Export<HirId>>)> + '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<Ty<'tcx>>,
+    /// Type cache holding all new types currently being processed to avoid loops.
+    current_new_types: HashSet<Ty<'tcx>>,
+}
+
+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<T: Relate<'tcx>>(
+        &mut self,
+        _: ty::Variance,
+        a: T,
+        b: T,
+    ) -> RelateResult<'tcx, T> {
+        self.relate(a, b)
+    }
+
+    fn relate<T: Relate<'tcx>>(&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<T: Relate<'tcx>>(
+        &mut self,
+        a: ty::Binder<T>,
+        b: ty::Binder<T>,
+    ) -> RelateResult<'tcx, ty::Binder<T>> {
+        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<DefId>,
+}
+
+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<u32, DefId> {
+        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<u32, DefId>,
+        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<T: TypeFoldable<'tcx>>(&self, index_map: &HashMap<u32, DefId>, 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[&param.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<u32, DefId>,
+        predicate: Predicate<'tcx>,
+    ) -> Option<Predicate<'tcx>> {
+        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<Vec<Predicate<'tcx>>> {
+        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<ParamEnv<'tcx>> {
+        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<InherentEntry> {
+        (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<HirId>) -> 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<ChangeType<'tcx>> {
+        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<Vec<FulfillmentError<'tcx>>> {
+        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<TypeError<'tcx2>> {
+        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<Vec<Predicate<'tcx2>>> {
+        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<A: Clone> {
+    pub a: A,
+}
+
+pub struct Def<A> {
+    pub d: A,
+}
+
+pub fn abc<A: Clone>(_: A) {}
+
+pub fn def<A>(_: 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<A> {
+    pub a: A,
+}
+
+pub struct Def<A: Clone> {
+    pub d: A,
+}
+
+pub fn abc<A>(_: A) {}
+
+pub fn def<A: Clone>(_: 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<A: Clone> {
+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<A> {
+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: Clone>(_: 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>(_: 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<Rc<Abc>>,
+}
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<Rc<Abc>>,
+}
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 {
+    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) -> 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::Def>(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<dyn a::Def>,
+}
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::Abc>(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<dyn a::Abc>,
+}
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>(_: A) { }
+
+pub struct Abc<A>(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 {
+    a
+}
+
+pub struct Abc<A>(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>(_: 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<A>(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<A>(&self, _: A) -> u8 {
+        0
+    }
+}
+
+#[allow(dead_code)]
+pub struct Def<A> {
+    field: A,
+}
+
+#[allow(dead_code)]
+impl Def<u8> {
+    pub fn def(&self) -> u16 {
+        0
+    }
+
+    pub fn abc() { }
+
+    fn abc2() { }
+}
+
+#[allow(dead_code)]
+impl Def<u16> {
+    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<A>(&self, a: A) -> A {
+        a
+    }
+}
+
+#[allow(dead_code)]
+pub struct Def<A> {
+    field: A,
+}
+
+#[allow(dead_code)]
+impl Def<bool> {
+    pub fn def(&self) -> u8 {
+        0
+    }
+}
+
+#[allow(dead_code)]
+impl Def<u8> {
+    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<A>(&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<V, E> {
+    #[allow(dead_code)]
+    struct MissingFieldDeserializer<E>(PhantomData<E>);
+
+    impl<E> Deserializer for MissingFieldDeserializer<E> {}
+    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<V, E> {
+    #[allow(dead_code)]
+    struct MissingFieldDeserializer<E>(PhantomData<E>);
+
+    impl<E> Deserializer for MissingFieldDeserializer<E> {}
+    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<T: TypedArrayElement>(_: CreateWith<T::Element>) { }
+
+/* #[allow(dead_code)]
+pub struct TypedArray<T: TypedArrayElement> {
+    computed: T::Element,
+}
+
+impl<T: TypedArrayElement> TypedArray<T> {
+    pub unsafe fn create(_: CreateWith<T::Element>) { }
+} */
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<T: TypedArrayElement>(_: CreateWith<T::Element>) { }
+
+/* #[allow(dead_code)]
+pub struct TypedArray<T: TypedArrayElement> {
+    computed: T::Element,
+}
+
+impl<T: TypedArrayElement> TypedArray<T> {
+    pub unsafe fn create(_: CreateWith<T::Element>) { }
+} */
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<T: IntoIterator> = <T as IntoIterator>::IntoIter;
+
+pub type E<T: IntoIterator> = 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<T: IntoIterator> = <T as IntoIterator>::Item;
+
+pub type E<T: IntoIterator> = <T as IntoIterator>::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<T: IntoIterator> = <T as IntoIterator>::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: IntoIterator> = 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<B> {
+    field: B,
+}
+
+pub struct Def<A=u8> {
+    pub field: A,
+}
+
+pub struct Def2<A=u16> {
+    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<A> {
+    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<A=u8> {
+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<A=u16> {
+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<T> Abc for Option<T> { }
+
+impl Abc for Def { }
+
+impl<T: Clone> Abc for Box<T> { }
+
+impl Abc for Box<Def> { }
+
+impl Abc for () { }
+
+impl<T> 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<T> Abc for Option<T> { }
+
+impl Abc for Def { }
+
+impl<T> Abc for Vec<T> { }
+
+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 `<std::vec::Vec<T> as old::Abc>`
+ --> trait_impls/old.rs:9:1
+  |
+9 | impl<T> Abc for Vec<T> { }
+  | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+  |
+  = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<old::Def as std::clone::Clone>`
+  --> 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 `<std::boxed::Box<T> as new::Abc>`
+  --> trait_impls/new.rs:11:1
+   |
+11 | impl<T: Clone> Abc for Box<T> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<std::boxed::Box<new::Def> as new::Abc>`
+  --> trait_impls/new.rs:13:1
+   |
+13 | impl Abc for Box<Def> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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 `<std::cell::Cell<(bool, T)> as new::Abc>`
+  --> trait_impls/new.rs:17:1
+   |
+17 | impl<T> 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<T> { }
+
+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<T> { }
+
+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<A> {}
+
+pub trait Cde {}
+
+pub trait Def<A, B> {
+    // 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<A> {
+    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<A: Clone> { }
+
+pub trait Tuv<A> { }
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<A> {}
+
+pub trait Def<A> {
+    fn def(&self, a: A) -> bool;
+}
+
+pub trait Efg<A, B> {
+    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<A> { }
+
+pub trait Tuv<A: Clone> { }
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<A> {}
+   | ^^^^^^^^^^^^^^^^^^^
+   |
+   = 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<A, B> {
+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<A> {
+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<A: Clone> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: added bound: `A: std::clone::Clone` (breaking)
+
+error: breaking changes in `Tuv`
+  --> traits/new.rs:48:1
+   |
+48 | pub trait Tuv<A> { }
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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> = T;
+pub type D<'a, T, U=Box<T>> = (&'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> = 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<T>> = (&'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::<String>()
+            .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::<String>()
+                .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::<Vec<_>>();
+            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::<String>()
+            .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::<String>()
+                .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 `<new::LogLevel as std::hash::Hash>`
+   --> 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 `<new::LogLevelFilter as std::hash::Hash>`
+   --> 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 `<new::LogRecord<'a> 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 `<new::LogMetadata<'a> 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 `<new::LogMetadata<'a> 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 `<new::LogMetadata<'a> 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 `<new::LogMetadata<'a> 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 `<new::LogMetadata<'a> 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 `<new::LogMetadata<'a> 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 `<new::LogLocation as std::marker::StructuralEq>`
+   --> 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 `<new::LogLocation as std::marker::StructuralPartialEq>`
+   --> 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 `<new::LogLocation as std::cmp::Ord>`
+   --> 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 `<new::LogLocation as std::cmp::PartialOrd>`
+   --> 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 `<new::LogLocation as std::hash::Hash>`
+   --> 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<M>(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<Box<Log>, 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 `<new::LogLevel as std::hash::Hash>`
+   --> 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 `<new::LogLevelFilter as std::hash::Hash>`
+   --> 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 `<new::LogRecord<'a> 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 `<new::LogMetadata<'a> 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 `<new::LogMetadata<'a> 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 `<new::LogMetadata<'a> 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 `<new::LogMetadata<'a> 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 `<new::LogMetadata<'a> 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 `<new::LogMetadata<'a> 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 `<new::LogLocation as std::marker::StructuralEq>`
+   --> 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 `<new::LogLocation as std::marker::StructuralPartialEq>`
+   --> 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 `<new::LogLocation as std::cmp::Ord>`
+   --> 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 `<new::LogLocation as std::cmp::PartialOrd>`
+   --> 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 `<new::LogLocation as std::hash::Hash>`
+   --> 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<M>(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<Box<Log>, 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 `<new::LogLevel as std::hash::Hash>`
+   --> 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 `<new::LogLevelFilter as std::hash::Hash>`
+   --> 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 `<new::LogRecord<'a> 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 `<new::LogMetadata<'a> 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 `<new::LogMetadata<'a> 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 `<new::LogMetadata<'a> 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 `<new::LogMetadata<'a> 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 `<new::LogMetadata<'a> 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 `<new::LogMetadata<'a> 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 `<new::LogLocation as std::marker::StructuralEq>`
+   --> 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 `<new::LogLocation as std::marker::StructuralPartialEq>`
+   --> 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 `<new::LogLocation as std::cmp::Ord>`
+   --> 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 `<new::LogLocation as std::cmp::PartialOrd>`
+   --> 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 `<new::LogLocation as std::hash::Hash>`
+   --> 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<M>(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<Box<Log>, 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 `<new::Generator<'a, T, R> 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 `<new::AsciiGenerator<'a, R> 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 `<new::XorShiftRng as std::fmt::Debug>`
+   --> 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 `<new::Open01<F> 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 `<new::Closed01<F> 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 `<new::StdRng as std::fmt::Debug>`
+   --> 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 `<new::ThreadRngReseeder as std::fmt::Debug>`
+   --> 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 `<new::ThreadRng as std::fmt::Debug>`
+   --> 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 `<new::distributions::RandSample<Sup> 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 `<new::distributions::Weighted<T> 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 `<new::distributions::WeightedChoice<'a, T> 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 `<new::distributions::Range<X> 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 `<new::distributions::Gamma as std::fmt::Debug>`
+  --> 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 `<new::distributions::gamma::GammaRepr as std::fmt::Debug>`
+  --> 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 `<new::distributions::gamma::GammaSmallShape as std::fmt::Debug>`
+  --> 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 `<new::distributions::gamma::GammaLargeShape as std::fmt::Debug>`
+  --> 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 `<new::distributions::ChiSquared as std::fmt::Debug>`
+   --> 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 `<new::distributions::gamma::ChiSquaredRepr as std::fmt::Debug>`
+   --> 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 `<new::distributions::FisherF as std::fmt::Debug>`
+   --> 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 `<new::distributions::StudentT as std::fmt::Debug>`
+   --> 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 `<new::distributions::normal::StandardNormal as std::fmt::Debug>`
+  --> 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 `<new::distributions::Normal as std::fmt::Debug>`
+  --> 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 `<new::distributions::LogNormal as std::fmt::Debug>`
+   --> 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 `<new::distributions::exponential::Exp1 as std::fmt::Debug>`
+  --> 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 `<new::distributions::Exp as std::fmt::Debug>`
+  --> 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 `<new::IsaacRng as std::fmt::Debug>`
+   --> 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 `<new::Isaac64Rng as std::fmt::Debug>`
+   --> 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 `<new::ChaChaRng as std::fmt::Debug>`
+  --> 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 `<new::reseeding::ReseedingRng<R, Rsdr> 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 `<new::reseeding::ReseedWithDefault as std::fmt::Debug>`
+   --> 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::<impl new::Rand for [T; 31]>`
+   --> rand_impls.rs:223:9
+    |
+223 | /         impl<T> Rand for [T; $n] where T: Rand {
+224 | |             #[inline]
+225 | |             fn rand<R: Rng>(_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::<impl new::Rand for [T; 0]>`
+   --> rand_impls.rs:231:9
+    |
+231 | /         impl<T> Rand for [T; $n] {
+232 | |             fn rand<R: Rng>(_rng: &mut R) -> [T; $n] { [] }
+233 | |         }
+    | |_________^
+    |
+    = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::OsRng as std::fmt::Debug>`
+  --> 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 `<new::read::ReadRng<R> 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 `<old::decode::Error as std::convert::From<rmp::decode::MarkerReadError>>`
+  --> rmpv-0.4.0/src/decode/mod.rs:60:1
+   |
+60 | / impl From<MarkerReadError> 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 `<old::decode::Error as std::convert::From<rmp::decode::ValueReadError>>`
+  --> rmpv-0.4.0/src/decode/mod.rs:66:1
+   |
+66 | / impl From<ValueReadError> 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<W>(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<W>(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 `<new::decode::Error as std::convert::From<rmp::decode::MarkerReadError>>`
+  --> rmpv-0.4.1/src/decode/mod.rs:60:1
+   |
+60 | / impl From<MarkerReadError> 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 `<new::decode::Error as std::convert::From<rmp::decode::ValueReadError>>`
+  --> rmpv-0.4.1/src/decode/mod.rs:66:1
+   |
+66 | / impl From<ValueReadError> 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 `<old::decode::Error as std::convert::From<rmp::decode::MarkerReadError>>`
+  --> rmpv-0.4.0/src/decode/mod.rs:60:1
+   |
+60 | / impl From<MarkerReadError> 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 `<old::decode::Error as std::convert::From<rmp::decode::ValueReadError>>`
+  --> rmpv-0.4.0/src/decode/mod.rs:66:1
+   |
+66 | / impl From<ValueReadError> 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<W>(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<W>(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 `<new::decode::Error as std::convert::From<rmp::decode::MarkerReadError>>`
+  --> rmpv-0.4.1/src/decode/mod.rs:60:1
+   |
+60 | / impl From<MarkerReadError> 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 `<new::decode::Error as std::convert::From<rmp::decode::ValueReadError>>`
+  --> rmpv-0.4.1/src/decode/mod.rs:66:1
+   |
+66 | / impl From<ValueReadError> 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 `<old::decode::Error as std::convert::From<rmp::decode::MarkerReadError>>`
+  --> rmpv-0.4.0\src\decode\mod.rs:60:1
+   |
+60 | / impl From<MarkerReadError> 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 `<old::decode::Error as std::convert::From<rmp::decode::ValueReadError>>`
+  --> rmpv-0.4.0\src\decode\mod.rs:66:1
+   |
+66 | / impl From<ValueReadError> 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<W>(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<W>(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 `<new::decode::Error as std::convert::From<rmp::decode::MarkerReadError>>`
+  --> rmpv-0.4.1\src\decode\mod.rs:60:1
+   |
+60 | / impl From<MarkerReadError> 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 `<new::decode::Error as std::convert::From<rmp::decode::ValueReadError>>`
+  --> rmpv-0.4.1\src\decode\mod.rs:66:1
+   |
+66 | / impl From<ValueReadError> 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<Self::Ok, Self::Error>;
+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<Self::Ok, Self::Error>;
+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<Self::Ok, Self::Error>;
+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<Self::Ok, Self::Error>;
+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<Self::Ok, Self::Error>;
+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<Self::Ok, Self::Error>;
+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<Self::Ok, Self::Error>;
+1776 | | }
+     | |_^
+     |
+     = note: added definition (technically breaking)
+
+warning: technically breaking changes in `new::ser::impls::<impl new::Serialize for std::ffi::CStr>`
+  --> serde-1.0.0/src/ser/impls.rs:73:1
+   |
+73 | / impl Serialize for CStr {
+74 | |     #[inline]
+75 | |     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+76 | |     where
+...  |
+80 | |     }
+81 | | }
+   | |_^
+   |
+   = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `new::ser::impls::<impl new::Serialize for std::ffi::CString>`
+  --> serde-1.0.0/src/ser/impls.rs:84:1
+   |
+84 | / impl Serialize for CString {
+85 | |     #[inline]
+86 | |     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+87 | |     where
+...  |
+91 | |     }
+92 | | }
+   | |_^
+   |
+   = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `new::ser::impls::<impl new::Serialize for [T; 0]>`
+   --> serde-1.0.0/src/ser/impls.rs:127:1
+    |
+127 | / impl<T> Serialize for [T; 0] {
+128 | |     #[inline]
+129 | |     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+130 | |     where
+...   |
+134 | |     }
+135 | | }
+    | |_^
+    |
+    = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `new::ser::impls::<impl new::Serialize for std::collections::HashSet<T, H>>`
+   --> serde-1.0.0/src/ser/impls.rs:182:9
+    |
+182 | /         impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
+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::<impl new::Serialize for std::ops::Range<Idx>>`
+   --> serde-1.0.0/src/ser/impls.rs:219:1
+    |
+219 | / impl<Idx> Serialize for ops::Range<Idx>
+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::<impl new::Serialize for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13)>`
+   --> 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::<impl new::Serialize for std::collections::HashMap<K, V, H>>`
+   --> serde-1.0.0/src/ser/impls.rs:295:9
+    |
+295 | /         impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*>
+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::<impl new::Serialize for std::cell::Cell<T>>`
+   --> serde-1.0.0/src/ser/impls.rs:354:1
+    |
+354 | / impl<T> Serialize for Cell<T>
+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::<impl new::Serialize for std::cell::RefCell<T>>`
+   --> serde-1.0.0/src/ser/impls.rs:366:1
+    |
+366 | / impl<T> Serialize for RefCell<T>
+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::<impl new::Serialize for std::sync::Mutex<T>>`
+   --> serde-1.0.0/src/ser/impls.rs:379:1
+    |
+379 | / impl<T> Serialize for Mutex<T>
+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::<impl new::Serialize for std::sync::RwLock<T>>`
+   --> serde-1.0.0/src/ser/impls.rs:395:1
+    |
+395 | / impl<T> Serialize for RwLock<T>
+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::<impl new::Serialize for std::time::Duration>`
+   --> serde-1.0.0/src/ser/impls.rs:433:1
+    |
+433 | / impl Serialize for Duration {
+434 | |     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+435 | |     where
+436 | |         S: Serializer,
+...   |
+443 | |     }
+444 | | }
+    | |_^
+    |
+    = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `new::ser::impls::<impl new::Serialize for std::net::IpAddr>`
+   --> serde-1.0.0/src/ser/impls.rs:475:1
+    |
+475 | / impl Serialize for net::IpAddr {
+476 | |     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+477 | |     where
+478 | |         S: Serializer,
+...   |
+484 | |     }
+485 | | }
+    | |_^
+    |
+    = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `new::ser::impls::<impl new::Serialize for std::ffi::OsStr>`
+   --> serde-1.0.0/src/ser/impls.rs:574:1
+    |
+574 | / impl Serialize for OsStr {
+575 | |     #[cfg(unix)]
+576 | |     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+577 | |     where
+...   |
+592 | |     }
+593 | | }
+    | |_^
+    |
+    = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `new::ser::impls::<impl new::Serialize for std::ffi::OsString>`
+   --> serde-1.0.0/src/ser/impls.rs:596:1
+    |
+596 | / impl Serialize for OsString {
+597 | |     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+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<Ok, Error> {
+72 | |     void: Void,
+73 | |     ok: PhantomData<Ok>,
+74 | |     error: PhantomData<Error>,
+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 `<new::de::value::Error as new::ser::Error>`
+  --> serde-1.0.0/src/de/value.rs:78:1
+   |
+78 | / impl ser::Error for Error {
+79 | |     fn custom<T>(msg: T) -> Self
+80 | |     where
+81 | |         T: Display,
+...  |
+84 | |     }
+85 | | }
+   | |_^
+   |
+   = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::de::value::UnitDeserializer<E> 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 `<new::de::value::UnitDeserializer<E> 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 `<new::de::value::U8Deserializer<E> 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 `<new::de::value::I8Deserializer<E> 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 `<new::de::value::U32Deserializer<E> 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 `<new::de::value::U32Deserializer<E> 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 `<new::de::value::StrDeserializer<'a, E> 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 `<new::de::value::StrDeserializer<'a, E> 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 `<new::de::value::StringDeserializer<E> 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 `<new::de::value::StringDeserializer<E> 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<E>,
+440 | | }
+    | |_^
+    |
+    = note: added definition (technically breaking)
+
+warning: technically breaking changes in `<new::de::value::CowStrDeserializer<'a, E> 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 `<new::de::value::SeqDeserializer<I, E> 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 `<new::de::value::SeqDeserializer<I, E> 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 `<new::de::value::SeqDeserializer<I, E> 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<I, E>
+558 | | where
+559 | |     I: Iterator<Item = T>,
+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<A> {
+665 | |     seq: A,
+666 | | }
+    | |_^
+    |
+    = note: added definition (technically breaking)
+
+warning: technically breaking changes in `<new::de::value::SeqAccessDeserializer<A> as new::Deserializer<'de>>`
+   --> serde-1.0.0/src/de/value.rs:675:1
+    |
+675 | / impl<'de, A> de::Deserializer<'de> for SeqAccessDeserializer<A>
+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 `<new::de::value::MapDeserializer<'de, I, E> 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 `<new::de::value::MapDeserializer<'de, I, E> 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 `<new::de::value::MapDeserializer<'de, I, E> 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 `<new::de::value::PairDeserializer<A, B, E> 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<A, B, E>
+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<A> {
+1072 | |     map: A,
+1073 | | }
+     | |_^
+     |
+     = note: added definition (technically breaking)
+
+warning: technically breaking changes in `<new::de::value::MapAccessDeserializer<A> as new::Deserializer<'de>>`
+    --> serde-1.0.0/src/de/value.rs:1082:1
+     |
+1082 | / impl<'de, A> de::Deserializer<'de> for MapAccessDeserializer<A>
+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 `<new::de::IgnoredAny as new::de::Visitor<'de>>`
+   --> 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 `<new::de::IgnoredAny as new::Deserialize<'de>>`
+   --> serde-1.0.0/src/de/ignored_any.rs:207:1
+    |
+207 | / impl<'de> Deserialize<'de> for IgnoredAny {
+208 | |     #[inline]
+209 | |     fn deserialize<D>(deserializer: D) -> Result<IgnoredAny, D::Error>
+210 | |     where
+...   |
+214 | |     }
+215 | | }
+    | |_^
+    |
+    = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::de::impls::<impl new::Deserialize<'de> 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 `<new::de::impls::StrVisitor as new::de::Visitor<'a>>`
+   --> 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::<impl new::Deserialize<'de> 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<D>(deserializer: D) -> Result<Self, D::Error>
+295 | |     where
+296 | |         D: Deserializer<'de>,
+...   |
+299 | |     }
+300 | | }
+    | |_^
+    |
+    = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::de::impls::BytesVisitor as new::de::Visitor<'a>>`
+   --> 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::<impl new::Deserialize<'de> 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<D>(deserializer: D) -> Result<Self, D::Error>
+330 | |     where
+331 | |         D: Deserializer<'de>,
+...   |
+334 | |     }
+335 | | }
+    | |_^
+    |
+    = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::de::impls::CStringVisitor as new::de::Visitor<'de>>`
+   --> 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::<impl new::Deserialize<'de> for std::ffi::CString>`
+   --> serde-1.0.0/src/de/impls.rs:394:1
+    |
+394 | / impl<'de> Deserialize<'de> for CString {
+395 | |     fn deserialize<D>(deserializer: D) -> Result<CString, D::Error>
+396 | |     where
+397 | |         D: Deserializer<'de>,
+...   |
+400 | |     }
+401 | | }
+    | |_^
+    |
+    = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::de::impls::PhantomDataVisitor<T> as new::de::Visitor<'de>>`
+   --> serde-1.0.0/src/de/impls.rs:472:1
+    |
+472 | / impl<'de, T> Visitor<'de> for PhantomDataVisitor<T> {
+473 | |     type Value = PhantomData<T>;
+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::<impl new::Deserialize<'de> for std::marker::PhantomData<T>>`
+   --> serde-1.0.0/src/de/impls.rs:488:1
+    |
+488 | / impl<'de, T> Deserialize<'de> for PhantomData<T> {
+489 | |     fn deserialize<D>(deserializer: D) -> Result<PhantomData<T>, 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::<impl new::Deserialize<'de> for std::collections::HashSet<T, S>>`
+   --> serde-1.0.0/src/de/impls.rs:509:9
+    |
+509 | /         impl<'de, T $(, $typaram)*> Deserialize<'de> for $ty<T $(, $typaram)*>
+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 `<new::de::impls::<impl new::Deserialize<'de> for std::collections::VecDeque<T>>::deserialize::SeqVisitor<T> as new::de::Visitor<'de>>`
+   --> serde-1.0.0/src/de/impls.rs:522:17
+    |
+522 | /                 impl<'de, T $(, $typaram)*> Visitor<'de> for SeqVisitor<T $(, $typaram)*>
+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 `<new::de::impls::ArrayVisitor<[T; 0]> 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::<impl new::Deserialize<'de> 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<D>(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 `<new::de::impls::ArrayVisitor<[T; 32]> 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 `<new::de::impls::TupleVisitor14<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> 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::<impl new::Deserialize<'de> 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<D>(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::<impl new::Deserialize<'de> for std::collections::HashMap<K, V, S>>`
+   --> serde-1.0.0/src/de/impls.rs:801:9
+    |
+801 | /         impl<'de, K, V $(, $typaram)*> Deserialize<'de> for $ty<K, V $(, $typaram)*>
+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 `<new::de::impls::<impl new::Deserialize<'de> for std::collections::HashMap<K, V, S>>::deserialize::MapVisitor<K, V, S> 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<K, V $(, $typaram)*>
+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::<impl new::Deserialize<'de> for std::net::IpAddr>`
+   --> serde-1.0.0/src/de/impls.rs:868:9
+    |
+868 | /         impl<'de> Deserialize<'de> for $ty {
+869 | |             fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+870 | |             where
+871 | |                 D: Deserializer<'de>,
+...   |
+875 | |             }
+876 | |         }
+    | |_________^
+    |
+    = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::de::impls::OsStringKind as new::Deserialize<'de>>`
+    --> serde-1.0.0/src/de/impls.rs:952:1
+     |
+952  | / impl<'de> Deserialize<'de> for OsStringKind {
+953  | |     fn deserialize<D>(deserializer: D) -> Result<OsStringKind, D::Error>
+954  | |     where
+955  | |         D: Deserializer<'de>,
+...    |
+1006 | |     }
+1007 | | }
+     | |_^
+     |
+     = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<<new::de::impls::OsStringKind as new::Deserialize<'de>>::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 `<new::de::impls::OsStringVisitor as new::de::Visitor<'de>>`
+    --> 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::<impl new::Deserialize<'de> for std::ffi::OsString>`
+    --> serde-1.0.0/src/de/impls.rs:1051:1
+     |
+1051 | / impl<'de> Deserialize<'de> for OsString {
+1052 | |     fn deserialize<D>(deserializer: D) -> Result<OsString, D::Error>
+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::<impl new::Deserialize<'de> 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::<impl new::Deserialize<'de> for std::boxed::Box<str>>`
+    --> serde-1.0.0/src/de/impls.rs:1089:1
+     |
+1089 | / impl<'de> Deserialize<'de> for Box<str> {
+1090 | |     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+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::<impl new::Deserialize<'de> for std::cell::Cell<T>>`
+    --> serde-1.0.0/src/de/impls.rs:1141:1
+     |
+1141 | / impl<'de, T> Deserialize<'de> for Cell<T>
+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::<impl new::Deserialize<'de> for std::cell::RefCell<T>>`
+    --> serde-1.0.0/src/de/impls.rs:1153:1
+     |
+1153 | / impl<'de, T> Deserialize<'de> for RefCell<T>
+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::<impl new::Deserialize<'de> for std::sync::Mutex<T>>`
+    --> serde-1.0.0/src/de/impls.rs:1166:1
+     |
+1166 | / impl<'de, T> Deserialize<'de> for Mutex<T>
+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::<impl new::Deserialize<'de> for std::sync::RwLock<T>>`
+    --> serde-1.0.0/src/de/impls.rs:1179:1
+     |
+1179 | / impl<'de, T> Deserialize<'de> for RwLock<T>
+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::<impl new::Deserialize<'de> for std::time::Duration>`
+    --> serde-1.0.0/src/de/impls.rs:1202:1
+     |
+1202 | / impl<'de> Deserialize<'de> for Duration {
+1203 | |     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+1204 | |     where
+1205 | |         D: Deserializer<'de>,
+...    |
+1324 | |     }
+1325 | | }
+     | |_^
+     |
+     = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::de::impls::<impl new::Deserialize<'de> 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<D>(deserializer: D) -> Result<Field, D::Error>
+1218 | |             where
+1219 | |                 D: Deserializer<'de>,
+...    |
+1257 | |             }
+1258 | |         }
+     | |_________^
+     |
+     = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<<new::de::impls::<impl new::Deserialize<'de> 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 `<new::de::impls::<impl new::Deserialize<'de> 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::<impl new::Deserialize<'de> for std::ops::Range<Idx>>`
+    --> serde-1.0.0/src/de/impls.rs:1338:1
+     |
+1338 | / impl<'de, Idx> Deserialize<'de> for ops::Range<Idx>
+1339 | | where
+1340 | |     Idx: Deserialize<'de>,
+1341 | | {
+...    |
+1468 | |     }
+1469 | | }
+     | |_^
+     |
+     = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::de::impls::<impl new::Deserialize<'de> for std::ops::Range<Idx>>::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<D>(deserializer: D) -> Result<Field, D::Error>
+1357 | |             where
+1358 | |                 D: Deserializer<'de>,
+...    |
+1396 | |             }
+1397 | |         }
+     | |_________^
+     |
+     = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<<new::de::impls::<impl new::Deserialize<'de> for std::ops::Range<Idx>>::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 `<new::de::impls::<impl new::Deserialize<'de> for std::ops::Range<Idx>>::deserialize::RangeVisitor<Idx> as new::de::Visitor<'de>>`
+    --> serde-1.0.0/src/de/impls.rs:1403:9
+     |
+1403 | /         impl<'de, Idx> Visitor<'de> for RangeVisitor<Idx>
+1404 | |         where
+1405 | |             Idx: Deserialize<'de>,
+1406 | |         {
+...    |
+1463 | |             }
+1464 | |         }
+     | |_________^
+     |
+     = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::de::impls::<impl new::Deserialize<'de> for std::result::Result<T, E>>::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<D>(deserializer: D) -> Result<Field, D::Error>
+1516 | |             where
+...    |
+1572 | |             }
+1573 | |         }
+     | |_________^
+     |
+     = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<<new::de::impls::<impl new::Deserialize<'de> for std::result::Result<T, E>>::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 `<new::de::impls::<impl new::Deserialize<'de> for std::result::Result<T, E>>::deserialize::ResultVisitor<T, E> as new::de::Visitor<'de>>`
+    --> serde-1.0.0/src/de/impls.rs:1577:9
+     |
+1577 | /         impl<'de, T, E> Visitor<'de> for ResultVisitor<T, E>
+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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+...  |
+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<D>(deserializer: D) -> Result<Self, D::Error>
+...  |
+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<Self::$ret, Self::Error> {
+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 `<new::private::ser::TaggedSerializer<S> as new::Serializer>`
+   --> serde-1.0.0/src/private/ser.rs:107:1
+    |
+107 | / impl<S> Serializer for TaggedSerializer<S>
+108 | | where
+109 | |     S: Serializer,
+110 | | {
+...   |
+336 | |     }
+337 | | }
+    | |_^
+    |
+    = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::private::ser::Error as new::ser::Error>`
+   --> serde-1.0.0/src/private/ser.rs:344:1
+    |
+344 | / impl ser::Error for Error {
+345 | |     fn custom<T>(_: T) -> Self
+346 | |     where
+347 | |         T: Display,
+...   |
+350 | |     }
+351 | | }
+    | |_^
+    |
+    = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::private::ser::content::Content as new::Serialize>`
+   --> serde-1.0.0/src/private/ser.rs:491:5
+    |
+491 | /     impl Serialize for Content {
+492 | |         fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+493 | |         where
+494 | |             S: Serializer,
+...   |
+570 | |         }
+571 | |     }
+    | |_____^
+    |
+    = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::private::ser::content::ContentSerializer<E> as new::Serializer>`
+   --> serde-1.0.0/src/private/ser.rs:583:5
+    |
+583 | /     impl<E> Serializer for ContentSerializer<E>
+584 | |     where
+585 | |         E: ser::Error,
+586 | |     {
+...   |
+803 | |         }
+804 | |     }
+    | |_____^
+    |
+    = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::private::de::missing_field::MissingFieldDeserializer<E> as new::Deserializer<'de>>`
+  --> serde-1.0.0/src/private/de.rs:30:5
+   |
+30 | /     impl<'de, E> Deserializer<'de> for MissingFieldDeserializer<E>
+31 | |     where
+32 | |         E: Error,
+33 | |     {
+...  |
+54 | |         }
+55 | |     }
+   | |_____^
+   |
+   = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::private::de::borrow_cow_str::CowStrVisitor as new::de::Visitor<'a>>`
+   --> 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 `<new::private::de::borrow_cow_bytes::CowBytesVisitor as new::de::Visitor<'a>>`
+   --> 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 `<new::private::de::Content as new::Deserialize<'de>>`
+   --> serde-1.0.0/src/private/de.rs:290:5
+    |
+290 | /     impl<'de> Deserialize<'de> for Content {
+291 | |         fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+292 | |         where
+293 | |             D: Deserializer<'de>,
+...   |
+298 | |         }
+299 | |     }
+    | |_____^
+    |
+    = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::private::de::content::ContentVisitor as new::de::Visitor<'de>>`
+   --> 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 `<new::private::de::content::TagOrContentVisitor as new::de::Visitor<'de>>`
+   --> 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 `<new::private::de::TaggedContentVisitor<T> as new::de::Visitor<'de>>`
+   --> serde-1.0.0/src/private/de.rs:775:5
+    |
+775 | /     impl<'de, T> Visitor<'de> for TaggedContentVisitor<T>
+776 | |     where
+777 | |         T: Deserialize<'de>,
+778 | |     {
+...   |
+817 | |         }
+818 | |     }
+    | |_____^
+    |
+    = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::private::de::TagOrContentFieldVisitor as new::de::Visitor<'de>>`
+   --> 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 `<new::private::de::ContentDeserializer<E> as new::Deserializer<'de>>`
+    --> serde-1.0.0/src/private/de.rs:874:5
+     |
+874  | /     impl<'de, E> Deserializer<'de> for ContentDeserializer<E>
+875  | |     where
+876  | |         E: de::Error,
+877  | |     {
+...    |
+999  | |         }
+1000 | |     }
+     | |_____^
+     |
+     = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::private::de::content::SeqDeserializer<E> as new::Deserializer<'de>>`
+    --> serde-1.0.0/src/private/de.rs:1125:5
+     |
+1125 | /     impl<'de, E> de::Deserializer<'de> for SeqDeserializer<E>
+1126 | |     where
+1127 | |         E: de::Error,
+1128 | |     {
+...    |
+1154 | |         }
+1155 | |     }
+     | |_____^
+     |
+     = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::private::de::content::MapDeserializer<E> as new::Deserializer<'de>>`
+    --> serde-1.0.0/src/private/de.rs:1237:5
+     |
+1237 | /     impl<'de, E> de::Deserializer<'de> for MapDeserializer<E>
+1238 | |     where
+1239 | |         E: de::Error,
+1240 | |     {
+...    |
+1255 | |         }
+1256 | |     }
+     | |_____^
+     |
+     = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::private::de::ContentRefDeserializer<'a, E> 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 `<new::private::de::content::SeqRefDeserializer<'a, E> 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 `<new::private::de::content::MapRefDeserializer<'a, E> 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 `<new::private::de::InternallyTaggedUnitVisitor<'a> 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 `<new::private::de::UntaggedUnitVisitor<'a> 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 `<new::private::de::StrDeserializer<'a, E> 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 `<new::private::de::BytesDeserializer<'a, E> 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 `<old::bytes::Bytes<'a> 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<S>(&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 `<old::bytes::ByteBuf as old::Serialize>`
+   --> serde-0.7.0/src/bytes.rs:139:1
+    |
+139 | / impl ser::Serialize for ByteBuf {
+140 | |     fn serialize<S>(&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 `<old::bytes::ByteBufVisitor as old::de::Visitor>`
+   --> 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 `<old::bytes::ByteBuf as old::Deserialize>`
+   --> serde-0.7.0/src/bytes.rs:197:1
+    |
+197 | / impl de::Deserialize for ByteBuf {
+198 | |     #[inline]
+199 | |     fn deserialize<D>(deserializer: &mut D) -> Result<ByteBuf, D::Error>
+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<T>(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<T>` (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<D>(deserializer: D) -> Result<Self, D::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(&mut self,
+344  | |                                        _len: usize,
+345  | |                                        visitor: V) -> Result<V::Value, Self::Error>
+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<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(
+934 | |         self,
+935 | |         name: &'static str,
+936 | |         visitor: V,
+937 | |     ) -> Result<V::Value, Self::Error>
+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<V>(
+944 | |         self,
+945 | |         name: &'static str,
+946 | |         visitor: V,
+947 | |     ) -> Result<V::Value, Self::Error>
+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<V>(
+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<V>(
+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<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
+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<V>(
+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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+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<E>(self, v: &'de str) -> Result<Self::Value, E>
+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<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
+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<A>(self, data: A) -> Result<Self::Value, A::Error>
+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<E>(&mut self, v: usize) -> Result<Self::Value, E>
+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<E>(&mut self, v: isize) -> Result<Self::Value, E>
+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<E>(&mut self, _name: &'static str) -> Result<Self::Value, E>
+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<E>(self, v: bool) -> Result<Self::Value, E>
+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<E>(self, v: i8) -> Result<Self::Value, E>
+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<E>(self, v: i16) -> Result<Self::Value, E>
+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<E>(self, v: i32) -> Result<Self::Value, E>
+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<E>(self, v: i64) -> Result<Self::Value, E>
+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<E>(self, v: u8) -> Result<Self::Value, E>
+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<E>(self, v: u16) -> Result<Self::Value, E>
+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<E>(self, v: u32) -> Result<Self::Value, E>
+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<E>(self, v: u64) -> Result<Self::Value, E>
+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<E>(self, v: f32) -> Result<Self::Value, E>
+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<E>(self, v: f64) -> Result<Self::Value, E>
+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<E>(self, v: char) -> Result<Self::Value, E>
+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<E>(self, v: &str) -> Result<Self::Value, E>
+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<E>(self, v: String) -> Result<Self::Value, E>
+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<E>(self) -> Result<Self::Value, E>
+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<E>(self) -> Result<Self::Value, E>
+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<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+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<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+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<A>(self, seq: A) -> Result<Self::Value, A::Error>
+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<A>(self, map: A) -> Result<Self::Value, A::Error>
+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<E>(self, v: &[u8]) -> Result<Self::Value, E>
+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<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
+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 `<old::de::impls::PrimitiveVisitor<T> as old::de::Visitor>`
+   --> serde-0.7.0/src/de/impls.rs:135:1
+    |
+135 | / impl<T> Visitor for PrimitiveVisitor<T>
+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 `<old::de::impls::OptionVisitor<T> as old::de::Visitor>`
+   --> serde-0.7.0/src/de/impls.rs:281:1
+    |
+281 | / impl<
+282 | |     T: Deserialize,
+283 | | > Visitor for OptionVisitor<T> {
+284 | |     type Value = Option<T>;
+...   |
+305 | |     }
+306 | | }
+    | |_^
+    |
+    = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `old::de::impls::<impl old::Deserialize for std::option::Option<T>>`
+   --> serde-0.7.0/src/de/impls.rs:308:1
+    |
+308 | / impl<T> Deserialize for Option<T> where T: Deserialize {
+309 | |     fn deserialize<D>(deserializer: &mut D) -> Result<Option<T>, 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<T> {
+469 | |     marker: PhantomData<T>,
+470 | | }
+    | |_^
+    |
+    = warning: item made private (breaking)
+
+error: breaking changes in `<old::de::impls::PhantomDataVisitor<T> as old::de::Visitor>`
+   --> serde-0.7.0/src/de/impls.rs:323:1
+    |
+323 | / impl<T> Visitor for PhantomDataVisitor<T> where T: Deserialize {
+324 | |     type Value = PhantomData<T>;
+325 | |
+326 | |     #[inline]
+...   |
+331 | |     }
+332 | | }
+    | |_^
+    |
+    = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `old::de::impls::<impl old::Deserialize for std::marker::PhantomData<T>>`
+   --> serde-0.7.0/src/de/impls.rs:334:1
+    |
+334 | / impl<T> Deserialize for PhantomData<T> where T: Deserialize {
+335 | |     fn deserialize<D>(deserializer: &mut D) -> Result<PhantomData<T>, 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<T> {
+357 | |             marker: PhantomData<T>,
+358 | |         }
+    | |_________^
+    |
+    = warning: removed definition (breaking)
+
+error: breaking changes in `<old::de::impls::VecDequeVisitor<T> as old::de::Visitor>`
+   --> serde-0.7.0/src/de/impls.rs:369:9
+    |
+369 | /         impl<T> Visitor for $visitor_name<T>
+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::<impl old::Deserialize for std::collections::LinkedList<T>>`
+   --> serde-0.7.0/src/de/impls.rs:397:9
+    |
+397 | /         impl<T> Deserialize for $ty
+398 | |             where T: $($constraints +)*,
+399 | |         {
+400 | |             fn deserialize<D>(deserializer: &mut D) -> Result<$ty, D::Error>
+...   |
+404 | |             }
+405 | |         }
+    | |_________^
+    |
+    = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<old::de::impls::ArrayVisitor0<T> as old::de::Visitor>`
+   --> serde-0.7.0/src/de/impls.rs:488:1
+    |
+488 | / impl<T> Visitor for ArrayVisitor0<T> 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::<impl old::Deserialize for [T; 0]>`
+   --> serde-0.7.0/src/de/impls.rs:507:1
+    |
+507 | / impl<T> Deserialize for [T; 0]
+508 | |     where T: Deserialize + Default
+509 | | {
+510 | |     fn deserialize<D>(deserializer: &mut D) -> Result<[T; 0], D::Error>
+...   |
+514 | |     }
+515 | | }
+    | |_^
+    |
+    = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<old::de::impls::ArrayVisitor27<T> as old::de::Visitor>`
+   --> serde-0.7.0/src/de/impls.rs:533:13
+    |
+533 | /             impl<T> Visitor for $visitor<T> 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::<impl old::Deserialize for [T; 7]>`
+   --> serde-0.7.0/src/de/impls.rs:553:13
+    |
+553 | /             impl<T> Deserialize for [T; $len]
+554 | |                 where T: Deserialize,
+555 | |             {
+556 | |                 fn deserialize<D>(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 `<old::de::impls::TupleVisitor12<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> 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::<impl old::Deserialize for (T0, T1, T2, T3, T4, T5, T6, T7)>`
+   --> 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<K, V> {
+696 | |             marker: PhantomData<$ty>,
+697 | |         }
+    | |_________^
+    |
+    = warning: removed definition (breaking)
+
+error: breaking changes in `<old::de::impls::HashMapVisitor<K, V> as old::de::Visitor>`
+   --> serde-0.7.0/src/de/impls.rs:708:9
+    |
+708 | /         impl<K, V> Visitor for $visitor_name<K, V>
+709 | |             where K: $($constraints +)*,
+710 | |                   V: Deserialize,
+711 | |         {
+...   |
+734 | |             }
+735 | |         }
+    | |_________^
+    |
+    = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `old::de::impls::<impl old::Deserialize for std::collections::BTreeMap<K, V>>`
+   --> serde-0.7.0/src/de/impls.rs:737:9
+    |
+737 | /         impl<K, V> 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::<impl old::Deserialize for std::boxed::Box<T>>`
+   --> serde-0.7.0/src/de/impls.rs:875:1
+    |
+875 | / impl<T: Deserialize> Deserialize for Box<T> {
+876 | |     fn deserialize<D>(deserializer: &mut D) -> Result<Box<T>, D::Error>
+877 | |         where D: Deserializer,
+878 | |     {
+...   |
+881 | |     }
+882 | | }
+    | |_^
+    |
+    = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `old::de::impls::<impl old::Deserialize for std::sync::Arc<T>>`
+   --> serde-0.7.0/src/de/impls.rs:884:1
+    |
+884 | / impl<T: Deserialize> Deserialize for Arc<T> {
+885 | |     fn deserialize<D>(deserializer: &mut D) -> Result<Arc<T>, D::Error>
+886 | |         where D: Deserializer,
+887 | |     {
+...   |
+890 | |     }
+891 | | }
+    | |_^
+    |
+    = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `old::de::impls::<impl old::Deserialize for std::rc::Rc<T>>`
+   --> serde-0.7.0/src/de/impls.rs:893:1
+    |
+893 | / impl<T: Deserialize> Deserialize for Rc<T> {
+894 | |     fn deserialize<D>(deserializer: &mut D) -> Result<Rc<T>, D::Error>
+895 | |         where D: Deserializer,
+896 | |     {
+...   |
+899 | |     }
+900 | | }
+    | |_^
+    |
+    = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `old::de::impls::<impl old::Deserialize for std::borrow::Cow<'a, T>>`
+   --> 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<D>(deserializer: &mut D) -> Result<Cow<'a, T>, D::Error>
+905 | |         where D: Deserializer,
+...   |
+909 | |     }
+910 | | }
+    | |_^
+    |
+    = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `old::de::impls::<impl old::Deserialize for std::result::Result<T, E>>`
+    --> serde-0.7.0/src/de/impls.rs:930:1
+     |
+930  | / impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
+931  | |     fn deserialize<D>(deserializer: &mut D) -> Result<Result<T, E>, D::Error>
+932  | |                       where D: Deserializer {
+933  | |         enum Field {
+...    |
+1009 | |     }
+1010 | | }
+     | |_^
+     |
+     = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<old::de::impls::<impl old::Deserialize for std::result::Result<T, E>>::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<D>(deserializer: &mut D) -> Result<Field, D::Error>
+941 | |                 where D: Deserializer
+...   |
+979 | |             }
+980 | |         }
+    | |_________^
+    |
+    = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<<old::de::impls::<impl old::Deserialize for std::result::Result<T, E>>::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<E>(&mut self, value: usize) -> Result<Field, E> 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 `<old::de::impls::IgnoredAny as old::Deserialize>`
+    --> serde-0.7.0/src/de/impls.rs:1018:1
+     |
+1018 | / impl Deserialize for IgnoredAny {
+1019 | |     #[inline]
+1020 | |     fn deserialize<D>(deserializer: &mut D) -> Result<IgnoredAny, D::Error>
+1021 | |         where D: Deserializer,
+...    |
+1113 | |     }
+1114 | | }
+     | |_^
+     |
+     = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<<old::de::impls::IgnoredAny as old::Deserialize>::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<E: de::Error = Error> {
+94 | |     /// The actual deserializer type.
+95 | |     type Deserializer: de::Deserializer<Error=E>;
+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<E> {
+122 | |     marker: PhantomData<E>,
+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<E> {
+122 | |     marker: PhantomData<E>,
+123 | | }
+    | |_^
+
+error: breaking changes in `I8Deserializer`
+   --> serde-1.0.0/src/de/value.rs:159:9
+    |
+159 | /         pub struct $name<E> {
+160 | |             value: $ty,
+161 | |             marker: PhantomData<E>
+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<E> {
+160 | |             value: $ty,
+161 | |             marker: PhantomData<E>
+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<E>,
+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<E>,
+291 | | }
+    | |_^
+
+error: breaking changes in `StringDeserializer`
+   --> serde-1.0.0/src/de/value.rs:361:1
+    |
+361 | / pub struct StringDeserializer<E> {
+362 | |     value: String,
+363 | |     marker: PhantomData<E>,
+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<E> {
+362 | |     value: String,
+363 | |     marker: PhantomData<E>,
+364 | | }
+    | |_^
+
+error: breaking changes in `SeqDeserializer`
+   --> serde-1.0.0/src/de/value.rs:515:1
+    |
+515 | / pub struct SeqDeserializer<I, E> {
+516 | |     iter: iter::Fuse<I>,
+517 | |     count: usize,
+518 | |     marker: PhantomData<E>,
+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 `<old::de::value::SeqDeserializer<I, E> as old::Deserializer>`
+   --> serde-0.7.0/src/de/value.rs:315:1
+    |
+315 | / impl<I, T, E> de::Deserializer for SeqDeserializer<I, E>
+316 | |     where I: Iterator<Item=T>,
+317 | |           T: ValueDeserializer<E>,
+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<V_, E> {
+404 | |     visitor: V_,
+405 | |     marker: PhantomData<E>,
+406 | | }
+    | |_^
+    |
+    = warning: removed definition (breaking)
+
+error: breaking changes in `<old::de::value::SeqVisitorDeserializer<V_, E> as old::Deserializer>`
+   --> serde-0.7.0/src/de/value.rs:421:1
+    |
+421 | / impl<V_, E> de::Deserializer for SeqVisitorDeserializer<V_, E>
+422 | |     where V_: de::SeqVisitor<Error = E>,
+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<E>,
+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<E>,
+    |     ^^^^^^^^^^^^^^^^^^^^^^
+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<E>,
+    |     ^^^^^^^^^^^^^^^^^^^^^
+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 `<old::de::value::MapDeserializer<I, K, V, E> as old::Deserializer>`
+   --> serde-0.7.0/src/de/value.rs:464:1
+    |
+464 | / impl<I, K, V, E> de::Deserializer for MapDeserializer<I, K, V, E>
+465 | |     where I: Iterator<Item=(K, V)>,
+466 | |           K: ValueDeserializer<E>,
+467 | |           V: ValueDeserializer<E>,
+...   |
+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<V_, E> {
+560 | |     visitor: V_,
+561 | |     marker: PhantomData<E>,
+562 | | }
+    | |_^
+    |
+    = warning: removed definition (breaking)
+
+error: breaking changes in `<old::de::value::MapVisitorDeserializer<V_, E> as old::Deserializer>`
+   --> serde-0.7.0/src/de/value.rs:577:1
+    |
+577 | / impl<V_, E> de::Deserializer for MapVisitorDeserializer<V_, E>
+578 | |     where V_: de::MapVisitor<Error = E>,
+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<E>);
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = warning: removed definition (breaking)
+
+error: breaking changes in `<old::de::value::BytesDeserializer<'a, E> 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<E>(Option<Vec<u8>>, PhantomData<E>);
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = warning: removed definition (breaking)
+
+error: breaking changes in `<old::de::value::ByteBufDeserializer<E> as old::Deserializer>`
+   --> serde-0.7.0/src/de/value.rs:634:1
+    |
+634 | / impl<E> de::Deserializer for ByteBufDeserializer<E>
+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<T>(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<T>` (technically breaking)
+
+error: breaking changes in `serialize`
+   --> serde-1.0.0/src/ser/mod.rs:236:5
+    |
+236 | /     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+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<Ok = Self::Ok, Error = Self::Error>;
+     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+warning: added item to trait (breaking)
+    --> serde-1.0.0/src/ser/mod.rs:334:5
+     |
+334  |     type SerializeTuple: SerializeTuple<Ok = Self::Ok, Error = Self::Error>;
+     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+warning: added item to trait (breaking)
+    --> serde-1.0.0/src/ser/mod.rs:340:5
+     |
+340  |     type SerializeTupleStruct: SerializeTupleStruct<Ok = Self::Ok, Error = Self::Error>;
+     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+warning: added item to trait (breaking)
+    --> serde-1.0.0/src/ser/mod.rs:346:5
+     |
+346  |     type SerializeTupleVariant: SerializeTupleVariant<Ok = Self::Ok, Error = Self::Error>;
+     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+warning: added item to trait (breaking)
+    --> serde-1.0.0/src/ser/mod.rs:352:5
+     |
+352  |     type SerializeMap: SerializeMap<Ok = Self::Ok, Error = Self::Error>;
+     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+warning: added item to trait (breaking)
+    --> serde-1.0.0/src/ser/mod.rs:358:5
+     |
+358  |     type SerializeStruct: SerializeStruct<Ok = Self::Ok, Error = Self::Error>;
+     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+warning: added item to trait (breaking)
+    --> serde-1.0.0/src/ser/mod.rs:364:5
+     |
+364  |     type SerializeStructVariant: SerializeStructVariant<Ok = Self::Ok, Error = Self::Error>;
+     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: added defaulted item to trait (technically breaking)
+    --> serde-1.0.0/src/ser/mod.rs:1243:5
+     |
+1243 | /     fn collect_seq<I>(self, iter: I) -> Result<Self::Ok, Self::Error>
+1244 | |     where
+1245 | |         I: IntoIterator,
+1246 | |         <I as IntoIterator>::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<K, V, I>(self, iter: I) -> Result<Self::Ok, Self::Error>
+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<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
+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<T>(&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<T>(&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<V>(&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<T>(&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<T>(&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<K, V>(&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<V>(&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<V>(&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<Self::Ok, Self::Error>;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = 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<Self::Ok, Self::Error>;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = 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<Self::Ok, Self::Error>;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = 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<Self::Ok, Self::Error>;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = 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<Self::Ok, Self::Error>;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = 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<Self::Ok, Self::Error>;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = 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<Self::Ok, Self::Error>;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = 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<Self::Ok, Self::Error>;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = 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<Self::Ok, Self::Error>;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = 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<Self::Ok, Self::Error>;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = 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<Self::Ok, Self::Error>;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = 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<Self::Ok, Self::Error>;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = 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<Self::Ok, Self::Error>;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = 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<Self::Ok, Self::Error>;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = 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<Self::Ok, Self::Error>;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = 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<Self::Ok, Self::Error>;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = 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<Self::Ok, Self::Error>;
+    | |_______________________________________^
+    |
+    = 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<T: ?Sized>(
+884 | |         self,
+885 | |         name: &'static str,
+886 | |         value: &T,
+887 | |     ) -> Result<Self::Ok, Self::Error>
+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<T: ?Sized>(
+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<Self::Ok, Self::Error>;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = 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<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
+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<usize>) -> Result<Self::SerializeSeq, Self::Error>;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = 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<Self::SerializeTuple, Self::Error>;
+     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+     |
+     = 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<Self::SerializeTupleStruct, Self::Error>;
+     | |_________________________________________________________^
+     |
+     = 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<Self::SerializeTupleVariant, Self::Error>;
+     | |__________________________________________________________^
+     |
+     = 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<usize>) -> Result<Self::SerializeMap, Self::Error>;
+     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+     |
+     = 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<Self::SerializeStruct, Self::Error>;
+     | |____________________________________________________^
+     |
+     = 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<Self::SerializeStructVariant, Self::Error>;
+     | |___________________________________________________________^
+     |
+     = 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<Iter> {
+158 | |     iter: Iter,
+159 | |     len: Option<usize>,
+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<Iter> {
+558 | |     iter: Iter,
+559 | |     len: Option<usize>,
+560 | | }
+    | |_^
+    |
+    = warning: removed definition (breaking)
+
+error: breaking changes in `old::ser::impls::<impl old::Serialize for std::rc::Rc<T>>`
+   --> serde-0.7.0/src/ser/impls.rs:654:1
+    |
+654 | / impl<T> Serialize for Rc<T> where T: Serialize, {
+655 | |     #[inline]
+656 | |     fn serialize<S>(&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::<impl old::Serialize for std::sync::Arc<T>>`
+   --> serde-0.7.0/src/ser/impls.rs:663:1
+    |
+663 | / impl<T> Serialize for Arc<T> where T: Serialize, {
+664 | |     #[inline]
+665 | |     fn serialize<S>(&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<E>,
+364 | | }
+    | |_^
+    |
+    = note: added definition (technically breaking)
+
+warning: technically breaking changes in `<new::de::value::BorrowedStrDeserializer<'de, E> 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 `<new::de::value::BorrowedStrDeserializer<'de, E> 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<E>,
+588 | | }
+    | |_^
+    |
+    = note: added definition (technically breaking)
+
+warning: technically breaking changes in `<new::de::value::BorrowedBytesDeserializer<'de, E> 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 `<new::de::impls::<impl new::Deserialize<'de> 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 `<new::de::impls::<impl new::Deserialize<'de> for std::collections::VecDeque<T>>::deserialize::SeqVisitor<T> as new::de::Visitor<'de>>`
+   --> serde-1.0.8/src/de/impls.rs:522:17
+    |
+522 | /                 impl<'de, T $(, $typaram)*> Visitor<'de> for SeqVisitor<T $(, $typaram)*>
+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 `<new::de::impls::<impl new::Deserialize<'de> for std::collections::BTreeMap<K, V>>::deserialize::MapVisitor<K, V> 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<K, V $(, $typaram)*>
+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::PathVisitor as new::de::Visitor<'a>>`
+   --> 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::<impl new::Deserialize<'de> 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<D>(deserializer: D) -> Result<Self, D::Error>
+931 | |     where
+932 | |         D: Deserializer<'de>,
+...   |
+935 | |     }
+936 | | }
+    | |_^
+    |
+    = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<<new::de::impls::OsStringKind as new::Deserialize<'de>>::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 `<new::de::impls::<impl new::Deserialize<'de> 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<D>(deserializer: D) -> Result<Field, D::Error>
+1256 | |             where
+1257 | |                 D: Deserializer<'de>,
+...    |
+1295 | |             }
+1296 | |         }
+     | |_________^
+     |
+     = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<<new::de::impls::<impl new::Deserialize<'de> 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 `<new::de::impls::<impl new::Deserialize<'de> 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 `<new::de::impls::<impl new::Deserialize<'de> for std::ops::Range<Idx>>::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<D>(deserializer: D) -> Result<Field, D::Error>
+1395 | |             where
+1396 | |                 D: Deserializer<'de>,
+...    |
+1434 | |             }
+1435 | |         }
+     | |_________^
+     |
+     = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<<new::de::impls::<impl new::Deserialize<'de> for std::ops::Range<Idx>>::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 `<new::de::impls::<impl new::Deserialize<'de> for std::ops::Range<Idx>>::deserialize::RangeVisitor<Idx> as new::de::Visitor<'de>>`
+    --> serde-1.0.8/src/de/impls.rs:1441:9
+     |
+1441 | /         impl<'de, Idx> Visitor<'de> for RangeVisitor<Idx>
+1442 | |         where
+1443 | |             Idx: Deserialize<'de>,
+1444 | |         {
+...    |
+1501 | |             }
+1502 | |         }
+     | |_________^
+     |
+     = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::de::impls::<impl new::Deserialize<'de> for std::result::Result<T, E>>::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<D>(deserializer: D) -> Result<Field, D::Error>
+1556 | |             where
+...    |
+1612 | |             }
+1613 | |         }
+     | |_________^
+     |
+     = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<<new::de::impls::<impl new::Deserialize<'de> for std::result::Result<T, E>>::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 `<new::de::impls::<impl new::Deserialize<'de> for std::result::Result<T, E>>::deserialize::ResultVisitor<T, E> as new::de::Visitor<'de>>`
+    --> serde-1.0.8/src/de/impls.rs:1617:9
+     |
+1617 | /         impl<'de, T, E> Visitor<'de> for ResultVisitor<T, E>
+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 `<new::private::de::missing_field::MissingFieldDeserializer<E> as new::Deserializer<'de>>`
+  --> serde-1.0.8/src/private/de.rs:31:5
+   |
+31 | /     impl<'de, E> Deserializer<'de> for MissingFieldDeserializer<E>
+32 | |     where
+33 | |         E: Error,
+34 | |     {
+...  |
+55 | |         }
+56 | |     }
+   | |_____^
+   |
+   = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::private::de::borrow_cow_str::CowStrVisitor as new::de::Visitor<'a>>`
+   --> 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 `<new::private::de::borrow_cow_bytes::CowBytesVisitor as new::de::Visitor<'a>>`
+   --> 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 `<new::private::de::TaggedContentVisitor<'de, T> 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 `<new::private::de::TaggedContentVisitor<'de, T> 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 `<new::private::de::TagContentOtherFieldVisitor as new::de::DeserializeSeed<'de>>`
+   --> 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<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+...   |
+945 | |         }
+946 | |     }
+    | |_____^
+    |
+    = note: trait impl generalized or newly added (technically breaking)
+
+warning: technically breaking changes in `<new::private::de::TagContentOtherFieldVisitor as new::de::Visitor<'de>>`
+   --> 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 `<new::private::de::ContentDeserializer<'de, E> 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 `<new::private::de::content::EnumDeserializer<'de, E> 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 `<new::private::de::content::VariantDeserializer<'de, E> 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 `<new::private::de::content::SeqDeserializer<'de, E> 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 `<new::private::de::content::SeqDeserializer<'de, E> 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 `<new::private::de::content::MapDeserializer<'de, E> 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 `<new::private::de::content::MapDeserializer<'de, E> 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 `<new::private::de::ContentRefDeserializer<'a, 'de, E> 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 `<new::private::de::content::EnumRefDeserializer<'a, 'de, E> 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 `<new::private::de::content::VariantRefDeserializer<'a, 'de, E> 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 `<new::private::de::content::SeqRefDeserializer<'a, 'de, E> 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 `<new::private::de::content::SeqRefDeserializer<'a, 'de, E> 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 `<new::private::de::content::MapRefDeserializer<'a, 'de, E> 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 `<new::private::de::content::MapRefDeserializer<'a, 'de, E> 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 `<new::private::de::ContentDeserializer<'de, E> 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 `<new::private::de::ContentRefDeserializer<'a, 'de, E> 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 `<old::de::impls::<impl old::Deserialize<'de> 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 `<old::de::impls::<impl old::Deserialize<'de> for std::collections::VecDeque<T>>::deserialize::SeqVisitor<T> as old::de::Visitor<'de>>`
+   --> serde-1.0.0/src/de/impls.rs:522:17
+    |
+522 | /                 impl<'de, T $(, $typaram)*> Visitor<'de> for SeqVisitor<T $(, $typaram)*>
+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 `<old::de::impls::<impl old::Deserialize<'de> for std::collections::HashMap<K, V, S>>::deserialize::MapVisitor<K, V, S> 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<K, V $(, $typaram)*>
+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 `<<old::de::impls::OsStringKind as old::Deserialize<'de>>::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 `<old::de::impls::<impl old::Deserialize<'de> 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<D>(deserializer: D) -> Result<Field, D::Error>
+1218 | |             where
+1219 | |                 D: Deserializer<'de>,
+...    |
+1257 | |             }
+1258 | |         }
+     | |_________^
+     |
+     = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<<old::de::impls::<impl old::Deserialize<'de> 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 `<old::de::impls::<impl old::Deserialize<'de> 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 `<old::de::impls::<impl old::Deserialize<'de> for std::ops::Range<Idx>>::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<D>(deserializer: D) -> Result<Field, D::Error>
+1357 | |             where
+1358 | |                 D: Deserializer<'de>,
+...    |
+1396 | |             }
+1397 | |         }
+     | |_________^
+     |
+     = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<<old::de::impls::<impl old::Deserialize<'de> for std::ops::Range<Idx>>::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 `<old::de::impls::<impl old::Deserialize<'de> for std::ops::Range<Idx>>::deserialize::RangeVisitor<Idx> as old::de::Visitor<'de>>`
+    --> serde-1.0.0/src/de/impls.rs:1403:9
+     |
+1403 | /         impl<'de, Idx> Visitor<'de> for RangeVisitor<Idx>
+1404 | |         where
+1405 | |             Idx: Deserialize<'de>,
+1406 | |         {
+...    |
+1463 | |             }
+1464 | |         }
+     | |_________^
+     |
+     = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<old::de::impls::<impl old::Deserialize<'de> for std::result::Result<T, E>>::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<D>(deserializer: D) -> Result<Field, D::Error>
+1516 | |             where
+...    |
+1572 | |             }
+1573 | |         }
+     | |_________^
+     |
+     = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<<old::de::impls::<impl old::Deserialize<'de> for std::result::Result<T, E>>::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 `<old::de::impls::<impl old::Deserialize<'de> for std::result::Result<T, E>>::deserialize::ResultVisitor<T, E> as old::de::Visitor<'de>>`
+    --> serde-1.0.0/src/de/impls.rs:1577:9
+     |
+1577 | /         impl<'de, T, E> Visitor<'de> for ResultVisitor<T, E>
+1578 | |         where
+1579 | |             T: Deserialize<'de>,
+1580 | |             E: Deserialize<'de>,
+...    |
+1596 | |             }
+1597 | |         }
+     | |_________^
+     |
+     = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<old::private::de::missing_field::MissingFieldDeserializer<E> as old::Deserializer<'de>>`
+  --> serde-1.0.0/src/private/de.rs:30:5
+   |
+30 | /     impl<'de, E> Deserializer<'de> for MissingFieldDeserializer<E>
+31 | |     where
+32 | |         E: Error,
+33 | |     {
+...  |
+54 | |         }
+55 | |     }
+   | |_____^
+   |
+   = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<old::private::de::borrow_cow_str::CowStrVisitor as old::de::Visitor<'a>>`
+   --> 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 `<old::private::de::borrow_cow_bytes::CowBytesVisitor as old::de::Visitor<'a>>`
+   --> 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<u8>),
+    |         ^^^^^^^^^^^^^^^^
+
+error: breaking changes in `<old::private::de::Content as old::Deserialize<'de>>`
+   --> serde-1.0.0/src/private/de.rs:290:5
+    |
+290 | /     impl<'de> Deserialize<'de> for Content {
+291 | |         fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+292 | |         where
+293 | |             D: Deserializer<'de>,
+...   |
+298 | |         }
+299 | |     }
+    | |_____^
+    |
+    = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<old::private::de::content::ContentVisitor as old::de::Visitor<'de>>`
+   --> 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 `<old::private::de::content::TagOrContentVisitor as old::de::DeserializeSeed<'de>>`
+   --> 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<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+...   |
+508 | |         }
+509 | |     }
+    | |_____^
+    |
+    = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<old::private::de::content::TagOrContentVisitor as old::de::Visitor<'de>>`
+   --> 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<TaggedContent<'de, T>>,
+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<TaggedContent<'de, T>>,
+    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+warning: variant field removed from variant with private fields (breaking)
+   --> serde-1.0.0/src/private/de.rs:745:9
+    |
+745 |         tag: PhantomData<T>,
+    |         ^^^^^^^^^^^^^^^^^^^
+
+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 `<old::private::de::TaggedContentVisitor<T> as old::de::DeserializeSeed<'de>>`
+   --> serde-1.0.0/src/private/de.rs:759:5
+    |
+759 | /     impl<'de, T> DeserializeSeed<'de> for TaggedContentVisitor<T>
+760 | |     where
+761 | |         T: Deserialize<'de>,
+762 | |     {
+...   |
+772 | |         }
+773 | |     }
+    | |_____^
+    |
+    = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<old::private::de::TaggedContentVisitor<T> as old::de::Visitor<'de>>`
+   --> serde-1.0.0/src/private/de.rs:775:5
+    |
+775 | /     impl<'de, T> Visitor<'de> for TaggedContentVisitor<T>
+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<E>,
+973 | |     }
+    | |_____^
+    |
+    = warning: region parameter added (breaking)
+
+error: breaking changes in `<old::private::de::ContentDeserializer<E> as old::Deserializer<'de>>`
+    --> serde-1.0.0/src/private/de.rs:874:5
+     |
+874  | /     impl<'de, E> Deserializer<'de> for ContentDeserializer<E>
+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 `<old::private::de::content::EnumDeserializer<E> as old::de::EnumAccess<'de>>`
+    --> serde-1.0.0/src/private/de.rs:1021:5
+     |
+1021 | /     impl<'de, E> de::EnumAccess<'de> for EnumDeserializer<E>
+1022 | |     where
+1023 | |         E: de::Error,
+1024 | |     {
+...    |
+1038 | |         }
+1039 | |     }
+     | |_____^
+     |
+     = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<old::private::de::content::VariantDeserializer<E> as old::de::VariantAccess<'de>>`
+    --> serde-1.0.0/src/private/de.rs:1049:5
+     |
+1049 | /     impl<'de, E> de::VariantAccess<'de> for VariantDeserializer<E>
+1050 | |     where
+1051 | |         E: de::Error,
+1052 | |     {
+...    |
+1102 | |         }
+1103 | |     }
+     | |_____^
+     |
+     = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<old::private::de::content::SeqDeserializer<E> as old::Deserializer<'de>>`
+    --> serde-1.0.0/src/private/de.rs:1125:5
+     |
+1125 | /     impl<'de, E> de::Deserializer<'de> for SeqDeserializer<E>
+1126 | |     where
+1127 | |         E: de::Error,
+1128 | |     {
+...    |
+1154 | |         }
+1155 | |     }
+     | |_____^
+     |
+     = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<old::private::de::content::SeqDeserializer<E> as old::de::SeqAccess<'de>>`
+    --> serde-1.0.0/src/private/de.rs:1157:5
+     |
+1157 | /     impl<'de, E> de::SeqAccess<'de> for SeqDeserializer<E>
+1158 | |     where
+1159 | |         E: de::Error,
+1160 | |     {
+...    |
+1178 | |         }
+1179 | |     }
+     | |_____^
+     |
+     = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<old::private::de::content::MapDeserializer<E> as old::de::MapAccess<'de>>`
+    --> serde-1.0.0/src/private/de.rs:1203:5
+     |
+1203 | /     impl<'de, E> de::MapAccess<'de> for MapDeserializer<E>
+1204 | |     where
+1205 | |         E: de::Error,
+1206 | |     {
+...    |
+1234 | |         }
+1235 | |     }
+     | |_____^
+     |
+     = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<old::private::de::content::MapDeserializer<E> as old::Deserializer<'de>>`
+    --> serde-1.0.0/src/private/de.rs:1237:5
+     |
+1237 | /     impl<'de, E> de::Deserializer<'de> for MapDeserializer<E>
+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<E>,
+1367 | |     }
+     | |_____^
+     |
+     = warning: region parameter added (breaking)
+
+error: breaking changes in `<old::private::de::ContentRefDeserializer<'a, E> 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 `<old::private::de::content::EnumRefDeserializer<'a, E> 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 `<old::private::de::content::VariantRefDeserializer<'a, E> 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 `<old::private::de::content::SeqRefDeserializer<'a, E> 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 `<old::private::de::content::SeqRefDeserializer<'a, E> 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 `<old::private::de::content::MapRefDeserializer<'a, E> 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 `<old::private::de::content::MapRefDeserializer<'a, E> 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 `<old::private::de::ContentDeserializer<E> 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<E>
+1652 | |     where
+1653 | |         E: de::Error,
+1654 | |     {
+...    |
+1659 | |         }
+1660 | |     }
+     | |_____^
+     |
+     = warning: trait impl specialized or removed (breaking)
+
+error: breaking changes in `<old::private::de::ContentRefDeserializer<'a, E> 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",