From f887d55a0da741bc34d80eeeeab007f535681a4c Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 25 May 2017 20:06:58 +0200 Subject: [PATCH 001/553] Initial (boring) version of compilation driver --- .gitignore | 3 +++ Cargo.toml | 9 +++++++ src/lib.rs | 1 + src/main.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 src/lib.rs create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000..4308d822046df --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +target/ +**/*.rs.bk +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000000000..a7fa566357c2e --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "semverver" +version = "0.1.0" +authors = ["Inokentiy Babushkin "] + +[lib] +plugin = true + +[dependencies] diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000000000..8b137891791fe --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ + diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000000000..4865adbd12fea --- /dev/null +++ b/src/main.rs @@ -0,0 +1,74 @@ +#![feature(box_syntax)] +#![feature(rustc_private)] + +extern crate getopts; +extern crate rustc; +extern crate rustc_driver; +extern crate rustc_errors; +extern crate syntax; + +use rustc::session::{config, Session}; +use rustc::session::config::{Input, ErrorOutputType}; + +use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; + +use std::path::PathBuf; + +use syntax::ast; + +struct SemVerVerCompilerCalls { + default: RustcDefaultCalls, +} + +impl SemVerVerCompilerCalls { + pub fn new() -> SemVerVerCompilerCalls { + SemVerVerCompilerCalls { default: RustcDefaultCalls } + } +} + +impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { + fn early_callback(&mut self, + matches: &getopts::Matches, + sopts: &config::Options, + cfg: &ast::CrateConfig, + descriptions: &rustc_errors::registry::Registry, + output: ErrorOutputType) + -> Compilation { + self.default + .early_callback(matches, sopts, cfg, descriptions, output) + } + + fn no_input(&mut self, + matches: &getopts::Matches, + sopts: &config::Options, + cfg: &ast::CrateConfig, + odir: &Option, + ofile: &Option, + descriptions: &rustc_errors::registry::Registry) + -> Option<(Input, Option)> { + self.default + .no_input(matches, sopts, cfg, odir, ofile, descriptions) + } + + fn late_callback(&mut self, + matches: &getopts::Matches, + sess: &Session, + input: &Input, + odir: &Option, + ofile: &Option) + -> Compilation { + self.default + .late_callback(matches, sess, input, odir, ofile) + } + + fn build_controller(&mut self, + sess: &Session, + matches: &getopts::Matches) + -> driver::CompileController<'a> { + let mut controller = self.default.build_controller(sess, matches); + + controller + } +} + +pub fn main() {} From 80b7fd4bd7c0e7d75cc58b8506f4e222b7164507 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 25 May 2017 21:01:14 +0200 Subject: [PATCH 002/553] Lots of boilerplate we'll need later anyway --- Cargo.toml | 3 +++ src/main.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index a7fa566357c2e..16e4e931a8a17 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,7 @@ authors = ["Inokentiy Babushkin "] [lib] plugin = true +[[bin]] +name = "cargo-semver" + [dependencies] diff --git a/src/main.rs b/src/main.rs index 4865adbd12fea..8714a26f7f25d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -67,8 +67,60 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { -> driver::CompileController<'a> { let mut controller = self.default.build_controller(sess, matches); + let old_callback = std::mem::replace(&mut controller.after_hir_lowering.callback, + box |_| {}); + controller.after_hir_lowering.callback = box move |state| { old_callback(state); }; + controller } } -pub fn main() {} +const CARGO_SEMVER_HELP: &str = r#"Checks a package's SemVer compatibility with already published versions. + +Usage: + cargo semver [options] [--] [...] + +Common options: + -h, --help Print this message + --features Features to compile for the package + -V, --version Print version info and exit + +Other options are the same as `cargo rustc`. +"#; + +fn help() { + println!("{}", CARGO_SEMVER_HELP); +} + +fn version() { + println!("{}", env!("CARGO_PKG_VERSION")); +} + +pub fn main() { + if std::env::args().any(|arg| arg == "-h" || arg == "--help") { + help(); + return; + } + + if std::env::args().any(|arg| arg == "-V" || arg == "--version") { + version(); + return; + } + + rustc_driver::in_rustc_thread(|| { + let args: Vec = std::env::args().collect(); // TODO: look at clippy here + + // let checks_enabled = std::env::args().any(|s| s == "-Zno-trans"); + + let mut cc = SemVerVerCompilerCalls::new(); // TODO: use `checks_enabled` + // TODO: the second result is a `Session` - maybe we'll need it + let (result, _) = rustc_driver::run_compiler(&args, &mut cc, None, None); + + if let Err(count) = result { + if count > 0 { + std::process::exit(1); + } + } + }) + .expect("rustc thread failed"); +} From 7296aaf57331bfb13b38e81adfb94ff4e643abcf Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 25 May 2017 23:16:13 +0200 Subject: [PATCH 003/553] slowly incorporating metadata lookup --- Cargo.toml | 1 + src/main.rs | 28 +++++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 16e4e931a8a17..ebd7afda0474b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,4 @@ plugin = true name = "cargo-semver" [dependencies] +cargo_metadata = "^0.2.1" diff --git a/src/main.rs b/src/main.rs index 8714a26f7f25d..9f6ecdf953449 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ #![feature(box_syntax)] #![feature(rustc_private)] +extern crate cargo_metadata; extern crate getopts; extern crate rustc; extern crate rustc_driver; @@ -12,6 +13,7 @@ use rustc::session::config::{Input, ErrorOutputType}; use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; +use std::io::{self, Write}; use std::path::PathBuf; use syntax::ast; @@ -97,6 +99,9 @@ fn version() { } pub fn main() { + // TODO: use getopt, as we import it anyway + // TODO: maybe don't use cargo_metadata, as it pulls in tons of deps + if std::env::args().any(|arg| arg == "-h" || arg == "--help") { help(); return; @@ -107,6 +112,27 @@ pub fn main() { return; } + if std::env::args() + .nth(1) + .map(|arg| arg == "semver") + .unwrap_or(false) { + // first run (we blatantly copy clippy's code structure here) + let manifest_path_arg = std::env::args() + .skip(2) + .find(|val| val.starts_with("--manifest-path=")); + + let mut metadata = if let Ok(data) = + cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)) { + data + } else { + let _ = io::stderr() + .write_fmt(format_args!("error: could not obtain cargo metadata.\n")); + std::process::exit(1); + }; + } else { + // second run TODO: elaborate etc + } + rustc_driver::in_rustc_thread(|| { let args: Vec = std::env::args().collect(); // TODO: look at clippy here @@ -122,5 +148,5 @@ pub fn main() { } } }) - .expect("rustc thread failed"); + .expect("rustc thread failed"); } From fc1f381888df60cfee7bdd09be46581983490d56 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 26 May 2017 18:19:51 +0200 Subject: [PATCH 004/553] Blatantly clippy-esque cargo subcommand infrastructure This should be a first step to do the following things: * dump the relevant items from the current crate, after building all the dependencies * download the most recent stable version of the current crate * kick off a custom driver performing all the necessary work --- src/main.rs | 159 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 139 insertions(+), 20 deletions(-) diff --git a/src/main.rs b/src/main.rs index 9f6ecdf953449..9051ca82c9df3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,17 +14,22 @@ use rustc::session::config::{Input, ErrorOutputType}; use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; use std::io::{self, Write}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; +use std::process::Command; use syntax::ast; struct SemVerVerCompilerCalls { default: RustcDefaultCalls, + enabled: bool } impl SemVerVerCompilerCalls { - pub fn new() -> SemVerVerCompilerCalls { - SemVerVerCompilerCalls { default: RustcDefaultCalls } + pub fn new(enabled: bool) -> SemVerVerCompilerCalls { + SemVerVerCompilerCalls { + default: RustcDefaultCalls, + enabled: enabled, + } } } @@ -69,9 +74,11 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { -> driver::CompileController<'a> { let mut controller = self.default.build_controller(sess, matches); - let old_callback = std::mem::replace(&mut controller.after_hir_lowering.callback, - box |_| {}); - controller.after_hir_lowering.callback = box move |state| { old_callback(state); }; + if self.enabled { + let old_callback = std::mem::replace(&mut controller.after_hir_lowering.callback, + box |_| {}); + controller.after_hir_lowering.callback = box move |state| { old_callback(state); }; + } controller } @@ -117,6 +124,8 @@ pub fn main() { .map(|arg| arg == "semver") .unwrap_or(false) { // first run (we blatantly copy clippy's code structure here) + // we are being run as `cargo semver` + let manifest_path_arg = std::env::args() .skip(2) .find(|val| val.starts_with("--manifest-path=")); @@ -129,24 +138,134 @@ pub fn main() { .write_fmt(format_args!("error: could not obtain cargo metadata.\n")); std::process::exit(1); }; - } else { - // second run TODO: elaborate etc - } - rustc_driver::in_rustc_thread(|| { - let args: Vec = std::env::args().collect(); // TODO: look at clippy here + let manifest_path = manifest_path_arg.map(|arg| PathBuf::from( + Path::new(&arg["--manifest-path=".len()..]))); + + let current_dir = std::env::current_dir(); + + let package_index = metadata + .packages + .iter() + .position(|package| { + let package_manifest_path = Path::new(&package.manifest_path); + if let Some(ref path) = manifest_path { + package_manifest_path == path + } else { + let current_dir = current_dir + .as_ref() + .expect("could not read current directory"); + let package_manifest_directory = package_manifest_path + .parent() + .expect("could not find parent directory of package manifest"); + package_manifest_directory == current_dir + } + }) + .expect("could not find matching package"); - // let checks_enabled = std::env::args().any(|s| s == "-Zno-trans"); + let package = metadata.packages.remove(package_index); - let mut cc = SemVerVerCompilerCalls::new(); // TODO: use `checks_enabled` - // TODO: the second result is a `Session` - maybe we'll need it - let (result, _) = rustc_driver::run_compiler(&args, &mut cc, None, None); + for target in package.targets { + let args = std::env::args().skip(2); - if let Err(count) = result { - if count > 0 { - std::process::exit(1); + if let Some(first) = target.kind.get(0) { + if target.kind.len() > 1 || first.ends_with("lib") { + if let Err(code) = process(std::iter::once("--lib".to_owned()).chain(args)) { + std::process::exit(code); + } + } else if ["bin", "example", "test", "bench"].contains(&&**first) { + if let Err(code) = process(vec![format!("--{}", first), target.name] + .into_iter() + .chain(args)) { + std::process::exit(code); + } + } + } else { + panic!("badly formatted cargo metadata: target::kind is an empty array"); } } - }) - .expect("rustc thread failed"); + } else { + // second run: we're being run by `cargo rustc` as we set it up to happen + + let home = option_env!("RUSTUP_HOME"); + let toolchain = option_env!("RUSTUP_TOOLCHAIN"); + let sys_root = if let (Some(home), Some(toolchain)) = (home, toolchain) { + format!("{}/toolchains/{}", home, toolchain) + } else { + option_env!("SYSROOT") + .map(|s| s.to_owned()) + .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 compilation, or use rustup") + }; + + rustc_driver::in_rustc_thread(|| { + // make it possible to call `cargo-semver` directly without having to pass + // --sysroot or anything + let args: Vec = if std::env::args().any(|s| s == "--sysroot") { + std::env::args().collect() + } else { + std::env::args() + .chain(Some("--sysroot".to_owned())) + .chain(Some(sys_root)) + .collect() + }; + + // this check ensures that dependencies are built but not checked and the final + // crate is checked but not built + let checks_enabled = std::env::args().any(|s| s == "-Zno-trans"); + + let mut cc = SemVerVerCompilerCalls::new(checks_enabled); + // TODO: the second result is a `Session` - maybe we'll need it + let (result, _) = rustc_driver::run_compiler(&args, &mut cc, None, None); + + if let Err(count) = result { + if count > 0 { + std::process::exit(1); + } + } + }) + .expect("rustc thread failed"); + } +} + +fn process(old_args: I) -> Result<(), i32> + where I: Iterator +{ + let mut args = vec!["rustc".to_owned()]; + + let found_dashes = old_args.fold(false, |mut found, arg| { + found |= arg == "--"; + args.push(arg); + found + }); + + if !found_dashes { + args.push("--".to_owned()); + } + + args.push("-Zno-trans".to_owned()); + + let path = std::env::current_exe().expect("current executable path invalid"); + + let exit_status = std::process::Command::new("cargo") + .args(&args) + .env("RUSTC", path) + .spawn() + .expect("could not run cargo") + .wait() + .expect("failed to wait for cargo?"); + + if exit_status.success() { + Ok(()) + } else { + Err(exit_status.code().unwrap_or(-1)) + } } From e4c5586aa42d02613c37bbb06b09fcc989d0d946 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 26 May 2017 20:25:37 +0200 Subject: [PATCH 005/553] Minimal cleanup after we've discovered some stuff --- src/main.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 9051ca82c9df3..97f528b47b517 100644 --- a/src/main.rs +++ b/src/main.rs @@ -106,7 +106,6 @@ fn version() { } pub fn main() { - // TODO: use getopt, as we import it anyway // TODO: maybe don't use cargo_metadata, as it pulls in tons of deps if std::env::args().any(|arg| arg == "-h" || arg == "--help") { @@ -196,8 +195,7 @@ pub fn main() { .map(|s| s.to_owned()) .or_else(|| { Command::new("rustc") - .arg("--print") - .arg("sysroot") + .args(&["--print", "sysroot"]) .output() .ok() .and_then(|out| String::from_utf8(out.stdout).ok()) @@ -236,6 +234,7 @@ pub fn main() { } } +// run `cargo rustc` with `RUSTC` set to our path fn process(old_args: I) -> Result<(), i32> where I: Iterator { From 5d33d09fcd7ecaba26bf3e85e5563e921a47b290 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 26 May 2017 21:23:46 +0200 Subject: [PATCH 006/553] First implementation steps --- src/check/export_map.rs | 9 +++++++++ src/check/mod.rs | 1 + src/lib.rs | 4 ++++ src/main.rs | 3 +++ 4 files changed, 17 insertions(+) create mode 100644 src/check/export_map.rs create mode 100644 src/check/mod.rs diff --git a/src/check/export_map.rs b/src/check/export_map.rs new file mode 100644 index 0000000000000..05f90e873e88f --- /dev/null +++ b/src/check/export_map.rs @@ -0,0 +1,9 @@ +use rustc::hir; + +pub struct ModuleHier { + // TODO +} + +pub struct ExportMap { + // TODO +} diff --git a/src/check/mod.rs b/src/check/mod.rs new file mode 100644 index 0000000000000..b0be69f680d40 --- /dev/null +++ b/src/check/mod.rs @@ -0,0 +1 @@ +pub mod export_map; diff --git a/src/lib.rs b/src/lib.rs index 8b137891791fe..e9f303ebd21a7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,5 @@ +#![feature(rustc_private)] +extern crate rustc; + +pub mod check; diff --git a/src/main.rs b/src/main.rs index 97f528b47b517..14ad603f7e6ff 100644 --- a/src/main.rs +++ b/src/main.rs @@ -124,6 +124,9 @@ pub fn main() { .unwrap_or(false) { // first run (we blatantly copy clippy's code structure here) // we are being run as `cargo semver` + // + // TODO: maybe it would make sense to reuse cargo internals here to avoid the quite ugly + // dance this turns out to be :) let manifest_path_arg = std::env::args() .skip(2) From 8d86b58fc41cd0576806aa027f5e64c19d7cb897 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 27 May 2017 16:45:16 +0200 Subject: [PATCH 007/553] Started implementing the cargo subcommand As discussed, a different plan is now being followed. This means that the cargo subcommand and the custom compiler driver get separated to allow for a metadata-based approach to determine version compatibility. Both crate versions are compiled and passed as dependencies to a dummy crate. The custom compiler driver then proceeds to perform the necessary checks based on rlib metadata. --- Cargo.toml | 13 +++-- src/{main.rs => bin/cargo_semver.rs} | 73 ++++++++++++++++++++++------ src/bin/rust_semverver.rs | 1 + 3 files changed, 70 insertions(+), 17 deletions(-) rename src/{main.rs => bin/cargo_semver.rs} (80%) create mode 100644 src/bin/rust_semverver.rs diff --git a/Cargo.toml b/Cargo.toml index ebd7afda0474b..993321f3b1f4b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,11 +3,18 @@ name = "semverver" version = "0.1.0" authors = ["Inokentiy Babushkin "] -[lib] -plugin = true - [[bin]] name = "cargo-semver" +path = "src/bin/cargo_semver.rs" + +[[bin]] +name = "rust-semverver" +path = "src/bin/rust_semverver.rs" [dependencies] +cargo = "^0.18.0" cargo_metadata = "^0.2.1" +crates-io = "^0.7.0" + +[replace] +"libgit2-sys:0.6.11" = { git = "https://github.com/ibabushkin/git2-rs.git", branch = "tmp-fix-libressl"} diff --git a/src/main.rs b/src/bin/cargo_semver.rs similarity index 80% rename from src/main.rs rename to src/bin/cargo_semver.rs index 14ad603f7e6ff..21c32b9fff360 100644 --- a/src/main.rs +++ b/src/bin/cargo_semver.rs @@ -1,24 +1,68 @@ #![feature(box_syntax)] -#![feature(rustc_private)] +// #![feature(rustc_private)] -extern crate cargo_metadata; -extern crate getopts; -extern crate rustc; -extern crate rustc_driver; -extern crate rustc_errors; -extern crate syntax; +// extern crate cargo_metadata; +// extern crate getopts; +// extern crate rustc; +// extern crate rustc_driver; +// extern crate rustc_errors; +// extern crate syntax; -use rustc::session::{config, Session}; -use rustc::session::config::{Input, ErrorOutputType}; +extern crate cargo; +extern crate crates_io; -use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; +use crates_io::{Crate, Registry, Result}; -use std::io::{self, Write}; -use std::path::{Path, PathBuf}; -use std::process::Command; +use cargo::core::{Source, SourceId, Package, PackageId}; +use cargo::sources::registry::RegistrySource; +use cargo::util::CargoResult; +use cargo::util::config::Config; +use cargo::util::important_paths::{find_root_manifest_for_wd}; // TODO: use this -use syntax::ast; +// use rustc::session::{config, Session}; +// use rustc::session::config::{Input, ErrorOutputType}; +// use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; + +// use std::io::{self, Write}; +// use std::path::{Path, PathBuf}; +// use std::process::Command; + +// use syntax::ast; + +pub fn exact_search(query: &str) -> Result { + // TODO: maybe we can get this with less constants :) + let mut registry = Registry::new("https://crates.io".to_owned(), None); + + match registry.search(query, 1) { + Ok((mut crates, _)) => Ok(crates.drain(..).find(|krate| krate.name == query).unwrap()), + Err(e) => Err(e) + } +} + + +fn main() { + let config = Config::default().expect("could not obtain default config"); + + let manifest_path = find_root_manifest_for_wd(None, config.cwd()).unwrap(); + let local_package = Package::for_path(&manifest_path, &config).unwrap(); + let name = local_package.name(); + + let source_id = SourceId::crates_io(&config).unwrap(); + let mut registry_source = RegistrySource::remote(&source_id, &config); + + let remote_crate = if let Ok(res) = exact_search(name) { res } else { panic!("fail") }; + println!("we found a crate {}, version {}", remote_crate.name, remote_crate.max_version); + + let package_id = PackageId::new(&remote_crate.name, + &remote_crate.max_version, + &source_id) + .unwrap(); + + let stable_package = registry_source.download(&package_id).unwrap(); +} + +/* struct SemVerVerCompilerCalls { default: RustcDefaultCalls, enabled: bool @@ -271,3 +315,4 @@ fn process(old_args: I) -> Result<(), i32> Err(exit_status.code().unwrap_or(-1)) } } +*/ diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/src/bin/rust_semverver.rs @@ -0,0 +1 @@ +fn main() {} From 49c6d1c4b399cde9447465715401e8d88314b472 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 27 May 2017 19:09:13 +0200 Subject: [PATCH 008/553] First steps towards rlib generation as we need it --- src/bin/cargo_semver.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 21c32b9fff360..a086d51884326 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -13,7 +13,8 @@ extern crate crates_io; use crates_io::{Crate, Registry, Result}; -use cargo::core::{Source, SourceId, Package, PackageId}; +use cargo::core::{Source, SourceId, Package, PackageId, Workspace}; +use cargo::ops::{compile, CompileMode, CompileOptions}; use cargo::sources::registry::RegistrySource; use cargo::util::CargoResult; use cargo::util::config::Config; @@ -25,12 +26,12 @@ use cargo::util::important_paths::{find_root_manifest_for_wd}; // TODO: use this // use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; // use std::io::{self, Write}; -// use std::path::{Path, PathBuf}; +use std::path::{Path, PathBuf}; // use std::process::Command; // use syntax::ast; -pub fn exact_search(query: &str) -> Result { +fn exact_search(query: &str) -> Result { // TODO: maybe we can get this with less constants :) let mut registry = Registry::new("https://crates.io".to_owned(), None); @@ -40,6 +41,12 @@ pub fn exact_search(query: &str) -> Result { } } +fn generate_rlib<'a>(config: &'a Config, workspace: Workspace<'a>) -> CargoResult { + let opts = CompileOptions::default(config, CompileMode::Build); + compile(&workspace, &opts).map(|c| c.root_output) + + //compilation.binaries +} fn main() { let config = Config::default().expect("could not obtain default config"); @@ -60,6 +67,14 @@ fn main() { .unwrap(); let stable_package = registry_source.download(&package_id).unwrap(); + let stable_workspace = + if let Ok(ret) = Workspace::ephemeral(stable_package, &config, None, false) { + ret + } else { + panic!("fail2"); + }; + + println!("{:?}", generate_rlib(&config, stable_workspace)); } /* From 161ac945e2b89f8232362ad7a7aea8c9afc27ca1 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 28 May 2017 23:20:19 +0200 Subject: [PATCH 009/553] A PoC implementation of rlib discovery for the fetched crate version --- src/bin/cargo_semver.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index a086d51884326..38cbe046f1465 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -14,7 +14,7 @@ extern crate crates_io; use crates_io::{Crate, Registry, Result}; use cargo::core::{Source, SourceId, Package, PackageId, Workspace}; -use cargo::ops::{compile, CompileMode, CompileOptions}; +use cargo::ops::{compile, Compilation, CompileMode, CompileOptions}; use cargo::sources::registry::RegistrySource; use cargo::util::CargoResult; use cargo::util::config::Config; @@ -26,7 +26,7 @@ use cargo::util::important_paths::{find_root_manifest_for_wd}; // TODO: use this // use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; // use std::io::{self, Write}; -use std::path::{Path, PathBuf}; +// use std::path::{Path, PathBuf}; // use std::process::Command; // use syntax::ast; @@ -41,11 +41,11 @@ fn exact_search(query: &str) -> Result { } } -fn generate_rlib<'a>(config: &'a Config, workspace: Workspace<'a>) -> CargoResult { +fn generate_rlib<'a>(config: &'a Config, workspace: Workspace<'a>) + -> CargoResult> +{ let opts = CompileOptions::default(config, CompileMode::Build); - compile(&workspace, &opts).map(|c| c.root_output) - - //compilation.binaries + compile(&workspace, &opts).map(|c| c) } fn main() { @@ -74,7 +74,12 @@ fn main() { panic!("fail2"); }; - println!("{:?}", generate_rlib(&config, stable_workspace)); + let compilation = generate_rlib(&config, stable_workspace).unwrap(); + for i in &compilation.libraries[&package_id] { + if i.0.name() == package_id.name() { + println!("{:?}", i.1); + } + } } /* From ab0390f10cbe5aed05f996562eff59662b9acad7 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 28 May 2017 23:27:32 +0200 Subject: [PATCH 010/553] Added some info to the repo --- Cargo.toml | 3 +++ LICENSE | 30 ++++++++++++++++++++++++++++++ README.md | 4 ++++ 3 files changed, 37 insertions(+) create mode 100644 LICENSE create mode 100644 README.md diff --git a/Cargo.toml b/Cargo.toml index 993321f3b1f4b..9692c00bb2ff6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,10 @@ [package] name = "semverver" +description = "Automatic verification of SemVer adhrence in rust library crates" +repository = "https://github.com/ibabushkin/rust-semverver" version = "0.1.0" authors = ["Inokentiy Babushkin "] +license = "BSD3" [[bin]] name = "cargo-semver" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000..0a222f044ff56 --- /dev/null +++ b/LICENSE @@ -0,0 +1,30 @@ +Copyright Inokentiy Babushkin (c) 2017 + +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/README.md b/README.md new file mode 100644 index 0000000000000..77551409100f6 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# rust-semverver +This repository is hosting the development of my Google Summer of Code project. + +More details to follow soon. From 2ab730f7c5e6eaf3eccbdd871a2854b90236eced Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 29 May 2017 11:59:14 +0200 Subject: [PATCH 011/553] Revamped error handling to address #1 --- src/bin/cargo_semver.rs | 67 ++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 38cbe046f1465..493af70482eee 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -11,14 +11,15 @@ extern crate cargo; extern crate crates_io; -use crates_io::{Crate, Registry, Result}; +use crates_io::{Crate, Registry}; -use cargo::core::{Source, SourceId, Package, PackageId, Workspace}; +use cargo::exit_with_error; +use cargo::core::{Package, PackageId, Source, SourceId, Workspace}; use cargo::ops::{compile, Compilation, CompileMode, CompileOptions}; use cargo::sources::registry::RegistrySource; -use cargo::util::CargoResult; +use cargo::util::{human, CargoResult, CliError}; use cargo::util::config::Config; -use cargo::util::important_paths::{find_root_manifest_for_wd}; // TODO: use this +use cargo::util::important_paths::find_root_manifest_for_wd; // use rustc::session::{config, Session}; // use rustc::session::config::{Input, ErrorOutputType}; @@ -31,14 +32,20 @@ use cargo::util::important_paths::{find_root_manifest_for_wd}; // TODO: use this // use syntax::ast; -fn exact_search(query: &str) -> Result { +fn exact_search(query: &str) -> CargoResult { // TODO: maybe we can get this with less constants :) let mut registry = Registry::new("https://crates.io".to_owned(), None); - match registry.search(query, 1) { - Ok((mut crates, _)) => Ok(crates.drain(..).find(|krate| krate.name == query).unwrap()), - Err(e) => Err(e) - } + registry + .search(query, 1) + .map_err(|e| + human(format!("failed to retrieve search results from the registry: {}", e))) + .and_then(|(mut crates, _)| { + crates + .drain(..) + .find(|krate| krate.name == query) + .ok_or(human(format!("failed to find a matching crate `{}`", query))) + }) } fn generate_rlib<'a>(config: &'a Config, workspace: Workspace<'a>) @@ -48,38 +55,42 @@ fn generate_rlib<'a>(config: &'a Config, workspace: Workspace<'a>) compile(&workspace, &opts).map(|c| c) } -fn main() { - let config = Config::default().expect("could not obtain default config"); +fn do_main() -> CargoResult<()> { + let config = Config::default()?; - let manifest_path = find_root_manifest_for_wd(None, config.cwd()).unwrap(); - let local_package = Package::for_path(&manifest_path, &config).unwrap(); + let manifest_path = find_root_manifest_for_wd(None, config.cwd())?; + let local_package = Package::for_path(&manifest_path, &config)?; let name = local_package.name(); - let source_id = SourceId::crates_io(&config).unwrap(); + let source_id = SourceId::crates_io(&config)?; let mut registry_source = RegistrySource::remote(&source_id, &config); - let remote_crate = if let Ok(res) = exact_search(name) { res } else { panic!("fail") }; - println!("we found a crate {}, version {}", remote_crate.name, remote_crate.max_version); + let remote_crate = exact_search(name)?; - let package_id = PackageId::new(&remote_crate.name, - &remote_crate.max_version, - &source_id) - .unwrap(); + let package_id = PackageId::new(name, &remote_crate.max_version, &source_id)?; - let stable_package = registry_source.download(&package_id).unwrap(); - let stable_workspace = - if let Ok(ret) = Workspace::ephemeral(stable_package, &config, None, false) { - ret - } else { - panic!("fail2"); - }; + let stable_package = registry_source.download(&package_id)?; + let stable_workspace = Workspace::ephemeral(stable_package, &config, None, false)?; + + let compilation = generate_rlib(&config, stable_workspace)?; - let compilation = generate_rlib(&config, stable_workspace).unwrap(); for i in &compilation.libraries[&package_id] { if i.0.name() == package_id.name() { println!("{:?}", i.1); } } + + Ok(()) +} + +fn main() { + if let Err(e) = do_main() { + if let Ok(config) = Config::default() { + exit_with_error(CliError::new(e, 1), &mut config.shell()); + } else { + panic!("ffs, we can't get a config and errors happened :/"); + } + } } /* From 574a4668cc6f3555c3df54b822b8606b386e8b23 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 29 May 2017 12:09:57 +0200 Subject: [PATCH 012/553] Added rlib generation for the local crate version --- src/bin/cargo_semver.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 493af70482eee..98c8d0a8611bf 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -48,9 +48,8 @@ fn exact_search(query: &str) -> CargoResult { }) } -fn generate_rlib<'a>(config: &'a Config, workspace: Workspace<'a>) - -> CargoResult> -{ +fn generate_rlib<'a>(config: &'a Config, + workspace: Workspace<'a>) -> CargoResult> { let opts = CompileOptions::default(config, CompileMode::Build); compile(&workspace, &opts).map(|c| c) } @@ -59,9 +58,19 @@ fn do_main() -> CargoResult<()> { let config = Config::default()?; let manifest_path = find_root_manifest_for_wd(None, config.cwd())?; + let local_package = Package::for_path(&manifest_path, &config)?; + let local_workspace = Workspace::new(&manifest_path, &config)?; + let local_compilation = generate_rlib(&config, local_workspace)?; + let name = local_package.name(); + for i in &local_compilation.libraries[local_package.package_id()] { + if i.0.name() == name { + println!("{:?}", i.1); + } + } + let source_id = SourceId::crates_io(&config)?; let mut registry_source = RegistrySource::remote(&source_id, &config); @@ -71,11 +80,10 @@ fn do_main() -> CargoResult<()> { let stable_package = registry_source.download(&package_id)?; let stable_workspace = Workspace::ephemeral(stable_package, &config, None, false)?; + let stable_compilation = generate_rlib(&config, stable_workspace)?; - let compilation = generate_rlib(&config, stable_workspace)?; - - for i in &compilation.libraries[&package_id] { - if i.0.name() == package_id.name() { + for i in &stable_compilation.libraries[&package_id] { + if i.0.name() == name { println!("{:?}", i.1); } } From ad21a69d9fdf573bacf1190aae581c8805f0fd5f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 29 May 2017 12:36:56 +0200 Subject: [PATCH 013/553] Added some explanatory comments --- src/bin/cargo_semver.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 98c8d0a8611bf..117105ed02592 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -32,6 +32,9 @@ use cargo::util::important_paths::find_root_manifest_for_wd; // use syntax::ast; +/// Given a crate name, try to locate the corresponding crate on `crates.io`. +/// +/// If no crate with the exact name is present, error out. fn exact_search(query: &str) -> CargoResult { // TODO: maybe we can get this with less constants :) let mut registry = Registry::new("https://crates.io".to_owned(), None); @@ -48,12 +51,27 @@ fn exact_search(query: &str) -> CargoResult { }) } +/// Compile a crate given it's workspace. +/// +/// The results returned are then used to locate the build artefacts, which in turn are linked +/// together for the actual analysis. fn generate_rlib<'a>(config: &'a Config, workspace: Workspace<'a>) -> CargoResult> { let opts = CompileOptions::default(config, CompileMode::Build); compile(&workspace, &opts).map(|c| c) } +/// Perform the heavy lifting. +/// +/// Obtain the local crate and compile it, then fetch the latest version from the registry, and +/// build it as well. +/// +/// TODO: +/// * split this up +/// * no, seriously, split this up +/// * give some structure to the build artefact gathering +/// * possibly reduce the complexity by investigating where some of the info can be sourced from +/// in a more direct fashion fn do_main() -> CargoResult<()> { let config = Config::default()?; From f65c537b0ffd2f17a1a87cefabdb44df9d176d4b Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 29 May 2017 15:04:52 +0200 Subject: [PATCH 014/553] Added a programmatic rustc invocation --- src/bin/cargo_semver.rs | 51 +++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 117105ed02592..776a98769f17d 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -26,9 +26,9 @@ use cargo::util::important_paths::find_root_manifest_for_wd; // use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; -// use std::io::{self, Write}; +use std::io::Write; // use std::path::{Path, PathBuf}; -// use std::process::Command; +use std::process::{Stdio, Command}; // use syntax::ast; @@ -68,7 +68,6 @@ fn generate_rlib<'a>(config: &'a Config, /// /// TODO: /// * split this up -/// * no, seriously, split this up /// * give some structure to the build artefact gathering /// * possibly reduce the complexity by investigating where some of the info can be sourced from /// in a more direct fashion @@ -83,11 +82,15 @@ fn do_main() -> CargoResult<()> { let name = local_package.name(); - for i in &local_compilation.libraries[local_package.package_id()] { - if i.0.name() == name { - println!("{:?}", i.1); - } - } + let local_rlib = + local_compilation + .libraries[local_package.package_id()] + .iter() + .find(|t| t.0.name() == name) + .ok_or(human("lost a build artifact"))?; + + println!("{:?}", local_rlib.1); + println!("{:?}", local_compilation.deps_output); let source_id = SourceId::crates_io(&config)?; let mut registry_source = RegistrySource::remote(&source_id, &config); @@ -100,12 +103,36 @@ fn do_main() -> CargoResult<()> { let stable_workspace = Workspace::ephemeral(stable_package, &config, None, false)?; let stable_compilation = generate_rlib(&config, stable_workspace)?; - for i in &stable_compilation.libraries[&package_id] { - if i.0.name() == name { - println!("{:?}", i.1); - } + let stable_rlib = + stable_compilation + .libraries[&package_id] + .iter() + .find(|t| t.0.name() == name) + .ok_or(human("lost a build artifact"))?; + + println!("{:?}", stable_rlib.1); + println!("{:?}", stable_compilation.deps_output); + + let mut child = Command::new("rustc") + .arg("--crate-type=lib") + .args(&["--extern", &*format!("old={}", stable_rlib.1.display())]) + .args(&[format!("-L{}", stable_compilation.deps_output.display())]) + .args(&["--extern", &*format!("new={}", local_rlib.1.display())]) + .args(&[format!("-L{}", local_compilation.deps_output.display())]) + .arg("-") + .stdin(Stdio::piped()) + .spawn() + .expect("could not run rustc?"); + + if let Some(ref mut stdin) = child.stdin { + // TODO: proper error handling + let _ = stdin.write_fmt(format_args!("extern crate new; extern crate old;")); } + child + .wait() + .expect("failed to wait for rustc?"); + Ok(()) } From 934bcebea8c6b18951cd47064fc7a6987b724c7f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 29 May 2017 16:41:07 +0200 Subject: [PATCH 015/553] Implemented the new custom driver and integrated it Our cargo plugin now correctly constructs a virtual crate and runs our custom compiler driver on it to perform the analysis. --- src/bin/cargo_semver.rs | 213 +++++--------------------------------- src/bin/rust_semverver.rs | 118 ++++++++++++++++++++- src/check/export_map.rs | 2 +- 3 files changed, 143 insertions(+), 190 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 776a98769f17d..dd03b4005c954 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -1,12 +1,6 @@ #![feature(box_syntax)] -// #![feature(rustc_private)] // extern crate cargo_metadata; -// extern crate getopts; -// extern crate rustc; -// extern crate rustc_driver; -// extern crate rustc_errors; -// extern crate syntax; extern crate cargo; extern crate crates_io; @@ -21,17 +15,9 @@ use cargo::util::{human, CargoResult, CliError}; use cargo::util::config::Config; use cargo::util::important_paths::find_root_manifest_for_wd; -// use rustc::session::{config, Session}; -// use rustc::session::config::{Input, ErrorOutputType}; - -// use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; - use std::io::Write; -// use std::path::{Path, PathBuf}; use std::process::{Stdio, Command}; -// use syntax::ast; - /// Given a crate name, try to locate the corresponding crate on `crates.io`. /// /// If no crate with the exact name is present, error out. @@ -44,11 +30,11 @@ fn exact_search(query: &str) -> CargoResult { .map_err(|e| human(format!("failed to retrieve search results from the registry: {}", e))) .and_then(|(mut crates, _)| { - crates - .drain(..) - .find(|krate| krate.name == query) - .ok_or(human(format!("failed to find a matching crate `{}`", query))) - }) + crates + .drain(..) + .find(|krate| krate.name == query) + .ok_or_else(|| human(format!("failed to find a matching crate `{}`", query))) + }) } /// Compile a crate given it's workspace. @@ -56,9 +42,10 @@ fn exact_search(query: &str) -> CargoResult { /// The results returned are then used to locate the build artefacts, which in turn are linked /// together for the actual analysis. fn generate_rlib<'a>(config: &'a Config, - workspace: Workspace<'a>) -> CargoResult> { + workspace: &Workspace<'a>) + -> CargoResult> { let opts = CompileOptions::default(config, CompileMode::Build); - compile(&workspace, &opts).map(|c| c) + compile(workspace, &opts).map(|c| c) } /// Perform the heavy lifting. @@ -78,16 +65,14 @@ fn do_main() -> CargoResult<()> { let local_package = Package::for_path(&manifest_path, &config)?; let local_workspace = Workspace::new(&manifest_path, &config)?; - let local_compilation = generate_rlib(&config, local_workspace)?; + let local_compilation = generate_rlib(&config, &local_workspace)?; let name = local_package.name(); - let local_rlib = - local_compilation - .libraries[local_package.package_id()] - .iter() - .find(|t| t.0.name() == name) - .ok_or(human("lost a build artifact"))?; + let local_rlib = local_compilation.libraries[local_package.package_id()] + .iter() + .find(|t| t.0.name() == name) + .ok_or_else(|| human("lost a build artifact"))?; println!("{:?}", local_rlib.1); println!("{:?}", local_compilation.deps_output); @@ -101,19 +86,17 @@ fn do_main() -> CargoResult<()> { let stable_package = registry_source.download(&package_id)?; let stable_workspace = Workspace::ephemeral(stable_package, &config, None, false)?; - let stable_compilation = generate_rlib(&config, stable_workspace)?; + let stable_compilation = generate_rlib(&config, &stable_workspace)?; - let stable_rlib = - stable_compilation - .libraries[&package_id] - .iter() - .find(|t| t.0.name() == name) - .ok_or(human("lost a build artifact"))?; + let stable_rlib = stable_compilation.libraries[&package_id] + .iter() + .find(|t| t.0.name() == name) + .ok_or_else(|| human("lost a build artifact"))?; println!("{:?}", stable_rlib.1); println!("{:?}", stable_compilation.deps_output); - let mut child = Command::new("rustc") + let mut child = Command::new("rust-semverver") .arg("--crate-type=lib") .args(&["--extern", &*format!("old={}", stable_rlib.1.display())]) .args(&[format!("-L{}", stable_compilation.deps_output.display())]) @@ -122,16 +105,18 @@ fn do_main() -> CargoResult<()> { .arg("-") .stdin(Stdio::piped()) .spawn() - .expect("could not run rustc?"); + .map_err(|e| human(format!("could not spawn rustc: {}", e)))?; if let Some(ref mut stdin) = child.stdin { - // TODO: proper error handling - let _ = stdin.write_fmt(format_args!("extern crate new; extern crate old;")); + stdin + .write_fmt(format_args!("extern crate new; extern crate old;"))?; + } else { + return Err(human("could not pipe to rustc (wtf?)")); } child .wait() - .expect("failed to wait for rustc?"); + .map_err(|e| human(format!("failed to wait for rustc: {}", e)))?; Ok(()) } @@ -147,71 +132,6 @@ fn main() { } /* -struct SemVerVerCompilerCalls { - default: RustcDefaultCalls, - enabled: bool -} - -impl SemVerVerCompilerCalls { - pub fn new(enabled: bool) -> SemVerVerCompilerCalls { - SemVerVerCompilerCalls { - default: RustcDefaultCalls, - enabled: enabled, - } - } -} - -impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { - fn early_callback(&mut self, - matches: &getopts::Matches, - sopts: &config::Options, - cfg: &ast::CrateConfig, - descriptions: &rustc_errors::registry::Registry, - output: ErrorOutputType) - -> Compilation { - self.default - .early_callback(matches, sopts, cfg, descriptions, output) - } - - fn no_input(&mut self, - matches: &getopts::Matches, - sopts: &config::Options, - cfg: &ast::CrateConfig, - odir: &Option, - ofile: &Option, - descriptions: &rustc_errors::registry::Registry) - -> Option<(Input, Option)> { - self.default - .no_input(matches, sopts, cfg, odir, ofile, descriptions) - } - - fn late_callback(&mut self, - matches: &getopts::Matches, - sess: &Session, - input: &Input, - odir: &Option, - ofile: &Option) - -> Compilation { - self.default - .late_callback(matches, sess, input, odir, ofile) - } - - fn build_controller(&mut self, - sess: &Session, - matches: &getopts::Matches) - -> driver::CompileController<'a> { - let mut controller = self.default.build_controller(sess, matches); - - if self.enabled { - let old_callback = std::mem::replace(&mut controller.after_hir_lowering.callback, - box |_| {}); - controller.after_hir_lowering.callback = box move |state| { old_callback(state); }; - } - - controller - } -} - const CARGO_SEMVER_HELP: &str = r#"Checks a package's SemVer compatibility with already published versions. Usage: @@ -314,89 +234,6 @@ pub fn main() { panic!("badly formatted cargo metadata: target::kind is an empty array"); } } - } else { - // second run: we're being run by `cargo rustc` as we set it up to happen - - let home = option_env!("RUSTUP_HOME"); - let toolchain = option_env!("RUSTUP_TOOLCHAIN"); - let sys_root = if let (Some(home), Some(toolchain)) = (home, toolchain) { - format!("{}/toolchains/{}", home, toolchain) - } else { - option_env!("SYSROOT") - .map(|s| s.to_owned()) - .or_else(|| { - Command::new("rustc") - .args(&["--print", "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 compilation, or use rustup") - }; - - rustc_driver::in_rustc_thread(|| { - // make it possible to call `cargo-semver` directly without having to pass - // --sysroot or anything - let args: Vec = if std::env::args().any(|s| s == "--sysroot") { - std::env::args().collect() - } else { - std::env::args() - .chain(Some("--sysroot".to_owned())) - .chain(Some(sys_root)) - .collect() - }; - - // this check ensures that dependencies are built but not checked and the final - // crate is checked but not built - let checks_enabled = std::env::args().any(|s| s == "-Zno-trans"); - - let mut cc = SemVerVerCompilerCalls::new(checks_enabled); - // TODO: the second result is a `Session` - maybe we'll need it - let (result, _) = rustc_driver::run_compiler(&args, &mut cc, None, None); - - if let Err(count) = result { - if count > 0 { - std::process::exit(1); - } - } - }) - .expect("rustc thread failed"); - } -} - -// run `cargo rustc` with `RUSTC` set to our path -fn process(old_args: I) -> Result<(), i32> - where I: Iterator -{ - let mut args = vec!["rustc".to_owned()]; - - let found_dashes = old_args.fold(false, |mut found, arg| { - found |= arg == "--"; - args.push(arg); - found - }); - - if !found_dashes { - args.push("--".to_owned()); - } - - args.push("-Zno-trans".to_owned()); - - let path = std::env::current_exe().expect("current executable path invalid"); - - let exit_status = std::process::Command::new("cargo") - .args(&args) - .env("RUSTC", path) - .spawn() - .expect("could not run cargo") - .wait() - .expect("failed to wait for cargo?"); - - if exit_status.success() { - Ok(()) - } else { - Err(exit_status.code().unwrap_or(-1)) } } */ diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index f328e4d9d04c3..4a9da8a7dc334 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -1 +1,117 @@ -fn main() {} +#![feature(box_syntax)] +#![feature(rustc_private)] + +extern crate getopts; +extern crate rustc; +extern crate rustc_driver; +extern crate rustc_errors; +extern crate syntax; + +use rustc::session::{config, Session}; +use rustc::session::config::{Input, ErrorOutputType}; + +use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; + +use std::path::PathBuf; +use std::process::Command; + +use syntax::ast; + +struct SemVerVerCompilerCalls { + default: RustcDefaultCalls, +} + +impl SemVerVerCompilerCalls { + pub fn new() -> SemVerVerCompilerCalls { + SemVerVerCompilerCalls { default: RustcDefaultCalls } + } +} + +impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { + fn early_callback(&mut self, + matches: &getopts::Matches, + sopts: &config::Options, + cfg: &ast::CrateConfig, + descriptions: &rustc_errors::registry::Registry, + output: ErrorOutputType) + -> Compilation { + self.default + .early_callback(matches, sopts, cfg, descriptions, output) + } + + fn no_input(&mut self, + matches: &getopts::Matches, + sopts: &config::Options, + cfg: &ast::CrateConfig, + odir: &Option, + ofile: &Option, + descriptions: &rustc_errors::registry::Registry) + -> Option<(Input, Option)> { + self.default + .no_input(matches, sopts, cfg, odir, ofile, descriptions) + } + + fn late_callback(&mut self, + matches: &getopts::Matches, + sess: &Session, + input: &Input, + odir: &Option, + ofile: &Option) + -> Compilation { + self.default + .late_callback(matches, sess, input, odir, ofile) + } + + fn build_controller(&mut self, + sess: &Session, + matches: &getopts::Matches) + -> driver::CompileController<'a> { + let mut controller = self.default.build_controller(sess, matches); + + let old_callback = std::mem::replace(&mut controller.after_hir_lowering.callback, + box |_| {}); + controller.after_hir_lowering.callback = box move |state| { old_callback(state); }; + + controller + } +} + +fn main() { + let home = option_env!("RUSTUP_HOME"); + let toolchain = option_env!("RUSTUP_TOOLCHAIN"); + let sys_root = if let (Some(home), Some(toolchain)) = (home, toolchain) { + format!("{}/toolchains/{}", home, toolchain) + } else { + option_env!("SYSROOT") + .map(|s| s.to_owned()) + .or_else(|| { + Command::new("rustc") + .args(&["--print", "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 compilation, or use rustup") + }; + + rustc_driver::in_rustc_thread(|| { + let args: Vec = if std::env::args().any(|s| s == "--sysroot") { + std::env::args().collect() + } else { + std::env::args() + .chain(Some("--sysroot".to_owned())) + .chain(Some(sys_root)) + .collect() + }; + + let mut cc = SemVerVerCompilerCalls::new(); + let (result, _) = rustc_driver::run_compiler(&args, &mut cc, None, None); + if let Err(count) = result { + if count > 0 { + std::process::exit(1); + } + } + }) + .expect("rustc thread failed"); +} diff --git a/src/check/export_map.rs b/src/check/export_map.rs index 05f90e873e88f..ec57ae6523da0 100644 --- a/src/check/export_map.rs +++ b/src/check/export_map.rs @@ -1,4 +1,4 @@ -use rustc::hir; +// use rustc::hir; pub struct ModuleHier { // TODO From 96cc247cfce82324aa4c3380c8e35cbf8f8bd6a0 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 29 May 2017 17:02:42 +0200 Subject: [PATCH 016/553] Better main function Some basic help message, etc. --- Cargo.toml | 1 - src/bin/cargo_semver.rs | 101 +++++----------------------------------- 2 files changed, 11 insertions(+), 91 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9692c00bb2ff6..48f980f926cf8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,6 @@ path = "src/bin/rust_semverver.rs" [dependencies] cargo = "^0.18.0" -cargo_metadata = "^0.2.1" crates-io = "^0.7.0" [replace] diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index dd03b4005c954..1eb23ad020b73 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -1,7 +1,5 @@ #![feature(box_syntax)] -// extern crate cargo_metadata; - extern crate cargo; extern crate crates_io; @@ -74,8 +72,8 @@ fn do_main() -> CargoResult<()> { .find(|t| t.0.name() == name) .ok_or_else(|| human("lost a build artifact"))?; - println!("{:?}", local_rlib.1); - println!("{:?}", local_compilation.deps_output); + println!("{}", local_rlib.1.display()); + println!("{}", local_compilation.deps_output.display()); let source_id = SourceId::crates_io(&config)?; let mut registry_source = RegistrySource::remote(&source_id, &config); @@ -93,8 +91,8 @@ fn do_main() -> CargoResult<()> { .find(|t| t.0.name() == name) .ok_or_else(|| human("lost a build artifact"))?; - println!("{:?}", stable_rlib.1); - println!("{:?}", stable_compilation.deps_output); + println!("{}", stable_rlib.1.display()); + println!("{}", stable_compilation.deps_output.display()); let mut child = Command::new("rust-semverver") .arg("--crate-type=lib") @@ -121,28 +119,16 @@ fn do_main() -> CargoResult<()> { Ok(()) } -fn main() { - if let Err(e) = do_main() { - if let Ok(config) = Config::default() { - exit_with_error(CliError::new(e, 1), &mut config.shell()); - } else { - panic!("ffs, we can't get a config and errors happened :/"); - } - } -} - -/* const CARGO_SEMVER_HELP: &str = r#"Checks a package's SemVer compatibility with already published versions. Usage: - cargo semver [options] [--] [...] + cargo semver [options] Common options: -h, --help Print this message - --features Features to compile for the package -V, --version Print version info and exit -Other options are the same as `cargo rustc`. +Currently, no other options are supported (this will change in the future) "#; fn help() { @@ -153,9 +139,7 @@ fn version() { println!("{}", env!("CARGO_PKG_VERSION")); } -pub fn main() { - // TODO: maybe don't use cargo_metadata, as it pulls in tons of deps - +fn main() { if std::env::args().any(|arg| arg == "-h" || arg == "--help") { help(); return; @@ -166,74 +150,11 @@ pub fn main() { return; } - if std::env::args() - .nth(1) - .map(|arg| arg == "semver") - .unwrap_or(false) { - // first run (we blatantly copy clippy's code structure here) - // we are being run as `cargo semver` - // - // TODO: maybe it would make sense to reuse cargo internals here to avoid the quite ugly - // dance this turns out to be :) - - let manifest_path_arg = std::env::args() - .skip(2) - .find(|val| val.starts_with("--manifest-path=")); - - let mut metadata = if let Ok(data) = - cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)) { - data + if let Err(e) = do_main() { + if let Ok(config) = Config::default() { + exit_with_error(CliError::new(e, 1), &mut config.shell()); } else { - let _ = io::stderr() - .write_fmt(format_args!("error: could not obtain cargo metadata.\n")); - std::process::exit(1); - }; - - let manifest_path = manifest_path_arg.map(|arg| PathBuf::from( - Path::new(&arg["--manifest-path=".len()..]))); - - let current_dir = std::env::current_dir(); - - let package_index = metadata - .packages - .iter() - .position(|package| { - let package_manifest_path = Path::new(&package.manifest_path); - if let Some(ref path) = manifest_path { - package_manifest_path == path - } else { - let current_dir = current_dir - .as_ref() - .expect("could not read current directory"); - let package_manifest_directory = package_manifest_path - .parent() - .expect("could not find parent directory of package manifest"); - package_manifest_directory == current_dir - } - }) - .expect("could not find matching package"); - - let package = metadata.packages.remove(package_index); - - for target in package.targets { - let args = std::env::args().skip(2); - - if let Some(first) = target.kind.get(0) { - if target.kind.len() > 1 || first.ends_with("lib") { - if let Err(code) = process(std::iter::once("--lib".to_owned()).chain(args)) { - std::process::exit(code); - } - } else if ["bin", "example", "test", "bench"].contains(&&**first) { - if let Err(code) = process(vec![format!("--{}", first), target.name] - .into_iter() - .chain(args)) { - std::process::exit(code); - } - } - } else { - panic!("badly formatted cargo metadata: target::kind is an empty array"); - } + panic!("ffs, we can't get a config and errors happened :/"); } } } -*/ From 795cd4d52e0f0034ec6f53026f136938ace815c9 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 29 May 2017 22:00:11 +0200 Subject: [PATCH 017/553] More README details --- README.md | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 77551409100f6..25f6bc83f04ff 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,21 @@ # rust-semverver -This repository is hosting the development of my Google Summer of Code project. +This repository is hosting a proof-of-concept implementation of an automatic tool checking +rust library crates for semantic versioning adherence. The goal is to provide an automated +command akin to `cargo clippy` that analyzes the current crate's souce code for changes +compared to the most recent version on `crates.io`. -More details to follow soon. +## Background +The approach taken is to compile both versions of the crate to `rlib`s and to link them as +dependencies of a third crate. Then, a custom compiler driver is run on the resulting +crate and all necessary analysis is performed in that context. + +The general concepts and aspects of the algorithms used are outlined in more detail in the +[proposal](https://summerofcode.withgoogle.com/projects/#5063973872336896). + +## Installation +This is currently irrelevant, as the functionality is not yet implemented. Please check +back later. + +## Usage +This is currently irrelevant, as the functionality is not yet implemented. Please check +back later. From 395a8e52a44f37223a2ae291250cd7c31fb49ec8 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 30 May 2017 11:59:32 +0200 Subject: [PATCH 018/553] Implemented basic root module lookup (finally) --- src/bin/rust_semverver.rs | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 4a9da8a7dc334..51436768e5dda 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -5,8 +5,10 @@ extern crate getopts; extern crate rustc; extern crate rustc_driver; extern crate rustc_errors; +extern crate rustc_metadata; extern crate syntax; +use rustc::hir::def_id::*; use rustc::session::{config, Session}; use rustc::session::config::{Input, ErrorOutputType}; @@ -17,6 +19,27 @@ use std::process::Command; use syntax::ast; +fn callback(state: &driver::CompileState) { + let tcx = state.tcx.unwrap(); + let cstore = &tcx.sess.cstore; + + let cnums = cstore.crates().iter().fold((None, None), |(n, o), crate_num| { + let name = cstore.crate_name(*crate_num); + if name == "new" { + (Some(*crate_num), o) + } else if name == "old" { + (n, Some(*crate_num)) + } else { + (n, o) + } + }); + + let new_did = DefId { krate: cnums.0.unwrap(), index: CRATE_DEF_INDEX }; + let old_did = DefId { krate: cnums.1.unwrap(), index: CRATE_DEF_INDEX }; + + println!("new: {:?}, old: {:?}", new_did, old_did); +} + struct SemVerVerCompilerCalls { default: RustcDefaultCalls, } @@ -68,9 +91,12 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { -> driver::CompileController<'a> { let mut controller = self.default.build_controller(sess, matches); - let old_callback = std::mem::replace(&mut controller.after_hir_lowering.callback, + let old_callback = std::mem::replace(&mut controller.after_analysis.callback, box |_| {}); - controller.after_hir_lowering.callback = box move |state| { old_callback(state); }; + controller.after_analysis.callback = box move |state| { + callback(state); + old_callback(state); + }; controller } From 9c50254a14508ad00febab0d7f583af0af695ec2 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 30 May 2017 13:37:59 +0200 Subject: [PATCH 019/553] Added basic export map dumping --- src/bin/rust_semverver.rs | 10 +++++- src/check/export_map.rs | 69 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 51436768e5dda..7a662d7bf2734 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -6,14 +6,18 @@ extern crate rustc; extern crate rustc_driver; extern crate rustc_errors; extern crate rustc_metadata; +extern crate semverver; extern crate syntax; +use semverver::check::export_map::ExportMap; + use rustc::hir::def_id::*; use rustc::session::{config, Session}; use rustc::session::config::{Input, ErrorOutputType}; use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; +use std::borrow::Borrow; use std::path::PathBuf; use std::process::Command; @@ -37,7 +41,11 @@ fn callback(state: &driver::CompileState) { let new_did = DefId { krate: cnums.0.unwrap(), index: CRATE_DEF_INDEX }; let old_did = DefId { krate: cnums.1.unwrap(), index: CRATE_DEF_INDEX }; - println!("new: {:?}, old: {:?}", new_did, old_did); + let new_map = ExportMap::new(new_did, cstore.borrow()); + let old_map = ExportMap::new(old_did, cstore.borrow()); + + println!("new: {:?}", new_map); + println!("old: {:?}", old_map); } struct SemVerVerCompilerCalls { diff --git a/src/check/export_map.rs b/src/check/export_map.rs index ec57ae6523da0..c3d79a3bf0867 100644 --- a/src/check/export_map.rs +++ b/src/check/export_map.rs @@ -1,9 +1,68 @@ -// use rustc::hir; +use rustc::hir::def::Def; +use rustc::hir::def_id::*; +use rustc::middle::cstore::CrateStore; +use rustc::ty::Visibility::Public; -pub struct ModuleHier { - // TODO -} +use std::collections::{HashMap, HashSet, VecDeque}; + +pub type VisitedModSet = HashSet; + +pub type ItemSet = HashSet; + +pub type ModMap = HashMap>; +#[derive(Debug)] pub struct ExportMap { - // TODO + visited_mods: VisitedModSet, + items: ItemSet, + exports: ModMap, + root: DefId, +} + +impl ExportMap { + pub fn new(root: DefId, cstore: &CrateStore) -> ExportMap { + let (visited, items, exports) = walk_mod(root, cstore); + ExportMap { + visited_mods: visited, + items: items, + exports: exports, + root: root, + } + } +} + +fn walk_mod(root: DefId, cstore: &CrateStore) -> (VisitedModSet, ItemSet, ModMap) { + let mut visited = HashSet::new(); + let mut items = HashSet::new(); + let mut exports = HashMap::new(); + + let mut mod_queue = VecDeque::new(); + mod_queue.push_back(root); + + while let Some(mod_id) = mod_queue.pop_front() { + let mut children = cstore.item_children(mod_id); + let mut current_children = Vec::new(); + + for child in children.drain(..).filter(|c| cstore.visibility(c.def.def_id()) == Public) { + match child.def { + Def::Mod(submod_id) => + if !visited.contains(&submod_id) { + visited.insert(submod_id); + current_children.push(submod_id); + mod_queue.push_back(submod_id); + } else { + current_children.push(submod_id); + }, + def => { + let def_id = def.def_id(); + items.insert(def_id); + current_children.push(def_id); + }, + } + } + + exports.insert(mod_id, current_children); + } + + (visited, items, exports) } From adec9a83d685fd96f7d180714fb93f5563b08cf0 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 30 May 2017 15:19:49 +0200 Subject: [PATCH 020/553] Added path dumping In addition to the other data we already extract from the compiler's internal representation, we now construct a map from paths to the definition IDs. With custom {Partial,}Eq and Hash instances on a wrapper type, it should be possible to perform matching across crate boundaries now. Also note that some of the data structures we currently generate might very well be superfluous and probably will be removed in the future. --- src/check/export_map.rs | 116 ++++++++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 39 deletions(-) diff --git a/src/check/export_map.rs b/src/check/export_map.rs index c3d79a3bf0867..4cc695c2c4397 100644 --- a/src/check/export_map.rs +++ b/src/check/export_map.rs @@ -1,9 +1,11 @@ use rustc::hir::def::Def; use rustc::hir::def_id::*; +use rustc::hir::map::definitions::DefPath; use rustc::middle::cstore::CrateStore; use rustc::ty::Visibility::Public; use std::collections::{HashMap, HashSet, VecDeque}; +use std::hash::{Hash, Hasher}; pub type VisitedModSet = HashSet; @@ -11,58 +13,94 @@ pub type ItemSet = HashSet; pub type ModMap = HashMap>; +#[derive(Debug)] +pub struct Path { + inner: DefPath, +} + +impl Path { + pub fn new(inner: DefPath) -> Path { + Path { + inner: inner, + } + } + + pub fn get_inner(&self) -> &DefPath { + &self.inner + } +} + +impl PartialEq for Path { + fn eq(&self, other: &Path) -> bool { + self.inner.data == other.get_inner().data + } +} + +impl Eq for Path {} + +impl Hash for Path { + fn hash(&self, state: &mut H) { + self.inner.data.hash(state); + } +} + +pub type PathMap = HashMap; + #[derive(Debug)] pub struct ExportMap { - visited_mods: VisitedModSet, + visited: VisitedModSet, items: ItemSet, exports: ModMap, + paths: PathMap, root: DefId, } impl ExportMap { pub fn new(root: DefId, cstore: &CrateStore) -> ExportMap { - let (visited, items, exports) = walk_mod(root, cstore); - ExportMap { - visited_mods: visited, - items: items, - exports: exports, - root: root, - } - } -} + let mut visited = HashSet::new(); + let mut items = HashSet::new(); + let mut exports = HashMap::new(); + let mut paths = HashMap::new(); + + let mut mod_queue = VecDeque::new(); + mod_queue.push_back(root); -fn walk_mod(root: DefId, cstore: &CrateStore) -> (VisitedModSet, ItemSet, ModMap) { - let mut visited = HashSet::new(); - let mut items = HashSet::new(); - let mut exports = HashMap::new(); - - let mut mod_queue = VecDeque::new(); - mod_queue.push_back(root); - - while let Some(mod_id) = mod_queue.pop_front() { - let mut children = cstore.item_children(mod_id); - let mut current_children = Vec::new(); - - for child in children.drain(..).filter(|c| cstore.visibility(c.def.def_id()) == Public) { - match child.def { - Def::Mod(submod_id) => - if !visited.contains(&submod_id) { - visited.insert(submod_id); - current_children.push(submod_id); - mod_queue.push_back(submod_id); - } else { - current_children.push(submod_id); + while let Some(mod_id) = mod_queue.pop_front() { + let mut children = cstore.item_children(mod_id); + let mut current_children = Vec::new(); + + for child in + children + .drain(..) + .filter(|c| cstore.visibility(c.def.def_id()) == Public) { + match child.def { + Def::Mod(submod_id) => + if !visited.contains(&submod_id) { + visited.insert(submod_id); + current_children.push(submod_id); + mod_queue.push_back(submod_id); + } else { + current_children.push(submod_id); + }, + def => { + let def_id = def.def_id(); + items.insert(def_id); + paths.insert(Path::new(cstore.def_path(def_id)), def_id); + println!("{}", cstore.def_path(def_id).data.len()); + current_children.push(def_id); }, - def => { - let def_id = def.def_id(); - items.insert(def_id); - current_children.push(def_id); - }, + } } + + exports.insert(mod_id, current_children); } - exports.insert(mod_id, current_children); + ExportMap { + visited: visited, + items: items, + exports: exports, + paths: paths, + root: root, + } } - - (visited, items, exports) } From dfe776e0fb1a02ffdecca21265b47f3f6834758f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 30 May 2017 15:43:50 +0200 Subject: [PATCH 021/553] Primitive export map comparison We simply look at every path in both export maps and check whether the other one has it. Depending on the currently active map, this is either an addition or a deletion of an element. --- src/bin/rust_semverver.rs | 5 +++-- src/check/export_map.rs | 19 ++++++++++++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 7a662d7bf2734..67bd4855e248a 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -44,8 +44,9 @@ fn callback(state: &driver::CompileState) { let new_map = ExportMap::new(new_did, cstore.borrow()); let old_map = ExportMap::new(old_did, cstore.borrow()); - println!("new: {:?}", new_map); - println!("old: {:?}", old_map); + old_map.compare(&new_map); + println!("==========================="); + new_map.compare(&old_map); } struct SemVerVerCompilerCalls { diff --git a/src/check/export_map.rs b/src/check/export_map.rs index 4cc695c2c4397..56e8b0b19cd05 100644 --- a/src/check/export_map.rs +++ b/src/check/export_map.rs @@ -25,14 +25,14 @@ impl Path { } } - pub fn get_inner(&self) -> &DefPath { + pub fn inner(&self) -> &DefPath { &self.inner } } impl PartialEq for Path { fn eq(&self, other: &Path) -> bool { - self.inner.data == other.get_inner().data + self.inner.data == other.inner().data } } @@ -86,7 +86,6 @@ impl ExportMap { let def_id = def.def_id(); items.insert(def_id); paths.insert(Path::new(cstore.def_path(def_id)), def_id); - println!("{}", cstore.def_path(def_id).data.len()); current_children.push(def_id); }, } @@ -103,4 +102,18 @@ impl ExportMap { root: root, } } + + pub fn lookup_path(&self, path: &Path) -> Option<&DefId> { + self.paths.get(path) + } + + pub fn compare(&self, other: &ExportMap) { + for path in self.paths.keys() { + if other.lookup_path(path).is_none() { + println!("path differs: {}", path.inner().to_string_no_crate()); + } else { + println!("path same: {}", path.inner().to_string_no_crate()); + } + } + } } From 79eb47916d02ab491568e61742b7e1fef942c1bf Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 30 May 2017 21:21:02 +0200 Subject: [PATCH 022/553] Rolled our own path implementation This fixes issue #4. The rationale is as follows: The compiler ignores what path an item is imported through, it always canonicalizes paths. However, we need to know whether the set of paths has changed, so we need to integrate some simple path handling in our module traversal. --- src/check/export_map.rs | 47 +++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/src/check/export_map.rs b/src/check/export_map.rs index 56e8b0b19cd05..9e11c7870d723 100644 --- a/src/check/export_map.rs +++ b/src/check/export_map.rs @@ -1,11 +1,9 @@ use rustc::hir::def::Def; use rustc::hir::def_id::*; -use rustc::hir::map::definitions::DefPath; use rustc::middle::cstore::CrateStore; use rustc::ty::Visibility::Public; use std::collections::{HashMap, HashSet, VecDeque}; -use std::hash::{Hash, Hasher}; pub type VisitedModSet = HashSet; @@ -13,34 +11,33 @@ pub type ItemSet = HashSet; pub type ModMap = HashMap>; -#[derive(Debug)] +#[derive(Debug, Default, PartialEq, Eq, Hash)] pub struct Path { - inner: DefPath, + inner: Vec, } impl Path { - pub fn new(inner: DefPath) -> Path { + pub fn new(segments: Vec) -> Path { Path { - inner: inner, + inner: segments, } } - pub fn inner(&self) -> &DefPath { - &self.inner - } -} + pub fn extend(&self, component: String) -> Path { + let mut inner = self.inner.clone(); + inner.push(component); -impl PartialEq for Path { - fn eq(&self, other: &Path) -> bool { - self.inner.data == other.inner().data + Path::new(inner) } -} -impl Eq for Path {} + pub fn inner(&self) -> String { + let mut new = String::new(); + for component in &self.inner { + new.push_str("::"); + new.push_str(component); + } -impl Hash for Path { - fn hash(&self, state: &mut H) { - self.inner.data.hash(state); + new } } @@ -61,11 +58,10 @@ impl ExportMap { let mut items = HashSet::new(); let mut exports = HashMap::new(); let mut paths = HashMap::new(); - let mut mod_queue = VecDeque::new(); - mod_queue.push_back(root); + mod_queue.push_back((root, Path::default())); - while let Some(mod_id) = mod_queue.pop_front() { + while let Some((mod_id, mod_path)) = mod_queue.pop_front() { let mut children = cstore.item_children(mod_id); let mut current_children = Vec::new(); @@ -73,19 +69,20 @@ impl ExportMap { children .drain(..) .filter(|c| cstore.visibility(c.def.def_id()) == Public) { + let child_name = String::from(&*child.ident.name.as_str()); match child.def { Def::Mod(submod_id) => if !visited.contains(&submod_id) { visited.insert(submod_id); current_children.push(submod_id); - mod_queue.push_back(submod_id); + mod_queue.push_back((submod_id, mod_path.extend(child_name))); } else { current_children.push(submod_id); }, def => { let def_id = def.def_id(); items.insert(def_id); - paths.insert(Path::new(cstore.def_path(def_id)), def_id); + paths.insert(mod_path.extend(child_name), def_id); current_children.push(def_id); }, } @@ -110,9 +107,9 @@ impl ExportMap { pub fn compare(&self, other: &ExportMap) { for path in self.paths.keys() { if other.lookup_path(path).is_none() { - println!("path differs: {}", path.inner().to_string_no_crate()); + println!("path differs: {}", path.inner()); } else { - println!("path same: {}", path.inner().to_string_no_crate()); + println!("path same: {}", path.inner()); } } } From 11224c61f60b5c5a3932c79339e2a7e49d78f0e5 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 31 May 2017 13:46:13 +0200 Subject: [PATCH 023/553] Simple change set implementation --- src/bin/rust_semverver.rs | 6 +-- src/check/change.rs | 94 +++++++++++++++++++++++++++++++++++++++ src/check/export_map.rs | 39 +++------------- src/check/mod.rs | 2 + src/check/path.rs | 35 +++++++++++++++ src/lib.rs | 1 + 6 files changed, 142 insertions(+), 35 deletions(-) create mode 100644 src/check/change.rs create mode 100644 src/check/path.rs diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 67bd4855e248a..d225cf10a3cd1 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -9,7 +9,7 @@ extern crate rustc_metadata; extern crate semverver; extern crate syntax; -use semverver::check::export_map::ExportMap; +use semverver::check::export_map::{Checking, ExportMap}; use rustc::hir::def_id::*; use rustc::session::{config, Session}; @@ -44,9 +44,9 @@ fn callback(state: &driver::CompileState) { let new_map = ExportMap::new(new_did, cstore.borrow()); let old_map = ExportMap::new(old_did, cstore.borrow()); - old_map.compare(&new_map); + old_map.compare(&new_map, Checking::FromOld); println!("==========================="); - new_map.compare(&old_map); + new_map.compare(&old_map, Checking::FromNew); } struct SemVerVerCompilerCalls { diff --git a/src/check/change.rs b/src/check/change.rs new file mode 100644 index 0000000000000..7222a3461cfe0 --- /dev/null +++ b/src/check/change.rs @@ -0,0 +1,94 @@ +use check::path::Path; + +use rustc::hir::def::Export; + +use std::collections::BTreeSet; +use std::cmp::Ordering; + +use syntax_pos::Span; + +#[derive(PartialEq, Eq, PartialOrd, Ord)] +pub enum ChangeCategory { + Patch, + NonBreaking, + TechnicallyBreaking, + Breaking, +} + +pub use self::ChangeCategory::*; + +pub enum ChangeType { + Removal, + Addition, +} + +pub use self::ChangeType::*; + +impl ChangeType { + pub fn to_category(&self) -> ChangeCategory { + match *self { + Removal => Breaking, + Addition => TechnicallyBreaking, + } + } +} + +pub struct Change { + change_type: ChangeType, + path: Path, + export: Export, +} + +impl Change { + pub fn span(&self) -> &Span { + &self.export.span + } + + pub fn type_(&self) -> &ChangeType { + &self.change_type + } +} + +impl PartialEq for Change { + fn eq(&self, other: &Change) -> bool { + self.span() == other.span() + } +} + +impl Eq for Change {} + +impl PartialOrd for Change { + fn partial_cmp(&self, other: &Change) -> Option { + self.span().partial_cmp(other.span()) + } +} + +impl Ord for Change { + fn cmp(&self, other: &Change) -> Ordering { + self.span().cmp(other.span()) + } +} + +pub struct ChangeSet { + changes: BTreeSet, + max: ChangeCategory, +} + +impl ChangeSet { + pub fn new() -> ChangeSet { + ChangeSet { + changes: BTreeSet::new(), + max: Patch, + } + } + + pub fn add_change(&mut self, change: Change) { + let cat = change.type_().to_category(); + + if cat > self.max { + self.max = cat; + } + + self.changes.insert(change); + } +} diff --git a/src/check/export_map.rs b/src/check/export_map.rs index 9e11c7870d723..d1fb40bf61e8b 100644 --- a/src/check/export_map.rs +++ b/src/check/export_map.rs @@ -1,5 +1,7 @@ +use check::path::{Path, PathMap}; + use rustc::hir::def::Def; -use rustc::hir::def_id::*; +use rustc::hir::def_id::DefId; use rustc::middle::cstore::CrateStore; use rustc::ty::Visibility::Public; @@ -11,38 +13,11 @@ pub type ItemSet = HashSet; pub type ModMap = HashMap>; -#[derive(Debug, Default, PartialEq, Eq, Hash)] -pub struct Path { - inner: Vec, +pub enum Checking { + FromOld, + FromNew, } -impl Path { - pub fn new(segments: Vec) -> Path { - Path { - inner: segments, - } - } - - pub fn extend(&self, component: String) -> Path { - let mut inner = self.inner.clone(); - inner.push(component); - - Path::new(inner) - } - - pub fn inner(&self) -> String { - let mut new = String::new(); - for component in &self.inner { - new.push_str("::"); - new.push_str(component); - } - - new - } -} - -pub type PathMap = HashMap; - #[derive(Debug)] pub struct ExportMap { visited: VisitedModSet, @@ -104,7 +79,7 @@ impl ExportMap { self.paths.get(path) } - pub fn compare(&self, other: &ExportMap) { + pub fn compare(&self, other: &ExportMap, from: Checking) { for path in self.paths.keys() { if other.lookup_path(path).is_none() { println!("path differs: {}", path.inner()); diff --git a/src/check/mod.rs b/src/check/mod.rs index b0be69f680d40..5f88f6550eada 100644 --- a/src/check/mod.rs +++ b/src/check/mod.rs @@ -1 +1,3 @@ +pub mod change; pub mod export_map; +pub mod path; diff --git a/src/check/path.rs b/src/check/path.rs new file mode 100644 index 0000000000000..f03bfd2a3efac --- /dev/null +++ b/src/check/path.rs @@ -0,0 +1,35 @@ +use rustc::hir::def_id::DefId; + +use std::collections::HashMap; + +#[derive(Debug, Default, PartialEq, Eq, Hash)] +pub struct Path { + inner: Vec, +} + +impl Path { + pub fn new(segments: Vec) -> Path { + Path { + inner: segments, + } + } + + pub fn extend(&self, component: String) -> Path { + let mut inner = self.inner.clone(); + inner.push(component); + + Path::new(inner) + } + + pub fn inner(&self) -> String { + let mut new = String::new(); + for component in &self.inner { + new.push_str("::"); + new.push_str(component); + } + + new + } +} + +pub type PathMap = HashMap; diff --git a/src/lib.rs b/src/lib.rs index e9f303ebd21a7..4af69f5e34fc0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #![feature(rustc_private)] extern crate rustc; +extern crate syntax_pos; pub mod check; From a7a4e03a0461a53ce2f845524115cd5581818d50 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 31 May 2017 14:41:38 +0200 Subject: [PATCH 024/553] Cleaned up the module traversal --- src/bin/rust_semverver.rs | 8 +++--- src/check/change.rs | 8 ++++++ src/check/export_map.rs | 56 +++++++++++++++------------------------ src/check/path.rs | 6 ++--- 4 files changed, 37 insertions(+), 41 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index d225cf10a3cd1..ab08e383746fe 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -9,6 +9,7 @@ extern crate rustc_metadata; extern crate semverver; extern crate syntax; +use semverver::check::change::ChangeSet; use semverver::check::export_map::{Checking, ExportMap}; use rustc::hir::def_id::*; @@ -44,9 +45,10 @@ fn callback(state: &driver::CompileState) { let new_map = ExportMap::new(new_did, cstore.borrow()); let old_map = ExportMap::new(old_did, cstore.borrow()); - old_map.compare(&new_map, Checking::FromOld); - println!("==========================="); - new_map.compare(&old_map, Checking::FromNew); + let mut changes = ChangeSet::new(); + + old_map.compare(&new_map, Checking::FromOld, &mut changes); + new_map.compare(&old_map, Checking::FromNew, &mut changes); } struct SemVerVerCompilerCalls { diff --git a/src/check/change.rs b/src/check/change.rs index 7222a3461cfe0..f68668925238d 100644 --- a/src/check/change.rs +++ b/src/check/change.rs @@ -40,6 +40,14 @@ pub struct Change { } impl Change { + pub fn new(change_type: ChangeType, path: Path, export: Export) -> Change { + Change { + change_type: change_type, + path: path, + export: export, + } + } + pub fn span(&self) -> &Span { &self.export.span } diff --git a/src/check/export_map.rs b/src/check/export_map.rs index d1fb40bf61e8b..cca52cf6e956b 100644 --- a/src/check/export_map.rs +++ b/src/check/export_map.rs @@ -1,6 +1,7 @@ +use check::change::{Addition, Removal, Change, ChangeSet}; use check::path::{Path, PathMap}; -use rustc::hir::def::Def; +use rustc::hir::def::{Def, Export}; use rustc::hir::def_id::DefId; use rustc::middle::cstore::CrateStore; use rustc::ty::Visibility::Public; @@ -9,8 +10,6 @@ use std::collections::{HashMap, HashSet, VecDeque}; pub type VisitedModSet = HashSet; -pub type ItemSet = HashSet; - pub type ModMap = HashMap>; pub enum Checking { @@ -21,24 +20,18 @@ pub enum Checking { #[derive(Debug)] pub struct ExportMap { visited: VisitedModSet, - items: ItemSet, - exports: ModMap, paths: PathMap, - root: DefId, } impl ExportMap { pub fn new(root: DefId, cstore: &CrateStore) -> ExportMap { let mut visited = HashSet::new(); - let mut items = HashSet::new(); - let mut exports = HashMap::new(); let mut paths = HashMap::new(); let mut mod_queue = VecDeque::new(); mod_queue.push_back((root, Path::default())); while let Some((mod_id, mod_path)) = mod_queue.pop_front() { let mut children = cstore.item_children(mod_id); - let mut current_children = Vec::new(); for child in children @@ -46,46 +39,39 @@ impl ExportMap { .filter(|c| cstore.visibility(c.def.def_id()) == Public) { let child_name = String::from(&*child.ident.name.as_str()); match child.def { - Def::Mod(submod_id) => - if !visited.contains(&submod_id) { - visited.insert(submod_id); - current_children.push(submod_id); - mod_queue.push_back((submod_id, mod_path.extend(child_name))); - } else { - current_children.push(submod_id); - }, - def => { - let def_id = def.def_id(); - items.insert(def_id); - paths.insert(mod_path.extend(child_name), def_id); - current_children.push(def_id); + Def::Mod(submod_id) if !visited.contains(&submod_id) => { + visited.insert(submod_id); + mod_queue.push_back((submod_id, mod_path.extend(child_name.clone()))); + paths.insert(mod_path.extend(child_name), child); + }, + _ => { + paths.insert(mod_path.extend(child_name), child); }, } } - - exports.insert(mod_id, current_children); } ExportMap { visited: visited, - items: items, - exports: exports, paths: paths, - root: root, } } - pub fn lookup_path(&self, path: &Path) -> Option<&DefId> { + pub fn lookup_path(&self, path: &Path) -> Option<&Export> { self.paths.get(path) } - pub fn compare(&self, other: &ExportMap, from: Checking) { - for path in self.paths.keys() { - if other.lookup_path(path).is_none() { - println!("path differs: {}", path.inner()); - } else { - println!("path same: {}", path.inner()); - } + pub fn compare(&self, other: &ExportMap, from: Checking, changes: &mut ChangeSet) { + for (path, export) in + self.paths + .iter() + .filter(|&(p, _)| other.lookup_path(p).is_none()) { + let change_type = match from { + Checking::FromNew => Addition, + Checking::FromOld => Removal, + }; + + changes.add_change(Change::new(change_type, path.clone(), export.clone())); } } } diff --git a/src/check/path.rs b/src/check/path.rs index f03bfd2a3efac..d57f4616e81a8 100644 --- a/src/check/path.rs +++ b/src/check/path.rs @@ -1,8 +1,8 @@ -use rustc::hir::def_id::DefId; +use rustc::hir::def::Export; use std::collections::HashMap; -#[derive(Debug, Default, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] pub struct Path { inner: Vec, } @@ -32,4 +32,4 @@ impl Path { } } -pub type PathMap = HashMap; +pub type PathMap = HashMap; From 63d3f296af6fcc9c4ec47b993149d2c8e051b90a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 31 May 2017 14:51:18 +0200 Subject: [PATCH 025/553] Wired up the new change set machinery --- src/bin/rust_semverver.rs | 2 ++ src/check/change.rs | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index ab08e383746fe..c4410354e9e6d 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -49,6 +49,8 @@ fn callback(state: &driver::CompileState) { old_map.compare(&new_map, Checking::FromOld, &mut changes); new_map.compare(&old_map, Checking::FromNew, &mut changes); + + changes.output(); } struct SemVerVerCompilerCalls { diff --git a/src/check/change.rs b/src/check/change.rs index f68668925238d..56af5f6f48f20 100644 --- a/src/check/change.rs +++ b/src/check/change.rs @@ -7,7 +7,7 @@ use std::cmp::Ordering; use syntax_pos::Span; -#[derive(PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum ChangeCategory { Patch, NonBreaking, @@ -17,6 +17,7 @@ pub enum ChangeCategory { pub use self::ChangeCategory::*; +#[derive(Debug)] pub enum ChangeType { Removal, Addition, @@ -55,6 +56,10 @@ impl Change { pub fn type_(&self) -> &ChangeType { &self.change_type } + + pub fn path(&self) -> &Path { + &self.path + } } impl PartialEq for Change { @@ -99,4 +104,12 @@ impl ChangeSet { self.changes.insert(change); } + + pub fn output(&self) { + println!("max: {:?}", self.max); + + for change in &self.changes { + println!(" {:?}: {}", change.type_(), change.path().inner()); + } + } } From 3e9b53386e62a6d09f9c9cae1c09a820586b6d4f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 31 May 2017 16:16:14 +0200 Subject: [PATCH 026/553] Cleanup and docs. Things got moved around, renamed, and even both. --- src/bin/rust_semverver.rs | 62 +++++++---- src/check/change.rs | 115 ------------------- src/check/path.rs | 35 ------ src/lib.rs | 2 +- src/semcheck/changes.rs | 152 ++++++++++++++++++++++++++ src/{check => semcheck}/export_map.rs | 40 ++++--- src/{check => semcheck}/mod.rs | 2 +- src/semcheck/path.rs | 36 ++++++ 8 files changed, 253 insertions(+), 191 deletions(-) delete mode 100644 src/check/change.rs delete mode 100644 src/check/path.rs create mode 100644 src/semcheck/changes.rs rename src/{check => semcheck}/export_map.rs (63%) rename src/{check => semcheck}/mod.rs (66%) create mode 100644 src/semcheck/path.rs diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index c4410354e9e6d..ff0b7e3122b52 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -9,8 +9,8 @@ extern crate rustc_metadata; extern crate semverver; extern crate syntax; -use semverver::check::change::ChangeSet; -use semverver::check::export_map::{Checking, ExportMap}; +use semverver::semcheck::changes::ChangeSet; +use semverver::semcheck::export_map::{Checking, ExportMap}; use rustc::hir::def_id::*; use rustc::session::{config, Session}; @@ -24,28 +24,41 @@ use std::process::Command; use syntax::ast; +/// After the typechecker has finished it's work, we perform our checks. +/// +/// To compare the two well-typed crates, we first find the aptly named crates `new` and `old`, +/// find their root modules and then proceed to walk their module trees. fn callback(state: &driver::CompileState) { let tcx = state.tcx.unwrap(); let cstore = &tcx.sess.cstore; - let cnums = cstore.crates().iter().fold((None, None), |(n, o), crate_num| { - let name = cstore.crate_name(*crate_num); - if name == "new" { - (Some(*crate_num), o) - } else if name == "old" { - (n, Some(*crate_num)) - } else { - (n, o) - } - }); + let cnums = cstore + .crates() + .iter() + .fold((None, None), |(n, o), crate_num| { + let name = cstore.crate_name(*crate_num); + if name == "new" { + (Some(*crate_num), o) + } else if name == "old" { + (n, Some(*crate_num)) + } else { + (n, o) + } + }); - let new_did = DefId { krate: cnums.0.unwrap(), index: CRATE_DEF_INDEX }; - let old_did = DefId { krate: cnums.1.unwrap(), index: CRATE_DEF_INDEX }; + let new_did = DefId { + krate: cnums.0.unwrap(), + index: CRATE_DEF_INDEX, + }; + let old_did = DefId { + krate: cnums.1.unwrap(), + index: CRATE_DEF_INDEX, + }; let new_map = ExportMap::new(new_did, cstore.borrow()); let old_map = ExportMap::new(old_did, cstore.borrow()); - let mut changes = ChangeSet::new(); + let mut changes = ChangeSet::default(); old_map.compare(&new_map, Checking::FromOld, &mut changes); new_map.compare(&old_map, Checking::FromNew, &mut changes); @@ -53,13 +66,14 @@ fn callback(state: &driver::CompileState) { changes.output(); } +/// Our wrapper to control compilation. struct SemVerVerCompilerCalls { default: RustcDefaultCalls, } impl SemVerVerCompilerCalls { pub fn new() -> SemVerVerCompilerCalls { - SemVerVerCompilerCalls { default: RustcDefaultCalls } + SemVerVerCompilerCalls { default: RustcDefaultCalls } // TODO: replace with constant } } @@ -104,17 +118,20 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { -> driver::CompileController<'a> { let mut controller = self.default.build_controller(sess, matches); - let old_callback = std::mem::replace(&mut controller.after_analysis.callback, - box |_| {}); + let old_callback = std::mem::replace(&mut controller.after_analysis.callback, box |_| {}); controller.after_analysis.callback = box move |state| { - callback(state); - old_callback(state); - }; + callback(state); + old_callback(state); + }; controller } } +/// Main routine. +/// +/// Find the sysroot before passing our args to the compiler driver, after registering our custom +/// compiler driver. fn main() { let home = option_env!("RUSTUP_HOME"); let toolchain = option_env!("RUSTUP_TOOLCHAIN"); @@ -151,6 +168,5 @@ fn main() { std::process::exit(1); } } - }) - .expect("rustc thread failed"); + }).expect("rustc thread failed"); } diff --git a/src/check/change.rs b/src/check/change.rs deleted file mode 100644 index 56af5f6f48f20..0000000000000 --- a/src/check/change.rs +++ /dev/null @@ -1,115 +0,0 @@ -use check::path::Path; - -use rustc::hir::def::Export; - -use std::collections::BTreeSet; -use std::cmp::Ordering; - -use syntax_pos::Span; - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum ChangeCategory { - Patch, - NonBreaking, - TechnicallyBreaking, - Breaking, -} - -pub use self::ChangeCategory::*; - -#[derive(Debug)] -pub enum ChangeType { - Removal, - Addition, -} - -pub use self::ChangeType::*; - -impl ChangeType { - pub fn to_category(&self) -> ChangeCategory { - match *self { - Removal => Breaking, - Addition => TechnicallyBreaking, - } - } -} - -pub struct Change { - change_type: ChangeType, - path: Path, - export: Export, -} - -impl Change { - pub fn new(change_type: ChangeType, path: Path, export: Export) -> Change { - Change { - change_type: change_type, - path: path, - export: export, - } - } - - pub fn span(&self) -> &Span { - &self.export.span - } - - pub fn type_(&self) -> &ChangeType { - &self.change_type - } - - pub fn path(&self) -> &Path { - &self.path - } -} - -impl PartialEq for Change { - fn eq(&self, other: &Change) -> bool { - self.span() == other.span() - } -} - -impl Eq for Change {} - -impl PartialOrd for Change { - fn partial_cmp(&self, other: &Change) -> Option { - self.span().partial_cmp(other.span()) - } -} - -impl Ord for Change { - fn cmp(&self, other: &Change) -> Ordering { - self.span().cmp(other.span()) - } -} - -pub struct ChangeSet { - changes: BTreeSet, - max: ChangeCategory, -} - -impl ChangeSet { - pub fn new() -> ChangeSet { - ChangeSet { - changes: BTreeSet::new(), - max: Patch, - } - } - - pub fn add_change(&mut self, change: Change) { - let cat = change.type_().to_category(); - - if cat > self.max { - self.max = cat; - } - - self.changes.insert(change); - } - - pub fn output(&self) { - println!("max: {:?}", self.max); - - for change in &self.changes { - println!(" {:?}: {}", change.type_(), change.path().inner()); - } - } -} diff --git a/src/check/path.rs b/src/check/path.rs deleted file mode 100644 index d57f4616e81a8..0000000000000 --- a/src/check/path.rs +++ /dev/null @@ -1,35 +0,0 @@ -use rustc::hir::def::Export; - -use std::collections::HashMap; - -#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] -pub struct Path { - inner: Vec, -} - -impl Path { - pub fn new(segments: Vec) -> Path { - Path { - inner: segments, - } - } - - pub fn extend(&self, component: String) -> Path { - let mut inner = self.inner.clone(); - inner.push(component); - - Path::new(inner) - } - - pub fn inner(&self) -> String { - let mut new = String::new(); - for component in &self.inner { - new.push_str("::"); - new.push_str(component); - } - - new - } -} - -pub type PathMap = HashMap; diff --git a/src/lib.rs b/src/lib.rs index 4af69f5e34fc0..14baaa7a1b531 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,4 +3,4 @@ extern crate rustc; extern crate syntax_pos; -pub mod check; +pub mod semcheck; diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs new file mode 100644 index 0000000000000..6c61c2c098c05 --- /dev/null +++ b/src/semcheck/changes.rs @@ -0,0 +1,152 @@ +use semcheck::path::ExportPath; + +use rustc::hir::def::Export; + +use std::collections::BTreeSet; +use std::cmp::Ordering; + +use syntax_pos::Span; + +/// 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. +/// +/// [1]: https://github.com/rust-lang/rfcs/blob/master/text/1105-api-evolution.md +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +pub enum ChangeCategory { + /// Patch change - no change to the public API of a crate. + Patch, + /// A backwards-compatible change. + NonBreaking, + /// A breaking change that is very unlikely to cause breakage. + TechnicallyBreaking, + /// A breaking, backwards-incompatible change. + Breaking, +} + +pub use self::ChangeCategory::*; + +impl Default for ChangeCategory { + fn default() -> ChangeCategory { + Patch + } +} + +/// The types of changes we identify. +/// +/// TODO: This will be further extended in the future. +#[derive(Debug)] +pub enum ChangeType { + /// The removal of a path an item is exported through. + Removal, + /// The addition of a path for an item (which possibly didn't exist previously). + Addition, +} + +pub use self::ChangeType::*; + +impl ChangeType { + /// Map a change type to the category it is part of. + pub fn to_category(&self) -> ChangeCategory { + match *self { + Removal => Breaking, + Addition => TechnicallyBreaking, + } + } +} + +/// A change record. +/// +/// Consists of all information we need to compute semantic versioning properties of +/// the change, as well as data we use to output it in a nice fashion. +/// +/// It is important to note that the `Eq` and `Ord` instances are constucted to only +/// regard the span of the associated item export. This allows us to sort them by +/// appearance in the source, but possibly could create conflict later on. +/// TODO: decide about this. +pub struct Change { + /// The type of the change in question - see above. + change_type: ChangeType, + /// The export path this change was recorded for. + path: ExportPath, + /// The associated item's export. + export: Export, +} + +impl Change { + pub fn new(change_type: ChangeType, path: ExportPath, export: Export) -> Change { + Change { + change_type: change_type, + path: path, + export: export, + } + } + + pub fn span(&self) -> &Span { + &self.export.span + } + + pub fn type_(&self) -> &ChangeType { + &self.change_type + } + + pub fn path(&self) -> &ExportPath { + &self.path + } +} + +impl PartialEq for Change { + fn eq(&self, other: &Change) -> bool { + self.span() == other.span() + } +} + +impl Eq for Change {} + +impl PartialOrd for Change { + fn partial_cmp(&self, other: &Change) -> Option { + self.span().partial_cmp(other.span()) + } +} + +impl Ord for Change { + fn cmp(&self, other: &Change) -> Ordering { + self.span().cmp(other.span()) + } +} + +/// The total set of changes recorded for two crate versions. +#[derive(Default)] +pub struct ChangeSet { + /// The currently recorded changes. + changes: BTreeSet, + /// The most severe change category already recorded. + max: ChangeCategory, +} + +impl ChangeSet { + + /// Add a change to the set and record it's category for later use. + pub fn add_change(&mut self, change: Change) { + let cat = change.type_().to_category(); + + if cat > self.max { + self.max = cat; + } + + self.changes.insert(change); + } + + /// Format the contents of a change set for user output. + /// + /// TODO: replace this with something more sophisticated. + pub fn output(&self) { + println!("max: {:?}", self.max); + + for change in &self.changes { + println!(" {:?}: {}", change.type_(), change.path().inner()); + } + } +} diff --git a/src/check/export_map.rs b/src/semcheck/export_map.rs similarity index 63% rename from src/check/export_map.rs rename to src/semcheck/export_map.rs index cca52cf6e956b..a9557ca9bdaa8 100644 --- a/src/check/export_map.rs +++ b/src/semcheck/export_map.rs @@ -1,5 +1,5 @@ -use check::change::{Addition, Removal, Change, ChangeSet}; -use check::path::{Path, PathMap}; +use semcheck::changes::{Addition, Removal, Change, ChangeSet}; +use semcheck::path::{ExportPath, PathMap}; use rustc::hir::def::{Def, Export}; use rustc::hir::def_id::DefId; @@ -8,33 +8,38 @@ use rustc::ty::Visibility::Public; use std::collections::{HashMap, HashSet, VecDeque}; -pub type VisitedModSet = HashSet; - -pub type ModMap = HashMap>; - +/// A marker to identify the current export map. pub enum Checking { + /// We're running from the old crate's export map. FromOld, + /// We're running from the new crate's export map. FromNew, } +/// The map of all exports from a crate. +/// +/// Mapping paths to item exports. #[derive(Debug)] pub struct ExportMap { - visited: VisitedModSet, + visited: HashSet, + /// The map of paths and item exports. paths: PathMap, } impl ExportMap { + /// Construct a new export map from a root module's `DefId` and given a `CrateStore`. + /// + /// Traverses the descendents of the given module and avoids mutually recursive modules. pub fn new(root: DefId, cstore: &CrateStore) -> ExportMap { let mut visited = HashSet::new(); let mut paths = HashMap::new(); let mut mod_queue = VecDeque::new(); - mod_queue.push_back((root, Path::default())); + mod_queue.push_back((root, ExportPath::default())); while let Some((mod_id, mod_path)) = mod_queue.pop_front() { let mut children = cstore.item_children(mod_id); - for child in - children + for child in children .drain(..) .filter(|c| cstore.visibility(c.def.def_id()) == Public) { let child_name = String::from(&*child.ident.name.as_str()); @@ -43,10 +48,10 @@ impl ExportMap { visited.insert(submod_id); mod_queue.push_back((submod_id, mod_path.extend(child_name.clone()))); paths.insert(mod_path.extend(child_name), child); - }, + } _ => { paths.insert(mod_path.extend(child_name), child); - }, + } } } } @@ -57,13 +62,16 @@ impl ExportMap { } } - pub fn lookup_path(&self, path: &Path) -> Option<&Export> { + /// Get a path's corresponding item export, if present. + pub fn lookup_path(&self, path: &ExportPath) -> Option<&Export> { self.paths.get(path) } + /// Compare two change sets, where the current one serves as reference. + /// + /// Record the changes determined that way in a `ChangeSet`. pub fn compare(&self, other: &ExportMap, from: Checking, changes: &mut ChangeSet) { - for (path, export) in - self.paths + for (path, export) in self.paths .iter() .filter(|&(p, _)| other.lookup_path(p).is_none()) { let change_type = match from { @@ -71,7 +79,7 @@ impl ExportMap { Checking::FromOld => Removal, }; - changes.add_change(Change::new(change_type, path.clone(), export.clone())); + changes.add_change(Change::new(change_type, path.clone(), *export)); } } } diff --git a/src/check/mod.rs b/src/semcheck/mod.rs similarity index 66% rename from src/check/mod.rs rename to src/semcheck/mod.rs index 5f88f6550eada..3fe3b158a32f3 100644 --- a/src/check/mod.rs +++ b/src/semcheck/mod.rs @@ -1,3 +1,3 @@ -pub mod change; +pub mod changes; pub mod export_map; pub mod path; diff --git a/src/semcheck/path.rs b/src/semcheck/path.rs new file mode 100644 index 0000000000000..d1643d9a3d95f --- /dev/null +++ b/src/semcheck/path.rs @@ -0,0 +1,36 @@ +use rustc::hir::def::Export; + +use std::collections::HashMap; + +/// An export path through which an item in a crate is made available. +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] +pub struct ExportPath { + /// The components of the path, stored as simple strings. + inner: Vec, +} + +impl ExportPath { + pub fn new(segments: Vec) -> ExportPath { + ExportPath { inner: segments } + } + + pub fn extend(&self, component: String) -> ExportPath { + let mut inner = self.inner.clone(); + inner.push(component); + + ExportPath::new(inner) + } + + pub fn inner(&self) -> String { + let mut new = String::new(); + for component in &self.inner { + new.push_str("::"); + new.push_str(component); + } + + new + } +} + +/// A map of export paths to item exports. +pub type PathMap = HashMap; From 9cc82ce87419d13c65e4ecd4ab1c5e99142e5ca8 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 31 May 2017 23:49:18 +0200 Subject: [PATCH 027/553] First batch of one quickcheck test --- Cargo.toml | 3 ++ src/lib.rs | 4 +++ src/semcheck/changes.rs | 68 ++++++++++++++++++++++++++++++++++++-- src/semcheck/export_map.rs | 7 ++-- src/semcheck/path.rs | 12 +++++++ 5 files changed, 90 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 48f980f926cf8..16dfe428a67d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,5 +18,8 @@ path = "src/bin/rust_semverver.rs" cargo = "^0.18.0" crates-io = "^0.7.0" +[dev-dependencies] +quickcheck = "^0.4.1" + [replace] "libgit2-sys:0.6.11" = { git = "https://github.com/ibabushkin/git2-rs.git", branch = "tmp-fix-libressl"} diff --git a/src/lib.rs b/src/lib.rs index 14baaa7a1b531..75ec8a76afcdc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,9 @@ #![feature(rustc_private)] +#[cfg(test)] +#[macro_use] +extern crate quickcheck; + extern crate rustc; extern crate syntax_pos; diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 6c61c2c098c05..ec282860e2d14 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -37,7 +37,7 @@ impl Default for ChangeCategory { /// The types of changes we identify. /// /// TODO: This will be further extended in the future. -#[derive(Debug)] +#[derive(Clone, Debug)] pub enum ChangeType { /// The removal of a path an item is exported through. Removal, @@ -75,6 +75,8 @@ pub struct Change { export: Export, } +// TODO: test the properties imposed by ord on all our custom impls + impl Change { pub fn new(change_type: ChangeType, path: ExportPath, export: Export) -> Change { Change { @@ -126,8 +128,9 @@ pub struct ChangeSet { max: ChangeCategory, } -impl ChangeSet { +// TODO: test that the stored max is indeed the maximum of all categories +impl ChangeSet { /// Add a change to the set and record it's category for later use. pub fn add_change(&mut self, change: Change) { let cat = change.type_().to_category(); @@ -150,3 +153,64 @@ impl ChangeSet { } } } + +#[cfg(test)] +mod tests { + use quickcheck::*; + use super::*; + + use rustc::hir::def::Def; + + use syntax_pos::DUMMY_SP; + use syntax_pos::hygiene::SyntaxContext; + use syntax_pos::symbol::{Ident, Interner}; + + impl Arbitrary for ChangeType { + fn arbitrary(g: &mut G) -> ChangeType { + g.choose(&[Removal, Addition]).unwrap().clone() + } + } + + /* + impl Arbitrary for Change { + fn arbitrary(g: &mut G) -> Change { + let mut interner = Interner::new(); + let export = Export { + name: interner.intern("test"), + def: Def::Err, + span: DUMMY_SP, + }; + Change::new(Arbitrary::arbitrary(g), Arbitrary::arbitrary(g), export) + } + }*/ + + fn build_change(t: ChangeType) -> Change { + let mut interner = Interner::new(); + let ident = Ident { + name: interner.intern("test"), + ctxt: SyntaxContext::empty(), + }; + + let export = Export { + ident: ident, + def: Def::Err, + span: DUMMY_SP, + }; + + Change::new(t, ExportPath::new(vec!["this is elegant enough".to_owned()]), export) + } + + quickcheck! { + fn prop(changes: Vec) -> bool { + let mut set = ChangeSet::default(); + + let max = changes.iter().map(|c| c.to_category()).max().unwrap_or(Patch); + + for change in changes.iter() { + set.add_change(build_change(change.clone())); + } + + set.max == max + } + } +} diff --git a/src/semcheck/export_map.rs b/src/semcheck/export_map.rs index a9557ca9bdaa8..f1bc8e4c575ee 100644 --- a/src/semcheck/export_map.rs +++ b/src/semcheck/export_map.rs @@ -21,11 +21,13 @@ pub enum Checking { /// Mapping paths to item exports. #[derive(Debug)] pub struct ExportMap { - visited: HashSet, /// The map of paths and item exports. paths: PathMap, } +// TODO: test that we fetch all modules from a crate store (by iterating over all DefIds) it +// defines and comparing them to the set of known DefIds here; + impl ExportMap { /// Construct a new export map from a root module's `DefId` and given a `CrateStore`. /// @@ -57,7 +59,6 @@ impl ExportMap { } ExportMap { - visited: visited, paths: paths, } } @@ -82,4 +83,6 @@ impl ExportMap { changes.add_change(Change::new(change_type, path.clone(), *export)); } } + + // TODO: test that the compairson with oneself doesn't modify the change set } diff --git a/src/semcheck/path.rs b/src/semcheck/path.rs index d1643d9a3d95f..475f8d16efbba 100644 --- a/src/semcheck/path.rs +++ b/src/semcheck/path.rs @@ -34,3 +34,15 @@ impl ExportPath { /// A map of export paths to item exports. pub type PathMap = HashMap; + +#[cfg(test)] +pub mod tests { + use quickcheck::*; + use super::*; + + impl Arbitrary for ExportPath { + fn arbitrary(g: &mut G) -> ExportPath { + ExportPath::new(Arbitrary::arbitrary(g)) + } + } +} From e28f3d2e524fa6373dd416b3083eea58af5cf855 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 31 May 2017 23:59:26 +0200 Subject: [PATCH 028/553] Updated comments and removed cruft --- src/semcheck/changes.rs | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index ec282860e2d14..e4042302a3e6f 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -171,19 +171,7 @@ mod tests { } } - /* - impl Arbitrary for Change { - fn arbitrary(g: &mut G) -> Change { - let mut interner = Interner::new(); - let export = Export { - name: interner.intern("test"), - def: Def::Err, - span: DUMMY_SP, - }; - Change::new(Arbitrary::arbitrary(g), Arbitrary::arbitrary(g), export) - } - }*/ - + /// We build these by hand, because symbols can't be sent between threads. fn build_change(t: ChangeType) -> Change { let mut interner = Interner::new(); let ident = Ident { @@ -201,7 +189,8 @@ mod tests { } quickcheck! { - fn prop(changes: Vec) -> bool { + /// The maximal change category for a change set gets computed correctly. + fn prop_max_change(changes: Vec) -> bool { let mut set = ChangeSet::default(); let max = changes.iter().map(|c| c.to_category()).max().unwrap_or(Patch); From 89708817cec8166372f05ba178c7eab42d5d5012 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 1 Jun 2017 10:09:52 +0200 Subject: [PATCH 029/553] More and better tests --- src/semcheck/changes.rs | 65 ++++++++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 11 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index e4042302a3e6f..87a9a8f9c9666 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -75,8 +75,6 @@ pub struct Change { export: Export, } -// TODO: test the properties imposed by ord on all our custom impls - impl Change { pub fn new(change_type: ChangeType, path: ExportPath, export: Export) -> Change { Change { @@ -128,8 +126,6 @@ pub struct ChangeSet { max: ChangeCategory, } -// TODO: test that the stored max is indeed the maximum of all categories - impl ChangeSet { /// Add a change to the set and record it's category for later use. pub fn add_change(&mut self, change: Change) { @@ -161,18 +157,43 @@ mod tests { use rustc::hir::def::Def; - use syntax_pos::DUMMY_SP; + use std::cmp::{max, min}; + + use syntax_pos::BytePos; use syntax_pos::hygiene::SyntaxContext; use syntax_pos::symbol::{Ident, Interner}; + #[derive(Clone, Debug)] + struct Span_(Span); + + impl Span_ { + pub fn inner(self) -> Span { + self.0 + } + } + + impl Arbitrary for Span_ { + fn arbitrary(g: &mut G) -> Span_ { + let a: u32 = Arbitrary::arbitrary(g); + let b: u32 = Arbitrary::arbitrary(g); + Span_(Span { + lo: BytePos(min(a, b)), + hi: BytePos(max(a, b)), + ctxt: SyntaxContext::empty() + }) + } + } + impl Arbitrary for ChangeType { fn arbitrary(g: &mut G) -> ChangeType { g.choose(&[Removal, Addition]).unwrap().clone() } } + type Change_ = (ChangeType, Span_); + /// We build these by hand, because symbols can't be sent between threads. - fn build_change(t: ChangeType) -> Change { + fn build_change(t: ChangeType, s: Span) -> Change { let mut interner = Interner::new(); let ident = Ident { name: interner.intern("test"), @@ -182,21 +203,43 @@ mod tests { let export = Export { ident: ident, def: Def::Err, - span: DUMMY_SP, + span: s, }; Change::new(t, ExportPath::new(vec!["this is elegant enough".to_owned()]), export) } quickcheck! { + fn ord_change_transitive(c1: Change_, c2: Change_, c3: Change_) -> bool { + let ch1 = build_change(c1.0, c1.1.inner()); + let ch2 = build_change(c2.0, c2.1.inner()); + let ch3 = build_change(c3.0, c3.1.inner()); + + 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 gets computed correctly. - fn prop_max_change(changes: Vec) -> bool { + fn max_change(changes: Vec) -> bool { let mut set = ChangeSet::default(); - let max = changes.iter().map(|c| c.to_category()).max().unwrap_or(Patch); + let max = changes.iter().map(|c| c.0.to_category()).max().unwrap_or(Patch); - for change in changes.iter() { - set.add_change(build_change(change.clone())); + for &(ref change, ref span) in changes.iter() { + set.add_change(build_change(change.clone(), span.clone().inner())); } set.max == max From 4ff661899acda751b42052db6b2e99f13e40a8c2 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 1 Jun 2017 17:43:34 +0200 Subject: [PATCH 030/553] Added travis integration --- .travis.yml | 5 +++++ src/semcheck/changes.rs | 1 + 2 files changed, 6 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000000..b4f863c8792cf --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: rust +rust: + - stable + - beta + - nightly diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 87a9a8f9c9666..3f9482ba87fd5 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -210,6 +210,7 @@ mod tests { } quickcheck! { + /// The `Ord` instance of `Change` obeys transitivity. fn ord_change_transitive(c1: Change_, c2: Change_, c3: Change_) -> bool { let ch1 = build_change(c1.0, c1.1.inner()); let ch2 = build_change(c2.0, c2.1.inner()); From 5bb81caa76e8c8468b573ee9d3fe40227816c08b Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 1 Jun 2017 17:52:08 +0200 Subject: [PATCH 031/553] Attempt #1 to fix travis build --- .travis.yml | 20 ++++++++++++++++++-- README.md | 1 + 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b4f863c8792cf..6256af76b247a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,21 @@ language: rust + rust: - - stable - - beta - nightly + +os: + - linux + +addons: + apt: + sources: + - kalakris-cmake + packages: + - cmake + - libcurl4-openssl-dev + - libelf-dev + - libdw-dev + +script: + - cargo build --verbose + - cargo test --verbose diff --git a/README.md b/README.md index 25f6bc83f04ff..d7922f8dd07db 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # rust-semverver +[![Build Status](https://travis-ci.org/ibabushkin/rust-semverver.svg?branch=master)](https://travis-ci.org/ibabushkin/rust-semverver) This repository is hosting a proof-of-concept implementation of an automatic tool checking rust library crates for semantic versioning adherence. The goal is to provide an automated command akin to `cargo clippy` that analyzes the current crate's souce code for changes From 91778d9639e98146f1ef9badf5c22936d524a5bd Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 1 Jun 2017 19:24:18 +0200 Subject: [PATCH 032/553] More tests --- README.md | 1 + src/semcheck/changes.rs | 16 +++++++--- src/semcheck/export_map.rs | 62 +++++++++++++++++++++++++++++++++++++- src/semcheck/path.rs | 2 +- 4 files changed, 75 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d7922f8dd07db..16b2e9c588c14 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # rust-semverver [![Build Status](https://travis-ci.org/ibabushkin/rust-semverver.svg?branch=master)](https://travis-ci.org/ibabushkin/rust-semverver) + This repository is hosting a proof-of-concept implementation of an automatic tool checking rust library crates for semantic versioning adherence. The goal is to provide an automated command akin to `cargo clippy` that analyzes the current crate's souce code for changes diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 3f9482ba87fd5..e16efd9c5683b 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -138,6 +138,14 @@ impl ChangeSet { self.changes.insert(change); } + /// Check for emptyness. + /// + /// Currently only used in tests. + #[cfg(test)] + pub fn is_empty(&self) -> bool { + self.changes.is_empty() + } + /// Format the contents of a change set for user output. /// /// TODO: replace this with something more sophisticated. @@ -151,9 +159,9 @@ impl ChangeSet { } #[cfg(test)] -mod tests { +pub mod tests { use quickcheck::*; - use super::*; + pub use super::*; use rustc::hir::def::Def; @@ -164,7 +172,7 @@ mod tests { use syntax_pos::symbol::{Ident, Interner}; #[derive(Clone, Debug)] - struct Span_(Span); + pub struct Span_(Span); impl Span_ { pub fn inner(self) -> Span { @@ -190,7 +198,7 @@ mod tests { } } - type Change_ = (ChangeType, Span_); + pub type Change_ = (ChangeType, Span_); /// We build these by hand, because symbols can't be sent between threads. fn build_change(t: ChangeType, s: Span) -> Change { diff --git a/src/semcheck/export_map.rs b/src/semcheck/export_map.rs index f1bc8e4c575ee..18cff2a9cc7a5 100644 --- a/src/semcheck/export_map.rs +++ b/src/semcheck/export_map.rs @@ -63,6 +63,16 @@ impl ExportMap { } } + /// Construct an empty export map without filling it. + /// + /// This is used for testing and similar tasks. + #[cfg(test)] + fn construct(paths: PathMap) -> ExportMap { + ExportMap { + paths: paths, + } + } + /// Get a path's corresponding item export, if present. pub fn lookup_path(&self, path: &ExportPath) -> Option<&Export> { self.paths.get(path) @@ -83,6 +93,56 @@ impl ExportMap { changes.add_change(Change::new(change_type, path.clone(), *export)); } } +} + +#[cfg(test)] +pub mod tests { + pub use super::*; + + use semcheck::changes::tests as changes; + use semcheck::path::tests as path; + + use syntax_pos::hygiene::SyntaxContext; + use syntax_pos::symbol::{Ident, Interner}; + + pub type ChangeType = Vec<(changes::Span_, path::ExportPath)>; + + pub fn build_export_map(change_data: ChangeType) -> ExportMap { + let mut paths = HashMap::new(); + + let mut interner = Interner::new(); - // TODO: test that the compairson with oneself doesn't modify the change set + for &(ref span, ref path) in change_data.iter() { + let ident = Ident { + name: interner.intern("test"), + ctxt: SyntaxContext::empty(), + }; + + let export = Export { + ident: ident, + def: Def::Err, + span: span.clone().inner(), + }; + + paths.insert(path.clone(), export); + } + + ExportMap::construct(paths) + } + + quickcheck! { + /// If we compare an export map to itself, it shouldn't detect any changes. + /// + /// FIXME: this is *very slow* + fn self_compare_unchanged(change_data: ChangeType) -> bool { + let mut change_set = ChangeSet::default(); + + let export_map = build_export_map(change_data); + + export_map.compare(&export_map, Checking::FromOld, &mut change_set); + export_map.compare(&export_map, Checking::FromNew, &mut change_set); + + change_set.is_empty() + } + } } diff --git a/src/semcheck/path.rs b/src/semcheck/path.rs index 475f8d16efbba..ff502d82e8a5a 100644 --- a/src/semcheck/path.rs +++ b/src/semcheck/path.rs @@ -38,7 +38,7 @@ pub type PathMap = HashMap; #[cfg(test)] pub mod tests { use quickcheck::*; - use super::*; + pub use super::*; impl Arbitrary for ExportPath { fn arbitrary(g: &mut G) -> ExportPath { From f7c17d3b0957d6daca2488f389324adaa47172a7 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 2 Jun 2017 20:46:28 +0200 Subject: [PATCH 033/553] More preparation for a better output system --- src/bin/rust_semverver.rs | 2 +- src/lib.rs | 3 +++ src/semcheck/changes.rs | 5 ++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index ff0b7e3122b52..88dbea77c6f70 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -63,7 +63,7 @@ fn callback(state: &driver::CompileState) { old_map.compare(&new_map, Checking::FromOld, &mut changes); new_map.compare(&old_map, Checking::FromNew, &mut changes); - changes.output(); + changes.output(&tcx.sess); } /// Our wrapper to control compilation. diff --git a/src/lib.rs b/src/lib.rs index 75ec8a76afcdc..006d5a0b1ebaa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,13 @@ #![feature(rustc_private)] +#![feature(rustc_diagnostic_macros)] #[cfg(test)] #[macro_use] extern crate quickcheck; extern crate rustc; +extern crate rustc_errors; +extern crate syntax; extern crate syntax_pos; pub mod semcheck; diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index e16efd9c5683b..037444f5a59bd 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -1,6 +1,7 @@ use semcheck::path::ExportPath; use rustc::hir::def::Export; +use rustc::session::Session; use std::collections::BTreeSet; use std::cmp::Ordering; @@ -149,11 +150,13 @@ impl ChangeSet { /// Format the contents of a change set for user output. /// /// TODO: replace this with something more sophisticated. - pub fn output(&self) { + pub fn output(&self, session: &Session) { println!("max: {:?}", self.max); for change in &self.changes { println!(" {:?}: {}", change.type_(), change.path().inner()); + // span_note!(session, change.span(), "S0001"); + // session.span_warn(*change.span(), "change"); } } } From 5d997d019a990836480142c5091ff7d1b3b9f3db Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 5 Jun 2017 15:39:17 +0200 Subject: [PATCH 034/553] Fixed correctness issues we had before Until now, we returned incorrect results when the same item got reexported multiple times. This was because we compared changes based on the spans of the affected items only, which in this case would clash, leading to items missing pseudo-randomly. The `{Partial,}{Eq,Ord}` instances of `Change` have been amended to include the export path as well, to avoid this issue. --- src/bin/cargo_semver.rs | 6 ------ src/semcheck/changes.rs | 12 +++++++++--- src/semcheck/export_map.rs | 2 ++ src/semcheck/path.rs | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 1eb23ad020b73..c3640aac08411 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -72,9 +72,6 @@ fn do_main() -> CargoResult<()> { .find(|t| t.0.name() == name) .ok_or_else(|| human("lost a build artifact"))?; - println!("{}", local_rlib.1.display()); - println!("{}", local_compilation.deps_output.display()); - let source_id = SourceId::crates_io(&config)?; let mut registry_source = RegistrySource::remote(&source_id, &config); @@ -91,9 +88,6 @@ fn do_main() -> CargoResult<()> { .find(|t| t.0.name() == name) .ok_or_else(|| human("lost a build artifact"))?; - println!("{}", stable_rlib.1.display()); - println!("{}", stable_compilation.deps_output.display()); - let mut child = Command::new("rust-semverver") .arg("--crate-type=lib") .args(&["--extern", &*format!("old={}", stable_rlib.1.display())]) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 037444f5a59bd..e4bbf02e7de5e 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -100,7 +100,7 @@ impl Change { impl PartialEq for Change { fn eq(&self, other: &Change) -> bool { - self.span() == other.span() + self.span() == other.span() && self.path() == other.path() } } @@ -108,13 +108,19 @@ impl Eq for Change {} impl PartialOrd for Change { fn partial_cmp(&self, other: &Change) -> Option { - self.span().partial_cmp(other.span()) + if let Some(ord1) = self.span().partial_cmp(other.span()) { + if let Some(ord2) = self.path().partial_cmp(other.path()) { + return Some(ord1.then(ord2)); + } + } + + None } } impl Ord for Change { fn cmp(&self, other: &Change) -> Ordering { - self.span().cmp(other.span()) + self.span().cmp(other.span()).then(self.path().cmp(other.path())) } } diff --git a/src/semcheck/export_map.rs b/src/semcheck/export_map.rs index 18cff2a9cc7a5..f004f34001ef9 100644 --- a/src/semcheck/export_map.rs +++ b/src/semcheck/export_map.rs @@ -90,6 +90,8 @@ impl ExportMap { Checking::FromOld => Removal, }; + println!("{:?}", path.clone()); + changes.add_change(Change::new(change_type, path.clone(), *export)); } } diff --git a/src/semcheck/path.rs b/src/semcheck/path.rs index ff502d82e8a5a..4ff06379dc94c 100644 --- a/src/semcheck/path.rs +++ b/src/semcheck/path.rs @@ -3,7 +3,7 @@ use rustc::hir::def::Export; use std::collections::HashMap; /// An export path through which an item in a crate is made available. -#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct ExportPath { /// The components of the path, stored as simple strings. inner: Vec, From b32b05a927c796c74ce8b86aa5b7aeb0b1fca965 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 5 Jun 2017 17:02:05 +0200 Subject: [PATCH 035/553] Added tests to prevent ordering bugs --- src/semcheck/changes.rs | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index e4bbf02e7de5e..bc42f30a99c26 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -64,9 +64,8 @@ impl ChangeType { /// the change, as well as data we use to output it in a nice fashion. /// /// It is important to note that the `Eq` and `Ord` instances are constucted to only -/// regard the span of the associated item export. This allows us to sort them by -/// appearance in the source, but possibly could create conflict later on. -/// TODO: decide about this. +/// regard the span and path of the associated item export. This allows us to sort them +/// by appearance in the source, but possibly could create conflict later on. pub struct Change { /// The type of the change in question - see above. change_type: ChangeType, @@ -262,5 +261,33 @@ pub mod tests { set.max == max } + + /// Different spans imply different items. + fn change_span_neq(c1: Change_, c2: Change_) -> bool { + let s1 = c1.1.inner(); + let s2 = c2.1.inner(); + + if s1 != s2 { + let ch1 = build_change(c1.0, s1); + let ch2 = build_change(c2.0, s2); + + ch1 != ch2 + } else { + true + } + } + + /// Different paths imply different items. + fn change_path_neq(c1: Change_, c2: ChangeType) -> bool { + let span = c1.1.inner(); + let ch1 = build_change(c1.0, span.clone()); + let ch2 = build_change(c2, span); + + if ch1.path() != ch2.path() { + ch1 != ch2 + } else { + true + } + } } } From a7861940609ce6fba8db166d18fcd3c3751e98d9 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 5 Jun 2017 22:42:32 +0200 Subject: [PATCH 036/553] Added some stuff to help with testing --- src/bin/rust_semverver.rs | 68 +++++++++++++++++++++++++++------------ src/semcheck/changes.rs | 6 ++-- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 88dbea77c6f70..dfcc7beb8a6a1 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -32,27 +32,55 @@ fn callback(state: &driver::CompileState) { let tcx = state.tcx.unwrap(); let cstore = &tcx.sess.cstore; - let cnums = cstore - .crates() - .iter() - .fold((None, None), |(n, o), crate_num| { - let name = cstore.crate_name(*crate_num); - if name == "new" { - (Some(*crate_num), o) - } else if name == "old" { - (n, Some(*crate_num)) - } else { - (n, o) - } - }); + let (new_did, old_did) = if std::env::var("RUST_SEMVERVER_TEST").is_err() { + // this is an actual program run + let cnums = cstore + .crates() + .iter() + .fold((None, None), |(n, o), crate_num| { + let name = cstore.crate_name(*crate_num); + if name == "new" { + (Some(*crate_num), o) + } else if name == "old" { + (n, Some(*crate_num)) + } else { + (n, o) + } + }); + + let new_did = DefId { + krate: cnums.0.unwrap(), + index: CRATE_DEF_INDEX, + }; + let old_did = DefId { + krate: cnums.1.unwrap(), + index: CRATE_DEF_INDEX, + }; - let new_did = DefId { - krate: cnums.0.unwrap(), - index: CRATE_DEF_INDEX, - }; - let old_did = DefId { - krate: cnums.1.unwrap(), - index: CRATE_DEF_INDEX, + (new_did, old_did) + } else { + // we are testing, so just fetch the *modules* `old` and `new` + let mod_id = DefId { + krate: LOCAL_CRATE, + index: CRATE_DEF_INDEX, + }; + + let mut children = cstore.item_children(mod_id); + + let dids = children + .drain(..) + .fold((mod_id, mod_id), |(n, o), child| { + let child_name = String::from(&*child.ident.name.as_str()); + if child_name == "new" { + (child.def.def_id(), o) + } else if child_name == "old" { + (n, child.def.def_id()) + } else { + (n, o) + } + }); + + dids }; let new_map = ExportMap::new(new_did, cstore.borrow()); diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index bc42f30a99c26..ec6bd26b02c4f 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -226,7 +226,7 @@ pub mod tests { } quickcheck! { - /// The `Ord` instance of `Change` obeys transitivity. + /// The `Ord` instance of `Change` is transitive. fn ord_change_transitive(c1: Change_, c2: Change_, c3: Change_) -> bool { let ch1 = build_change(c1.0, c1.1.inner()); let ch2 = build_change(c2.0, c2.1.inner()); @@ -262,7 +262,7 @@ pub mod tests { set.max == max } - /// Different spans imply different items. + /// Difference in spans implies difference in `Change`s. fn change_span_neq(c1: Change_, c2: Change_) -> bool { let s1 = c1.1.inner(); let s2 = c2.1.inner(); @@ -277,7 +277,7 @@ pub mod tests { } } - /// Different paths imply different items. + /// Difference in paths implies difference in `Change`s. fn change_path_neq(c1: Change_, c2: ChangeType) -> bool { let span = c1.1.inner(); let ch1 = build_change(c1.0, span.clone()); From 2bf3f20eacfaca5da3947382fde9e974eacbf6a8 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 5 Jun 2017 23:10:46 +0200 Subject: [PATCH 037/553] Added an example test runner --- tests/examples.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 tests/examples.rs diff --git a/tests/examples.rs b/tests/examples.rs new file mode 100644 index 0000000000000..b1aaa6edf502d --- /dev/null +++ b/tests/examples.rs @@ -0,0 +1,49 @@ +use std::fs::File; +use std::os::unix::io::{AsRawFd, FromRawFd}; +use std::process::{Command, Stdio}; + +#[test] +fn examples() { + let mut exe_path = std::env::current_dir().unwrap(); + loop { + if let Some(fname) = exe_path.file_name() { + if fname == "rust-semverver" { + exe_path.join("target/debug/rust-semverver"); + break; + } + } + + if !exe_path.pop() { + panic!("blergh"); + } + } + + let mut success = true; + + // FIXME: this assumes a different dir + for file in std::fs::read_dir("tests/examples").unwrap().map(|f| f.unwrap().path()) { + if file.extension().map_or(false, |e| e == "rs") { + let out_file = file.with_extension("out"); + let output = File::create(&out_file).unwrap(); + let fd = output.as_raw_fd(); + let out = unsafe {Stdio::from_raw_fd(fd)}; + let err = unsafe {Stdio::from_raw_fd(fd)}; + + let _ = Command::new(exe_path.clone()) + .arg("--crate-type=lib") + .arg(file) + .env("RUST_SEMVERVER_TEST", "1") + .stdin(Stdio::null()) + .stdout(out) + .stderr(err) + .spawn(); + success &= Command::new("git") + .args(&["diff", "--exit-code", out_file.to_str().unwrap()]) + .status() + .unwrap() + .success(); + } + } + + assert!(success, "an error occured"); +} From b717da2aa22e53d4adbb3a4c8b17a9868e24267e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 5 Jun 2017 23:28:37 +0200 Subject: [PATCH 038/553] Fixed test runner and added first integration test --- tests/examples.rs | 20 ++++--- tests/examples/removal.out | 110 +++++++++++++++++++++++++++++++++++++ tests/examples/removal.rs | 7 +++ 3 files changed, 130 insertions(+), 7 deletions(-) create mode 100644 tests/examples/removal.out create mode 100644 tests/examples/removal.rs diff --git a/tests/examples.rs b/tests/examples.rs index b1aaa6edf502d..a5b32d3a2a774 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -1,23 +1,25 @@ use std::fs::File; use std::os::unix::io::{AsRawFd, FromRawFd}; +use std::path::Path; use std::process::{Command, Stdio}; #[test] fn examples() { - let mut exe_path = std::env::current_dir().unwrap(); + let mut cur_path = std::env::current_dir().unwrap(); loop { - if let Some(fname) = exe_path.file_name() { + if let Some(fname) = cur_path.file_name() { if fname == "rust-semverver" { - exe_path.join("target/debug/rust-semverver"); break; } } - if !exe_path.pop() { + if !cur_path.pop() { panic!("blergh"); } } + let exe_path = cur_path.join(Path::new("target/debug/rust-semverver")); + let mut success = true; // FIXME: this assumes a different dir @@ -26,17 +28,21 @@ fn examples() { let out_file = file.with_extension("out"); let output = File::create(&out_file).unwrap(); let fd = output.as_raw_fd(); - let out = unsafe {Stdio::from_raw_fd(fd)}; + //let out = unsafe {Stdio::from_raw_fd(fd)}; let err = unsafe {Stdio::from_raw_fd(fd)}; let _ = Command::new(exe_path.clone()) .arg("--crate-type=lib") .arg(file) .env("RUST_SEMVERVER_TEST", "1") + .env("RUST_BACKTRACE", "full") .stdin(Stdio::null()) - .stdout(out) + .stdout(Stdio::null()) .stderr(err) - .spawn(); + .status(); + + println!("{:?}", exe_path); + success &= Command::new("git") .args(&["diff", "--exit-code", out_file.to_str().unwrap()]) .status() diff --git a/tests/examples/removal.out b/tests/examples/removal.out new file mode 100644 index 0000000000000..5a35e5425373a --- /dev/null +++ b/tests/examples/removal.out @@ -0,0 +1,110 @@ +warning: struct is never used: `Abc` + --> tests/examples/basic.rs:2:5 + | +2 | pub struct Abc {} + | ^^^^^^^^^^^^^^^^^ + | + = note: #[warn(dead_code)] on by default + +thread 'rustc' panicked at 'called `Option::unwrap()` on a `None` value', /checkout/src/libcore/option.rs:335 +stack backtrace: + 0: 0x7f139e9b03e3 - std::sys::imp::backtrace::tracing::imp::unwind_backtrace::hcab99e0793da62c7 + at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49 + 1: 0x7f139e9ab39a - std::sys_common::backtrace::_print::hbfe5b0c7e79c0711 + at /checkout/src/libstd/sys_common/backtrace.rs:71 + 2: 0x7f139e9bf1aa - std::panicking::default_hook::{{closure}}::h9ba2c6973907a2be + at /checkout/src/libstd/sys_common/backtrace.rs:60 + at /checkout/src/libstd/panicking.rs:355 + 3: 0x7f139e9bedab - std::panicking::default_hook::he4d55e2dd21c3cca + at /checkout/src/libstd/panicking.rs:371 + 4: 0x7f139e9bf5bb - std::panicking::rust_panic_with_hook::ha138c05cd33ad44d + at /checkout/src/libstd/panicking.rs:549 + 5: 0x7f139e9bf494 - std::panicking::begin_panic::hcdbfa35c94142fa2 + at /checkout/src/libstd/panicking.rs:511 + 6: 0x7f139e9bf3c9 - std::panicking::begin_panic_fmt::hc09fe500d9b7be81 + at /checkout/src/libstd/panicking.rs:495 + 7: 0x7f139e9bf357 - rust_begin_unwind + at /checkout/src/libstd/panicking.rs:471 + 8: 0x7f139ea0762d - core::panicking::panic_fmt::h883a028e9f4b4457 + at /checkout/src/libcore/panicking.rs:69 + 9: 0x7f139ea07564 - core::panicking::panic::hdb3cf3207dda37bb + at /checkout/src/libcore/panicking.rs:49 + 10: 0x7f139d54c5bd - rustc_metadata::cstore::CStore::get_crate_data::h445ab0320781c30b + 11: 0x7f139d539c44 - rustc_metadata::cstore_impl::::item_children::h81f6f098556fec3e + 12: 0x55d71974b93a - rust_semverver::callback::h961cda43d644d484 + at /home/twk/gsoc/rust-semverver/src/bin/rust_semverver.rs:68 + 13: 0x55d71974c430 - >::build_controller::{{closure}}::hbf52b5b070796df8 + at /home/twk/gsoc/rust-semverver/src/bin/rust_semverver.rs:151 + 14: 0x7f139f7d0900 - rustc_driver::driver::compile_input::{{closure}}::h5dd0b6da256c9f40 + 15: 0x7f139f7f4c8c - rustc_driver::driver::phase_3_run_analysis_passes::{{closure}}::h5ee2deada840296d + 16: 0x7f139f7ef21b - rustc_driver::driver::phase_3_run_analysis_passes::hbc88dd193ceb02a2 + 17: 0x7f139f7cd860 - rustc_driver::driver::compile_input::h22316d34abd2e92e + 18: 0x7f139f816086 - rustc_driver::run_compiler::he2000b3a5ab5e49a + 19: 0x55d71974ccc3 - rust_semverver::main::{{closure}}::hfa63611fbdf249ba + at /home/twk/gsoc/rust-semverver/src/bin/rust_semverver.rs:193 + 20: 0x55d71971ca6a - std::sys_common::backtrace::__rust_begin_short_backtrace::h76a8599ef2491d7a + at /checkout/src/libstd/sys_common/backtrace.rs:136 + 21: 0x55d71971d90a - std::thread::Builder::spawn::{{closure}}::{{closure}}::h90f183c75e2a9e24 + at /checkout/src/libstd/thread/mod.rs:364 + 22: 0x55d7197487fa - as core::ops::FnOnce<()>>::call_once::h8efd35a7243e084f + at /checkout/src/libstd/panic.rs:296 + 23: 0x55d71971de67 - std::panicking::try::do_call::h7e716e63e0d08d1a + at /checkout/src/libstd/panicking.rs:454 + 24: 0x7f139e9c890a - __rust_maybe_catch_panic + at /checkout/src/libpanic_unwind/lib.rs:98 + 25: 0x55d71971dd1d - std::panicking::try::h310202eb16363da5 + at /checkout/src/libstd/panicking.rs:433 + 26: 0x55d71971cf01 - std::panic::catch_unwind::h346b7cad9419fbb9 + at /checkout/src/libstd/panic.rs:361 + 27: 0x55d71971d76a - std::thread::Builder::spawn::{{closure}}::h2d8ab74385184d58 + at /checkout/src/libstd/thread/mod.rs:363 + 28: 0x55d7197361c7 - >::call_box::hb62016c613268c9c + at /checkout/src/liballoc/boxed.rs:648 + 29: 0x7f139e9bdfb5 - std::sys::imp::thread::Thread::new::thread_start::h227b2afaa9316a8d + at /checkout/src/liballoc/boxed.rs:658 + at /checkout/src/libstd/sys_common/thread.rs:21 + at /checkout/src/libstd/sys/unix/thread.rs:84 + 30: 0x7f139e717213 - start_thread + at /builddir/glibc-2.25/nptl/pthread_create.c:456 + 31: 0x7f139e24316e - clone + at ../sysdeps/unix/sysv/linux/x86_64/clone.S:97 + 32: 0x0 - +thread 'main' panicked at 'rustc thread failed: Any', /checkout/src/libcore/result.rs:859 +stack backtrace: + 0: 0x7f139e9b03e3 - std::sys::imp::backtrace::tracing::imp::unwind_backtrace::hcab99e0793da62c7 + at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49 + 1: 0x7f139e9ab39a - std::sys_common::backtrace::_print::hbfe5b0c7e79c0711 + at /checkout/src/libstd/sys_common/backtrace.rs:71 + 2: 0x7f139e9bf1aa - std::panicking::default_hook::{{closure}}::h9ba2c6973907a2be + at /checkout/src/libstd/sys_common/backtrace.rs:60 + at /checkout/src/libstd/panicking.rs:355 + 3: 0x7f139e9bedab - std::panicking::default_hook::he4d55e2dd21c3cca + at /checkout/src/libstd/panicking.rs:371 + 4: 0x7f139e9bf5bb - std::panicking::rust_panic_with_hook::ha138c05cd33ad44d + at /checkout/src/libstd/panicking.rs:549 + 5: 0x7f139e9bf494 - std::panicking::begin_panic::hcdbfa35c94142fa2 + at /checkout/src/libstd/panicking.rs:511 + 6: 0x7f139e9bf3c9 - std::panicking::begin_panic_fmt::hc09fe500d9b7be81 + at /checkout/src/libstd/panicking.rs:495 + 7: 0x7f139e9bf357 - rust_begin_unwind + at /checkout/src/libstd/panicking.rs:471 + 8: 0x7f139ea0762d - core::panicking::panic_fmt::h883a028e9f4b4457 + at /checkout/src/libcore/panicking.rs:69 + 9: 0x55d71973617a - core::result::unwrap_failed::h834326e7b6af2497 + at /checkout/src/libcore/macros.rs:29 + 10: 0x55d7197212d6 - >::expect::h09bfbddf509147ed + at /checkout/src/libcore/result.rs:761 + 11: 0x55d71974c70c - rust_semverver::main::hec9b0208f30ee0af + at /home/twk/gsoc/rust-semverver/src/bin/rust_semverver.rs:182 + 12: 0x7f139e9c890a - __rust_maybe_catch_panic + at /checkout/src/libpanic_unwind/lib.rs:98 + 13: 0x7f139e9c0458 - std::rt::lang_start::ha09816a4e25587ea + at /checkout/src/libstd/panicking.rs:433 + at /checkout/src/libstd/panic.rs:361 + at /checkout/src/libstd/rt.rs:59 + 14: 0x55d71974cdf2 - main + 15: 0x7f139e17b4e0 - __libc_start_main + at ../csu/libc-start.c:295 + 16: 0x55d71970be09 - _start + at ../sysdeps/x86_64/start.S:120 + 17: 0x0 - diff --git a/tests/examples/removal.rs b/tests/examples/removal.rs new file mode 100644 index 0000000000000..63dff4dcd58ba --- /dev/null +++ b/tests/examples/removal.rs @@ -0,0 +1,7 @@ +mod old { + pub struct Abc {} +} + +mod new { + +} From e7d360c0d0e922088085e90020a15925d2d0e389 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 6 Jun 2017 11:42:35 +0200 Subject: [PATCH 039/553] Fixed integration test suite --- .gitignore | 1 + src/bin/rust_semverver.rs | 19 +++++-- tests/examples.rs | 42 ++++++++++++-- tests/examples/removal.out | 113 +------------------------------------ tests/examples/removal.rs | 6 +- 5 files changed, 57 insertions(+), 124 deletions(-) diff --git a/.gitignore b/.gitignore index 4308d822046df..99a4f151eec77 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ target/ **/*.rs.bk Cargo.lock +*.rlib diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index dfcc7beb8a6a1..930299fad45ba 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -47,7 +47,6 @@ fn callback(state: &driver::CompileState) { (n, o) } }); - let new_did = DefId { krate: cnums.0.unwrap(), index: CRATE_DEF_INDEX, @@ -60,16 +59,26 @@ fn callback(state: &driver::CompileState) { (new_did, old_did) } else { // we are testing, so just fetch the *modules* `old` and `new` - let mod_id = DefId { - krate: LOCAL_CRATE, + let cnum = cstore + .crates() + .iter() + .fold(None, |k, crate_num| { + if cstore.crate_name(*crate_num) == "oldandnew" { + Some(*crate_num) + } else { + k + } + }); + let mod_did = DefId { + krate: cnum.unwrap(), index: CRATE_DEF_INDEX, }; - let mut children = cstore.item_children(mod_id); + let mut children = cstore.item_children(mod_did); let dids = children .drain(..) - .fold((mod_id, mod_id), |(n, o), child| { + .fold((mod_did, mod_did), |(n, o), child| { let child_name = String::from(&*child.ident.name.as_str()); if child_name == "new" { (child.def.def_id(), o) diff --git a/tests/examples.rs b/tests/examples.rs index a5b32d3a2a774..cbe223e150ca9 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -1,4 +1,5 @@ use std::fs::File; +use std::io::Write; use std::os::unix::io::{AsRawFd, FromRawFd}; use std::path::Path; use std::process::{Command, Stdio}; @@ -30,18 +31,42 @@ fn examples() { let fd = output.as_raw_fd(); //let out = unsafe {Stdio::from_raw_fd(fd)}; let err = unsafe {Stdio::from_raw_fd(fd)}; + let out = unsafe {Stdio::from_raw_fd(fd)}; - let _ = Command::new(exe_path.clone()) - .arg("--crate-type=lib") + success &= Command::new("rustc") + .args(&["--crate-type=lib", "-o", "liboldandnew.rlib"]) .arg(file) - .env("RUST_SEMVERVER_TEST", "1") + .env("RUST_LOG", "debug") .env("RUST_BACKTRACE", "full") .stdin(Stdio::null()) - .stdout(Stdio::null()) + .status() + .unwrap() + .success(); + + let mut child = Command::new(exe_path.clone()) + .args(&["--crate-type=lib", + "--extern", + "oldandnew=liboldandnew.rlib", + "-"]) + .env("RUST_SEMVERVER_TEST", "1") + .env("RUST_LOG", "debug") + .env("RUST_BACKTRACE", "full") + .stdin(Stdio::piped()) + .stdout(out) .stderr(err) - .status(); + .spawn() + .unwrap(); + + if let Some(ref mut stdin) = child.stdin { + stdin.write_fmt(format_args!("extern crate oldandnew;")).unwrap(); + } else { + panic!("could not pipe to rustc (wtf?)"); + } - println!("{:?}", exe_path); + success &= child + .wait() + .unwrap() + .success(); success &= Command::new("git") .args(&["diff", "--exit-code", out_file.to_str().unwrap()]) @@ -51,5 +76,10 @@ fn examples() { } } + Command::new("rm") + .arg("liboldandnew.rlib") + .status() + .unwrap(); + assert!(success, "an error occured"); } diff --git a/tests/examples/removal.out b/tests/examples/removal.out index 5a35e5425373a..62fca1ee936f2 100644 --- a/tests/examples/removal.out +++ b/tests/examples/removal.out @@ -1,110 +1,3 @@ -warning: struct is never used: `Abc` - --> tests/examples/basic.rs:2:5 - | -2 | pub struct Abc {} - | ^^^^^^^^^^^^^^^^^ - | - = note: #[warn(dead_code)] on by default - -thread 'rustc' panicked at 'called `Option::unwrap()` on a `None` value', /checkout/src/libcore/option.rs:335 -stack backtrace: - 0: 0x7f139e9b03e3 - std::sys::imp::backtrace::tracing::imp::unwind_backtrace::hcab99e0793da62c7 - at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49 - 1: 0x7f139e9ab39a - std::sys_common::backtrace::_print::hbfe5b0c7e79c0711 - at /checkout/src/libstd/sys_common/backtrace.rs:71 - 2: 0x7f139e9bf1aa - std::panicking::default_hook::{{closure}}::h9ba2c6973907a2be - at /checkout/src/libstd/sys_common/backtrace.rs:60 - at /checkout/src/libstd/panicking.rs:355 - 3: 0x7f139e9bedab - std::panicking::default_hook::he4d55e2dd21c3cca - at /checkout/src/libstd/panicking.rs:371 - 4: 0x7f139e9bf5bb - std::panicking::rust_panic_with_hook::ha138c05cd33ad44d - at /checkout/src/libstd/panicking.rs:549 - 5: 0x7f139e9bf494 - std::panicking::begin_panic::hcdbfa35c94142fa2 - at /checkout/src/libstd/panicking.rs:511 - 6: 0x7f139e9bf3c9 - std::panicking::begin_panic_fmt::hc09fe500d9b7be81 - at /checkout/src/libstd/panicking.rs:495 - 7: 0x7f139e9bf357 - rust_begin_unwind - at /checkout/src/libstd/panicking.rs:471 - 8: 0x7f139ea0762d - core::panicking::panic_fmt::h883a028e9f4b4457 - at /checkout/src/libcore/panicking.rs:69 - 9: 0x7f139ea07564 - core::panicking::panic::hdb3cf3207dda37bb - at /checkout/src/libcore/panicking.rs:49 - 10: 0x7f139d54c5bd - rustc_metadata::cstore::CStore::get_crate_data::h445ab0320781c30b - 11: 0x7f139d539c44 - rustc_metadata::cstore_impl::::item_children::h81f6f098556fec3e - 12: 0x55d71974b93a - rust_semverver::callback::h961cda43d644d484 - at /home/twk/gsoc/rust-semverver/src/bin/rust_semverver.rs:68 - 13: 0x55d71974c430 - >::build_controller::{{closure}}::hbf52b5b070796df8 - at /home/twk/gsoc/rust-semverver/src/bin/rust_semverver.rs:151 - 14: 0x7f139f7d0900 - rustc_driver::driver::compile_input::{{closure}}::h5dd0b6da256c9f40 - 15: 0x7f139f7f4c8c - rustc_driver::driver::phase_3_run_analysis_passes::{{closure}}::h5ee2deada840296d - 16: 0x7f139f7ef21b - rustc_driver::driver::phase_3_run_analysis_passes::hbc88dd193ceb02a2 - 17: 0x7f139f7cd860 - rustc_driver::driver::compile_input::h22316d34abd2e92e - 18: 0x7f139f816086 - rustc_driver::run_compiler::he2000b3a5ab5e49a - 19: 0x55d71974ccc3 - rust_semverver::main::{{closure}}::hfa63611fbdf249ba - at /home/twk/gsoc/rust-semverver/src/bin/rust_semverver.rs:193 - 20: 0x55d71971ca6a - std::sys_common::backtrace::__rust_begin_short_backtrace::h76a8599ef2491d7a - at /checkout/src/libstd/sys_common/backtrace.rs:136 - 21: 0x55d71971d90a - std::thread::Builder::spawn::{{closure}}::{{closure}}::h90f183c75e2a9e24 - at /checkout/src/libstd/thread/mod.rs:364 - 22: 0x55d7197487fa - as core::ops::FnOnce<()>>::call_once::h8efd35a7243e084f - at /checkout/src/libstd/panic.rs:296 - 23: 0x55d71971de67 - std::panicking::try::do_call::h7e716e63e0d08d1a - at /checkout/src/libstd/panicking.rs:454 - 24: 0x7f139e9c890a - __rust_maybe_catch_panic - at /checkout/src/libpanic_unwind/lib.rs:98 - 25: 0x55d71971dd1d - std::panicking::try::h310202eb16363da5 - at /checkout/src/libstd/panicking.rs:433 - 26: 0x55d71971cf01 - std::panic::catch_unwind::h346b7cad9419fbb9 - at /checkout/src/libstd/panic.rs:361 - 27: 0x55d71971d76a - std::thread::Builder::spawn::{{closure}}::h2d8ab74385184d58 - at /checkout/src/libstd/thread/mod.rs:363 - 28: 0x55d7197361c7 - >::call_box::hb62016c613268c9c - at /checkout/src/liballoc/boxed.rs:648 - 29: 0x7f139e9bdfb5 - std::sys::imp::thread::Thread::new::thread_start::h227b2afaa9316a8d - at /checkout/src/liballoc/boxed.rs:658 - at /checkout/src/libstd/sys_common/thread.rs:21 - at /checkout/src/libstd/sys/unix/thread.rs:84 - 30: 0x7f139e717213 - start_thread - at /builddir/glibc-2.25/nptl/pthread_create.c:456 - 31: 0x7f139e24316e - clone - at ../sysdeps/unix/sysv/linux/x86_64/clone.S:97 - 32: 0x0 - -thread 'main' panicked at 'rustc thread failed: Any', /checkout/src/libcore/result.rs:859 -stack backtrace: - 0: 0x7f139e9b03e3 - std::sys::imp::backtrace::tracing::imp::unwind_backtrace::hcab99e0793da62c7 - at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49 - 1: 0x7f139e9ab39a - std::sys_common::backtrace::_print::hbfe5b0c7e79c0711 - at /checkout/src/libstd/sys_common/backtrace.rs:71 - 2: 0x7f139e9bf1aa - std::panicking::default_hook::{{closure}}::h9ba2c6973907a2be - at /checkout/src/libstd/sys_common/backtrace.rs:60 - at /checkout/src/libstd/panicking.rs:355 - 3: 0x7f139e9bedab - std::panicking::default_hook::he4d55e2dd21c3cca - at /checkout/src/libstd/panicking.rs:371 - 4: 0x7f139e9bf5bb - std::panicking::rust_panic_with_hook::ha138c05cd33ad44d - at /checkout/src/libstd/panicking.rs:549 - 5: 0x7f139e9bf494 - std::panicking::begin_panic::hcdbfa35c94142fa2 - at /checkout/src/libstd/panicking.rs:511 - 6: 0x7f139e9bf3c9 - std::panicking::begin_panic_fmt::hc09fe500d9b7be81 - at /checkout/src/libstd/panicking.rs:495 - 7: 0x7f139e9bf357 - rust_begin_unwind - at /checkout/src/libstd/panicking.rs:471 - 8: 0x7f139ea0762d - core::panicking::panic_fmt::h883a028e9f4b4457 - at /checkout/src/libcore/panicking.rs:69 - 9: 0x55d71973617a - core::result::unwrap_failed::h834326e7b6af2497 - at /checkout/src/libcore/macros.rs:29 - 10: 0x55d7197212d6 - >::expect::h09bfbddf509147ed - at /checkout/src/libcore/result.rs:761 - 11: 0x55d71974c70c - rust_semverver::main::hec9b0208f30ee0af - at /home/twk/gsoc/rust-semverver/src/bin/rust_semverver.rs:182 - 12: 0x7f139e9c890a - __rust_maybe_catch_panic - at /checkout/src/libpanic_unwind/lib.rs:98 - 13: 0x7f139e9c0458 - std::rt::lang_start::ha09816a4e25587ea - at /checkout/src/libstd/panicking.rs:433 - at /checkout/src/libstd/panic.rs:361 - at /checkout/src/libstd/rt.rs:59 - 14: 0x55d71974cdf2 - main - 15: 0x7f139e17b4e0 - __libc_start_main - at ../csu/libc-start.c:295 - 16: 0x55d71970be09 - _start - at ../sysdeps/x86_64/start.S:120 - 17: 0x0 - +ExportPath { inner: ["Abc"] } +max: Breaking + Removal: ::Abc diff --git a/tests/examples/removal.rs b/tests/examples/removal.rs index 63dff4dcd58ba..409052d251136 100644 --- a/tests/examples/removal.rs +++ b/tests/examples/removal.rs @@ -1,7 +1,7 @@ -mod old { - pub struct Abc {} +pub mod old { + pub struct Abc; } -mod new { +pub mod new { } From 04140943929decb2a098b60cefc5f059a44d6084 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 6 Jun 2017 11:51:24 +0200 Subject: [PATCH 040/553] Fixed some clippy warnings --- src/bin/rust_semverver.rs | 2 +- src/semcheck/changes.rs | 2 +- src/semcheck/export_map.rs | 2 -- tests/examples/removal.out | 1 - 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 930299fad45ba..c98fb17129787 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -100,7 +100,7 @@ fn callback(state: &driver::CompileState) { old_map.compare(&new_map, Checking::FromOld, &mut changes); new_map.compare(&old_map, Checking::FromNew, &mut changes); - changes.output(&tcx.sess); + changes.output(tcx.sess); } /// Our wrapper to control compilation. diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index ec6bd26b02c4f..16899db044406 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -155,7 +155,7 @@ impl ChangeSet { /// Format the contents of a change set for user output. /// /// TODO: replace this with something more sophisticated. - pub fn output(&self, session: &Session) { + pub fn output(&self, _: &Session) { println!("max: {:?}", self.max); for change in &self.changes { diff --git a/src/semcheck/export_map.rs b/src/semcheck/export_map.rs index f004f34001ef9..18cff2a9cc7a5 100644 --- a/src/semcheck/export_map.rs +++ b/src/semcheck/export_map.rs @@ -90,8 +90,6 @@ impl ExportMap { Checking::FromOld => Removal, }; - println!("{:?}", path.clone()); - changes.add_change(Change::new(change_type, path.clone(), *export)); } } diff --git a/tests/examples/removal.out b/tests/examples/removal.out index 62fca1ee936f2..14df5cd4f3118 100644 --- a/tests/examples/removal.out +++ b/tests/examples/removal.out @@ -1,3 +1,2 @@ -ExportPath { inner: ["Abc"] } max: Breaking Removal: ::Abc From 5ef54e5735752a827f20cfc076255ef9acc42594 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 6 Jun 2017 12:02:38 +0200 Subject: [PATCH 041/553] Added more integration tests --- tests/examples/addition.out | 2 ++ tests/examples/addition.rs | 7 +++++++ tests/examples/addition_path.out | 5 +++++ tests/examples/addition_path.rs | 19 +++++++++++++++++++ tests/examples/removal_path.out | 5 +++++ tests/examples/removal_path.rs | 19 +++++++++++++++++++ 6 files changed, 57 insertions(+) create mode 100644 tests/examples/addition.out create mode 100644 tests/examples/addition.rs create mode 100644 tests/examples/addition_path.out create mode 100644 tests/examples/addition_path.rs create mode 100644 tests/examples/removal_path.out create mode 100644 tests/examples/removal_path.rs diff --git a/tests/examples/addition.out b/tests/examples/addition.out new file mode 100644 index 0000000000000..23bf7936dfb61 --- /dev/null +++ b/tests/examples/addition.out @@ -0,0 +1,2 @@ +max: TechnicallyBreaking + Addition: ::Abc diff --git a/tests/examples/addition.rs b/tests/examples/addition.rs new file mode 100644 index 0000000000000..90a2d74cb540e --- /dev/null +++ b/tests/examples/addition.rs @@ -0,0 +1,7 @@ +pub mod old { + +} + +pub mod new { + pub struct Abc; +} diff --git a/tests/examples/addition_path.out b/tests/examples/addition_path.out new file mode 100644 index 0000000000000..8ed851771f493 --- /dev/null +++ b/tests/examples/addition_path.out @@ -0,0 +1,5 @@ +max: TechnicallyBreaking + Addition: ::b + Addition: ::b::Abc + Addition: ::c + Addition: ::c::Abc diff --git a/tests/examples/addition_path.rs b/tests/examples/addition_path.rs new file mode 100644 index 0000000000000..d07398a25c71a --- /dev/null +++ b/tests/examples/addition_path.rs @@ -0,0 +1,19 @@ +pub mod old { + pub mod a { + pub struct Abc; + } +} + +pub mod new { + pub mod a { + pub struct Abc; + } + + pub mod b { + pub use new::a::*; + } + + pub mod c { + pub use new::a::Abc; + } +} diff --git a/tests/examples/removal_path.out b/tests/examples/removal_path.out new file mode 100644 index 0000000000000..ea383c8456bb0 --- /dev/null +++ b/tests/examples/removal_path.out @@ -0,0 +1,5 @@ +max: Breaking + Removal: ::b + Removal: ::b::Abc + Removal: ::c + Removal: ::c::Abc diff --git a/tests/examples/removal_path.rs b/tests/examples/removal_path.rs new file mode 100644 index 0000000000000..954f131f10c80 --- /dev/null +++ b/tests/examples/removal_path.rs @@ -0,0 +1,19 @@ +pub mod old { + pub mod a { + pub struct Abc; + } + + pub mod b { + pub use old::a::*; + } + + pub mod c { + pub use old::a::Abc; + } +} + +pub mod new { + pub mod a { + pub struct Abc; + } +} From 21b8d68d15a194f742ef15a1ede2d5ce03783a8b Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 6 Jun 2017 16:16:48 +0200 Subject: [PATCH 042/553] Implemented the new module traversal system Instead of computing all "relevant" item paths, we now traverse the module tree lazily and match the children of each module directly. Then, we decide which modules correspond to each other and need to be processed in the future. This guarantees termination, since we only have a finite set of module pairs to process, which we keep track of. Since we avoid the code complexity and exponential runtime of the path-based algorithm, some bugs have been eradicated in the process. --- src/bin/rust_semverver.rs | 11 +--- src/semcheck/changes.rs | 56 +++++++++--------- src/semcheck/export_map.rs | 89 +++++++++++++++++------------ src/semcheck/mod.rs | 1 - src/semcheck/path.rs | 48 ---------------- tests/examples/addition.out | 2 +- tests/examples/addition_path.out | 6 +- tests/examples/pathologic_paths.out | 3 + tests/examples/pathologic_paths.rs | 24 ++++++++ tests/examples/pub_use.out | 1 + tests/examples/pub_use.rs | 17 ++++++ tests/examples/removal.out | 2 +- tests/examples/removal_path.out | 6 +- 13 files changed, 134 insertions(+), 132 deletions(-) delete mode 100644 src/semcheck/path.rs create mode 100644 tests/examples/pathologic_paths.out create mode 100644 tests/examples/pathologic_paths.rs create mode 100644 tests/examples/pub_use.out create mode 100644 tests/examples/pub_use.rs diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index c98fb17129787..960e156a89a50 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -9,8 +9,7 @@ extern crate rustc_metadata; extern crate semverver; extern crate syntax; -use semverver::semcheck::changes::ChangeSet; -use semverver::semcheck::export_map::{Checking, ExportMap}; +use semverver::semcheck::export_map::traverse; use rustc::hir::def_id::*; use rustc::session::{config, Session}; @@ -92,13 +91,7 @@ fn callback(state: &driver::CompileState) { dids }; - let new_map = ExportMap::new(new_did, cstore.borrow()); - let old_map = ExportMap::new(old_did, cstore.borrow()); - - let mut changes = ChangeSet::default(); - - old_map.compare(&new_map, Checking::FromOld, &mut changes); - new_map.compare(&old_map, Checking::FromNew, &mut changes); + let changes = traverse(cstore.borrow(), new_did, old_did); changes.output(tcx.sess); } diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 16899db044406..d2a510da30abe 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -1,11 +1,11 @@ -use semcheck::path::ExportPath; - -use rustc::hir::def::Export; +use rustc::hir::def::{Def, Export}; use rustc::session::Session; use std::collections::BTreeSet; use std::cmp::Ordering; +use syntax::symbol::Ident; + use syntax_pos::Span; /// The categories we use when analyzing changes between crate versions. @@ -44,6 +44,8 @@ pub enum ChangeType { Removal, /// The addition of a path for an item (which possibly didn't exist previously). Addition, + /// An unknown change. + Unknown, } pub use self::ChangeType::*; @@ -54,6 +56,7 @@ impl ChangeType { match *self { Removal => Breaking, Addition => TechnicallyBreaking, + Unknown => Breaking, // TODO } } } @@ -69,17 +72,17 @@ impl ChangeType { pub struct Change { /// The type of the change in question - see above. change_type: ChangeType, - /// The export path this change was recorded for. - path: ExportPath, + // The export path this change was recorded for. + // path: ExportPath, /// The associated item's export. export: Export, } impl Change { - pub fn new(change_type: ChangeType, path: ExportPath, export: Export) -> Change { + pub fn new(change_type: ChangeType, export: Export) -> Change { Change { change_type: change_type, - path: path, + //path: path, export: export, } } @@ -92,14 +95,18 @@ impl Change { &self.change_type } - pub fn path(&self) -> &ExportPath { - &self.path + pub fn ident(&self) -> &Ident { + &self.export.ident } + + /*pub fn path(&self) -> &ExportPath { + &self.path + }*/ } impl PartialEq for Change { fn eq(&self, other: &Change) -> bool { - self.span() == other.span() && self.path() == other.path() + self.span() == other.span() //&& self.path() == other.path() } } @@ -107,19 +114,19 @@ impl Eq for Change {} impl PartialOrd for Change { fn partial_cmp(&self, other: &Change) -> Option { - if let Some(ord1) = self.span().partial_cmp(other.span()) { + /*if let Some(ord1) = */ self.span().partial_cmp(other.span()) /* { if let Some(ord2) = self.path().partial_cmp(other.path()) { return Some(ord1.then(ord2)); } } - None + None*/ } } impl Ord for Change { fn cmp(&self, other: &Change) -> Ordering { - self.span().cmp(other.span()).then(self.path().cmp(other.path())) + self.span().cmp(other.span()) // .then(self.path().cmp(other.path())) } } @@ -144,6 +151,10 @@ impl ChangeSet { self.changes.insert(change); } + pub fn register_change(&mut self, new: Def, old: Def) { + // TODO + } + /// Check for emptyness. /// /// Currently only used in tests. @@ -159,7 +170,9 @@ impl ChangeSet { println!("max: {:?}", self.max); for change in &self.changes { - println!(" {:?}: {}", change.type_(), change.path().inner()); + // println!(" {:?}: {}", change.type_(), change.path().inner()); + println!(" {:?}: {}", change.type_(), change.ident().name.as_str()); + // session.span_warn(*change.span(), "change"); // span_note!(session, change.span(), "S0001"); // session.span_warn(*change.span(), "change"); } @@ -222,7 +235,7 @@ pub mod tests { span: s, }; - Change::new(t, ExportPath::new(vec!["this is elegant enough".to_owned()]), export) + Change::new(t, /*ExportPath::new(vec!["this is elegant enough".to_owned()]),*/ export) } quickcheck! { @@ -276,18 +289,5 @@ pub mod tests { true } } - - /// Difference in paths implies difference in `Change`s. - fn change_path_neq(c1: Change_, c2: ChangeType) -> bool { - let span = c1.1.inner(); - let ch1 = build_change(c1.0, span.clone()); - let ch2 = build_change(c2, span); - - if ch1.path() != ch2.path() { - ch1 != ch2 - } else { - true - } - } } } diff --git a/src/semcheck/export_map.rs b/src/semcheck/export_map.rs index 18cff2a9cc7a5..a6a9421a9db43 100644 --- a/src/semcheck/export_map.rs +++ b/src/semcheck/export_map.rs @@ -1,21 +1,61 @@ use semcheck::changes::{Addition, Removal, Change, ChangeSet}; -use semcheck::path::{ExportPath, PathMap}; -use rustc::hir::def::{Def, Export}; +use rustc::hir::def::Export; +use rustc::hir::def::Def::Mod; use rustc::hir::def_id::DefId; use rustc::middle::cstore::CrateStore; use rustc::ty::Visibility::Public; use std::collections::{HashMap, HashSet, VecDeque}; -/// A marker to identify the current export map. -pub enum Checking { - /// We're running from the old crate's export map. - FromOld, - /// We're running from the new crate's export map. - FromNew, +pub fn traverse(cstore: &CrateStore, new: DefId, old: DefId) -> ChangeSet { + let mut changes = ChangeSet::default(); + let mut visited = HashSet::new(); + let mut children = HashMap::new(); + let mut mod_queue = VecDeque::new(); + + mod_queue.push_back((new, old)); + + while let Some((new_did, old_did)) = mod_queue.pop_front() { + let mut c_new = cstore.item_children(new_did); + let mut c_old = cstore.item_children(old_did); + + for child in c_new.drain(..).filter(|c| cstore.visibility(c.def.def_id()) == Public) { + let child_name = String::from(&*child.ident.name.as_str()); + children.entry(child_name).or_insert((None, None)).0 = Some(child); + } + + for child in c_old.drain(..).filter(|c| cstore.visibility(c.def.def_id()) == Public) { + let child_name = String::from(&*child.ident.name.as_str()); + children.entry(child_name).or_insert((None, None)).1 = Some(child); + } + + for (_, items) in children.drain() { + match items { + (Some(Export { def: Mod(n), .. }), Some(Export { def: Mod(o), .. })) => { + if !visited.insert((n, o)) { + mod_queue.push_back((n, o)); + } + changes.register_change(Mod(n), Mod(o)); + }, + (Some(Export { def: n, ..}), Some(Export { def: o, .. })) => { + changes.register_change(n, o); + }, + (Some(new), None) => { + changes.add_change(Change::new(Addition, new)); + }, + (None, Some(old)) => { + changes.add_change(Change::new(Removal, old)); + }, + (None, None) => unreachable!(), + } + } + } + + changes } +/* /// The map of all exports from a crate. /// /// Mapping paths to item exports. @@ -23,6 +63,8 @@ pub enum Checking { pub struct ExportMap { /// The map of paths and item exports. paths: PathMap, + // submods: HashMap>, + // items: HashMap, } // TODO: test that we fetch all modules from a crate store (by iterating over all DefIds) it @@ -94,42 +136,17 @@ impl ExportMap { } } } +*/ #[cfg(test)] pub mod tests { pub use super::*; - use semcheck::changes::tests as changes; - use semcheck::path::tests as path; + /* use semcheck::changes::tests as changes; use syntax_pos::hygiene::SyntaxContext; use syntax_pos::symbol::{Ident, Interner}; - pub type ChangeType = Vec<(changes::Span_, path::ExportPath)>; - - pub fn build_export_map(change_data: ChangeType) -> ExportMap { - let mut paths = HashMap::new(); - - let mut interner = Interner::new(); - - for &(ref span, ref path) in change_data.iter() { - let ident = Ident { - name: interner.intern("test"), - ctxt: SyntaxContext::empty(), - }; - - let export = Export { - ident: ident, - def: Def::Err, - span: span.clone().inner(), - }; - - paths.insert(path.clone(), export); - } - - ExportMap::construct(paths) - } - quickcheck! { /// If we compare an export map to itself, it shouldn't detect any changes. /// @@ -144,5 +161,5 @@ pub mod tests { change_set.is_empty() } - } + } */ } diff --git a/src/semcheck/mod.rs b/src/semcheck/mod.rs index 3fe3b158a32f3..e61e676d25e5e 100644 --- a/src/semcheck/mod.rs +++ b/src/semcheck/mod.rs @@ -1,3 +1,2 @@ pub mod changes; pub mod export_map; -pub mod path; diff --git a/src/semcheck/path.rs b/src/semcheck/path.rs deleted file mode 100644 index 4ff06379dc94c..0000000000000 --- a/src/semcheck/path.rs +++ /dev/null @@ -1,48 +0,0 @@ -use rustc::hir::def::Export; - -use std::collections::HashMap; - -/// An export path through which an item in a crate is made available. -#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct ExportPath { - /// The components of the path, stored as simple strings. - inner: Vec, -} - -impl ExportPath { - pub fn new(segments: Vec) -> ExportPath { - ExportPath { inner: segments } - } - - pub fn extend(&self, component: String) -> ExportPath { - let mut inner = self.inner.clone(); - inner.push(component); - - ExportPath::new(inner) - } - - pub fn inner(&self) -> String { - let mut new = String::new(); - for component in &self.inner { - new.push_str("::"); - new.push_str(component); - } - - new - } -} - -/// A map of export paths to item exports. -pub type PathMap = HashMap; - -#[cfg(test)] -pub mod tests { - use quickcheck::*; - pub use super::*; - - impl Arbitrary for ExportPath { - fn arbitrary(g: &mut G) -> ExportPath { - ExportPath::new(Arbitrary::arbitrary(g)) - } - } -} diff --git a/tests/examples/addition.out b/tests/examples/addition.out index 23bf7936dfb61..5b4289bcaacf7 100644 --- a/tests/examples/addition.out +++ b/tests/examples/addition.out @@ -1,2 +1,2 @@ max: TechnicallyBreaking - Addition: ::Abc + Addition: Abc diff --git a/tests/examples/addition_path.out b/tests/examples/addition_path.out index 8ed851771f493..8dd0fa554c7ac 100644 --- a/tests/examples/addition_path.out +++ b/tests/examples/addition_path.out @@ -1,5 +1,3 @@ max: TechnicallyBreaking - Addition: ::b - Addition: ::b::Abc - Addition: ::c - Addition: ::c::Abc + Addition: b + Addition: c diff --git a/tests/examples/pathologic_paths.out b/tests/examples/pathologic_paths.out new file mode 100644 index 0000000000000..60a190c6f5f06 --- /dev/null +++ b/tests/examples/pathologic_paths.out @@ -0,0 +1,3 @@ +max: TechnicallyBreaking + Addition: a + Addition: b diff --git a/tests/examples/pathologic_paths.rs b/tests/examples/pathologic_paths.rs new file mode 100644 index 0000000000000..2dfa6cbb4282f --- /dev/null +++ b/tests/examples/pathologic_paths.rs @@ -0,0 +1,24 @@ +#![recursion_limit="128"] + +pub mod old { + +} + +pub mod new { + macro_rules! blow { + () => {}; + (_ $($rest:tt)*) => { + pub mod a { blow!($($rest)*); } + pub mod b { pub use super::a::*; } + } + } + + blow!(_ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _); +} diff --git a/tests/examples/pub_use.out b/tests/examples/pub_use.out new file mode 100644 index 0000000000000..0f1c04fd61923 --- /dev/null +++ b/tests/examples/pub_use.out @@ -0,0 +1 @@ +max: Patch diff --git a/tests/examples/pub_use.rs b/tests/examples/pub_use.rs new file mode 100644 index 0000000000000..0b0115755a774 --- /dev/null +++ b/tests/examples/pub_use.rs @@ -0,0 +1,17 @@ +pub mod old { + pub mod a { + pub struct Abc; + } + + pub use old::a as b; +} + +pub mod new { + pub mod a { + pub struct Abc; + } + + pub mod b { + pub use new::a::*; + } +} diff --git a/tests/examples/removal.out b/tests/examples/removal.out index 14df5cd4f3118..0348a24dd5905 100644 --- a/tests/examples/removal.out +++ b/tests/examples/removal.out @@ -1,2 +1,2 @@ max: Breaking - Removal: ::Abc + Removal: Abc diff --git a/tests/examples/removal_path.out b/tests/examples/removal_path.out index ea383c8456bb0..74b6acccdf481 100644 --- a/tests/examples/removal_path.out +++ b/tests/examples/removal_path.out @@ -1,5 +1,3 @@ max: Breaking - Removal: ::b - Removal: ::b::Abc - Removal: ::c - Removal: ::c::Abc + Removal: b + Removal: c From 168da31cdf775e0ac9fe0d95d61cfd4433155980 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 6 Jun 2017 16:50:25 +0200 Subject: [PATCH 043/553] Cleanup Removed code that won't be used ever again, fixed some small annoyances, and renamed a module. --- src/bin/rust_semverver.rs | 10 ++- src/semcheck/changes.rs | 34 ++------ src/semcheck/export_map.rs | 165 ------------------------------------- src/semcheck/mod.rs | 2 +- src/semcheck/traverse.rs | 60 ++++++++++++++ 5 files changed, 72 insertions(+), 199 deletions(-) delete mode 100644 src/semcheck/export_map.rs create mode 100644 src/semcheck/traverse.rs diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 960e156a89a50..5251853b3dfa3 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -9,7 +9,7 @@ extern crate rustc_metadata; extern crate semverver; extern crate syntax; -use semverver::semcheck::export_map::traverse; +use semverver::semcheck::traverse::traverse; use rustc::hir::def_id::*; use rustc::session::{config, Session}; @@ -57,7 +57,7 @@ fn callback(state: &driver::CompileState) { (new_did, old_did) } else { - // we are testing, so just fetch the *modules* `old` and `new` + // we are testing, so just fetch the *modules* `old` and `new` from a crate `oldandnew` let cnum = cstore .crates() .iter() @@ -103,7 +103,7 @@ struct SemVerVerCompilerCalls { impl SemVerVerCompilerCalls { pub fn new() -> SemVerVerCompilerCalls { - SemVerVerCompilerCalls { default: RustcDefaultCalls } // TODO: replace with constant + SemVerVerCompilerCalls { default: RustcDefaultCalls } } } @@ -148,11 +148,13 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { -> driver::CompileController<'a> { let mut controller = self.default.build_controller(sess, matches); - let old_callback = std::mem::replace(&mut controller.after_analysis.callback, box |_| {}); + let old_callback = std::mem::replace(&mut controller.after_analysis.callback, + box |_| {}); controller.after_analysis.callback = box move |state| { callback(state); old_callback(state); }; + controller.after_analysis.stop = Compilation::Stop; controller } diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index d2a510da30abe..3d3f066610708 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -36,15 +36,13 @@ impl Default for ChangeCategory { } /// The types of changes we identify. -/// -/// TODO: This will be further extended in the future. #[derive(Clone, Debug)] pub enum ChangeType { /// The removal of a path an item is exported through. Removal, /// The addition of a path for an item (which possibly didn't exist previously). Addition, - /// An unknown change. + /// An unknown change is any change we don't yet explicitly handle. Unknown, } @@ -54,9 +52,8 @@ impl ChangeType { /// Map a change type to the category it is part of. pub fn to_category(&self) -> ChangeCategory { match *self { - Removal => Breaking, + Removal | Unknown => Breaking, Addition => TechnicallyBreaking, - Unknown => Breaking, // TODO } } } @@ -72,8 +69,6 @@ impl ChangeType { pub struct Change { /// The type of the change in question - see above. change_type: ChangeType, - // The export path this change was recorded for. - // path: ExportPath, /// The associated item's export. export: Export, } @@ -82,7 +77,6 @@ impl Change { pub fn new(change_type: ChangeType, export: Export) -> Change { Change { change_type: change_type, - //path: path, export: export, } } @@ -98,15 +92,11 @@ impl Change { pub fn ident(&self) -> &Ident { &self.export.ident } - - /*pub fn path(&self) -> &ExportPath { - &self.path - }*/ } impl PartialEq for Change { fn eq(&self, other: &Change) -> bool { - self.span() == other.span() //&& self.path() == other.path() + self.span() == other.span() } } @@ -114,19 +104,13 @@ impl Eq for Change {} impl PartialOrd for Change { fn partial_cmp(&self, other: &Change) -> Option { - /*if let Some(ord1) = */ self.span().partial_cmp(other.span()) /* { - if let Some(ord2) = self.path().partial_cmp(other.path()) { - return Some(ord1.then(ord2)); - } - } - - None*/ + self.span().partial_cmp(other.span()) } } impl Ord for Change { fn cmp(&self, other: &Change) -> Ordering { - self.span().cmp(other.span()) // .then(self.path().cmp(other.path())) + self.span().cmp(other.span()) } } @@ -155,14 +139,6 @@ impl ChangeSet { // TODO } - /// Check for emptyness. - /// - /// Currently only used in tests. - #[cfg(test)] - pub fn is_empty(&self) -> bool { - self.changes.is_empty() - } - /// Format the contents of a change set for user output. /// /// TODO: replace this with something more sophisticated. diff --git a/src/semcheck/export_map.rs b/src/semcheck/export_map.rs deleted file mode 100644 index a6a9421a9db43..0000000000000 --- a/src/semcheck/export_map.rs +++ /dev/null @@ -1,165 +0,0 @@ -use semcheck::changes::{Addition, Removal, Change, ChangeSet}; - -use rustc::hir::def::Export; -use rustc::hir::def::Def::Mod; -use rustc::hir::def_id::DefId; -use rustc::middle::cstore::CrateStore; -use rustc::ty::Visibility::Public; - -use std::collections::{HashMap, HashSet, VecDeque}; - -pub fn traverse(cstore: &CrateStore, new: DefId, old: DefId) -> ChangeSet { - let mut changes = ChangeSet::default(); - let mut visited = HashSet::new(); - let mut children = HashMap::new(); - let mut mod_queue = VecDeque::new(); - - mod_queue.push_back((new, old)); - - while let Some((new_did, old_did)) = mod_queue.pop_front() { - let mut c_new = cstore.item_children(new_did); - let mut c_old = cstore.item_children(old_did); - - for child in c_new.drain(..).filter(|c| cstore.visibility(c.def.def_id()) == Public) { - let child_name = String::from(&*child.ident.name.as_str()); - children.entry(child_name).or_insert((None, None)).0 = Some(child); - } - - for child in c_old.drain(..).filter(|c| cstore.visibility(c.def.def_id()) == Public) { - let child_name = String::from(&*child.ident.name.as_str()); - children.entry(child_name).or_insert((None, None)).1 = Some(child); - } - - for (_, items) in children.drain() { - match items { - (Some(Export { def: Mod(n), .. }), Some(Export { def: Mod(o), .. })) => { - if !visited.insert((n, o)) { - mod_queue.push_back((n, o)); - } - changes.register_change(Mod(n), Mod(o)); - }, - (Some(Export { def: n, ..}), Some(Export { def: o, .. })) => { - changes.register_change(n, o); - }, - (Some(new), None) => { - changes.add_change(Change::new(Addition, new)); - }, - (None, Some(old)) => { - changes.add_change(Change::new(Removal, old)); - }, - (None, None) => unreachable!(), - } - } - } - - changes -} - -/* -/// The map of all exports from a crate. -/// -/// Mapping paths to item exports. -#[derive(Debug)] -pub struct ExportMap { - /// The map of paths and item exports. - paths: PathMap, - // submods: HashMap>, - // items: HashMap, -} - -// TODO: test that we fetch all modules from a crate store (by iterating over all DefIds) it -// defines and comparing them to the set of known DefIds here; - -impl ExportMap { - /// Construct a new export map from a root module's `DefId` and given a `CrateStore`. - /// - /// Traverses the descendents of the given module and avoids mutually recursive modules. - pub fn new(root: DefId, cstore: &CrateStore) -> ExportMap { - let mut visited = HashSet::new(); - let mut paths = HashMap::new(); - let mut mod_queue = VecDeque::new(); - mod_queue.push_back((root, ExportPath::default())); - - while let Some((mod_id, mod_path)) = mod_queue.pop_front() { - let mut children = cstore.item_children(mod_id); - - for child in children - .drain(..) - .filter(|c| cstore.visibility(c.def.def_id()) == Public) { - let child_name = String::from(&*child.ident.name.as_str()); - match child.def { - Def::Mod(submod_id) if !visited.contains(&submod_id) => { - visited.insert(submod_id); - mod_queue.push_back((submod_id, mod_path.extend(child_name.clone()))); - paths.insert(mod_path.extend(child_name), child); - } - _ => { - paths.insert(mod_path.extend(child_name), child); - } - } - } - } - - ExportMap { - paths: paths, - } - } - - /// Construct an empty export map without filling it. - /// - /// This is used for testing and similar tasks. - #[cfg(test)] - fn construct(paths: PathMap) -> ExportMap { - ExportMap { - paths: paths, - } - } - - /// Get a path's corresponding item export, if present. - pub fn lookup_path(&self, path: &ExportPath) -> Option<&Export> { - self.paths.get(path) - } - - /// Compare two change sets, where the current one serves as reference. - /// - /// Record the changes determined that way in a `ChangeSet`. - pub fn compare(&self, other: &ExportMap, from: Checking, changes: &mut ChangeSet) { - for (path, export) in self.paths - .iter() - .filter(|&(p, _)| other.lookup_path(p).is_none()) { - let change_type = match from { - Checking::FromNew => Addition, - Checking::FromOld => Removal, - }; - - changes.add_change(Change::new(change_type, path.clone(), *export)); - } - } -} -*/ - -#[cfg(test)] -pub mod tests { - pub use super::*; - - /* use semcheck::changes::tests as changes; - - use syntax_pos::hygiene::SyntaxContext; - use syntax_pos::symbol::{Ident, Interner}; - - quickcheck! { - /// If we compare an export map to itself, it shouldn't detect any changes. - /// - /// FIXME: this is *very slow* - fn self_compare_unchanged(change_data: ChangeType) -> bool { - let mut change_set = ChangeSet::default(); - - let export_map = build_export_map(change_data); - - export_map.compare(&export_map, Checking::FromOld, &mut change_set); - export_map.compare(&export_map, Checking::FromNew, &mut change_set); - - change_set.is_empty() - } - } */ -} diff --git a/src/semcheck/mod.rs b/src/semcheck/mod.rs index e61e676d25e5e..1198e839aeb52 100644 --- a/src/semcheck/mod.rs +++ b/src/semcheck/mod.rs @@ -1,2 +1,2 @@ pub mod changes; -pub mod export_map; +pub mod traverse; diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs new file mode 100644 index 0000000000000..b73618847d647 --- /dev/null +++ b/src/semcheck/traverse.rs @@ -0,0 +1,60 @@ +use semcheck::changes::{Addition, Removal, Change, ChangeSet}; + +use rustc::hir::def::Export; +use rustc::hir::def::Def::Mod; +use rustc::hir::def_id::DefId; +use rustc::middle::cstore::CrateStore; +use rustc::ty::Visibility::Public; + +use std::collections::{HashMap, HashSet, VecDeque}; + +/// Traverse the two root modules in an interleaved manner. +/// +/// Match up pairs of modules from the two crate versions and compare for changes. +/// Matching children get processed in the same fashion. +pub fn traverse(cstore: &CrateStore, new: DefId, old: DefId) -> ChangeSet { + let mut changes = ChangeSet::default(); + let mut visited = HashSet::new(); + let mut children = HashMap::new(); + let mut mod_queue = VecDeque::new(); + + mod_queue.push_back((new, old)); + + while let Some((new_did, old_did)) = mod_queue.pop_front() { + let mut c_new = cstore.item_children(new_did); + let mut c_old = cstore.item_children(old_did); + + for child in c_new.drain(..).filter(|c| cstore.visibility(c.def.def_id()) == Public) { + let child_name = String::from(&*child.ident.name.as_str()); + children.entry(child_name).or_insert((None, None)).0 = Some(child); + } + + for child in c_old.drain(..).filter(|c| cstore.visibility(c.def.def_id()) == Public) { + let child_name = String::from(&*child.ident.name.as_str()); + children.entry(child_name).or_insert((None, None)).1 = Some(child); + } + + for (_, items) in children.drain() { + match items { + (Some(Export { def: Mod(n), .. }), Some(Export { def: Mod(o), .. })) => { + if !visited.insert((n, o)) { + mod_queue.push_back((n, o)); + } + changes.register_change(Mod(n), Mod(o)); + }, + (Some(Export { def: n, ..}), Some(Export { def: o, .. })) => { + changes.register_change(n, o); + }, + (Some(new), None) => { + changes.add_change(Change::new(Addition, new)); + }, + (None, Some(old)) => { + changes.add_change(Change::new(Removal, old)); + }, + (None, None) => unreachable!(), + } + } + } + + changes +} From 95eb7e92212a2dcbf478b16196d154f7bf223413 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 6 Jun 2017 17:19:17 +0200 Subject: [PATCH 044/553] Updated tests --- tests/examples/addition.out | 1 + tests/examples/addition.rs | 4 ++++ tests/examples/addition_path.out | 1 + tests/examples/addition_path.rs | 2 ++ tests/examples/removal.out | 1 + tests/examples/removal.rs | 4 ++++ tests/examples/removal_path.out | 1 + tests/examples/removal_path.rs | 2 ++ 8 files changed, 16 insertions(+) diff --git a/tests/examples/addition.out b/tests/examples/addition.out index 5b4289bcaacf7..e6afd9497117d 100644 --- a/tests/examples/addition.out +++ b/tests/examples/addition.out @@ -1,2 +1,3 @@ max: TechnicallyBreaking Addition: Abc + Addition: a diff --git a/tests/examples/addition.rs b/tests/examples/addition.rs index 90a2d74cb540e..24c9be4469acd 100644 --- a/tests/examples/addition.rs +++ b/tests/examples/addition.rs @@ -4,4 +4,8 @@ pub mod old { pub mod new { pub struct Abc; + + pub mod a { + + } } diff --git a/tests/examples/addition_path.out b/tests/examples/addition_path.out index 8dd0fa554c7ac..8d9f73208af1d 100644 --- a/tests/examples/addition_path.out +++ b/tests/examples/addition_path.out @@ -1,3 +1,4 @@ max: TechnicallyBreaking Addition: b Addition: c + Addition: Abc diff --git a/tests/examples/addition_path.rs b/tests/examples/addition_path.rs index d07398a25c71a..875092736b679 100644 --- a/tests/examples/addition_path.rs +++ b/tests/examples/addition_path.rs @@ -16,4 +16,6 @@ pub mod new { pub mod c { pub use new::a::Abc; } + + pub use self::a::Abc; } diff --git a/tests/examples/removal.out b/tests/examples/removal.out index 0348a24dd5905..5b00f39f2d696 100644 --- a/tests/examples/removal.out +++ b/tests/examples/removal.out @@ -1,2 +1,3 @@ max: Breaking Removal: Abc + Removal: a diff --git a/tests/examples/removal.rs b/tests/examples/removal.rs index 409052d251136..bffaa6d7b7387 100644 --- a/tests/examples/removal.rs +++ b/tests/examples/removal.rs @@ -1,5 +1,9 @@ pub mod old { pub struct Abc; + + pub mod a { + + } } pub mod new { diff --git a/tests/examples/removal_path.out b/tests/examples/removal_path.out index 74b6acccdf481..564410e6c1db8 100644 --- a/tests/examples/removal_path.out +++ b/tests/examples/removal_path.out @@ -1,3 +1,4 @@ max: Breaking Removal: b Removal: c + Removal: Abc diff --git a/tests/examples/removal_path.rs b/tests/examples/removal_path.rs index 954f131f10c80..533c34e989f71 100644 --- a/tests/examples/removal_path.rs +++ b/tests/examples/removal_path.rs @@ -10,6 +10,8 @@ pub mod old { pub mod c { pub use old::a::Abc; } + + pub use self::a::Abc; } pub mod new { From c306f545512dd75b069f91f4cceaca8f6c19aa57 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 6 Jun 2017 17:24:54 +0200 Subject: [PATCH 045/553] Small fixes to the test runner --- tests/examples.rs | 61 +++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/tests/examples.rs b/tests/examples.rs index cbe223e150ca9..08fad76acbb6a 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -33,46 +33,49 @@ fn examples() { let err = unsafe {Stdio::from_raw_fd(fd)}; let out = unsafe {Stdio::from_raw_fd(fd)}; - success &= Command::new("rustc") + let compile_success = Command::new("rustc") .args(&["--crate-type=lib", "-o", "liboldandnew.rlib"]) .arg(file) - .env("RUST_LOG", "debug") .env("RUST_BACKTRACE", "full") .stdin(Stdio::null()) .status() .unwrap() .success(); - let mut child = Command::new(exe_path.clone()) - .args(&["--crate-type=lib", - "--extern", - "oldandnew=liboldandnew.rlib", - "-"]) - .env("RUST_SEMVERVER_TEST", "1") - .env("RUST_LOG", "debug") - .env("RUST_BACKTRACE", "full") - .stdin(Stdio::piped()) - .stdout(out) - .stderr(err) - .spawn() - .unwrap(); + success &= compile_success; - if let Some(ref mut stdin) = child.stdin { - stdin.write_fmt(format_args!("extern crate oldandnew;")).unwrap(); - } else { - panic!("could not pipe to rustc (wtf?)"); - } + if compile_success { + let mut child = Command::new(exe_path.clone()) + .args(&["--crate-type=lib", + "--extern", + "oldandnew=liboldandnew.rlib", + "-"]) + .env("RUST_SEMVERVER_TEST", "1") + .env("RUST_LOG", "debug") + .env("RUST_BACKTRACE", "full") + .stdin(Stdio::piped()) + .stdout(out) + .stderr(err) + .spawn() + .unwrap(); - success &= child - .wait() - .unwrap() - .success(); + if let Some(ref mut stdin) = child.stdin { + stdin.write_fmt(format_args!("extern crate oldandnew;")).unwrap(); + } else { + panic!("could not pipe to rustc (wtf?)"); + } - success &= Command::new("git") - .args(&["diff", "--exit-code", out_file.to_str().unwrap()]) - .status() - .unwrap() - .success(); + success &= child + .wait() + .unwrap() + .success(); + + success &= Command::new("git") + .args(&["diff", "--exit-code", out_file.to_str().unwrap()]) + .status() + .unwrap() + .success(); + } } } From 470890e9594c60442df97195cbdaa6a09ca1c213 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 8 Jun 2017 10:03:32 +0200 Subject: [PATCH 046/553] Updated build to fix #2 --- Cargo.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 16dfe428a67d9..52372b2fe1e38 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,3 @@ crates-io = "^0.7.0" [dev-dependencies] quickcheck = "^0.4.1" - -[replace] -"libgit2-sys:0.6.11" = { git = "https://github.com/ibabushkin/git2-rs.git", branch = "tmp-fix-libressl"} From 4d75d4d0d3438951e5b797f47e671299c56d56cb Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 8 Jun 2017 11:45:08 +0200 Subject: [PATCH 047/553] Some code cleanup. Less unwrap()s, more expect(), more sane error reporting. --- src/bin/rust_semverver.rs | 67 +++++++++++++++++++++++---------------- src/semcheck/changes.rs | 14 ++++---- src/semcheck/traverse.rs | 18 +++++++---- tests/examples.rs | 52 +++++++++++------------------- 4 files changed, 75 insertions(+), 76 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 5251853b3dfa3..33bcd35439eed 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -46,49 +46,62 @@ fn callback(state: &driver::CompileState) { (n, o) } }); - let new_did = DefId { - krate: cnums.0.unwrap(), - index: CRATE_DEF_INDEX, - }; - let old_did = DefId { - krate: cnums.1.unwrap(), - index: CRATE_DEF_INDEX, - }; - - (new_did, old_did) + if let (Some(c0), Some(c1)) = cnums { + (DefId { + krate: c0, + index: CRATE_DEF_INDEX, + }, + DefId { + krate: c1, + index: CRATE_DEF_INDEX, + }) + } else { + tcx.sess.err("could not find crate `new` and/or `old`"); + return; + } } else { // we are testing, so just fetch the *modules* `old` and `new` from a crate `oldandnew` let cnum = cstore .crates() .iter() - .fold(None, |k, crate_num| { - if cstore.crate_name(*crate_num) == "oldandnew" { - Some(*crate_num) - } else { - k - } - }); - let mod_did = DefId { - krate: cnum.unwrap(), - index: CRATE_DEF_INDEX, + .fold(None, + |k, crate_num| if cstore.crate_name(*crate_num) == "oldandnew" { + Some(*crate_num) + } else { + k + }); + + let mod_did = if let Some(c) = cnum { + DefId { + krate: c, + index: CRATE_DEF_INDEX, + } + } else { + tcx.sess.err("could not find crate `oldandnew`"); + return; }; let mut children = cstore.item_children(mod_did); let dids = children .drain(..) - .fold((mod_did, mod_did), |(n, o), child| { + .fold((None, None), |(n, o), child| { let child_name = String::from(&*child.ident.name.as_str()); if child_name == "new" { - (child.def.def_id(), o) + (Some(child.def.def_id()), o) } else if child_name == "old" { - (n, child.def.def_id()) + (n, Some(child.def.def_id())) } else { (n, o) } }); - dids + if let (Some(n), Some(o)) = dids { + (n, o) + } else { + tcx.sess.err("could not find module `new` and/or `old` in crate `oldandnew`"); + return; + } }; let changes = traverse(cstore.borrow(), new_did, old_did); @@ -148,8 +161,7 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { -> driver::CompileController<'a> { let mut controller = self.default.build_controller(sess, matches); - let old_callback = std::mem::replace(&mut controller.after_analysis.callback, - box |_| {}); + let old_callback = std::mem::replace(&mut controller.after_analysis.callback, box |_| {}); controller.after_analysis.callback = box move |state| { callback(state); old_callback(state); @@ -200,5 +212,6 @@ fn main() { std::process::exit(1); } } - }).expect("rustc thread failed"); + }) + .expect("rustc thread failed"); } diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 3d3f066610708..20c2f24d1320b 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -142,15 +142,13 @@ impl ChangeSet { /// Format the contents of a change set for user output. /// /// TODO: replace this with something more sophisticated. - pub fn output(&self, _: &Session) { + pub fn output(&self, session: &Session) { println!("max: {:?}", self.max); for change in &self.changes { - // println!(" {:?}: {}", change.type_(), change.path().inner()); println!(" {:?}: {}", change.type_(), change.ident().name.as_str()); // session.span_warn(*change.span(), "change"); // span_note!(session, change.span(), "S0001"); - // session.span_warn(*change.span(), "change"); } } } @@ -182,10 +180,10 @@ pub mod tests { let a: u32 = Arbitrary::arbitrary(g); let b: u32 = Arbitrary::arbitrary(g); Span_(Span { - lo: BytePos(min(a, b)), - hi: BytePos(max(a, b)), - ctxt: SyntaxContext::empty() - }) + lo: BytePos(min(a, b)), + hi: BytePos(max(a, b)), + ctxt: SyntaxContext::empty(), + }) } } @@ -211,7 +209,7 @@ pub mod tests { span: s, }; - Change::new(t, /*ExportPath::new(vec!["this is elegant enough".to_owned()]),*/ export) + Change::new(t, export) } quickcheck! { diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index b73618847d647..c9050eaf71d17 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -24,12 +24,16 @@ pub fn traverse(cstore: &CrateStore, new: DefId, old: DefId) -> ChangeSet { let mut c_new = cstore.item_children(new_did); let mut c_old = cstore.item_children(old_did); - for child in c_new.drain(..).filter(|c| cstore.visibility(c.def.def_id()) == Public) { + for child in c_new + .drain(..) + .filter(|c| cstore.visibility(c.def.def_id()) == Public) { let child_name = String::from(&*child.ident.name.as_str()); children.entry(child_name).or_insert((None, None)).0 = Some(child); } - for child in c_old.drain(..).filter(|c| cstore.visibility(c.def.def_id()) == Public) { + for child in c_old + .drain(..) + .filter(|c| cstore.visibility(c.def.def_id()) == Public) { let child_name = String::from(&*child.ident.name.as_str()); children.entry(child_name).or_insert((None, None)).1 = Some(child); } @@ -41,16 +45,16 @@ pub fn traverse(cstore: &CrateStore, new: DefId, old: DefId) -> ChangeSet { mod_queue.push_back((n, o)); } changes.register_change(Mod(n), Mod(o)); - }, - (Some(Export { def: n, ..}), Some(Export { def: o, .. })) => { + } + (Some(Export { def: n, .. }), Some(Export { def: o, .. })) => { changes.register_change(n, o); - }, + } (Some(new), None) => { changes.add_change(Change::new(Addition, new)); - }, + } (None, Some(old)) => { changes.add_change(Change::new(Removal, old)); - }, + } (None, None) => unreachable!(), } } diff --git a/tests/examples.rs b/tests/examples.rs index 08fad76acbb6a..266553c38dcde 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -1,37 +1,22 @@ use std::fs::File; use std::io::Write; use std::os::unix::io::{AsRawFd, FromRawFd}; -use std::path::Path; use std::process::{Command, Stdio}; #[test] fn examples() { - let mut cur_path = std::env::current_dir().unwrap(); - loop { - if let Some(fname) = cur_path.file_name() { - if fname == "rust-semverver" { - break; - } - } - - if !cur_path.pop() { - panic!("blergh"); - } - } - - let exe_path = cur_path.join(Path::new("target/debug/rust-semverver")); - let mut success = true; - // FIXME: this assumes a different dir - for file in std::fs::read_dir("tests/examples").unwrap().map(|f| f.unwrap().path()) { + for file in std::fs::read_dir("tests/examples") + .expect("could not read dir") + .map(|f| f.expect("could not get file info").path()) { if file.extension().map_or(false, |e| e == "rs") { let out_file = file.with_extension("out"); - let output = File::create(&out_file).unwrap(); + let output = File::create(&out_file).expect("could not create file"); let fd = output.as_raw_fd(); //let out = unsafe {Stdio::from_raw_fd(fd)}; - let err = unsafe {Stdio::from_raw_fd(fd)}; - let out = unsafe {Stdio::from_raw_fd(fd)}; + let err = unsafe { Stdio::from_raw_fd(fd) }; + let out = unsafe { Stdio::from_raw_fd(fd) }; let compile_success = Command::new("rustc") .args(&["--crate-type=lib", "-o", "liboldandnew.rlib"]) @@ -39,17 +24,17 @@ fn examples() { .env("RUST_BACKTRACE", "full") .stdin(Stdio::null()) .status() - .unwrap() + .expect("could not run rustc") .success(); success &= compile_success; if compile_success { - let mut child = Command::new(exe_path.clone()) + let mut child = Command::new("./target/debug/rust-semverver") .args(&["--crate-type=lib", - "--extern", - "oldandnew=liboldandnew.rlib", - "-"]) + "--extern", + "oldandnew=liboldandnew.rlib", + "-"]) .env("RUST_SEMVERVER_TEST", "1") .env("RUST_LOG", "debug") .env("RUST_BACKTRACE", "full") @@ -57,23 +42,22 @@ fn examples() { .stdout(out) .stderr(err) .spawn() - .unwrap(); + .expect("could not run rust-semverver"); if let Some(ref mut stdin) = child.stdin { - stdin.write_fmt(format_args!("extern crate oldandnew;")).unwrap(); + stdin + .write_fmt(format_args!("extern crate oldandnew;")) + .expect("could not pipe to rust-semverver"); } else { panic!("could not pipe to rustc (wtf?)"); } - success &= child - .wait() - .unwrap() - .success(); + success &= child.wait().expect("could not wait for child").success(); success &= Command::new("git") .args(&["diff", "--exit-code", out_file.to_str().unwrap()]) .status() - .unwrap() + .expect("could not run git diff") .success(); } } @@ -82,7 +66,7 @@ fn examples() { Command::new("rm") .arg("liboldandnew.rlib") .status() - .unwrap(); + .expect("could not run rm"); assert!(success, "an error occured"); } From 6c1e25d96f8ffbdc7a46b6ece07c885bfe6bbb2f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 8 Jun 2017 15:59:57 +0200 Subject: [PATCH 048/553] Restructured change handling. We now define differences between changes based on arity. The arity of a change is determined by whether it affects an item that is present in both versions of the crate or not. --- src/semcheck/changes.rs | 239 +++++++++++++++++++++++++++++---------- src/semcheck/traverse.rs | 9 +- 2 files changed, 181 insertions(+), 67 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 20c2f24d1320b..e08ba75a75194 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -1,4 +1,4 @@ -use rustc::hir::def::{Def, Export}; +use rustc::hir::def::Export; use rustc::session::Session; use std::collections::BTreeSet; @@ -29,91 +29,184 @@ pub enum ChangeCategory { pub use self::ChangeCategory::*; -impl Default for ChangeCategory { +impl<'a> Default for ChangeCategory { fn default() -> ChangeCategory { Patch } } -/// The types of changes we identify. -#[derive(Clone, Debug)] -pub enum ChangeType { - /// The removal of a path an item is exported through. - Removal, - /// The addition of a path for an item (which possibly didn't exist previously). - Addition, - /// An unknown change is any change we don't yet explicitly handle. - Unknown, +impl<'a> From<&'a UnaryChange> for ChangeCategory { + fn from(change: &UnaryChange) -> ChangeCategory { + match *change { + UnaryChange::Addition(_) => TechnicallyBreaking, + UnaryChange::Removal(_) => Breaking, + } + } +} + +impl<'a> From<&'a BinaryChangeType> for ChangeCategory { + fn from(type_: &BinaryChangeType) -> ChangeCategory { + match *type_ { + Unknown => Breaking, + } + } } -pub use self::ChangeType::*; +impl<'a> From<&'a BinaryChange> for ChangeCategory { + fn from(change: &BinaryChange) -> ChangeCategory { + From::from(change.type_()) + } +} -impl ChangeType { - /// Map a change type to the category it is part of. - pub fn to_category(&self) -> ChangeCategory { - match *self { - Removal | Unknown => Breaking, - Addition => TechnicallyBreaking, +impl<'a> From<&'a Change> for ChangeCategory { + fn from(change: &Change) -> ChangeCategory { + match *change { + Change::Unary(ref u) => From::from(u), + Change::Binary(ref b) => From::from(b), } } } +/// The types of changes we identify. +#[derive(Clone, Debug)] +pub enum BinaryChangeType { + /// An unknown change is any change we don't yet explicitly handle. + Unknown, +} + +pub use self::BinaryChangeType::*; + /// A change record. /// /// Consists of all information we need to compute semantic versioning properties of /// the change, as well as data we use to output it in a nice fashion. +#[derive(PartialEq, Eq, PartialOrd, Ord)] +pub enum Change { + Unary(UnaryChange), + Binary(BinaryChange), +} + +impl Change { + pub fn new_addition(export: Export) -> Change { + Change::Unary(UnaryChange::Addition(export)) + } + + pub fn new_removal(export: Export) -> Change { + Change::Unary(UnaryChange::Removal(export)) + } + + pub fn new_binary(type_: BinaryChangeType, old: Export, new: Export) -> Change { + Change::Binary(BinaryChange::new(type_, old, new)) + } +} + +/// A change record of a change that introduced or removed an item. /// /// It is important to note that the `Eq` and `Ord` instances are constucted to only /// regard the span and path of the associated item export. This allows us to sort them /// by appearance in the source, but possibly could create conflict later on. -pub struct Change { - /// The type of the change in question - see above. - change_type: ChangeType, - /// The associated item's export. - export: Export, +pub enum UnaryChange { + /// An item has been added. + Addition(Export), + /// An item has been removed. + Removal(Export), } -impl Change { - pub fn new(change_type: ChangeType, export: Export) -> Change { - Change { - change_type: change_type, - export: export, +impl UnaryChange { + fn export(&self) -> &Export { + match *self { + UnaryChange::Addition(ref e) | UnaryChange::Removal(ref e) => e, } } pub fn span(&self) -> &Span { - &self.export.span + &self.export().span } - pub fn type_(&self) -> &ChangeType { - &self.change_type + pub fn ident(&self) -> &Ident { + &self.export().ident } - pub fn ident(&self) -> &Ident { - &self.export.ident + pub fn type_(&self) -> &'static str { + match *self { + UnaryChange::Addition(_) => "Addition", + UnaryChange::Removal(_) => "Removal", + } } } -impl PartialEq for Change { - fn eq(&self, other: &Change) -> bool { +impl PartialEq for UnaryChange { + fn eq(&self, other: &UnaryChange) -> bool { self.span() == other.span() } } -impl Eq for Change {} +impl Eq for UnaryChange {} -impl PartialOrd for Change { - fn partial_cmp(&self, other: &Change) -> Option { +impl PartialOrd for UnaryChange { + fn partial_cmp(&self, other: &UnaryChange) -> Option { self.span().partial_cmp(other.span()) } } -impl Ord for Change { - fn cmp(&self, other: &Change) -> Ordering { +impl Ord for UnaryChange { + fn cmp(&self, other: &UnaryChange) -> Ordering { self.span().cmp(other.span()) } } +pub struct BinaryChange { + type_: BinaryChangeType, + old: Export, + new: Export, +} + +impl BinaryChange { + pub fn new(type_: BinaryChangeType, old: Export, new: Export) -> BinaryChange { + BinaryChange { + type_: type_, + old: old, + new: new, + } + } + + pub fn type_(&self) -> &BinaryChangeType { + &self.type_ + } + + pub fn new_span(&self) -> &Span { + &self.new.span + } + + pub fn old_span(&self) -> &Span { + &self.old.span + } + + pub fn ident(&self) -> &Ident { + &self.old.ident + } +} + +impl PartialEq for BinaryChange { + fn eq(&self, other: &BinaryChange) -> bool { + self.new_span() == other.new_span() + } +} + +impl Eq for BinaryChange {} + +impl PartialOrd for BinaryChange { + fn partial_cmp(&self, other: &BinaryChange) -> Option { + self.new_span().partial_cmp(other.new_span()) + } +} + +impl Ord for BinaryChange { + fn cmp(&self, other: &BinaryChange) -> Ordering { + self.new_span().cmp(other.new_span()) + } +} + /// The total set of changes recorded for two crate versions. #[derive(Default)] pub struct ChangeSet { @@ -126,7 +219,7 @@ pub struct ChangeSet { impl ChangeSet { /// Add a change to the set and record it's category for later use. pub fn add_change(&mut self, change: Change) { - let cat = change.type_().to_category(); + let cat: ChangeCategory = From::from(&change); if cat > self.max { self.max = cat; @@ -135,10 +228,6 @@ impl ChangeSet { self.changes.insert(change); } - pub fn register_change(&mut self, new: Def, old: Def) { - // TODO - } - /// Format the contents of a change set for user output. /// /// TODO: replace this with something more sophisticated. @@ -146,7 +235,14 @@ impl ChangeSet { println!("max: {:?}", self.max); for change in &self.changes { - println!(" {:?}: {}", change.type_(), change.ident().name.as_str()); + match *change { + Change::Unary(ref c) => { + println!(" {}: {}", c.type_(), c.ident().name.as_str()); + }, + Change::Binary(ref c) => { + println!(" {:?}: {}", c.type_(), c.ident().name.as_str()); + }, + } // session.span_warn(*change.span(), "change"); // span_note!(session, change.span(), "S0001"); } @@ -187,16 +283,31 @@ pub mod tests { } } - impl Arbitrary for ChangeType { - fn arbitrary(g: &mut G) -> ChangeType { - g.choose(&[Removal, Addition]).unwrap().clone() + #[derive(Clone, Debug)] + pub enum UnaryChangeType { + Removal, + Addition, + } + + impl Arbitrary for UnaryChangeType { + fn arbitrary(g: &mut G) -> UnaryChangeType { + g.choose(&[UnaryChangeType::Removal, UnaryChangeType::Addition]).unwrap().clone() } } - pub type Change_ = (ChangeType, Span_); + impl<'a> From<&'a UnaryChangeType> for ChangeCategory { + fn from(change: &UnaryChangeType) -> ChangeCategory { + match *change { + UnaryChangeType::Addition => TechnicallyBreaking, + UnaryChangeType::Removal => Breaking, + } + } + } + + pub type UnaryChange_ = (UnaryChangeType, Span_); /// We build these by hand, because symbols can't be sent between threads. - fn build_change(t: ChangeType, s: Span) -> Change { + fn build_unary_change(t: UnaryChangeType, s: Span) -> UnaryChange { let mut interner = Interner::new(); let ident = Ident { name: interner.intern("test"), @@ -209,15 +320,18 @@ pub mod tests { span: s, }; - Change::new(t, export) + match t { + UnaryChangeType::Addition => UnaryChange::Addition(export), + UnaryChangeType::Removal => UnaryChange::Removal(export), + } } quickcheck! { /// The `Ord` instance of `Change` is transitive. - fn ord_change_transitive(c1: Change_, c2: Change_, c3: Change_) -> bool { - let ch1 = build_change(c1.0, c1.1.inner()); - let ch2 = build_change(c2.0, c2.1.inner()); - let ch3 = build_change(c3.0, c3.1.inner()); + fn ord_change_transitive(c1: UnaryChange_, c2: UnaryChange_, c3: UnaryChange_) -> bool { + let ch1 = build_unary_change(c1.0, c1.1.inner()); + let ch2 = build_unary_change(c2.0, c2.1.inner()); + let ch3 = build_unary_change(c3.0, c3.1.inner()); let mut res = true; @@ -237,26 +351,27 @@ pub mod tests { } /// The maximal change category for a change set gets computed correctly. - fn max_change(changes: Vec) -> bool { + fn max_change(changes: Vec) -> bool { let mut set = ChangeSet::default(); - let max = changes.iter().map(|c| c.0.to_category()).max().unwrap_or(Patch); + let max = changes.iter().map(|c| From::from(&c.0)).max().unwrap_or(Patch); for &(ref change, ref span) in changes.iter() { - set.add_change(build_change(change.clone(), span.clone().inner())); + set.add_change( + Change::Unary(build_unary_change(change.clone(), span.clone().inner()))); } set.max == max } /// Difference in spans implies difference in `Change`s. - fn change_span_neq(c1: Change_, c2: Change_) -> bool { + fn change_span_neq(c1: UnaryChange_, c2: UnaryChange_) -> bool { let s1 = c1.1.inner(); let s2 = c2.1.inner(); if s1 != s2 { - let ch1 = build_change(c1.0, s1); - let ch2 = build_change(c2.0, s2); + let ch1 = build_unary_change(c1.0, s1); + let ch2 = build_unary_change(c2.0, s2); ch1 != ch2 } else { diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index c9050eaf71d17..0882d5a2f9a82 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -1,4 +1,4 @@ -use semcheck::changes::{Addition, Removal, Change, ChangeSet}; +use semcheck::changes::{Change, ChangeSet}; use rustc::hir::def::Export; use rustc::hir::def::Def::Mod; @@ -44,16 +44,15 @@ pub fn traverse(cstore: &CrateStore, new: DefId, old: DefId) -> ChangeSet { if !visited.insert((n, o)) { mod_queue.push_back((n, o)); } - changes.register_change(Mod(n), Mod(o)); } (Some(Export { def: n, .. }), Some(Export { def: o, .. })) => { - changes.register_change(n, o); + // changes.add_change(Change::construct(n, o)); } (Some(new), None) => { - changes.add_change(Change::new(Addition, new)); + changes.add_change(Change::new_addition(new)); } (None, Some(old)) => { - changes.add_change(Change::new(Removal, old)); + changes.add_change(Change::new_removal(old)); } (None, None) => unreachable!(), } From f0800393be63fb2cbd01119bb3d3ce50c97982f4 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 8 Jun 2017 16:08:47 +0200 Subject: [PATCH 049/553] Added docs to the new change datastructures. --- src/semcheck/changes.rs | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index e08ba75a75194..15d0559ebb8d4 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -67,7 +67,7 @@ impl<'a> From<&'a Change> for ChangeCategory { } } -/// The types of changes we identify. +/// The types of changes we identify between items present in both crate versions. #[derive(Clone, Debug)] pub enum BinaryChangeType { /// An unknown change is any change we don't yet explicitly handle. @@ -82,19 +82,24 @@ pub use self::BinaryChangeType::*; /// the change, as well as data we use to output it in a nice fashion. #[derive(PartialEq, Eq, PartialOrd, Ord)] pub enum Change { + /// A wrapper around a unary change. Unary(UnaryChange), + /// A wrapper around a binary change. Binary(BinaryChange), } impl Change { + /// Construct a new addition change from it's export. pub fn new_addition(export: Export) -> Change { Change::Unary(UnaryChange::Addition(export)) } + /// Construct a new removal change from it's export. pub fn new_removal(export: Export) -> Change { Change::Unary(UnaryChange::Removal(export)) } + /// Construct a new binary change from it's exports and type. pub fn new_binary(type_: BinaryChangeType, old: Export, new: Export) -> Change { Change::Binary(BinaryChange::new(type_, old, new)) } @@ -103,8 +108,8 @@ impl Change { /// A change record of a change that introduced or removed an item. /// /// It is important to note that the `Eq` and `Ord` instances are constucted to only -/// regard the span and path of the associated item export. This allows us to sort them -/// by appearance in the source, but possibly could create conflict later on. +/// regard the span of the associated item export. This allows us to sort them by appearance +/// in the source, but possibly could create conflict later on. pub enum UnaryChange { /// An item has been added. Addition(Export), @@ -113,20 +118,24 @@ pub enum UnaryChange { } impl UnaryChange { + /// Get the change item's sole export. fn export(&self) -> &Export { match *self { UnaryChange::Addition(ref e) | UnaryChange::Removal(ref e) => e, } } + /// Get the change item's sole span. pub fn span(&self) -> &Span { &self.export().span } + /// Get the change item's ident. pub fn ident(&self) -> &Ident { &self.export().ident } + /// Render the change's type to a string. pub fn type_(&self) -> &'static str { match *self { UnaryChange::Addition(_) => "Addition", @@ -155,13 +164,22 @@ impl Ord for UnaryChange { } } +/// A change record of a change of an item between versions. +/// +/// It is important to note that the `Eq` and `Ord` instances are constucted to only +/// regard the *new* span of the associated item export. This allows us to sort them +/// by appearance in *new* the source, but possibly could create conflict later on. pub struct BinaryChange { + /// The type of the change affecting the item. type_: BinaryChangeType, + /// The old export of the change item. old: Export, + /// The new export of the change item. new: Export, } impl BinaryChange { + /// Construct a new binary change record. pub fn new(type_: BinaryChangeType, old: Export, new: Export) -> BinaryChange { BinaryChange { type_: type_, @@ -170,18 +188,22 @@ impl BinaryChange { } } + /// Get the change's type. pub fn type_(&self) -> &BinaryChangeType { &self.type_ } + /// Get the new span of the change item. pub fn new_span(&self) -> &Span { &self.new.span } + /// Get the old span of the change item. pub fn old_span(&self) -> &Span { &self.old.span } + /// Get the ident of the change item. pub fn ident(&self) -> &Ident { &self.old.ident } From dbbbebb26bcd11332e96ed9a80137a877862bf2f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 8 Jun 2017 16:58:13 +0200 Subject: [PATCH 050/553] Updated tests --- src/semcheck/changes.rs | 94 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 4 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 15d0559ebb8d4..1de7ac0a48f44 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -305,6 +305,7 @@ pub mod tests { } } + // we don't need this type elsewhere, so we define it here. #[derive(Clone, Debug)] pub enum UnaryChangeType { Removal, @@ -326,6 +327,12 @@ pub mod tests { } } + impl Arbitrary for BinaryChangeType { + fn arbitrary(g: &mut G) -> BinaryChangeType { + g.choose(&[BinaryChangeType::Unknown]).unwrap().clone() + } + } + pub type UnaryChange_ = (UnaryChangeType, Span_); /// We build these by hand, because symbols can't be sent between threads. @@ -335,7 +342,6 @@ pub mod tests { name: interner.intern("test"), ctxt: SyntaxContext::empty(), }; - let export = Export { ident: ident, def: Def::Err, @@ -348,9 +354,35 @@ pub mod tests { } } + pub type BinaryChange_ = (BinaryChangeType, Span_, Span_); + + fn build_binary_change(t: BinaryChangeType, s1: Span, s2: Span) -> BinaryChange { + let mut interner = Interner::new(); + let ident1 = Ident { + name: interner.intern("test"), + ctxt: SyntaxContext::empty(), + }; + let ident2 = Ident { + name: interner.intern("test"), + ctxt: SyntaxContext::empty(), + }; + let export1 = Export { + ident: ident1, + def: Def::Err, + span: s1, + }; + let export2 = Export { + ident: ident2, + def: Def::Err, + span: s2, + }; + + BinaryChange::new(t, export1, export2) + } + quickcheck! { /// The `Ord` instance of `Change` is transitive. - fn ord_change_transitive(c1: UnaryChange_, c2: UnaryChange_, c3: UnaryChange_) -> bool { + fn ord_uchange_transitive(c1: UnaryChange_, c2: UnaryChange_, c3: UnaryChange_) -> bool { let ch1 = build_unary_change(c1.0, c1.1.inner()); let ch2 = build_unary_change(c2.0, c2.1.inner()); let ch3 = build_unary_change(c3.0, c3.1.inner()); @@ -372,8 +404,32 @@ pub mod tests { res } + fn ord_bchange_transitive(c1: BinaryChange_, c2: BinaryChange_, c3: BinaryChange_) + -> bool + { + let ch1 = build_binary_change(c1.0, c1.1.inner(), c1.2.inner()); + let ch2 = build_binary_change(c2.0, c2.1.inner(), c2.2.inner()); + let ch3 = build_binary_change(c3.0, c3.1.inner(), c3.2.inner()); + + 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 gets computed correctly. - fn max_change(changes: Vec) -> bool { + fn max_uchange(changes: Vec) -> bool { let mut set = ChangeSet::default(); let max = changes.iter().map(|c| From::from(&c.0)).max().unwrap_or(Patch); @@ -386,8 +442,23 @@ pub mod tests { set.max == max } + /// The maximal change category for a change set gets computed correctly. + fn max_bchange(changes: Vec) -> bool { + let mut set = ChangeSet::default(); + + let max = changes.iter().map(|c| From::from(&c.0)).max().unwrap_or(Patch); + + for &(ref change, ref span1, ref span2) in changes.iter() { + set.add_change( + Change::Binary(build_binary_change( + change.clone(), span1.clone().inner(), span2.clone().inner()))); + } + + set.max == max + } + /// Difference in spans implies difference in `Change`s. - fn change_span_neq(c1: UnaryChange_, c2: UnaryChange_) -> bool { + fn uchange_span_neq(c1: UnaryChange_, c2: UnaryChange_) -> bool { let s1 = c1.1.inner(); let s2 = c2.1.inner(); @@ -400,5 +471,20 @@ pub mod tests { true } } + + /// Difference in spans implies difference in `Change`s. + fn bchange_span_neq(c1: BinaryChange_, c2: BinaryChange_) -> bool { + let s1 = c1.1.inner(); + let s2 = c2.1.inner(); + + if s1 != s2 { + let ch1 = build_binary_change(c1.0, s1, c1.2.inner()); + let ch2 = build_binary_change(c2.0, s2, c2.2.inner()); + + ch1 != ch2 + } else { + true + } + } } } From cd0500cbf0ac898eccd3684734e29a682c8c5d9e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 9 Jun 2017 09:34:52 +0200 Subject: [PATCH 051/553] Added a rough sketch ofthe `BinaryChangeType` enum --- src/semcheck/changes.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 1de7ac0a48f44..00914d02d7011 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -44,10 +44,20 @@ impl<'a> From<&'a UnaryChange> for ChangeCategory { } } +// TODO: this will need a lot of changes impl<'a> From<&'a BinaryChangeType> for ChangeCategory { fn from(type_: &BinaryChangeType) -> ChangeCategory { match *type_ { + KindDifference | + TypeSpecialization | + StructFieldAdded(_, _) | + StructFieldRemoved(_, _) | + EnumVariantAdded | + EnumVariantRemoved | + ImplItemAdded(_) | + ImplItemRemoved | Unknown => Breaking, + TypeGeneralization => TechnicallyBreaking, } } } @@ -68,8 +78,27 @@ impl<'a> From<&'a Change> for ChangeCategory { } /// The types of changes we identify between items present in both crate versions. +/// TODO: this needs a lot of refinement still #[derive(Clone, Debug)] pub enum BinaryChangeType { + /// An item has changed it's kind. + KindDifference, + /// An item has changed it's type (signature) to be more general. + TypeGeneralization, + /// An item has changed it's type (signature) to be less general. + TypeSpecialization, + /// A field has been added to a struct. + StructFieldAdded(bool, bool), // TODO: EXXXXPPPPLAAAAIN! + /// A field has been removed from a struct. + StructFieldRemoved(bool, bool), // TODO: EXXXXPPPPLAAAIN! + /// A variant has been added to an enum. + EnumVariantAdded, + /// A variant has been removed to an enum. + EnumVariantRemoved, + /// An impl item has been added. + ImplItemAdded(bool), // TODO: EXPLAAAIN! + /// An impl item has been removed. + ImplItemRemoved, /// An unknown change is any change we don't yet explicitly handle. Unknown, } From 28e63dec82f1598a6dfd5ad454cd2db39e7cb381 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 9 Jun 2017 12:19:55 +0200 Subject: [PATCH 052/553] Added very rudimentary item diffing --- src/bin/rust_semverver.rs | 4 ++-- src/semcheck/changes.rs | 32 ++++++++++++++++++++++---------- src/semcheck/traverse.rs | 27 +++++++++++++++++++++++---- 3 files changed, 47 insertions(+), 16 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 33bcd35439eed..00e3f2d9cf9f3 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -9,7 +9,7 @@ extern crate rustc_metadata; extern crate semverver; extern crate syntax; -use semverver::semcheck::traverse::traverse; +use semverver::semcheck::traverse::traverse_modules; use rustc::hir::def_id::*; use rustc::session::{config, Session}; @@ -104,7 +104,7 @@ fn callback(state: &driver::CompileState) { } }; - let changes = traverse(cstore.borrow(), new_did, old_did); + let changes = traverse_modules(cstore.borrow(), new_did, old_did); changes.output(tcx.sess); } diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 00914d02d7011..994721dea89da 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -50,12 +50,16 @@ impl<'a> From<&'a BinaryChangeType> for ChangeCategory { match *type_ { KindDifference | TypeSpecialization | - StructFieldAdded(_, _) | - StructFieldRemoved(_, _) | + StructFieldAdded { .. } | + StructFieldRemoved { .. } | + StructStyleChanged { .. } | EnumVariantAdded | EnumVariantRemoved | - ImplItemAdded(_) | - ImplItemRemoved | + VariantFieldAdded | + VariantFieldRemoved | + VariantFieldStyleChanged { .. } | + TraitImplItemAdded { .. } | + TraitImplItemRemoved | Unknown => Breaking, TypeGeneralization => TechnicallyBreaking, } @@ -88,17 +92,25 @@ pub enum BinaryChangeType { /// An item has changed it's type (signature) to be less general. TypeSpecialization, /// A field has been added to a struct. - StructFieldAdded(bool, bool), // TODO: EXXXXPPPPLAAAAIN! + StructFieldAdded { public: bool, total_public: bool }, // TODO: EXXXXPPPPLAAAAIN! /// A field has been removed from a struct. - StructFieldRemoved(bool, bool), // TODO: EXXXXPPPPLAAAIN! + StructFieldRemoved { public: bool, total_public: bool }, // TODO: EXXXXPPPPLAAAIN! + /// A struct has changed it's style. + StructStyleChanged { now_tuple: bool, total_private: bool }, /// A variant has been added to an enum. EnumVariantAdded, - /// A variant has been removed to an enum. + /// A variant has been removed from an enum. EnumVariantRemoved, + /// A field hasb been added to an enum variant. + VariantFieldAdded, + /// A field has been removed from an enum variant. + VariantFieldRemoved, + /// An enum variant has changed it's style. + VariantFieldStyleChanged { now_tuple: bool }, /// An impl item has been added. - ImplItemAdded(bool), // TODO: EXPLAAAIN! + TraitImplItemAdded { defaulted: bool }, // TODO: EXPLAAAIN! /// An impl item has been removed. - ImplItemRemoved, + TraitImplItemRemoved, /// An unknown change is any change we don't yet explicitly handle. Unknown, } @@ -282,7 +294,7 @@ impl ChangeSet { /// Format the contents of a change set for user output. /// /// TODO: replace this with something more sophisticated. - pub fn output(&self, session: &Session) { + pub fn output(&self, _: &Session) { println!("max: {:?}", self.max); for change in &self.changes { diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 0882d5a2f9a82..5c48bf78cbe34 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -1,7 +1,8 @@ +use semcheck::changes::BinaryChangeType::*; use semcheck::changes::{Change, ChangeSet}; +use rustc::hir::def::Def::*; use rustc::hir::def::Export; -use rustc::hir::def::Def::Mod; use rustc::hir::def_id::DefId; use rustc::middle::cstore::CrateStore; use rustc::ty::Visibility::Public; @@ -12,7 +13,7 @@ use std::collections::{HashMap, HashSet, VecDeque}; /// /// Match up pairs of modules from the two crate versions and compare for changes. /// Matching children get processed in the same fashion. -pub fn traverse(cstore: &CrateStore, new: DefId, old: DefId) -> ChangeSet { +pub fn traverse_modules(cstore: &CrateStore, new: DefId, old: DefId) -> ChangeSet { let mut changes = ChangeSet::default(); let mut visited = HashSet::new(); let mut children = HashMap::new(); @@ -45,8 +46,10 @@ pub fn traverse(cstore: &CrateStore, new: DefId, old: DefId) -> ChangeSet { mod_queue.push_back((n, o)); } } - (Some(Export { def: n, .. }), Some(Export { def: o, .. })) => { - // changes.add_change(Change::construct(n, o)); + (Some(n), Some(o)) => { + if let Some(change) = diff_items(cstore, n, o) { + changes.add_change(change); + } } (Some(new), None) => { changes.add_change(Change::new_addition(new)); @@ -61,3 +64,19 @@ pub fn traverse(cstore: &CrateStore, new: DefId, old: DefId) -> ChangeSet { changes } + +pub fn diff_items(_: &CrateStore, new: Export, old: Export) -> Option { + match (new.def, old.def) { + (Struct(_), Struct(_)) => Some(Change::new_binary(Unknown, old, new)), + (Union(_), Union(_)) => Some(Change::new_binary(Unknown, old, new)), + (Enum(_), Enum(_)) => Some(Change::new_binary(Unknown, old, new)), + (Trait(_), Trait(_)) => Some(Change::new_binary(Unknown, old, new)), + (TyAlias(_), TyAlias(_)) => Some(Change::new_binary(Unknown, old, new)), + (Fn(_), Fn(_)) => Some(Change::new_binary(Unknown, old, new)), + (Const(_), Const(_)) => Some(Change::new_binary(Unknown, old, new)), + (Static(_, _), Static(_, _)) => Some(Change::new_binary(Unknown, old, new)), + (Method(_), Method(_)) => Some(Change::new_binary(Unknown, old, new)), + (Macro(_, _), Macro(_, _)) => Some(Change::new_binary(Unknown, old, new)), + (n, o) => Some(Change::new_binary(KindDifference, old, new)), + } +} From 4767a4a5bce5984391e5597e9982ebad0c96fd1a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 9 Jun 2017 12:24:45 +0200 Subject: [PATCH 053/553] Added kind difference tests --- src/semcheck/traverse.rs | 6 +++++- tests/examples/kind_change.out | 2 ++ tests/examples/kind_change.rs | 9 +++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 tests/examples/kind_change.out create mode 100644 tests/examples/kind_change.rs diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 5c48bf78cbe34..7195544a23f6b 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -65,6 +65,10 @@ pub fn traverse_modules(cstore: &CrateStore, new: DefId, old: DefId) -> ChangeSe changes } +/// Given two items, dispatch to further checks. +/// +/// If the two items can't be meaningfully compared because they are of different kinds, +/// we return that difference directly. pub fn diff_items(_: &CrateStore, new: Export, old: Export) -> Option { match (new.def, old.def) { (Struct(_), Struct(_)) => Some(Change::new_binary(Unknown, old, new)), @@ -77,6 +81,6 @@ pub fn diff_items(_: &CrateStore, new: Export, old: Export) -> Option { (Static(_, _), Static(_, _)) => Some(Change::new_binary(Unknown, old, new)), (Method(_), Method(_)) => Some(Change::new_binary(Unknown, old, new)), (Macro(_, _), Macro(_, _)) => Some(Change::new_binary(Unknown, old, new)), - (n, o) => Some(Change::new_binary(KindDifference, old, new)), + _ => Some(Change::new_binary(KindDifference, old, new)), } } diff --git a/tests/examples/kind_change.out b/tests/examples/kind_change.out new file mode 100644 index 0000000000000..b52f571a2e090 --- /dev/null +++ b/tests/examples/kind_change.out @@ -0,0 +1,2 @@ +max: Breaking + KindDifference: Abc diff --git a/tests/examples/kind_change.rs b/tests/examples/kind_change.rs new file mode 100644 index 0000000000000..5821f14a0e3f8 --- /dev/null +++ b/tests/examples/kind_change.rs @@ -0,0 +1,9 @@ +pub mod old { + pub struct Abc; +} + +pub mod new { + pub enum Abc { + + } +} From e1a895b02803e44e8985976c675f5259984aeeff Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 10 Jun 2017 21:19:07 +0200 Subject: [PATCH 054/553] Updated to work with the new rust nightly. --- src/bin/rust_semverver.rs | 5 ++--- src/semcheck/changes.rs | 5 +++-- src/semcheck/traverse.rs | 11 +++++++---- tests/examples/addition.out | 6 ++++++ tests/examples/addition_path.out | 9 +++++++++ tests/examples/kind_change.out | 2 ++ tests/examples/pathologic_paths.out | 6 ++++++ tests/examples/removal.out | 6 ++++++ tests/examples/removal_path.out | 9 +++++++++ 9 files changed, 50 insertions(+), 9 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 00e3f2d9cf9f3..28db9119c5a48 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -17,7 +17,6 @@ use rustc::session::config::{Input, ErrorOutputType}; use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; -use std::borrow::Borrow; use std::path::PathBuf; use std::process::Command; @@ -81,7 +80,7 @@ fn callback(state: &driver::CompileState) { return; }; - let mut children = cstore.item_children(mod_did); + let mut children = cstore.item_children(mod_did, tcx.sess); let dids = children .drain(..) @@ -104,7 +103,7 @@ fn callback(state: &driver::CompileState) { } }; - let changes = traverse_modules(cstore.borrow(), new_did, old_did); + let changes = traverse_modules(&tcx, new_did, old_did); changes.output(tcx.sess); } diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 994721dea89da..827ee2d5a31a6 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -294,19 +294,20 @@ impl ChangeSet { /// Format the contents of a change set for user output. /// /// TODO: replace this with something more sophisticated. - pub fn output(&self, _: &Session) { + pub fn output(&self, session: &Session) { println!("max: {:?}", self.max); for change in &self.changes { match *change { Change::Unary(ref c) => { println!(" {}: {}", c.type_(), c.ident().name.as_str()); + session.span_warn(*c.span(), "change"); }, Change::Binary(ref c) => { println!(" {:?}: {}", c.type_(), c.ident().name.as_str()); + session.span_warn(*c.new_span(), "change"); }, } - // session.span_warn(*change.span(), "change"); // span_note!(session, change.span(), "S0001"); } } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 7195544a23f6b..ab107d0416587 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -5,15 +5,18 @@ use rustc::hir::def::Def::*; use rustc::hir::def::Export; use rustc::hir::def_id::DefId; use rustc::middle::cstore::CrateStore; +use rustc::ty::TyCtxt; use rustc::ty::Visibility::Public; +use std::borrow::Borrow; use std::collections::{HashMap, HashSet, VecDeque}; /// Traverse the two root modules in an interleaved manner. /// /// Match up pairs of modules from the two crate versions and compare for changes. /// Matching children get processed in the same fashion. -pub fn traverse_modules(cstore: &CrateStore, new: DefId, old: DefId) -> ChangeSet { +pub fn traverse_modules(tcx: &TyCtxt, new: DefId, old: DefId) -> ChangeSet { + let cstore = &tcx.sess.cstore; let mut changes = ChangeSet::default(); let mut visited = HashSet::new(); let mut children = HashMap::new(); @@ -22,8 +25,8 @@ pub fn traverse_modules(cstore: &CrateStore, new: DefId, old: DefId) -> ChangeSe mod_queue.push_back((new, old)); while let Some((new_did, old_did)) = mod_queue.pop_front() { - let mut c_new = cstore.item_children(new_did); - let mut c_old = cstore.item_children(old_did); + let mut c_new = cstore.item_children(new_did, tcx.sess); + let mut c_old = cstore.item_children(old_did, tcx.sess); for child in c_new .drain(..) @@ -47,7 +50,7 @@ pub fn traverse_modules(cstore: &CrateStore, new: DefId, old: DefId) -> ChangeSe } } (Some(n), Some(o)) => { - if let Some(change) = diff_items(cstore, n, o) { + if let Some(change) = diff_items(cstore.borrow(), n, o) { changes.add_change(change); } } diff --git a/tests/examples/addition.out b/tests/examples/addition.out index e6afd9497117d..e0378cff024d1 100644 --- a/tests/examples/addition.out +++ b/tests/examples/addition.out @@ -1,3 +1,9 @@ max: TechnicallyBreaking Addition: Abc +/home/twk/gsoc/rust-semverver/tests/examples/addition.rs:6:5: 6:20 +warning: change + Addition: a +/home/twk/gsoc/rust-semverver/tests/examples/addition.rs:10:5: 10:6 +warning: change + diff --git a/tests/examples/addition_path.out b/tests/examples/addition_path.out index 8d9f73208af1d..10954dd8e2dcc 100644 --- a/tests/examples/addition_path.out +++ b/tests/examples/addition_path.out @@ -1,4 +1,13 @@ max: TechnicallyBreaking Addition: b +/home/twk/gsoc/rust-semverver/tests/examples/addition_path.rs:13:9: 14:6 +warning: change + Addition: c +/home/twk/gsoc/rust-semverver/tests/examples/addition_path.rs:17:9: 18:6 +warning: change + Addition: Abc +/home/twk/gsoc/rust-semverver/tests/examples/addition_path.rs:20:13: 20:25 +warning: change + diff --git a/tests/examples/kind_change.out b/tests/examples/kind_change.out index b52f571a2e090..b5fb109ed6635 100644 --- a/tests/examples/kind_change.out +++ b/tests/examples/kind_change.out @@ -1,2 +1,4 @@ max: Breaking KindDifference: Abc +warning: change + diff --git a/tests/examples/pathologic_paths.out b/tests/examples/pathologic_paths.out index 60a190c6f5f06..09515e6b31064 100644 --- a/tests/examples/pathologic_paths.out +++ b/tests/examples/pathologic_paths.out @@ -1,3 +1,9 @@ max: TechnicallyBreaking Addition: a +/home/twk/gsoc/rust-semverver/tests/examples/pathologic_paths.rs:11:25: 11:44 +warning: change + Addition: b +/home/twk/gsoc/rust-semverver/tests/examples/pathologic_paths.rs:12:25: 12:47 +warning: change + diff --git a/tests/examples/removal.out b/tests/examples/removal.out index 5b00f39f2d696..a70cf44a3d4bc 100644 --- a/tests/examples/removal.out +++ b/tests/examples/removal.out @@ -1,3 +1,9 @@ max: Breaking Removal: Abc +/home/twk/gsoc/rust-semverver/tests/examples/removal.rs:2:5: 2:20 +warning: change + Removal: a +/home/twk/gsoc/rust-semverver/tests/examples/removal.rs:6:5: 6:6 +warning: change + diff --git a/tests/examples/removal_path.out b/tests/examples/removal_path.out index 564410e6c1db8..951d92a66d9e2 100644 --- a/tests/examples/removal_path.out +++ b/tests/examples/removal_path.out @@ -1,4 +1,13 @@ max: Breaking Removal: b +/home/twk/gsoc/rust-semverver/tests/examples/removal_path.rs:7:9: 8:6 +warning: change + Removal: c +/home/twk/gsoc/rust-semverver/tests/examples/removal_path.rs:11:9: 12:6 +warning: change + Removal: Abc +/home/twk/gsoc/rust-semverver/tests/examples/removal_path.rs:14:13: 14:25 +warning: change + From 91dd37d4c9d8091fe87130cfdd6b685d68e1566a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 11 Jun 2017 16:21:39 +0200 Subject: [PATCH 055/553] Fixed tests (we changed the output code, duh) --- tests/examples/addition.out | 2 -- tests/examples/addition_path.out | 3 --- tests/examples/pathologic_paths.out | 2 -- tests/examples/removal.out | 2 -- tests/examples/removal_path.out | 3 --- 5 files changed, 12 deletions(-) diff --git a/tests/examples/addition.out b/tests/examples/addition.out index e0378cff024d1..0d2e6d82728fc 100644 --- a/tests/examples/addition.out +++ b/tests/examples/addition.out @@ -1,9 +1,7 @@ max: TechnicallyBreaking Addition: Abc -/home/twk/gsoc/rust-semverver/tests/examples/addition.rs:6:5: 6:20 warning: change Addition: a -/home/twk/gsoc/rust-semverver/tests/examples/addition.rs:10:5: 10:6 warning: change diff --git a/tests/examples/addition_path.out b/tests/examples/addition_path.out index 10954dd8e2dcc..cbf313f5b547c 100644 --- a/tests/examples/addition_path.out +++ b/tests/examples/addition_path.out @@ -1,13 +1,10 @@ max: TechnicallyBreaking Addition: b -/home/twk/gsoc/rust-semverver/tests/examples/addition_path.rs:13:9: 14:6 warning: change Addition: c -/home/twk/gsoc/rust-semverver/tests/examples/addition_path.rs:17:9: 18:6 warning: change Addition: Abc -/home/twk/gsoc/rust-semverver/tests/examples/addition_path.rs:20:13: 20:25 warning: change diff --git a/tests/examples/pathologic_paths.out b/tests/examples/pathologic_paths.out index 09515e6b31064..f19052df9d864 100644 --- a/tests/examples/pathologic_paths.out +++ b/tests/examples/pathologic_paths.out @@ -1,9 +1,7 @@ max: TechnicallyBreaking Addition: a -/home/twk/gsoc/rust-semverver/tests/examples/pathologic_paths.rs:11:25: 11:44 warning: change Addition: b -/home/twk/gsoc/rust-semverver/tests/examples/pathologic_paths.rs:12:25: 12:47 warning: change diff --git a/tests/examples/removal.out b/tests/examples/removal.out index a70cf44a3d4bc..e0c96b3b6d861 100644 --- a/tests/examples/removal.out +++ b/tests/examples/removal.out @@ -1,9 +1,7 @@ max: Breaking Removal: Abc -/home/twk/gsoc/rust-semverver/tests/examples/removal.rs:2:5: 2:20 warning: change Removal: a -/home/twk/gsoc/rust-semverver/tests/examples/removal.rs:6:5: 6:6 warning: change diff --git a/tests/examples/removal_path.out b/tests/examples/removal_path.out index 951d92a66d9e2..30a039afafb7b 100644 --- a/tests/examples/removal_path.out +++ b/tests/examples/removal_path.out @@ -1,13 +1,10 @@ max: Breaking Removal: b -/home/twk/gsoc/rust-semverver/tests/examples/removal_path.rs:7:9: 8:6 warning: change Removal: c -/home/twk/gsoc/rust-semverver/tests/examples/removal_path.rs:11:9: 12:6 warning: change Removal: Abc -/home/twk/gsoc/rust-semverver/tests/examples/removal_path.rs:14:13: 14:25 warning: change From 9613dacdea9fb9a0d18802800f6c7db6be82b0d9 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 12 Jun 2017 11:29:26 +0200 Subject: [PATCH 056/553] Cleaned up our kind-of-broken ordering of "old" and "new" Also added some initial stuff to be used for further checks. --- src/bin/rust_semverver.rs | 34 ++++++++++++++--------------- src/semcheck/traverse.rs | 45 ++++++++++++++++++++++----------------- 2 files changed, 42 insertions(+), 37 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 28db9119c5a48..77de99036a259 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -30,19 +30,19 @@ fn callback(state: &driver::CompileState) { let tcx = state.tcx.unwrap(); let cstore = &tcx.sess.cstore; - let (new_did, old_did) = if std::env::var("RUST_SEMVERVER_TEST").is_err() { + let (old_did, new_did) = if std::env::var("RUST_SEMVERVER_TEST").is_err() { // this is an actual program run let cnums = cstore .crates() .iter() - .fold((None, None), |(n, o), crate_num| { + .fold((None, None), |(o, n), crate_num| { let name = cstore.crate_name(*crate_num); - if name == "new" { - (Some(*crate_num), o) - } else if name == "old" { - (n, Some(*crate_num)) + if name == "old" { + (Some(*crate_num), n) + } else if name == "new" { + (o, Some(*crate_num)) } else { - (n, o) + (o, n) } }); if let (Some(c0), Some(c1)) = cnums { @@ -55,7 +55,7 @@ fn callback(state: &driver::CompileState) { index: CRATE_DEF_INDEX, }) } else { - tcx.sess.err("could not find crate `new` and/or `old`"); + tcx.sess.err("could not find crate `old` and/or `new`"); return; } } else { @@ -84,26 +84,26 @@ fn callback(state: &driver::CompileState) { let dids = children .drain(..) - .fold((None, None), |(n, o), child| { + .fold((None, None), |(o, n), child| { let child_name = String::from(&*child.ident.name.as_str()); - if child_name == "new" { - (Some(child.def.def_id()), o) - } else if child_name == "old" { - (n, Some(child.def.def_id())) + if child_name == "old" { + (Some(child.def.def_id()), n) + } else if child_name == "new" { + (o, Some(child.def.def_id())) } else { - (n, o) + (o, n) } }); - if let (Some(n), Some(o)) = dids { - (n, o) + if let (Some(o), Some(n)) = dids { + (o, n) } else { tcx.sess.err("could not find module `new` and/or `old` in crate `oldandnew`"); return; } }; - let changes = traverse_modules(&tcx, new_did, old_did); + let changes = traverse_modules(&tcx, old_did, new_did); changes.output(tcx.sess); } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index ab107d0416587..21f809cafdec2 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -1,41 +1,40 @@ +use semcheck::changes::BinaryChangeType; use semcheck::changes::BinaryChangeType::*; use semcheck::changes::{Change, ChangeSet}; use rustc::hir::def::Def::*; use rustc::hir::def::Export; use rustc::hir::def_id::DefId; -use rustc::middle::cstore::CrateStore; use rustc::ty::TyCtxt; use rustc::ty::Visibility::Public; -use std::borrow::Borrow; use std::collections::{HashMap, HashSet, VecDeque}; /// Traverse the two root modules in an interleaved manner. /// /// Match up pairs of modules from the two crate versions and compare for changes. /// Matching children get processed in the same fashion. -pub fn traverse_modules(tcx: &TyCtxt, new: DefId, old: DefId) -> ChangeSet { +pub fn traverse_modules(tcx: &TyCtxt, old: DefId, new: DefId) -> ChangeSet { let cstore = &tcx.sess.cstore; let mut changes = ChangeSet::default(); let mut visited = HashSet::new(); let mut children = HashMap::new(); let mut mod_queue = VecDeque::new(); - mod_queue.push_back((new, old)); + mod_queue.push_back((old, new)); - while let Some((new_did, old_did)) = mod_queue.pop_front() { - let mut c_new = cstore.item_children(new_did, tcx.sess); + while let Some((old_did, new_did)) = mod_queue.pop_front() { let mut c_old = cstore.item_children(old_did, tcx.sess); + let mut c_new = cstore.item_children(new_did, tcx.sess); - for child in c_new + for child in c_old .drain(..) .filter(|c| cstore.visibility(c.def.def_id()) == Public) { let child_name = String::from(&*child.ident.name.as_str()); children.entry(child_name).or_insert((None, None)).0 = Some(child); } - for child in c_old + for child in c_new .drain(..) .filter(|c| cstore.visibility(c.def.def_id()) == Public) { let child_name = String::from(&*child.ident.name.as_str()); @@ -44,22 +43,22 @@ pub fn traverse_modules(tcx: &TyCtxt, new: DefId, old: DefId) -> ChangeSet { for (_, items) in children.drain() { match items { - (Some(Export { def: Mod(n), .. }), Some(Export { def: Mod(o), .. })) => { - if !visited.insert((n, o)) { - mod_queue.push_back((n, o)); + (Some(Export { def: Mod(o), .. }), Some(Export { def: Mod(n), .. })) => { + if !visited.insert((o, n)) { + mod_queue.push_back((o, n)); } } - (Some(n), Some(o)) => { - if let Some(change) = diff_items(cstore.borrow(), n, o) { + (Some(o), Some(n)) => { + if let Some(change) = diff_items(tcx, o, n) { changes.add_change(change); } } - (Some(new), None) => { - changes.add_change(Change::new_addition(new)); - } - (None, Some(old)) => { + (Some(old), None) => { changes.add_change(Change::new_removal(old)); } + (None, Some(new)) => { + changes.add_change(Change::new_addition(new)); + } (None, None) => unreachable!(), } } @@ -72,13 +71,14 @@ pub fn traverse_modules(tcx: &TyCtxt, new: DefId, old: DefId) -> ChangeSet { /// /// If the two items can't be meaningfully compared because they are of different kinds, /// we return that difference directly. -pub fn diff_items(_: &CrateStore, new: Export, old: Export) -> Option { - match (new.def, old.def) { +fn diff_items(tcx: &TyCtxt, old: Export, new: Export) -> Option { + match (old.def, new.def) { (Struct(_), Struct(_)) => Some(Change::new_binary(Unknown, old, new)), (Union(_), Union(_)) => Some(Change::new_binary(Unknown, old, new)), (Enum(_), Enum(_)) => Some(Change::new_binary(Unknown, old, new)), (Trait(_), Trait(_)) => Some(Change::new_binary(Unknown, old, new)), - (TyAlias(_), TyAlias(_)) => Some(Change::new_binary(Unknown, old, new)), + (TyAlias(o), TyAlias(n)) => + diff_tyaliases(tcx, o, n).map(|t| Change::new_binary(t, old, new)), (Fn(_), Fn(_)) => Some(Change::new_binary(Unknown, old, new)), (Const(_), Const(_)) => Some(Change::new_binary(Unknown, old, new)), (Static(_, _), Static(_, _)) => Some(Change::new_binary(Unknown, old, new)), @@ -87,3 +87,8 @@ pub fn diff_items(_: &CrateStore, new: Export, old: Export) -> Option { _ => Some(Change::new_binary(KindDifference, old, new)), } } + +fn diff_tyaliases(tcx: &TyCtxt, old: DefId, new: DefId) -> Option { + println!("matching TyAlias'es found"); + None +} From c58465a207dc866784b3166150fe33ee4c80cd6b Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 14 Jun 2017 22:55:05 +0200 Subject: [PATCH 057/553] First version of generics traversal. We are now able to determine whether type and region parameters have been added or removed. --- src/semcheck/changes.rs | 12 +++++++ src/semcheck/traverse.rs | 68 +++++++++++++++++++++++++++++++++---- tests/examples/ty_alias.out | 16 +++++++++ tests/examples/ty_alias.rs | 17 ++++++++++ 4 files changed, 107 insertions(+), 6 deletions(-) create mode 100644 tests/examples/ty_alias.out create mode 100644 tests/examples/ty_alias.rs diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 827ee2d5a31a6..ac44885e863ed 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -49,6 +49,10 @@ impl<'a> From<&'a BinaryChangeType> for ChangeCategory { fn from(type_: &BinaryChangeType) -> ChangeCategory { match *type_ { KindDifference | + RegionParameterAdded | + RegionParameterRemoved | + TypeParameterAdded { .. } | + TypeParameterRemoved { .. } | TypeSpecialization | StructFieldAdded { .. } | StructFieldRemoved { .. } | @@ -87,6 +91,14 @@ impl<'a> From<&'a Change> for ChangeCategory { pub enum BinaryChangeType { /// An item has changed it's kind. KindDifference, + /// A region parameter has been added to an item. + RegionParameterAdded, + /// A region parameter has been removed from an item. + RegionParameterRemoved, + /// A type parameter has been added to an item. + TypeParameterAdded { defaulted: bool }, + /// A type parameter has been removed from an item. + TypeParameterRemoved { defaulted: bool }, /// An item has changed it's type (signature) to be more general. TypeGeneralization, /// An item has changed it's type (signature) to be less general. diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 21f809cafdec2..b53bb205e2a63 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -49,9 +49,7 @@ pub fn traverse_modules(tcx: &TyCtxt, old: DefId, new: DefId) -> ChangeSet { } } (Some(o), Some(n)) => { - if let Some(change) = diff_items(tcx, o, n) { - changes.add_change(change); - } + diff_items(&mut changes, tcx, o, n); } (Some(old), None) => { changes.add_change(Change::new_removal(old)); @@ -71,8 +69,13 @@ pub fn traverse_modules(tcx: &TyCtxt, old: DefId, new: DefId) -> ChangeSet { /// /// If the two items can't be meaningfully compared because they are of different kinds, /// we return that difference directly. -fn diff_items(tcx: &TyCtxt, old: Export, new: Export) -> Option { - match (old.def, new.def) { +fn diff_items(changes: &mut ChangeSet, tcx: &TyCtxt, old: Export, new: Export) { + let mut generics_changes = diff_generics(tcx, old.def.def_id(), new.def.def_id()); + for change_type in generics_changes.drain(..) { + changes.add_change(Change::new_binary(change_type, old, new)); + } + + let change = match (old.def, new.def) { (Struct(_), Struct(_)) => Some(Change::new_binary(Unknown, old, new)), (Union(_), Union(_)) => Some(Change::new_binary(Unknown, old, new)), (Enum(_), Enum(_)) => Some(Change::new_binary(Unknown, old, new)), @@ -85,10 +88,63 @@ fn diff_items(tcx: &TyCtxt, old: Export, new: Export) -> Option { (Method(_), Method(_)) => Some(Change::new_binary(Unknown, old, new)), (Macro(_, _), Macro(_, _)) => Some(Change::new_binary(Unknown, old, new)), _ => Some(Change::new_binary(KindDifference, old, new)), + }; + + if let Some(c) = change { + changes.add_change(c); + } +} + +fn diff_generics(tcx: &TyCtxt, old: DefId, new: DefId) -> Vec { + use std::cmp::max; + + let mut ret = Vec::new(); + + let old_gen = tcx.generics_of(old); + let new_gen = tcx.generics_of(new); + + for i in 0..max(old_gen.regions.len(), new_gen.regions.len()) { + match (old_gen.regions.get(i), new_gen.regions.get(i)) { + (Some(_ /* old_region */), Some(_ /* new_region */)) => { + // TODO: handle name changes? + }, + (Some(_ /* old_region */), None) => { + ret.push(RegionParameterRemoved); + }, + (None, Some(_ /* new_region */)) => { + ret.push(RegionParameterAdded); + }, + (None, None) => unreachable!(), + } + } + + for i in 0..max(old_gen.types.len(), new_gen.types.len()) { + match (old_gen.types.get(i), new_gen.types.get(i)) { + (Some(old_type), Some(new_type)) => { + if old_type.has_default && !new_type.has_default { + // TODO: major for sure + } else if !old_type.has_default && new_type.has_default { + // TODO: minor, I guess? + } + }, + (Some(old_type), None) => { + ret.push(TypeParameterRemoved { defaulted: old_type.has_default }); + }, + (None, Some(new_type)) => { + ret.push(TypeParameterAdded { defaulted: new_type.has_default }); + }, + (None, None) => unreachable!(), + } } + + ret } +/// Given two type aliases' definitions, compare their types. fn diff_tyaliases(tcx: &TyCtxt, old: DefId, new: DefId) -> Option { - println!("matching TyAlias'es found"); + // let cstore = &tcx.sess.cstore; + /* println!("matching TyAlias'es found"); + println!("old: {:?}", tcx.type_of(old)); + println!("new: {:?}", tcx.type_of(new));*/ None } diff --git a/tests/examples/ty_alias.out b/tests/examples/ty_alias.out new file mode 100644 index 0000000000000..e61bbdb5b3917 --- /dev/null +++ b/tests/examples/ty_alias.out @@ -0,0 +1,16 @@ +max: Breaking + RegionParameterAdded: B +warning: change + + RegionParameterRemoved: C +warning: change + + TypeParameterAdded { defaulted: true }: D +warning: change + + TypeParameterAdded { defaulted: false }: E +warning: change + + TypeParameterRemoved { defaulted: false }: F +warning: change + diff --git a/tests/examples/ty_alias.rs b/tests/examples/ty_alias.rs new file mode 100644 index 0000000000000..3d041a8fa5b0b --- /dev/null +++ b/tests/examples/ty_alias.rs @@ -0,0 +1,17 @@ +pub mod old { + 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, T> = &'a T; +} + +pub mod new { + pub type A = u16; + pub type B<'a, 'b, T> = (&'a T, &'b T); + pub type C = T; + pub type D<'a, T, U=T> = (&'a T, U); + pub type E<'a, T, U> = (&'a T, U); + pub type F<'a> = (&'a u8); +} From 7c75d5826ddb22abd61525ceb4a45507ccbce8a2 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 15 Jun 2017 14:11:58 +0200 Subject: [PATCH 058/553] Added DefId mapping and separated passes. --- src/lib.rs | 2 +- src/semcheck/traverse.rs | 31 ++++++++++++++++++++++++++++--- tests/examples/ty_alias.out | 5 ++++- tests/examples/ty_alias.rs | 8 +++++--- 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 006d5a0b1ebaa..8cef6b28dc47d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ -#![feature(rustc_private)] #![feature(rustc_diagnostic_macros)] +#![feature(rustc_private)] #[cfg(test)] #[macro_use] diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index b53bb205e2a63..46ee55c34e580 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -10,6 +10,21 @@ use rustc::ty::Visibility::Public; use std::collections::{HashMap, HashSet, VecDeque}; +#[derive(Default)] +struct IdMapping { + pub mapping: HashMap, +} + +impl IdMapping { + pub fn add(&mut self, old: Export, new: Export) { + self.mapping.insert(old.def.def_id(), (new.def.def_id(), old, new)); + } + + pub fn get_new_id(&self, old: DefId) -> DefId { + self.mapping[&old].0 + } +} + /// Traverse the two root modules in an interleaved manner. /// /// Match up pairs of modules from the two crate versions and compare for changes. @@ -17,6 +32,7 @@ use std::collections::{HashMap, HashSet, VecDeque}; pub fn traverse_modules(tcx: &TyCtxt, old: DefId, new: DefId) -> ChangeSet { let cstore = &tcx.sess.cstore; let mut changes = ChangeSet::default(); + let mut id_mapping = IdMapping::default(); let mut visited = HashSet::new(); let mut children = HashMap::new(); let mut mod_queue = VecDeque::new(); @@ -49,7 +65,7 @@ pub fn traverse_modules(tcx: &TyCtxt, old: DefId, new: DefId) -> ChangeSet { } } (Some(o), Some(n)) => { - diff_items(&mut changes, tcx, o, n); + id_mapping.add(o, n); } (Some(old), None) => { changes.add_change(Change::new_removal(old)); @@ -62,6 +78,10 @@ pub fn traverse_modules(tcx: &TyCtxt, old: DefId, new: DefId) -> ChangeSet { } } + for &(_, old, new) in id_mapping.mapping.values() { + diff_items(&mut changes, &id_mapping, tcx, old, new); + } + changes } @@ -69,7 +89,11 @@ pub fn traverse_modules(tcx: &TyCtxt, old: DefId, new: DefId) -> ChangeSet { /// /// If the two items can't be meaningfully compared because they are of different kinds, /// we return that difference directly. -fn diff_items(changes: &mut ChangeSet, tcx: &TyCtxt, old: Export, new: Export) { +fn diff_items(changes: &mut ChangeSet, + id_mapping: &IdMapping, + tcx: &TyCtxt, + old: Export, + new: Export) { let mut generics_changes = diff_generics(tcx, old.def.def_id(), new.def.def_id()); for change_type in generics_changes.drain(..) { changes.add_change(Change::new_binary(change_type, old, new)); @@ -141,7 +165,8 @@ fn diff_generics(tcx: &TyCtxt, old: DefId, new: DefId) -> Vec } /// Given two type aliases' definitions, compare their types. -fn diff_tyaliases(tcx: &TyCtxt, old: DefId, new: DefId) -> Option { +fn diff_tyaliases(/*tcx*/ _: &TyCtxt, /*old*/ _: DefId, /*new*/ _: DefId) + -> Option { // let cstore = &tcx.sess.cstore; /* println!("matching TyAlias'es found"); println!("old: {:?}", tcx.type_of(old)); diff --git a/tests/examples/ty_alias.out b/tests/examples/ty_alias.out index e61bbdb5b3917..043aa3a1ffa5e 100644 --- a/tests/examples/ty_alias.out +++ b/tests/examples/ty_alias.out @@ -11,6 +11,9 @@ warning: change TypeParameterAdded { defaulted: false }: E warning: change - TypeParameterRemoved { defaulted: false }: F + TypeParameterRemoved { defaulted: true }: F +warning: change + + TypeParameterRemoved { defaulted: false }: G warning: change diff --git a/tests/examples/ty_alias.rs b/tests/examples/ty_alias.rs index 3d041a8fa5b0b..19868abae7987 100644 --- a/tests/examples/ty_alias.rs +++ b/tests/examples/ty_alias.rs @@ -4,14 +4,16 @@ pub mod old { 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, T> = &'a T; + pub type F<'a, U=u8> = &'a U; + pub type G<'a, T> = &'a T; } pub mod new { pub type A = u16; - pub type B<'a, 'b, T> = (&'a T, &'b T); + pub type B<'a, 'b : 'a, T> = (&'a T, &'b T); pub type C = T; pub type D<'a, T, U=T> = (&'a T, U); pub type E<'a, T, U> = (&'a T, U); - pub type F<'a> = (&'a u8); + pub type F<'a> = &'a u8; + pub type G<'a> = (&'a u8); } From 6af7af9ea0738786aaec4f690115bf3c42e4dbcc Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 15 Jun 2017 15:42:46 +0200 Subject: [PATCH 059/553] Extremely rudimentary machanisms to compare items' types --- src/semcheck/traverse.rs | 35 ++++++++++++++++++++++++++++++----- tests/examples/struct.out | 6 ++++++ tests/examples/struct.rs | 11 +++++++++++ tests/examples/ty_alias.out | 2 ++ 4 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 tests/examples/struct.out create mode 100644 tests/examples/struct.rs diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 46ee55c34e580..837bebd77ea56 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -1,11 +1,12 @@ use semcheck::changes::BinaryChangeType; use semcheck::changes::BinaryChangeType::*; -use semcheck::changes::{Change, ChangeSet}; +use semcheck::changes::{Change, ChangeCategory, ChangeSet}; use rustc::hir::def::Def::*; use rustc::hir::def::Export; use rustc::hir::def_id::DefId; use rustc::ty::TyCtxt; +use rustc::ty::subst::{Subst, Substs}; use rustc::ty::Visibility::Public; use std::collections::{HashMap, HashSet, VecDeque}; @@ -94,8 +95,13 @@ fn diff_items(changes: &mut ChangeSet, tcx: &TyCtxt, old: Export, new: Export) { + let mut check_type = true; let mut generics_changes = diff_generics(tcx, old.def.def_id(), new.def.def_id()); for change_type in generics_changes.drain(..) { + if ChangeCategory::from(&change_type) == ChangeCategory::Breaking { + check_type = false; + } + changes.add_change(Change::new_binary(change_type, old, new)); } @@ -111,14 +117,35 @@ fn diff_items(changes: &mut ChangeSet, (Static(_, _), Static(_, _)) => Some(Change::new_binary(Unknown, old, new)), (Method(_), Method(_)) => Some(Change::new_binary(Unknown, old, new)), (Macro(_, _), Macro(_, _)) => Some(Change::new_binary(Unknown, old, new)), - _ => Some(Change::new_binary(KindDifference, old, new)), + _ => { + check_type = false; + Some(Change::new_binary(KindDifference, old, new)) + }, }; + if check_type { + let _ = diff_type(id_mapping, tcx, old.def.def_id(), new.def.def_id()); + } + if let Some(c) = change { changes.add_change(c); } } +fn diff_type(id_mapping: &IdMapping, tcx: &TyCtxt, old: DefId, new: DefId) + -> Vec +{ + let res = Vec::new(); + + let new_ty = tcx.type_of(new); + let old_ty = tcx.type_of(old).subst(*tcx, Substs::identity_for_item(*tcx, new)); + + println!("old_ty: {:?}", old_ty); + println!("new_ty: {:?}", new_ty); + + res +} + fn diff_generics(tcx: &TyCtxt, old: DefId, new: DefId) -> Vec { use std::cmp::max; @@ -129,15 +156,13 @@ fn diff_generics(tcx: &TyCtxt, old: DefId, new: DefId) -> Vec for i in 0..max(old_gen.regions.len(), new_gen.regions.len()) { match (old_gen.regions.get(i), new_gen.regions.get(i)) { - (Some(_ /* old_region */), Some(_ /* new_region */)) => { - // TODO: handle name changes? - }, (Some(_ /* old_region */), None) => { ret.push(RegionParameterRemoved); }, (None, Some(_ /* new_region */)) => { ret.push(RegionParameterAdded); }, + (Some(_), Some(_)) => (), (None, None) => unreachable!(), } } diff --git a/tests/examples/struct.out b/tests/examples/struct.out new file mode 100644 index 0000000000000..0b7583bd92b3f --- /dev/null +++ b/tests/examples/struct.out @@ -0,0 +1,6 @@ +old_ty: oldandnew::old::Abc +new_ty: oldandnew::new::Abc +max: Breaking + Unknown: Abc +warning: change + diff --git a/tests/examples/struct.rs b/tests/examples/struct.rs new file mode 100644 index 0000000000000..3d133ee32ed43 --- /dev/null +++ b/tests/examples/struct.rs @@ -0,0 +1,11 @@ +pub mod old { + pub struct Abc { + field: A, + } +} + +pub mod new { + pub struct Abc { + field: B, + } +} diff --git a/tests/examples/ty_alias.out b/tests/examples/ty_alias.out index 043aa3a1ffa5e..78429e8b35bd3 100644 --- a/tests/examples/ty_alias.out +++ b/tests/examples/ty_alias.out @@ -1,3 +1,5 @@ +old_ty: u8 +new_ty: u16 max: Breaking RegionParameterAdded: B warning: change From 1b116f9e00a8679df7f32169d2d1a924a0ff89de Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 15 Jun 2017 17:06:02 +0200 Subject: [PATCH 060/553] Small fixes and cleanup in preparation for type traversal. --- src/semcheck/traverse.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 837bebd77ea56..0c922c8af3de4 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -123,16 +123,16 @@ fn diff_items(changes: &mut ChangeSet, }, }; - if check_type { - let _ = diff_type(id_mapping, tcx, old.def.def_id(), new.def.def_id()); - } - if let Some(c) = change { changes.add_change(c); } + + if check_type { + let _ = diff_type(id_mapping, tcx, old.def.def_id(), new.def.def_id()); + } } -fn diff_type(id_mapping: &IdMapping, tcx: &TyCtxt, old: DefId, new: DefId) +fn diff_type(_: &IdMapping, tcx: &TyCtxt, old: DefId, new: DefId) -> Vec { let res = Vec::new(); @@ -172,8 +172,12 @@ fn diff_generics(tcx: &TyCtxt, old: DefId, new: DefId) -> Vec (Some(old_type), Some(new_type)) => { if old_type.has_default && !new_type.has_default { // TODO: major for sure + ret.push(TypeParameterRemoved { defaulted: true }); + ret.push(TypeParameterAdded { defaulted: false }); } else if !old_type.has_default && new_type.has_default { // TODO: minor, I guess? + ret.push(TypeParameterRemoved { defaulted: false }); + ret.push(TypeParameterAdded { defaulted: true }); } }, (Some(old_type), None) => { From cc612bb7c418ebb33c0a4c46673d425d5ed7cf0d Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 15 Jun 2017 18:53:15 +0200 Subject: [PATCH 061/553] Added version number generation. --- Cargo.toml | 1 + src/bin/cargo_semver.rs | 1 + src/bin/rust_semverver.rs | 24 ++++++++++++++++++------ src/lib.rs | 1 + src/semcheck/changes.rs | 16 ++++++++++++++-- src/semcheck/traverse.rs | 9 +++++++++ tests/examples.rs | 1 + tests/examples/addition.out | 2 +- tests/examples/addition_path.out | 2 +- tests/examples/kind_change.out | 2 +- tests/examples/pathologic_paths.out | 2 +- tests/examples/pub_use.out | 2 +- tests/examples/removal.out | 2 +- tests/examples/removal_path.out | 2 +- tests/examples/struct.out | 2 +- tests/examples/ty_alias.out | 2 +- 16 files changed, 54 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 52372b2fe1e38..2bd03979c0dfb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ path = "src/bin/rust_semverver.rs" [dependencies] cargo = "^0.18.0" crates-io = "^0.7.0" +semver = "^0.7.0" [dev-dependencies] quickcheck = "^0.4.1" diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index c3640aac08411..054f742a44659 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -96,6 +96,7 @@ fn do_main() -> CargoResult<()> { .args(&[format!("-L{}", local_compilation.deps_output.display())]) .arg("-") .stdin(Stdio::piped()) + .env("RUST_SEMVER_CRATE_VERSION", format!("{}", &remote_crate.max_version)) .spawn() .map_err(|e| human(format!("could not spawn rustc: {}", e)))?; diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 77de99036a259..e9a36bd810c1c 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -6,6 +6,7 @@ extern crate rustc; extern crate rustc_driver; extern crate rustc_errors; extern crate rustc_metadata; +extern crate semver; extern crate semverver; extern crate syntax; @@ -26,7 +27,7 @@ use syntax::ast; /// /// To compare the two well-typed crates, we first find the aptly named crates `new` and `old`, /// find their root modules and then proceed to walk their module trees. -fn callback(state: &driver::CompileState) { +fn callback(state: &driver::CompileState, version: &str) { let tcx = state.tcx.unwrap(); let cstore = &tcx.sess.cstore; @@ -105,17 +106,21 @@ fn callback(state: &driver::CompileState) { let changes = traverse_modules(&tcx, old_did, new_did); - changes.output(tcx.sess); + changes.output(tcx.sess, version); } /// Our wrapper to control compilation. struct SemVerVerCompilerCalls { default: RustcDefaultCalls, + version: String, } impl SemVerVerCompilerCalls { - pub fn new() -> SemVerVerCompilerCalls { - SemVerVerCompilerCalls { default: RustcDefaultCalls } + pub fn new(version: String) -> SemVerVerCompilerCalls { + SemVerVerCompilerCalls { + default: RustcDefaultCalls, + version: version, + } } } @@ -161,8 +166,9 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { let mut controller = self.default.build_controller(sess, matches); let old_callback = std::mem::replace(&mut controller.after_analysis.callback, box |_| {}); + let version = self.version.clone(); controller.after_analysis.callback = box move |state| { - callback(state); + callback(state, &version); old_callback(state); }; controller.after_analysis.stop = Compilation::Stop; @@ -204,7 +210,13 @@ fn main() { .collect() }; - let mut cc = SemVerVerCompilerCalls::new(); + let version = if let Ok(ver) = std::env::var("RUST_SEMVER_CRATE_VERSION") { + ver + } else { + std::process::exit(1); + }; + + let mut cc = SemVerVerCompilerCalls::new(version); let (result, _) = rustc_driver::run_compiler(&args, &mut cc, None, None); if let Err(count) = result { if count > 0 { diff --git a/src/lib.rs b/src/lib.rs index 8cef6b28dc47d..a3382e5606dac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ extern crate quickcheck; extern crate rustc; extern crate rustc_errors; +extern crate semver; extern crate syntax; extern crate syntax_pos; diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index ac44885e863ed..2fc664d728c93 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -1,6 +1,8 @@ use rustc::hir::def::Export; use rustc::session::Session; +use semver::Version; + use std::collections::BTreeSet; use std::cmp::Ordering; @@ -306,8 +308,18 @@ impl ChangeSet { /// Format the contents of a change set for user output. /// /// TODO: replace this with something more sophisticated. - pub fn output(&self, session: &Session) { - println!("max: {:?}", self.max); + pub fn output(&self, session: &Session, version: &str) { + if let Ok(mut new_version) = Version::parse(version) { + match self.max { + Patch => new_version.increment_patch(), + NonBreaking | TechnicallyBreaking => new_version.increment_minor(), + Breaking => new_version.increment_major(), + } + + println!("version bump: {} -> ({:?}) -> {}", version, self.max, new_version); + } else { + println!("max change: {} (could not parse) -> {:?}", version, self.max); + } for change in &self.changes { match *change { diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 0c922c8af3de4..4e1346f138886 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -6,6 +6,7 @@ use rustc::hir::def::Def::*; use rustc::hir::def::Export; use rustc::hir::def_id::DefId; use rustc::ty::TyCtxt; +use rustc::ty::fold::TypeFolder; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::Visibility::Public; @@ -132,6 +133,14 @@ fn diff_items(changes: &mut ChangeSet, } } +struct ComparisonFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + tcx: TyCtxt<'a, 'gcx, 'tcx>, +} + +impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ComparisonFolder<'a, 'gcx, 'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } +} + fn diff_type(_: &IdMapping, tcx: &TyCtxt, old: DefId, new: DefId) -> Vec { diff --git a/tests/examples.rs b/tests/examples.rs index 266553c38dcde..f0ecb721b88e2 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -38,6 +38,7 @@ fn examples() { .env("RUST_SEMVERVER_TEST", "1") .env("RUST_LOG", "debug") .env("RUST_BACKTRACE", "full") + .env("RUST_SEMVER_CRATE_VERSION", "1.0.0") .stdin(Stdio::piped()) .stdout(out) .stderr(err) diff --git a/tests/examples/addition.out b/tests/examples/addition.out index 0d2e6d82728fc..9d46339122fdf 100644 --- a/tests/examples/addition.out +++ b/tests/examples/addition.out @@ -1,4 +1,4 @@ -max: TechnicallyBreaking +version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 Addition: Abc warning: change diff --git a/tests/examples/addition_path.out b/tests/examples/addition_path.out index cbf313f5b547c..0e1ef2456d901 100644 --- a/tests/examples/addition_path.out +++ b/tests/examples/addition_path.out @@ -1,4 +1,4 @@ -max: TechnicallyBreaking +version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 Addition: b warning: change diff --git a/tests/examples/kind_change.out b/tests/examples/kind_change.out index b5fb109ed6635..8092955019199 100644 --- a/tests/examples/kind_change.out +++ b/tests/examples/kind_change.out @@ -1,4 +1,4 @@ -max: Breaking +version bump: 1.0.0 -> (Breaking) -> 2.0.0 KindDifference: Abc warning: change diff --git a/tests/examples/pathologic_paths.out b/tests/examples/pathologic_paths.out index f19052df9d864..450febc052727 100644 --- a/tests/examples/pathologic_paths.out +++ b/tests/examples/pathologic_paths.out @@ -1,4 +1,4 @@ -max: TechnicallyBreaking +version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 Addition: a warning: change diff --git a/tests/examples/pub_use.out b/tests/examples/pub_use.out index 0f1c04fd61923..84bd4ceab5d48 100644 --- a/tests/examples/pub_use.out +++ b/tests/examples/pub_use.out @@ -1 +1 @@ -max: Patch +version bump: 1.0.0 -> (Patch) -> 1.0.1 diff --git a/tests/examples/removal.out b/tests/examples/removal.out index e0c96b3b6d861..7affcc6fa137f 100644 --- a/tests/examples/removal.out +++ b/tests/examples/removal.out @@ -1,4 +1,4 @@ -max: Breaking +version bump: 1.0.0 -> (Breaking) -> 2.0.0 Removal: Abc warning: change diff --git a/tests/examples/removal_path.out b/tests/examples/removal_path.out index 30a039afafb7b..cdcd01cef73f1 100644 --- a/tests/examples/removal_path.out +++ b/tests/examples/removal_path.out @@ -1,4 +1,4 @@ -max: Breaking +version bump: 1.0.0 -> (Breaking) -> 2.0.0 Removal: b warning: change diff --git a/tests/examples/struct.out b/tests/examples/struct.out index 0b7583bd92b3f..1e8aed0a6fce6 100644 --- a/tests/examples/struct.out +++ b/tests/examples/struct.out @@ -1,6 +1,6 @@ old_ty: oldandnew::old::Abc new_ty: oldandnew::new::Abc -max: Breaking +version bump: 1.0.0 -> (Breaking) -> 2.0.0 Unknown: Abc warning: change diff --git a/tests/examples/ty_alias.out b/tests/examples/ty_alias.out index 78429e8b35bd3..9c6b6f6f1b28d 100644 --- a/tests/examples/ty_alias.out +++ b/tests/examples/ty_alias.out @@ -1,6 +1,6 @@ old_ty: u8 new_ty: u16 -max: Breaking +version bump: 1.0.0 -> (Breaking) -> 2.0.0 RegionParameterAdded: B warning: change From 5043437eb4508c0e3a6bb0d39e5358cbecbfeabd Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 16 Jun 2017 22:35:53 +0200 Subject: [PATCH 062/553] Added first version of type comparison --- src/bin/rust_semverver.rs | 2 +- src/semcheck/changes.rs | 3 ++- src/semcheck/traverse.rs | 51 +++++++++++++++++++++++++------------ tests/examples/struct.out | 10 +++++--- tests/examples/struct.rs | 18 +++++++++++++ tests/examples/ty_alias.out | 4 +++ 6 files changed, 67 insertions(+), 21 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index e9a36bd810c1c..f66677a5b4231 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -104,7 +104,7 @@ fn callback(state: &driver::CompileState, version: &str) { } }; - let changes = traverse_modules(&tcx, old_did, new_did); + let changes = traverse_modules(tcx, old_did, new_did); changes.output(tcx.sess, version); } diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 2fc664d728c93..35dc48a5fac5f 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -53,7 +53,7 @@ impl<'a> From<&'a BinaryChangeType> for ChangeCategory { KindDifference | RegionParameterAdded | RegionParameterRemoved | - TypeParameterAdded { .. } | + TypeParameterAdded { defaulted: false } | TypeParameterRemoved { .. } | TypeSpecialization | StructFieldAdded { .. } | @@ -68,6 +68,7 @@ impl<'a> From<&'a BinaryChangeType> for ChangeCategory { TraitImplItemRemoved | Unknown => Breaking, TypeGeneralization => TechnicallyBreaking, + TypeParameterAdded { defaulted: true } => NonBreaking, } } } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 4e1346f138886..03d5c62751083 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -6,7 +6,7 @@ use rustc::hir::def::Def::*; use rustc::hir::def::Export; use rustc::hir::def_id::DefId; use rustc::ty::TyCtxt; -use rustc::ty::fold::TypeFolder; +use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::Visibility::Public; @@ -31,7 +31,7 @@ impl IdMapping { /// /// Match up pairs of modules from the two crate versions and compare for changes. /// Matching children get processed in the same fashion. -pub fn traverse_modules(tcx: &TyCtxt, old: DefId, new: DefId) -> ChangeSet { +pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { let cstore = &tcx.sess.cstore; let mut changes = ChangeSet::default(); let mut id_mapping = IdMapping::default(); @@ -93,7 +93,7 @@ pub fn traverse_modules(tcx: &TyCtxt, old: DefId, new: DefId) -> ChangeSet { /// we return that difference directly. fn diff_items(changes: &mut ChangeSet, id_mapping: &IdMapping, - tcx: &TyCtxt, + tcx: TyCtxt, old: Export, new: Export) { let mut check_type = true; @@ -107,7 +107,7 @@ fn diff_items(changes: &mut ChangeSet, } let change = match (old.def, new.def) { - (Struct(_), Struct(_)) => Some(Change::new_binary(Unknown, old, new)), + (Struct(_), Struct(_)) => None, // Some(Change::new_binary(Unknown, old, new)), (Union(_), Union(_)) => Some(Change::new_binary(Unknown, old, new)), (Enum(_), Enum(_)) => Some(Change::new_binary(Unknown, old, new)), (Trait(_), Trait(_)) => Some(Change::new_binary(Unknown, old, new)), @@ -133,29 +133,48 @@ fn diff_items(changes: &mut ChangeSet, } } -struct ComparisonFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - tcx: TyCtxt<'a, 'gcx, 'tcx>, -} - -impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ComparisonFolder<'a, 'gcx, 'tcx> { - fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } -} -fn diff_type(_: &IdMapping, tcx: &TyCtxt, old: DefId, new: DefId) +fn diff_type(id_mapping: &IdMapping, tcx: TyCtxt, old: DefId, new: DefId) -> Vec { + use rustc::ty::AdtDef; + use rustc::ty::TypeVariants::*; + let res = Vec::new(); let new_ty = tcx.type_of(new); - let old_ty = tcx.type_of(old).subst(*tcx, Substs::identity_for_item(*tcx, new)); + let old_ty = tcx.type_of(old).subst(tcx, Substs::identity_for_item(tcx, new)); + + let old_ty_cmp = old_ty.fold_with(&mut BottomUpFolder { tcx: tcx, fldop: |ty| { + match ty.sty { + TyAdt(&AdtDef { ref did, .. }, substs) => { + let new_did = id_mapping.get_new_id(*did); + let new_adt = tcx.adt_def(new_did); + tcx.mk_adt(new_adt, substs) // TODO: error if mismatch? + }, + /* TyDynamic(predicates, region) => { - println!("old_ty: {:?}", old_ty); + }, TyClosure, TyRef (because of region?), TyProjection, TyAnon + TyProjection(projection_ty) => { + + }, */ + _ => ty, + } + }}); + + println!("old_ty: {:?}", old_ty_cmp); println!("new_ty: {:?}", new_ty); + if let Result::Err(err) = tcx.global_tcx().infer_ctxt() + .enter(|infcx| infcx.can_eq(tcx.param_env(new), old_ty_cmp, new_ty)) + { + println!("diff: {}", err); + } + res } -fn diff_generics(tcx: &TyCtxt, old: DefId, new: DefId) -> Vec { +fn diff_generics(tcx: TyCtxt, old: DefId, new: DefId) -> Vec { use std::cmp::max; let mut ret = Vec::new(); @@ -203,7 +222,7 @@ fn diff_generics(tcx: &TyCtxt, old: DefId, new: DefId) -> Vec } /// Given two type aliases' definitions, compare their types. -fn diff_tyaliases(/*tcx*/ _: &TyCtxt, /*old*/ _: DefId, /*new*/ _: DefId) +fn diff_tyaliases(/*tcx*/ _: TyCtxt, /*old*/ _: DefId, /*new*/ _: DefId) -> Option { // let cstore = &tcx.sess.cstore; /* println!("matching TyAlias'es found"); diff --git a/tests/examples/struct.out b/tests/examples/struct.out index 1e8aed0a6fce6..ddfe97f66815a 100644 --- a/tests/examples/struct.out +++ b/tests/examples/struct.out @@ -1,6 +1,10 @@ -old_ty: oldandnew::old::Abc +old_ty: oldandnew::new::Def +new_ty: oldandnew::new::Def +old_ty: oldandnew::new::Efg +new_ty: oldandnew::new::Efg +old_ty: oldandnew::new::Abc new_ty: oldandnew::new::Abc -version bump: 1.0.0 -> (Breaking) -> 2.0.0 - Unknown: Abc +version bump: 1.0.0 -> (NonBreaking) -> 1.1.0 + TypeParameterAdded { defaulted: true }: Def warning: change diff --git a/tests/examples/struct.rs b/tests/examples/struct.rs index 3d133ee32ed43..cf4d20c71648f 100644 --- a/tests/examples/struct.rs +++ b/tests/examples/struct.rs @@ -1,11 +1,29 @@ +#[allow(dead_code)] pub mod old { pub struct Abc { field: A, } + + pub struct Def { + field: u8, + } + + pub struct Efg { + pub field: u8, + } } +#[allow(dead_code)] pub mod new { pub struct Abc { field: B, } + + pub struct Def { + field: A, + } + + pub struct Efg { + pub field: u16, + } } diff --git a/tests/examples/ty_alias.out b/tests/examples/ty_alias.out index 9c6b6f6f1b28d..2604f3bcfbb4d 100644 --- a/tests/examples/ty_alias.out +++ b/tests/examples/ty_alias.out @@ -1,5 +1,9 @@ old_ty: u8 new_ty: u16 +diff: expected u8, found u16 +old_ty: &'a T +new_ty: (&'a T, U) +diff: expected reference, found tuple version bump: 1.0.0 -> (Breaking) -> 2.0.0 RegionParameterAdded: B warning: change From 4d1ab0bfb23883566d7b599b2d3c0181a3d289a2 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 17 Jun 2017 19:09:02 +0200 Subject: [PATCH 063/553] Refactored change set and pass structure. We now store changes in a more senseful fashion. This means that we'll be able to *guarantee* deterministic output after recompiles soon. Currently, that's kind of broken after every compile of the analysis target. In other news, this allows us to cleanly separate the passes of module traversal and type checking. Next step would be to add more structural checks to the first pass doing module traversal. --- src/bin/cargo_semver.rs | 2 +- src/semcheck/changes.rs | 400 ++++++++++++++++------------ src/semcheck/traverse.rs | 106 +++++--- tests/examples/addition.out | 6 +- tests/examples/addition_path.out | 8 +- tests/examples/kind_change.out | 5 +- tests/examples/pathologic_paths.out | 4 - tests/examples/removal.out | 4 - tests/examples/removal_path.out | 8 +- tests/examples/struct.out | 11 +- tests/examples/ty_alias.out | 39 ++- 11 files changed, 324 insertions(+), 269 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 054f742a44659..8be3785de366d 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -96,7 +96,7 @@ fn do_main() -> CargoResult<()> { .args(&[format!("-L{}", local_compilation.deps_output.display())]) .arg("-") .stdin(Stdio::piped()) - .env("RUST_SEMVER_CRATE_VERSION", format!("{}", &remote_crate.max_version)) + .env("RUST_SEMVER_CRATE_VERSION", &remote_crate.max_version) .spawn() .map_err(|e| human(format!("could not spawn rustc: {}", e)))?; diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 35dc48a5fac5f..1a4e6eb5fc680 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -1,9 +1,10 @@ use rustc::hir::def::Export; +use rustc::hir::def_id::DefId; use rustc::session::Session; use semver::Version; -use std::collections::BTreeSet; +use std::collections::{BTreeSet, HashMap}; use std::cmp::Ordering; use syntax::symbol::Ident; @@ -17,7 +18,7 @@ use syntax_pos::Span; /// defines them as non-breaking when introduced to the standard libraries. /// /// [1]: https://github.com/rust-lang/rfcs/blob/master/text/1105-api-evolution.md -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum ChangeCategory { /// Patch change - no change to the public API of a crate. Patch, @@ -37,60 +38,76 @@ impl<'a> Default for ChangeCategory { } } -impl<'a> From<&'a UnaryChange> for ChangeCategory { - fn from(change: &UnaryChange) -> ChangeCategory { - match *change { +/// A change record of a change that introduced or removed an item. +/// +/// It is important to note that the `Eq` and `Ord` instances are constucted to only +/// regard the span of the associated item export. This allows us to sort them by appearance +/// in the source, but possibly could create conflict later on. +/// TODO: regard the origin of the span as well. +pub enum UnaryChange { + /// An item has been added. + Addition(Export), + /// An item has been removed. + Removal(Export), +} + +impl UnaryChange { + pub fn to_category(&self) -> ChangeCategory { + match *self { UnaryChange::Addition(_) => TechnicallyBreaking, UnaryChange::Removal(_) => Breaking, } } -} -// TODO: this will need a lot of changes -impl<'a> From<&'a BinaryChangeType> for ChangeCategory { - fn from(type_: &BinaryChangeType) -> ChangeCategory { - match *type_ { - KindDifference | - RegionParameterAdded | - RegionParameterRemoved | - TypeParameterAdded { defaulted: false } | - TypeParameterRemoved { .. } | - TypeSpecialization | - StructFieldAdded { .. } | - StructFieldRemoved { .. } | - StructStyleChanged { .. } | - EnumVariantAdded | - EnumVariantRemoved | - VariantFieldAdded | - VariantFieldRemoved | - VariantFieldStyleChanged { .. } | - TraitImplItemAdded { .. } | - TraitImplItemRemoved | - Unknown => Breaking, - TypeGeneralization => TechnicallyBreaking, - TypeParameterAdded { defaulted: true } => NonBreaking, + /// Get the change item's sole export. + fn export(&self) -> &Export { + match *self { + UnaryChange::Addition(ref e) | UnaryChange::Removal(ref e) => e, + } + } + + /// Get the change item's sole span. + pub fn span(&self) -> &Span { + &self.export().span + } + + /// Get the change item's ident. + pub fn ident(&self) -> &Ident { + &self.export().ident + } + + /// Render the change's type to a string. + pub fn type_(&self) -> &'static str { + match *self { + UnaryChange::Addition(_) => "Addition", + UnaryChange::Removal(_) => "Removal", } } } -impl<'a> From<&'a BinaryChange> for ChangeCategory { - fn from(change: &BinaryChange) -> ChangeCategory { - From::from(change.type_()) +impl PartialEq for UnaryChange { + fn eq(&self, other: &UnaryChange) -> bool { + self.span() == other.span() } } -impl<'a> From<&'a Change> for ChangeCategory { - fn from(change: &Change) -> ChangeCategory { - match *change { - Change::Unary(ref u) => From::from(u), - Change::Binary(ref b) => From::from(b), - } +impl Eq for UnaryChange {} + +impl PartialOrd for UnaryChange { + fn partial_cmp(&self, other: &UnaryChange) -> Option { + self.span().partial_cmp(other.span()) + } +} + +impl Ord for UnaryChange { + fn cmp(&self, other: &UnaryChange) -> Ordering { + self.span().cmp(other.span()) } } /// The types of changes we identify between items present in both crate versions. /// TODO: this needs a lot of refinement still -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum BinaryChangeType { /// An item has changed it's kind. KindDifference, @@ -102,9 +119,9 @@ pub enum BinaryChangeType { TypeParameterAdded { defaulted: bool }, /// A type parameter has been removed from an item. TypeParameterRemoved { defaulted: bool }, - /// An item has changed it's type (signature) to be more general. + /// The bounds on a type parameter have been loosened. TypeGeneralization, - /// An item has changed it's type (signature) to be less general. + /// The bounds on a type parameter have been tightened. TypeSpecialization, /// A field has been added to a struct. StructFieldAdded { public: bool, total_public: bool }, // TODO: EXXXXPPPPLAAAAIN! @@ -122,6 +139,8 @@ pub enum BinaryChangeType { VariantFieldRemoved, /// An enum variant has changed it's style. VariantFieldStyleChanged { now_tuple: bool }, + /// A field in a struct or enum has changed it's type. + FieldTypeChanged(String), // FIXME: terrible for obvious reasons /// An impl item has been added. TraitImplItemAdded { defaulted: bool }, // TODO: EXPLAAAIN! /// An impl item has been removed. @@ -132,102 +151,44 @@ pub enum BinaryChangeType { pub use self::BinaryChangeType::*; -/// A change record. -/// -/// Consists of all information we need to compute semantic versioning properties of -/// the change, as well as data we use to output it in a nice fashion. -#[derive(PartialEq, Eq, PartialOrd, Ord)] -pub enum Change { - /// A wrapper around a unary change. - Unary(UnaryChange), - /// A wrapper around a binary change. - Binary(BinaryChange), -} - -impl Change { - /// Construct a new addition change from it's export. - pub fn new_addition(export: Export) -> Change { - Change::Unary(UnaryChange::Addition(export)) - } - - /// Construct a new removal change from it's export. - pub fn new_removal(export: Export) -> Change { - Change::Unary(UnaryChange::Removal(export)) - } - - /// Construct a new binary change from it's exports and type. - pub fn new_binary(type_: BinaryChangeType, old: Export, new: Export) -> Change { - Change::Binary(BinaryChange::new(type_, old, new)) - } -} - -/// A change record of a change that introduced or removed an item. -/// -/// It is important to note that the `Eq` and `Ord` instances are constucted to only -/// regard the span of the associated item export. This allows us to sort them by appearance -/// in the source, but possibly could create conflict later on. -pub enum UnaryChange { - /// An item has been added. - Addition(Export), - /// An item has been removed. - Removal(Export), -} - -impl UnaryChange { - /// Get the change item's sole export. - fn export(&self) -> &Export { +impl BinaryChangeType { + // TODO: this will need a lot of changes + pub fn to_category(&self) -> ChangeCategory { match *self { - UnaryChange::Addition(ref e) | UnaryChange::Removal(ref e) => e, - } - } - - /// Get the change item's sole span. - pub fn span(&self) -> &Span { - &self.export().span - } - - /// Get the change item's ident. - pub fn ident(&self) -> &Ident { - &self.export().ident - } - - /// Render the change's type to a string. - pub fn type_(&self) -> &'static str { - match *self { - UnaryChange::Addition(_) => "Addition", - UnaryChange::Removal(_) => "Removal", + KindDifference | + RegionParameterAdded | + RegionParameterRemoved | + TypeParameterAdded { defaulted: false } | + TypeParameterRemoved { .. } | + TypeSpecialization | + StructFieldAdded { .. } | + StructFieldRemoved { .. } | + StructStyleChanged { .. } | + EnumVariantAdded | + EnumVariantRemoved | + VariantFieldAdded | + VariantFieldRemoved | + VariantFieldStyleChanged { .. } | + FieldTypeChanged(_) | + TraitImplItemAdded { .. } | + TraitImplItemRemoved | + Unknown => Breaking, + TypeGeneralization => TechnicallyBreaking, + TypeParameterAdded { defaulted: true } => NonBreaking, } } } -impl PartialEq for UnaryChange { - fn eq(&self, other: &UnaryChange) -> bool { - self.span() == other.span() - } -} - -impl Eq for UnaryChange {} - -impl PartialOrd for UnaryChange { - fn partial_cmp(&self, other: &UnaryChange) -> Option { - self.span().partial_cmp(other.span()) - } -} - -impl Ord for UnaryChange { - fn cmp(&self, other: &UnaryChange) -> Ordering { - self.span().cmp(other.span()) - } -} - -/// A change record of a change of an item between versions. +/// A change record of an item kept between versions. /// /// It is important to note that the `Eq` and `Ord` instances are constucted to only /// regard the *new* span of the associated item export. This allows us to sort them -/// by appearance in *new* the source, but possibly could create conflict later on. +/// by appearance in the *new* source, but possibly could create conflict later on. pub struct BinaryChange { /// The type of the change affecting the item. - type_: BinaryChangeType, + changes: BTreeSet, + /// The most severe change category already recorded for the item. + max: ChangeCategory, /// The old export of the change item. old: Export, /// The new export of the change item. @@ -235,32 +196,37 @@ pub struct BinaryChange { } impl BinaryChange { - /// Construct a new binary change record. - pub fn new(type_: BinaryChangeType, old: Export, new: Export) -> BinaryChange { + /// Construct a new empty change record for an item. + fn new(old: Export, new: Export) -> BinaryChange { BinaryChange { - type_: type_, + changes: BTreeSet::new(), + max: ChangeCategory::default(), old: old, new: new, } } - /// Get the change's type. - pub fn type_(&self) -> &BinaryChangeType { - &self.type_ + fn add(&mut self, type_: BinaryChangeType) { + let cat = type_.to_category(); + + if cat > self.max { + self.max = cat; + } + + self.changes.insert(type_); } - /// Get the new span of the change item. - pub fn new_span(&self) -> &Span { - &self.new.span + fn to_category(&self) -> ChangeCategory { + self.max.clone() } - /// Get the old span of the change item. - pub fn old_span(&self) -> &Span { - &self.old.span + /// Get the new span of the change item. + fn new_span(&self) -> &Span { + &self.new.span } /// Get the ident of the change item. - pub fn ident(&self) -> &Ident { + fn ident(&self) -> &Ident { &self.old.ident } } @@ -285,31 +251,113 @@ impl Ord for BinaryChange { } } +/// A change record for any item. +/// +/// Consists of all information we need to compute semantic versioning properties of +/// the change(s) performed on it, as well as data we use to output it in a nice fashion. +#[derive(PartialEq, Eq, PartialOrd, Ord)] +pub enum Change { + /// A wrapper around a unary change. + Unary(UnaryChange), + /// A wrapper around a binary change set. + Binary(BinaryChange), +} + +impl Change { + fn new_addition(item: Export) -> Change { + Change::Unary(UnaryChange::Addition(item)) + } + + fn new_removal(item: Export) -> Change { + Change::Unary(UnaryChange::Removal(item)) + } + + fn new_binary(old: Export, new: Export) -> Change { + Change::Binary(BinaryChange::new(old, new)) + } + + fn add(&mut self, type_: BinaryChangeType) { + match *self { + Change::Unary(_) => panic!("can't add binary change types to unary change"), + Change::Binary(ref mut b) => b.add(type_), + } + } + + fn to_category(&self) -> ChangeCategory { + match *self { + Change::Unary(ref u) => u.to_category(), + Change::Binary(ref b) => b.to_category(), + } + } +} + +/// An identifier used to unambiguously refer to items we record changes for. +#[derive(PartialEq, Eq, Hash)] +pub enum ChangeKey { + /// An item referred to using the old definition's id. + /// This includes items that have been removed *or* changed. + OldKey(DefId), + /// An item referred to using the new definition's id. + /// This includes items that have been added *only* + NewKey(DefId), +} + /// The total set of changes recorded for two crate versions. #[derive(Default)] pub struct ChangeSet { /// The currently recorded changes. - changes: BTreeSet, + changes: HashMap, /// The most severe change category already recorded. max: ChangeCategory, } impl ChangeSet { - /// Add a change to the set and record it's category for later use. - pub fn add_change(&mut self, change: Change) { - let cat: ChangeCategory = From::from(&change); + pub fn new_addition(&mut self, item: Export) { + self.new_change(Change::new_addition(item), ChangeKey::NewKey(item.def.def_id())); + } + + pub fn new_removal(&mut self, item: Export) { + self.new_change(Change::new_removal(item), ChangeKey::NewKey(item.def.def_id())); + } + + fn new_change(&mut self, change: Change, key: ChangeKey) { + let cat = change.to_category(); if cat > self.max { - self.max = cat; + self.max = cat.clone(); } - self.changes.insert(change); + self.changes.insert(key, change); + } + + pub fn new_binary(&mut self, type_: BinaryChangeType, old: Export, new: Export) { + let key = ChangeKey::OldKey(old.def.def_id()); + let cat = type_.to_category(); + + if cat > self.max { + self.max = cat.clone(); + } + + let entry = self.changes + .entry(key) + .or_insert_with(|| Change::new_binary(old, new)); + + entry.add(type_); + } + + pub fn item_breaking(&self, key: DefId) -> bool { + // we only care about items that were present before, since only those can get breaking + // changes (additions don't count). + self.changes + .get(&ChangeKey::OldKey(key)) + .map(|changes| changes.to_category() == Breaking) + .unwrap_or(false) } /// Format the contents of a change set for user output. /// /// TODO: replace this with something more sophisticated. - pub fn output(&self, session: &Session, version: &str) { + pub fn output(&self, /*session*/ _: &Session, version: &str) { if let Ok(mut new_version) = Version::parse(version) { match self.max { Patch => new_version.increment_patch(), @@ -322,15 +370,18 @@ impl ChangeSet { println!("max change: {} (could not parse) -> {:?}", version, self.max); } - for change in &self.changes { + for change in self.changes.values() { match *change { - Change::Unary(ref c) => { - println!(" {}: {}", c.type_(), c.ident().name.as_str()); - session.span_warn(*c.span(), "change"); + Change::Unary(ref u) => { + println!(" {}: {}", u.type_(), u.ident().name.as_str()); + // session.span_warn(*c.span(), "change"); }, - Change::Binary(ref c) => { - println!(" {:?}: {}", c.type_(), c.ident().name.as_str()); - session.span_warn(*c.new_span(), "change"); + Change::Binary(ref b) => { + println!(" {} -", b.ident().name.as_str()); + for change in &b.changes { + println!(" {:?}", change); + // session.span_warn(*c.new_span(), "change"); + } }, } // span_note!(session, change.span(), "S0001"); @@ -343,6 +394,7 @@ pub mod tests { use quickcheck::*; pub use super::*; + use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::hir::def::Def; use std::cmp::{max, min}; @@ -411,7 +463,10 @@ pub mod tests { }; let export = Export { ident: ident, - def: Def::Err, + def: Def::Mod(DefId { + krate: LOCAL_CRATE, + index: CRATE_DEF_INDEX, + }), span: s, }; @@ -435,16 +490,25 @@ pub mod tests { }; let export1 = Export { ident: ident1, - def: Def::Err, + def: Def::Mod(DefId { + krate: LOCAL_CRATE, + index: CRATE_DEF_INDEX, + }), span: s1, }; let export2 = Export { ident: ident2, - def: Def::Err, + def: Def::Mod(DefId { + krate: LOCAL_CRATE, + index: CRATE_DEF_INDEX, + }), span: s2, }; - BinaryChange::new(t, export1, export2) + let mut change = BinaryChange::new(export1, export2); + change.add(t); + + change } quickcheck! { @@ -502,8 +566,9 @@ pub mod tests { let max = changes.iter().map(|c| From::from(&c.0)).max().unwrap_or(Patch); for &(ref change, ref span) in changes.iter() { - set.add_change( - Change::Unary(build_unary_change(change.clone(), span.clone().inner()))); + let change = build_unary_change(change.clone(), span.clone().inner()); + let key = ChangeKey::NewKey(change.export().def.def_id()); + set.new_change(Change::Unary(change), key); } set.max == max @@ -513,12 +578,15 @@ pub mod tests { fn max_bchange(changes: Vec) -> bool { let mut set = ChangeSet::default(); - let max = changes.iter().map(|c| From::from(&c.0)).max().unwrap_or(Patch); + let max = changes.iter().map(|c| c.0.to_category()).max().unwrap_or(Patch); for &(ref change, ref span1, ref span2) in changes.iter() { - set.add_change( - Change::Binary(build_binary_change( - change.clone(), span1.clone().inner(), span2.clone().inner()))); + let change = + build_binary_change(change.clone(), + span1.clone().inner(), + span2.clone().inner()); + let key = ChangeKey::OldKey(change.old.def.def_id()); + set.new_change(Change::Binary(change), key); } set.max == max @@ -545,8 +613,8 @@ pub mod tests { let s2 = c2.1.inner(); if s1 != s2 { - let ch1 = build_binary_change(c1.0, s1, c1.2.inner()); - let ch2 = build_binary_change(c2.0, s2, c2.2.inner()); + let ch1 = build_binary_change(c1.0, c1.2.inner(), s1); + let ch2 = build_binary_change(c2.0, c2.2.inner(), s2); ch1 != ch2 } else { diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 03d5c62751083..36b2650b4e567 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -1,6 +1,6 @@ use semcheck::changes::BinaryChangeType; use semcheck::changes::BinaryChangeType::*; -use semcheck::changes::{Change, ChangeCategory, ChangeSet}; +use semcheck::changes::ChangeSet; use rustc::hir::def::Def::*; use rustc::hir::def::Export; @@ -14,16 +14,27 @@ use std::collections::{HashMap, HashSet, VecDeque}; #[derive(Default)] struct IdMapping { - pub mapping: HashMap, + toplevel_mapping: HashMap, + mapping: HashMap, } impl IdMapping { - pub fn add(&mut self, old: Export, new: Export) { - self.mapping.insert(old.def.def_id(), (new.def.def_id(), old, new)); + pub fn add_export(&mut self, old: Export, new: Export) -> bool { + self.toplevel_mapping + .insert(old.def.def_id(), (new.def.def_id(), old, new)) + .is_some() + } + + pub fn add_item(&mut self, old: DefId, new: DefId) { + self.mapping.insert(old, new); } pub fn get_new_id(&self, old: DefId) -> DefId { - self.mapping[&old].0 + if let Some(new) = self.toplevel_mapping.get(&old) { + new.0 + } else { + self.mapping[&old] + } } } @@ -67,80 +78,92 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { } } (Some(o), Some(n)) => { - id_mapping.add(o, n); + if !id_mapping.add_export(o, n) { + diff_item_structures(&mut changes, &id_mapping, tcx, o, n); + } } (Some(old), None) => { - changes.add_change(Change::new_removal(old)); + changes.new_removal(old); } (None, Some(new)) => { - changes.add_change(Change::new_addition(new)); + changes.new_addition(new); } (None, None) => unreachable!(), } } } - for &(_, old, new) in id_mapping.mapping.values() { + for &(_, old, new) in id_mapping.toplevel_mapping.values() { diff_items(&mut changes, &id_mapping, tcx, old, new); } changes } -/// Given two items, dispatch to further checks. +/// Given two items, perform *structural* checks. +/// +/// This establishes the needed correspondence relationship between non-toplevel items. +/// For instance, struct fields, enum variants etc. are matched up against each other here. /// /// If the two items can't be meaningfully compared because they are of different kinds, /// we return that difference directly. +fn diff_item_structures(changes: &mut ChangeSet, + _: &IdMapping, + tcx: TyCtxt, + old: Export, + new: Export) { + let mut generics_changes = diff_generics(tcx, old.def.def_id(), new.def.def_id()); + for change_type in generics_changes.drain(..) { + changes.new_binary(change_type, old, new); + } +} + +/// Given two items, perform *non-structural* checks. +/// +/// This encompasses all checks for type and requires that the structural checks have already +/// been performed. fn diff_items(changes: &mut ChangeSet, id_mapping: &IdMapping, tcx: TyCtxt, old: Export, new: Export) { - let mut check_type = true; - let mut generics_changes = diff_generics(tcx, old.def.def_id(), new.def.def_id()); - for change_type in generics_changes.drain(..) { - if ChangeCategory::from(&change_type) == ChangeCategory::Breaking { - check_type = false; - } - - changes.add_change(Change::new_binary(change_type, old, new)); - } - - let change = match (old.def, new.def) { - (Struct(_), Struct(_)) => None, // Some(Change::new_binary(Unknown, old, new)), - (Union(_), Union(_)) => Some(Change::new_binary(Unknown, old, new)), + let mut structural_changes = match (old.def, new.def) { + (Struct(o), Struct(n)) => diff_structs(tcx, o, n), + (TyAlias(o), TyAlias(n)) => diff_tyaliases(tcx, o, n), + /*(Union(_), Union(_)) => Some(Change::new_binary(Unknown, old, new)), (Enum(_), Enum(_)) => Some(Change::new_binary(Unknown, old, new)), (Trait(_), Trait(_)) => Some(Change::new_binary(Unknown, old, new)), - (TyAlias(o), TyAlias(n)) => - diff_tyaliases(tcx, o, n).map(|t| Change::new_binary(t, old, new)), (Fn(_), Fn(_)) => Some(Change::new_binary(Unknown, old, new)), (Const(_), Const(_)) => Some(Change::new_binary(Unknown, old, new)), (Static(_, _), Static(_, _)) => Some(Change::new_binary(Unknown, old, new)), (Method(_), Method(_)) => Some(Change::new_binary(Unknown, old, new)), - (Macro(_, _), Macro(_, _)) => Some(Change::new_binary(Unknown, old, new)), + (Macro(_, _), Macro(_, _)) => Some(Change::new_binary(Unknown, old, new)),*/ _ => { - check_type = false; - Some(Change::new_binary(KindDifference, old, new)) + vec![KindDifference] }, }; - if let Some(c) = change { - changes.add_change(c); + for change_type in structural_changes.drain(..) { + changes.new_binary(change_type, old, new); } - if check_type { - let _ = diff_type(id_mapping, tcx, old.def.def_id(), new.def.def_id()); + if !changes.item_breaking(old.def.def_id()) { + let mut type_changes = diff_types(id_mapping, tcx, old.def.def_id(), new.def.def_id()); + + for change_type in type_changes.drain(..) { + changes.new_binary(change_type, old, new); + } } } -fn diff_type(id_mapping: &IdMapping, tcx: TyCtxt, old: DefId, new: DefId) +fn diff_types(id_mapping: &IdMapping, tcx: TyCtxt, old: DefId, new: DefId) -> Vec { use rustc::ty::AdtDef; use rustc::ty::TypeVariants::*; - let res = Vec::new(); + let mut res = Vec::new(); let new_ty = tcx.type_of(new); let old_ty = tcx.type_of(old).subst(tcx, Substs::identity_for_item(tcx, new)); @@ -162,13 +185,14 @@ fn diff_type(id_mapping: &IdMapping, tcx: TyCtxt, old: DefId, new: DefId) } }}); - println!("old_ty: {:?}", old_ty_cmp); - println!("new_ty: {:?}", new_ty); + // println!("old_ty: {:?}", old_ty_cmp); + // println!("new_ty: {:?}", new_ty); if let Result::Err(err) = tcx.global_tcx().infer_ctxt() .enter(|infcx| infcx.can_eq(tcx.param_env(new), old_ty_cmp, new_ty)) { - println!("diff: {}", err); + // println!("diff: {}", err); + res.push(FieldTypeChanged(format!("{}", err))); // FIXME: this is obv a terrible hack } res @@ -223,10 +247,14 @@ fn diff_generics(tcx: TyCtxt, old: DefId, new: DefId) -> Vec { /// Given two type aliases' definitions, compare their types. fn diff_tyaliases(/*tcx*/ _: TyCtxt, /*old*/ _: DefId, /*new*/ _: DefId) - -> Option { + -> Vec { // let cstore = &tcx.sess.cstore; /* println!("matching TyAlias'es found"); println!("old: {:?}", tcx.type_of(old)); println!("new: {:?}", tcx.type_of(new));*/ - None + Vec::new() +} + +fn diff_structs(/*tcx*/ _: TyCtxt, /*old*/ _: DefId, /*new*/ _: DefId) -> Vec { + Vec::new() } diff --git a/tests/examples/addition.out b/tests/examples/addition.out index 9d46339122fdf..0b25ee2e4ed80 100644 --- a/tests/examples/addition.out +++ b/tests/examples/addition.out @@ -1,7 +1,3 @@ version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 - Addition: Abc -warning: change - Addition: a -warning: change - + Addition: Abc diff --git a/tests/examples/addition_path.out b/tests/examples/addition_path.out index 0e1ef2456d901..311093751a421 100644 --- a/tests/examples/addition_path.out +++ b/tests/examples/addition_path.out @@ -1,10 +1,4 @@ version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 - Addition: b -warning: change - Addition: c -warning: change - Addition: Abc -warning: change - + Addition: b diff --git a/tests/examples/kind_change.out b/tests/examples/kind_change.out index 8092955019199..9d9b0be888833 100644 --- a/tests/examples/kind_change.out +++ b/tests/examples/kind_change.out @@ -1,4 +1,3 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 - KindDifference: Abc -warning: change - + Abc - + KindDifference diff --git a/tests/examples/pathologic_paths.out b/tests/examples/pathologic_paths.out index 450febc052727..f4082427c6a09 100644 --- a/tests/examples/pathologic_paths.out +++ b/tests/examples/pathologic_paths.out @@ -1,7 +1,3 @@ version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 Addition: a -warning: change - Addition: b -warning: change - diff --git a/tests/examples/removal.out b/tests/examples/removal.out index 7affcc6fa137f..cfbf823a874a0 100644 --- a/tests/examples/removal.out +++ b/tests/examples/removal.out @@ -1,7 +1,3 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 Removal: Abc -warning: change - Removal: a -warning: change - diff --git a/tests/examples/removal_path.out b/tests/examples/removal_path.out index cdcd01cef73f1..9c7569af42e8f 100644 --- a/tests/examples/removal_path.out +++ b/tests/examples/removal_path.out @@ -1,10 +1,4 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 + Removal: Abc Removal: b -warning: change - Removal: c -warning: change - - Removal: Abc -warning: change - diff --git a/tests/examples/struct.out b/tests/examples/struct.out index ddfe97f66815a..03f10547d7cc9 100644 --- a/tests/examples/struct.out +++ b/tests/examples/struct.out @@ -1,10 +1,3 @@ -old_ty: oldandnew::new::Def -new_ty: oldandnew::new::Def -old_ty: oldandnew::new::Efg -new_ty: oldandnew::new::Efg -old_ty: oldandnew::new::Abc -new_ty: oldandnew::new::Abc version bump: 1.0.0 -> (NonBreaking) -> 1.1.0 - TypeParameterAdded { defaulted: true }: Def -warning: change - + Def - + TypeParameterAdded { defaulted: true } diff --git a/tests/examples/ty_alias.out b/tests/examples/ty_alias.out index 2604f3bcfbb4d..3f4f97a7d97eb 100644 --- a/tests/examples/ty_alias.out +++ b/tests/examples/ty_alias.out @@ -1,25 +1,16 @@ -old_ty: u8 -new_ty: u16 -diff: expected u8, found u16 -old_ty: &'a T -new_ty: (&'a T, U) -diff: expected reference, found tuple version bump: 1.0.0 -> (Breaking) -> 2.0.0 - RegionParameterAdded: B -warning: change - - RegionParameterRemoved: C -warning: change - - TypeParameterAdded { defaulted: true }: D -warning: change - - TypeParameterAdded { defaulted: false }: E -warning: change - - TypeParameterRemoved { defaulted: true }: F -warning: change - - TypeParameterRemoved { defaulted: false }: G -warning: change - + G - + TypeParameterRemoved { defaulted: false } + C - + RegionParameterRemoved + A - + FieldTypeChanged("expected u8, found u16") + B - + RegionParameterAdded + E - + TypeParameterAdded { defaulted: false } + D - + TypeParameterAdded { defaulted: true } + FieldTypeChanged("expected reference, found tuple") + F - + TypeParameterRemoved { defaulted: true } From a35786f683b9b9281df1df48eacf8919bfa1c724 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 17 Jun 2017 19:44:08 +0200 Subject: [PATCH 064/553] Updated docs. --- src/semcheck/changes.rs | 32 ++++++++++++++++++++++++-------- src/semcheck/traverse.rs | 18 ++++++++++++++++-- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 1a4e6eb5fc680..dfedadf4582ae 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -43,7 +43,7 @@ impl<'a> Default for ChangeCategory { /// It is important to note that the `Eq` and `Ord` instances are constucted to only /// regard the span of the associated item export. This allows us to sort them by appearance /// in the source, but possibly could create conflict later on. -/// TODO: regard the origin of the span as well. +// TODO: regard the origin of the span as well. pub enum UnaryChange { /// An item has been added. Addition(Export), @@ -52,6 +52,7 @@ pub enum UnaryChange { } impl UnaryChange { + /// Get the change's category. pub fn to_category(&self) -> ChangeCategory { match *self { UnaryChange::Addition(_) => TechnicallyBreaking, @@ -106,7 +107,7 @@ impl Ord for UnaryChange { } /// The types of changes we identify between items present in both crate versions. -/// TODO: this needs a lot of refinement still +// TODO: this needs a lot of refinement still #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum BinaryChangeType { /// An item has changed it's kind. @@ -152,7 +153,7 @@ pub enum BinaryChangeType { pub use self::BinaryChangeType::*; impl BinaryChangeType { - // TODO: this will need a lot of changes + // TODO: this will need a lot of changes (it's *very* conservative rn) pub fn to_category(&self) -> ChangeCategory { match *self { KindDifference | @@ -184,6 +185,7 @@ impl BinaryChangeType { /// It is important to note that the `Eq` and `Ord` instances are constucted to only /// regard the *new* span of the associated item export. This allows us to sort them /// by appearance in the *new* source, but possibly could create conflict later on. +// TODO: we should an invariant that the two exports present are *always* tied together. pub struct BinaryChange { /// The type of the change affecting the item. changes: BTreeSet, @@ -206,6 +208,7 @@ impl BinaryChange { } } + /// Add another change type to the change record. fn add(&mut self, type_: BinaryChangeType) { let cat = type_.to_category(); @@ -216,6 +219,7 @@ impl BinaryChange { self.changes.insert(type_); } + /// Get the change's category. fn to_category(&self) -> ChangeCategory { self.max.clone() } @@ -264,18 +268,22 @@ pub enum Change { } impl Change { + /// Construct a new addition-change for the given export. fn new_addition(item: Export) -> Change { Change::Unary(UnaryChange::Addition(item)) } + /// Construct a new removal-change for the given export. fn new_removal(item: Export) -> Change { Change::Unary(UnaryChange::Removal(item)) } + /// Construct a new binary change for the given exports. fn new_binary(old: Export, new: Export) -> Change { Change::Binary(BinaryChange::new(old, new)) } + /// Add a change type to a given binary change. fn add(&mut self, type_: BinaryChangeType) { match *self { Change::Unary(_) => panic!("can't add binary change types to unary change"), @@ -283,6 +291,7 @@ impl Change { } } + /// Get the change's category. fn to_category(&self) -> ChangeCategory { match *self { Change::Unary(ref u) => u.to_category(), @@ -312,15 +321,18 @@ pub struct ChangeSet { } impl ChangeSet { + /// Add a new addition-change for the given export. pub fn new_addition(&mut self, item: Export) { - self.new_change(Change::new_addition(item), ChangeKey::NewKey(item.def.def_id())); + self.new_unary_change(Change::new_addition(item), ChangeKey::NewKey(item.def.def_id())); } + /// Add a new removal-change for the given export. pub fn new_removal(&mut self, item: Export) { - self.new_change(Change::new_removal(item), ChangeKey::NewKey(item.def.def_id())); + self.new_unary_change(Change::new_removal(item), ChangeKey::NewKey(item.def.def_id())); } - fn new_change(&mut self, change: Change, key: ChangeKey) { + /// Add a new (unary) change for the given key. + fn new_unary_change(&mut self, change: Change, key: ChangeKey) { let cat = change.to_category(); if cat > self.max { @@ -330,6 +342,7 @@ impl ChangeSet { self.changes.insert(key, change); } + /// Add a new binary change for the given exports. pub fn new_binary(&mut self, type_: BinaryChangeType, old: Export, new: Export) { let key = ChangeKey::OldKey(old.def.def_id()); let cat = type_.to_category(); @@ -345,6 +358,9 @@ impl ChangeSet { entry.add(type_); } + /// 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, key: DefId) -> bool { // we only care about items that were present before, since only those can get breaking // changes (additions don't count). @@ -568,7 +584,7 @@ pub mod tests { for &(ref change, ref span) in changes.iter() { let change = build_unary_change(change.clone(), span.clone().inner()); let key = ChangeKey::NewKey(change.export().def.def_id()); - set.new_change(Change::Unary(change), key); + set.new_unary_change(Change::Unary(change), key); } set.max == max @@ -586,7 +602,7 @@ pub mod tests { span1.clone().inner(), span2.clone().inner()); let key = ChangeKey::OldKey(change.old.def.def_id()); - set.new_change(Change::Binary(change), key); + set.new_unary_change(Change::Binary(change), key); } set.max == max diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 36b2650b4e567..2382ca2cc53f4 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -12,23 +12,32 @@ use rustc::ty::Visibility::Public; use std::collections::{HashMap, HashSet, VecDeque}; +/// A mapping from old to new `DefId`s, as well as exports. +/// +/// Exports 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. #[derive(Default)] struct IdMapping { + /// Toplevel items' old `DefId` mapped to new `DefId`, as well as old and new exports. toplevel_mapping: HashMap, + /// Other item's old `DefId` mapped to new `DefId`. mapping: HashMap, } impl IdMapping { + /// Register two exports representing the same item across versions. pub fn add_export(&mut self, old: Export, new: Export) -> bool { self.toplevel_mapping .insert(old.def.def_id(), (new.def.def_id(), old, new)) .is_some() } + /// Add any other item pair's old and new `DefId`s. pub fn add_item(&mut self, old: DefId, new: DefId) { self.mapping.insert(old, new); } + /// Get the new `DefId` associated with the given old one. pub fn get_new_id(&self, old: DefId) -> DefId { if let Some(new) = self.toplevel_mapping.get(&old) { new.0 @@ -42,6 +51,8 @@ impl IdMapping { /// /// Match up pairs of modules from the two crate versions and compare for changes. /// Matching children get processed in the same fashion. +/// +// TODO: describe the passes we do. pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { let cstore = &tcx.sess.cstore; let mut changes = ChangeSet::default(); @@ -139,7 +150,7 @@ fn diff_items(changes: &mut ChangeSet, (Method(_), Method(_)) => Some(Change::new_binary(Unknown, old, new)), (Macro(_, _), Macro(_, _)) => Some(Change::new_binary(Unknown, old, new)),*/ _ => { - vec![KindDifference] + vec![KindDifference] // TODO: move this to `diff_item_structures` as per docs }, }; @@ -157,6 +168,7 @@ fn diff_items(changes: &mut ChangeSet, } +/// Given two items, compare their types for equality. fn diff_types(id_mapping: &IdMapping, tcx: TyCtxt, old: DefId, new: DefId) -> Vec { @@ -198,6 +210,7 @@ fn diff_types(id_mapping: &IdMapping, tcx: TyCtxt, old: DefId, new: DefId) res } +/// Given two items, compare their type and region parameter sets. fn diff_generics(tcx: TyCtxt, old: DefId, new: DefId) -> Vec { use std::cmp::max; @@ -245,7 +258,7 @@ fn diff_generics(tcx: TyCtxt, old: DefId, new: DefId) -> Vec { ret } -/// Given two type aliases' definitions, compare their types. +/// Given two type aliases' definitions, compare them. fn diff_tyaliases(/*tcx*/ _: TyCtxt, /*old*/ _: DefId, /*new*/ _: DefId) -> Vec { // let cstore = &tcx.sess.cstore; @@ -255,6 +268,7 @@ fn diff_tyaliases(/*tcx*/ _: TyCtxt, /*old*/ _: DefId, /*new*/ _: DefId) Vec::new() } +/// Given two structs' definitions, compare them. fn diff_structs(/*tcx*/ _: TyCtxt, /*old*/ _: DefId, /*new*/ _: DefId) -> Vec { Vec::new() } From 87909a09e33ed4b8862a6a4ecffd753d0cfd9dc3 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 18 Jun 2017 20:21:31 +0200 Subject: [PATCH 065/553] Fixed #14 and implemented very first steps for struct traversal. --- src/semcheck/traverse.rs | 116 ++++++++++++++++++++----------- tests/examples/addition.out | 1 + tests/examples/addition_path.out | 5 +- tests/examples/kind_change.out | 1 + tests/examples/removal.out | 1 + tests/examples/removal_path.out | 3 +- tests/examples/struct.out | 6 ++ tests/examples/ty_alias.out | 16 ++--- 8 files changed, 98 insertions(+), 51 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 2382ca2cc53f4..b170f1701580b 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -2,6 +2,7 @@ use semcheck::changes::BinaryChangeType; use semcheck::changes::BinaryChangeType::*; use semcheck::changes::ChangeSet; +use rustc::hir::def::Def; use rustc::hir::def::Def::*; use rustc::hir::def::Export; use rustc::hir::def_id::DefId; @@ -47,6 +48,43 @@ impl IdMapping { } } +#[derive(PartialEq, Eq, Hash)] +enum Namespace { + Type, + Value, + Macro, + Err, +} + +fn get_namespace(def: &Def) -> Namespace { + match *def { + Mod(_) | + Struct(_) | + Union(_) | + Enum(_) | + Variant(_) | + Trait(_) | + TyAlias(_) | + AssociatedTy(_) | + PrimTy(_) | + TyParam(_) | + SelfTy(_, _) => Namespace::Type, + Fn(_) | + Const(_) | + Static(_, _) | + StructCtor(_, _) | + VariantCtor(_, _) | + Method(_) | + AssociatedConst(_) | + Local(_) | + Upvar(_, _, _) | + Label(_) => Namespace::Value, + Macro(_, _) => Namespace::Macro, + GlobalAsm(_) | + Err => Namespace::Err, + } +} + /// Traverse the two root modules in an interleaved manner. /// /// Match up pairs of modules from the two crate versions and compare for changes. @@ -67,18 +105,19 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { let mut c_old = cstore.item_children(old_did, tcx.sess); let mut c_new = cstore.item_children(new_did, tcx.sess); + // TODO: refactor this to avoid storing tons of `Namespace` values. for child in c_old .drain(..) .filter(|c| cstore.visibility(c.def.def_id()) == Public) { - let child_name = String::from(&*child.ident.name.as_str()); - children.entry(child_name).or_insert((None, None)).0 = Some(child); + let key = (get_namespace(&child.def), child.ident.name); + children.entry(key).or_insert((None, None)).0 = Some(child); } for child in c_new .drain(..) .filter(|c| cstore.visibility(c.def.def_id()) == Public) { - let child_name = String::from(&*child.ident.name.as_str()); - children.entry(child_name).or_insert((None, None)).1 = Some(child); + let key = (get_namespace(&child.def), child.ident.name); + children.entry(key).or_insert((None, None)).1 = Some(child); } for (_, items) in children.drain() { @@ -123,10 +162,42 @@ fn diff_item_structures(changes: &mut ChangeSet, tcx: TyCtxt, old: Export, new: Export) { - let mut generics_changes = diff_generics(tcx, old.def.def_id(), new.def.def_id()); + let old_def_id = old.def.def_id(); + let new_def_id = new.def.def_id(); + + let mut generics_changes = diff_generics(tcx, old_def_id, new_def_id); for change_type in generics_changes.drain(..) { changes.new_binary(change_type, old, new); } + + // TODO: crude dispatching logic for now (needs totality etc). + match (old.def, new.def) { + (TyAlias(_), TyAlias(_)) => return, + (Struct(_), Struct(_)) | + (Union(_), Union(_)) | + (Enum(_), Enum(_)) | + (Trait(_), Trait(_)) | + (Fn(_), Fn(_)) | + (Const(_), Const(_)) | + (Static(_, _), Static(_, _)) | + (Method(_), Method(_)) | + (Macro(_, _), Macro(_, _)) => {}, + _ => { + // No match - so we don't need to look further. + changes.new_binary(KindDifference, old, new); + return; + }, + } + + let (old_def, new_def) = match (old.def, new.def) { + (Struct(_), Struct(_)) | + (Union(_), Union(_)) | + (Enum(_), Enum(_)) => (tcx.adt_def(old_def_id), tcx.adt_def(new_def_id)), + _ => return, + }; + + println!("old: {:?}", old_def); + println!("new: {:?}", new_def); } /// Given two items, perform *non-structural* checks. @@ -138,26 +209,6 @@ fn diff_items(changes: &mut ChangeSet, tcx: TyCtxt, old: Export, new: Export) { - let mut structural_changes = match (old.def, new.def) { - (Struct(o), Struct(n)) => diff_structs(tcx, o, n), - (TyAlias(o), TyAlias(n)) => diff_tyaliases(tcx, o, n), - /*(Union(_), Union(_)) => Some(Change::new_binary(Unknown, old, new)), - (Enum(_), Enum(_)) => Some(Change::new_binary(Unknown, old, new)), - (Trait(_), Trait(_)) => Some(Change::new_binary(Unknown, old, new)), - (Fn(_), Fn(_)) => Some(Change::new_binary(Unknown, old, new)), - (Const(_), Const(_)) => Some(Change::new_binary(Unknown, old, new)), - (Static(_, _), Static(_, _)) => Some(Change::new_binary(Unknown, old, new)), - (Method(_), Method(_)) => Some(Change::new_binary(Unknown, old, new)), - (Macro(_, _), Macro(_, _)) => Some(Change::new_binary(Unknown, old, new)),*/ - _ => { - vec![KindDifference] // TODO: move this to `diff_item_structures` as per docs - }, - }; - - for change_type in structural_changes.drain(..) { - changes.new_binary(change_type, old, new); - } - if !changes.item_breaking(old.def.def_id()) { let mut type_changes = diff_types(id_mapping, tcx, old.def.def_id(), new.def.def_id()); @@ -257,18 +308,3 @@ fn diff_generics(tcx: TyCtxt, old: DefId, new: DefId) -> Vec { ret } - -/// Given two type aliases' definitions, compare them. -fn diff_tyaliases(/*tcx*/ _: TyCtxt, /*old*/ _: DefId, /*new*/ _: DefId) - -> Vec { - // let cstore = &tcx.sess.cstore; - /* println!("matching TyAlias'es found"); - println!("old: {:?}", tcx.type_of(old)); - println!("new: {:?}", tcx.type_of(new));*/ - Vec::new() -} - -/// Given two structs' definitions, compare them. -fn diff_structs(/*tcx*/ _: TyCtxt, /*old*/ _: DefId, /*new*/ _: DefId) -> Vec { - Vec::new() -} diff --git a/tests/examples/addition.out b/tests/examples/addition.out index 0b25ee2e4ed80..3d3e7deba2e54 100644 --- a/tests/examples/addition.out +++ b/tests/examples/addition.out @@ -1,3 +1,4 @@ version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 Addition: a Addition: Abc + Addition: Abc diff --git a/tests/examples/addition_path.out b/tests/examples/addition_path.out index 311093751a421..2b698b314ad74 100644 --- a/tests/examples/addition_path.out +++ b/tests/examples/addition_path.out @@ -1,4 +1,5 @@ version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 - Addition: c - Addition: Abc Addition: b + Addition: Abc + Addition: Abc + Addition: c diff --git a/tests/examples/kind_change.out b/tests/examples/kind_change.out index 9d9b0be888833..535605b40e684 100644 --- a/tests/examples/kind_change.out +++ b/tests/examples/kind_change.out @@ -1,3 +1,4 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 + Removal: Abc Abc - KindDifference diff --git a/tests/examples/removal.out b/tests/examples/removal.out index cfbf823a874a0..faa76161e8736 100644 --- a/tests/examples/removal.out +++ b/tests/examples/removal.out @@ -1,3 +1,4 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 Removal: Abc Removal: a + Removal: Abc diff --git a/tests/examples/removal_path.out b/tests/examples/removal_path.out index 9c7569af42e8f..31036cea7c0d4 100644 --- a/tests/examples/removal_path.out +++ b/tests/examples/removal_path.out @@ -1,4 +1,5 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 - Removal: Abc Removal: b Removal: c + Removal: Abc + Removal: Abc diff --git a/tests/examples/struct.out b/tests/examples/struct.out index 03f10547d7cc9..09088619af12b 100644 --- a/tests/examples/struct.out +++ b/tests/examples/struct.out @@ -1,3 +1,9 @@ +old: oldandnew::old::Abc +new: oldandnew::new::Abc +old: oldandnew::old::Def +new: oldandnew::new::Def +old: oldandnew::old::Efg +new: oldandnew::new::Efg version bump: 1.0.0 -> (NonBreaking) -> 1.1.0 Def - TypeParameterAdded { defaulted: true } diff --git a/tests/examples/ty_alias.out b/tests/examples/ty_alias.out index 3f4f97a7d97eb..fcd5c6ed1854e 100644 --- a/tests/examples/ty_alias.out +++ b/tests/examples/ty_alias.out @@ -1,16 +1,16 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 - G - - TypeParameterRemoved { defaulted: false } - C - - RegionParameterRemoved + F - + TypeParameterRemoved { defaulted: true } A - FieldTypeChanged("expected u8, found u16") - B - - RegionParameterAdded E - TypeParameterAdded { defaulted: false } + C - + RegionParameterRemoved D - TypeParameterAdded { defaulted: true } FieldTypeChanged("expected reference, found tuple") - F - - TypeParameterRemoved { defaulted: true } + B - + RegionParameterAdded + G - + TypeParameterRemoved { defaulted: false } From 25e4b304b4db1ae0a969378a83d7cb81e5fde011 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 19 Jun 2017 12:32:30 +0200 Subject: [PATCH 066/553] First version of span-based output. It still needs a lot of polishing, but we get spans and messages constructed by the compiler's machinery. A significant improvement. --- src/semcheck/changes.rs | 50 +++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index dfedadf4582ae..918aa0dba0410 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -84,6 +84,16 @@ impl UnaryChange { UnaryChange::Removal(_) => "Removal", } } + + fn report(&self, session: &Session) { + let msg = format!("{} of at least one path to `{}` ({:?})", + self.type_(), + self.ident(), + self.to_category()); + let mut builder = session.struct_span_warn(self.export().span, &msg); + + builder.emit(); + } } impl PartialEq for UnaryChange { @@ -233,6 +243,23 @@ impl BinaryChange { fn ident(&self) -> &Ident { &self.old.ident } + + fn report(&self, session: &Session) { + let msg = format!("{:?} changes in `{}`", self.max, self.ident()); + let mut builder = session.struct_span_warn(self.new.span, &msg); + + for change in &self.changes { + let cat = change.to_category(); + let sub_msg = format!("{:?} ({:?})", cat, change); + if cat == Breaking { + builder.warn(&sub_msg); + } else { + builder.note(&sub_msg); + } + } + + builder.emit(); + } } impl PartialEq for BinaryChange { @@ -298,6 +325,13 @@ impl Change { Change::Binary(ref b) => b.to_category(), } } + + fn report(&self, session: &Session) { + match *self { + Change::Unary(ref u) => u.report(session), + Change::Binary(ref b) => b.report(session), + } + } } /// An identifier used to unambiguously refer to items we record changes for. @@ -373,7 +407,7 @@ impl ChangeSet { /// Format the contents of a change set for user output. /// /// TODO: replace this with something more sophisticated. - pub fn output(&self, /*session*/ _: &Session, version: &str) { + pub fn output(&self, session: &Session, version: &str) { if let Ok(mut new_version) = Version::parse(version) { match self.max { Patch => new_version.increment_patch(), @@ -387,19 +421,7 @@ impl ChangeSet { } for change in self.changes.values() { - match *change { - Change::Unary(ref u) => { - println!(" {}: {}", u.type_(), u.ident().name.as_str()); - // session.span_warn(*c.span(), "change"); - }, - Change::Binary(ref b) => { - println!(" {} -", b.ident().name.as_str()); - for change in &b.changes { - println!(" {:?}", change); - // session.span_warn(*c.new_span(), "change"); - } - }, - } + change.report(session); // span_note!(session, change.span(), "S0001"); } } From 718c761ab23fa42add5535af8e8abeed863f2f0d Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 19 Jun 2017 12:33:16 +0200 Subject: [PATCH 067/553] Very basic ADT traversal. No logic is so far using the traversal, but the basic structure is present now. --- src/semcheck/traverse.rs | 52 ++++++++++++++++++++- tests/examples/addition.out | 21 +++++++-- tests/examples/addition_path.out | 30 ++++++++++-- tests/examples/kind_change.out | 19 ++++++-- tests/examples/pathologic_paths.out | 14 +++++- tests/examples/removal.out | 21 +++++++-- tests/examples/removal_path.out | 30 ++++++++++-- tests/examples/struct.out | 24 ++++++---- tests/examples/ty_alias.out | 72 +++++++++++++++++++++++------ 9 files changed, 239 insertions(+), 44 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index b170f1701580b..52e9dfed90bf3 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -196,8 +196,56 @@ fn diff_item_structures(changes: &mut ChangeSet, _ => return, }; - println!("old: {:?}", old_def); - println!("new: {:?}", new_def); + let mut variants = HashMap::new(); + let mut fields = HashMap::new(); + + for variant in &old_def.variants { + variants.entry(variant.name).or_insert((None, None)).0 = Some(variant); + } + + for variant in &new_def.variants { + variants.entry(variant.name).or_insert((None, None)).1 = Some(variant); + } + + for (_, items) in variants.drain() { + match items { + (Some(old), Some(new)) => { + for field in &old.fields { + fields.entry(field.name).or_insert((None, None)).0 = Some(field); + } + + for field in &new.fields { + fields.entry(field.name).or_insert((None, None)).1 = Some(field); + } + + for (_, items2) in fields.drain() { + match items2 { + (Some(o), Some(n)) => { + println!("matching fields"); + }, + (Some(o), None) => { + println!("removed field"); + }, + (None, Some(n)) => { + println!("added field"); + }, + (None, None) => unreachable!(), + } + } + + println!("matching variants"); + }, + (Some(old), None) => { + println!("removed variant"); + // TODO: a new variant has been removed from the enum (apparently) + }, + (None, Some(new)) => { + println!("added variant"); + // TODO: a new variant has been added to the enum (apparently) + }, + (None, None) => unreachable!(), + } + } } /// Given two items, perform *non-structural* checks. diff --git a/tests/examples/addition.out b/tests/examples/addition.out index 3d3e7deba2e54..eaeecd3a61b38 100644 --- a/tests/examples/addition.out +++ b/tests/examples/addition.out @@ -1,4 +1,19 @@ version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 - Addition: a - Addition: Abc - Addition: Abc +warning: Addition of at least one path to `Abc` (TechnicallyBreaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/addition.rs:6:5 + | +6 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + +warning: Addition of at least one path to `a` (TechnicallyBreaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/addition.rs:10:5 + | +10 | } + | ^ + +warning: Addition of at least one path to `Abc` (TechnicallyBreaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/addition.rs:6:5 + | +6 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + diff --git a/tests/examples/addition_path.out b/tests/examples/addition_path.out index 2b698b314ad74..7aa189b00b874 100644 --- a/tests/examples/addition_path.out +++ b/tests/examples/addition_path.out @@ -1,5 +1,27 @@ version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 - Addition: b - Addition: Abc - Addition: Abc - Addition: c +warning: Addition of at least one path to `b` (TechnicallyBreaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/addition_path.rs:13:9 + | +13 | / pub use new::a::*; +14 | | } + | |_____^ + +warning: Addition of at least one path to `Abc` (TechnicallyBreaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/addition_path.rs:20:13 + | +20 | pub use self::a::Abc; + | ^^^^^^^^^^^^ + +warning: Addition of at least one path to `Abc` (TechnicallyBreaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/addition_path.rs:20:13 + | +20 | pub use self::a::Abc; + | ^^^^^^^^^^^^ + +warning: Addition of at least one path to `c` (TechnicallyBreaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/addition_path.rs:17:9 + | +17 | / pub use new::a::Abc; +18 | | } + | |_____^ + diff --git a/tests/examples/kind_change.out b/tests/examples/kind_change.out index 535605b40e684..0261b422589fb 100644 --- a/tests/examples/kind_change.out +++ b/tests/examples/kind_change.out @@ -1,4 +1,17 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 - Removal: Abc - Abc - - KindDifference +warning: Breaking changes in `Abc` + --> /home/twk/gsoc/rust-semverver/tests/examples/kind_change.rs:6:5 + | +6 | / pub enum Abc { +7 | | +8 | | } + | |_____^ + | + = warning: Breaking (KindDifference) + +warning: Removal of at least one path to `Abc` (Breaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/kind_change.rs:2:5 + | +2 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + diff --git a/tests/examples/pathologic_paths.out b/tests/examples/pathologic_paths.out index f4082427c6a09..a9e6d1a977fcf 100644 --- a/tests/examples/pathologic_paths.out +++ b/tests/examples/pathologic_paths.out @@ -1,3 +1,13 @@ version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 - Addition: a - Addition: b +warning: Addition of at least one path to `b` (TechnicallyBreaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/pathologic_paths.rs:12:25 + | +12 | pub mod b { pub use super::a::*; } + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: Addition of at least one path to `a` (TechnicallyBreaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/pathologic_paths.rs:11:25 + | +11 | pub mod a { blow!($($rest)*); } + | ^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/examples/removal.out b/tests/examples/removal.out index faa76161e8736..5317823dd4b65 100644 --- a/tests/examples/removal.out +++ b/tests/examples/removal.out @@ -1,4 +1,19 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 - Removal: Abc - Removal: a - Removal: Abc +warning: Removal of at least one path to `a` (Breaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/removal.rs:6:5 + | +6 | } + | ^ + +warning: Removal of at least one path to `Abc` (Breaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/removal.rs:2:5 + | +2 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + +warning: Removal of at least one path to `Abc` (Breaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/removal.rs:2:5 + | +2 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + diff --git a/tests/examples/removal_path.out b/tests/examples/removal_path.out index 31036cea7c0d4..e52b15ebfa5fc 100644 --- a/tests/examples/removal_path.out +++ b/tests/examples/removal_path.out @@ -1,5 +1,27 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 - Removal: b - Removal: c - Removal: Abc - Removal: Abc +warning: Removal of at least one path to `b` (Breaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/removal_path.rs:7:9 + | +7 | / pub use old::a::*; +8 | | } + | |_____^ + +warning: Removal of at least one path to `Abc` (Breaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/removal_path.rs:14:13 + | +14 | pub use self::a::Abc; + | ^^^^^^^^^^^^ + +warning: Removal of at least one path to `c` (Breaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/removal_path.rs:11:9 + | +11 | / pub use old::a::Abc; +12 | | } + | |_____^ + +warning: Removal of at least one path to `Abc` (Breaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/removal_path.rs:14:13 + | +14 | pub use self::a::Abc; + | ^^^^^^^^^^^^ + diff --git a/tests/examples/struct.out b/tests/examples/struct.out index 09088619af12b..f24980af82683 100644 --- a/tests/examples/struct.out +++ b/tests/examples/struct.out @@ -1,9 +1,17 @@ -old: oldandnew::old::Abc -new: oldandnew::new::Abc -old: oldandnew::old::Def -new: oldandnew::new::Def -old: oldandnew::old::Efg -new: oldandnew::new::Efg +matching fields +matching variants +matching fields +matching variants +matching fields +matching variants version bump: 1.0.0 -> (NonBreaking) -> 1.1.0 - Def - - TypeParameterAdded { defaulted: true } +warning: NonBreaking changes in `Def` + --> /home/twk/gsoc/rust-semverver/tests/examples/struct.rs:22:5 + | +22 | / pub struct Def { +23 | | field: A, +24 | | } + | |_____^ + | + = note: NonBreaking (TypeParameterAdded { defaulted: true }) + diff --git a/tests/examples/ty_alias.out b/tests/examples/ty_alias.out index fcd5c6ed1854e..673108e3a42cf 100644 --- a/tests/examples/ty_alias.out +++ b/tests/examples/ty_alias.out @@ -1,16 +1,58 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 - F - - TypeParameterRemoved { defaulted: true } - A - - FieldTypeChanged("expected u8, found u16") - E - - TypeParameterAdded { defaulted: false } - C - - RegionParameterRemoved - D - - TypeParameterAdded { defaulted: true } - FieldTypeChanged("expected reference, found tuple") - B - - RegionParameterAdded - G - - TypeParameterRemoved { defaulted: false } +warning: Breaking changes in `C` + --> /home/twk/gsoc/rust-semverver/tests/examples/ty_alias.rs:14:5 + | +14 | pub type C = T; + | ^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (RegionParameterRemoved) + +warning: Breaking changes in `A` + --> /home/twk/gsoc/rust-semverver/tests/examples/ty_alias.rs:12:5 + | +12 | pub type A = u16; + | ^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (FieldTypeChanged("expected u8, found u16")) + +warning: Breaking changes in `D` + --> /home/twk/gsoc/rust-semverver/tests/examples/ty_alias.rs:15:5 + | +15 | pub type D<'a, T, U=T> = (&'a T, U); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: NonBreaking (TypeParameterAdded { defaulted: true }) + = warning: Breaking (FieldTypeChanged("expected reference, found tuple")) + +warning: Breaking changes in `F` + --> /home/twk/gsoc/rust-semverver/tests/examples/ty_alias.rs:17:5 + | +17 | pub type F<'a> = &'a u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (TypeParameterRemoved { defaulted: true }) + +warning: Breaking changes in `G` + --> /home/twk/gsoc/rust-semverver/tests/examples/ty_alias.rs:18:5 + | +18 | pub type G<'a> = (&'a u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (TypeParameterRemoved { defaulted: false }) + +warning: Breaking changes in `E` + --> /home/twk/gsoc/rust-semverver/tests/examples/ty_alias.rs:16:5 + | +16 | pub type E<'a, T, U> = (&'a T, U); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (TypeParameterAdded { defaulted: false }) + +warning: Breaking changes in `B` + --> /home/twk/gsoc/rust-semverver/tests/examples/ty_alias.rs:13:5 + | +13 | pub type B<'a, 'b : 'a, T> = (&'a T, &'b T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (RegionParameterAdded) + From 7cece1ebdf263f07ecf4f78eb11e95679f64af87 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 19 Jun 2017 13:12:09 +0200 Subject: [PATCH 068/553] Fixed tests. We now have a deterministic ordering of outputs again. However this comes at a price, the ordering gets constructed on the fly using spans associated with all `DefId`s we record, introducing a small performance penality and possibly significant memory overhead. --- src/semcheck/changes.rs | 28 ++++++++++---- tests/examples/addition.out | 6 --- tests/examples/addition_path.out | 16 +++----- tests/examples/kind_change.out | 10 ----- tests/examples/pathologic_paths.out | 12 +++--- tests/examples/removal.out | 14 ++----- tests/examples/removal_path.out | 6 --- tests/examples/struct.out | 10 ----- tests/examples/ty_alias.out | 57 ----------------------------- 9 files changed, 35 insertions(+), 124 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 918aa0dba0410..ea4b1555287c9 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -4,7 +4,7 @@ use rustc::session::Session; use semver::Version; -use std::collections::{BTreeSet, HashMap}; +use std::collections::{BTreeSet, BTreeMap, HashMap}; use std::cmp::Ordering; use syntax::symbol::Ident; @@ -85,6 +85,7 @@ impl UnaryChange { } } + /// Report the change. fn report(&self, session: &Session) { let msg = format!("{} of at least one path to `{}` ({:?})", self.type_(), @@ -195,7 +196,8 @@ impl BinaryChangeType { /// It is important to note that the `Eq` and `Ord` instances are constucted to only /// regard the *new* span of the associated item export. This allows us to sort them /// by appearance in the *new* source, but possibly could create conflict later on. -// TODO: we should an invariant that the two exports present are *always* tied together. +// TODO: we should introduce an invariant that the two exports present are *always* +// tied together. pub struct BinaryChange { /// The type of the change affecting the item. changes: BTreeSet, @@ -244,6 +246,7 @@ impl BinaryChange { &self.old.ident } + /// Report the change. fn report(&self, session: &Session) { let msg = format!("{:?} changes in `{}`", self.max, self.ident()); let mut builder = session.struct_span_warn(self.new.span, &msg); @@ -318,6 +321,14 @@ impl Change { } } + /// Get the change's representative span. + fn span(&self) -> &Span { + match *self { + Change::Unary(ref u) => u.span(), + Change::Binary(ref b) => b.new_span(), + } + } + /// Get the change's category. fn to_category(&self) -> ChangeCategory { match *self { @@ -326,6 +337,7 @@ impl Change { } } + /// Report the change. fn report(&self, session: &Session) { match *self { Change::Unary(ref u) => u.report(session), @@ -335,7 +347,7 @@ impl Change { } /// An identifier used to unambiguously refer to items we record changes for. -#[derive(PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq, Eq, Hash)] pub enum ChangeKey { /// An item referred to using the old definition's id. /// This includes items that have been removed *or* changed. @@ -350,6 +362,8 @@ pub enum ChangeKey { pub struct ChangeSet { /// The currently recorded changes. changes: HashMap, + /// The mapping of spans to changes, for ordering purposes. + spans: BTreeMap, /// The most severe change category already recorded. max: ChangeCategory, } @@ -373,6 +387,7 @@ impl ChangeSet { self.max = cat.clone(); } + self.spans.insert(*change.span(), key.clone()); self.changes.insert(key, change); } @@ -405,8 +420,6 @@ impl ChangeSet { } /// Format the contents of a change set for user output. - /// - /// TODO: replace this with something more sophisticated. pub fn output(&self, session: &Session, version: &str) { if let Ok(mut new_version) = Version::parse(version) { match self.max { @@ -420,9 +433,8 @@ impl ChangeSet { println!("max change: {} (could not parse) -> {:?}", version, self.max); } - for change in self.changes.values() { - change.report(session); - // span_note!(session, change.span(), "S0001"); + for key in self.spans.values() { + self.changes[key].report(session); } } } diff --git a/tests/examples/addition.out b/tests/examples/addition.out index eaeecd3a61b38..e6b80bd38c0b4 100644 --- a/tests/examples/addition.out +++ b/tests/examples/addition.out @@ -11,9 +11,3 @@ warning: Addition of at least one path to `a` (TechnicallyBreaking) 10 | } | ^ -warning: Addition of at least one path to `Abc` (TechnicallyBreaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/addition.rs:6:5 - | -6 | pub struct Abc; - | ^^^^^^^^^^^^^^^ - diff --git a/tests/examples/addition_path.out b/tests/examples/addition_path.out index 7aa189b00b874..6cdbd8907eb63 100644 --- a/tests/examples/addition_path.out +++ b/tests/examples/addition_path.out @@ -6,11 +6,12 @@ warning: Addition of at least one path to `b` (TechnicallyBreaking) 14 | | } | |_____^ -warning: Addition of at least one path to `Abc` (TechnicallyBreaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/addition_path.rs:20:13 +warning: Addition of at least one path to `c` (TechnicallyBreaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/addition_path.rs:17:9 | -20 | pub use self::a::Abc; - | ^^^^^^^^^^^^ +17 | / pub use new::a::Abc; +18 | | } + | |_____^ warning: Addition of at least one path to `Abc` (TechnicallyBreaking) --> /home/twk/gsoc/rust-semverver/tests/examples/addition_path.rs:20:13 @@ -18,10 +19,3 @@ warning: Addition of at least one path to `Abc` (TechnicallyBreaking) 20 | pub use self::a::Abc; | ^^^^^^^^^^^^ -warning: Addition of at least one path to `c` (TechnicallyBreaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/addition_path.rs:17:9 - | -17 | / pub use new::a::Abc; -18 | | } - | |_____^ - diff --git a/tests/examples/kind_change.out b/tests/examples/kind_change.out index 0261b422589fb..94790405b501f 100644 --- a/tests/examples/kind_change.out +++ b/tests/examples/kind_change.out @@ -1,14 +1,4 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Breaking changes in `Abc` - --> /home/twk/gsoc/rust-semverver/tests/examples/kind_change.rs:6:5 - | -6 | / pub enum Abc { -7 | | -8 | | } - | |_____^ - | - = warning: Breaking (KindDifference) - warning: Removal of at least one path to `Abc` (Breaking) --> /home/twk/gsoc/rust-semverver/tests/examples/kind_change.rs:2:5 | diff --git a/tests/examples/pathologic_paths.out b/tests/examples/pathologic_paths.out index a9e6d1a977fcf..1c3cfb3d2ff2d 100644 --- a/tests/examples/pathologic_paths.out +++ b/tests/examples/pathologic_paths.out @@ -1,13 +1,13 @@ version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 -warning: Addition of at least one path to `b` (TechnicallyBreaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/pathologic_paths.rs:12:25 - | -12 | pub mod b { pub use super::a::*; } - | ^^^^^^^^^^^^^^^^^^^^^^ - warning: Addition of at least one path to `a` (TechnicallyBreaking) --> /home/twk/gsoc/rust-semverver/tests/examples/pathologic_paths.rs:11:25 | 11 | pub mod a { blow!($($rest)*); } | ^^^^^^^^^^^^^^^^^^^ +warning: Addition of at least one path to `b` (TechnicallyBreaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/pathologic_paths.rs:12:25 + | +12 | pub mod b { pub use super::a::*; } + | ^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/examples/removal.out b/tests/examples/removal.out index 5317823dd4b65..3db22faa5a4f0 100644 --- a/tests/examples/removal.out +++ b/tests/examples/removal.out @@ -1,19 +1,13 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Removal of at least one path to `a` (Breaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/removal.rs:6:5 - | -6 | } - | ^ - warning: Removal of at least one path to `Abc` (Breaking) --> /home/twk/gsoc/rust-semverver/tests/examples/removal.rs:2:5 | 2 | pub struct Abc; | ^^^^^^^^^^^^^^^ -warning: Removal of at least one path to `Abc` (Breaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/removal.rs:2:5 +warning: Removal of at least one path to `a` (Breaking) + --> /home/twk/gsoc/rust-semverver/tests/examples/removal.rs:6:5 | -2 | pub struct Abc; - | ^^^^^^^^^^^^^^^ +6 | } + | ^ diff --git a/tests/examples/removal_path.out b/tests/examples/removal_path.out index e52b15ebfa5fc..b9cd9b5ccca99 100644 --- a/tests/examples/removal_path.out +++ b/tests/examples/removal_path.out @@ -6,12 +6,6 @@ warning: Removal of at least one path to `b` (Breaking) 8 | | } | |_____^ -warning: Removal of at least one path to `Abc` (Breaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/removal_path.rs:14:13 - | -14 | pub use self::a::Abc; - | ^^^^^^^^^^^^ - warning: Removal of at least one path to `c` (Breaking) --> /home/twk/gsoc/rust-semverver/tests/examples/removal_path.rs:11:9 | diff --git a/tests/examples/struct.out b/tests/examples/struct.out index f24980af82683..2d7fdde3251f3 100644 --- a/tests/examples/struct.out +++ b/tests/examples/struct.out @@ -5,13 +5,3 @@ matching variants matching fields matching variants version bump: 1.0.0 -> (NonBreaking) -> 1.1.0 -warning: NonBreaking changes in `Def` - --> /home/twk/gsoc/rust-semverver/tests/examples/struct.rs:22:5 - | -22 | / pub struct Def { -23 | | field: A, -24 | | } - | |_____^ - | - = note: NonBreaking (TypeParameterAdded { defaulted: true }) - diff --git a/tests/examples/ty_alias.out b/tests/examples/ty_alias.out index 673108e3a42cf..2768b1c58ee1a 100644 --- a/tests/examples/ty_alias.out +++ b/tests/examples/ty_alias.out @@ -1,58 +1 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Breaking changes in `C` - --> /home/twk/gsoc/rust-semverver/tests/examples/ty_alias.rs:14:5 - | -14 | pub type C = T; - | ^^^^^^^^^^^^^^^^^^ - | - = warning: Breaking (RegionParameterRemoved) - -warning: Breaking changes in `A` - --> /home/twk/gsoc/rust-semverver/tests/examples/ty_alias.rs:12:5 - | -12 | pub type A = u16; - | ^^^^^^^^^^^^^^^^^ - | - = warning: Breaking (FieldTypeChanged("expected u8, found u16")) - -warning: Breaking changes in `D` - --> /home/twk/gsoc/rust-semverver/tests/examples/ty_alias.rs:15:5 - | -15 | pub type D<'a, T, U=T> = (&'a T, U); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: NonBreaking (TypeParameterAdded { defaulted: true }) - = warning: Breaking (FieldTypeChanged("expected reference, found tuple")) - -warning: Breaking changes in `F` - --> /home/twk/gsoc/rust-semverver/tests/examples/ty_alias.rs:17:5 - | -17 | pub type F<'a> = &'a u8; - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: Breaking (TypeParameterRemoved { defaulted: true }) - -warning: Breaking changes in `G` - --> /home/twk/gsoc/rust-semverver/tests/examples/ty_alias.rs:18:5 - | -18 | pub type G<'a> = (&'a u8); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: Breaking (TypeParameterRemoved { defaulted: false }) - -warning: Breaking changes in `E` - --> /home/twk/gsoc/rust-semverver/tests/examples/ty_alias.rs:16:5 - | -16 | pub type E<'a, T, U> = (&'a T, U); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: Breaking (TypeParameterAdded { defaulted: false }) - -warning: Breaking changes in `B` - --> /home/twk/gsoc/rust-semverver/tests/examples/ty_alias.rs:13:5 - | -13 | pub type B<'a, 'b : 'a, T> = (&'a T, &'b T); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: Breaking (RegionParameterAdded) - From 1af9737fdd0ab00cb54799a73d622723d67ad8c4 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 19 Jun 2017 14:35:56 +0200 Subject: [PATCH 069/553] Fixed test-runner to be agnostic to the current directory. --- tests/examples.rs | 27 +++++++++++++++++++++++---- tests/examples/addition.out | 4 ++-- tests/examples/addition_path.out | 6 +++--- tests/examples/kind_change.out | 2 +- tests/examples/pathologic_paths.out | 4 ++-- tests/examples/removal.out | 4 ++-- tests/examples/removal_path.out | 6 +++--- 7 files changed, 36 insertions(+), 17 deletions(-) diff --git a/tests/examples.rs b/tests/examples.rs index f0ecb721b88e2..44b9ff35eca0f 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -1,3 +1,4 @@ +use std::env; use std::fs::File; use std::io::Write; use std::os::unix::io::{AsRawFd, FromRawFd}; @@ -7,6 +8,9 @@ use std::process::{Command, Stdio}; fn examples() { let mut success = true; + let current_dir = env::current_dir().expect("could not determine current dir"); + let subst = format!("s#{}#$REPO_PATH#g", current_dir.to_str().unwrap()); + for file in std::fs::read_dir("tests/examples") .expect("could not read dir") .map(|f| f.expect("could not get file info").path()) { @@ -14,7 +18,6 @@ fn examples() { let out_file = file.with_extension("out"); let output = File::create(&out_file).expect("could not create file"); let fd = output.as_raw_fd(); - //let out = unsafe {Stdio::from_raw_fd(fd)}; let err = unsafe { Stdio::from_raw_fd(fd) }; let out = unsafe { Stdio::from_raw_fd(fd) }; @@ -30,6 +33,21 @@ fn examples() { success &= compile_success; if compile_success { + let mut sed_child = Command::new("sed") + .arg(&subst) + .stdin(Stdio::piped()) + .stdout(out) + .stderr(err) + .spawn() + .expect("could not run sed"); + + let (err_pipe, out_pipe) = if let Some(ref mut stdin) = sed_child.stdin { + let fd = stdin.as_raw_fd(); + unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } + } else { + panic!("could not pipe to sed"); + }; + let mut child = Command::new("./target/debug/rust-semverver") .args(&["--crate-type=lib", "--extern", @@ -40,8 +58,8 @@ fn examples() { .env("RUST_BACKTRACE", "full") .env("RUST_SEMVER_CRATE_VERSION", "1.0.0") .stdin(Stdio::piped()) - .stdout(out) - .stderr(err) + .stdout(out_pipe) + .stderr(err_pipe) .spawn() .expect("could not run rust-semverver"); @@ -50,10 +68,11 @@ fn examples() { .write_fmt(format_args!("extern crate oldandnew;")) .expect("could not pipe to rust-semverver"); } else { - panic!("could not pipe to rustc (wtf?)"); + panic!("could not pipe to rustc"); } success &= child.wait().expect("could not wait for child").success(); + success &= sed_child.wait().expect("could not wait for sed child").success(); success &= Command::new("git") .args(&["diff", "--exit-code", out_file.to_str().unwrap()]) diff --git a/tests/examples/addition.out b/tests/examples/addition.out index e6b80bd38c0b4..322f3d3346501 100644 --- a/tests/examples/addition.out +++ b/tests/examples/addition.out @@ -1,12 +1,12 @@ version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 warning: Addition of at least one path to `Abc` (TechnicallyBreaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/addition.rs:6:5 + --> $REPO_PATH/tests/examples/addition.rs:6:5 | 6 | pub struct Abc; | ^^^^^^^^^^^^^^^ warning: Addition of at least one path to `a` (TechnicallyBreaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/addition.rs:10:5 + --> $REPO_PATH/tests/examples/addition.rs:10:5 | 10 | } | ^ diff --git a/tests/examples/addition_path.out b/tests/examples/addition_path.out index 6cdbd8907eb63..0c5b799b1b71f 100644 --- a/tests/examples/addition_path.out +++ b/tests/examples/addition_path.out @@ -1,20 +1,20 @@ version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 warning: Addition of at least one path to `b` (TechnicallyBreaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/addition_path.rs:13:9 + --> $REPO_PATH/tests/examples/addition_path.rs:13:9 | 13 | / pub use new::a::*; 14 | | } | |_____^ warning: Addition of at least one path to `c` (TechnicallyBreaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/addition_path.rs:17:9 + --> $REPO_PATH/tests/examples/addition_path.rs:17:9 | 17 | / pub use new::a::Abc; 18 | | } | |_____^ warning: Addition of at least one path to `Abc` (TechnicallyBreaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/addition_path.rs:20:13 + --> $REPO_PATH/tests/examples/addition_path.rs:20:13 | 20 | pub use self::a::Abc; | ^^^^^^^^^^^^ diff --git a/tests/examples/kind_change.out b/tests/examples/kind_change.out index 94790405b501f..d5a6af561b84e 100644 --- a/tests/examples/kind_change.out +++ b/tests/examples/kind_change.out @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 warning: Removal of at least one path to `Abc` (Breaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/kind_change.rs:2:5 + --> $REPO_PATH/tests/examples/kind_change.rs:2:5 | 2 | pub struct Abc; | ^^^^^^^^^^^^^^^ diff --git a/tests/examples/pathologic_paths.out b/tests/examples/pathologic_paths.out index 1c3cfb3d2ff2d..4c5c82f4f5c4c 100644 --- a/tests/examples/pathologic_paths.out +++ b/tests/examples/pathologic_paths.out @@ -1,12 +1,12 @@ version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 warning: Addition of at least one path to `a` (TechnicallyBreaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/pathologic_paths.rs:11:25 + --> $REPO_PATH/tests/examples/pathologic_paths.rs:11:25 | 11 | pub mod a { blow!($($rest)*); } | ^^^^^^^^^^^^^^^^^^^ warning: Addition of at least one path to `b` (TechnicallyBreaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/pathologic_paths.rs:12:25 + --> $REPO_PATH/tests/examples/pathologic_paths.rs:12:25 | 12 | pub mod b { pub use super::a::*; } | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/examples/removal.out b/tests/examples/removal.out index 3db22faa5a4f0..6dd25ab08277c 100644 --- a/tests/examples/removal.out +++ b/tests/examples/removal.out @@ -1,12 +1,12 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 warning: Removal of at least one path to `Abc` (Breaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/removal.rs:2:5 + --> $REPO_PATH/tests/examples/removal.rs:2:5 | 2 | pub struct Abc; | ^^^^^^^^^^^^^^^ warning: Removal of at least one path to `a` (Breaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/removal.rs:6:5 + --> $REPO_PATH/tests/examples/removal.rs:6:5 | 6 | } | ^ diff --git a/tests/examples/removal_path.out b/tests/examples/removal_path.out index b9cd9b5ccca99..fbb112308f12e 100644 --- a/tests/examples/removal_path.out +++ b/tests/examples/removal_path.out @@ -1,20 +1,20 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 warning: Removal of at least one path to `b` (Breaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/removal_path.rs:7:9 + --> $REPO_PATH/tests/examples/removal_path.rs:7:9 | 7 | / pub use old::a::*; 8 | | } | |_____^ warning: Removal of at least one path to `c` (Breaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/removal_path.rs:11:9 + --> $REPO_PATH/tests/examples/removal_path.rs:11:9 | 11 | / pub use old::a::Abc; 12 | | } | |_____^ warning: Removal of at least one path to `Abc` (Breaking) - --> /home/twk/gsoc/rust-semverver/tests/examples/removal_path.rs:14:13 + --> $REPO_PATH/tests/examples/removal_path.rs:14:13 | 14 | pub use self::a::Abc; | ^^^^^^^^^^^^ From 43ed6fa8c31427e05acb571c3512009a7b866523 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 19 Jun 2017 17:09:02 +0200 Subject: [PATCH 070/553] Simple ADT traversal. --- src/semcheck/changes.rs | 19 +++++++++++++++++++ src/semcheck/traverse.rs | 30 ++++++++++++++---------------- tests/examples/struct.out | 6 ------ 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index ea4b1555287c9..db8fbc4bf60c0 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -407,6 +407,25 @@ impl ChangeSet { entry.add(type_); } + pub fn add_binary(&mut self, type_: BinaryChangeType, old: DefId) -> bool { + use std::collections::hash_map::Entry; + + let key = ChangeKey::OldKey(old); + let cat = type_.to_category(); + + if cat > self.max { + self.max = cat.clone(); + } + + match self.changes.entry(key) { + Entry::Occupied(c) => { + c.into_mut().add(type_); + true + }, + Entry::Vacant(_) => false, + } + } + /// Check whether an item with the given id has undergone breaking changes. /// /// The expected `DefId` is obviously an *old* one. diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 52e9dfed90bf3..377c6f717a0ca 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -89,7 +89,6 @@ fn get_namespace(def: &Def) -> Namespace { /// /// Match up pairs of modules from the two crate versions and compare for changes. /// Matching children get processed in the same fashion. -/// // TODO: describe the passes we do. pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { let cstore = &tcx.sess.cstore; @@ -129,7 +128,7 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { } (Some(o), Some(n)) => { if !id_mapping.add_export(o, n) { - diff_item_structures(&mut changes, &id_mapping, tcx, o, n); + diff_item_structures(&mut changes, &mut id_mapping, tcx, o, n); } } (Some(old), None) => { @@ -158,7 +157,7 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { /// If the two items can't be meaningfully compared because they are of different kinds, /// we return that difference directly. fn diff_item_structures(changes: &mut ChangeSet, - _: &IdMapping, + id_mapping: &mut IdMapping, tcx: TyCtxt, old: Export, new: Export) { @@ -210,6 +209,8 @@ fn diff_item_structures(changes: &mut ChangeSet, for (_, items) in variants.drain() { match items { (Some(old), Some(new)) => { + id_mapping.add_item(old.did, new.did); + for field in &old.fields { fields.entry(field.name).or_insert((None, None)).0 = Some(field); } @@ -219,29 +220,26 @@ fn diff_item_structures(changes: &mut ChangeSet, } for (_, items2) in fields.drain() { + // TODO: visibility match items2 { (Some(o), Some(n)) => { - println!("matching fields"); + id_mapping.add_item(o.did, n.did); }, - (Some(o), None) => { - println!("removed field"); + (Some(_), None) => { + changes.add_binary(VariantFieldRemoved, old_def_id); }, - (None, Some(n)) => { - println!("added field"); + (None, Some(_)) => { + changes.add_binary(VariantFieldAdded, old_def_id); }, (None, None) => unreachable!(), } } - - println!("matching variants"); }, - (Some(old), None) => { - println!("removed variant"); - // TODO: a new variant has been removed from the enum (apparently) + (Some(_), None) => { + changes.add_binary(EnumVariantRemoved, old_def_id); }, - (None, Some(new)) => { - println!("added variant"); - // TODO: a new variant has been added to the enum (apparently) + (None, Some(_)) => { + changes.add_binary(EnumVariantAdded, old_def_id); }, (None, None) => unreachable!(), } diff --git a/tests/examples/struct.out b/tests/examples/struct.out index 2d7fdde3251f3..e700be2bd26d0 100644 --- a/tests/examples/struct.out +++ b/tests/examples/struct.out @@ -1,7 +1 @@ -matching fields -matching variants -matching fields -matching variants -matching fields -matching variants version bump: 1.0.0 -> (NonBreaking) -> 1.1.0 From 8ffc0b4f00d95e0a67ccd2483956f49254812e9e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 19 Jun 2017 18:18:08 +0200 Subject: [PATCH 071/553] Changed change set handling (again). We now allow for subspans being stored for each binary change type stored in the set. The inner workings of the implementation should be probably improved still, but the overall structure is fine as-is. --- src/semcheck/changes.rs | 65 +++++++++++++++++++--------------------- src/semcheck/traverse.rs | 27 ++++++++++------- 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index db8fbc4bf60c0..257f000bf0374 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -200,7 +200,7 @@ impl BinaryChangeType { // tied together. pub struct BinaryChange { /// The type of the change affecting the item. - changes: BTreeSet, + changes: BTreeSet<(BinaryChangeType, Option)>, /// The most severe change category already recorded for the item. max: ChangeCategory, /// The old export of the change item. @@ -221,14 +221,14 @@ impl BinaryChange { } /// Add another change type to the change record. - fn add(&mut self, type_: BinaryChangeType) { + fn add(&mut self, type_: BinaryChangeType, span: Option) { let cat = type_.to_category(); if cat > self.max { self.max = cat; } - self.changes.insert(type_); + self.changes.insert((type_, span)); } /// Get the change's category. @@ -248,16 +248,28 @@ impl BinaryChange { /// Report the change. fn report(&self, session: &Session) { + if self.max == Patch { + return; + } + let msg = format!("{:?} changes in `{}`", self.max, self.ident()); let mut builder = session.struct_span_warn(self.new.span, &msg); for change in &self.changes { - let cat = change.to_category(); - let sub_msg = format!("{:?} ({:?})", cat, change); - if cat == Breaking { - builder.warn(&sub_msg); + let cat = change.0.to_category(); + let sub_msg = format!("{:?} ({:?})", cat, change.0); + if let Some(span) = change.1 { + if cat == Breaking { + builder.span_warn(span, &sub_msg); + } else { + builder.span_note(span, &sub_msg,); + } } else { - builder.note(&sub_msg); + if cat == Breaking { + builder.warn(&sub_msg); + } else { + builder.note(&sub_msg,); + } } } @@ -314,10 +326,10 @@ impl Change { } /// Add a change type to a given binary change. - fn add(&mut self, type_: BinaryChangeType) { + fn add(&mut self, type_: BinaryChangeType, span: Option) { match *self { Change::Unary(_) => panic!("can't add binary change types to unary change"), - Change::Binary(ref mut b) => b.add(type_), + Change::Binary(ref mut b) => b.add(type_, span), } } @@ -391,25 +403,14 @@ impl ChangeSet { self.changes.insert(key, change); } - /// Add a new binary change for the given exports. - pub fn new_binary(&mut self, type_: BinaryChangeType, old: Export, new: Export) { - let key = ChangeKey::OldKey(old.def.def_id()); - let cat = type_.to_category(); - - if cat > self.max { - self.max = cat.clone(); - } - - let entry = self.changes - .entry(key) - .or_insert_with(|| Change::new_binary(old, new)); - - entry.add(type_); + /// Add a new binary change entry for the given exports. + pub fn new_binary(&mut self, old: Export, new: Export) { + self.changes + .insert(ChangeKey::OldKey(old.def.def_id()), Change::new_binary(old, new)); } - pub fn add_binary(&mut self, type_: BinaryChangeType, old: DefId) -> bool { - use std::collections::hash_map::Entry; - + /// Add a new binary change to an already existing entry. + pub fn add_binary(&mut self, type_: BinaryChangeType, old: DefId, span: Option) { let key = ChangeKey::OldKey(old); let cat = type_.to_category(); @@ -417,13 +418,7 @@ impl ChangeSet { self.max = cat.clone(); } - match self.changes.entry(key) { - Entry::Occupied(c) => { - c.into_mut().add(type_); - true - }, - Entry::Vacant(_) => false, - } + self.changes.get_mut(&key).unwrap().add(type_, span); } /// Check whether an item with the given id has undergone breaking changes. @@ -575,7 +570,7 @@ pub mod tests { }; let mut change = BinaryChange::new(export1, export2); - change.add(t); + change.add(t, Some(s1)); change } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 377c6f717a0ca..d1a418dfe61a8 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -128,6 +128,7 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { } (Some(o), Some(n)) => { if !id_mapping.add_export(o, n) { + changes.new_binary(o, n); diff_item_structures(&mut changes, &mut id_mapping, tcx, o, n); } } @@ -166,7 +167,7 @@ fn diff_item_structures(changes: &mut ChangeSet, let mut generics_changes = diff_generics(tcx, old_def_id, new_def_id); for change_type in generics_changes.drain(..) { - changes.new_binary(change_type, old, new); + changes.add_binary(change_type, old_def_id, None); } // TODO: crude dispatching logic for now (needs totality etc). @@ -183,7 +184,7 @@ fn diff_item_structures(changes: &mut ChangeSet, (Macro(_, _), Macro(_, _)) => {}, _ => { // No match - so we don't need to look further. - changes.new_binary(KindDifference, old, new); + changes.add_binary(KindDifference, old_def_id, None); return; }, } @@ -225,21 +226,25 @@ fn diff_item_structures(changes: &mut ChangeSet, (Some(o), Some(n)) => { id_mapping.add_item(o.did, n.did); }, - (Some(_), None) => { - changes.add_binary(VariantFieldRemoved, old_def_id); + (Some(o), None) => { + changes.add_binary(VariantFieldRemoved, + old_def_id, + Some(tcx.def_span(o.did))); }, - (None, Some(_)) => { - changes.add_binary(VariantFieldAdded, old_def_id); + (None, Some(n)) => { + changes.add_binary(VariantFieldAdded, + old_def_id, + Some(tcx.def_span(n.did))); }, (None, None) => unreachable!(), } } }, - (Some(_), None) => { - changes.add_binary(EnumVariantRemoved, old_def_id); + (Some(old), None) => { + changes.add_binary(EnumVariantRemoved, old_def_id, Some(tcx.def_span(old.did))); }, - (None, Some(_)) => { - changes.add_binary(EnumVariantAdded, old_def_id); + (None, Some(new)) => { + changes.add_binary(EnumVariantAdded, old_def_id, Some(tcx.def_span(new.did))); }, (None, None) => unreachable!(), } @@ -259,7 +264,7 @@ fn diff_items(changes: &mut ChangeSet, let mut type_changes = diff_types(id_mapping, tcx, old.def.def_id(), new.def.def_id()); for change_type in type_changes.drain(..) { - changes.new_binary(change_type, old, new); + changes.add_binary(change_type, old.def.def_id(), None); } } } From feab88204f9e2c21421d9b45bf8e655c1725a1ff Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 20 Jun 2017 12:00:24 +0200 Subject: [PATCH 072/553] First sketch of private item handling --- src/semcheck/changes.rs | 17 +++++++--- src/semcheck/traverse.rs | 21 ++++++++----- tests/examples/addition.out | 20 ++++++++---- tests/examples/addition.rs | 11 +++++++ tests/examples/kind_change.out | 10 ++++++ tests/examples/removal.out | 12 +++++-- tests/examples/removal.rs | 11 +++++++ tests/examples/struct.out | 10 ++++++ tests/examples/ty_alias.out | 57 ++++++++++++++++++++++++++++++++++ 9 files changed, 149 insertions(+), 20 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 257f000bf0374..f0dfeb24bc2ff 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -121,6 +121,10 @@ impl Ord for UnaryChange { // TODO: this needs a lot of refinement still #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum BinaryChangeType { + /// An item has been made public. + ItemMadePublic, + /// An item has been made private + ItemMadePrivate, /// An item has changed it's kind. KindDifference, /// A region parameter has been added to an item. @@ -167,6 +171,7 @@ impl BinaryChangeType { // TODO: this will need a lot of changes (it's *very* conservative rn) pub fn to_category(&self) -> ChangeCategory { match *self { + ItemMadePrivate | KindDifference | RegionParameterAdded | RegionParameterRemoved | @@ -185,7 +190,8 @@ impl BinaryChangeType { TraitImplItemAdded { .. } | TraitImplItemRemoved | Unknown => Breaking, - TypeGeneralization => TechnicallyBreaking, + TypeGeneralization | + ItemMadePublic => TechnicallyBreaking, TypeParameterAdded { defaulted: true } => NonBreaking, } } @@ -268,7 +274,7 @@ impl BinaryChange { if cat == Breaking { builder.warn(&sub_msg); } else { - builder.note(&sub_msg,); + builder.note(&sub_msg); } } } @@ -405,8 +411,11 @@ impl ChangeSet { /// Add a new binary change entry for the given exports. pub fn new_binary(&mut self, old: Export, new: Export) { - self.changes - .insert(ChangeKey::OldKey(old.def.def_id()), Change::new_binary(old, new)); + let key = ChangeKey::OldKey(old.def.def_id()); + let change = Change::new_binary(old, new); + + self.spans.insert(*change.span(), key.clone()); + self.changes.insert(key, change); } /// Add a new binary change to an already existing entry. diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index d1a418dfe61a8..d34b60fe4ab6a 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -7,9 +7,9 @@ use rustc::hir::def::Def::*; use rustc::hir::def::Export; use rustc::hir::def_id::DefId; use rustc::ty::TyCtxt; +use rustc::ty::Visibility::Public; use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; use rustc::ty::subst::{Subst, Substs}; -use rustc::ty::Visibility::Public; use std::collections::{HashMap, HashSet, VecDeque}; @@ -105,16 +105,12 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { let mut c_new = cstore.item_children(new_did, tcx.sess); // TODO: refactor this to avoid storing tons of `Namespace` values. - for child in c_old - .drain(..) - .filter(|c| cstore.visibility(c.def.def_id()) == Public) { + for child in c_old.drain(..) { let key = (get_namespace(&child.def), child.ident.name); children.entry(key).or_insert((None, None)).0 = Some(child); } - for child in c_new - .drain(..) - .filter(|c| cstore.visibility(c.def.def_id()) == Public) { + for child in c_new.drain(..) { let key = (get_namespace(&child.def), child.ident.name); children.entry(key).or_insert((None, None)).1 = Some(child); } @@ -122,13 +118,21 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { for (_, items) in children.drain() { match items { (Some(Export { def: Mod(o), .. }), Some(Export { def: Mod(n), .. })) => { + // TODO: handle private modules correctly! if !visited.insert((o, n)) { mod_queue.push_back((o, n)); } } (Some(o), Some(n)) => { if !id_mapping.add_export(o, n) { + let old_vis = cstore.visibility(o.def.def_id()); + let new_vis = cstore.visibility(n.def.def_id()); changes.new_binary(o, n); + if old_vis == Public && new_vis != Public { + changes.add_binary(ItemMadePrivate, o.def.def_id(), None); + } else if old_vis != Public && new_vis == Public { + changes.add_binary(ItemMadePublic, o.def.def_id(), None); + } diff_item_structures(&mut changes, &mut id_mapping, tcx, o, n); } } @@ -172,7 +176,8 @@ fn diff_item_structures(changes: &mut ChangeSet, // TODO: crude dispatching logic for now (needs totality etc). match (old.def, new.def) { - (TyAlias(_), TyAlias(_)) => return, + (TyAlias(_), TyAlias(_)) | + (StructCtor(_, _), StructCtor(_, _)) => return, (Struct(_), Struct(_)) | (Union(_), Union(_)) | (Enum(_), Enum(_)) | diff --git a/tests/examples/addition.out b/tests/examples/addition.out index 322f3d3346501..b773b98353156 100644 --- a/tests/examples/addition.out +++ b/tests/examples/addition.out @@ -1,13 +1,21 @@ version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 warning: Addition of at least one path to `Abc` (TechnicallyBreaking) - --> $REPO_PATH/tests/examples/addition.rs:6:5 - | -6 | pub struct Abc; - | ^^^^^^^^^^^^^^^ + --> $REPO_PATH/tests/examples/addition.rs:11:5 + | +11 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + +warning: TechnicallyBreaking changes in `Bce` + --> $REPO_PATH/tests/examples/addition.rs:13:5 + | +13 | pub struct Bce; + | ^^^^^^^^^^^^^^^ + | + = note: TechnicallyBreaking (ItemMadePublic) warning: Addition of at least one path to `a` (TechnicallyBreaking) - --> $REPO_PATH/tests/examples/addition.rs:10:5 + --> $REPO_PATH/tests/examples/addition.rs:17:5 | -10 | } +17 | } | ^ diff --git a/tests/examples/addition.rs b/tests/examples/addition.rs index 24c9be4469acd..751b3bb1eaefb 100644 --- a/tests/examples/addition.rs +++ b/tests/examples/addition.rs @@ -1,11 +1,22 @@ pub mod old { + #[allow(dead_code)] + struct Bce; + mod b { + + } } pub mod new { pub struct Abc; + pub struct Bce; + pub mod a { } + + pub mod b { + + } } diff --git a/tests/examples/kind_change.out b/tests/examples/kind_change.out index d5a6af561b84e..606ccdc18d6eb 100644 --- a/tests/examples/kind_change.out +++ b/tests/examples/kind_change.out @@ -5,3 +5,13 @@ warning: Removal of at least one path to `Abc` (Breaking) 2 | pub struct Abc; | ^^^^^^^^^^^^^^^ +warning: Breaking changes in `Abc` + --> $REPO_PATH/tests/examples/kind_change.rs:6:5 + | +6 | / pub enum Abc { +7 | | +8 | | } + | |_____^ + | + = warning: Breaking (KindDifference) + diff --git a/tests/examples/removal.out b/tests/examples/removal.out index 6dd25ab08277c..3890c640e6928 100644 --- a/tests/examples/removal.out +++ b/tests/examples/removal.out @@ -6,8 +6,16 @@ warning: Removal of at least one path to `Abc` (Breaking) | ^^^^^^^^^^^^^^^ warning: Removal of at least one path to `a` (Breaking) - --> $REPO_PATH/tests/examples/removal.rs:6:5 + --> $REPO_PATH/tests/examples/removal.rs:8:5 | -6 | } +8 | } | ^ +warning: Breaking changes in `Bce` + --> $REPO_PATH/tests/examples/removal.rs:17:5 + | +17 | struct Bce; + | ^^^^^^^^^^^ + | + = warning: Breaking (ItemMadePrivate) + diff --git a/tests/examples/removal.rs b/tests/examples/removal.rs index bffaa6d7b7387..10c3464478bb4 100644 --- a/tests/examples/removal.rs +++ b/tests/examples/removal.rs @@ -1,11 +1,22 @@ pub mod old { pub struct Abc; + pub struct Bce; + pub mod a { } + + pub mod b { + + } } pub mod new { + #[allow(dead_code)] + struct Bce; + + mod b { + } } diff --git a/tests/examples/struct.out b/tests/examples/struct.out index e700be2bd26d0..3426e03e80ed0 100644 --- a/tests/examples/struct.out +++ b/tests/examples/struct.out @@ -1 +1,11 @@ version bump: 1.0.0 -> (NonBreaking) -> 1.1.0 +warning: NonBreaking changes in `Def` + --> $REPO_PATH/tests/examples/struct.rs:22:5 + | +22 | / pub struct Def { +23 | | field: A, +24 | | } + | |_____^ + | + = note: NonBreaking (TypeParameterAdded { defaulted: true }) + diff --git a/tests/examples/ty_alias.out b/tests/examples/ty_alias.out index 2768b1c58ee1a..c7e82989aa111 100644 --- a/tests/examples/ty_alias.out +++ b/tests/examples/ty_alias.out @@ -1 +1,58 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 +warning: Breaking changes in `A` + --> $REPO_PATH/tests/examples/ty_alias.rs:12:5 + | +12 | pub type A = u16; + | ^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (FieldTypeChanged("expected u8, found u16")) + +warning: Breaking changes in `B` + --> $REPO_PATH/tests/examples/ty_alias.rs:13:5 + | +13 | pub type B<'a, 'b : 'a, T> = (&'a T, &'b T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (RegionParameterAdded) + +warning: Breaking changes in `C` + --> $REPO_PATH/tests/examples/ty_alias.rs:14:5 + | +14 | pub type C = T; + | ^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (RegionParameterRemoved) + +warning: Breaking changes in `D` + --> $REPO_PATH/tests/examples/ty_alias.rs:15:5 + | +15 | pub type D<'a, T, U=T> = (&'a T, U); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: NonBreaking (TypeParameterAdded { defaulted: true }) + = warning: Breaking (FieldTypeChanged("expected reference, found tuple")) + +warning: Breaking changes in `E` + --> $REPO_PATH/tests/examples/ty_alias.rs:16:5 + | +16 | pub type E<'a, T, U> = (&'a T, U); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (TypeParameterAdded { defaulted: false }) + +warning: Breaking changes in `F` + --> $REPO_PATH/tests/examples/ty_alias.rs:17:5 + | +17 | pub type F<'a> = &'a u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (TypeParameterRemoved { defaulted: true }) + +warning: Breaking changes in `G` + --> $REPO_PATH/tests/examples/ty_alias.rs:18:5 + | +18 | pub type G<'a> = (&'a u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (TypeParameterRemoved { defaulted: false }) + From 00cd0d0b1032f2cc609987dd17197cd9fe5ec5aa Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 20 Jun 2017 14:49:02 +0200 Subject: [PATCH 073/553] Improved version of private item traversal. It remains to fix a few false positives that are present due to us no longer benefitting the implicit reachability of items through paths we previously computed during the module traversal. Since we now need an exhaustive mapping between definition IDs from both crate versions, we can't simply traverse public items only. --- src/semcheck/changes.rs | 26 ++++++++++++++------------ src/semcheck/traverse.rs | 31 ++++++++++++++++++++++++------- tests/examples/addition.out | 30 ++++++++++++++++++++++-------- tests/examples/addition.rs | 7 ++++--- tests/examples/removal.out | 20 ++++++++++++++++++-- tests/examples/removal.rs | 7 ++++--- 6 files changed, 86 insertions(+), 35 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index f0dfeb24bc2ff..dc95415549ddc 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -213,16 +213,19 @@ pub struct BinaryChange { old: Export, /// The new export of the change item. new: Export, + /// Whether to output changes. Used to distinguish all-private items. + output: bool } impl BinaryChange { /// Construct a new empty change record for an item. - fn new(old: Export, new: Export) -> BinaryChange { + fn new(old: Export, new: Export, output: bool) -> BinaryChange { BinaryChange { changes: BTreeSet::new(), max: ChangeCategory::default(), old: old, new: new, + output: output, } } @@ -254,7 +257,7 @@ impl BinaryChange { /// Report the change. fn report(&self, session: &Session) { - if self.max == Patch { + if self.max == Patch || !self.output { return; } @@ -270,12 +273,11 @@ impl BinaryChange { } else { builder.span_note(span, &sub_msg,); } + // change.1 == None from here on. + } else if cat == Breaking { + builder.warn(&sub_msg); } else { - if cat == Breaking { - builder.warn(&sub_msg); - } else { - builder.note(&sub_msg); - } + builder.note(&sub_msg); } } @@ -327,8 +329,8 @@ impl Change { } /// Construct a new binary change for the given exports. - fn new_binary(old: Export, new: Export) -> Change { - Change::Binary(BinaryChange::new(old, new)) + fn new_binary(old: Export, new: Export, output: bool) -> Change { + Change::Binary(BinaryChange::new(old, new, output)) } /// Add a change type to a given binary change. @@ -410,9 +412,9 @@ impl ChangeSet { } /// Add a new binary change entry for the given exports. - pub fn new_binary(&mut self, old: Export, new: Export) { + pub fn new_binary(&mut self, old: Export, new: Export, output: bool) { let key = ChangeKey::OldKey(old.def.def_id()); - let change = Change::new_binary(old, new); + let change = Change::new_binary(old, new, output); self.spans.insert(*change.span(), key.clone()); self.changes.insert(key, change); @@ -578,7 +580,7 @@ pub mod tests { span: s2, }; - let mut change = BinaryChange::new(export1, export2); + let mut change = BinaryChange::new(export1, export2, true); change.add(t, Some(s1)); change diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index d34b60fe4ab6a..65b3fce2393a5 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -118,21 +118,38 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { for (_, items) in children.drain() { match items { (Some(Export { def: Mod(o), .. }), Some(Export { def: Mod(n), .. })) => { - // TODO: handle private modules correctly! - if !visited.insert((o, n)) { + if visited.insert((o, n)) { + let o_vis = cstore.visibility(o); + let n_vis = cstore.visibility(n); + + if o_vis != n_vis { + // TODO: ugly + changes.new_binary(items.0.unwrap(), items.1.unwrap(), true); + + if o_vis == Public && n_vis != Public { + changes.add_binary(ItemMadePrivate, o, None); + } else if o_vis != Public && n_vis == Public { + changes.add_binary(ItemMadePublic, o, None); + } + } + mod_queue.push_back((o, n)); } } (Some(o), Some(n)) => { if !id_mapping.add_export(o, n) { - let old_vis = cstore.visibility(o.def.def_id()); - let new_vis = cstore.visibility(n.def.def_id()); - changes.new_binary(o, n); - if old_vis == Public && new_vis != Public { + let o_vis = cstore.visibility(o.def.def_id()); + let n_vis = cstore.visibility(n.def.def_id()); + + let output = o_vis == Public || n_vis == Public; + changes.new_binary(o, n, output); + + if o_vis == Public && n_vis != Public { changes.add_binary(ItemMadePrivate, o.def.def_id(), None); - } else if old_vis != Public && new_vis == Public { + } else if o_vis != Public && n_vis == Public { changes.add_binary(ItemMadePublic, o.def.def_id(), None); } + diff_item_structures(&mut changes, &mut id_mapping, tcx, o, n); } } diff --git a/tests/examples/addition.out b/tests/examples/addition.out index b773b98353156..b8fe6e6866d2f 100644 --- a/tests/examples/addition.out +++ b/tests/examples/addition.out @@ -1,21 +1,35 @@ -version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 +version bump: 1.0.0 -> (Breaking) -> 2.0.0 +warning: Removal of at least one path to `Cde` (Breaking) + --> $REPO_PATH/tests/examples/addition.rs:7:9 + | +7 | pub struct Cde; + | ^^^^^^^^^^^^^^^ + warning: Addition of at least one path to `Abc` (TechnicallyBreaking) - --> $REPO_PATH/tests/examples/addition.rs:11:5 + --> $REPO_PATH/tests/examples/addition.rs:12:5 | -11 | pub struct Abc; +12 | pub struct Abc; | ^^^^^^^^^^^^^^^ -warning: TechnicallyBreaking changes in `Bce` - --> $REPO_PATH/tests/examples/addition.rs:13:5 +warning: TechnicallyBreaking changes in `Bcd` + --> $REPO_PATH/tests/examples/addition.rs:14:5 | -13 | pub struct Bce; +14 | pub struct Bcd; | ^^^^^^^^^^^^^^^ | = note: TechnicallyBreaking (ItemMadePublic) warning: Addition of at least one path to `a` (TechnicallyBreaking) - --> $REPO_PATH/tests/examples/addition.rs:17:5 + --> $REPO_PATH/tests/examples/addition.rs:18:5 + | +18 | } + | ^ + +warning: TechnicallyBreaking changes in `b` + --> $REPO_PATH/tests/examples/addition.rs:22:5 | -17 | } +22 | } | ^ + | + = note: TechnicallyBreaking (ItemMadePublic) diff --git a/tests/examples/addition.rs b/tests/examples/addition.rs index 751b3bb1eaefb..5bcafc4c8b744 100644 --- a/tests/examples/addition.rs +++ b/tests/examples/addition.rs @@ -1,16 +1,17 @@ pub mod old { #[allow(dead_code)] - struct Bce; + struct Bcd; mod b { - + #[allow(dead_code)] + pub struct Cde; } } pub mod new { pub struct Abc; - pub struct Bce; + pub struct Bcd; pub mod a { diff --git a/tests/examples/removal.out b/tests/examples/removal.out index 3890c640e6928..38a4860335977 100644 --- a/tests/examples/removal.out +++ b/tests/examples/removal.out @@ -11,11 +11,27 @@ warning: Removal of at least one path to `a` (Breaking) 8 | } | ^ -warning: Breaking changes in `Bce` +warning: Breaking changes in `Bcd` --> $REPO_PATH/tests/examples/removal.rs:17:5 | -17 | struct Bce; +17 | struct Bcd; | ^^^^^^^^^^^ | = warning: Breaking (ItemMadePrivate) +warning: Breaking changes in `b` + --> $REPO_PATH/tests/examples/removal.rs:20:9 + | +20 | / #[allow(dead_code)] +21 | | pub struct Cde; +22 | | } + | |_____^ + | + = warning: Breaking (ItemMadePrivate) + +warning: Addition of at least one path to `Cde` (TechnicallyBreaking) + --> $REPO_PATH/tests/examples/removal.rs:21:9 + | +21 | pub struct Cde; + | ^^^^^^^^^^^^^^^ + diff --git a/tests/examples/removal.rs b/tests/examples/removal.rs index 10c3464478bb4..3559f27f823a7 100644 --- a/tests/examples/removal.rs +++ b/tests/examples/removal.rs @@ -1,7 +1,7 @@ pub mod old { pub struct Abc; - pub struct Bce; + pub struct Bcd; pub mod a { @@ -14,9 +14,10 @@ pub mod old { pub mod new { #[allow(dead_code)] - struct Bce; + struct Bcd; mod b { - + #[allow(dead_code)] + pub struct Cde; } } From 20e76d804b1f74c99dccb86df5eee54863d7a389 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 21 Jun 2017 21:54:52 +0200 Subject: [PATCH 074/553] Implemented proper ADT traversal. --- src/semcheck/changes.rs | 37 +++++++---------- src/semcheck/traverse.rs | 87 +++++++++++++++++++++++++++++++--------- 2 files changed, 82 insertions(+), 42 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index dc95415549ddc..6f8345efcf7c9 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -139,26 +139,20 @@ pub enum BinaryChangeType { TypeGeneralization, /// The bounds on a type parameter have been tightened. TypeSpecialization, - /// A field has been added to a struct. - StructFieldAdded { public: bool, total_public: bool }, // TODO: EXXXXPPPPLAAAAIN! - /// A field has been removed from a struct. - StructFieldRemoved { public: bool, total_public: bool }, // TODO: EXXXXPPPPLAAAIN! - /// A struct has changed it's style. - StructStyleChanged { now_tuple: bool, total_private: bool }, /// A variant has been added to an enum. - EnumVariantAdded, + VariantAdded, /// A variant has been removed from an enum. - EnumVariantRemoved, - /// A field hasb been added to an enum variant. - VariantFieldAdded, - /// A field has been removed from an enum variant. - VariantFieldRemoved, - /// An enum variant has changed it's style. - VariantFieldStyleChanged { now_tuple: bool }, + VariantRemoved, + /// A field hasb been added to a variant. + VariantFieldAdded { public: bool, total_public: bool }, + /// A field has been removed from a variant. + VariantFieldRemoved { public: bool, total_public: bool }, + /// A variant has changed it's style. + VariantStyleChanged { now_struct: bool, total_private: bool }, /// A field in a struct or enum has changed it's type. FieldTypeChanged(String), // FIXME: terrible for obvious reasons /// An impl item has been added. - TraitImplItemAdded { defaulted: bool }, // TODO: EXPLAAAIN! + TraitImplItemAdded { defaulted: bool }, /// An impl item has been removed. TraitImplItemRemoved, /// An unknown change is any change we don't yet explicitly handle. @@ -178,14 +172,11 @@ impl BinaryChangeType { TypeParameterAdded { defaulted: false } | TypeParameterRemoved { .. } | TypeSpecialization | - StructFieldAdded { .. } | - StructFieldRemoved { .. } | - StructStyleChanged { .. } | - EnumVariantAdded | - EnumVariantRemoved | - VariantFieldAdded | - VariantFieldRemoved | - VariantFieldStyleChanged { .. } | + VariantAdded | + VariantRemoved | + VariantFieldAdded { .. } | + VariantFieldRemoved { .. } | + VariantStyleChanged { .. } | FieldTypeChanged(_) | TraitImplItemAdded { .. } | TraitImplItemRemoved | diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 65b3fce2393a5..476e41bd67ffe 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -2,7 +2,7 @@ use semcheck::changes::BinaryChangeType; use semcheck::changes::BinaryChangeType::*; use semcheck::changes::ChangeSet; -use rustc::hir::def::Def; +use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def::Def::*; use rustc::hir::def::Export; use rustc::hir::def_id::DefId; @@ -105,7 +105,9 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { let mut c_new = cstore.item_children(new_did, tcx.sess); // TODO: refactor this to avoid storing tons of `Namespace` values. + // println!("old"); for child in c_old.drain(..) { + // println!(" {:?}", child.def.def_id()); let key = (get_namespace(&child.def), child.ident.name); children.entry(key).or_insert((None, None)).0 = Some(child); } @@ -191,21 +193,36 @@ fn diff_item_structures(changes: &mut ChangeSet, changes.add_binary(change_type, old_def_id, None); } - // TODO: crude dispatching logic for now (needs totality etc). + // TODO: extend as needed. match (old.def, new.def) { - (TyAlias(_), TyAlias(_)) | - (StructCtor(_, _), StructCtor(_, _)) => return, - (Struct(_), Struct(_)) | - (Union(_), Union(_)) | - (Enum(_), Enum(_)) | + // (matching) things we don't care about (for now) + (Mod(_), Mod(_)) | (Trait(_), Trait(_)) | + (TyAlias(_), TyAlias(_)) | + (AssociatedTy(_), AssociatedTy(_)) | + (PrimTy(_), PrimTy(_)) | + (TyParam(_), TyParam(_)) | + (SelfTy(_, _), SelfTy(_, _)) | (Fn(_), Fn(_)) | + (StructCtor(_, _), StructCtor(_, _)) | + (VariantCtor(_, _), VariantCtor(_, _)) | + (Method(_), Method(_)) | + (AssociatedConst(_), AssociatedConst(_)) | + (Local(_), Local(_)) | + (Upvar(_, _, _), Upvar(_, _, _)) | + (Label(_), Label(_)) | + (GlobalAsm(_), GlobalAsm(_)) | + (Macro(_, _), Macro(_, _)) | + (Variant(_), Variant(_)) | (Const(_), Const(_)) | (Static(_, _), Static(_, _)) | - (Method(_), Method(_)) | - (Macro(_, _), Macro(_, _)) => {}, + (Err, Err) => return, + // ADTs for now + (Struct(_), Struct(_)) | + (Union(_), Union(_)) | + (Enum(_), Enum(_)) => {}, + // non-matching item pair - register the difference and abort _ => { - // No match - so we don't need to look further. changes.add_binary(KindDifference, old_def_id, None); return; }, @@ -242,31 +259,63 @@ fn diff_item_structures(changes: &mut ChangeSet, fields.entry(field.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 = VariantStyleChanged { + now_struct: new.ctor_kind == CtorKind::Fictive, + total_private: total_private, + }; + changes.add_binary(c, old_def_id, Some(tcx.def_span(old.did))); + } + for (_, items2) in fields.drain() { - // TODO: visibility match items2 { (Some(o), Some(n)) => { id_mapping.add_item(o.did, n.did); + + if o.vis != Public && n.vis == Public { + changes.add_binary(ItemMadePublic, + old_def_id, + Some(tcx.def_span(o.did))); + } else if o.vis == Public && n.vis != Public { + changes.add_binary(ItemMadePrivate, + old_def_id, + Some(tcx.def_span(o.did))); + } }, (Some(o), None) => { - changes.add_binary(VariantFieldRemoved, - old_def_id, - Some(tcx.def_span(o.did))); + let c = VariantFieldRemoved { + public: o.vis == Public, + total_public: total_public + }; + changes.add_binary(c, old_def_id, Some(tcx.def_span(o.did))); }, (None, Some(n)) => { - changes.add_binary(VariantFieldAdded, - old_def_id, - Some(tcx.def_span(n.did))); + let c = VariantFieldRemoved { + public: n.vis == Public, + total_public: total_public + }; + changes.add_binary(c, old_def_id, Some(tcx.def_span(n.did))); }, (None, None) => unreachable!(), } } }, (Some(old), None) => { - changes.add_binary(EnumVariantRemoved, old_def_id, Some(tcx.def_span(old.did))); + changes.add_binary(VariantRemoved, old_def_id, Some(tcx.def_span(old.did))); }, (None, Some(new)) => { - changes.add_binary(EnumVariantAdded, old_def_id, Some(tcx.def_span(new.did))); + changes.add_binary(VariantAdded, old_def_id, Some(tcx.def_span(new.did))); }, (None, None) => unreachable!(), } From 8b712453d9e45f222c083d50137cd7178b4f9df8 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 21 Jun 2017 22:32:27 +0200 Subject: [PATCH 075/553] Shuffled some tests around --- tests/examples/addition.out | 34 ++++++++++++++++++---------------- tests/examples/addition.rs | 6 +++--- tests/examples/removal.out | 24 +++++++++++------------- tests/examples/removal.rs | 6 +++--- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/tests/examples/addition.out b/tests/examples/addition.out index b8fe6e6866d2f..1880483b93593 100644 --- a/tests/examples/addition.out +++ b/tests/examples/addition.out @@ -1,35 +1,37 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Removal of at least one path to `Cde` (Breaking) - --> $REPO_PATH/tests/examples/addition.rs:7:9 - | -7 | pub struct Cde; - | ^^^^^^^^^^^^^^^ - +version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 warning: Addition of at least one path to `Abc` (TechnicallyBreaking) - --> $REPO_PATH/tests/examples/addition.rs:12:5 + --> $REPO_PATH/tests/examples/addition.rs:11:5 | -12 | pub struct Abc; +11 | pub struct Abc; | ^^^^^^^^^^^^^^^ warning: TechnicallyBreaking changes in `Bcd` - --> $REPO_PATH/tests/examples/addition.rs:14:5 + --> $REPO_PATH/tests/examples/addition.rs:13:5 | -14 | pub struct Bcd; +13 | pub struct Bcd; | ^^^^^^^^^^^^^^^ | = note: TechnicallyBreaking (ItemMadePublic) warning: Addition of at least one path to `a` (TechnicallyBreaking) - --> $REPO_PATH/tests/examples/addition.rs:18:5 + --> $REPO_PATH/tests/examples/addition.rs:17:5 | -18 | } +17 | } | ^ warning: TechnicallyBreaking changes in `b` - --> $REPO_PATH/tests/examples/addition.rs:22:5 + --> $REPO_PATH/tests/examples/addition.rs:20:9 | -22 | } - | ^ +20 | / #[allow(dead_code)] +21 | | pub struct Cde; +22 | | } + | |_____^ | = note: TechnicallyBreaking (ItemMadePublic) +warning: Addition of at least one path to `Cde` (TechnicallyBreaking) + --> $REPO_PATH/tests/examples/addition.rs:21:9 + | +21 | pub struct Cde; + | ^^^^^^^^^^^^^^^ + diff --git a/tests/examples/addition.rs b/tests/examples/addition.rs index 5bcafc4c8b744..5f6ae15cec8a7 100644 --- a/tests/examples/addition.rs +++ b/tests/examples/addition.rs @@ -3,8 +3,7 @@ pub mod old { struct Bcd; mod b { - #[allow(dead_code)] - pub struct Cde; + } } @@ -18,6 +17,7 @@ pub mod new { } pub mod b { - + #[allow(dead_code)] + pub struct Cde; } } diff --git a/tests/examples/removal.out b/tests/examples/removal.out index 38a4860335977..9cb7b20a3fbe5 100644 --- a/tests/examples/removal.out +++ b/tests/examples/removal.out @@ -11,27 +11,25 @@ warning: Removal of at least one path to `a` (Breaking) 8 | } | ^ +warning: Removal of at least one path to `Cde` (Breaking) + --> $REPO_PATH/tests/examples/removal.rs:12:9 + | +12 | pub struct Cde; + | ^^^^^^^^^^^^^^^ + warning: Breaking changes in `Bcd` - --> $REPO_PATH/tests/examples/removal.rs:17:5 + --> $REPO_PATH/tests/examples/removal.rs:18:5 | -17 | struct Bcd; +18 | struct Bcd; | ^^^^^^^^^^^ | = warning: Breaking (ItemMadePrivate) warning: Breaking changes in `b` - --> $REPO_PATH/tests/examples/removal.rs:20:9 + --> $REPO_PATH/tests/examples/removal.rs:22:5 | -20 | / #[allow(dead_code)] -21 | | pub struct Cde; -22 | | } - | |_____^ +22 | } + | ^ | = warning: Breaking (ItemMadePrivate) -warning: Addition of at least one path to `Cde` (TechnicallyBreaking) - --> $REPO_PATH/tests/examples/removal.rs:21:9 - | -21 | pub struct Cde; - | ^^^^^^^^^^^^^^^ - diff --git a/tests/examples/removal.rs b/tests/examples/removal.rs index 3559f27f823a7..77f9cd2aa616c 100644 --- a/tests/examples/removal.rs +++ b/tests/examples/removal.rs @@ -8,7 +8,8 @@ pub mod old { } pub mod b { - + #[allow(dead_code)] + pub struct Cde; } } @@ -17,7 +18,6 @@ pub mod new { struct Bcd; mod b { - #[allow(dead_code)] - pub struct Cde; + } } From 21f88784067436c5757b4e55273719f2a1d9b6c2 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 21 Jun 2017 23:24:00 +0200 Subject: [PATCH 076/553] More tests --- src/semcheck/traverse.rs | 2 +- tests/examples/enum.out | 29 +++++++++++++++++ tests/examples/enum.rs | 19 +++++++++++ tests/examples/struct.out | 68 ++++++++++++++++++++++++++++++++++++--- tests/examples/struct.rs | 22 +++++++++++++ 5 files changed, 134 insertions(+), 6 deletions(-) create mode 100644 tests/examples/enum.out create mode 100644 tests/examples/enum.rs diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 476e41bd67ffe..3d1c1c655d0b7 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -301,7 +301,7 @@ fn diff_item_structures(changes: &mut ChangeSet, changes.add_binary(c, old_def_id, Some(tcx.def_span(o.did))); }, (None, Some(n)) => { - let c = VariantFieldRemoved { + let c = VariantFieldAdded { public: n.vis == Public, total_public: total_public }; diff --git a/tests/examples/enum.out b/tests/examples/enum.out new file mode 100644 index 0000000000000..a40373a1fdeec --- /dev/null +++ b/tests/examples/enum.out @@ -0,0 +1,29 @@ +version bump: 1.0.0 -> (Breaking) -> 2.0.0 +warning: Breaking changes in `Abc` + --> $REPO_PATH/tests/examples/enum.rs:12:5 + | +12 | / pub enum Abc { +13 | | Abc, +14 | | } + | |_____^ + | +warning: Breaking (VariantAdded) + --> $REPO_PATH/tests/examples/enum.rs:13:9 + | +13 | Abc, + | ^^^ + +warning: Breaking changes in `Bcd` + --> $REPO_PATH/tests/examples/enum.rs:16:5 + | +16 | / pub enum Bcd { +17 | | +18 | | } + | |_____^ + | +warning: Breaking (VariantRemoved) + --> $REPO_PATH/tests/examples/enum.rs:7:9 + | +7 | Abc, + | ^^^ + diff --git a/tests/examples/enum.rs b/tests/examples/enum.rs new file mode 100644 index 0000000000000..cf1c882d84c07 --- /dev/null +++ b/tests/examples/enum.rs @@ -0,0 +1,19 @@ +pub mod old { + pub enum Abc { + + } + + pub enum Bcd { + Abc, + } +} + +pub mod new { + pub enum Abc { + Abc, + } + + pub enum Bcd { + + } +} diff --git a/tests/examples/struct.out b/tests/examples/struct.out index 3426e03e80ed0..9099eedb59fb8 100644 --- a/tests/examples/struct.out +++ b/tests/examples/struct.out @@ -1,11 +1,69 @@ -version bump: 1.0.0 -> (NonBreaking) -> 1.1.0 +version bump: 1.0.0 -> (Breaking) -> 2.0.0 +warning: Removal of at least one path to `Hij` (Breaking) + --> $REPO_PATH/tests/examples/struct.rs:23:5 + | +23 | pub struct Hij(u8); + | ^^^^^^^^^^^^^^^^^^^ + warning: NonBreaking changes in `Def` - --> $REPO_PATH/tests/examples/struct.rs:22:5 + --> $REPO_PATH/tests/examples/struct.rs:32:5 | -22 | / pub struct Def { -23 | | field: A, -24 | | } +32 | / pub struct Def { +33 | | field: A, +34 | | } | |_____^ | = note: NonBreaking (TypeParameterAdded { defaulted: true }) +warning: TechnicallyBreaking changes in `Fgh` + --> $REPO_PATH/tests/examples/struct.rs:40:5 + | +40 | / pub struct Fgh { +41 | | pub field: u8, +42 | | } + | |_____^ + | +note: TechnicallyBreaking (ItemMadePublic) + --> $REPO_PATH/tests/examples/struct.rs:16:9 + | +16 | field: u8, + | ^^^^^^^^^ + +warning: Breaking changes in `Ghi` + --> $REPO_PATH/tests/examples/struct.rs:44:5 + | +44 | / pub struct Ghi { +45 | | field: u8, +46 | | } + | |_____^ + | +warning: Breaking (ItemMadePrivate) + --> $REPO_PATH/tests/examples/struct.rs:20:9 + | +20 | pub field: u8, + | ^^^^^^^^^^^^^ + +warning: Breaking changes in `Hij` + --> $REPO_PATH/tests/examples/struct.rs:48:5 + | +48 | / pub struct Hij { +49 | | field: u8, +50 | | } + | |_____^ + | +warning: Breaking (VariantFieldAdded { public: false, total_public: false }) + --> $REPO_PATH/tests/examples/struct.rs:49:9 + | +49 | field: u8, + | ^^^^^^^^^ +warning: Breaking (VariantFieldRemoved { public: false, total_public: false }) + --> $REPO_PATH/tests/examples/struct.rs:23:20 + | +23 | pub struct Hij(u8); + | ^^^ +warning: Breaking (VariantStyleChanged { now_struct: true, total_private: true }) + --> $REPO_PATH/tests/examples/struct.rs:23:5 + | +23 | pub struct Hij(u8); + | ^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/examples/struct.rs b/tests/examples/struct.rs index cf4d20c71648f..dae30374b25a7 100644 --- a/tests/examples/struct.rs +++ b/tests/examples/struct.rs @@ -11,6 +11,16 @@ pub mod old { pub struct Efg { pub field: u8, } + + pub struct Fgh { + field: u8, + } + + pub struct Ghi { + pub field: u8, + } + + pub struct Hij(u8); } #[allow(dead_code)] @@ -26,4 +36,16 @@ pub mod new { pub struct Efg { pub field: u16, } + + pub struct Fgh { + pub field: u8, + } + + pub struct Ghi { + field: u8, + } + + pub struct Hij { + field: u8, + } } From ba734db8820ed7b259b946a58b1833989294ccc9 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 22 Jun 2017 17:27:47 +0200 Subject: [PATCH 077/553] Finished implementation of private item traversal. --- src/semcheck/traverse.rs | 44 ++++++++++++++++++++++++++----------- tests/examples/addition.out | 24 ++++++++++---------- tests/examples/addition.rs | 9 ++++++++ tests/examples/removal.out | 8 +++---- tests/examples/removal.rs | 9 ++++++++ tests/examples/struct.out | 6 ----- 6 files changed, 65 insertions(+), 35 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 3d1c1c655d0b7..de2d1b1e8d8c7 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -98,16 +98,14 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { let mut children = HashMap::new(); let mut mod_queue = VecDeque::new(); - mod_queue.push_back((old, new)); + mod_queue.push_back((old, new, Public, Public)); - while let Some((old_did, new_did)) = mod_queue.pop_front() { + while let Some((old_did, new_did, old_vis, new_vis)) = mod_queue.pop_front() { let mut c_old = cstore.item_children(old_did, tcx.sess); let mut c_new = cstore.item_children(new_did, tcx.sess); // TODO: refactor this to avoid storing tons of `Namespace` values. - // println!("old"); for child in c_old.drain(..) { - // println!(" {:?}", child.def.def_id()); let key = (get_namespace(&child.def), child.ident.name); children.entry(key).or_insert((None, None)).0 = Some(child); } @@ -121,8 +119,16 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { match items { (Some(Export { def: Mod(o), .. }), Some(Export { def: Mod(n), .. })) => { if visited.insert((o, n)) { - let o_vis = cstore.visibility(o); - let n_vis = cstore.visibility(n); + let o_vis = if old_vis == Public { + cstore.visibility(o) + } else { + old_vis + }; + let n_vis = if new_vis == Public { + cstore.visibility(n) + } else { + new_vis + }; if o_vis != n_vis { // TODO: ugly @@ -135,13 +141,21 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { } } - mod_queue.push_back((o, n)); + mod_queue.push_back((o, n, o_vis, n_vis)); } } (Some(o), Some(n)) => { if !id_mapping.add_export(o, n) { - let o_vis = cstore.visibility(o.def.def_id()); - let n_vis = cstore.visibility(n.def.def_id()); + let o_vis = if old_vis == Public { + cstore.visibility(o.def.def_id()) + } else { + old_vis + }; + let n_vis = if new_vis == Public { + cstore.visibility(n.def.def_id()) + } else { + new_vis + }; let output = o_vis == Public || n_vis == Public; changes.new_binary(o, n, output); @@ -155,11 +169,15 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { diff_item_structures(&mut changes, &mut id_mapping, tcx, o, n); } } - (Some(old), None) => { - changes.new_removal(old); + (Some(o), None) => { + if old_vis == Public && cstore.visibility(o.def.def_id()) == Public { + changes.new_removal(o); + } } - (None, Some(new)) => { - changes.new_addition(new); + (None, Some(n)) => { + if new_vis == Public && cstore.visibility(n.def.def_id()) == Public { + changes.new_addition(n); + } } (None, None) => unreachable!(), } diff --git a/tests/examples/addition.out b/tests/examples/addition.out index 1880483b93593..a15f9f1e4212a 100644 --- a/tests/examples/addition.out +++ b/tests/examples/addition.out @@ -1,37 +1,37 @@ version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 warning: Addition of at least one path to `Abc` (TechnicallyBreaking) - --> $REPO_PATH/tests/examples/addition.rs:11:5 + --> $REPO_PATH/tests/examples/addition.rs:15:5 | -11 | pub struct Abc; +15 | pub struct Abc; | ^^^^^^^^^^^^^^^ warning: TechnicallyBreaking changes in `Bcd` - --> $REPO_PATH/tests/examples/addition.rs:13:5 + --> $REPO_PATH/tests/examples/addition.rs:17:5 | -13 | pub struct Bcd; +17 | pub struct Bcd; | ^^^^^^^^^^^^^^^ | = note: TechnicallyBreaking (ItemMadePublic) warning: Addition of at least one path to `a` (TechnicallyBreaking) - --> $REPO_PATH/tests/examples/addition.rs:17:5 + --> $REPO_PATH/tests/examples/addition.rs:21:5 | -17 | } +21 | } | ^ warning: TechnicallyBreaking changes in `b` - --> $REPO_PATH/tests/examples/addition.rs:20:9 + --> $REPO_PATH/tests/examples/addition.rs:24:9 | -20 | / #[allow(dead_code)] -21 | | pub struct Cde; -22 | | } +24 | / #[allow(dead_code)] +25 | | pub struct Cde; +26 | | } | |_____^ | = note: TechnicallyBreaking (ItemMadePublic) warning: Addition of at least one path to `Cde` (TechnicallyBreaking) - --> $REPO_PATH/tests/examples/addition.rs:21:9 + --> $REPO_PATH/tests/examples/addition.rs:25:9 | -21 | pub struct Cde; +25 | pub struct Cde; | ^^^^^^^^^^^^^^^ diff --git a/tests/examples/addition.rs b/tests/examples/addition.rs index 5f6ae15cec8a7..b0deed0ce1ea8 100644 --- a/tests/examples/addition.rs +++ b/tests/examples/addition.rs @@ -5,6 +5,10 @@ pub mod old { mod b { } + + mod c { + + } } pub mod new { @@ -20,4 +24,9 @@ pub mod new { #[allow(dead_code)] pub struct Cde; } + + mod c { + #[allow(dead_code)] + pub struct Def; + } } diff --git a/tests/examples/removal.out b/tests/examples/removal.out index 9cb7b20a3fbe5..d830637f69c78 100644 --- a/tests/examples/removal.out +++ b/tests/examples/removal.out @@ -18,17 +18,17 @@ warning: Removal of at least one path to `Cde` (Breaking) | ^^^^^^^^^^^^^^^ warning: Breaking changes in `Bcd` - --> $REPO_PATH/tests/examples/removal.rs:18:5 + --> $REPO_PATH/tests/examples/removal.rs:23:5 | -18 | struct Bcd; +23 | struct Bcd; | ^^^^^^^^^^^ | = warning: Breaking (ItemMadePrivate) warning: Breaking changes in `b` - --> $REPO_PATH/tests/examples/removal.rs:22:5 + --> $REPO_PATH/tests/examples/removal.rs:27:5 | -22 | } +27 | } | ^ | = warning: Breaking (ItemMadePrivate) diff --git a/tests/examples/removal.rs b/tests/examples/removal.rs index 77f9cd2aa616c..8082edc86287d 100644 --- a/tests/examples/removal.rs +++ b/tests/examples/removal.rs @@ -11,6 +11,11 @@ pub mod old { #[allow(dead_code)] pub struct Cde; } + + mod c { + #[allow(dead_code)] + pub struct Def; + } } pub mod new { @@ -20,4 +25,8 @@ pub mod new { mod b { } + + mod c { + + } } diff --git a/tests/examples/struct.out b/tests/examples/struct.out index 9099eedb59fb8..11bc3ddfe64a3 100644 --- a/tests/examples/struct.out +++ b/tests/examples/struct.out @@ -1,10 +1,4 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Removal of at least one path to `Hij` (Breaking) - --> $REPO_PATH/tests/examples/struct.rs:23:5 - | -23 | pub struct Hij(u8); - | ^^^^^^^^^^^^^^^^^^^ - warning: NonBreaking changes in `Def` --> $REPO_PATH/tests/examples/struct.rs:32:5 | From dde41248c0f35632b617c1ef6ca16b3dd0d7fad7 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 24 Jun 2017 12:17:23 +0200 Subject: [PATCH 078/553] Some renaming and restructuring work. --- src/semcheck/traverse.rs | 105 ++++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 50 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index de2d1b1e8d8c7..c79b4a39c8679 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -146,13 +146,15 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { } (Some(o), Some(n)) => { if !id_mapping.add_export(o, n) { + let o_def_id = o.def.def_id(); + let n_def_id = n.def.def_id(); let o_vis = if old_vis == Public { - cstore.visibility(o.def.def_id()) + cstore.visibility(o_def_id) } else { old_vis }; let n_vis = if new_vis == Public { - cstore.visibility(n.def.def_id()) + cstore.visibility(n_def_id) } else { new_vis }; @@ -161,12 +163,58 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { changes.new_binary(o, n, output); if o_vis == Public && n_vis != Public { - changes.add_binary(ItemMadePrivate, o.def.def_id(), None); + changes.add_binary(ItemMadePrivate, o_def_id, None); } else if o_vis != Public && n_vis == Public { - changes.add_binary(ItemMadePublic, o.def.def_id(), None); + changes.add_binary(ItemMadePublic, o_def_id, None); } - diff_item_structures(&mut changes, &mut id_mapping, tcx, o, n); + // TODO: extend as needed. + match (o.def, n.def) { + // (matching) things we don't care about (for now) + (Mod(_), Mod(_)) | + (Trait(_), Trait(_)) | + (AssociatedTy(_), AssociatedTy(_)) | + (PrimTy(_), PrimTy(_)) | + (TyParam(_), TyParam(_)) | + (SelfTy(_, _), SelfTy(_, _)) | + (Fn(_), Fn(_)) | + (StructCtor(_, _), StructCtor(_, _)) | + (VariantCtor(_, _), VariantCtor(_, _)) | + (Method(_), Method(_)) | + (AssociatedConst(_), AssociatedConst(_)) | + (Local(_), Local(_)) | + (Upvar(_, _, _), Upvar(_, _, _)) | + (Label(_), Label(_)) | + (GlobalAsm(_), GlobalAsm(_)) | + (Macro(_, _), Macro(_, _)) | + (Variant(_), Variant(_)) | + (Const(_), Const(_)) | + (Static(_, _), Static(_, _)) | + (Err, Err) => {}, + (TyAlias(_), TyAlias(_)) => { + let mut generics_changes = + diff_generics(tcx, o_def_id, n_def_id); + for change_type in generics_changes.drain(..) { + changes.add_binary(change_type, o_def_id, None); + } + }, + // ADTs for now + (Struct(_), Struct(_)) | + (Union(_), Union(_)) | + (Enum(_), Enum(_)) => { + let mut generics_changes = + diff_generics(tcx, o_def_id, n_def_id); + for change_type in generics_changes.drain(..) { + changes.add_binary(change_type, o_def_id, None); + } + + diff_adts(&mut changes, &mut id_mapping, tcx, o, n); + }, + // non-matching item pair - register the difference and abort + _ => { + changes.add_binary(KindDifference, o_def_id, None); + }, + } } } (Some(o), None) => { @@ -191,14 +239,11 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { changes } -/// Given two items, perform *structural* checks. +/// Given two ADT items, perform *structural* checks. /// /// This establishes the needed correspondence relationship between non-toplevel items. /// For instance, struct fields, enum variants etc. are matched up against each other here. -/// -/// If the two items can't be meaningfully compared because they are of different kinds, -/// we return that difference directly. -fn diff_item_structures(changes: &mut ChangeSet, +fn diff_adts(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, old: Export, @@ -206,46 +251,6 @@ fn diff_item_structures(changes: &mut ChangeSet, let old_def_id = old.def.def_id(); let new_def_id = new.def.def_id(); - let mut generics_changes = diff_generics(tcx, old_def_id, new_def_id); - for change_type in generics_changes.drain(..) { - changes.add_binary(change_type, old_def_id, None); - } - - // TODO: extend as needed. - match (old.def, new.def) { - // (matching) things we don't care about (for now) - (Mod(_), Mod(_)) | - (Trait(_), Trait(_)) | - (TyAlias(_), TyAlias(_)) | - (AssociatedTy(_), AssociatedTy(_)) | - (PrimTy(_), PrimTy(_)) | - (TyParam(_), TyParam(_)) | - (SelfTy(_, _), SelfTy(_, _)) | - (Fn(_), Fn(_)) | - (StructCtor(_, _), StructCtor(_, _)) | - (VariantCtor(_, _), VariantCtor(_, _)) | - (Method(_), Method(_)) | - (AssociatedConst(_), AssociatedConst(_)) | - (Local(_), Local(_)) | - (Upvar(_, _, _), Upvar(_, _, _)) | - (Label(_), Label(_)) | - (GlobalAsm(_), GlobalAsm(_)) | - (Macro(_, _), Macro(_, _)) | - (Variant(_), Variant(_)) | - (Const(_), Const(_)) | - (Static(_, _), Static(_, _)) | - (Err, Err) => return, - // ADTs for now - (Struct(_), Struct(_)) | - (Union(_), Union(_)) | - (Enum(_), Enum(_)) => {}, - // non-matching item pair - register the difference and abort - _ => { - changes.add_binary(KindDifference, old_def_id, None); - return; - }, - } - let (old_def, new_def) = match (old.def, new.def) { (Struct(_), Struct(_)) | (Union(_), Union(_)) | From de1289e194545db8c2c699b19a1012708893abcd Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 25 Jun 2017 17:57:02 +0200 Subject: [PATCH 079/553] First draft for a mismatch-inference TypeRelation --- src/semcheck/traverse.rs | 81 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index c79b4a39c8679..77d625e0a3726 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -6,9 +6,11 @@ use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def::Def::*; use rustc::hir::def::Export; use rustc::hir::def_id::DefId; -use rustc::ty::TyCtxt; +use rustc::ty; +use rustc::ty::{Ty, TyCtxt}; use rustc::ty::Visibility::Public; use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; +use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc::ty::subst::{Subst, Substs}; use std::collections::{HashMap, HashSet, VecDeque}; @@ -232,6 +234,16 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { } } + for &(_, old, new) in id_mapping.toplevel_mapping.values() { + let mut mismatch = Mismatch { + tcx: tcx, + toplevel_mapping: &id_mapping.toplevel_mapping, + mapping: &mut id_mapping.mapping, + }; + + let _ = mismatch.tys(tcx.type_of(old.def.def_id()), tcx.type_of(new.def.def_id())); + } + for &(_, old, new) in id_mapping.toplevel_mapping.values() { diff_items(&mut changes, &id_mapping, tcx, old, new); } @@ -239,6 +251,73 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { changes } +struct Mismatch<'a, 'gcx: 'a + 'tcx, 'tcx: 'a, A: 'a> { + tcx: TyCtxt<'a, 'gcx, 'tcx>, + toplevel_mapping: &'a HashMap, + mapping: &'a mut HashMap, +} + +impl<'a, 'gcx, 'tcx, A: 'a> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx, A> { + fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { + self.tcx + } + + fn tag(&self) -> &'static str { + "Mismatch" + } + + fn a_is_expected(&self) -> bool { + true + } + + fn relate_with_variance>(&mut self, + _: ty::Variance, + a: &T, + b: &T) + -> RelateResult<'tcx, T> { + self.relate(a, b) + } + + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + use rustc::ty::TypeVariants::*; + + let matching = match (&a.sty, &b.sty) { + (&TyAdt(a_adt, _), &TyAdt(b_adt, _)) => Some((a_adt.did, b_adt.did)), + (&TyFnDef(a_did, _, _), &TyFnDef(b_did, _, _)) => Some((a_did, b_did)), + (&TyClosure(a_did, _), &TyClosure(b_did, _)) => Some((a_did, b_did)), + (&TyProjection(a_proj), &TyProjection(b_proj)) => + Some((a_proj.trait_ref.def_id, b_proj.trait_ref.def_id)), + (&TyAnon(a_did, _), &TyAnon(b_did, _)) => Some((a_did, b_did)), + _ => None, + }; + + if let Some((old_did, new_did)) = matching { + if !self.toplevel_mapping.contains_key(&old_did) && + !self.mapping.contains_key(&old_did) + { + println!("adding mapping: {:?} => {:?}", old_did, new_did); + self.mapping.insert(old_did, new_did); + } + } + + ty::relate::super_relate_tys(self, a, b) + } + + fn regions(&mut self, a: ty::Region<'tcx>, _: ty::Region<'tcx>) + -> RelateResult<'tcx, ty::Region<'tcx>> + { + // TODO + Ok(a) + } + + fn binders>(&mut self, a: &ty::Binder, _: &ty::Binder) + -> RelateResult<'tcx, ty::Binder> + { + // TODO + Ok(a.clone()) + } +} + /// Given two ADT items, perform *structural* checks. /// /// This establishes the needed correspondence relationship between non-toplevel items. From 28a02091973d19e823a7e07a8593a3b6a8b41c66 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 26 Jun 2017 14:08:51 +0200 Subject: [PATCH 080/553] Added env dumping to the test runner. --- tests/examples.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/examples.rs b/tests/examples.rs index 44b9ff35eca0f..3d12ac8cbcbba 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -1,3 +1,4 @@ +#![feature(pattern)] use std::env; use std::fs::File; use std::io::Write; @@ -6,6 +7,8 @@ use std::process::{Command, Stdio}; #[test] fn examples() { + use std::str::pattern::Pattern; + let mut success = true; let current_dir = env::current_dir().expect("could not determine current dir"); @@ -88,5 +91,15 @@ fn examples() { .status() .expect("could not run rm"); + if !success { + println!(); + for (name, value) in env::vars() { + // filter some crap *my* less puts there, rendering the terminal in a bright green :) + if !"LESS".is_contained_in(&name) { + println!("{}={}", name, value); + } + } + } + assert!(success, "an error occured"); } From 8bb178e0140b8a2452ea4d3b5ca2d8fbeb31ade0 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 26 Jun 2017 14:31:35 +0200 Subject: [PATCH 081/553] Implemented inference for mismatches. Using a custom TypeRelation implementation, types that are not exported by both crate versions can be inferred to be the same item, regardless of possible name changes. Next steps include: * implementing similar capabilities for trait bounds, * amending the existing implementation to account for corner cases we might have missed, * restructuring the code for more compartmentarization, it's got real bad lately. --- src/semcheck/traverse.rs | 161 ++++++++++++++++++++++++++++++++++----- tests/examples/infer.out | 21 +++++ tests/examples/infer.rs | 43 +++++++++++ 3 files changed, 207 insertions(+), 18 deletions(-) create mode 100644 tests/examples/infer.out create mode 100644 tests/examples/infer.rs diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 77d625e0a3726..6f00421b072aa 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -3,12 +3,12 @@ use semcheck::changes::BinaryChangeType::*; use semcheck::changes::ChangeSet; use rustc::hir::def::{Def, CtorKind}; -use rustc::hir::def::Def::*; use rustc::hir::def::Export; use rustc::hir::def_id::DefId; use rustc::ty; use rustc::ty::{Ty, TyCtxt}; use rustc::ty::Visibility::Public; +use rustc::ty::error::TypeError; use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc::ty::subst::{Subst, Substs}; @@ -59,6 +59,8 @@ enum Namespace { } fn get_namespace(def: &Def) -> Namespace { + use rustc::hir::def::Def::*; + match *def { Mod(_) | Struct(_) | @@ -93,6 +95,8 @@ fn get_namespace(def: &Def) -> Namespace { /// Matching children get processed in the same fashion. // TODO: describe the passes we do. pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { + use rustc::hir::def::Def::*; + let cstore = &tcx.sess.cstore; let mut changes = ChangeSet::default(); let mut id_mapping = IdMapping::default(); @@ -235,13 +239,20 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { } for &(_, old, new) in id_mapping.toplevel_mapping.values() { - let mut mismatch = Mismatch { - tcx: tcx, - toplevel_mapping: &id_mapping.toplevel_mapping, - mapping: &mut id_mapping.mapping, - }; + let old_did = old.def.def_id(); + let new_did = new.def.def_id(); + + { + let mut mismatch = Mismatch { + tcx: tcx, + toplevel_mapping: &id_mapping.toplevel_mapping, + mapping: &mut id_mapping.mapping, + }; - let _ = mismatch.tys(tcx.type_of(old.def.def_id()), tcx.type_of(new.def.def_id())); + let _ = mismatch.tys(tcx.type_of(old_did), tcx.type_of(new_did)); + } + + diff_bounds(&mut changes, tcx, old_did, new_did); } for &(_, old, new) in id_mapping.toplevel_mapping.values() { @@ -251,6 +262,17 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { changes } +fn diff_bounds(_changes: &mut ChangeSet, _tcx: TyCtxt, _old: DefId, _new: DefId) + -> (Vec, Vec<(DefId, DefId)>) +{ + let res = Default::default(); + + // let old_preds = tcx.predicates_of(old).predicates; + // let new_preds = tcx.predicates_of(new).predicates; + + res +} + struct Mismatch<'a, 'gcx: 'a + 'tcx, 'tcx: 'a, A: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, toplevel_mapping: &'a HashMap, @@ -278,6 +300,10 @@ impl<'a, 'gcx, 'tcx, A: 'a> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, self.relate(a, b) } + fn relate>(&mut self, a: &T, b: &T) -> RelateResult<'tcx, T> { + Relate::relate(self, a, b) + } + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { use rustc::ty::TypeVariants::*; @@ -288,19 +314,21 @@ impl<'a, 'gcx, 'tcx, A: 'a> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, (&TyProjection(a_proj), &TyProjection(b_proj)) => Some((a_proj.trait_ref.def_id, b_proj.trait_ref.def_id)), (&TyAnon(a_did, _), &TyAnon(b_did, _)) => Some((a_did, b_did)), - _ => None, + _ => { + None + }, }; if let Some((old_did, new_did)) = matching { if !self.toplevel_mapping.contains_key(&old_did) && !self.mapping.contains_key(&old_did) { - println!("adding mapping: {:?} => {:?}", old_did, new_did); + // println!("adding mapping: {:?} => {:?}", old_did, new_did); self.mapping.insert(old_did, new_did); } } - ty::relate::super_relate_tys(self, a, b) + relate_tys_mismatch(self, a, b) } fn regions(&mut self, a: ty::Region<'tcx>, _: ty::Region<'tcx>) @@ -310,11 +338,106 @@ impl<'a, 'gcx, 'tcx, A: 'a> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, Ok(a) } - fn binders>(&mut self, a: &ty::Binder, _: &ty::Binder) + fn binders>(&mut self, a: &ty::Binder, b: &ty::Binder) -> RelateResult<'tcx, ty::Binder> { - // TODO - Ok(a.clone()) + Ok(ty::Binder(self.relate(a.skip_binder(), b.skip_binder())?)) + } +} +fn relate_tys_mismatch<'a, 'gcx, 'tcx, R>(relation: &mut R, a: Ty<'tcx>, b: Ty<'tcx>) + -> RelateResult<'tcx, Ty<'tcx>> + where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a +{ + use rustc::ty::TypeVariants::*; + + let tcx = relation.tcx(); + let a_sty = &a.sty; + let b_sty = &b.sty; + match (a_sty, b_sty) { + (&TyInfer(_), _) | (_, &TyInfer(_)) => { + // As the original function this is ripped off of, we don't handle these cases. + panic!("var types encountered in relate_tys_mismatch") + }, + (&TyError, _) | (_, &TyError) => { + Ok(tcx.types.err) + }, + (&TyNever, _) | + (&TyChar, _) | + (&TyBool, _) | + (&TyInt(_), _) | + (&TyUint(_), _) | + (&TyFloat(_), _) | + (&TyStr, _) | + (&TyParam(_), _) | + (&TyClosure(_, _), _) if a == b => { + Ok(a) + }, + (&TyAdt(a_def, a_substs), &TyAdt(_, b_substs)) => { + // TODO: possibly do something here + let substs = relation.relate_item_substs(a_def.did, a_substs, b_substs)?; + Ok(tcx.mk_adt(a_def, substs)) + }, + (&TyDynamic(_, _), &TyDynamic(_, _)) => { + // TODO: decide whether this is needed + /*let region_bound = relation.with_cause(Cause::ExistentialRegionBound, + |relation| { + relation.relate(a_region, b_region) + })?; + Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound))*/ + Err(TypeError::Mismatch) + }, + (&TyRawPtr(ref a_mt), &TyRawPtr(ref b_mt)) => { + let mt = relation.relate(a_mt, b_mt)?; + Ok(tcx.mk_ptr(mt)) + }, + (&TyRef(ref a_r, ref a_mt), &TyRef(ref b_r, ref b_mt)) => { + let r = relation.relate(a_r, b_r)?; + let mt = relation.relate(a_mt, b_mt)?; + Ok(tcx.mk_ref(r, mt)) + }, + (&TyArray(a_t, sz_a), &TyArray(b_t, sz_b)) => { + let t = relation.relate(&a_t, &b_t)?; + if sz_a == sz_b { + Ok(tcx.mk_array(t, sz_a)) + } else { + Err(TypeError::Mismatch) + } + }, + (&TySlice(a_t), &TySlice(b_t)) => { + let t = relation.relate(&a_t, &b_t)?; + Ok(tcx.mk_slice(t)) + }, + (&TyTuple(as_, a_defaulted), &TyTuple(bs, b_defaulted)) => { + let rs = as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)); + if as_.len() == bs.len() { + let defaulted = a_defaulted || b_defaulted; + tcx.mk_tup(rs, defaulted) + } else if !(as_.is_empty() || bs.is_empty()) { + Err(TypeError::Mismatch) + } else { + Err(TypeError::Mismatch) + } + }, + (&TyFnDef(a_def_id, a_substs, a_fty), &TyFnDef(_, b_substs, b_fty)) => { + let substs = ty::relate::relate_substs(relation, None, a_substs, b_substs)?; + let fty = relation.relate(&a_fty, &b_fty)?; + Ok(tcx.mk_fn_def(a_def_id, substs, fty)) + }, + (&TyFnPtr(a_fty), &TyFnPtr(b_fty)) => { + let fty = relation.relate(&a_fty, &b_fty)?; + Ok(tcx.mk_fn_ptr(fty)) + }, + (&TyProjection(ref a_data), &TyProjection(ref b_data)) => { + let projection_ty = relation.relate(a_data, b_data)?; + Ok(tcx.mk_projection(projection_ty.trait_ref, projection_ty.item_name(tcx))) + }, + (&TyAnon(a_def_id, a_substs), &TyAnon(_, b_substs)) => { + let substs = ty::relate::relate_substs(relation, None, a_substs, b_substs)?; + Ok(tcx.mk_anon(a_def_id, substs)) + }, + _ => { + Err(TypeError::Mismatch) + } } } @@ -323,10 +446,12 @@ impl<'a, 'gcx, 'tcx, A: 'a> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, /// This establishes the needed correspondence relationship between non-toplevel items. /// For instance, struct fields, enum variants etc. are matched up against each other here. fn diff_adts(changes: &mut ChangeSet, - id_mapping: &mut IdMapping, - tcx: TyCtxt, - old: Export, - new: Export) { + id_mapping: &mut IdMapping, + tcx: TyCtxt, + old: Export, + new: Export) { + use rustc::hir::def::Def::*; + let old_def_id = old.def.def_id(); let new_def_id = new.def.def_id(); @@ -460,7 +585,7 @@ fn diff_types(id_mapping: &IdMapping, tcx: TyCtxt, old: DefId, new: DefId) TyAdt(&AdtDef { ref did, .. }, substs) => { let new_did = id_mapping.get_new_id(*did); let new_adt = tcx.adt_def(new_did); - tcx.mk_adt(new_adt, substs) // TODO: error if mismatch? + tcx.mk_adt(new_adt, substs) }, /* TyDynamic(predicates, region) => { diff --git a/tests/examples/infer.out b/tests/examples/infer.out new file mode 100644 index 0000000000000..b58a299acde3f --- /dev/null +++ b/tests/examples/infer.out @@ -0,0 +1,21 @@ +version bump: 1.0.0 -> (Breaking) -> 2.0.0 +warning: Breaking changes in `a` + --> $REPO_PATH/tests/examples/infer.rs:32:5 + | +32 | / pub fn a(a: A) -> A { +33 | | a +34 | | } + | |_____^ + | + = warning: Breaking (FieldTypeChanged("expected fn item, found a different fn item")) + +warning: Breaking changes in `b` + --> $REPO_PATH/tests/examples/infer.rs:36:5 + | +36 | / pub fn b() -> a::Opq { +37 | | a::Opq +38 | | } + | |_____^ + | + = warning: Breaking (FieldTypeChanged("expected fn item, found a different fn item")) + diff --git a/tests/examples/infer.rs b/tests/examples/infer.rs new file mode 100644 index 0000000000000..0eded7bf8ff5d --- /dev/null +++ b/tests/examples/infer.rs @@ -0,0 +1,43 @@ +pub mod old { + mod a { + pub trait Abc { + + } + + pub struct Klm; + } + + pub fn a(a: A) -> A { + a + } + + pub fn b() -> a::Klm { + a::Klm + } + + pub struct Hij { + pub field: Box, + } +} + +pub mod new { + mod a { + pub trait Def { + + } + + pub struct Opq; + } + + pub fn a(a: A) -> A { + a + } + + pub fn b() -> a::Opq { + a::Opq + } + + pub struct Hij { + pub field: Box, + } +} From ef0706173bd7fc8698c252b4e9996d80dea77aa5 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 26 Jun 2017 15:49:36 +0200 Subject: [PATCH 082/553] Some restructuring and doc changes. --- src/semcheck/mismatch.rs | 188 +++++++++++++++++++++++++++++ src/semcheck/mod.rs | 1 + src/semcheck/traverse.rs | 252 +++++++-------------------------------- 3 files changed, 230 insertions(+), 211 deletions(-) create mode 100644 src/semcheck/mismatch.rs diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs new file mode 100644 index 0000000000000..a086398e06982 --- /dev/null +++ b/src/semcheck/mismatch.rs @@ -0,0 +1,188 @@ +use rustc::hir::def_id::DefId; +use rustc::ty; +use rustc::ty::{Ty, TyCtxt}; +use rustc::ty::error::TypeError; +use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; + +use std::collections::HashMap; + +/// 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. +pub struct Mismatch<'a, 'gcx: 'a + 'tcx, 'tcx: 'a, A: 'a> { + /// The type context used. + pub tcx: TyCtxt<'a, 'gcx, 'tcx>, + /// The mapping of toplevel items. + pub toplevel_mapping: &'a HashMap, + /// The mapping of all other items. + pub mapping: &'a mut HashMap, +} + +impl<'a, 'gcx, 'tcx, A: 'a> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx, A> { + fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { + self.tcx + } + + fn tag(&self) -> &'static str { + "Mismatch" + } + + fn a_is_expected(&self) -> bool { + true + } + + fn relate_with_variance>(&mut self, + _: ty::Variance, + a: &T, + b: &T) + -> RelateResult<'tcx, T> { + self.relate(a, b) + } + + fn relate>(&mut self, a: &T, b: &T) -> RelateResult<'tcx, T> { + Relate::relate(self, a, b) + } + + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + use rustc::ty::TypeVariants::*; + + let matching = match (&a.sty, &b.sty) { + (&TyAdt(a_adt, _), &TyAdt(b_adt, _)) => Some((a_adt.did, b_adt.did)), + (&TyFnDef(a_did, _, _), &TyFnDef(b_did, _, _)) => Some((a_did, b_did)), + (&TyClosure(a_did, _), &TyClosure(b_did, _)) => Some((a_did, b_did)), + (&TyProjection(a_proj), &TyProjection(b_proj)) => + Some((a_proj.trait_ref.def_id, b_proj.trait_ref.def_id)), + (&TyAnon(a_did, _), &TyAnon(b_did, _)) => Some((a_did, b_did)), + _ => { + None + }, + }; + + if let Some((old_did, new_did)) = matching { + if !self.toplevel_mapping.contains_key(&old_did) && + !self.mapping.contains_key(&old_did) + { + // println!("adding mapping: {:?} => {:?}", old_did, new_did); + self.mapping.insert(old_did, new_did); + } + } + + relate_tys_mismatch(self, a, b) + } + + fn regions(&mut self, a: ty::Region<'tcx>, _: ty::Region<'tcx>) + -> RelateResult<'tcx, ty::Region<'tcx>> + { + // TODO + Ok(a) + } + + fn binders>(&mut self, a: &ty::Binder, b: &ty::Binder) + -> RelateResult<'tcx, ty::Binder> + { + Ok(ty::Binder(self.relate(a.skip_binder(), b.skip_binder())?)) + } +} + +/// Relate two items after possible matches have been recorded. +/// +/// This assumes the usage of the `Mismatch` type relation. The parametrization is used for +/// implementation-internal reasons. +fn relate_tys_mismatch<'a, 'gcx, 'tcx, R>(relation: &mut R, a: Ty<'tcx>, b: Ty<'tcx>) + -> RelateResult<'tcx, Ty<'tcx>> + where 'gcx: 'a+'tcx, 'tcx: 'a, R: TypeRelation<'a, 'gcx, 'tcx> +{ + use rustc::ty::TypeVariants::*; + + let tcx = relation.tcx(); + let a_sty = &a.sty; + let b_sty = &b.sty; + match (a_sty, b_sty) { + (&TyInfer(_), _) | (_, &TyInfer(_)) => { + // As the original function this is ripped off of, we don't handle these cases. + panic!("var types encountered in relate_tys_mismatch") + }, + (&TyError, _) | (_, &TyError) => { + Ok(tcx.types.err) + }, + (&TyNever, _) | + (&TyChar, _) | + (&TyBool, _) | + (&TyInt(_), _) | + (&TyUint(_), _) | + (&TyFloat(_), _) | + (&TyStr, _) | + (&TyParam(_), _) | + (&TyClosure(_, _), _) if a == b => { + Ok(a) + }, + (&TyAdt(a_def, a_substs), &TyAdt(_, b_substs)) => { + // TODO: possibly do something here + let substs = relation.relate_item_substs(a_def.did, a_substs, b_substs)?; + Ok(tcx.mk_adt(a_def, substs)) + }, + (&TyDynamic(_, _), &TyDynamic(_, _)) => { + // TODO: decide whether this is needed + /*let region_bound = relation.with_cause(Cause::ExistentialRegionBound, + |relation| { + relation.relate(a_region, b_region) + })?; + Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound))*/ + Err(TypeError::Mismatch) + }, + (&TyRawPtr(ref a_mt), &TyRawPtr(ref b_mt)) => { + let mt = relation.relate(a_mt, b_mt)?; + Ok(tcx.mk_ptr(mt)) + }, + (&TyRef(ref a_r, ref a_mt), &TyRef(ref b_r, ref b_mt)) => { + let r = relation.relate(a_r, b_r)?; + let mt = relation.relate(a_mt, b_mt)?; + Ok(tcx.mk_ref(r, mt)) + }, + (&TyArray(a_t, sz_a), &TyArray(b_t, sz_b)) => { + let t = relation.relate(&a_t, &b_t)?; + if sz_a == sz_b { + Ok(tcx.mk_array(t, sz_a)) + } else { + Err(TypeError::Mismatch) + } + }, + (&TySlice(a_t), &TySlice(b_t)) => { + let t = relation.relate(&a_t, &b_t)?; + Ok(tcx.mk_slice(t)) + }, + (&TyTuple(as_, a_defaulted), &TyTuple(bs, b_defaulted)) => { + let rs = as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)); + if as_.len() == bs.len() { + let defaulted = a_defaulted || b_defaulted; + tcx.mk_tup(rs, defaulted) + } else if !(as_.is_empty() || bs.is_empty()) { + Err(TypeError::Mismatch) + } else { + Err(TypeError::Mismatch) + } + }, + (&TyFnDef(a_def_id, a_substs, a_fty), &TyFnDef(_, b_substs, b_fty)) => { + let substs = ty::relate::relate_substs(relation, None, a_substs, b_substs)?; + let fty = relation.relate(&a_fty, &b_fty)?; + Ok(tcx.mk_fn_def(a_def_id, substs, fty)) + }, + (&TyFnPtr(a_fty), &TyFnPtr(b_fty)) => { + let fty = relation.relate(&a_fty, &b_fty)?; + Ok(tcx.mk_fn_ptr(fty)) + }, + (&TyProjection(ref a_data), &TyProjection(ref b_data)) => { + let projection_ty = relation.relate(a_data, b_data)?; + Ok(tcx.mk_projection(projection_ty.trait_ref, projection_ty.item_name(tcx))) + }, + (&TyAnon(a_def_id, a_substs), &TyAnon(_, b_substs)) => { + let substs = ty::relate::relate_substs(relation, None, a_substs, b_substs)?; + Ok(tcx.mk_anon(a_def_id, substs)) + }, + _ => { + Err(TypeError::Mismatch) + } + } +} diff --git a/src/semcheck/mod.rs b/src/semcheck/mod.rs index 1198e839aeb52..4c4ecf543057a 100644 --- a/src/semcheck/mod.rs +++ b/src/semcheck/mod.rs @@ -1,2 +1,3 @@ pub mod changes; +mod mismatch; pub mod traverse; diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 6f00421b072aa..e8466dd568b96 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -1,16 +1,15 @@ use semcheck::changes::BinaryChangeType; use semcheck::changes::BinaryChangeType::*; use semcheck::changes::ChangeSet; +use semcheck::mismatch::Mismatch; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def::Export; use rustc::hir::def_id::DefId; -use rustc::ty; -use rustc::ty::{Ty, TyCtxt}; +use rustc::ty::TyCtxt; use rustc::ty::Visibility::Public; -use rustc::ty::error::TypeError; use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; -use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; +use rustc::ty::relate::TypeRelation; use rustc::ty::subst::{Subst, Substs}; use std::collections::{HashMap, HashSet, VecDeque}; @@ -50,14 +49,20 @@ impl IdMapping { } } +/// A representation of a namespace an item belongs to. #[derive(PartialEq, Eq, Hash)] enum Namespace { + /// The type namespace. Type, + /// The value namespace. Value, + /// The macro namespace. Macro, + /// No namespace, so to say. Err, } +/// Get an item's namespace. fn get_namespace(def: &Def) -> Namespace { use rustc::hir::def::Def::*; @@ -256,192 +261,13 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { } for &(_, old, new) in id_mapping.toplevel_mapping.values() { - diff_items(&mut changes, &id_mapping, tcx, old, new); + diff_types(&mut changes, &id_mapping, tcx, old, new); } changes } -fn diff_bounds(_changes: &mut ChangeSet, _tcx: TyCtxt, _old: DefId, _new: DefId) - -> (Vec, Vec<(DefId, DefId)>) -{ - let res = Default::default(); - - // let old_preds = tcx.predicates_of(old).predicates; - // let new_preds = tcx.predicates_of(new).predicates; - - res -} - -struct Mismatch<'a, 'gcx: 'a + 'tcx, 'tcx: 'a, A: 'a> { - tcx: TyCtxt<'a, 'gcx, 'tcx>, - toplevel_mapping: &'a HashMap, - mapping: &'a mut HashMap, -} - -impl<'a, 'gcx, 'tcx, A: 'a> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx, A> { - fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { - self.tcx - } - - fn tag(&self) -> &'static str { - "Mismatch" - } - - fn a_is_expected(&self) -> bool { - true - } - - fn relate_with_variance>(&mut self, - _: ty::Variance, - a: &T, - b: &T) - -> RelateResult<'tcx, T> { - self.relate(a, b) - } - - fn relate>(&mut self, a: &T, b: &T) -> RelateResult<'tcx, T> { - Relate::relate(self, a, b) - } - - fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { - use rustc::ty::TypeVariants::*; - - let matching = match (&a.sty, &b.sty) { - (&TyAdt(a_adt, _), &TyAdt(b_adt, _)) => Some((a_adt.did, b_adt.did)), - (&TyFnDef(a_did, _, _), &TyFnDef(b_did, _, _)) => Some((a_did, b_did)), - (&TyClosure(a_did, _), &TyClosure(b_did, _)) => Some((a_did, b_did)), - (&TyProjection(a_proj), &TyProjection(b_proj)) => - Some((a_proj.trait_ref.def_id, b_proj.trait_ref.def_id)), - (&TyAnon(a_did, _), &TyAnon(b_did, _)) => Some((a_did, b_did)), - _ => { - None - }, - }; - - if let Some((old_did, new_did)) = matching { - if !self.toplevel_mapping.contains_key(&old_did) && - !self.mapping.contains_key(&old_did) - { - // println!("adding mapping: {:?} => {:?}", old_did, new_did); - self.mapping.insert(old_did, new_did); - } - } - - relate_tys_mismatch(self, a, b) - } - - fn regions(&mut self, a: ty::Region<'tcx>, _: ty::Region<'tcx>) - -> RelateResult<'tcx, ty::Region<'tcx>> - { - // TODO - Ok(a) - } - - fn binders>(&mut self, a: &ty::Binder, b: &ty::Binder) - -> RelateResult<'tcx, ty::Binder> - { - Ok(ty::Binder(self.relate(a.skip_binder(), b.skip_binder())?)) - } -} -fn relate_tys_mismatch<'a, 'gcx, 'tcx, R>(relation: &mut R, a: Ty<'tcx>, b: Ty<'tcx>) - -> RelateResult<'tcx, Ty<'tcx>> - where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a -{ - use rustc::ty::TypeVariants::*; - - let tcx = relation.tcx(); - let a_sty = &a.sty; - let b_sty = &b.sty; - match (a_sty, b_sty) { - (&TyInfer(_), _) | (_, &TyInfer(_)) => { - // As the original function this is ripped off of, we don't handle these cases. - panic!("var types encountered in relate_tys_mismatch") - }, - (&TyError, _) | (_, &TyError) => { - Ok(tcx.types.err) - }, - (&TyNever, _) | - (&TyChar, _) | - (&TyBool, _) | - (&TyInt(_), _) | - (&TyUint(_), _) | - (&TyFloat(_), _) | - (&TyStr, _) | - (&TyParam(_), _) | - (&TyClosure(_, _), _) if a == b => { - Ok(a) - }, - (&TyAdt(a_def, a_substs), &TyAdt(_, b_substs)) => { - // TODO: possibly do something here - let substs = relation.relate_item_substs(a_def.did, a_substs, b_substs)?; - Ok(tcx.mk_adt(a_def, substs)) - }, - (&TyDynamic(_, _), &TyDynamic(_, _)) => { - // TODO: decide whether this is needed - /*let region_bound = relation.with_cause(Cause::ExistentialRegionBound, - |relation| { - relation.relate(a_region, b_region) - })?; - Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound))*/ - Err(TypeError::Mismatch) - }, - (&TyRawPtr(ref a_mt), &TyRawPtr(ref b_mt)) => { - let mt = relation.relate(a_mt, b_mt)?; - Ok(tcx.mk_ptr(mt)) - }, - (&TyRef(ref a_r, ref a_mt), &TyRef(ref b_r, ref b_mt)) => { - let r = relation.relate(a_r, b_r)?; - let mt = relation.relate(a_mt, b_mt)?; - Ok(tcx.mk_ref(r, mt)) - }, - (&TyArray(a_t, sz_a), &TyArray(b_t, sz_b)) => { - let t = relation.relate(&a_t, &b_t)?; - if sz_a == sz_b { - Ok(tcx.mk_array(t, sz_a)) - } else { - Err(TypeError::Mismatch) - } - }, - (&TySlice(a_t), &TySlice(b_t)) => { - let t = relation.relate(&a_t, &b_t)?; - Ok(tcx.mk_slice(t)) - }, - (&TyTuple(as_, a_defaulted), &TyTuple(bs, b_defaulted)) => { - let rs = as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)); - if as_.len() == bs.len() { - let defaulted = a_defaulted || b_defaulted; - tcx.mk_tup(rs, defaulted) - } else if !(as_.is_empty() || bs.is_empty()) { - Err(TypeError::Mismatch) - } else { - Err(TypeError::Mismatch) - } - }, - (&TyFnDef(a_def_id, a_substs, a_fty), &TyFnDef(_, b_substs, b_fty)) => { - let substs = ty::relate::relate_substs(relation, None, a_substs, b_substs)?; - let fty = relation.relate(&a_fty, &b_fty)?; - Ok(tcx.mk_fn_def(a_def_id, substs, fty)) - }, - (&TyFnPtr(a_fty), &TyFnPtr(b_fty)) => { - let fty = relation.relate(&a_fty, &b_fty)?; - Ok(tcx.mk_fn_ptr(fty)) - }, - (&TyProjection(ref a_data), &TyProjection(ref b_data)) => { - let projection_ty = relation.relate(a_data, b_data)?; - Ok(tcx.mk_projection(projection_ty.trait_ref, projection_ty.item_name(tcx))) - }, - (&TyAnon(a_def_id, a_substs), &TyAnon(_, b_substs)) => { - let substs = ty::relate::relate_substs(relation, None, a_substs, b_substs)?; - Ok(tcx.mk_anon(a_def_id, substs)) - }, - _ => { - Err(TypeError::Mismatch) - } - } -} - -/// Given two ADT items, perform *structural* checks. +/// Given two ADT items, perform structural checks. /// /// This establishes the needed correspondence relationship between non-toplevel items. /// For instance, struct fields, enum variants etc. are matched up against each other here. @@ -549,36 +375,24 @@ fn diff_adts(changes: &mut ChangeSet, } } -/// Given two items, perform *non-structural* checks. -/// -/// This encompasses all checks for type and requires that the structural checks have already -/// been performed. -fn diff_items(changes: &mut ChangeSet, +/// Given two items, compare their types. +fn diff_types(changes: &mut ChangeSet, id_mapping: &IdMapping, tcx: TyCtxt, old: Export, new: Export) { - if !changes.item_breaking(old.def.def_id()) { - let mut type_changes = diff_types(id_mapping, tcx, old.def.def_id(), new.def.def_id()); - - for change_type in type_changes.drain(..) { - changes.add_binary(change_type, old.def.def_id(), None); - } - } -} - - -/// Given two items, compare their types for equality. -fn diff_types(id_mapping: &IdMapping, tcx: TyCtxt, old: DefId, new: DefId) - -> Vec -{ use rustc::ty::AdtDef; use rustc::ty::TypeVariants::*; - let mut res = Vec::new(); + if changes.item_breaking(old.def.def_id()) { + return; + } - let new_ty = tcx.type_of(new); - let old_ty = tcx.type_of(old).subst(tcx, Substs::identity_for_item(tcx, new)); + let old_def_id = old.def.def_id(); + let new_def_id = new.def.def_id(); + + let new_ty = tcx.type_of(new_def_id); + let old_ty = tcx.type_of(old_def_id).subst(tcx, Substs::identity_for_item(tcx, new_def_id)); let old_ty_cmp = old_ty.fold_with(&mut BottomUpFolder { tcx: tcx, fldop: |ty| { match ty.sty { @@ -600,14 +414,18 @@ fn diff_types(id_mapping: &IdMapping, tcx: TyCtxt, old: DefId, new: DefId) // println!("old_ty: {:?}", old_ty_cmp); // println!("new_ty: {:?}", new_ty); - if let Result::Err(err) = tcx.global_tcx().infer_ctxt() - .enter(|infcx| infcx.can_eq(tcx.param_env(new), old_ty_cmp, new_ty)) + if let Err(err) = tcx.global_tcx().infer_ctxt() + .enter(|infcx| infcx.can_eq(tcx.param_env(new_def_id), old_ty_cmp, new_ty)) { // println!("diff: {}", err); - res.push(FieldTypeChanged(format!("{}", err))); // FIXME: this is obv a terrible hack + changes.add_binary(FieldTypeChanged(format!("{}", err)), old_def_id, None); } - res + /* let mut type_changes = diff_types(id_mapping, tcx, old.def.def_id(), new.def.def_id()); + + for change_type in type_changes.drain(..) { + changes.add_binary(change_type, old.def.def_id(), None); + } */ } /// Given two items, compare their type and region parameter sets. @@ -657,3 +475,15 @@ fn diff_generics(tcx: TyCtxt, old: DefId, new: DefId) -> Vec { ret } + +/// Given two items, compare the bounds on their type and region parameters. +fn diff_bounds(_changes: &mut ChangeSet, _tcx: TyCtxt, _old: DefId, _new: DefId) + -> (Vec, Vec<(DefId, DefId)>) +{ + let res = Default::default(); + + // let old_preds = tcx.predicates_of(old).predicates; + // let new_preds = tcx.predicates_of(new).predicates; + + res +} From 319da7d632bea35a85385074d83003577af4506f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 26 Jun 2017 16:56:57 +0200 Subject: [PATCH 083/553] Restructured analysis passes. This greatly improves documentation and makes the whole code much more easy to follow. --- src/bin/rust_semverver.rs | 4 +- src/semcheck/traverse.rs | 193 +++++++++++++++++++++----------------- 2 files changed, 111 insertions(+), 86 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index f66677a5b4231..fa07a5e54d414 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -10,7 +10,7 @@ extern crate semver; extern crate semverver; extern crate syntax; -use semverver::semcheck::traverse::traverse_modules; +use semverver::semcheck::traverse::run_analysis; use rustc::hir::def_id::*; use rustc::session::{config, Session}; @@ -104,7 +104,7 @@ fn callback(state: &driver::CompileState, version: &str) { } }; - let changes = traverse_modules(tcx, old_did, new_did); + let changes = run_analysis(tcx, old_did, new_did); changes.output(tcx.sess, version); } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index e8466dd568b96..0b3eadc953c10 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -94,17 +94,58 @@ fn get_namespace(def: &Def) -> Namespace { } } -/// Traverse the two root modules in an interleaved manner. +/// The main entry point to our analysis passes. /// -/// Match up pairs of modules from the two crate versions and compare for changes. -/// Matching children get processed in the same fashion. -// TODO: describe the passes we do. -pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { +/// Set up the necessary data structures and run the analysis passes. +pub fn run_analysis(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { + let mut changes = Default::default(); + let mut id_mapping = Default::default(); + + // first pass + diff_structure(&mut changes, &mut id_mapping, tcx, old, new); + + // second (and third, for now) pass + for &(_, old, new) in id_mapping.toplevel_mapping.values() { + let old_did = old.def.def_id(); + let new_did = new.def.def_id(); + + { + let mut mismatch = Mismatch { + tcx: tcx, + toplevel_mapping: &id_mapping.toplevel_mapping, + mapping: &mut id_mapping.mapping, + }; + + let _ = mismatch.tys(tcx.type_of(old_did), tcx.type_of(new_did)); + } + + diff_bounds(&mut changes, tcx, old_did, new_did); + } + + // fourth pass + for &(_, old, new) in id_mapping.toplevel_mapping.values() { + diff_types(&mut changes, &id_mapping, tcx, old, new); + } + + changes +} + +// 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 their 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. +fn diff_structure(changes: &mut ChangeSet, + id_mapping: &mut IdMapping, + tcx: TyCtxt, + old: DefId, + new: DefId) { use rustc::hir::def::Def::*; let cstore = &tcx.sess.cstore; - let mut changes = ChangeSet::default(); - let mut id_mapping = IdMapping::default(); let mut visited = HashSet::new(); let mut children = HashMap::new(); let mut mod_queue = VecDeque::new(); @@ -219,7 +260,7 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { changes.add_binary(change_type, o_def_id, None); } - diff_adts(&mut changes, &mut id_mapping, tcx, o, n); + diff_adts(changes, id_mapping, tcx, o, n); }, // non-matching item pair - register the difference and abort _ => { @@ -242,29 +283,6 @@ pub fn traverse_modules(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { } } } - - for &(_, old, new) in id_mapping.toplevel_mapping.values() { - let old_did = old.def.def_id(); - let new_did = new.def.def_id(); - - { - let mut mismatch = Mismatch { - tcx: tcx, - toplevel_mapping: &id_mapping.toplevel_mapping, - mapping: &mut id_mapping.mapping, - }; - - let _ = mismatch.tys(tcx.type_of(old_did), tcx.type_of(new_did)); - } - - diff_bounds(&mut changes, tcx, old_did, new_did); - } - - for &(_, old, new) in id_mapping.toplevel_mapping.values() { - diff_types(&mut changes, &id_mapping, tcx, old, new); - } - - changes } /// Given two ADT items, perform structural checks. @@ -375,59 +393,6 @@ fn diff_adts(changes: &mut ChangeSet, } } -/// Given two items, compare their types. -fn diff_types(changes: &mut ChangeSet, - id_mapping: &IdMapping, - tcx: TyCtxt, - old: Export, - new: Export) { - use rustc::ty::AdtDef; - use rustc::ty::TypeVariants::*; - - if changes.item_breaking(old.def.def_id()) { - return; - } - - let old_def_id = old.def.def_id(); - let new_def_id = new.def.def_id(); - - let new_ty = tcx.type_of(new_def_id); - let old_ty = tcx.type_of(old_def_id).subst(tcx, Substs::identity_for_item(tcx, new_def_id)); - - let old_ty_cmp = old_ty.fold_with(&mut BottomUpFolder { tcx: tcx, fldop: |ty| { - match ty.sty { - TyAdt(&AdtDef { ref did, .. }, substs) => { - let new_did = id_mapping.get_new_id(*did); - let new_adt = tcx.adt_def(new_did); - tcx.mk_adt(new_adt, substs) - }, - /* TyDynamic(predicates, region) => { - - }, TyClosure, TyRef (because of region?), TyProjection, TyAnon - TyProjection(projection_ty) => { - - }, */ - _ => ty, - } - }}); - - // println!("old_ty: {:?}", old_ty_cmp); - // println!("new_ty: {:?}", new_ty); - - if let Err(err) = tcx.global_tcx().infer_ctxt() - .enter(|infcx| infcx.can_eq(tcx.param_env(new_def_id), old_ty_cmp, new_ty)) - { - // println!("diff: {}", err); - changes.add_binary(FieldTypeChanged(format!("{}", err)), old_def_id, None); - } - - /* let mut type_changes = diff_types(id_mapping, tcx, old.def.def_id(), new.def.def_id()); - - for change_type in type_changes.drain(..) { - changes.add_binary(change_type, old.def.def_id(), None); - } */ -} - /// Given two items, compare their type and region parameter sets. fn diff_generics(tcx: TyCtxt, old: DefId, new: DefId) -> Vec { use std::cmp::max; @@ -476,6 +441,10 @@ fn diff_generics(tcx: TyCtxt, old: DefId, new: DefId) -> Vec { ret } +// Below functions constitute the third pass of analysis, in which parameter bounds of matching +// items are compared for changes and used to determine matching relationships between items not +// being exported. + /// Given two items, compare the bounds on their type and region parameters. fn diff_bounds(_changes: &mut ChangeSet, _tcx: TyCtxt, _old: DefId, _new: DefId) -> (Vec, Vec<(DefId, DefId)>) @@ -487,3 +456,59 @@ fn diff_bounds(_changes: &mut ChangeSet, _tcx: TyCtxt, _old: DefId, _new: DefId) res } + +// Below functions constitute the fourth and last pass of analysis, in which the types of +// matching items are compared for changes. + +/// Given two items, compare their types. +fn diff_types(changes: &mut ChangeSet, + id_mapping: &IdMapping, + tcx: TyCtxt, + old: Export, + new: Export) { + use rustc::ty::AdtDef; + use rustc::ty::TypeVariants::*; + + if changes.item_breaking(old.def.def_id()) { + return; + } + + let old_def_id = old.def.def_id(); + let new_def_id = new.def.def_id(); + + let new_ty = tcx.type_of(new_def_id); + let old_ty = tcx.type_of(old_def_id).subst(tcx, Substs::identity_for_item(tcx, new_def_id)); + + let old_ty_cmp = old_ty.fold_with(&mut BottomUpFolder { tcx: tcx, fldop: |ty| { + match ty.sty { + TyAdt(&AdtDef { ref did, .. }, substs) => { + let new_did = id_mapping.get_new_id(*did); + let new_adt = tcx.adt_def(new_did); + tcx.mk_adt(new_adt, substs) + }, + /* TyDynamic(predicates, region) => { + + }, TyClosure, TyRef (because of region?), TyProjection, TyAnon + TyProjection(projection_ty) => { + + }, */ + _ => ty, + } + }}); + + // println!("old_ty: {:?}", old_ty_cmp); + // println!("new_ty: {:?}", new_ty); + + if let Err(err) = tcx.global_tcx().infer_ctxt() + .enter(|infcx| infcx.can_eq(tcx.param_env(new_def_id), old_ty_cmp, new_ty)) + { + // println!("diff: {}", err); + changes.add_binary(FieldTypeChanged(format!("{}", err)), old_def_id, None); + } + + /* let mut type_changes = diff_types(id_mapping, tcx, old.def.def_id(), new.def.def_id()); + + for change_type in type_changes.drain(..) { + changes.add_binary(change_type, old.def.def_id(), None); + } */ +} From c64c8a65ba68bad59e8974b486fd6a7c924fdc45 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 26 Jun 2017 17:19:13 +0200 Subject: [PATCH 084/553] Updated tests. --- src/semcheck/traverse.rs | 4 ++-- tests/examples/enum.out | 49 ++++++++++++++++++++++++++++++++-------- tests/examples/enum.rs | 18 +++++++++++++++ tests/examples/fn.out | 9 ++++++++ tests/examples/fn.rs | 7 ++++++ 5 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 tests/examples/fn.out create mode 100644 tests/examples/fn.rs diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 0b3eadc953c10..7ebabe9597312 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -287,8 +287,8 @@ fn diff_structure(changes: &mut ChangeSet, /// Given two ADT items, perform structural checks. /// -/// This establishes the needed correspondence relationship between non-toplevel items. -/// For instance, struct fields, enum variants etc. are matched up against each other here. +/// This establishes the needed correspondence relationship between non-toplevel items such as +/// enum variants, struct fields etc. fn diff_adts(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, diff --git a/tests/examples/enum.out b/tests/examples/enum.out index a40373a1fdeec..6bc8ee5fe9947 100644 --- a/tests/examples/enum.out +++ b/tests/examples/enum.out @@ -1,24 +1,24 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 warning: Breaking changes in `Abc` - --> $REPO_PATH/tests/examples/enum.rs:12:5 + --> $REPO_PATH/tests/examples/enum.rs:21:5 | -12 | / pub enum Abc { -13 | | Abc, -14 | | } +21 | / pub enum Abc { +22 | | Abc, +23 | | } | |_____^ | warning: Breaking (VariantAdded) - --> $REPO_PATH/tests/examples/enum.rs:13:9 + --> $REPO_PATH/tests/examples/enum.rs:22:9 | -13 | Abc, +22 | Abc, | ^^^ warning: Breaking changes in `Bcd` - --> $REPO_PATH/tests/examples/enum.rs:16:5 + --> $REPO_PATH/tests/examples/enum.rs:25:5 | -16 | / pub enum Bcd { -17 | | -18 | | } +25 | / pub enum Bcd { +26 | | +27 | | } | |_____^ | warning: Breaking (VariantRemoved) @@ -27,3 +27,32 @@ warning: Breaking (VariantRemoved) 7 | Abc, | ^^^ +warning: Breaking changes in `Cde` + --> $REPO_PATH/tests/examples/enum.rs:29:5 + | +29 | / pub enum Cde { +30 | | Abc, +31 | | Bcd, +32 | | } + | |_____^ + | +warning: Breaking (VariantAdded) + --> $REPO_PATH/tests/examples/enum.rs:31:9 + | +31 | Bcd, + | ^^^ + +warning: Breaking changes in `Def` + --> $REPO_PATH/tests/examples/enum.rs:34:5 + | +34 | / pub enum Def { +35 | | Abc, +36 | | } + | |_____^ + | +warning: Breaking (VariantRemoved) + --> $REPO_PATH/tests/examples/enum.rs:16:9 + | +16 | Bcd, + | ^^^ + diff --git a/tests/examples/enum.rs b/tests/examples/enum.rs index cf1c882d84c07..c885e17d1d48a 100644 --- a/tests/examples/enum.rs +++ b/tests/examples/enum.rs @@ -6,6 +6,15 @@ pub mod old { pub enum Bcd { Abc, } + + pub enum Cde { + Abc, + } + + pub enum Def { + Abc, + Bcd, + } } pub mod new { @@ -16,4 +25,13 @@ pub mod new { pub enum Bcd { } + + pub enum Cde { + Abc, + Bcd, + } + + pub enum Def { + Abc, + } } diff --git a/tests/examples/fn.out b/tests/examples/fn.out new file mode 100644 index 0000000000000..091a68d567a5b --- /dev/null +++ b/tests/examples/fn.out @@ -0,0 +1,9 @@ +version bump: 1.0.0 -> (Breaking) -> 2.0.0 +warning: Breaking changes in `abc` + --> $REPO_PATH/tests/examples/fn.rs:6:5 + | +6 | pub fn abc() {} + | ^^^^^^^^^^^^^^^ + | + = warning: Breaking (FieldTypeChanged("expected fn item, found a different fn item")) + diff --git a/tests/examples/fn.rs b/tests/examples/fn.rs new file mode 100644 index 0000000000000..71c65cb516301 --- /dev/null +++ b/tests/examples/fn.rs @@ -0,0 +1,7 @@ +pub mod old { + pub fn abc() {} +} + +pub mod new { + pub fn abc() {} +} From 1fb70595e990095b5f8400f586776c124049e3a9 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 26 Jun 2017 23:18:41 +0200 Subject: [PATCH 085/553] Added structural checks to fn items. --- src/semcheck/changes.rs | 15 +++++++++++- src/semcheck/traverse.rs | 51 +++++++++++++++++++++++++++++++++------- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 6f8345efcf7c9..847b051adae32 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -155,6 +155,14 @@ pub enum BinaryChangeType { TraitImplItemAdded { defaulted: bool }, /// An impl item has been removed. TraitImplItemRemoved, + /// A function changed it's variadicity. + FnVariadicChanged, + /// A function changed it's unsafety. + FnUnsafetyChanged { now_unsafe: bool }, + /// A function's ABI has changed. + FnAbiChanged, + /// A function's arity changed. + FnArityChanged, /// An unknown change is any change we don't yet explicitly handle. Unknown, } @@ -180,10 +188,15 @@ impl BinaryChangeType { FieldTypeChanged(_) | TraitImplItemAdded { .. } | TraitImplItemRemoved | + FnVariadicChanged | + FnUnsafetyChanged { now_unsafe: true } | + FnAbiChanged | + FnArityChanged | Unknown => Breaking, TypeGeneralization | ItemMadePublic => TechnicallyBreaking, - TypeParameterAdded { defaulted: true } => NonBreaking, + TypeParameterAdded { defaulted: true } | + FnUnsafetyChanged { now_unsafe: false } => NonBreaking, } } } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 7ebabe9597312..4b4c7cd01e381 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -229,10 +229,8 @@ fn diff_structure(changes: &mut ChangeSet, (PrimTy(_), PrimTy(_)) | (TyParam(_), TyParam(_)) | (SelfTy(_, _), SelfTy(_, _)) | - (Fn(_), Fn(_)) | (StructCtor(_, _), StructCtor(_, _)) | (VariantCtor(_, _), VariantCtor(_, _)) | - (Method(_), Method(_)) | (AssociatedConst(_), AssociatedConst(_)) | (Local(_), Local(_)) | (Upvar(_, _, _), Upvar(_, _, _)) | @@ -243,6 +241,10 @@ fn diff_structure(changes: &mut ChangeSet, (Const(_), Const(_)) | (Static(_, _), Static(_, _)) | (Err, Err) => {}, + (Fn(_), Fn(_)) | + (Method(_), Method(_)) => { + diff_fn(changes, tcx, o, n); + }, (TyAlias(_), TyAlias(_)) => { let mut generics_changes = diff_generics(tcx, o_def_id, n_def_id); @@ -285,6 +287,45 @@ fn diff_structure(changes: &mut ChangeSet, } } +/// Given two fn items, perform structural checks. +fn diff_fn(changes: &mut ChangeSet, + tcx: TyCtxt, + old: Export, + new: Export) { + use rustc::hir::Unsafety::Unsafe; + use rustc::ty::TypeVariants::*; + + let old_def_id = old.def.def_id(); + let new_def_id = new.def.def_id(); + + let old_ty = tcx.type_of(old_def_id); + let new_ty = tcx.type_of(new_def_id); + + let (old_sig, new_sig) = match (&old_ty.sty, &new_ty.sty) { + (&TyFnDef(_, _, ref o), &TyFnDef(_, _, ref n)) => (o.skip_binder(), n.skip_binder()), + (&TyFnPtr(ref o), &TyFnPtr(ref n)) => (o.skip_binder(), n.skip_binder()), + _ => return, + }; + + if old_sig.variadic != new_sig.variadic { + changes.add_binary(FnVariadicChanged, old_def_id, None); + } + + if old_sig.unsafety != new_sig.unsafety { + let change = FnUnsafetyChanged { now_unsafe: new_sig.unsafety == Unsafe }; + changes.add_binary(change, old_def_id, None); + } + + if old_sig.abi != new_sig.abi { + // TODO: more sophisticatd comparison + changes.add_binary(FnAbiChanged, old_def_id, None); + } + + if old_sig.inputs_and_output.len() != new_sig.inputs_and_output.len() { + changes.add_binary(FnArityChanged, old_def_id, None); + } +} + /// Given two ADT items, perform structural checks. /// /// This establishes the needed correspondence relationship between non-toplevel items such as @@ -505,10 +546,4 @@ fn diff_types(changes: &mut ChangeSet, // println!("diff: {}", err); changes.add_binary(FieldTypeChanged(format!("{}", err)), old_def_id, None); } - - /* let mut type_changes = diff_types(id_mapping, tcx, old.def.def_id(), new.def.def_id()); - - for change_type in type_changes.drain(..) { - changes.add_binary(change_type, old.def.def_id(), None); - } */ } From 3ec4588cf02c4dfc75d0b64bdc619caebee9a97a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 27 Jun 2017 11:23:24 +0200 Subject: [PATCH 086/553] Added fn tests. --- tests/examples/fn.out | 38 ++++++++++++++++++++++++++++++++------ tests/examples/fn.rs | 14 ++++++++++++++ 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/tests/examples/fn.out b/tests/examples/fn.out index 091a68d567a5b..a640a082412fc 100644 --- a/tests/examples/fn.out +++ b/tests/examples/fn.out @@ -1,9 +1,35 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 warning: Breaking changes in `abc` - --> $REPO_PATH/tests/examples/fn.rs:6:5 - | -6 | pub fn abc() {} - | ^^^^^^^^^^^^^^^ - | - = warning: Breaking (FieldTypeChanged("expected fn item, found a different fn item")) + --> $REPO_PATH/tests/examples/fn.rs:12:5 + | +12 | pub fn abc() {} + | ^^^^^^^^^^^^^^^ + | + = warning: Breaking (FieldTypeChanged("expected fn item, found a different fn item")) + +warning: Breaking changes in `bcd` + --> $REPO_PATH/tests/examples/fn.rs:14:5 + | +14 | pub fn bcd(_: u8) {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (FnArityChanged) + +warning: Breaking changes in `cde` + --> $REPO_PATH/tests/examples/fn.rs:16:5 + | +16 | / pub fn cde() -> u16 { // TODO: maybe make this case TechnicallyBreaking +17 | | 0xcde +18 | | } + | |_____^ + | + = warning: Breaking (FieldTypeChanged("expected fn item, found a different fn item")) + +warning: Breaking changes in `def` + --> $REPO_PATH/tests/examples/fn.rs:20:5 + | +20 | pub fn def() {} + | ^^^^^^^^^^^^^^^ + | + = warning: Breaking (FnArityChanged) diff --git a/tests/examples/fn.rs b/tests/examples/fn.rs index 71c65cb516301..d75bea2901cc4 100644 --- a/tests/examples/fn.rs +++ b/tests/examples/fn.rs @@ -1,7 +1,21 @@ pub mod old { pub fn abc() {} + + pub fn bcd() {} + + pub fn cde() {} + + pub fn def(_: u8) {} } pub mod new { pub fn abc() {} + + pub fn bcd(_: u8) {} + + pub fn cde() -> u16 { // TODO: maybe make this case TechnicallyBreaking + 0xcde + } + + pub fn def() {} } From 6653a935700dde40ad065f098bd47d720a82c778 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 27 Jun 2017 13:16:16 +0200 Subject: [PATCH 087/553] Clippy lints and code restructuring for a queue-based second pass --- src/semcheck/mismatch.rs | 22 ++++++++++----------- src/semcheck/traverse.rs | 42 +++++++++++++++++++++++----------------- 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index a086398e06982..649781165dcc1 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -50,11 +50,11 @@ impl<'a, 'gcx, 'tcx, A: 'a> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, let matching = match (&a.sty, &b.sty) { (&TyAdt(a_adt, _), &TyAdt(b_adt, _)) => Some((a_adt.did, b_adt.did)), - (&TyFnDef(a_did, _, _), &TyFnDef(b_did, _, _)) => Some((a_did, b_did)), - (&TyClosure(a_did, _), &TyClosure(b_did, _)) => Some((a_did, b_did)), + (&TyFnDef(a_did, _, _), &TyFnDef(b_did, _, _)) | + (&TyClosure(a_did, _), &TyClosure(b_did, _)) | + (&TyAnon(a_did, _), &TyAnon(b_did, _)) => Some((a_did, b_did)), (&TyProjection(a_proj), &TyProjection(b_proj)) => Some((a_proj.trait_ref.def_id, b_proj.trait_ref.def_id)), - (&TyAnon(a_did, _), &TyAnon(b_did, _)) => Some((a_did, b_did)), _ => { None }, @@ -123,22 +123,22 @@ fn relate_tys_mismatch<'a, 'gcx, 'tcx, R>(relation: &mut R, a: Ty<'tcx>, b: Ty<' let substs = relation.relate_item_substs(a_def.did, a_substs, b_substs)?; Ok(tcx.mk_adt(a_def, substs)) }, - (&TyDynamic(_, _), &TyDynamic(_, _)) => { + /* (&TyDynamic(_, _), &TyDynamic(_, _)) => { // TODO: decide whether this is needed - /*let region_bound = relation.with_cause(Cause::ExistentialRegionBound, + let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| { relation.relate(a_region, b_region) })?; - Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound))*/ + Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound)) Err(TypeError::Mismatch) - }, + },*/ (&TyRawPtr(ref a_mt), &TyRawPtr(ref b_mt)) => { let mt = relation.relate(a_mt, b_mt)?; Ok(tcx.mk_ptr(mt)) }, - (&TyRef(ref a_r, ref a_mt), &TyRef(ref b_r, ref b_mt)) => { - let r = relation.relate(a_r, b_r)?; - let mt = relation.relate(a_mt, b_mt)?; + (&TyRef(a_r, a_mt), &TyRef(b_r, b_mt)) => { + let r = relation.relate(&a_r, &b_r)?; + let mt = relation.relate(&a_mt, &b_mt)?; Ok(tcx.mk_ref(r, mt)) }, (&TyArray(a_t, sz_a), &TyArray(b_t, sz_b)) => { @@ -158,8 +158,6 @@ fn relate_tys_mismatch<'a, 'gcx, 'tcx, R>(relation: &mut R, a: Ty<'tcx>, b: Ty<' if as_.len() == bs.len() { let defaulted = a_defaulted || b_defaulted; tcx.mk_tup(rs, defaulted) - } else if !(as_.is_empty() || bs.is_empty()) { - Err(TypeError::Mismatch) } else { Err(TypeError::Mismatch) } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 4b4c7cd01e381..140841e43e65f 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -105,21 +105,25 @@ pub fn run_analysis(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { diff_structure(&mut changes, &mut id_mapping, tcx, old, new); // second (and third, for now) pass - for &(_, old, new) in id_mapping.toplevel_mapping.values() { - let old_did = old.def.def_id(); - let new_did = new.def.def_id(); - - { - let mut mismatch = Mismatch { - tcx: tcx, - toplevel_mapping: &id_mapping.toplevel_mapping, - mapping: &mut id_mapping.mapping, - }; - + { + let mut item_queue: VecDeque<_> = + id_mapping + .toplevel_mapping + .values() + .map(|&(_, old, new)| (old.def.def_id(), new.def.def_id())) + .collect(); + + let mut mismatch = Mismatch { + tcx: tcx, + toplevel_mapping: &id_mapping.toplevel_mapping, + mapping: &mut id_mapping.mapping, + }; + + while let Some((old_did, new_did)) = item_queue.pop_front() { let _ = mismatch.tys(tcx.type_of(old_did), tcx.type_of(new_did)); - } - diff_bounds(&mut changes, tcx, old_did, new_did); + diff_bounds(&mut changes, tcx, old_did, new_did); + } } // fourth pass @@ -302,7 +306,7 @@ fn diff_fn(changes: &mut ChangeSet, let new_ty = tcx.type_of(new_def_id); let (old_sig, new_sig) = match (&old_ty.sty, &new_ty.sty) { - (&TyFnDef(_, _, ref o), &TyFnDef(_, _, ref n)) => (o.skip_binder(), n.skip_binder()), + (&TyFnDef(_, _, ref o), &TyFnDef(_, _, ref n)) | (&TyFnPtr(ref o), &TyFnPtr(ref n)) => (o.skip_binder(), n.skip_binder()), _ => return, }; @@ -490,12 +494,14 @@ fn diff_generics(tcx: TyCtxt, old: DefId, new: DefId) -> Vec { fn diff_bounds(_changes: &mut ChangeSet, _tcx: TyCtxt, _old: DefId, _new: DefId) -> (Vec, Vec<(DefId, DefId)>) { - let res = Default::default(); + /* let res = Default::default(); + + let old_preds = tcx.predicates_of(old).predicates; + let new_preds = tcx.predicates_of(new).predicates; - // let old_preds = tcx.predicates_of(old).predicates; - // let new_preds = tcx.predicates_of(new).predicates; + res */ - res + Default::default() } // Below functions constitute the fourth and last pass of analysis, in which the types of From e1f6b7558c17f9e54191a9c6e5f2a363749725f1 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 27 Jun 2017 16:57:43 +0200 Subject: [PATCH 088/553] Implemented an item queue for the second pass. --- src/semcheck/mismatch.rs | 36 +++++++++++++++++++++++------------- src/semcheck/traverse.rs | 20 +++++++++++++------- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 649781165dcc1..f6fbf3aefe382 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -4,23 +4,35 @@ use rustc::ty::{Ty, TyCtxt}; use rustc::ty::error::TypeError; use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; -use std::collections::HashMap; +use std::collections::{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. -pub struct Mismatch<'a, 'gcx: 'a + 'tcx, 'tcx: 'a, A: 'a> { +pub struct Mismatch<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { /// The type context used. pub tcx: TyCtxt<'a, 'gcx, 'tcx>, - /// The mapping of toplevel items. - pub toplevel_mapping: &'a HashMap, - /// The mapping of all other items. - pub mapping: &'a mut HashMap, + /// The queue to append found item pairings. + pub item_queue: VecDeque<(DefId, DefId)>, + /// All visited items. + pub visited: HashSet<(DefId, DefId)>, } -impl<'a, 'gcx, 'tcx, A: 'a> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx, A> { +impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> Mismatch<'a, 'gcx, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, item_queue: VecDeque<(DefId, DefId)>) + -> Mismatch<'a, 'gcx, 'tcx> + { + Mismatch { + tcx: tcx, + item_queue: item_queue, + visited: Default::default(), + } + } +} + +impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.tcx } @@ -60,12 +72,10 @@ impl<'a, 'gcx, 'tcx, A: 'a> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, }, }; - if let Some((old_did, new_did)) = matching { - if !self.toplevel_mapping.contains_key(&old_did) && - !self.mapping.contains_key(&old_did) - { - // println!("adding mapping: {:?} => {:?}", old_did, new_did); - self.mapping.insert(old_did, new_did); + if let Some(dids) = matching { + if !self.visited.contains(&dids) { + self.visited.insert(dids); + self.item_queue.push_back(dids); } } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 140841e43e65f..71b7d3e1db777 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -47,6 +47,11 @@ impl IdMapping { self.mapping[&old] } } + + /// Tell us whether a `DefId` is present in the mappings. + pub fn contains_id(&self, old: DefId) -> bool { + self.toplevel_mapping.contains_key(&old) || self.mapping.contains_key(&old) + } } /// A representation of a namespace an item belongs to. @@ -106,22 +111,23 @@ pub fn run_analysis(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { // second (and third, for now) pass { - let mut item_queue: VecDeque<_> = + let item_queue: VecDeque<_> = id_mapping .toplevel_mapping .values() .map(|&(_, old, new)| (old.def.def_id(), new.def.def_id())) .collect(); - let mut mismatch = Mismatch { - tcx: tcx, - toplevel_mapping: &id_mapping.toplevel_mapping, - mapping: &mut id_mapping.mapping, - }; + let mut mismatch = Mismatch::new(tcx, item_queue); - while let Some((old_did, new_did)) = item_queue.pop_front() { + while let Some((old_did, new_did)) = mismatch.item_queue.pop_front() { let _ = mismatch.tys(tcx.type_of(old_did), tcx.type_of(new_did)); + if !id_mapping.contains_id(old_did) { + // println!("adding mapping: {:?} => {:?}", old_did, new_did); + id_mapping.add_item(old_did, new_did); + } + diff_bounds(&mut changes, tcx, old_did, new_did); } } From e7151cbb54706aa46140ea03b0df4d04f83693a0 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 27 Jun 2017 17:18:37 +0200 Subject: [PATCH 089/553] Restructured DefId map implementation. --- src/bin/rust_semverver.rs | 2 +- src/semcheck/id_mapping.rs | 91 +++++++++++++++++++++++++++++++++++ src/semcheck/mod.rs | 6 ++- src/semcheck/traverse.rs | 97 ++++---------------------------------- 4 files changed, 105 insertions(+), 91 deletions(-) create mode 100644 src/semcheck/id_mapping.rs diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index fa07a5e54d414..7a5a30583e6b7 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -10,7 +10,7 @@ extern crate semver; extern crate semverver; extern crate syntax; -use semverver::semcheck::traverse::run_analysis; +use semverver::semcheck::run_analysis; use rustc::hir::def_id::*; use rustc::session::{config, Session}; diff --git a/src/semcheck/id_mapping.rs b/src/semcheck/id_mapping.rs new file mode 100644 index 0000000000000..267eb76bcebd4 --- /dev/null +++ b/src/semcheck/id_mapping.rs @@ -0,0 +1,91 @@ +use rustc::hir::def::Def; +use rustc::hir::def::Export; +use rustc::hir::def_id::DefId; + +use std::collections::HashMap; + +/// A mapping from old to new `DefId`s, as well as exports. +/// +/// Exports 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. +#[derive(Default)] +pub struct IdMapping { + /// Toplevel items' old `DefId` mapped to new `DefId`, as well as old and new exports. + pub toplevel_mapping: HashMap, + /// Other item's old `DefId` mapped to new `DefId`. + mapping: HashMap, +} + +impl IdMapping { + /// Register two exports representing the same item across versions. + pub fn add_export(&mut self, old: Export, new: Export) -> bool { + self.toplevel_mapping + .insert(old.def.def_id(), (new.def.def_id(), old, new)) + .is_some() + } + + /// Add any other item pair's old and new `DefId`s. + pub fn add_item(&mut self, old: DefId, new: DefId) { + self.mapping.insert(old, new); + } + + /// Get the new `DefId` associated with the given old one. + pub fn get_new_id(&self, old: DefId) -> DefId { + if let Some(new) = self.toplevel_mapping.get(&old) { + new.0 + } else { + self.mapping[&old] + } + } + + /// Tell us whether a `DefId` is present in the mappings. + pub fn contains_id(&self, old: DefId) -> bool { + self.toplevel_mapping.contains_key(&old) || self.mapping.contains_key(&old) + } +} + +/// A representation of a namespace an item belongs to. +#[derive(PartialEq, Eq, Hash)] +pub enum Namespace { + /// The type namespace. + Type, + /// The value namespace. + Value, + /// The macro namespace. + Macro, + /// No namespace, so to say. + Err, +} + +/// Get an item's namespace. +pub fn get_namespace(def: &Def) -> Namespace { + use rustc::hir::def::Def::*; + + match *def { + Mod(_) | + Struct(_) | + Union(_) | + Enum(_) | + Variant(_) | + Trait(_) | + TyAlias(_) | + AssociatedTy(_) | + PrimTy(_) | + TyParam(_) | + SelfTy(_, _) => Namespace::Type, + Fn(_) | + Const(_) | + Static(_, _) | + StructCtor(_, _) | + VariantCtor(_, _) | + Method(_) | + AssociatedConst(_) | + Local(_) | + Upvar(_, _, _) | + Label(_) => Namespace::Value, + Macro(_, _) => Namespace::Macro, + GlobalAsm(_) | + Err => Namespace::Err, + } +} + diff --git a/src/semcheck/mod.rs b/src/semcheck/mod.rs index 4c4ecf543057a..5636eda8eb818 100644 --- a/src/semcheck/mod.rs +++ b/src/semcheck/mod.rs @@ -1,3 +1,7 @@ pub mod changes; + +mod id_mapping; mod mismatch; -pub mod traverse; +mod traverse; + +pub use self::traverse::run_analysis; diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 71b7d3e1db777..cf1a9ed9f49d1 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -1,9 +1,10 @@ use semcheck::changes::BinaryChangeType; use semcheck::changes::BinaryChangeType::*; use semcheck::changes::ChangeSet; +use semcheck::id_mapping::{get_namespace, IdMapping}; use semcheck::mismatch::Mismatch; -use rustc::hir::def::{Def, CtorKind}; +use rustc::hir::def::CtorKind; use rustc::hir::def::Export; use rustc::hir::def_id::DefId; use rustc::ty::TyCtxt; @@ -14,91 +15,6 @@ use rustc::ty::subst::{Subst, Substs}; use std::collections::{HashMap, HashSet, VecDeque}; -/// A mapping from old to new `DefId`s, as well as exports. -/// -/// Exports 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. -#[derive(Default)] -struct IdMapping { - /// Toplevel items' old `DefId` mapped to new `DefId`, as well as old and new exports. - toplevel_mapping: HashMap, - /// Other item's old `DefId` mapped to new `DefId`. - mapping: HashMap, -} - -impl IdMapping { - /// Register two exports representing the same item across versions. - pub fn add_export(&mut self, old: Export, new: Export) -> bool { - self.toplevel_mapping - .insert(old.def.def_id(), (new.def.def_id(), old, new)) - .is_some() - } - - /// Add any other item pair's old and new `DefId`s. - pub fn add_item(&mut self, old: DefId, new: DefId) { - self.mapping.insert(old, new); - } - - /// Get the new `DefId` associated with the given old one. - pub fn get_new_id(&self, old: DefId) -> DefId { - if let Some(new) = self.toplevel_mapping.get(&old) { - new.0 - } else { - self.mapping[&old] - } - } - - /// Tell us whether a `DefId` is present in the mappings. - pub fn contains_id(&self, old: DefId) -> bool { - self.toplevel_mapping.contains_key(&old) || self.mapping.contains_key(&old) - } -} - -/// A representation of a namespace an item belongs to. -#[derive(PartialEq, Eq, Hash)] -enum Namespace { - /// The type namespace. - Type, - /// The value namespace. - Value, - /// The macro namespace. - Macro, - /// No namespace, so to say. - Err, -} - -/// Get an item's namespace. -fn get_namespace(def: &Def) -> Namespace { - use rustc::hir::def::Def::*; - - match *def { - Mod(_) | - Struct(_) | - Union(_) | - Enum(_) | - Variant(_) | - Trait(_) | - TyAlias(_) | - AssociatedTy(_) | - PrimTy(_) | - TyParam(_) | - SelfTy(_, _) => Namespace::Type, - Fn(_) | - Const(_) | - Static(_, _) | - StructCtor(_, _) | - VariantCtor(_, _) | - Method(_) | - AssociatedConst(_) | - Local(_) | - Upvar(_, _, _) | - Label(_) => Namespace::Value, - Macro(_, _) => Namespace::Macro, - GlobalAsm(_) | - Err => Namespace::Err, - } -} - /// The main entry point to our analysis passes. /// /// Set up the necessary data structures and run the analysis passes. @@ -109,7 +25,7 @@ pub fn run_analysis(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { // first pass diff_structure(&mut changes, &mut id_mapping, tcx, old, new); - // second (and third, for now) pass + // second pass { let item_queue: VecDeque<_> = id_mapping @@ -127,11 +43,14 @@ pub fn run_analysis(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { // println!("adding mapping: {:?} => {:?}", old_did, new_did); id_mapping.add_item(old_did, new_did); } - - diff_bounds(&mut changes, tcx, old_did, new_did); } } + // third pass + for &(_, old, new) in id_mapping.toplevel_mapping.values() { + diff_bounds(&mut changes, tcx, old.def.def_id(), new.def.def_id()); + } + // fourth pass for &(_, old, new) in id_mapping.toplevel_mapping.values() { diff_types(&mut changes, &id_mapping, tcx, old, new); From 382d30e8ae7b0e7c054013b5a68bc8706c75711e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 27 Jun 2017 23:18:27 +0200 Subject: [PATCH 090/553] Moved some traversal logic to the mismatch type relation. --- src/semcheck/mismatch.rs | 22 ++++++++++++++++++---- src/semcheck/traverse.rs | 5 +---- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index f6fbf3aefe382..e79a0bf7827e4 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -13,14 +13,15 @@ use std::collections::{HashSet, VecDeque}; /// their names across versions. pub struct Mismatch<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { /// The type context used. - pub tcx: TyCtxt<'a, 'gcx, 'tcx>, + tcx: TyCtxt<'a, 'gcx, 'tcx>, /// The queue to append found item pairings. - pub item_queue: VecDeque<(DefId, DefId)>, + item_queue: VecDeque<(DefId, DefId)>, /// All visited items. - pub visited: HashSet<(DefId, DefId)>, + visited: HashSet<(DefId, DefId)>, } impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> Mismatch<'a, 'gcx, 'tcx> { + /// Construct a new mismtach type relation. pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, item_queue: VecDeque<(DefId, DefId)>) -> Mismatch<'a, 'gcx, 'tcx> { @@ -30,6 +31,19 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> Mismatch<'a, 'gcx, 'tcx> { visited: Default::default(), } } + + /// Process the next pair of `DefId`s in the queue and return them. + pub fn process_next(&mut self) -> Option<(DefId, DefId)> { + let did_pair = self.item_queue.pop_front(); + + if let Some((old_did, new_did)) = did_pair { + let old_ty = self.tcx.type_of(old_did); + let new_ty = self.tcx.type_of(new_did); + let _ = self.tys(old_ty, new_ty); + } + + did_pair + } } impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { @@ -102,7 +116,7 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { /// implementation-internal reasons. fn relate_tys_mismatch<'a, 'gcx, 'tcx, R>(relation: &mut R, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> - where 'gcx: 'a+'tcx, 'tcx: 'a, R: TypeRelation<'a, 'gcx, 'tcx> + where 'gcx: 'a + 'tcx, 'tcx: 'a, R: TypeRelation<'a, 'gcx, 'tcx> { use rustc::ty::TypeVariants::*; diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index cf1a9ed9f49d1..6eaac7f47bb38 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -10,7 +10,6 @@ use rustc::hir::def_id::DefId; use rustc::ty::TyCtxt; use rustc::ty::Visibility::Public; use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; -use rustc::ty::relate::TypeRelation; use rustc::ty::subst::{Subst, Substs}; use std::collections::{HashMap, HashSet, VecDeque}; @@ -36,9 +35,7 @@ pub fn run_analysis(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { let mut mismatch = Mismatch::new(tcx, item_queue); - while let Some((old_did, new_did)) = mismatch.item_queue.pop_front() { - let _ = mismatch.tys(tcx.type_of(old_did), tcx.type_of(new_did)); - + while let Some((old_did, new_did)) = mismatch.process_next() { if !id_mapping.contains_id(old_did) { // println!("adding mapping: {:?} => {:?}", old_did, new_did); id_mapping.add_item(old_did, new_did); From 3a05de70b96301ae3677c04740441470e2cb6286 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 28 Jun 2017 00:40:33 +0200 Subject: [PATCH 091/553] Reduced complexity of mismatch relation. --- src/semcheck/mismatch.rs | 94 +++++++++++++--------------------------- 1 file changed, 31 insertions(+), 63 deletions(-) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index e79a0bf7827e4..f279372e0579f 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -1,7 +1,6 @@ use rustc::hir::def_id::DefId; use rustc::ty; use rustc::ty::{Ty, TyCtxt}; -use rustc::ty::error::TypeError; use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; use std::collections::{HashSet, VecDeque}; @@ -128,83 +127,52 @@ fn relate_tys_mismatch<'a, 'gcx, 'tcx, R>(relation: &mut R, a: Ty<'tcx>, b: Ty<' // As the original function this is ripped off of, we don't handle these cases. panic!("var types encountered in relate_tys_mismatch") }, - (&TyError, _) | (_, &TyError) => { + (&TyAdt(a_def, a_substs), &TyAdt(_, b_substs)) => { + let _ = relation.relate_item_substs(a_def.did, a_substs, b_substs)?; Ok(tcx.types.err) }, - (&TyNever, _) | - (&TyChar, _) | - (&TyBool, _) | - (&TyInt(_), _) | - (&TyUint(_), _) | - (&TyFloat(_), _) | - (&TyStr, _) | - (&TyParam(_), _) | - (&TyClosure(_, _), _) if a == b => { - Ok(a) - }, - (&TyAdt(a_def, a_substs), &TyAdt(_, b_substs)) => { - // TODO: possibly do something here - let substs = relation.relate_item_substs(a_def.did, a_substs, b_substs)?; - Ok(tcx.mk_adt(a_def, substs)) + (&TyDynamic(a_obj, a_r), &TyDynamic(b_obj, b_r)) => { + // TODO: more sophiticated mechanism here + let _ = relation.relate(&a_r, &b_r); + let _ = relation.relate(&a_obj, &b_obj); + Ok(tcx.types.err) }, - /* (&TyDynamic(_, _), &TyDynamic(_, _)) => { - // TODO: decide whether this is needed - let region_bound = relation.with_cause(Cause::ExistentialRegionBound, - |relation| { - relation.relate(a_region, b_region) - })?; - Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound)) - Err(TypeError::Mismatch) - },*/ - (&TyRawPtr(ref a_mt), &TyRawPtr(ref b_mt)) => { - let mt = relation.relate(a_mt, b_mt)?; - Ok(tcx.mk_ptr(mt)) + (&TyRawPtr(a_mt), &TyRawPtr(b_mt)) => { + let _ = relation.relate(&a_mt, &b_mt); + Ok(tcx.types.err) }, (&TyRef(a_r, a_mt), &TyRef(b_r, b_mt)) => { - let r = relation.relate(&a_r, &b_r)?; - let mt = relation.relate(&a_mt, &b_mt)?; - Ok(tcx.mk_ref(r, mt)) - }, - (&TyArray(a_t, sz_a), &TyArray(b_t, sz_b)) => { - let t = relation.relate(&a_t, &b_t)?; - if sz_a == sz_b { - Ok(tcx.mk_array(t, sz_a)) - } else { - Err(TypeError::Mismatch) - } + let _ = relation.relate(&a_r, &b_r); + let _ = relation.relate(&a_mt, &b_mt); + Ok(tcx.types.err) }, + (&TyArray(a_t, _), &TyArray(b_t, _)) | (&TySlice(a_t), &TySlice(b_t)) => { - let t = relation.relate(&a_t, &b_t)?; - Ok(tcx.mk_slice(t)) + relation.relate(&a_t, &b_t) }, - (&TyTuple(as_, a_defaulted), &TyTuple(bs, b_defaulted)) => { - let rs = as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)); - if as_.len() == bs.len() { - let defaulted = a_defaulted || b_defaulted; - tcx.mk_tup(rs, defaulted) - } else { - Err(TypeError::Mismatch) - } + (&TyTuple(as_, _), &TyTuple(bs, _)) => { + let _ = as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)); + Ok(tcx.types.err) }, - (&TyFnDef(a_def_id, a_substs, a_fty), &TyFnDef(_, b_substs, b_fty)) => { - let substs = ty::relate::relate_substs(relation, None, a_substs, b_substs)?; - let fty = relation.relate(&a_fty, &b_fty)?; - Ok(tcx.mk_fn_def(a_def_id, substs, fty)) + (&TyFnDef(_, a_substs, a_fty), &TyFnDef(_, b_substs, b_fty)) => { + let _ = ty::relate::relate_substs(relation, None, a_substs, b_substs)?; + let _ = relation.relate(&a_fty, &b_fty); + Ok(tcx.types.err) }, (&TyFnPtr(a_fty), &TyFnPtr(b_fty)) => { - let fty = relation.relate(&a_fty, &b_fty)?; - Ok(tcx.mk_fn_ptr(fty)) + let _ = relation.relate(&a_fty, &b_fty); + Ok(tcx.types.err) }, - (&TyProjection(ref a_data), &TyProjection(ref b_data)) => { - let projection_ty = relation.relate(a_data, b_data)?; - Ok(tcx.mk_projection(projection_ty.trait_ref, projection_ty.item_name(tcx))) + (&TyProjection(a_data), &TyProjection(b_data)) => { + let _ = relation.relate(&a_data, &b_data); + Ok(tcx.types.err) }, - (&TyAnon(a_def_id, a_substs), &TyAnon(_, b_substs)) => { - let substs = ty::relate::relate_substs(relation, None, a_substs, b_substs)?; - Ok(tcx.mk_anon(a_def_id, substs)) + (&TyAnon(_, a_substs), &TyAnon(_, b_substs)) => { + let _ = ty::relate::relate_substs(relation, None, a_substs, b_substs); + Ok(tcx.types.err) }, _ => { - Err(TypeError::Mismatch) + Ok(tcx.types.err) } } } From bb2a33f435a4ecb0ef389633fd4cad2591d29530 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 28 Jun 2017 15:37:40 +0200 Subject: [PATCH 092/553] Further shrinking of `relate_tys_mismatch`. --- src/semcheck/mismatch.rs | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index f279372e0579f..0b7f6d2821a8c 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -119,60 +119,48 @@ fn relate_tys_mismatch<'a, 'gcx, 'tcx, R>(relation: &mut R, a: Ty<'tcx>, b: Ty<' { use rustc::ty::TypeVariants::*; - let tcx = relation.tcx(); - let a_sty = &a.sty; - let b_sty = &b.sty; - match (a_sty, b_sty) { + match (&a.sty, &b.sty) { (&TyInfer(_), _) | (_, &TyInfer(_)) => { // As the original function this is ripped off of, we don't handle these cases. panic!("var types encountered in relate_tys_mismatch") }, (&TyAdt(a_def, a_substs), &TyAdt(_, b_substs)) => { let _ = relation.relate_item_substs(a_def.did, a_substs, b_substs)?; - Ok(tcx.types.err) }, (&TyDynamic(a_obj, a_r), &TyDynamic(b_obj, b_r)) => { // TODO: more sophiticated mechanism here let _ = relation.relate(&a_r, &b_r); let _ = relation.relate(&a_obj, &b_obj); - Ok(tcx.types.err) }, (&TyRawPtr(a_mt), &TyRawPtr(b_mt)) => { let _ = relation.relate(&a_mt, &b_mt); - Ok(tcx.types.err) }, (&TyRef(a_r, a_mt), &TyRef(b_r, b_mt)) => { let _ = relation.relate(&a_r, &b_r); let _ = relation.relate(&a_mt, &b_mt); - Ok(tcx.types.err) }, (&TyArray(a_t, _), &TyArray(b_t, _)) | (&TySlice(a_t), &TySlice(b_t)) => { - relation.relate(&a_t, &b_t) + let _ = relation.relate(&a_t, &b_t); }, (&TyTuple(as_, _), &TyTuple(bs, _)) => { let _ = as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)); - Ok(tcx.types.err) }, (&TyFnDef(_, a_substs, a_fty), &TyFnDef(_, b_substs, b_fty)) => { let _ = ty::relate::relate_substs(relation, None, a_substs, b_substs)?; let _ = relation.relate(&a_fty, &b_fty); - Ok(tcx.types.err) }, (&TyFnPtr(a_fty), &TyFnPtr(b_fty)) => { let _ = relation.relate(&a_fty, &b_fty); - Ok(tcx.types.err) }, (&TyProjection(a_data), &TyProjection(b_data)) => { let _ = relation.relate(&a_data, &b_data); - Ok(tcx.types.err) }, (&TyAnon(_, a_substs), &TyAnon(_, b_substs)) => { let _ = ty::relate::relate_substs(relation, None, a_substs, b_substs); - Ok(tcx.types.err) }, - _ => { - Ok(tcx.types.err) - } - } + _ => (), + }; + + Ok(relation.tcx().types.err) } From 9276b6982f551ac1dd86ce65c74dcd6f4ccb6226 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 29 Jun 2017 12:09:37 +0200 Subject: [PATCH 093/553] Added a debugging wrapper. --- .gitignore | 1 + tests/examples.rs | 35 ++++++++++++++++++++++++----------- tests/helper/test.rs | 1 + 3 files changed, 26 insertions(+), 11 deletions(-) create mode 100644 tests/helper/test.rs diff --git a/.gitignore b/.gitignore index 99a4f151eec77..2a2e51bd2b66a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ target/ **/*.rs.bk Cargo.lock *.rlib +tests/debug.sh diff --git a/tests/examples.rs b/tests/examples.rs index 3d12ac8cbcbba..3933ecca3a713 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -1,14 +1,13 @@ -#![feature(pattern)] use std::env; use std::fs::File; use std::io::Write; +use std::os::unix::fs::PermissionsExt; use std::os::unix::io::{AsRawFd, FromRawFd}; +use std::path::Path; use std::process::{Command, Stdio}; #[test] fn examples() { - use std::str::pattern::Pattern; - let mut success = true; let current_dir = env::current_dir().expect("could not determine current dir"); @@ -91,14 +90,28 @@ fn examples() { .status() .expect("could not run rm"); - if !success { - println!(); - for (name, value) in env::vars() { - // filter some crap *my* less puts there, rendering the terminal in a bright green :) - if !"LESS".is_contained_in(&name) { - println!("{}={}", name, value); - } - } + 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"); + + 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#"#!/bin/sh +rustc --crate-type=lib -o liboldandnew.rlib "$1" + +export LD_LIBRARY_PATH={} +export RUST_SEMVERVER_TEST=1 +export RUST_LOG=debug +export RUST_BACKTRACE=full +export RUST_SEMVER_CRATE_VERSION=1.0.0 + +arg_str="set args --crate-type=lib --extern oldandnew=liboldandnew.rlib - < tests/helper/test.rs" + +rust-gdb ./target/debug/rust-semverver -iex "$arg_str" +rm liboldandnew.rlib"#, path); } assert!(success, "an error occured"); diff --git a/tests/helper/test.rs b/tests/helper/test.rs new file mode 100644 index 0000000000000..b892b3f4f0838 --- /dev/null +++ b/tests/helper/test.rs @@ -0,0 +1 @@ +extern crate oldandnew; From 10280622193a4a5bf925b71d6e983b55873951eb Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 29 Jun 2017 14:31:42 +0200 Subject: [PATCH 094/553] Updated debugging wrapper to include rust source. --- tests/examples.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/examples.rs b/tests/examples.rs index 3933ecca3a713..3b9891295778f 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -109,8 +109,9 @@ export RUST_BACKTRACE=full export RUST_SEMVER_CRATE_VERSION=1.0.0 arg_str="set args --crate-type=lib --extern oldandnew=liboldandnew.rlib - < tests/helper/test.rs" +src_str="set substitute-path /checkout $(rustc --print sysroot)/lib/rustlib/src/rust" -rust-gdb ./target/debug/rust-semverver -iex "$arg_str" +rust-gdb ./target/debug/rust-semverver -iex "$arg_str" -iex "$src_str" rm liboldandnew.rlib"#, path); } From 93443b77e86e39b1f8cb9de51b55b5739118a6c8 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 29 Jun 2017 16:55:37 +0200 Subject: [PATCH 095/553] Fixed build with newest nightly. --- src/semcheck/mismatch.rs | 7 +++---- src/semcheck/traverse.rs | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 0b7f6d2821a8c..7a5b355741b3b 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -75,7 +75,7 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { let matching = match (&a.sty, &b.sty) { (&TyAdt(a_adt, _), &TyAdt(b_adt, _)) => Some((a_adt.did, b_adt.did)), - (&TyFnDef(a_did, _, _), &TyFnDef(b_did, _, _)) | + (&TyFnDef(a_did, _), &TyFnDef(b_did, _)) | (&TyClosure(a_did, _), &TyClosure(b_did, _)) | (&TyAnon(a_did, _), &TyAnon(b_did, _)) => Some((a_did, b_did)), (&TyProjection(a_proj), &TyProjection(b_proj)) => @@ -146,9 +146,8 @@ fn relate_tys_mismatch<'a, 'gcx, 'tcx, R>(relation: &mut R, a: Ty<'tcx>, b: Ty<' (&TyTuple(as_, _), &TyTuple(bs, _)) => { let _ = as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)); }, - (&TyFnDef(_, a_substs, a_fty), &TyFnDef(_, b_substs, b_fty)) => { - let _ = ty::relate::relate_substs(relation, None, a_substs, b_substs)?; - let _ = relation.relate(&a_fty, &b_fty); + (&TyFnDef(a_def_id, a_substs), &TyFnDef(_, b_substs)) => { + let _ = relation.relate_item_substs(a_def_id, a_substs, b_substs); }, (&TyFnPtr(a_fty), &TyFnPtr(b_fty)) => { let _ = relation.relate(&a_fty, &b_fty); diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 6eaac7f47bb38..d9e254a4b3b14 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -228,7 +228,7 @@ fn diff_fn(changes: &mut ChangeSet, let new_ty = tcx.type_of(new_def_id); let (old_sig, new_sig) = match (&old_ty.sty, &new_ty.sty) { - (&TyFnDef(_, _, ref o), &TyFnDef(_, _, ref n)) | + // TODO: (&TyFnDef(_, _, ref o), &TyFnDef(_, _, ref n)) | (&TyFnPtr(ref o), &TyFnPtr(ref n)) => (o.skip_binder(), n.skip_binder()), _ => return, }; From 451a8209883b5171197018edc0bba006d723650a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 29 Jun 2017 17:18:28 +0200 Subject: [PATCH 096/553] Reimplemented structural checks on functions for the newest nightly. --- src/semcheck/traverse.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index d9e254a4b3b14..ff5bc61bb9082 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -219,7 +219,6 @@ fn diff_fn(changes: &mut ChangeSet, old: Export, new: Export) { use rustc::hir::Unsafety::Unsafe; - use rustc::ty::TypeVariants::*; let old_def_id = old.def.def_id(); let new_def_id = new.def.def_id(); @@ -227,11 +226,15 @@ fn diff_fn(changes: &mut ChangeSet, let old_ty = tcx.type_of(old_def_id); let new_ty = tcx.type_of(new_def_id); - let (old_sig, new_sig) = match (&old_ty.sty, &new_ty.sty) { - // TODO: (&TyFnDef(_, _, ref o), &TyFnDef(_, _, ref n)) | - (&TyFnPtr(ref o), &TyFnPtr(ref n)) => (o.skip_binder(), n.skip_binder()), - _ => return, - }; + if !old_ty.is_fn() || !new_ty.is_fn() { + return; + } + + let old_poly_sig = old_ty.fn_sig(tcx); + let new_poly_sig = new_ty.fn_sig(tcx); + + let old_sig = old_poly_sig.skip_binder(); + let new_sig = new_poly_sig.skip_binder(); if old_sig.variadic != new_sig.variadic { changes.add_binary(FnVariadicChanged, old_def_id, None); From a1d173660a04c1d0d82b9ba78890e395fb6e5ed5 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 29 Jun 2017 19:53:53 +0200 Subject: [PATCH 097/553] Cleaned up type relation in the second pass. --- src/semcheck/id_mapping.rs | 25 +++++-- src/semcheck/mismatch.rs | 147 +++++++++++++++++-------------------- src/semcheck/traverse.rs | 36 +++------ tests/examples/infer.out | 16 ++-- tests/examples/infer.rs | 10 ++- 5 files changed, 113 insertions(+), 121 deletions(-) diff --git a/src/semcheck/id_mapping.rs b/src/semcheck/id_mapping.rs index 267eb76bcebd4..ab3f71b68c22b 100644 --- a/src/semcheck/id_mapping.rs +++ b/src/semcheck/id_mapping.rs @@ -2,7 +2,7 @@ use rustc::hir::def::Def; use rustc::hir::def::Export; use rustc::hir::def_id::DefId; -use std::collections::HashMap; +use std::collections::{HashMap, VecDeque}; /// A mapping from old to new `DefId`s, as well as exports. /// @@ -19,14 +19,22 @@ pub struct IdMapping { impl IdMapping { /// Register two exports representing the same item across versions. pub fn add_export(&mut self, old: Export, new: Export) -> bool { - self.toplevel_mapping - .insert(old.def.def_id(), (new.def.def_id(), old, new)) - .is_some() + if !self.toplevel_mapping.contains_key(&old.def.def_id()) { + self.toplevel_mapping + .insert(old.def.def_id(), (new.def.def_id(), old, new)); + return true; + } + + false } /// Add any other item pair's old and new `DefId`s. pub fn add_item(&mut self, old: DefId, new: DefId) { - self.mapping.insert(old, new); + if !self.mapping.contains_key(&old) { + self.mapping.insert(old, new); + } else { + panic!("bug: overwriting {:?} => {:?} with {:?}!", old, self.mapping[&old], new); + } } /// Get the new `DefId` associated with the given old one. @@ -42,6 +50,13 @@ impl IdMapping { pub fn contains_id(&self, old: DefId) -> bool { self.toplevel_mapping.contains_key(&old) || self.mapping.contains_key(&old) } + + pub fn construct_queue(&self) -> VecDeque<(DefId, DefId)> { + self.toplevel_mapping + .values() + .map(|&(_, old, new)| (old.def.def_id(), new.def.def_id())) + .collect() + } } /// A representation of a namespace an item belongs to. diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 7a5b355741b3b..c42e4e685b303 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -3,7 +3,9 @@ use rustc::ty; use rustc::ty::{Ty, TyCtxt}; use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; -use std::collections::{HashSet, VecDeque}; +use semcheck::id_mapping::IdMapping; + +use std::collections::VecDeque; /// A relation searching for items appearing at the same spot in a type. /// @@ -15,33 +17,30 @@ pub struct Mismatch<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, /// The queue to append found item pairings. item_queue: VecDeque<(DefId, DefId)>, - /// All visited items. - visited: HashSet<(DefId, DefId)>, + /// The id mapping to use. + id_mapping: &'a mut IdMapping, } impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> Mismatch<'a, 'gcx, 'tcx> { /// Construct a new mismtach type relation. - pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, item_queue: VecDeque<(DefId, DefId)>) + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a mut IdMapping) -> Mismatch<'a, 'gcx, 'tcx> { Mismatch { tcx: tcx, - item_queue: item_queue, - visited: Default::default(), + item_queue: id_mapping.construct_queue(), + id_mapping: id_mapping, } } /// Process the next pair of `DefId`s in the queue and return them. - pub fn process_next(&mut self) -> Option<(DefId, DefId)> { - let did_pair = self.item_queue.pop_front(); - - if let Some((old_did, new_did)) = did_pair { + pub fn process(&mut self) { + while let Some((old_did, new_did)) = self.item_queue.pop_front() { let old_ty = self.tcx.type_of(old_did); let new_ty = self.tcx.type_of(new_did); - let _ = self.tys(old_ty, new_ty); + // println!("processing types: {:?}, {:?}", old_ty, new_ty); + let _ = self.relate(&old_ty, &new_ty); } - - did_pair } } @@ -73,26 +72,73 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { use rustc::ty::TypeVariants::*; + // TODO: maybe fetch def ids from TyFnDef, TyClosure, TyAnon, TyProjection let matching = match (&a.sty, &b.sty) { - (&TyAdt(a_adt, _), &TyAdt(b_adt, _)) => Some((a_adt.did, b_adt.did)), - (&TyFnDef(a_did, _), &TyFnDef(b_did, _)) | - (&TyClosure(a_did, _), &TyClosure(b_did, _)) | - (&TyAnon(a_did, _), &TyAnon(b_did, _)) => Some((a_did, b_did)), - (&TyProjection(a_proj), &TyProjection(b_proj)) => - Some((a_proj.trait_ref.def_id, b_proj.trait_ref.def_id)), - _ => { + (&TyInfer(_), _) | (_, &TyInfer(_)) => { + // As the original function this is ripped off of, we don't handle these cases. + panic!("var types encountered in Mismatch::tys") + }, + (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs)) => { + let _ = self.relate_item_substs(a_def.did, a_substs, b_substs)?; + Some((a_def.did, b_def.did)) + }, + (&TyDynamic(a_obj, a_r), &TyDynamic(b_obj, b_r)) => { + if let (Some(a), Some(b)) = (a_obj.principal(), b_obj.principal()) { + println!("kinda found mapping: {:?} => {:?}", + a.skip_binder().def_id, + b.skip_binder().def_id); + } + + let _ = self.relate(&a_r, &b_r); + let _ = self.relate(&a_obj, &b_obj); + None + }, + (&TyRawPtr(a_mt), &TyRawPtr(b_mt)) => { + let _ = self.relate(&a_mt, &b_mt); + None + }, + (&TyRef(a_r, a_mt), &TyRef(b_r, b_mt)) => { + let _ = self.relate(&a_r, &b_r); + let _ = self.relate(&a_mt, &b_mt); + None + }, + (&TyArray(a_t, _), &TyArray(b_t, _)) | + (&TySlice(a_t), &TySlice(b_t)) => { + let _ = self.relate(&a_t, &b_t); + None + }, + (&TyTuple(as_, _), &TyTuple(bs, _)) => { + let _ = as_.iter().zip(bs).map(|(a, b)| self.relate(a, b)); + None + }, + (&TyFnDef(a_def_id, a_substs), &TyFnDef(_, b_substs)) => { + let _ = self.relate_item_substs(a_def_id, a_substs, b_substs); + None + }, + (&TyFnPtr(a_fty), &TyFnPtr(b_fty)) => { + let _ = self.relate(&a_fty, &b_fty); + None + }, + (&TyProjection(a_data), &TyProjection(b_data)) => { + let _ = self.relate(&a_data, &b_data); + None + }, + (&TyAnon(_, a_substs), &TyAnon(_, b_substs)) => { + let _ = ty::relate::relate_substs(self, None, a_substs, b_substs); None }, + _ => None, }; if let Some(dids) = matching { - if !self.visited.contains(&dids) { - self.visited.insert(dids); + if !self.id_mapping.contains_id(dids.0) { + // println!("adding mapping: {:?} => {:?}", dids.0, dids.1); + self.id_mapping.add_item(dids.0, dids.1); self.item_queue.push_back(dids); } } - relate_tys_mismatch(self, a, b) + Ok(self.tcx.types.err) } fn regions(&mut self, a: ty::Region<'tcx>, _: ty::Region<'tcx>) @@ -108,58 +154,3 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { Ok(ty::Binder(self.relate(a.skip_binder(), b.skip_binder())?)) } } - -/// Relate two items after possible matches have been recorded. -/// -/// This assumes the usage of the `Mismatch` type relation. The parametrization is used for -/// implementation-internal reasons. -fn relate_tys_mismatch<'a, 'gcx, 'tcx, R>(relation: &mut R, a: Ty<'tcx>, b: Ty<'tcx>) - -> RelateResult<'tcx, Ty<'tcx>> - where 'gcx: 'a + 'tcx, 'tcx: 'a, R: TypeRelation<'a, 'gcx, 'tcx> -{ - use rustc::ty::TypeVariants::*; - - match (&a.sty, &b.sty) { - (&TyInfer(_), _) | (_, &TyInfer(_)) => { - // As the original function this is ripped off of, we don't handle these cases. - panic!("var types encountered in relate_tys_mismatch") - }, - (&TyAdt(a_def, a_substs), &TyAdt(_, b_substs)) => { - let _ = relation.relate_item_substs(a_def.did, a_substs, b_substs)?; - }, - (&TyDynamic(a_obj, a_r), &TyDynamic(b_obj, b_r)) => { - // TODO: more sophiticated mechanism here - let _ = relation.relate(&a_r, &b_r); - let _ = relation.relate(&a_obj, &b_obj); - }, - (&TyRawPtr(a_mt), &TyRawPtr(b_mt)) => { - let _ = relation.relate(&a_mt, &b_mt); - }, - (&TyRef(a_r, a_mt), &TyRef(b_r, b_mt)) => { - let _ = relation.relate(&a_r, &b_r); - let _ = relation.relate(&a_mt, &b_mt); - }, - (&TyArray(a_t, _), &TyArray(b_t, _)) | - (&TySlice(a_t), &TySlice(b_t)) => { - let _ = relation.relate(&a_t, &b_t); - }, - (&TyTuple(as_, _), &TyTuple(bs, _)) => { - let _ = as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)); - }, - (&TyFnDef(a_def_id, a_substs), &TyFnDef(_, b_substs)) => { - let _ = relation.relate_item_substs(a_def_id, a_substs, b_substs); - }, - (&TyFnPtr(a_fty), &TyFnPtr(b_fty)) => { - let _ = relation.relate(&a_fty, &b_fty); - }, - (&TyProjection(a_data), &TyProjection(b_data)) => { - let _ = relation.relate(&a_data, &b_data); - }, - (&TyAnon(_, a_substs), &TyAnon(_, b_substs)) => { - let _ = ty::relate::relate_substs(relation, None, a_substs, b_substs); - }, - _ => (), - }; - - Ok(relation.tcx().types.err) -} diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index ff5bc61bb9082..1b78ec60e0b7e 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -1,9 +1,3 @@ -use semcheck::changes::BinaryChangeType; -use semcheck::changes::BinaryChangeType::*; -use semcheck::changes::ChangeSet; -use semcheck::id_mapping::{get_namespace, IdMapping}; -use semcheck::mismatch::Mismatch; - use rustc::hir::def::CtorKind; use rustc::hir::def::Export; use rustc::hir::def_id::DefId; @@ -12,6 +6,12 @@ use rustc::ty::Visibility::Public; use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; use rustc::ty::subst::{Subst, Substs}; +use semcheck::changes::BinaryChangeType; +use semcheck::changes::BinaryChangeType::*; +use semcheck::changes::ChangeSet; +use semcheck::id_mapping::{get_namespace, IdMapping}; +use semcheck::mismatch::Mismatch; + use std::collections::{HashMap, HashSet, VecDeque}; /// The main entry point to our analysis passes. @@ -26,21 +26,8 @@ pub fn run_analysis(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { // second pass { - let item_queue: VecDeque<_> = - id_mapping - .toplevel_mapping - .values() - .map(|&(_, old, new)| (old.def.def_id(), new.def.def_id())) - .collect(); - - let mut mismatch = Mismatch::new(tcx, item_queue); - - while let Some((old_did, new_did)) = mismatch.process_next() { - if !id_mapping.contains_id(old_did) { - // println!("adding mapping: {:?} => {:?}", old_did, new_did); - id_mapping.add_item(old_did, new_did); - } - } + let mut mismatch = Mismatch::new(tcx, &mut id_mapping); + mismatch.process(); } // third pass @@ -123,7 +110,7 @@ fn diff_structure(changes: &mut ChangeSet, } } (Some(o), Some(n)) => { - if !id_mapping.add_export(o, n) { + if id_mapping.add_export(o, n) { let o_def_id = o.def.def_id(); let n_def_id = n.def.def_id(); let o_vis = if old_vis == Public { @@ -468,13 +455,10 @@ fn diff_types(changes: &mut ChangeSet, } }}); - // println!("old_ty: {:?}", old_ty_cmp); - // println!("new_ty: {:?}", new_ty); - if let Err(err) = tcx.global_tcx().infer_ctxt() .enter(|infcx| infcx.can_eq(tcx.param_env(new_def_id), old_ty_cmp, new_ty)) { - // println!("diff: {}", err); + // TODO: possibly rename this. changes.add_binary(FieldTypeChanged(format!("{}", err)), old_def_id, None); } } diff --git a/tests/examples/infer.out b/tests/examples/infer.out index b58a299acde3f..95fadab1f337a 100644 --- a/tests/examples/infer.out +++ b/tests/examples/infer.out @@ -1,20 +1,20 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 warning: Breaking changes in `a` - --> $REPO_PATH/tests/examples/infer.rs:32:5 + --> $REPO_PATH/tests/examples/infer.rs:33:5 | -32 | / pub fn a(a: A) -> A { -33 | | a -34 | | } +33 | / pub fn a(a: A) -> A { +34 | | a +35 | | } | |_____^ | = warning: Breaking (FieldTypeChanged("expected fn item, found a different fn item")) warning: Breaking changes in `b` - --> $REPO_PATH/tests/examples/infer.rs:36:5 + --> $REPO_PATH/tests/examples/infer.rs:37:5 | -36 | / pub fn b() -> a::Opq { -37 | | a::Opq -38 | | } +37 | / pub fn b() -> a::Opq { +38 | | a::Opq +39 | | } | |_____^ | = warning: Breaking (FieldTypeChanged("expected fn item, found a different fn item")) diff --git a/tests/examples/infer.rs b/tests/examples/infer.rs index 0eded7bf8ff5d..7e1360a9bdc6e 100644 --- a/tests/examples/infer.rs +++ b/tests/examples/infer.rs @@ -15,8 +15,9 @@ pub mod old { a::Klm } - pub struct Hij { - pub field: Box, + pub struct Hij<'a> { + pub field: &'a a::Abc, + pub field2: ::std::rc::Rc, } } @@ -37,7 +38,8 @@ pub mod new { a::Opq } - pub struct Hij { - pub field: Box, + pub struct Hij<'a> { + pub field: &'a a::Def, + pub field2: ::std::rc::Rc, } } From bfe367073c7cefe107bcd792fc88a884d59e8243 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 29 Jun 2017 22:09:10 +0200 Subject: [PATCH 098/553] Fixed type relation's function signature traversal. --- src/semcheck/mismatch.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index c42e4e685b303..a23642ad7729d 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -112,7 +112,10 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { None }, (&TyFnDef(a_def_id, a_substs), &TyFnDef(_, 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()); None }, (&TyFnPtr(a_fty), &TyFnPtr(b_fty)) => { From 837716cb41df90c5205a6703ee31c778d59f7d4b Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 30 Jun 2017 00:11:32 +0200 Subject: [PATCH 099/553] Implemented ADT traversal in type relation. --- src/semcheck/mismatch.rs | 24 +++++++++++++++++++++++- tests/examples/infer.out | 2 ++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index a23642ad7729d..4b3057427cb21 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -1,11 +1,12 @@ use rustc::hir::def_id::DefId; use rustc::ty; use rustc::ty::{Ty, TyCtxt}; +use rustc::ty::Visibility::Public; use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; use semcheck::id_mapping::IdMapping; -use std::collections::VecDeque; +use std::collections::{HashMap, VecDeque}; /// A relation searching for items appearing at the same spot in a type. /// @@ -80,6 +81,27 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { }, (&TyAdt(a_def, a_substs), &TyAdt(b_def, 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) { + if self.id_mapping.contains_id(field.did) { + let a_field_ty = field.ty(self.tcx, a_substs); + let b_field_ty = + b_fields[&self.id_mapping.get_new_id(field.did)] + .ty(self.tcx, b_substs); + + // println!("found: {:?}, {:?}", a_field_ty, b_field_ty); + let _ = self.relate(&a_field_ty, &b_field_ty); + } + } + Some((a_def.did, b_def.did)) }, (&TyDynamic(a_obj, a_r), &TyDynamic(b_obj, b_r)) => { diff --git a/tests/examples/infer.out b/tests/examples/infer.out index 95fadab1f337a..cc665c1034bf7 100644 --- a/tests/examples/infer.out +++ b/tests/examples/infer.out @@ -1,3 +1,5 @@ +kinda found mapping: DefId { krate: CrateNum(11), node: DefIndex(5) => infer/8cd878b::old[0]::a[0]::Abc[0] } => DefId { krate: CrateNum(11), node: DefIndex(12) => infer/8cd878b::new[0]::a[0]::Def[0] } +kinda found mapping: DefId { krate: CrateNum(11), node: DefIndex(5) => infer/8cd878b::old[0]::a[0]::Abc[0] } => DefId { krate: CrateNum(11), node: DefIndex(12) => infer/8cd878b::new[0]::a[0]::Def[0] } version bump: 1.0.0 -> (Breaking) -> 2.0.0 warning: Breaking changes in `a` --> $REPO_PATH/tests/examples/infer.rs:33:5 From dc4ab3dc8b040313430578e556907120a5503e3e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 30 Jun 2017 18:49:52 +0200 Subject: [PATCH 100/553] Avoid matching up items from other crates in the type relation. --- src/semcheck/mismatch.rs | 32 ++++++++++++++++++++++---------- src/semcheck/traverse.rs | 2 +- tests/examples/infer.out | 2 -- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 4b3057427cb21..967956d6ce802 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -1,4 +1,4 @@ -use rustc::hir::def_id::DefId; +use rustc::hir::def_id::{CrateNum, DefId}; use rustc::ty; use rustc::ty::{Ty, TyCtxt}; use rustc::ty::Visibility::Public; @@ -20,17 +20,20 @@ pub struct Mismatch<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { item_queue: VecDeque<(DefId, DefId)>, /// The id mapping to use. id_mapping: &'a mut IdMapping, + /// The old crate. + old_crate: CrateNum, } impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> Mismatch<'a, 'gcx, 'tcx> { /// Construct a new mismtach type relation. - pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a mut IdMapping) + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, old_crate: CrateNum, id_mapping: &'a mut IdMapping) -> Mismatch<'a, 'gcx, 'tcx> { Mismatch { tcx: tcx, item_queue: id_mapping.construct_queue(), id_mapping: id_mapping, + old_crate: old_crate, } } @@ -97,7 +100,6 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { b_fields[&self.id_mapping.get_new_id(field.did)] .ty(self.tcx, b_substs); - // println!("found: {:?}, {:?}", a_field_ty, b_field_ty); let _ = self.relate(&a_field_ty, &b_field_ty); } } @@ -105,15 +107,25 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { Some((a_def.did, b_def.did)) }, (&TyDynamic(a_obj, a_r), &TyDynamic(b_obj, b_r)) => { + // let _ = self.relate(&a_obj, &b_obj); + let _ = self.relate(&a_r, &b_r); + if let (Some(a), Some(b)) = (a_obj.principal(), b_obj.principal()) { - println!("kinda found mapping: {:?} => {:?}", + let _ = self.relate(&a, &b); + /* println!("kinda adding mapping: {:?} => {:?}", a.skip_binder().def_id, - b.skip_binder().def_id); - } + b.skip_binder().def_id); */ + let a_did = a.skip_binder().def_id; + let b_did = b.skip_binder().def_id; + if !self.id_mapping.contains_id(a_did) && a_did.krate == self.old_crate { + self.id_mapping.add_item(a_did, b_did); + } - let _ = self.relate(&a_r, &b_r); - let _ = self.relate(&a_obj, &b_obj); - None + // TODO: Some((a.skip_binder().def_id, b.skip_binder().def_id)) + None + } else { + None + } }, (&TyRawPtr(a_mt), &TyRawPtr(b_mt)) => { let _ = self.relate(&a_mt, &b_mt); @@ -156,7 +168,7 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { }; if let Some(dids) = matching { - if !self.id_mapping.contains_id(dids.0) { + if !self.id_mapping.contains_id(dids.0) && dids.0.krate == self.old_crate { // println!("adding mapping: {:?} => {:?}", dids.0, dids.1); self.id_mapping.add_item(dids.0, dids.1); self.item_queue.push_back(dids); diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 1b78ec60e0b7e..794aa88846158 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -26,7 +26,7 @@ pub fn run_analysis(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { // second pass { - let mut mismatch = Mismatch::new(tcx, &mut id_mapping); + let mut mismatch = Mismatch::new(tcx, old.krate, &mut id_mapping); mismatch.process(); } diff --git a/tests/examples/infer.out b/tests/examples/infer.out index cc665c1034bf7..95fadab1f337a 100644 --- a/tests/examples/infer.out +++ b/tests/examples/infer.out @@ -1,5 +1,3 @@ -kinda found mapping: DefId { krate: CrateNum(11), node: DefIndex(5) => infer/8cd878b::old[0]::a[0]::Abc[0] } => DefId { krate: CrateNum(11), node: DefIndex(12) => infer/8cd878b::new[0]::a[0]::Def[0] } -kinda found mapping: DefId { krate: CrateNum(11), node: DefIndex(5) => infer/8cd878b::old[0]::a[0]::Abc[0] } => DefId { krate: CrateNum(11), node: DefIndex(12) => infer/8cd878b::new[0]::a[0]::Def[0] } version bump: 1.0.0 -> (Breaking) -> 2.0.0 warning: Breaking changes in `a` --> $REPO_PATH/tests/examples/infer.rs:33:5 From b13e685288a604c9d7878918340c947649f86b46 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 1 Jul 2017 12:27:21 +0200 Subject: [PATCH 101/553] Removed ugly string allocation from type error handling. --- src/semcheck/changes.rs | 89 +++++++++++++++++-------------------- src/semcheck/traverse.rs | 55 ++++++++++++----------- tests/examples/fn.out | 4 +- tests/examples/infer.out | 4 +- tests/examples/struct.out | 16 +++---- tests/examples/ty_alias.out | 4 +- 6 files changed, 86 insertions(+), 86 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 847b051adae32..89b8ef2439915 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -1,10 +1,11 @@ use rustc::hir::def::Export; use rustc::hir::def_id::DefId; use rustc::session::Session; +use rustc::ty::error::TypeError; use semver::Version; -use std::collections::{BTreeSet, BTreeMap, HashMap}; +use std::collections::{BTreeMap, HashMap}; use std::cmp::Ordering; use syntax::symbol::Ident; @@ -119,8 +120,8 @@ impl Ord for UnaryChange { /// The types of changes we identify between items present in both crate versions. // TODO: this needs a lot of refinement still -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum BinaryChangeType { +#[derive(Clone, Debug)] +pub enum BinaryChangeType<'tcx> { /// An item has been made public. ItemMadePublic, /// An item has been made private @@ -150,7 +151,7 @@ pub enum BinaryChangeType { /// A variant has changed it's style. VariantStyleChanged { now_struct: bool, total_private: bool }, /// A field in a struct or enum has changed it's type. - FieldTypeChanged(String), // FIXME: terrible for obvious reasons + FieldTypeChanged(TypeError<'tcx>), /// An impl item has been added. TraitImplItemAdded { defaulted: bool }, /// An impl item has been removed. @@ -169,7 +170,7 @@ pub enum BinaryChangeType { pub use self::BinaryChangeType::*; -impl BinaryChangeType { +impl<'tcx> BinaryChangeType<'tcx> { // TODO: this will need a lot of changes (it's *very* conservative rn) pub fn to_category(&self) -> ChangeCategory { match *self { @@ -208,9 +209,9 @@ impl BinaryChangeType { /// by appearance in the *new* source, but possibly could create conflict later on. // TODO: we should introduce an invariant that the two exports present are *always* // tied together. -pub struct BinaryChange { +pub struct BinaryChange<'tcx> { /// The type of the change affecting the item. - changes: BTreeSet<(BinaryChangeType, Option)>, + changes: Vec<(BinaryChangeType<'tcx>, Option)>, /// The most severe change category already recorded for the item. max: ChangeCategory, /// The old export of the change item. @@ -221,11 +222,11 @@ pub struct BinaryChange { output: bool } -impl BinaryChange { +impl<'tcx> BinaryChange<'tcx> { /// Construct a new empty change record for an item. - fn new(old: Export, new: Export, output: bool) -> BinaryChange { + fn new(old: Export, new: Export, output: bool) -> BinaryChange<'tcx> { BinaryChange { - changes: BTreeSet::new(), + changes: Vec::new(), max: ChangeCategory::default(), old: old, new: new, @@ -234,14 +235,14 @@ impl BinaryChange { } /// Add another change type to the change record. - fn add(&mut self, type_: BinaryChangeType, span: Option) { + fn add(&mut self, type_: BinaryChangeType<'tcx>, span: Option) { let cat = type_.to_category(); if cat > self.max { self.max = cat; } - self.changes.insert((type_, span)); + self.changes.push((type_, span)); } /// Get the change's category. @@ -289,22 +290,22 @@ impl BinaryChange { } } -impl PartialEq for BinaryChange { +impl<'tcx> PartialEq for BinaryChange<'tcx> { fn eq(&self, other: &BinaryChange) -> bool { self.new_span() == other.new_span() } } -impl Eq for BinaryChange {} +impl<'tcx> Eq for BinaryChange<'tcx> {} -impl PartialOrd for BinaryChange { - fn partial_cmp(&self, other: &BinaryChange) -> Option { +impl<'tcx> PartialOrd for BinaryChange<'tcx> { + fn partial_cmp(&self, other: &BinaryChange<'tcx>) -> Option { self.new_span().partial_cmp(other.new_span()) } } -impl Ord for BinaryChange { - fn cmp(&self, other: &BinaryChange) -> Ordering { +impl<'tcx> Ord for BinaryChange<'tcx> { + fn cmp(&self, other: &BinaryChange<'tcx>) -> Ordering { self.new_span().cmp(other.new_span()) } } @@ -314,31 +315,31 @@ impl Ord for BinaryChange { /// Consists of all information we need to compute semantic versioning properties of /// the change(s) performed on it, as well as data we use to output it in a nice fashion. #[derive(PartialEq, Eq, PartialOrd, Ord)] -pub enum Change { +pub enum Change<'tcx> { /// A wrapper around a unary change. Unary(UnaryChange), /// A wrapper around a binary change set. - Binary(BinaryChange), + Binary(BinaryChange<'tcx>), } -impl Change { +impl<'tcx> Change<'tcx> { /// Construct a new addition-change for the given export. - fn new_addition(item: Export) -> Change { + fn new_addition(item: Export) -> Change<'tcx> { Change::Unary(UnaryChange::Addition(item)) } /// Construct a new removal-change for the given export. - fn new_removal(item: Export) -> Change { + fn new_removal(item: Export) -> Change<'tcx> { Change::Unary(UnaryChange::Removal(item)) } /// Construct a new binary change for the given exports. - fn new_binary(old: Export, new: Export, output: bool) -> Change { + fn new_binary(old: Export, new: Export, output: bool) -> Change<'tcx> { Change::Binary(BinaryChange::new(old, new, output)) } /// Add a change type to a given binary change. - fn add(&mut self, type_: BinaryChangeType, span: Option) { + fn add(&mut self, type_: BinaryChangeType<'tcx>, span: Option) { match *self { Change::Unary(_) => panic!("can't add binary change types to unary change"), Change::Binary(ref mut b) => b.add(type_, span), @@ -383,16 +384,16 @@ pub enum ChangeKey { /// The total set of changes recorded for two crate versions. #[derive(Default)] -pub struct ChangeSet { +pub struct ChangeSet<'tcx> { /// The currently recorded changes. - changes: HashMap, + changes: HashMap>, /// The mapping of spans to changes, for ordering purposes. spans: BTreeMap, /// The most severe change category already recorded. max: ChangeCategory, } -impl ChangeSet { +impl<'tcx> ChangeSet<'tcx> { /// Add a new addition-change for the given export. pub fn new_addition(&mut self, item: Export) { self.new_unary_change(Change::new_addition(item), ChangeKey::NewKey(item.def.def_id())); @@ -404,7 +405,7 @@ impl ChangeSet { } /// Add a new (unary) change for the given key. - fn new_unary_change(&mut self, change: Change, key: ChangeKey) { + fn new_unary_change(&mut self, change: Change<'tcx>, key: ChangeKey) { let cat = change.to_category(); if cat > self.max { @@ -425,7 +426,7 @@ impl ChangeSet { } /// Add a new binary change to an already existing entry. - pub fn add_binary(&mut self, type_: BinaryChangeType, old: DefId, span: Option) { + pub fn add_binary(&mut self, type_: BinaryChangeType<'tcx>, old: DefId, span: Option) { let key = ChangeKey::OldKey(old); let cat = type_.to_category(); @@ -525,12 +526,6 @@ pub mod tests { } } - impl Arbitrary for BinaryChangeType { - fn arbitrary(g: &mut G) -> BinaryChangeType { - g.choose(&[BinaryChangeType::Unknown]).unwrap().clone() - } - } - pub type UnaryChange_ = (UnaryChangeType, Span_); /// We build these by hand, because symbols can't be sent between threads. @@ -555,7 +550,7 @@ pub mod tests { } } - pub type BinaryChange_ = (BinaryChangeType, Span_, Span_); + pub type BinaryChange_ = (Span_, Span_); fn build_binary_change(t: BinaryChangeType, s1: Span, s2: Span) -> BinaryChange { let mut interner = Interner::new(); @@ -617,9 +612,9 @@ pub mod tests { fn ord_bchange_transitive(c1: BinaryChange_, c2: BinaryChange_, c3: BinaryChange_) -> bool { - let ch1 = build_binary_change(c1.0, c1.1.inner(), c1.2.inner()); - let ch2 = build_binary_change(c2.0, c2.1.inner(), c2.2.inner()); - let ch3 = build_binary_change(c3.0, c3.1.inner(), c3.2.inner()); + let ch1 = build_binary_change(Unknown, c1.0.inner(), c1.1.inner()); + let ch2 = build_binary_change(Unknown, c2.0.inner(), c2.1.inner()); + let ch3 = build_binary_change(Unknown, c3.0.inner(), c3.1.inner()); let mut res = true; @@ -657,11 +652,11 @@ pub mod tests { fn max_bchange(changes: Vec) -> bool { let mut set = ChangeSet::default(); - let max = changes.iter().map(|c| c.0.to_category()).max().unwrap_or(Patch); + let max = changes.iter().map(|_| Unknown.to_category()).max().unwrap_or(Patch); - for &(ref change, ref span1, ref span2) in changes.iter() { + for &(ref span1, ref span2) in changes.iter() { let change = - build_binary_change(change.clone(), + build_binary_change(Unknown, span1.clone().inner(), span2.clone().inner()); let key = ChangeKey::OldKey(change.old.def.def_id()); @@ -688,12 +683,12 @@ pub mod tests { /// Difference in spans implies difference in `Change`s. fn bchange_span_neq(c1: BinaryChange_, c2: BinaryChange_) -> bool { - let s1 = c1.1.inner(); - let s2 = c2.1.inner(); + let s1 = c1.0.inner(); + let s2 = c2.0.inner(); if s1 != s2 { - let ch1 = build_binary_change(c1.0, c1.2.inner(), s1); - let ch2 = build_binary_change(c2.0, c2.2.inner(), s2); + let ch1 = build_binary_change(Unknown, c1.1.inner(), s1); + let ch2 = build_binary_change(Unknown, c2.1.inner(), s2); ch1 != ch2 } else { diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 794aa88846158..85f7669f80b85 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -17,7 +17,9 @@ use std::collections::{HashMap, HashSet, VecDeque}; /// The main entry point to our analysis passes. /// /// Set up the necessary data structures and run the analysis passes. -pub fn run_analysis(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { +pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefId) + -> ChangeSet<'tcx> +{ let mut changes = Default::default(); let mut id_mapping = Default::default(); @@ -51,11 +53,11 @@ pub fn run_analysis(tcx: TyCtxt, old: DefId, new: DefId) -> ChangeSet { /// 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. -fn diff_structure(changes: &mut ChangeSet, - id_mapping: &mut IdMapping, - tcx: TyCtxt, - old: DefId, - new: DefId) { +fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, + id_mapping: &mut IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + old: DefId, + new: DefId) { use rustc::hir::def::Def::*; let cstore = &tcx.sess.cstore; @@ -201,10 +203,7 @@ fn diff_structure(changes: &mut ChangeSet, } /// Given two fn items, perform structural checks. -fn diff_fn(changes: &mut ChangeSet, - tcx: TyCtxt, - old: Export, - new: Export) { +fn diff_fn(changes: &mut ChangeSet, tcx: TyCtxt, old: Export, new: Export) { use rustc::hir::Unsafety::Unsafe; let old_def_id = old.def.def_id(); @@ -351,7 +350,9 @@ fn diff_adts(changes: &mut ChangeSet, } /// Given two items, compare their type and region parameter sets. -fn diff_generics(tcx: TyCtxt, old: DefId, new: DefId) -> Vec { +fn diff_generics(tcx: TyCtxt, old: DefId, new: DefId) + -> Vec> +{ use std::cmp::max; let mut ret = Vec::new(); @@ -403,8 +404,11 @@ fn diff_generics(tcx: TyCtxt, old: DefId, new: DefId) -> Vec { // being exported. /// Given two items, compare the bounds on their type and region parameters. -fn diff_bounds(_changes: &mut ChangeSet, _tcx: TyCtxt, _old: DefId, _new: DefId) - -> (Vec, Vec<(DefId, DefId)>) +fn diff_bounds<'a, 'tcx>(_changes: &mut ChangeSet, + _tcx: TyCtxt<'a, 'tcx, 'tcx>, + _old: DefId, + _new: DefId) + -> (Vec>, Vec<(DefId, DefId)>) { /* let res = Default::default(); @@ -420,12 +424,12 @@ fn diff_bounds(_changes: &mut ChangeSet, _tcx: TyCtxt, _old: DefId, _new: DefId) // matching items are compared for changes. /// Given two items, compare their types. -fn diff_types(changes: &mut ChangeSet, - id_mapping: &IdMapping, - tcx: TyCtxt, - old: Export, - new: Export) { - use rustc::ty::AdtDef; +fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + old: Export, + new: Export) { + use rustc::ty::{AdtDef, Lift}; use rustc::ty::TypeVariants::*; if changes.item_breaking(old.def.def_id()) { @@ -455,10 +459,11 @@ fn diff_types(changes: &mut ChangeSet, } }}); - if let Err(err) = tcx.global_tcx().infer_ctxt() - .enter(|infcx| infcx.can_eq(tcx.param_env(new_def_id), old_ty_cmp, new_ty)) - { - // TODO: possibly rename this. - changes.add_binary(FieldTypeChanged(format!("{}", err)), old_def_id, None); - } + tcx.infer_ctxt().enter(|infcx| + if let Err(err) = infcx.can_eq(tcx.param_env(new_def_id), old_ty_cmp, new_ty) { + // TODO: possibly rename this. + changes.add_binary(FieldTypeChanged(err.lift_to_tcx(tcx).unwrap()), + old_def_id, + None); + }); } diff --git a/tests/examples/fn.out b/tests/examples/fn.out index a640a082412fc..86358add59ffd 100644 --- a/tests/examples/fn.out +++ b/tests/examples/fn.out @@ -5,7 +5,7 @@ warning: Breaking changes in `abc` 12 | pub fn abc() {} | ^^^^^^^^^^^^^^^ | - = warning: Breaking (FieldTypeChanged("expected fn item, found a different fn item")) + = warning: Breaking (FieldTypeChanged(Sorts(ExpectedFound { expected: fn() {oldandnew::old::abc}, found: fn() {oldandnew::new::abc} }))) warning: Breaking changes in `bcd` --> $REPO_PATH/tests/examples/fn.rs:14:5 @@ -23,7 +23,7 @@ warning: Breaking changes in `cde` 18 | | } | |_____^ | - = warning: Breaking (FieldTypeChanged("expected fn item, found a different fn item")) + = warning: Breaking (FieldTypeChanged(Sorts(ExpectedFound { expected: fn() {oldandnew::old::cde}, found: fn() -> u16 {oldandnew::new::cde} }))) warning: Breaking changes in `def` --> $REPO_PATH/tests/examples/fn.rs:20:5 diff --git a/tests/examples/infer.out b/tests/examples/infer.out index 95fadab1f337a..728097d8fec20 100644 --- a/tests/examples/infer.out +++ b/tests/examples/infer.out @@ -7,7 +7,7 @@ warning: Breaking changes in `a` 35 | | } | |_____^ | - = warning: Breaking (FieldTypeChanged("expected fn item, found a different fn item")) + = warning: Breaking (FieldTypeChanged(Sorts(ExpectedFound { expected: fn(A) -> A {oldandnew::old::a::}, found: fn(A) -> A {oldandnew::new::a::} }))) warning: Breaking changes in `b` --> $REPO_PATH/tests/examples/infer.rs:37:5 @@ -17,5 +17,5 @@ warning: Breaking changes in `b` 39 | | } | |_____^ | - = warning: Breaking (FieldTypeChanged("expected fn item, found a different fn item")) + = warning: Breaking (FieldTypeChanged(Sorts(ExpectedFound { expected: fn() -> oldandnew::old::a::Klm {oldandnew::old::b}, found: fn() -> oldandnew::new::a::Opq {oldandnew::new::b} }))) diff --git a/tests/examples/struct.out b/tests/examples/struct.out index 11bc3ddfe64a3..a22626c5cb5b3 100644 --- a/tests/examples/struct.out +++ b/tests/examples/struct.out @@ -45,19 +45,19 @@ warning: Breaking changes in `Hij` 50 | | } | |_____^ | -warning: Breaking (VariantFieldAdded { public: false, total_public: false }) - --> $REPO_PATH/tests/examples/struct.rs:49:9 +warning: Breaking (VariantStyleChanged { now_struct: true, total_private: true }) + --> $REPO_PATH/tests/examples/struct.rs:23:5 | -49 | field: u8, - | ^^^^^^^^^ +23 | pub struct Hij(u8); + | ^^^^^^^^^^^^^^^^^^^ warning: Breaking (VariantFieldRemoved { public: false, total_public: false }) --> $REPO_PATH/tests/examples/struct.rs:23:20 | 23 | pub struct Hij(u8); | ^^^ -warning: Breaking (VariantStyleChanged { now_struct: true, total_private: true }) - --> $REPO_PATH/tests/examples/struct.rs:23:5 +warning: Breaking (VariantFieldAdded { public: false, total_public: false }) + --> $REPO_PATH/tests/examples/struct.rs:49:9 | -23 | pub struct Hij(u8); - | ^^^^^^^^^^^^^^^^^^^ +49 | field: u8, + | ^^^^^^^^^ diff --git a/tests/examples/ty_alias.out b/tests/examples/ty_alias.out index c7e82989aa111..a36595e9886c8 100644 --- a/tests/examples/ty_alias.out +++ b/tests/examples/ty_alias.out @@ -5,7 +5,7 @@ warning: Breaking changes in `A` 12 | pub type A = u16; | ^^^^^^^^^^^^^^^^^ | - = warning: Breaking (FieldTypeChanged("expected u8, found u16")) + = warning: Breaking (FieldTypeChanged(Sorts(ExpectedFound { expected: u8, found: u16 }))) warning: Breaking changes in `B` --> $REPO_PATH/tests/examples/ty_alias.rs:13:5 @@ -30,7 +30,7 @@ warning: Breaking changes in `D` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: NonBreaking (TypeParameterAdded { defaulted: true }) - = warning: Breaking (FieldTypeChanged("expected reference, found tuple")) + = warning: Breaking (FieldTypeChanged(Sorts(ExpectedFound { expected: &'a T, found: (&'a T, U) }))) warning: Breaking changes in `E` --> $REPO_PATH/tests/examples/ty_alias.rs:16:5 From 2be8b44a4a96684d1f6128dc18b6c492f3104995 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 1 Jul 2017 12:59:58 +0200 Subject: [PATCH 102/553] Renamed the change type wrapping type errors. --- src/semcheck/changes.rs | 5 ++--- src/semcheck/traverse.rs | 3 +-- tests/examples/fn.out | 4 ++-- tests/examples/infer.out | 4 ++-- tests/examples/ty_alias.out | 4 ++-- 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 89b8ef2439915..0f574e1cd2719 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -119,7 +119,6 @@ impl Ord for UnaryChange { } /// The types of changes we identify between items present in both crate versions. -// TODO: this needs a lot of refinement still #[derive(Clone, Debug)] pub enum BinaryChangeType<'tcx> { /// An item has been made public. @@ -151,7 +150,7 @@ pub enum BinaryChangeType<'tcx> { /// A variant has changed it's style. VariantStyleChanged { now_struct: bool, total_private: bool }, /// A field in a struct or enum has changed it's type. - FieldTypeChanged(TypeError<'tcx>), + TypeChanged { error: TypeError<'tcx> }, /// An impl item has been added. TraitImplItemAdded { defaulted: bool }, /// An impl item has been removed. @@ -186,7 +185,7 @@ impl<'tcx> BinaryChangeType<'tcx> { VariantFieldAdded { .. } | VariantFieldRemoved { .. } | VariantStyleChanged { .. } | - FieldTypeChanged(_) | + TypeChanged { .. } | TraitImplItemAdded { .. } | TraitImplItemRemoved | FnVariadicChanged | diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 85f7669f80b85..5b75434438a82 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -461,8 +461,7 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, tcx.infer_ctxt().enter(|infcx| if let Err(err) = infcx.can_eq(tcx.param_env(new_def_id), old_ty_cmp, new_ty) { - // TODO: possibly rename this. - changes.add_binary(FieldTypeChanged(err.lift_to_tcx(tcx).unwrap()), + changes.add_binary(TypeChanged { error: err.lift_to_tcx(tcx).unwrap() }, old_def_id, None); }); diff --git a/tests/examples/fn.out b/tests/examples/fn.out index 86358add59ffd..81de4288094ff 100644 --- a/tests/examples/fn.out +++ b/tests/examples/fn.out @@ -5,7 +5,7 @@ warning: Breaking changes in `abc` 12 | pub fn abc() {} | ^^^^^^^^^^^^^^^ | - = warning: Breaking (FieldTypeChanged(Sorts(ExpectedFound { expected: fn() {oldandnew::old::abc}, found: fn() {oldandnew::new::abc} }))) + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: fn() {oldandnew::old::abc}, found: fn() {oldandnew::new::abc} }) }) warning: Breaking changes in `bcd` --> $REPO_PATH/tests/examples/fn.rs:14:5 @@ -23,7 +23,7 @@ warning: Breaking changes in `cde` 18 | | } | |_____^ | - = warning: Breaking (FieldTypeChanged(Sorts(ExpectedFound { expected: fn() {oldandnew::old::cde}, found: fn() -> u16 {oldandnew::new::cde} }))) + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: fn() {oldandnew::old::cde}, found: fn() -> u16 {oldandnew::new::cde} }) }) warning: Breaking changes in `def` --> $REPO_PATH/tests/examples/fn.rs:20:5 diff --git a/tests/examples/infer.out b/tests/examples/infer.out index 728097d8fec20..24cc67de9e09e 100644 --- a/tests/examples/infer.out +++ b/tests/examples/infer.out @@ -7,7 +7,7 @@ warning: Breaking changes in `a` 35 | | } | |_____^ | - = warning: Breaking (FieldTypeChanged(Sorts(ExpectedFound { expected: fn(A) -> A {oldandnew::old::a::}, found: fn(A) -> A {oldandnew::new::a::} }))) + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: fn(A) -> A {oldandnew::old::a::}, found: fn(A) -> A {oldandnew::new::a::} }) }) warning: Breaking changes in `b` --> $REPO_PATH/tests/examples/infer.rs:37:5 @@ -17,5 +17,5 @@ warning: Breaking changes in `b` 39 | | } | |_____^ | - = warning: Breaking (FieldTypeChanged(Sorts(ExpectedFound { expected: fn() -> oldandnew::old::a::Klm {oldandnew::old::b}, found: fn() -> oldandnew::new::a::Opq {oldandnew::new::b} }))) + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: fn() -> oldandnew::old::a::Klm {oldandnew::old::b}, found: fn() -> oldandnew::new::a::Opq {oldandnew::new::b} }) }) diff --git a/tests/examples/ty_alias.out b/tests/examples/ty_alias.out index a36595e9886c8..095660ba18d75 100644 --- a/tests/examples/ty_alias.out +++ b/tests/examples/ty_alias.out @@ -5,7 +5,7 @@ warning: Breaking changes in `A` 12 | pub type A = u16; | ^^^^^^^^^^^^^^^^^ | - = warning: Breaking (FieldTypeChanged(Sorts(ExpectedFound { expected: u8, found: u16 }))) + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) warning: Breaking changes in `B` --> $REPO_PATH/tests/examples/ty_alias.rs:13:5 @@ -30,7 +30,7 @@ warning: Breaking changes in `D` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: NonBreaking (TypeParameterAdded { defaulted: true }) - = warning: Breaking (FieldTypeChanged(Sorts(ExpectedFound { expected: &'a T, found: (&'a T, U) }))) + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: &'a T, found: (&'a T, U) }) }) warning: Breaking changes in `E` --> $REPO_PATH/tests/examples/ty_alias.rs:16:5 From b0df508cdc68e355d01b74154a04d1d7d39b269c Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 1 Jul 2017 13:26:47 +0200 Subject: [PATCH 103/553] Don't check for field additions/removal in some cases. If a constructor changed from enum-like to struct-like or vice-versa, it doesn't make sense to record the changes to it's fields, as it's redundant information only. --- src/semcheck/traverse.rs | 3 +++ tests/examples/struct.out | 10 ---------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 5b75434438a82..347c09c398693 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -303,6 +303,9 @@ fn diff_adts(changes: &mut ChangeSet, total_private: total_private, }; changes.add_binary(c, old_def_id, Some(tcx.def_span(old.did))); + + // TODO: this might need a condition later on. + continue; } for (_, items2) in fields.drain() { diff --git a/tests/examples/struct.out b/tests/examples/struct.out index a22626c5cb5b3..0cd44c70fbc6f 100644 --- a/tests/examples/struct.out +++ b/tests/examples/struct.out @@ -50,14 +50,4 @@ warning: Breaking (VariantStyleChanged { now_struct: true, total_private: true } | 23 | pub struct Hij(u8); | ^^^^^^^^^^^^^^^^^^^ -warning: Breaking (VariantFieldRemoved { public: false, total_public: false }) - --> $REPO_PATH/tests/examples/struct.rs:23:20 - | -23 | pub struct Hij(u8); - | ^^^ -warning: Breaking (VariantFieldAdded { public: false, total_public: false }) - --> $REPO_PATH/tests/examples/struct.rs:49:9 - | -49 | field: u8, - | ^^^^^^^^^ From aa1a0d4c12c0a51e1255effea30312771490cb1f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 1 Jul 2017 14:13:05 +0200 Subject: [PATCH 104/553] Improved name mapping implementation. --- src/lib.rs | 1 + src/semcheck/id_mapping.rs | 106 ---------------------------- src/semcheck/mapping.rs | 138 +++++++++++++++++++++++++++++++++++++ src/semcheck/mismatch.rs | 2 +- src/semcheck/mod.rs | 2 +- src/semcheck/traverse.rs | 23 ++----- 6 files changed, 147 insertions(+), 125 deletions(-) delete mode 100644 src/semcheck/id_mapping.rs create mode 100644 src/semcheck/mapping.rs diff --git a/src/lib.rs b/src/lib.rs index a3382e5606dac..1857d2c26122d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(conservative_impl_trait)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] diff --git a/src/semcheck/id_mapping.rs b/src/semcheck/id_mapping.rs deleted file mode 100644 index ab3f71b68c22b..0000000000000 --- a/src/semcheck/id_mapping.rs +++ /dev/null @@ -1,106 +0,0 @@ -use rustc::hir::def::Def; -use rustc::hir::def::Export; -use rustc::hir::def_id::DefId; - -use std::collections::{HashMap, VecDeque}; - -/// A mapping from old to new `DefId`s, as well as exports. -/// -/// Exports 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. -#[derive(Default)] -pub struct IdMapping { - /// Toplevel items' old `DefId` mapped to new `DefId`, as well as old and new exports. - pub toplevel_mapping: HashMap, - /// Other item's old `DefId` mapped to new `DefId`. - mapping: HashMap, -} - -impl IdMapping { - /// Register two exports representing the same item across versions. - pub fn add_export(&mut self, old: Export, new: Export) -> bool { - if !self.toplevel_mapping.contains_key(&old.def.def_id()) { - self.toplevel_mapping - .insert(old.def.def_id(), (new.def.def_id(), old, new)); - return true; - } - - false - } - - /// Add any other item pair's old and new `DefId`s. - pub fn add_item(&mut self, old: DefId, new: DefId) { - if !self.mapping.contains_key(&old) { - self.mapping.insert(old, new); - } else { - panic!("bug: overwriting {:?} => {:?} with {:?}!", old, self.mapping[&old], new); - } - } - - /// Get the new `DefId` associated with the given old one. - pub fn get_new_id(&self, old: DefId) -> DefId { - if let Some(new) = self.toplevel_mapping.get(&old) { - new.0 - } else { - self.mapping[&old] - } - } - - /// Tell us whether a `DefId` is present in the mappings. - pub fn contains_id(&self, old: DefId) -> bool { - self.toplevel_mapping.contains_key(&old) || self.mapping.contains_key(&old) - } - - pub fn construct_queue(&self) -> VecDeque<(DefId, DefId)> { - self.toplevel_mapping - .values() - .map(|&(_, old, new)| (old.def.def_id(), new.def.def_id())) - .collect() - } -} - -/// A representation of a namespace an item belongs to. -#[derive(PartialEq, Eq, Hash)] -pub enum Namespace { - /// The type namespace. - Type, - /// The value namespace. - Value, - /// The macro namespace. - Macro, - /// No namespace, so to say. - Err, -} - -/// Get an item's namespace. -pub fn get_namespace(def: &Def) -> Namespace { - use rustc::hir::def::Def::*; - - match *def { - Mod(_) | - Struct(_) | - Union(_) | - Enum(_) | - Variant(_) | - Trait(_) | - TyAlias(_) | - AssociatedTy(_) | - PrimTy(_) | - TyParam(_) | - SelfTy(_, _) => Namespace::Type, - Fn(_) | - Const(_) | - Static(_, _) | - StructCtor(_, _) | - VariantCtor(_, _) | - Method(_) | - AssociatedConst(_) | - Local(_) | - Upvar(_, _, _) | - Label(_) => Namespace::Value, - Macro(_, _) => Namespace::Macro, - GlobalAsm(_) | - Err => Namespace::Err, - } -} - diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs new file mode 100644 index 0000000000000..607f5989a4a1d --- /dev/null +++ b/src/semcheck/mapping.rs @@ -0,0 +1,138 @@ +use rustc::hir::def::Export; +use rustc::hir::def_id::DefId; + +use std::collections::{HashMap, VecDeque}; + +use syntax::ast::Name; + +/// A mapping from old to new `DefId`s, as well as exports. +/// +/// Exports 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. +#[derive(Default)] +pub struct IdMapping { + /// Toplevel items' old `DefId` mapped to new `DefId`, as well as old and new exports. + pub toplevel_mapping: HashMap, + /// Other item's old `DefId` mapped to new `DefId`. + mapping: HashMap, +} + +impl IdMapping { + /// Register two exports representing the same item across versions. + pub fn add_export(&mut self, old: Export, new: Export) -> bool { + if !self.toplevel_mapping.contains_key(&old.def.def_id()) { + self.toplevel_mapping + .insert(old.def.def_id(), (new.def.def_id(), old, new)); + return true; + } + + false + } + + /// Add any other item pair's old and new `DefId`s. + pub fn add_item(&mut self, old: DefId, new: DefId) { + if !self.mapping.contains_key(&old) { + self.mapping.insert(old, new); + } else { + panic!("bug: overwriting {:?} => {:?} with {:?}!", old, self.mapping[&old], new); + } + } + + /// Get the new `DefId` associated with the given old one. + pub fn get_new_id(&self, old: DefId) -> DefId { + if let Some(new) = self.toplevel_mapping.get(&old) { + new.0 + } else { + self.mapping[&old] + } + } + + /// Tell us whether a `DefId` is present in the mappings. + pub fn contains_id(&self, old: DefId) -> bool { + self.toplevel_mapping.contains_key(&old) || self.mapping.contains_key(&old) + } + + pub fn construct_queue(&self) -> VecDeque<(DefId, DefId)> { + self.toplevel_mapping + .values() + .map(|&(_, old, new)| (old.def.def_id(), new.def.def_id())) + .collect() + } +} + +/// 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. +#[derive(Default)] +pub struct NameMapping { + /// The exports in the type namespace. + type_map: HashMap, Option)>, + /// The exports in the value namespace. + value_map: HashMap, Option)>, + /// The exports in the macro namespace. + macro_map: HashMap, Option)>, +} + +impl NameMapping { + /// Insert a single export in the appropriate map, at the appropriate position. + fn insert(&mut self, item: Export, old: bool) { + use rustc::hir::def::Def::*; + + let map = match item.def { + Mod(_) | + Struct(_) | + Union(_) | + Enum(_) | + Variant(_) | + Trait(_) | + TyAlias(_) | + AssociatedTy(_) | + PrimTy(_) | + TyParam(_) | + SelfTy(_, _) => Some(&mut self.type_map), + Fn(_) | + Const(_) | + Static(_, _) | + StructCtor(_, _) | + VariantCtor(_, _) | + Method(_) | + AssociatedConst(_) | + Local(_) | + Upvar(_, _, _) | + Label(_) => Some(&mut self.value_map), + Macro(_, _) => Some(&mut self.macro_map), + GlobalAsm(_) | + Err => 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, mut old_items: Vec, mut new_items: Vec) { + for item in old_items.drain(..) { + self.insert(item, true); + } + + for item in new_items.drain(..) { + self.insert(item, false); + } + } + + /// Drain the item pairs being stored. + pub fn drain<'a>(&'a mut self) + -> impl Iterator, Option)> + 'a + { + self.type_map + .drain() + .chain(self.value_map.drain()) + .chain(self.macro_map.drain()) + .map(|t| t.1) + } +} diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 967956d6ce802..d7fa6e4e0b85e 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -4,7 +4,7 @@ use rustc::ty::{Ty, TyCtxt}; use rustc::ty::Visibility::Public; use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; -use semcheck::id_mapping::IdMapping; +use semcheck::mapping::IdMapping; use std::collections::{HashMap, VecDeque}; diff --git a/src/semcheck/mod.rs b/src/semcheck/mod.rs index 5636eda8eb818..e456abc000834 100644 --- a/src/semcheck/mod.rs +++ b/src/semcheck/mod.rs @@ -1,6 +1,6 @@ pub mod changes; -mod id_mapping; +mod mapping; mod mismatch; mod traverse; diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 347c09c398693..c169ecd477fb9 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -9,7 +9,7 @@ use rustc::ty::subst::{Subst, Substs}; use semcheck::changes::BinaryChangeType; use semcheck::changes::BinaryChangeType::*; use semcheck::changes::ChangeSet; -use semcheck::id_mapping::{get_namespace, IdMapping}; +use semcheck::mapping::{IdMapping, NameMapping}; use semcheck::mismatch::Mismatch; use std::collections::{HashMap, HashSet, VecDeque}; @@ -62,27 +62,16 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, let cstore = &tcx.sess.cstore; let mut visited = HashSet::new(); - let mut children = HashMap::new(); + let mut children = NameMapping::default(); let mut mod_queue = VecDeque::new(); mod_queue.push_back((old, new, Public, Public)); while let Some((old_did, new_did, old_vis, new_vis)) = mod_queue.pop_front() { - let mut c_old = cstore.item_children(old_did, tcx.sess); - let mut c_new = cstore.item_children(new_did, tcx.sess); + children.add(cstore.item_children(old_did, tcx.sess), + cstore.item_children(new_did, tcx.sess)); - // TODO: refactor this to avoid storing tons of `Namespace` values. - for child in c_old.drain(..) { - let key = (get_namespace(&child.def), child.ident.name); - children.entry(key).or_insert((None, None)).0 = Some(child); - } - - for child in c_new.drain(..) { - let key = (get_namespace(&child.def), child.ident.name); - children.entry(key).or_insert((None, None)).1 = Some(child); - } - - for (_, items) in children.drain() { + for items in children.drain() { match items { (Some(Export { def: Mod(o), .. }), Some(Export { def: Mod(n), .. })) => { if visited.insert((o, n)) { @@ -232,7 +221,7 @@ fn diff_fn(changes: &mut ChangeSet, tcx: TyCtxt, old: Export, new: Export) { } if old_sig.abi != new_sig.abi { - // TODO: more sophisticatd comparison + // TODO: more sophisticated comparison changes.add_binary(FnAbiChanged, old_def_id, None); } From cda4f240afc111903ccd53c14f6208490f1256ca Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 1 Jul 2017 18:18:29 +0200 Subject: [PATCH 105/553] Small cleanup --- src/semcheck/traverse.rs | 50 ++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index c169ecd477fb9..2b961ee773682 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -73,35 +73,33 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, for items in children.drain() { match items { - (Some(Export { def: Mod(o), .. }), Some(Export { def: Mod(n), .. })) => { - if visited.insert((o, n)) { - let o_vis = if old_vis == Public { - cstore.visibility(o) - } else { - old_vis - }; - let n_vis = if new_vis == Public { - cstore.visibility(n) - } else { - new_vis - }; + (Some(o), Some(n)) => { + if let (Mod(o_did), Mod(n_did)) = (o.def, n.def) { + if visited.insert((o_did, n_did)) { + let o_vis = if old_vis == Public { + cstore.visibility(o_did) + } else { + old_vis + }; + let n_vis = if new_vis == Public { + cstore.visibility(n_did) + } else { + new_vis + }; - if o_vis != n_vis { - // TODO: ugly - changes.new_binary(items.0.unwrap(), items.1.unwrap(), true); + if o_vis != n_vis { + changes.new_binary(o, n, true); - if o_vis == Public && n_vis != Public { - changes.add_binary(ItemMadePrivate, o, None); - } else if o_vis != Public && n_vis == Public { - changes.add_binary(ItemMadePublic, o, None); + if o_vis == Public && n_vis != Public { + changes.add_binary(ItemMadePrivate, o_did, None); + } else if o_vis != Public && n_vis == Public { + changes.add_binary(ItemMadePublic, o_did, None); + } } - } - mod_queue.push_back((o, n, o_vis, n_vis)); - } - } - (Some(o), Some(n)) => { - if id_mapping.add_export(o, n) { + mod_queue.push_back((o_did, n_did, o_vis, n_vis)); + } + } else if id_mapping.add_export(o, n) { let o_def_id = o.def.def_id(); let n_def_id = n.def.def_id(); let o_vis = if old_vis == Public { @@ -369,11 +367,9 @@ fn diff_generics(tcx: TyCtxt, old: DefId, new: DefId) match (old_gen.types.get(i), new_gen.types.get(i)) { (Some(old_type), Some(new_type)) => { if old_type.has_default && !new_type.has_default { - // TODO: major for sure ret.push(TypeParameterRemoved { defaulted: true }); ret.push(TypeParameterAdded { defaulted: false }); } else if !old_type.has_default && new_type.has_default { - // TODO: minor, I guess? ret.push(TypeParameterRemoved { defaulted: false }); ret.push(TypeParameterAdded { defaulted: true }); } From e9b7521d6513a2eddb5b5142defa0e5b0ecb0e2d Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 1 Jul 2017 18:50:45 +0200 Subject: [PATCH 106/553] Added docs and cleaned up some iterator logic. --- src/semcheck/changes.rs | 8 ++++++++ src/semcheck/mapping.rs | 15 ++++++++++++++- src/semcheck/mismatch.rs | 6 ++++++ src/semcheck/mod.rs | 3 +++ src/semcheck/traverse.rs | 15 +++++++++++++-- 5 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 0f574e1cd2719..356c2283765ab 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -1,3 +1,11 @@ +//! Change representation. +//! +//! This module provides data types to represent, store and record changes found in various +//! analysis passes. We distinguish between "unary" and "binary" changes, depending on whether +//! there is a single item affected in one crate version or a matching item in the other crate +//! version as well. The ordering of changes and output generation is performed using these data +//! structures, too. + use rustc::hir::def::Export; use rustc::hir::def_id::DefId; use rustc::session::Session; diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 607f5989a4a1d..ead00a5521f2c 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -1,3 +1,8 @@ +//! 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::Export; use rustc::hir::def_id::DefId; @@ -12,7 +17,7 @@ use syntax::ast::Name; #[derive(Default)] pub struct IdMapping { /// Toplevel items' old `DefId` mapped to new `DefId`, as well as old and new exports. - pub toplevel_mapping: HashMap, + toplevel_mapping: HashMap, /// Other item's old `DefId` mapped to new `DefId`. mapping: HashMap, } @@ -52,12 +57,20 @@ impl IdMapping { self.toplevel_mapping.contains_key(&old) || self.mapping.contains_key(&old) } + /// Construct a queue of toplevel item pairs' `DefId`s. pub fn construct_queue(&self) -> VecDeque<(DefId, DefId)> { self.toplevel_mapping .values() .map(|&(_, old, new)| (old.def.def_id(), new.def.def_id())) .collect() } + + /// Iterate over the toplevel item pairs. + pub fn toplevel_values<'a>(&'a self) -> impl Iterator + 'a { + self.toplevel_mapping + .values() + .map(|&(_, old, new)| (old, new)) + } } /// A mapping from names to pairs of old and new exports. diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index d7fa6e4e0b85e..8b555761f85ec 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -1,3 +1,9 @@ +//! 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 yet not matched with other items are +//! essentially just 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 rustc::hir::def_id::{CrateNum, DefId}; use rustc::ty; use rustc::ty::{Ty, TyCtxt}; diff --git a/src/semcheck/mod.rs b/src/semcheck/mod.rs index e456abc000834..5bbe48119bcd4 100644 --- a/src/semcheck/mod.rs +++ b/src/semcheck/mod.rs @@ -1,3 +1,6 @@ +//! This module holds all logic and data structures needed to perform semver analysis on two +//! modules which are usually crate roots (or just regular modules in a testing scenario). + pub mod changes; mod mapping; diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 2b961ee773682..5d5416e5a6ef2 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -1,3 +1,14 @@ +//! 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 find non-public items that are named +//! differently, yet are compatible in their usage. The (currently not implemented) third pass +//! performs the same analysis on trait bounds. The fourth and final pass now uses the +//! information collected in the previous passes to compare the types of all item pairs having +//! been matched. + use rustc::hir::def::CtorKind; use rustc::hir::def::Export; use rustc::hir::def_id::DefId; @@ -33,12 +44,12 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI } // third pass - for &(_, old, new) in id_mapping.toplevel_mapping.values() { + for (old, new) in id_mapping.toplevel_values() { diff_bounds(&mut changes, tcx, old.def.def_id(), new.def.def_id()); } // fourth pass - for &(_, old, new) in id_mapping.toplevel_mapping.values() { + for (old, new) in id_mapping.toplevel_values() { diff_types(&mut changes, &id_mapping, tcx, old, new); } From ff7681e635a64a911238e02964cec9203dd4a5de Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 3 Jul 2017 14:10:26 +0200 Subject: [PATCH 107/553] First naive version of struct and fn type checking. --- src/semcheck/mapping.rs | 45 +++++++++++++----- src/semcheck/traverse.rs | 96 +++++++++++++++++++++++++++++---------- tests/examples/fn.out | 10 +--- tests/examples/infer.out | 24 ++++------ tests/examples/struct.out | 13 +++++- 5 files changed, 126 insertions(+), 62 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index ead00a5521f2c..ac55ed70f886d 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -6,7 +6,7 @@ use rustc::hir::def::Export; use rustc::hir::def_id::DefId; -use std::collections::{HashMap, VecDeque}; +use std::collections::{BTreeSet, HashMap, VecDeque}; use syntax::ast::Name; @@ -20,27 +20,41 @@ pub struct IdMapping { toplevel_mapping: HashMap, /// Other item's old `DefId` mapped to new `DefId`. mapping: HashMap, + /// Children mapping, allowing us to enumerate descendants in `AdtDef`s. + child_mapping: HashMap>, } impl IdMapping { /// Register two exports representing the same item across versions. pub fn add_export(&mut self, old: Export, new: Export) -> bool { - if !self.toplevel_mapping.contains_key(&old.def.def_id()) { - self.toplevel_mapping - .insert(old.def.def_id(), (new.def.def_id(), old, new)); - return true; + if self.toplevel_mapping.contains_key(&old.def.def_id()) { + return false; } - false + self.toplevel_mapping + .insert(old.def.def_id(), (new.def.def_id(), old, new)); + + true } /// Add any other item pair's old and new `DefId`s. pub fn add_item(&mut self, old: DefId, new: DefId) { - if !self.mapping.contains_key(&old) { - self.mapping.insert(old, new); - } else { - panic!("bug: overwriting {:?} => {:?} with {:?}!", old, self.mapping[&old], new); - } + assert!(!self.mapping.contains_key(&old), + "bug: overwriting {:?} => {:?} with {:?}!", + old, + self.mapping[&old], + new); + + self.mapping.insert(old, new); + } + + /// Add any other item pair's old and new `DefId`s, together with a parent entry. + pub fn add_subitem(&mut self, parent: DefId, old: DefId, new: DefId) { + self.add_item(old, new); + self.child_mapping + .entry(parent) + .or_insert_with(Default::default) + .insert(old); } /// Get the new `DefId` associated with the given old one. @@ -71,6 +85,15 @@ impl IdMapping { .values() .map(|&(_, old, new)| (old, new)) } + + /// Iterate over the item pairs of all children of a given item. + pub fn children_values<'a>(&'a self, parent: DefId) + -> Option + 'a> + { + self.child_mapping + .get(&parent) + .map(|m| m.iter().map(move |old| (*old, self.mapping[old]))) + } } /// A mapping from names to pairs of old and new exports. diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 5d5416e5a6ef2..b87046391f934 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -12,7 +12,7 @@ use rustc::hir::def::CtorKind; use rustc::hir::def::Export; use rustc::hir::def_id::DefId; -use rustc::ty::TyCtxt; +use rustc::ty::{Ty, TyCtxt}; use rustc::ty::Visibility::Public; use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; use rustc::ty::subst::{Subst, Substs}; @@ -210,10 +210,6 @@ fn diff_fn(changes: &mut ChangeSet, tcx: TyCtxt, old: Export, new: Export) { let old_ty = tcx.type_of(old_def_id); let new_ty = tcx.type_of(new_def_id); - if !old_ty.is_fn() || !new_ty.is_fn() { - return; - } - let old_poly_sig = old_ty.fn_sig(tcx); let new_poly_sig = new_ty.fn_sig(tcx); @@ -274,7 +270,7 @@ fn diff_adts(changes: &mut ChangeSet, for (_, items) in variants.drain() { match items { (Some(old), Some(new)) => { - id_mapping.add_item(old.did, new.did); + id_mapping.add_subitem(old_def_id, old.did, new.did); for field in &old.fields { fields.entry(field.name).or_insert((None, None)).0 = Some(field); @@ -309,7 +305,7 @@ fn diff_adts(changes: &mut ChangeSet, for (_, items2) in fields.drain() { match items2 { (Some(o), Some(n)) => { - id_mapping.add_item(o.did, n.did); + id_mapping.add_subitem(old_def_id, o.did, n.did); if o.vis != Public && n.vis == Public { changes.add_binary(ItemMadePublic, @@ -428,8 +424,7 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>, old: Export, new: Export) { - use rustc::ty::{AdtDef, Lift}; - use rustc::ty::TypeVariants::*; + use rustc::hir::def::Def::*; if changes.item_breaking(old.def.def_id()) { return; @@ -438,30 +433,81 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let old_def_id = old.def.def_id(); let new_def_id = new.def.def_id(); + let substs = Substs::identity_for_item(tcx, new_def_id); + + let old_ty = tcx.type_of(old_def_id).subst(tcx, substs); let new_ty = tcx.type_of(new_def_id); - let old_ty = tcx.type_of(old_def_id).subst(tcx, Substs::identity_for_item(tcx, new_def_id)); - let old_ty_cmp = old_ty.fold_with(&mut BottomUpFolder { tcx: tcx, fldop: |ty| { - match ty.sty { - TyAdt(&AdtDef { ref did, .. }, substs) => { - let new_did = id_mapping.get_new_id(*did); - let new_adt = tcx.adt_def(new_did); - tcx.mk_adt(new_adt, substs) - }, - /* TyDynamic(predicates, region) => { + match old.def { + TyAlias(_) => { + cmp_types(changes, id_mapping, tcx, old_def_id, new_def_id, old_ty, new_ty); + }, + Fn(_) => { + let old_poly_sig = old_ty.fn_sig(tcx); + let new_poly_sig = new_ty.fn_sig(tcx); - }, TyClosure, TyRef (because of region?), TyProjection, TyAnon - TyProjection(projection_ty) => { + let o_tys = old_poly_sig.skip_binder().inputs_and_output; + let n_tys = new_poly_sig.skip_binder().inputs_and_output; - }, */ - _ => ty, - } - }}); + for (o_ty, n_ty) in o_tys.iter().zip(n_tys.iter()) { + cmp_types(changes, id_mapping, tcx, old_def_id, new_def_id, o_ty, n_ty); + } + }, + Struct(_) | Enum(_) | Union(_) => { + if let Some(children) = id_mapping.children_values(old_def_id) { + for (o_did, n_did) in children { + let o_ty = tcx.type_of(o_did); + let n_ty = tcx.type_of(n_did); + + cmp_types(changes, id_mapping, tcx, old_def_id, new_def_id, o_ty, n_ty); + } + } + }, + _ => (), + } +} + +/// Compare two types and possibly register the error. +fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + old_def_id: DefId, + new_def_id: DefId, + old: Ty<'tcx>, + new: Ty<'tcx>) { + use rustc::ty::Lift; + + let old = fold_to_new(id_mapping, tcx, old, new_def_id); tcx.infer_ctxt().enter(|infcx| - if let Err(err) = infcx.can_eq(tcx.param_env(new_def_id), old_ty_cmp, new_ty) { + if let Err(err) = infcx.can_eq(tcx.param_env(new_def_id), old, new) { changes.add_binary(TypeChanged { error: err.lift_to_tcx(tcx).unwrap() }, old_def_id, None); }); } + +/// Fold a type of an old item to be comparable with a new type. +fn fold_to_new<'a, 'tcx>(id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + old_ty: Ty<'tcx>, + new_def_id: DefId) -> Ty<'tcx> { + use rustc::ty::AdtDef; + use rustc::ty::TypeVariants::*; + + let substs = Substs::identity_for_item(tcx, new_def_id); + + old_ty.subst(tcx, substs).fold_with(&mut BottomUpFolder { tcx: tcx, fldop: |ty| { + match ty.sty { + TyAdt(&AdtDef { ref did, .. }, substs) if id_mapping.contains_id(*did) => { + let new_did = id_mapping.get_new_id(*did); + let new_adt = tcx.adt_def(new_did); + tcx.mk_adt(new_adt, substs) + }, + /* TyDynamic(preds, region) => { + TODO + }, */ + _ => ty, + } + }}) +} diff --git a/tests/examples/fn.out b/tests/examples/fn.out index 81de4288094ff..25f905138d820 100644 --- a/tests/examples/fn.out +++ b/tests/examples/fn.out @@ -1,12 +1,4 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Breaking changes in `abc` - --> $REPO_PATH/tests/examples/fn.rs:12:5 - | -12 | pub fn abc() {} - | ^^^^^^^^^^^^^^^ - | - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: fn() {oldandnew::old::abc}, found: fn() {oldandnew::new::abc} }) }) - warning: Breaking changes in `bcd` --> $REPO_PATH/tests/examples/fn.rs:14:5 | @@ -23,7 +15,7 @@ warning: Breaking changes in `cde` 18 | | } | |_____^ | - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: fn() {oldandnew::old::cde}, found: fn() -> u16 {oldandnew::new::cde} }) }) + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: (), found: u16 }) }) warning: Breaking changes in `def` --> $REPO_PATH/tests/examples/fn.rs:20:5 diff --git a/tests/examples/infer.out b/tests/examples/infer.out index 24cc67de9e09e..4410c5ac04c57 100644 --- a/tests/examples/infer.out +++ b/tests/examples/infer.out @@ -1,21 +1,13 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Breaking changes in `a` - --> $REPO_PATH/tests/examples/infer.rs:33:5 +warning: Breaking changes in `Hij` + --> $REPO_PATH/tests/examples/infer.rs:41:5 | -33 | / pub fn a(a: A) -> A { -34 | | a -35 | | } +41 | / pub struct Hij<'a> { +42 | | pub field: &'a a::Def, +43 | | pub field2: ::std::rc::Rc, +44 | | } | |_____^ | - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: fn(A) -> A {oldandnew::old::a::}, found: fn(A) -> A {oldandnew::new::a::} }) }) - -warning: Breaking changes in `b` - --> $REPO_PATH/tests/examples/infer.rs:37:5 - | -37 | / pub fn b() -> a::Opq { -38 | | a::Opq -39 | | } - | |_____^ - | - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: fn() -> oldandnew::old::a::Klm {oldandnew::old::b}, found: fn() -> oldandnew::new::a::Opq {oldandnew::new::b} }) }) + = warning: Breaking (TypeChanged { error: Traits(ExpectedFound { expected: DefId { krate: CrateNum(11), node: DefIndex(5) => infer/8cd878b::old[0]::a[0]::Abc[0] }, found: DefId { krate: CrateNum(11), node: DefIndex(12) => infer/8cd878b::new[0]::a[0]::Def[0] } }) }) + = warning: Breaking (TypeChanged { error: Traits(ExpectedFound { expected: DefId { krate: CrateNum(11), node: DefIndex(5) => infer/8cd878b::old[0]::a[0]::Abc[0] }, found: DefId { krate: CrateNum(11), node: DefIndex(12) => infer/8cd878b::new[0]::a[0]::Def[0] } }) }) diff --git a/tests/examples/struct.out b/tests/examples/struct.out index 0cd44c70fbc6f..88ae446129527 100644 --- a/tests/examples/struct.out +++ b/tests/examples/struct.out @@ -1,5 +1,5 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: NonBreaking changes in `Def` +warning: Breaking changes in `Def` --> $REPO_PATH/tests/examples/struct.rs:32:5 | 32 | / pub struct Def { @@ -8,6 +8,17 @@ warning: NonBreaking changes in `Def` | |_____^ | = note: NonBreaking (TypeParameterAdded { defaulted: true }) + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: A }) }) + +warning: Breaking changes in `Efg` + --> $REPO_PATH/tests/examples/struct.rs:36:5 + | +36 | / pub struct Efg { +37 | | pub field: u16, +38 | | } + | |_____^ + | + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) warning: TechnicallyBreaking changes in `Fgh` --> $REPO_PATH/tests/examples/struct.rs:40:5 From bbc6fc972d6aa513c9529b9f41ac70f989fcb0cc Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 3 Jul 2017 15:22:20 +0200 Subject: [PATCH 108/553] Implemented fn type checking in a proper way. --- src/semcheck/traverse.rs | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index b87046391f934..7c8c19a62af33 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -425,6 +425,7 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, old: Export, new: Export) { use rustc::hir::def::Def::*; + use rustc::ty::Binder; if changes.item_breaking(old.def.def_id()) { return; @@ -443,15 +444,17 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, cmp_types(changes, id_mapping, tcx, old_def_id, new_def_id, old_ty, new_ty); }, Fn(_) => { - let old_poly_sig = old_ty.fn_sig(tcx); - let new_poly_sig = new_ty.fn_sig(tcx); - - let o_tys = old_poly_sig.skip_binder().inputs_and_output; - let n_tys = new_poly_sig.skip_binder().inputs_and_output; - - for (o_ty, n_ty) in o_tys.iter().zip(n_tys.iter()) { - cmp_types(changes, id_mapping, tcx, old_def_id, new_def_id, o_ty, n_ty); - } + let old_fn_sig = + Binder(fold_to_new(id_mapping, tcx, *old_ty.fn_sig(tcx).skip_binder())); + let new_fn_sig = new_ty.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)); }, Struct(_) | Enum(_) | Union(_) => { if let Some(children) = id_mapping.children_values(old_def_id) { @@ -477,7 +480,9 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, new: Ty<'tcx>) { use rustc::ty::Lift; - let old = fold_to_new(id_mapping, tcx, old, new_def_id); + let substs = Substs::identity_for_item(tcx, new_def_id); + + let old = fold_to_new(id_mapping, tcx, old.subst(tcx, substs)); tcx.infer_ctxt().enter(|infcx| if let Err(err) = infcx.can_eq(tcx.param_env(new_def_id), old, new) { @@ -488,16 +493,13 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } /// Fold a type of an old item to be comparable with a new type. -fn fold_to_new<'a, 'tcx>(id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - old_ty: Ty<'tcx>, - new_def_id: DefId) -> Ty<'tcx> { +fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, old: T) -> T + where T: TypeFoldable<'tcx> +{ use rustc::ty::AdtDef; use rustc::ty::TypeVariants::*; - let substs = Substs::identity_for_item(tcx, new_def_id); - - old_ty.subst(tcx, substs).fold_with(&mut BottomUpFolder { tcx: tcx, fldop: |ty| { + old.fold_with(&mut BottomUpFolder { tcx: tcx, fldop: |ty| { match ty.sty { TyAdt(&AdtDef { ref did, .. }, substs) if id_mapping.contains_id(*did) => { let new_did = id_mapping.get_new_id(*did); From 4f72ae5b26feeb45714f78e0ab254ef1e3fb8ac7 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 3 Jul 2017 15:48:48 +0200 Subject: [PATCH 109/553] Fixed build with newest nightly. --- src/bin/rust_semverver.rs | 8 +++----- src/semcheck/traverse.rs | 6 +++--- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 7a5a30583e6b7..c7fd0306ae68c 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -13,7 +13,7 @@ extern crate syntax; use semverver::semcheck::run_analysis; use rustc::hir::def_id::*; -use rustc::session::{config, Session}; +use rustc::session::{config, CompileIncomplete, Session}; use rustc::session::config::{Input, ErrorOutputType}; use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; @@ -218,10 +218,8 @@ fn main() { let mut cc = SemVerVerCompilerCalls::new(version); let (result, _) = rustc_driver::run_compiler(&args, &mut cc, None, None); - if let Err(count) = result { - if count > 0 { - std::process::exit(1); - } + if let Err(CompileIncomplete::Errored(_)) = result { + std::process::exit(1); } }) .expect("rustc thread failed"); diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 7c8c19a62af33..d27404719aeda 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -445,7 +445,7 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, }, Fn(_) => { let old_fn_sig = - Binder(fold_to_new(id_mapping, tcx, *old_ty.fn_sig(tcx).skip_binder())); + Binder(fold_to_new(id_mapping, tcx, old_ty.fn_sig(tcx).skip_binder())); let new_fn_sig = new_ty.fn_sig(tcx); cmp_types(changes, @@ -482,7 +482,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let substs = Substs::identity_for_item(tcx, new_def_id); - let old = fold_to_new(id_mapping, tcx, old.subst(tcx, substs)); + let old = fold_to_new(id_mapping, tcx, &old.subst(tcx, substs)); tcx.infer_ctxt().enter(|infcx| if let Err(err) = infcx.can_eq(tcx.param_env(new_def_id), old, new) { @@ -493,7 +493,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } /// Fold a type of an old item to be comparable with a new type. -fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, old: T) -> T +fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, old: &T) -> T where T: TypeFoldable<'tcx> { use rustc::ty::AdtDef; From 01f9548538b6be288082bfaf6c29437df015eac6 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 3 Jul 2017 18:03:06 +0200 Subject: [PATCH 110/553] Implemented proper DefId substitution for trait objects. --- src/semcheck/traverse.rs | 51 ++++++++++++++++++++++++++++++++++++---- tests/examples/infer.out | 14 +---------- 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index d27404719aeda..4d17b17337bda 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -496,7 +496,8 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, old: &T) -> T where T: TypeFoldable<'tcx> { - use rustc::ty::AdtDef; + use rustc::ty::{AdtDef, Binder, ExistentialProjection, ExistentialTraitRef}; + use rustc::ty::ExistentialPredicate::*; use rustc::ty::TypeVariants::*; old.fold_with(&mut BottomUpFolder { tcx: tcx, fldop: |ty| { @@ -506,9 +507,51 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, let new_adt = tcx.adt_def(new_did); tcx.mk_adt(new_adt, substs) }, - /* TyDynamic(preds, region) => { - TODO - }, */ + TyDynamic(preds, region) => { + let new_preds = tcx.mk_existential_predicates(preds.iter().map(|p| { + match *p.skip_binder() { + Trait(ExistentialTraitRef { def_id: did, substs }) => { + let new_did = if id_mapping.contains_id(did) { + id_mapping.get_new_id(did) + } else { + did + }; + + Trait(ExistentialTraitRef { + def_id: new_did, + substs: substs + }) + }, + Projection(ExistentialProjection { trait_ref, item_name, ty }) => { + let ExistentialTraitRef { def_id: did, substs } = trait_ref; + let new_did = if id_mapping.contains_id(did) { + id_mapping.get_new_id(did) + } else { + did + }; + + Projection(ExistentialProjection { + trait_ref: ExistentialTraitRef { + def_id: new_did, + substs: substs, + }, + item_name: item_name, + ty: ty, + }) + + }, + AutoTrait(did) => { + if id_mapping.contains_id(did) { + AutoTrait(id_mapping.get_new_id(did)) + } else { + AutoTrait(did) + } + }, + } + })); + + tcx.mk_dynamic(Binder(new_preds), region) + }, _ => ty, } }}) diff --git a/tests/examples/infer.out b/tests/examples/infer.out index 4410c5ac04c57..84bd4ceab5d48 100644 --- a/tests/examples/infer.out +++ b/tests/examples/infer.out @@ -1,13 +1 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Breaking changes in `Hij` - --> $REPO_PATH/tests/examples/infer.rs:41:5 - | -41 | / pub struct Hij<'a> { -42 | | pub field: &'a a::Def, -43 | | pub field2: ::std::rc::Rc, -44 | | } - | |_____^ - | - = warning: Breaking (TypeChanged { error: Traits(ExpectedFound { expected: DefId { krate: CrateNum(11), node: DefIndex(5) => infer/8cd878b::old[0]::a[0]::Abc[0] }, found: DefId { krate: CrateNum(11), node: DefIndex(12) => infer/8cd878b::new[0]::a[0]::Def[0] } }) }) - = warning: Breaking (TypeChanged { error: Traits(ExpectedFound { expected: DefId { krate: CrateNum(11), node: DefIndex(5) => infer/8cd878b::old[0]::a[0]::Abc[0] }, found: DefId { krate: CrateNum(11), node: DefIndex(12) => infer/8cd878b::new[0]::a[0]::Def[0] } }) }) - +version bump: 1.0.0 -> (Patch) -> 1.0.1 From 38a218bbf0a676e7b8a72439b6afa32cc4e5479e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 6 Jul 2017 18:28:24 +0200 Subject: [PATCH 111/553] Implemented naive subsitution of defaulted type params. --- src/semcheck/mapping.rs | 16 ++++++++- src/semcheck/traverse.rs | 60 ++++++++++++++++--------------- tests/examples/macro.out | 7 ++++ tests/examples/macro.rs | 26 ++++++++++++++ tests/examples/struct.out | 71 ++++++++++++++++++++++--------------- tests/examples/struct.rs | 10 +++++- tests/examples/ty_alias.out | 2 +- 7 files changed, 133 insertions(+), 59 deletions(-) create mode 100644 tests/examples/macro.out create mode 100644 tests/examples/macro.rs diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index ac55ed70f886d..115694c4ddb81 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -6,7 +6,7 @@ use rustc::hir::def::Export; use rustc::hir::def_id::DefId; -use std::collections::{BTreeSet, HashMap, VecDeque}; +use std::collections::{BTreeSet, HashMap, HashSet, VecDeque}; use syntax::ast::Name; @@ -22,6 +22,8 @@ pub struct IdMapping { mapping: HashMap, /// Children mapping, allowing us to enumerate descendants in `AdtDef`s. child_mapping: HashMap>, + /// Set of new defaulted type parameters. + defaulted_type_params: HashSet, } impl IdMapping { @@ -57,6 +59,18 @@ impl IdMapping { .insert(old); } + /// Record that a `DefId` represents a newly added defaulted type parameter. + pub fn add_defaulted_type_param(&mut self, new: DefId) { + self.defaulted_type_params + .insert(new); + } + + /// Check whether a `DefId` represents a newly added defaulted type parameter. + pub fn is_defaulted_type_param(&self, new: &DefId) -> bool { + self.defaulted_type_params + .contains(new) + } + /// Get the new `DefId` associated with the given old one. pub fn get_new_id(&self, old: DefId) -> DefId { if let Some(new) = self.toplevel_mapping.get(&old) { diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 4d17b17337bda..f4340e208884f 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -159,22 +159,13 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, diff_fn(changes, tcx, o, n); }, (TyAlias(_), TyAlias(_)) => { - let mut generics_changes = - diff_generics(tcx, o_def_id, n_def_id); - for change_type in generics_changes.drain(..) { - changes.add_binary(change_type, o_def_id, None); - } + diff_generics(changes, id_mapping, tcx, o_def_id, n_def_id); }, // ADTs for now (Struct(_), Struct(_)) | (Union(_), Union(_)) | (Enum(_), Enum(_)) => { - let mut generics_changes = - diff_generics(tcx, o_def_id, n_def_id); - for change_type in generics_changes.drain(..) { - changes.add_binary(change_type, o_def_id, None); - } - + diff_generics(changes, id_mapping, tcx, o_def_id, n_def_id); diff_adts(changes, id_mapping, tcx, o, n); }, // non-matching item pair - register the difference and abort @@ -347,12 +338,14 @@ fn diff_adts(changes: &mut ChangeSet, } /// Given two items, compare their type and region parameter sets. -fn diff_generics(tcx: TyCtxt, old: DefId, new: DefId) - -> Vec> -{ +fn diff_generics(changes: &mut ChangeSet, + id_mapping: &mut IdMapping, + tcx: TyCtxt, + old: DefId, + new: DefId) { use std::cmp::max; - let mut ret = Vec::new(); + let mut found = Vec::new(); let old_gen = tcx.generics_of(old); let new_gen = tcx.generics_of(new); @@ -360,10 +353,10 @@ fn diff_generics(tcx: TyCtxt, old: DefId, new: DefId) for i in 0..max(old_gen.regions.len(), new_gen.regions.len()) { match (old_gen.regions.get(i), new_gen.regions.get(i)) { (Some(_ /* old_region */), None) => { - ret.push(RegionParameterRemoved); + found.push(RegionParameterRemoved); }, (None, Some(_ /* new_region */)) => { - ret.push(RegionParameterAdded); + found.push(RegionParameterAdded); }, (Some(_), Some(_)) => (), (None, None) => unreachable!(), @@ -374,24 +367,29 @@ fn diff_generics(tcx: TyCtxt, old: DefId, new: DefId) match (old_gen.types.get(i), new_gen.types.get(i)) { (Some(old_type), Some(new_type)) => { if old_type.has_default && !new_type.has_default { - ret.push(TypeParameterRemoved { defaulted: true }); - ret.push(TypeParameterAdded { defaulted: false }); + found.push(TypeParameterRemoved { defaulted: true }); + found.push(TypeParameterAdded { defaulted: false }); } else if !old_type.has_default && new_type.has_default { - ret.push(TypeParameterRemoved { defaulted: false }); - ret.push(TypeParameterAdded { defaulted: true }); + found.push(TypeParameterRemoved { defaulted: false }); + found.push(TypeParameterAdded { defaulted: true }); } }, (Some(old_type), None) => { - ret.push(TypeParameterRemoved { defaulted: old_type.has_default }); + found.push(TypeParameterRemoved { defaulted: old_type.has_default }); }, (None, Some(new_type)) => { - ret.push(TypeParameterAdded { defaulted: new_type.has_default }); + found.push(TypeParameterAdded { defaulted: new_type.has_default }); + if new_type.has_default { + id_mapping.add_defaulted_type_param(new_type.def_id); + } }, (None, None) => unreachable!(), } } - ret + for change_type in found.drain(..) { + changes.add_binary(change_type, old, None); + } } // Below functions constitute the third pass of analysis, in which parameter bounds of matching @@ -434,9 +432,7 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let old_def_id = old.def.def_id(); let new_def_id = new.def.def_id(); - let substs = Substs::identity_for_item(tcx, new_def_id); - - let old_ty = tcx.type_of(old_def_id).subst(tcx, substs); + let old_ty = tcx.type_of(old_def_id); let new_ty = tcx.type_of(new_def_id); match old.def { @@ -478,11 +474,19 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, new_def_id: DefId, old: Ty<'tcx>, new: Ty<'tcx>) { - use rustc::ty::Lift; + use rustc::ty::{Lift, ReEarlyBound}; let substs = Substs::identity_for_item(tcx, new_def_id); + let substs2 = Substs::for_item(tcx, new_def_id, |def, _| { + tcx.mk_region(ReEarlyBound(def.to_early_bound_region_data())) + }, |def, _| if id_mapping.is_defaulted_type_param(&def.def_id) { + tcx.type_of(def.def_id) + } else { + tcx.mk_param_from_def(def) + }); let old = fold_to_new(id_mapping, tcx, &old.subst(tcx, substs)); + let new = new.subst(tcx, substs2); tcx.infer_ctxt().enter(|infcx| if let Err(err) = infcx.can_eq(tcx.param_env(new_def_id), old, new) { diff --git a/tests/examples/macro.out b/tests/examples/macro.out new file mode 100644 index 0000000000000..7576b93137454 --- /dev/null +++ b/tests/examples/macro.out @@ -0,0 +1,7 @@ +version bump: 1.0.0 -> (Breaking) -> 2.0.0 +warning: Removal of at least one path to `bar` (Breaking) + --> $REPO_PATH/tests/examples/macro.rs:6:9 + | +6 | pub macro bar() { Item } + | ^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/examples/macro.rs b/tests/examples/macro.rs new file mode 100644 index 0000000000000..5b95347ef5734 --- /dev/null +++ b/tests/examples/macro.rs @@ -0,0 +1,26 @@ +#![feature(decl_macro, use_extern_macros)] + +pub mod old { + pub struct Item; + + pub macro bar() { Item } + + fn abc() -> Item { + bar!() + } +} + +pub mod new { + pub struct Item; + + #[macro_export] + macro_rules! bar { + () => { + Item + } + } + + fn abc() -> Item { + bar!() + } +} diff --git a/tests/examples/struct.out b/tests/examples/struct.out index 88ae446129527..130d7f80ab4f4 100644 --- a/tests/examples/struct.out +++ b/tests/examples/struct.out @@ -1,64 +1,79 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Breaking changes in `Def` - --> $REPO_PATH/tests/examples/struct.rs:32:5 +warning: TechnicallyBreaking changes in `Def` + --> $REPO_PATH/tests/examples/struct.rs:36:5 + | +36 | / pub struct Def { +37 | | pub field: A, +38 | | } + | |_____^ + | + = note: NonBreaking (TypeParameterAdded { defaulted: true }) +note: TechnicallyBreaking (ItemMadePublic) + --> $REPO_PATH/tests/examples/struct.rs:8:9 | -32 | / pub struct Def { -33 | | field: A, -34 | | } +8 | field: u8, + | ^^^^^^^^^ + +warning: Breaking changes in `Def2` + --> $REPO_PATH/tests/examples/struct.rs:40:5 + | +40 | / pub struct Def2 { +41 | | pub field: A, +42 | | } | |_____^ | = note: NonBreaking (TypeParameterAdded { defaulted: true }) - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: A }) }) + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) warning: Breaking changes in `Efg` - --> $REPO_PATH/tests/examples/struct.rs:36:5 + --> $REPO_PATH/tests/examples/struct.rs:44:5 | -36 | / pub struct Efg { -37 | | pub field: u16, -38 | | } +44 | / pub struct Efg { +45 | | pub field: u16, +46 | | } | |_____^ | = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) warning: TechnicallyBreaking changes in `Fgh` - --> $REPO_PATH/tests/examples/struct.rs:40:5 + --> $REPO_PATH/tests/examples/struct.rs:48:5 | -40 | / pub struct Fgh { -41 | | pub field: u8, -42 | | } +48 | / pub struct Fgh { +49 | | pub field: u8, +50 | | } | |_____^ | note: TechnicallyBreaking (ItemMadePublic) - --> $REPO_PATH/tests/examples/struct.rs:16:9 + --> $REPO_PATH/tests/examples/struct.rs:20:9 | -16 | field: u8, +20 | field: u8, | ^^^^^^^^^ warning: Breaking changes in `Ghi` - --> $REPO_PATH/tests/examples/struct.rs:44:5 + --> $REPO_PATH/tests/examples/struct.rs:52:5 | -44 | / pub struct Ghi { -45 | | field: u8, -46 | | } +52 | / pub struct Ghi { +53 | | field: u8, +54 | | } | |_____^ | warning: Breaking (ItemMadePrivate) - --> $REPO_PATH/tests/examples/struct.rs:20:9 + --> $REPO_PATH/tests/examples/struct.rs:24:9 | -20 | pub field: u8, +24 | pub field: u8, | ^^^^^^^^^^^^^ warning: Breaking changes in `Hij` - --> $REPO_PATH/tests/examples/struct.rs:48:5 + --> $REPO_PATH/tests/examples/struct.rs:56:5 | -48 | / pub struct Hij { -49 | | field: u8, -50 | | } +56 | / pub struct Hij { +57 | | field: u8, +58 | | } | |_____^ | warning: Breaking (VariantStyleChanged { now_struct: true, total_private: true }) - --> $REPO_PATH/tests/examples/struct.rs:23:5 + --> $REPO_PATH/tests/examples/struct.rs:27:5 | -23 | pub struct Hij(u8); +27 | pub struct Hij(u8); | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/examples/struct.rs b/tests/examples/struct.rs index dae30374b25a7..f0c1c89fd0d92 100644 --- a/tests/examples/struct.rs +++ b/tests/examples/struct.rs @@ -8,6 +8,10 @@ pub mod old { field: u8, } + pub struct Def2 { + pub field: u8, + } + pub struct Efg { pub field: u8, } @@ -30,7 +34,11 @@ pub mod new { } pub struct Def { - field: A, + pub field: A, + } + + pub struct Def2 { + pub field: A, } pub struct Efg { diff --git a/tests/examples/ty_alias.out b/tests/examples/ty_alias.out index 095660ba18d75..ea8e9a8fe5647 100644 --- a/tests/examples/ty_alias.out +++ b/tests/examples/ty_alias.out @@ -30,7 +30,7 @@ warning: Breaking changes in `D` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: NonBreaking (TypeParameterAdded { defaulted: true }) - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: &'a T, found: (&'a T, U) }) }) + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: &'a T, found: (&'a T, T) }) }) warning: Breaking changes in `E` --> $REPO_PATH/tests/examples/ty_alias.rs:16:5 From 3489d39d289dac1a7fd39f7e92fd7121c16a1bdd Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 6 Jul 2017 20:51:38 +0200 Subject: [PATCH 112/553] Fixed an ordering bug. --- src/semcheck/traverse.rs | 16 ++++--- tests/examples/enum.out | 90 ++++++++++++++++++++++++++++--------- tests/examples/enum.rs | 20 +++++++++ tests/examples/macro.rs | 1 + tests/examples/ty_alias.out | 6 +-- tests/examples/ty_alias.rs | 2 +- 6 files changed, 103 insertions(+), 32 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index f4340e208884f..b98bb6900ccef 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -23,7 +23,7 @@ use semcheck::changes::ChangeSet; use semcheck::mapping::{IdMapping, NameMapping}; use semcheck::mismatch::Mismatch; -use std::collections::{HashMap, HashSet, VecDeque}; +use std::collections::{BTreeMap, HashSet, VecDeque}; /// The main entry point to our analysis passes. /// @@ -247,8 +247,8 @@ fn diff_adts(changes: &mut ChangeSet, _ => return, }; - let mut variants = HashMap::new(); - let mut fields = HashMap::new(); + let mut variants = BTreeMap::new(); + let mut fields = BTreeMap::new(); for variant in &old_def.variants { variants.entry(variant.name).or_insert((None, None)).0 = Some(variant); @@ -258,8 +258,8 @@ fn diff_adts(changes: &mut ChangeSet, variants.entry(variant.name).or_insert((None, None)).1 = Some(variant); } - for (_, items) in variants.drain() { - match items { + for items in variants.values() { + match *items { (Some(old), Some(new)) => { id_mapping.add_subitem(old_def_id, old.did, new.did); @@ -293,8 +293,8 @@ fn diff_adts(changes: &mut ChangeSet, continue; } - for (_, items2) in fields.drain() { - match items2 { + for items2 in fields.values() { + match *items2 { (Some(o), Some(n)) => { id_mapping.add_subitem(old_def_id, o.did, n.did); @@ -325,6 +325,8 @@ fn diff_adts(changes: &mut ChangeSet, (None, None) => unreachable!(), } } + + fields.clear(); }, (Some(old), None) => { changes.add_binary(VariantRemoved, old_def_id, Some(tcx.def_span(old.did))); diff --git a/tests/examples/enum.out b/tests/examples/enum.out index 6bc8ee5fe9947..7898ee6be0f4d 100644 --- a/tests/examples/enum.out +++ b/tests/examples/enum.out @@ -1,24 +1,24 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 warning: Breaking changes in `Abc` - --> $REPO_PATH/tests/examples/enum.rs:21:5 + --> $REPO_PATH/tests/examples/enum.rs:31:5 | -21 | / pub enum Abc { -22 | | Abc, -23 | | } +31 | / pub enum Abc { +32 | | Abc, +33 | | } | |_____^ | warning: Breaking (VariantAdded) - --> $REPO_PATH/tests/examples/enum.rs:22:9 + --> $REPO_PATH/tests/examples/enum.rs:32:9 | -22 | Abc, +32 | Abc, | ^^^ warning: Breaking changes in `Bcd` - --> $REPO_PATH/tests/examples/enum.rs:25:5 + --> $REPO_PATH/tests/examples/enum.rs:35:5 | -25 | / pub enum Bcd { -26 | | -27 | | } +35 | / pub enum Bcd { +36 | | +37 | | } | |_____^ | warning: Breaking (VariantRemoved) @@ -28,26 +28,26 @@ warning: Breaking (VariantRemoved) | ^^^ warning: Breaking changes in `Cde` - --> $REPO_PATH/tests/examples/enum.rs:29:5 + --> $REPO_PATH/tests/examples/enum.rs:39:5 | -29 | / pub enum Cde { -30 | | Abc, -31 | | Bcd, -32 | | } +39 | / pub enum Cde { +40 | | Abc, +41 | | Bcd, +42 | | } | |_____^ | warning: Breaking (VariantAdded) - --> $REPO_PATH/tests/examples/enum.rs:31:9 + --> $REPO_PATH/tests/examples/enum.rs:41:9 | -31 | Bcd, +41 | Bcd, | ^^^ warning: Breaking changes in `Def` - --> $REPO_PATH/tests/examples/enum.rs:34:5 + --> $REPO_PATH/tests/examples/enum.rs:44:5 | -34 | / pub enum Def { -35 | | Abc, -36 | | } +44 | / pub enum Def { +45 | | Abc, +46 | | } | |_____^ | warning: Breaking (VariantRemoved) @@ -56,3 +56,51 @@ warning: Breaking (VariantRemoved) 16 | Bcd, | ^^^ +warning: Breaking changes in `Efg` + --> $REPO_PATH/tests/examples/enum.rs:48:5 + | +48 | / pub enum Efg { +49 | | Abc(u8), +50 | | Bcd, +51 | | Cde { f: u8 }, +... | +55 | | Ghi { g: u8 }, +56 | | } + | |_____^ + | +warning: Breaking (VariantStyleChanged { now_struct: false, total_private: true }) + --> $REPO_PATH/tests/examples/enum.rs:20:9 + | +20 | Abc, + | ^^^ +warning: Breaking (VariantStyleChanged { now_struct: false, total_private: true }) + --> $REPO_PATH/tests/examples/enum.rs:21:9 + | +21 | Bcd(u8), + | ^^^^^^^ +warning: Breaking (VariantStyleChanged { now_struct: true, total_private: true }) + --> $REPO_PATH/tests/examples/enum.rs:22:9 + | +22 | Cde, + | ^^^ +warning: Breaking (VariantStyleChanged { now_struct: false, total_private: true }) + --> $REPO_PATH/tests/examples/enum.rs:23:9 + | +23 | Def { f: u8 }, + | ^^^^^^^^^^^^^ +warning: Breaking (VariantStyleChanged { now_struct: true, total_private: true }) + --> $REPO_PATH/tests/examples/enum.rs:24:9 + | +24 | Efg(u8), + | ^^^^^^^ +warning: Breaking (VariantFieldRemoved { public: false, total_public: false }) + --> $REPO_PATH/tests/examples/enum.rs:26:15 + | +26 | Ghi { f: u8 }, + | ^^^^^ +warning: Breaking (VariantFieldAdded { public: false, total_public: false }) + --> $REPO_PATH/tests/examples/enum.rs:55:15 + | +55 | Ghi { g: u8 }, + | ^^^^^ + diff --git a/tests/examples/enum.rs b/tests/examples/enum.rs index c885e17d1d48a..7790d7df12f5d 100644 --- a/tests/examples/enum.rs +++ b/tests/examples/enum.rs @@ -15,6 +15,16 @@ pub mod old { Abc, Bcd, } + + pub enum Efg { + Abc, + Bcd(u8), + Cde, + Def { f: u8 }, + Efg(u8), + Fgh { f: u8 }, + Ghi { f: u8 }, + } } pub mod new { @@ -34,4 +44,14 @@ pub mod new { 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/tests/examples/macro.rs b/tests/examples/macro.rs index 5b95347ef5734..87c3382706c43 100644 --- a/tests/examples/macro.rs +++ b/tests/examples/macro.rs @@ -20,6 +20,7 @@ pub mod new { } } + #[allow(dead_code)] fn abc() -> Item { bar!() } diff --git a/tests/examples/ty_alias.out b/tests/examples/ty_alias.out index ea8e9a8fe5647..84ed1a8fa82cf 100644 --- a/tests/examples/ty_alias.out +++ b/tests/examples/ty_alias.out @@ -26,11 +26,11 @@ warning: Breaking changes in `C` warning: Breaking changes in `D` --> $REPO_PATH/tests/examples/ty_alias.rs:15:5 | -15 | pub type D<'a, T, U=T> = (&'a T, U); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +15 | pub type D<'a, T, U=Box> = (&'a T, U); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: NonBreaking (TypeParameterAdded { defaulted: true }) - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: &'a T, found: (&'a T, T) }) }) + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: &'a T, found: (&'a T, std::boxed::Box) }) }) warning: Breaking changes in `E` --> $REPO_PATH/tests/examples/ty_alias.rs:16:5 diff --git a/tests/examples/ty_alias.rs b/tests/examples/ty_alias.rs index 19868abae7987..46300f3a38c31 100644 --- a/tests/examples/ty_alias.rs +++ b/tests/examples/ty_alias.rs @@ -12,7 +12,7 @@ pub mod new { pub type A = u16; pub type B<'a, 'b : 'a, T> = (&'a T, &'b T); pub type C = T; - pub type D<'a, T, U=T> = (&'a T, U); + pub type D<'a, T, U=Box> = (&'a T, U); pub type E<'a, T, U> = (&'a T, U); pub type F<'a> = &'a u8; pub type G<'a> = (&'a u8); From c8c95d033bfa1ceb5a64ce21286e8c4b3c7fb22b Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 6 Jul 2017 21:24:44 +0200 Subject: [PATCH 113/553] More test cases for function tests. --- src/semcheck/traverse.rs | 2 +- tests/examples/fn.out | 46 +++++++++++++++++++++++++++++++++------- tests/examples/fn.rs | 28 +++++++++++++++++++++++- 3 files changed, 66 insertions(+), 10 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index b98bb6900ccef..42abd521a8c9b 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -156,6 +156,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, (Err, Err) => {}, (Fn(_), Fn(_)) | (Method(_), Method(_)) => { + diff_generics(changes, id_mapping, tcx, o_def_id, n_def_id); diff_fn(changes, tcx, o, n); }, (TyAlias(_), TyAlias(_)) => { @@ -289,7 +290,6 @@ fn diff_adts(changes: &mut ChangeSet, }; changes.add_binary(c, old_def_id, Some(tcx.def_span(old.did))); - // TODO: this might need a condition later on. continue; } diff --git a/tests/examples/fn.out b/tests/examples/fn.out index 25f905138d820..aca07053096c1 100644 --- a/tests/examples/fn.out +++ b/tests/examples/fn.out @@ -1,27 +1,57 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 warning: Breaking changes in `bcd` - --> $REPO_PATH/tests/examples/fn.rs:14:5 + --> $REPO_PATH/tests/examples/fn.rs:26:5 | -14 | pub fn bcd(_: u8) {} +26 | pub fn bcd(_: u8) {} | ^^^^^^^^^^^^^^^^^^^^ | = warning: Breaking (FnArityChanged) warning: Breaking changes in `cde` - --> $REPO_PATH/tests/examples/fn.rs:16:5 + --> $REPO_PATH/tests/examples/fn.rs:28:5 | -16 | / pub fn cde() -> u16 { // TODO: maybe make this case TechnicallyBreaking -17 | | 0xcde -18 | | } +28 | / pub fn cde() -> u16 { +29 | | 0xcde +30 | | } | |_____^ | = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: (), found: u16 }) }) warning: Breaking changes in `def` - --> $REPO_PATH/tests/examples/fn.rs:20:5 + --> $REPO_PATH/tests/examples/fn.rs:32:5 | -20 | pub fn def() {} +32 | pub fn def() {} | ^^^^^^^^^^^^^^^ | = warning: Breaking (FnArityChanged) +warning: Breaking changes in `efg` + --> $REPO_PATH/tests/examples/fn.rs:36:5 + | +36 | / pub fn efg(a: A, _: A) -> A { +37 | | a +38 | | } + | |_____^ + | + = warning: Breaking (TypeParameterAdded { defaulted: false }) + +warning: Breaking changes in `fgh` + --> $REPO_PATH/tests/examples/fn.rs:40:5 + | +40 | / pub fn fgh(a: u8, _: u16) -> u8 { +41 | | a +42 | | } + | |_____^ + | + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) + +warning: Breaking changes in `ghi` + --> $REPO_PATH/tests/examples/fn.rs:44:5 + | +44 | / pub fn ghi(a: u8, _: u8) -> u16 { +45 | | a as u16 +46 | | } + | |_____^ + | + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) + diff --git a/tests/examples/fn.rs b/tests/examples/fn.rs index d75bea2901cc4..a2338cc8dd966 100644 --- a/tests/examples/fn.rs +++ b/tests/examples/fn.rs @@ -6,6 +6,18 @@ pub mod old { 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 mod new { @@ -13,9 +25,23 @@ pub mod new { pub fn bcd(_: u8) {} - pub fn cde() -> u16 { // TODO: maybe make this case TechnicallyBreaking + pub fn cde() -> u16 { 0xcde } pub fn def() {} + + // TODO: this should be non-breaking (even after we make TypeParameterAdded something + // that is not `Breaking`) + pub fn efg(a: A, _: A) -> A { + a + } + + pub fn fgh(a: u8, _: u16) -> u8 { + a + } + + pub fn ghi(a: u8, _: u8) -> u16 { + a as u16 + } } From 41c836b91f7c8ca171698d05416e923282f6d599 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 6 Jul 2017 22:09:38 +0200 Subject: [PATCH 114/553] Fixed some spans. --- src/semcheck/traverse.rs | 6 +++--- tests/examples/enum.out | 30 +++++++++++++++--------------- tests/examples/struct.out | 26 ++++++++++++++------------ 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 42abd521a8c9b..67cd400709d2a 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -288,7 +288,7 @@ fn diff_adts(changes: &mut ChangeSet, now_struct: new.ctor_kind == CtorKind::Fictive, total_private: total_private, }; - changes.add_binary(c, old_def_id, Some(tcx.def_span(old.did))); + changes.add_binary(c, old_def_id, Some(tcx.def_span(new.did))); continue; } @@ -301,11 +301,11 @@ fn diff_adts(changes: &mut ChangeSet, if o.vis != Public && n.vis == Public { changes.add_binary(ItemMadePublic, old_def_id, - Some(tcx.def_span(o.did))); + Some(tcx.def_span(n.did))); } else if o.vis == Public && n.vis != Public { changes.add_binary(ItemMadePrivate, old_def_id, - Some(tcx.def_span(o.did))); + Some(tcx.def_span(n.did))); } }, (Some(o), None) => { diff --git a/tests/examples/enum.out b/tests/examples/enum.out index 7898ee6be0f4d..bc35ea5c5fb54 100644 --- a/tests/examples/enum.out +++ b/tests/examples/enum.out @@ -69,30 +69,30 @@ warning: Breaking changes in `Efg` | |_____^ | warning: Breaking (VariantStyleChanged { now_struct: false, total_private: true }) - --> $REPO_PATH/tests/examples/enum.rs:20:9 + --> $REPO_PATH/tests/examples/enum.rs:49:9 | -20 | Abc, - | ^^^ +49 | Abc(u8), + | ^^^^^^^ warning: Breaking (VariantStyleChanged { now_struct: false, total_private: true }) - --> $REPO_PATH/tests/examples/enum.rs:21:9 + --> $REPO_PATH/tests/examples/enum.rs:50:9 | -21 | Bcd(u8), - | ^^^^^^^ +50 | Bcd, + | ^^^ warning: Breaking (VariantStyleChanged { now_struct: true, total_private: true }) - --> $REPO_PATH/tests/examples/enum.rs:22:9 + --> $REPO_PATH/tests/examples/enum.rs:51:9 | -22 | Cde, - | ^^^ +51 | Cde { f: u8 }, + | ^^^^^^^^^^^^^ warning: Breaking (VariantStyleChanged { now_struct: false, total_private: true }) - --> $REPO_PATH/tests/examples/enum.rs:23:9 + --> $REPO_PATH/tests/examples/enum.rs:52:9 | -23 | Def { f: u8 }, - | ^^^^^^^^^^^^^ +52 | Def, + | ^^^ warning: Breaking (VariantStyleChanged { now_struct: true, total_private: true }) - --> $REPO_PATH/tests/examples/enum.rs:24:9 + --> $REPO_PATH/tests/examples/enum.rs:53:9 | -24 | Efg(u8), - | ^^^^^^^ +53 | Efg { f: u8 }, + | ^^^^^^^^^^^^^ warning: Breaking (VariantFieldRemoved { public: false, total_public: false }) --> $REPO_PATH/tests/examples/enum.rs:26:15 | diff --git a/tests/examples/struct.out b/tests/examples/struct.out index 130d7f80ab4f4..91822eb4c1bbd 100644 --- a/tests/examples/struct.out +++ b/tests/examples/struct.out @@ -9,10 +9,10 @@ warning: TechnicallyBreaking changes in `Def` | = note: NonBreaking (TypeParameterAdded { defaulted: true }) note: TechnicallyBreaking (ItemMadePublic) - --> $REPO_PATH/tests/examples/struct.rs:8:9 + --> $REPO_PATH/tests/examples/struct.rs:37:9 | -8 | field: u8, - | ^^^^^^^^^ +37 | pub field: A, + | ^^^^^^^^^^^^ warning: Breaking changes in `Def2` --> $REPO_PATH/tests/examples/struct.rs:40:5 @@ -44,10 +44,10 @@ warning: TechnicallyBreaking changes in `Fgh` | |_____^ | note: TechnicallyBreaking (ItemMadePublic) - --> $REPO_PATH/tests/examples/struct.rs:20:9 + --> $REPO_PATH/tests/examples/struct.rs:49:9 | -20 | field: u8, - | ^^^^^^^^^ +49 | pub field: u8, + | ^^^^^^^^^^^^^ warning: Breaking changes in `Ghi` --> $REPO_PATH/tests/examples/struct.rs:52:5 @@ -58,10 +58,10 @@ warning: Breaking changes in `Ghi` | |_____^ | warning: Breaking (ItemMadePrivate) - --> $REPO_PATH/tests/examples/struct.rs:24:9 + --> $REPO_PATH/tests/examples/struct.rs:53:9 | -24 | pub field: u8, - | ^^^^^^^^^^^^^ +53 | field: u8, + | ^^^^^^^^^ warning: Breaking changes in `Hij` --> $REPO_PATH/tests/examples/struct.rs:56:5 @@ -72,8 +72,10 @@ warning: Breaking changes in `Hij` | |_____^ | warning: Breaking (VariantStyleChanged { now_struct: true, total_private: true }) - --> $REPO_PATH/tests/examples/struct.rs:27:5 + --> $REPO_PATH/tests/examples/struct.rs:56:5 | -27 | pub struct Hij(u8); - | ^^^^^^^^^^^^^^^^^^^ +56 | / pub struct Hij { +57 | | field: u8, +58 | | } + | |_____^ From 27b0cb6638011fce0473d1999f15ac0ad78df830 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 7 Jul 2017 17:51:39 +0200 Subject: [PATCH 115/553] Implemented type-inference based function type comparison. --- src/semcheck/traverse.rs | 54 +++++++++++++++++++++++++++++----------- tests/examples/fn.out | 4 +-- 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 67cd400709d2a..a326aed2c07ae 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -156,17 +156,32 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, (Err, Err) => {}, (Fn(_), Fn(_)) | (Method(_), Method(_)) => { - diff_generics(changes, id_mapping, tcx, o_def_id, n_def_id); + diff_generics(changes, + id_mapping, + tcx, + true, + o_def_id, + n_def_id); diff_fn(changes, tcx, o, n); }, (TyAlias(_), TyAlias(_)) => { - diff_generics(changes, id_mapping, tcx, o_def_id, n_def_id); + diff_generics(changes, + id_mapping, + tcx, + false, + o_def_id, + n_def_id); }, // ADTs for now (Struct(_), Struct(_)) | (Union(_), Union(_)) | (Enum(_), Enum(_)) => { - diff_generics(changes, id_mapping, tcx, o_def_id, n_def_id); + diff_generics(changes, + id_mapping, + tcx, + false, + o_def_id, + n_def_id); diff_adts(changes, id_mapping, tcx, o, n); }, // non-matching item pair - register the difference and abort @@ -343,6 +358,7 @@ fn diff_adts(changes: &mut ChangeSet, fn diff_generics(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, + is_fn: bool, old: DefId, new: DefId) { use std::cmp::max; @@ -379,8 +395,8 @@ fn diff_generics(changes: &mut ChangeSet, (Some(old_type), None) => { found.push(TypeParameterRemoved { defaulted: old_type.has_default }); }, - (None, Some(new_type)) => { - found.push(TypeParameterAdded { defaulted: new_type.has_default }); + (None, Some(new_type)) => { // FIXME: is_fn could be used in a more elegant fashion + found.push(TypeParameterAdded { defaulted: new_type.has_default || is_fn }); if new_type.has_default { id_mapping.add_defaulted_type_param(new_type.def_id); } @@ -476,26 +492,34 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, new_def_id: DefId, old: Ty<'tcx>, new: Ty<'tcx>) { + use syntax_pos::DUMMY_SP; use rustc::ty::{Lift, ReEarlyBound}; let substs = Substs::identity_for_item(tcx, new_def_id); - let substs2 = Substs::for_item(tcx, new_def_id, |def, _| { - tcx.mk_region(ReEarlyBound(def.to_early_bound_region_data())) - }, |def, _| if id_mapping.is_defaulted_type_param(&def.def_id) { - tcx.type_of(def.def_id) - } else { - tcx.mk_param_from_def(def) - }); let old = fold_to_new(id_mapping, tcx, &old.subst(tcx, substs)); - let new = new.subst(tcx, substs2); - tcx.infer_ctxt().enter(|infcx| + tcx.infer_ctxt().enter(|infcx| { + let new_substs = if new.is_fn() { + infcx.fresh_substs_for_item(DUMMY_SP, new_def_id) + } else { + Substs::for_item(tcx, new_def_id, |def, _| { + tcx.mk_region(ReEarlyBound(def.to_early_bound_region_data())) + }, |def, _| if id_mapping.is_defaulted_type_param(&def.def_id) { + tcx.type_of(def.def_id) + } else { + tcx.mk_param_from_def(def) + }) + }; + + let new = new.subst(infcx.tcx, new_substs); + if let Err(err) = infcx.can_eq(tcx.param_env(new_def_id), old, new) { changes.add_binary(TypeChanged { error: err.lift_to_tcx(tcx).unwrap() }, old_def_id, None); - }); + } + }); } /// Fold a type of an old item to be comparable with a new type. diff --git a/tests/examples/fn.out b/tests/examples/fn.out index aca07053096c1..40cdc2ff627de 100644 --- a/tests/examples/fn.out +++ b/tests/examples/fn.out @@ -25,7 +25,7 @@ warning: Breaking changes in `def` | = warning: Breaking (FnArityChanged) -warning: Breaking changes in `efg` +warning: NonBreaking changes in `efg` --> $REPO_PATH/tests/examples/fn.rs:36:5 | 36 | / pub fn efg(a: A, _: A) -> A { @@ -33,7 +33,7 @@ warning: Breaking changes in `efg` 38 | | } | |_____^ | - = warning: Breaking (TypeParameterAdded { defaulted: false }) + = note: NonBreaking (TypeParameterAdded { defaulted: true }) warning: Breaking changes in `fgh` --> $REPO_PATH/tests/examples/fn.rs:40:5 From 9a41a2eeca71494bb9082c0426dc6f57ef50fa97 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 7 Jul 2017 21:46:32 +0200 Subject: [PATCH 116/553] Added first traces of trait checks. --- src/semcheck/mismatch.rs | 8 ++++++-- src/semcheck/traverse.rs | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 8b555761f85ec..9571214b4fee6 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -45,10 +45,15 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> Mismatch<'a, 'gcx, 'tcx> { /// Process the next pair of `DefId`s in the queue and return them. pub fn process(&mut self) { + use rustc::hir::def::Def::Trait; + while let Some((old_did, new_did)) = self.item_queue.pop_front() { + if let Some(Trait(_)) = self.tcx.describe_def(old_did) { + continue; + } + let old_ty = self.tcx.type_of(old_did); let new_ty = self.tcx.type_of(new_did); - // println!("processing types: {:?}, {:?}", old_ty, new_ty); let _ = self.relate(&old_ty, &new_ty); } } @@ -187,7 +192,6 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { fn regions(&mut self, a: ty::Region<'tcx>, _: ty::Region<'tcx>) -> RelateResult<'tcx, ty::Region<'tcx>> { - // TODO Ok(a) } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index a326aed2c07ae..093bf1a6b141d 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -23,7 +23,7 @@ use semcheck::changes::ChangeSet; use semcheck::mapping::{IdMapping, NameMapping}; use semcheck::mismatch::Mismatch; -use std::collections::{BTreeMap, HashSet, VecDeque}; +use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; /// The main entry point to our analysis passes. /// @@ -137,7 +137,6 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, match (o.def, n.def) { // (matching) things we don't care about (for now) (Mod(_), Mod(_)) | - (Trait(_), Trait(_)) | (AssociatedTy(_), AssociatedTy(_)) | (PrimTy(_), PrimTy(_)) | (TyParam(_), TyParam(_)) | @@ -184,6 +183,9 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, n_def_id); diff_adts(changes, id_mapping, tcx, o, n); }, + (Trait(_), Trait(_)) => { + diff_traits(changes, id_mapping, tcx, o_def_id, n_def_id); + }, // non-matching item pair - register the difference and abort _ => { changes.add_binary(KindDifference, o_def_id, None); @@ -354,6 +356,32 @@ fn diff_adts(changes: &mut ChangeSet, } } +/// Given two trait items, perform structural checks. +/// +/// This establishes the needed correspondence relationship between non-toplevel items found in +/// the trait definition. +fn diff_traits(changes: &mut ChangeSet, + id_mapping: &mut IdMapping, + tcx: TyCtxt, + old: DefId, + new: DefId) { + let old_unsafety = tcx.trait_def(old).unsafety; + let new_unsafety = tcx.trait_def(new).unsafety; + + let mut items = HashMap::new(); + + for old_did in tcx.associated_item_def_ids(old).iter() { + println!("found: {:?}", old_did); + items.entry(tcx.def_symbol_name(*old_did).name) + .or_insert((None, None)).0 = tcx.describe_def(*old_did); + } + + for new_did in tcx.associated_item_def_ids(new).iter() { + items.entry(tcx.def_symbol_name(*new_did).name) + .or_insert((None, None)).1 = tcx.describe_def(*new_did); + } +} + /// Given two items, compare their type and region parameter sets. fn diff_generics(changes: &mut ChangeSet, id_mapping: &mut IdMapping, @@ -450,6 +478,10 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let old_def_id = old.def.def_id(); let new_def_id = new.def.def_id(); + if let Trait(_) = old.def { + return; + } + let old_ty = tcx.type_of(old_def_id); let new_ty = tcx.type_of(new_def_id); From 7c572f65f43dddf2ba3242946d3655499699513b Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 7 Jul 2017 22:54:45 +0200 Subject: [PATCH 117/553] Mapping overhaul and more first steps in trait checks. --- src/semcheck/mapping.rs | 43 +++++++++++++----------- src/semcheck/mismatch.rs | 4 +-- src/semcheck/traverse.rs | 70 ++++++++++++++++++++++++---------------- 3 files changed, 69 insertions(+), 48 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 115694c4ddb81..8c668df74599a 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -3,7 +3,7 @@ //! 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::Export; +use rustc::hir::def::{Def, Export}; use rustc::hir::def_id::DefId; use std::collections::{BTreeSet, HashMap, HashSet, VecDeque}; @@ -17,9 +17,11 @@ use syntax::ast::Name; #[derive(Default)] pub struct IdMapping { /// Toplevel items' old `DefId` mapped to new `DefId`, as well as old and new exports. - toplevel_mapping: HashMap, + toplevel_mapping: HashMap, + /// Trait items' old `DefId` mapped to new `DefId`. + trait_item_mapping: HashMap, /// Other item's old `DefId` mapped to new `DefId`. - mapping: HashMap, + internal_mapping: HashMap, /// Children mapping, allowing us to enumerate descendants in `AdtDef`s. child_mapping: HashMap>, /// Set of new defaulted type parameters. @@ -28,31 +30,36 @@ pub struct IdMapping { impl IdMapping { /// Register two exports representing the same item across versions. - pub fn add_export(&mut self, old: Export, new: Export) -> bool { - if self.toplevel_mapping.contains_key(&old.def.def_id()) { + pub fn add_export(&mut self, old: Def, new: Def) -> bool { + if self.toplevel_mapping.contains_key(&old.def_id()) { return false; } self.toplevel_mapping - .insert(old.def.def_id(), (new.def.def_id(), old, new)); + .insert(old.def_id(), (old, new)); true } + /// Add any trait item pair's old and new `DefId`s. + pub fn add_trait_item(&mut self, old: Def, new: Def) { + self.trait_item_mapping.insert(old.def_id(), (old, new)); + } + /// Add any other item pair's old and new `DefId`s. - pub fn add_item(&mut self, old: DefId, new: DefId) { - assert!(!self.mapping.contains_key(&old), + pub fn add_internal_item(&mut self, old: DefId, new: DefId) { + assert!(!self.internal_mapping.contains_key(&old), "bug: overwriting {:?} => {:?} with {:?}!", old, - self.mapping[&old], + self.internal_mapping[&old], new); - self.mapping.insert(old, new); + self.internal_mapping.insert(old, new); } /// Add any other item pair's old and new `DefId`s, together with a parent entry. pub fn add_subitem(&mut self, parent: DefId, old: DefId, new: DefId) { - self.add_item(old, new); + self.add_internal_item(old, new); self.child_mapping .entry(parent) .or_insert_with(Default::default) @@ -74,30 +81,30 @@ impl IdMapping { /// Get the new `DefId` associated with the given old one. pub fn get_new_id(&self, old: DefId) -> DefId { if let Some(new) = self.toplevel_mapping.get(&old) { - new.0 + new.1.def_id() } else { - self.mapping[&old] + self.internal_mapping[&old] } } /// Tell us whether a `DefId` is present in the mappings. pub fn contains_id(&self, old: DefId) -> bool { - self.toplevel_mapping.contains_key(&old) || self.mapping.contains_key(&old) + self.toplevel_mapping.contains_key(&old) || self.internal_mapping.contains_key(&old) } /// Construct a queue of toplevel item pairs' `DefId`s. pub fn construct_queue(&self) -> VecDeque<(DefId, DefId)> { self.toplevel_mapping .values() - .map(|&(_, old, new)| (old.def.def_id(), new.def.def_id())) + .map(|&(old, new)| (old.def_id(), new.def_id())) .collect() } /// Iterate over the toplevel item pairs. - pub fn toplevel_values<'a>(&'a self) -> impl Iterator + 'a { + pub fn toplevel_values<'a>(&'a self) -> impl Iterator + 'a { self.toplevel_mapping .values() - .map(|&(_, old, new)| (old, new)) + .chain(self.trait_item_mapping.values()) } /// Iterate over the item pairs of all children of a given item. @@ -106,7 +113,7 @@ impl IdMapping { { self.child_mapping .get(&parent) - .map(|m| m.iter().map(move |old| (*old, self.mapping[old]))) + .map(|m| m.iter().map(move |old| (*old, self.internal_mapping[old]))) } } diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 9571214b4fee6..a6209409558d4 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -129,7 +129,7 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { let a_did = a.skip_binder().def_id; let b_did = b.skip_binder().def_id; if !self.id_mapping.contains_id(a_did) && a_did.krate == self.old_crate { - self.id_mapping.add_item(a_did, b_did); + self.id_mapping.add_internal_item(a_did, b_did); } // TODO: Some((a.skip_binder().def_id, b.skip_binder().def_id)) @@ -181,7 +181,7 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { if let Some(dids) = matching { if !self.id_mapping.contains_id(dids.0) && dids.0.krate == self.old_crate { // println!("adding mapping: {:?} => {:?}", dids.0, dids.1); - self.id_mapping.add_item(dids.0, dids.1); + self.id_mapping.add_internal_item(dids.0, dids.1); self.item_queue.push_back(dids); } } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 093bf1a6b141d..1c16b8da29f1b 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -9,8 +9,7 @@ //! information collected in the previous passes to compare the types of all item pairs having //! been matched. -use rustc::hir::def::CtorKind; -use rustc::hir::def::Export; +use rustc::hir::def::{CtorKind, Def}; use rustc::hir::def_id::DefId; use rustc::ty::{Ty, TyCtxt}; use rustc::ty::Visibility::Public; @@ -44,12 +43,12 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI } // third pass - for (old, new) in id_mapping.toplevel_values() { - diff_bounds(&mut changes, tcx, old.def.def_id(), new.def.def_id()); + for &(old, new) in id_mapping.toplevel_values() { + diff_bounds(&mut changes, tcx, old.def_id(), new.def_id()); } // fourth pass - for (old, new) in id_mapping.toplevel_values() { + for &(old, new) in id_mapping.toplevel_values() { diff_types(&mut changes, &id_mapping, tcx, old, new); } @@ -110,7 +109,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, mod_queue.push_back((o_did, n_did, o_vis, n_vis)); } - } else if id_mapping.add_export(o, n) { + } else if id_mapping.add_export(o.def, n.def) { let o_def_id = o.def.def_id(); let n_def_id = n.def.def_id(); let o_vis = if old_vis == Public { @@ -161,7 +160,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, true, o_def_id, n_def_id); - diff_fn(changes, tcx, o, n); + diff_fn(changes, tcx, o.def, n.def); }, (TyAlias(_), TyAlias(_)) => { diff_generics(changes, @@ -181,7 +180,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, false, o_def_id, n_def_id); - diff_adts(changes, id_mapping, tcx, o, n); + diff_adts(changes, id_mapping, tcx, o.def, n.def); }, (Trait(_), Trait(_)) => { diff_traits(changes, id_mapping, tcx, o_def_id, n_def_id); @@ -210,11 +209,11 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, } /// Given two fn items, perform structural checks. -fn diff_fn(changes: &mut ChangeSet, tcx: TyCtxt, old: Export, new: Export) { +fn diff_fn(changes: &mut ChangeSet, tcx: TyCtxt, old: Def, new: Def) { use rustc::hir::Unsafety::Unsafe; - let old_def_id = old.def.def_id(); - let new_def_id = new.def.def_id(); + let old_def_id = old.def_id(); + let new_def_id = new.def_id(); let old_ty = tcx.type_of(old_def_id); let new_ty = tcx.type_of(new_def_id); @@ -251,14 +250,14 @@ fn diff_fn(changes: &mut ChangeSet, tcx: TyCtxt, old: Export, new: Export) { fn diff_adts(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, - old: Export, - new: Export) { + old: Def, + new: Def) { use rustc::hir::def::Def::*; - let old_def_id = old.def.def_id(); - let new_def_id = new.def.def_id(); + let old_def_id = old.def_id(); + let new_def_id = new.def_id(); - let (old_def, new_def) = match (old.def, new.def) { + let (old_def, new_def) = match (old, new) { (Struct(_), Struct(_)) | (Union(_), Union(_)) | (Enum(_), Enum(_)) => (tcx.adt_def(old_def_id), tcx.adt_def(new_def_id)), @@ -360,18 +359,17 @@ fn diff_adts(changes: &mut ChangeSet, /// /// This establishes the needed correspondence relationship between non-toplevel items found in /// the trait definition. -fn diff_traits(changes: &mut ChangeSet, +fn diff_traits(_changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, old: DefId, new: DefId) { - let old_unsafety = tcx.trait_def(old).unsafety; - let new_unsafety = tcx.trait_def(new).unsafety; + let _old_unsafety = tcx.trait_def(old).unsafety; + let _new_unsafety = tcx.trait_def(new).unsafety; let mut items = HashMap::new(); for old_did in tcx.associated_item_def_ids(old).iter() { - println!("found: {:?}", old_did); items.entry(tcx.def_symbol_name(*old_did).name) .or_insert((None, None)).0 = tcx.describe_def(*old_did); } @@ -380,6 +378,22 @@ fn diff_traits(changes: &mut ChangeSet, items.entry(tcx.def_symbol_name(*new_did).name) .or_insert((None, None)).1 = tcx.describe_def(*new_did); } + + for item_pair in items.values() { + match *item_pair { + (Some(old_def), Some(new_def)) => { + id_mapping.add_trait_item(old_def, new_def); + // println!("map!"); + }, + (Some(old_def), None) => { + // println!("missing: {:?}", old_def); + }, + (None, Some(new_def)) => { + // println!("added: {:?}", new_def); + }, + (None, None) => unreachable!(), + } + } } /// Given two items, compare their type and region parameter sets. @@ -466,26 +480,26 @@ fn diff_bounds<'a, 'tcx>(_changes: &mut ChangeSet, fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, - old: Export, - new: Export) { + old: Def, + new: Def) { use rustc::hir::def::Def::*; use rustc::ty::Binder; - if changes.item_breaking(old.def.def_id()) { + let old_def_id = old.def_id(); + let new_def_id = new.def_id(); + + if changes.item_breaking(old_def_id) { return; } - let old_def_id = old.def.def_id(); - let new_def_id = new.def.def_id(); - - if let Trait(_) = old.def { + if let Trait(_) = old { return; } let old_ty = tcx.type_of(old_def_id); let new_ty = tcx.type_of(new_def_id); - match old.def { + match old { TyAlias(_) => { cmp_types(changes, id_mapping, tcx, old_def_id, new_def_id, old_ty, new_ty); }, From e5814c163e78977eb6f444f7f4ab91df3ca53085 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 8 Jul 2017 11:34:33 +0200 Subject: [PATCH 118/553] Cleaned up trait item matching and fixed some weirdnesses in type checking. --- src/semcheck/traverse.rs | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 1c16b8da29f1b..047ea0f0f0bce 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -370,12 +370,12 @@ fn diff_traits(_changes: &mut ChangeSet, let mut items = HashMap::new(); for old_did in tcx.associated_item_def_ids(old).iter() { - items.entry(tcx.def_symbol_name(*old_did).name) + items.entry(tcx.associated_item(*old_did).name) .or_insert((None, None)).0 = tcx.describe_def(*old_did); } for new_did in tcx.associated_item_def_ids(new).iter() { - items.entry(tcx.def_symbol_name(*new_did).name) + items.entry(tcx.associated_item(*new_did).name) .or_insert((None, None)).1 = tcx.describe_def(*new_did); } @@ -383,13 +383,13 @@ fn diff_traits(_changes: &mut ChangeSet, match *item_pair { (Some(old_def), Some(new_def)) => { id_mapping.add_trait_item(old_def, new_def); - // println!("map!"); + println!("map!"); }, (Some(old_def), None) => { - // println!("missing: {:?}", old_def); + println!("missing: {:?}", old_def); }, (None, Some(new_def)) => { - // println!("added: {:?}", new_def); + println!("added: {:?}", new_def); }, (None, None) => unreachable!(), } @@ -492,21 +492,22 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, return; } - if let Trait(_) = old { - return; - } - - let old_ty = tcx.type_of(old_def_id); - let new_ty = tcx.type_of(new_def_id); - match old { TyAlias(_) => { - cmp_types(changes, id_mapping, tcx, old_def_id, new_def_id, old_ty, new_ty); + cmp_types(changes, + id_mapping, + tcx, + old_def_id, + new_def_id, + tcx.type_of(old_def_id), + tcx.type_of(new_def_id)); }, Fn(_) => { let old_fn_sig = - Binder(fold_to_new(id_mapping, tcx, old_ty.fn_sig(tcx).skip_binder())); - let new_fn_sig = new_ty.fn_sig(tcx); + Binder(fold_to_new(id_mapping, + tcx, + tcx.type_of(old_def_id).fn_sig(tcx).skip_binder())); + let new_fn_sig = tcx.type_of(new_def_id).fn_sig(tcx); cmp_types(changes, id_mapping, From d82859a7a0b73138b21e97cc0e5f4439e619ebba Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 9 Jul 2017 12:31:08 +0200 Subject: [PATCH 119/553] Finished implementing basic trait checks. * Structural checks are performed. * Functions are passed to the type checking mechanism. * The change set implementation has been improved to allow for this. --- src/semcheck/changes.rs | 90 +++++++++--------------- src/semcheck/traverse.rs | 143 ++++++++++++++++++++++++++++++++++----- 2 files changed, 158 insertions(+), 75 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 356c2283765ab..9ad71b9fcbc2c 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -16,7 +16,7 @@ use semver::Version; use std::collections::{BTreeMap, HashMap}; use std::cmp::Ordering; -use syntax::symbol::Ident; +use syntax::symbol::{Ident, Symbol}; use syntax_pos::Span; @@ -143,10 +143,6 @@ pub enum BinaryChangeType<'tcx> { TypeParameterAdded { defaulted: bool }, /// A type parameter has been removed from an item. TypeParameterRemoved { defaulted: bool }, - /// The bounds on a type parameter have been loosened. - TypeGeneralization, - /// The bounds on a type parameter have been tightened. - TypeSpecialization, /// A variant has been added to an enum. VariantAdded, /// A variant has been removed from an enum. @@ -157,12 +153,6 @@ pub enum BinaryChangeType<'tcx> { VariantFieldRemoved { public: bool, total_public: bool }, /// A variant has changed it's style. VariantStyleChanged { now_struct: bool, total_private: bool }, - /// A field in a struct or enum has changed it's type. - TypeChanged { error: TypeError<'tcx> }, - /// An impl item has been added. - TraitImplItemAdded { defaulted: bool }, - /// An impl item has been removed. - TraitImplItemRemoved, /// A function changed it's variadicity. FnVariadicChanged, /// A function changed it's unsafety. @@ -171,6 +161,12 @@ pub enum BinaryChangeType<'tcx> { FnAbiChanged, /// A function's arity changed. FnArityChanged, + /// A trait's definition added an item. + TraitItemAdded { defaulted: bool }, + /// A trait's definition removed an item. + TraitItemRemoved { defaulted: bool }, + /// A field in a struct or enum has changed it's type. + TypeChanged { error: TypeError<'tcx> }, /// An unknown change is any change we don't yet explicitly handle. Unknown, } @@ -187,21 +183,20 @@ impl<'tcx> BinaryChangeType<'tcx> { RegionParameterRemoved | TypeParameterAdded { defaulted: false } | TypeParameterRemoved { .. } | - TypeSpecialization | VariantAdded | VariantRemoved | VariantFieldAdded { .. } | VariantFieldRemoved { .. } | VariantStyleChanged { .. } | TypeChanged { .. } | - TraitImplItemAdded { .. } | - TraitImplItemRemoved | FnVariadicChanged | FnUnsafetyChanged { now_unsafe: true } | FnAbiChanged | FnArityChanged | + TraitItemAdded { defaulted: false } | + TraitItemRemoved { .. } | Unknown => Breaking, - TypeGeneralization | + TraitItemAdded { defaulted: true } | ItemMadePublic => TechnicallyBreaking, TypeParameterAdded { defaulted: true } | FnUnsafetyChanged { now_unsafe: false } => NonBreaking, @@ -221,22 +216,22 @@ pub struct BinaryChange<'tcx> { changes: Vec<(BinaryChangeType<'tcx>, Option)>, /// The most severe change category already recorded for the item. max: ChangeCategory, - /// The old export of the change item. - old: Export, - /// The new export of the change item. - new: Export, + /// The symbol associated with the change item. + name: Symbol, + /// The new span associated with the change item. + new_span: Span, /// Whether to output changes. Used to distinguish all-private items. output: bool } impl<'tcx> BinaryChange<'tcx> { /// Construct a new empty change record for an item. - fn new(old: Export, new: Export, output: bool) -> BinaryChange<'tcx> { + fn new(name: Symbol, span: Span, output: bool) -> BinaryChange<'tcx> { BinaryChange { changes: Vec::new(), max: ChangeCategory::default(), - old: old, - new: new, + name: name, + new_span: span, output: output, } } @@ -259,12 +254,12 @@ impl<'tcx> BinaryChange<'tcx> { /// Get the new span of the change item. fn new_span(&self) -> &Span { - &self.new.span + &self.new_span } /// Get the ident of the change item. - fn ident(&self) -> &Ident { - &self.old.ident + fn ident(&self) -> &Symbol { + &self.name } /// Report the change. @@ -274,7 +269,7 @@ impl<'tcx> BinaryChange<'tcx> { } let msg = format!("{:?} changes in `{}`", self.max, self.ident()); - let mut builder = session.struct_span_warn(self.new.span, &msg); + let mut builder = session.struct_span_warn(self.new_span, &msg); for change in &self.changes { let cat = change.0.to_category(); @@ -341,8 +336,8 @@ impl<'tcx> Change<'tcx> { } /// Construct a new binary change for the given exports. - fn new_binary(old: Export, new: Export, output: bool) -> Change<'tcx> { - Change::Binary(BinaryChange::new(old, new, output)) + fn new_binary(name: Symbol, span: Span, output: bool) -> Change<'tcx> { + Change::Binary(BinaryChange::new(name, span, output)) } /// Add a change type to a given binary change. @@ -424,9 +419,9 @@ impl<'tcx> ChangeSet<'tcx> { } /// Add a new binary change entry for the given exports. - pub fn new_binary(&mut self, old: Export, new: Export, output: bool) { - let key = ChangeKey::OldKey(old.def.def_id()); - let change = Change::new_binary(old, new, output); + pub fn new_binary(&mut self, old_did: DefId, name: Symbol, span: Span, output: bool) { + let key = ChangeKey::OldKey(old_did); + let change = Change::new_binary(name, span, output); self.spans.insert(*change.span(), key.clone()); self.changes.insert(key, change); @@ -561,32 +556,7 @@ pub mod tests { fn build_binary_change(t: BinaryChangeType, s1: Span, s2: Span) -> BinaryChange { let mut interner = Interner::new(); - let ident1 = Ident { - name: interner.intern("test"), - ctxt: SyntaxContext::empty(), - }; - let ident2 = Ident { - name: interner.intern("test"), - ctxt: SyntaxContext::empty(), - }; - let export1 = Export { - ident: ident1, - def: Def::Mod(DefId { - krate: LOCAL_CRATE, - index: CRATE_DEF_INDEX, - }), - span: s1, - }; - let export2 = Export { - ident: ident2, - def: Def::Mod(DefId { - krate: LOCAL_CRATE, - index: CRATE_DEF_INDEX, - }), - span: s2, - }; - - let mut change = BinaryChange::new(export1, export2, true); + let mut change = BinaryChange::new(interner.intern("test"), s2, true); change.add(t, Some(s1)); change @@ -666,7 +636,11 @@ pub mod tests { build_binary_change(Unknown, span1.clone().inner(), span2.clone().inner()); - let key = ChangeKey::OldKey(change.old.def.def_id()); + let did = DefId { + krate: LOCAL_CRATE, + index: CRATE_DEF_INDEX, + }; + let key = ChangeKey::OldKey(did); set.new_unary_change(Change::Binary(change), key); } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 047ea0f0f0bce..74299aa552c6c 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -11,9 +11,10 @@ use rustc::hir::def::{CtorKind, Def}; use rustc::hir::def_id::DefId; -use rustc::ty::{Ty, TyCtxt}; +use rustc::infer::InferCtxt; +use rustc::ty::{Region, Ty, TyCtxt}; use rustc::ty::Visibility::Public; -use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; +use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder}; use rustc::ty::subst::{Subst, Substs}; use semcheck::changes::BinaryChangeType; @@ -98,7 +99,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, }; if o_vis != n_vis { - changes.new_binary(o, n, true); + changes.new_binary(o.def.def_id(), o.ident.name, n.span, true); if o_vis == Public && n_vis != Public { changes.add_binary(ItemMadePrivate, o_did, None); @@ -124,7 +125,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, }; let output = o_vis == Public || n_vis == Public; - changes.new_binary(o, n, output); + changes.new_binary(o.def.def_id(), o.ident.name, n.span, output); if o_vis == Public && n_vis != Public { changes.add_binary(ItemMadePrivate, o_def_id, None); @@ -359,7 +360,7 @@ fn diff_adts(changes: &mut ChangeSet, /// /// This establishes the needed correspondence relationship between non-toplevel items found in /// the trait definition. -fn diff_traits(_changes: &mut ChangeSet, +fn diff_traits(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, old: DefId, @@ -370,26 +371,38 @@ fn diff_traits(_changes: &mut ChangeSet, let mut items = HashMap::new(); for old_did in tcx.associated_item_def_ids(old).iter() { - items.entry(tcx.associated_item(*old_did).name) - .or_insert((None, None)).0 = tcx.describe_def(*old_did); + let item = tcx.associated_item(*old_did); + items.entry(item.name).or_insert((None, None)).0 = + tcx.describe_def(*old_did).map(|d| (d, item)); } for new_did in tcx.associated_item_def_ids(new).iter() { - items.entry(tcx.associated_item(*new_did).name) - .or_insert((None, None)).1 = tcx.describe_def(*new_did); + let item = tcx.associated_item(*new_did); + items.entry(item.name).or_insert((None, None)).1 = + tcx.describe_def(*new_did).map(|d| (d, item)); + } - for item_pair in items.values() { + for (name, item_pair) in items.iter() { match *item_pair { - (Some(old_def), Some(new_def)) => { + (Some((old_def, _)), Some((new_def, _))) => { id_mapping.add_trait_item(old_def, new_def); - println!("map!"); + changes.new_binary(old_def.def_id(), + *name, + tcx.def_span(new_def.def_id()), + true); }, - (Some(old_def), None) => { - println!("missing: {:?}", old_def); + (Some((_, old_item)), None) => { + let change_type = TraitItemRemoved { + defaulted: old_item.defaultness.has_value(), + }; + changes.add_binary(change_type , old, Some(tcx.def_span(old_item.def_id))); }, - (None, Some(new_def)) => { - println!("added: {:?}", new_def); + (None, Some((_, new_item))) => { + let change_type = TraitItemAdded { + defaulted: new_item.defaultness.has_value(), + }; + changes.add_binary(change_type , old, Some(tcx.def_span(new_item.def_id))); }, (None, None) => unreachable!(), } @@ -502,7 +515,7 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, tcx.type_of(old_def_id), tcx.type_of(new_def_id)); }, - Fn(_) => { + Fn(_) | Method(_) => { let old_fn_sig = Binder(fold_to_new(id_mapping, tcx, @@ -531,6 +544,46 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } } +struct Resolver<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { + tcx: TyCtxt<'a, 'gcx, 'tcx>, + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, +} + +impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> Resolver<'a, 'gcx, 'tcx> { + pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) + -> Resolver<'a, 'gcx, 'tcx> + { + Resolver { + tcx: infcx.tcx, + infcx: infcx, + } + } +} + +impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> TypeFolder<'gcx, 'tcx> for Resolver<'a, 'gcx, 'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { + self.tcx + } + + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + if let Ok(t) = self.infcx.fully_resolve(&t) { + t + } else { + panic!("*running around screaming*"); + } + } + + // NB: taken verbatim from: `src/librustc_typeck/check/writeback.rs` + fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> { + match self.infcx.fully_resolve(&r) { + Ok(r) => r, + Err(_) => { + self.tcx.types.re_static + } + } + } +} + /// Compare two types and possibly register the error. fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, @@ -562,6 +615,62 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let new = new.subst(infcx.tcx, new_substs); if let Err(err) = infcx.can_eq(tcx.param_env(new_def_id), old, new) { + // let err = err.fold_with(&mut Resolver::new(tcx, &infcx)); + // TODO: replace with `TypeFoldable` as soon as possible + use rustc::ty::error::ExpectedFound; + use rustc::ty::error::TypeError::*; + use rustc::infer::type_variable::Default; + let mut folder = Resolver::new(&infcx); + let err = match err { + Mismatch => Mismatch, + UnsafetyMismatch(x) => UnsafetyMismatch(x.fold_with(&mut folder)), + AbiMismatch(x) => AbiMismatch(x.fold_with(&mut folder)), + Mutability => Mutability, + TupleSize(x) => TupleSize(x), + FixedArraySize(x) => FixedArraySize(x), + ArgCount => ArgCount, + RegionsDoesNotOutlive(a, b) => { + RegionsDoesNotOutlive(a.fold_with(&mut folder), b.fold_with(&mut folder)) + }, + RegionsNotSame(a, b) => { + RegionsNotSame(a.fold_with(&mut folder), b.fold_with(&mut folder)) + }, + RegionsNoOverlap(a, b) => { + RegionsNoOverlap(a.fold_with(&mut folder), b.fold_with(&mut folder)) + }, + RegionsInsufficientlyPolymorphic(a, b, ref c) => { + let c = c.clone(); + RegionsInsufficientlyPolymorphic(a, b.fold_with(&mut folder), c) + }, + RegionsOverlyPolymorphic(a, b, ref c) => { + let c = c.clone(); + RegionsOverlyPolymorphic(a, b.fold_with(&mut folder), c) + }, + IntMismatch(x) => IntMismatch(x), + FloatMismatch(x) => FloatMismatch(x), + Traits(x) => Traits(x), + VariadicMismatch(x) => VariadicMismatch(x), + CyclicTy => CyclicTy, + ProjectionNameMismatched(x) => ProjectionNameMismatched(x), + ProjectionBoundsLength(x) => ProjectionBoundsLength(x), + Sorts(x) => Sorts(x.fold_with(&mut folder)), + TyParamDefaultMismatch(ExpectedFound { expected, found }) => { + let y = Default { + ty: expected.ty.fold_with(&mut folder), + origin_span: expected.origin_span, + def_id: expected.def_id + }; + let z = Default { + ty: found.ty.fold_with(&mut folder), + origin_span: found.origin_span, + def_id: found.def_id + }; + + TyParamDefaultMismatch(ExpectedFound { expected: y, found: z }) + }, + ExistentialMismatch(x) => ExistentialMismatch(x.fold_with(&mut folder)), + }; + changes.add_binary(TypeChanged { error: err.lift_to_tcx(tcx).unwrap() }, old_def_id, None); From a32350b80952b5a6176daef41d8b6fc2d605103e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 9 Jul 2017 12:32:52 +0200 Subject: [PATCH 120/553] Added basic trait tests. --- tests/examples/trait.out | 46 ++++++++++++++++++++++++++++++++++++++++ tests/examples/trait.rs | 29 +++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 tests/examples/trait.out create mode 100644 tests/examples/trait.rs diff --git a/tests/examples/trait.out b/tests/examples/trait.out new file mode 100644 index 0000000000000..4c660c7b5454d --- /dev/null +++ b/tests/examples/trait.out @@ -0,0 +1,46 @@ +version bump: 1.0.0 -> (Breaking) -> 2.0.0 +warning: Breaking changes in `Abc` + --> $REPO_PATH/tests/examples/trait.rs:17:5 + | +17 | / pub trait Abc { +18 | | type A; +19 | | fn test(&self) -> u8; +20 | | fn test3(&self) -> u8; +... | +27 | | fn test7() -> u16; +28 | | } + | |_____^ + | +note: TechnicallyBreaking (TraitItemAdded { defaulted: true }) + --> $REPO_PATH/tests/examples/trait.rs:24:9 + | +24 | / fn test6() -> u8 { +25 | | 0 +26 | | } + | |_________^ +warning: Breaking (TraitItemRemoved { defaulted: true }) + --> $REPO_PATH/tests/examples/trait.rs:9:9 + | +9 | / fn test5() -> u8 { +10 | | 0 +11 | | } + | |_________^ +warning: Breaking (TraitItemRemoved { defaulted: false }) + --> $REPO_PATH/tests/examples/trait.rs:5:9 + | +5 | fn test2(&self) -> u8; + | ^^^^^^^^^^^^^^^^^^^^^^ +warning: Breaking (TraitItemAdded { defaulted: false }) + --> $REPO_PATH/tests/examples/trait.rs:20:9 + | +20 | fn test3(&self) -> u8; + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: Breaking changes in `test7` + --> $REPO_PATH/tests/examples/trait.rs:27:9 + | +27 | fn test7() -> u16; + | ^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) + diff --git a/tests/examples/trait.rs b/tests/examples/trait.rs new file mode 100644 index 0000000000000..187b07b38956a --- /dev/null +++ b/tests/examples/trait.rs @@ -0,0 +1,29 @@ +pub mod old { + pub trait Abc { + type A; + fn test(&self) -> u8; + fn test2(&self) -> u8; + fn test4() -> u8 { + 0 + } + fn test5() -> u8 { + 0 + } + fn test7() -> u8; + } +} + +pub mod new { + pub trait Abc { + type A; + fn test(&self) -> u8; + fn test3(&self) -> u8; + fn test4() -> u8 { + 0 + } + fn test6() -> u8 { + 0 + } + fn test7() -> u16; + } +} From 1bf7c040b562c6f6964a9fa10f61bb90f508907a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 9 Jul 2017 13:11:49 +0200 Subject: [PATCH 121/553] Ripped out structural checks for fn items and added method checks. Things like arity and ABI mismatches are already handled by the typechecker, so use that. Instead, compare function constness and the possibility of calling methods as methods. --- src/semcheck/changes.rs | 21 ++++++++----------- src/semcheck/traverse.rs | 44 ++++++++++++++++------------------------ tests/examples/fn.out | 4 ++-- tests/examples/trait.out | 22 ++++++++++---------- 4 files changed, 38 insertions(+), 53 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 9ad71b9fcbc2c..0e17a78d786a0 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -153,14 +153,10 @@ pub enum BinaryChangeType<'tcx> { VariantFieldRemoved { public: bool, total_public: bool }, /// A variant has changed it's style. VariantStyleChanged { now_struct: bool, total_private: bool }, - /// A function changed it's variadicity. - FnVariadicChanged, - /// A function changed it's unsafety. - FnUnsafetyChanged { now_unsafe: bool }, - /// A function's ABI has changed. - FnAbiChanged, - /// A function's arity changed. - FnArityChanged, + /// A function has changed it's constness. + FnConstChanged { now_const: bool }, + /// A method has changed whether it can be invoked as a method call. + MethodSelfChanged { now_self: bool }, /// A trait's definition added an item. TraitItemAdded { defaulted: bool }, /// A trait's definition removed an item. @@ -189,17 +185,16 @@ impl<'tcx> BinaryChangeType<'tcx> { VariantFieldRemoved { .. } | VariantStyleChanged { .. } | TypeChanged { .. } | - FnVariadicChanged | - FnUnsafetyChanged { now_unsafe: true } | - FnAbiChanged | - FnArityChanged | + FnConstChanged { now_const: false } | + MethodSelfChanged { now_self: false } | TraitItemAdded { defaulted: false } | TraitItemRemoved { .. } | Unknown => Breaking, + MethodSelfChanged { now_self: true } | TraitItemAdded { defaulted: true } | ItemMadePublic => TechnicallyBreaking, TypeParameterAdded { defaulted: true } | - FnUnsafetyChanged { now_unsafe: false } => NonBreaking, + FnConstChanged { now_const: true } => NonBreaking, } } } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 74299aa552c6c..816532d712c18 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -12,7 +12,7 @@ use rustc::hir::def::{CtorKind, Def}; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; -use rustc::ty::{Region, Ty, TyCtxt}; +use rustc::ty::{AssociatedItem, Region, Ty, TyCtxt}; use rustc::ty::Visibility::Public; use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder}; use rustc::ty::subst::{Subst, Substs}; @@ -23,7 +23,7 @@ use semcheck::changes::ChangeSet; use semcheck::mapping::{IdMapping, NameMapping}; use semcheck::mismatch::Mismatch; -use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; +use std::collections::{BTreeMap, HashSet, VecDeque}; /// The main entry point to our analysis passes. /// @@ -211,37 +211,26 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, /// Given two fn items, perform structural checks. fn diff_fn(changes: &mut ChangeSet, tcx: TyCtxt, old: Def, new: Def) { - use rustc::hir::Unsafety::Unsafe; - let old_def_id = old.def_id(); let new_def_id = new.def_id(); - let old_ty = tcx.type_of(old_def_id); - let new_ty = tcx.type_of(new_def_id); - - let old_poly_sig = old_ty.fn_sig(tcx); - let new_poly_sig = new_ty.fn_sig(tcx); + let old_const = tcx.is_const_fn(old_def_id); + let new_const = tcx.is_const_fn(new_def_id); - let old_sig = old_poly_sig.skip_binder(); - let new_sig = new_poly_sig.skip_binder(); - - if old_sig.variadic != new_sig.variadic { - changes.add_binary(FnVariadicChanged, old_def_id, None); - } - - if old_sig.unsafety != new_sig.unsafety { - let change = FnUnsafetyChanged { now_unsafe: new_sig.unsafety == Unsafe }; - changes.add_binary(change, old_def_id, None); + if old_const != new_const { + changes.add_binary(FnConstChanged { now_const: new_const }, old_def_id, None); } +} - if old_sig.abi != new_sig.abi { - // TODO: more sophisticated comparison - changes.add_binary(FnAbiChanged, old_def_id, None); +/// Given two method items, perform structural checks. +fn diff_method(changes: &mut ChangeSet, tcx: TyCtxt, old: AssociatedItem, new: AssociatedItem) { + if old.method_has_self_argument != new.method_has_self_argument { + changes.add_binary(MethodSelfChanged { now_self: new.method_has_self_argument }, + old.def_id, + None); } - if old_sig.inputs_and_output.len() != new_sig.inputs_and_output.len() { - changes.add_binary(FnArityChanged, old_def_id, None); - } + diff_fn(changes, tcx, Def::Method(old.def_id), Def::Method(new.def_id)); } /// Given two ADT items, perform structural checks. @@ -368,7 +357,7 @@ fn diff_traits(changes: &mut ChangeSet, let _old_unsafety = tcx.trait_def(old).unsafety; let _new_unsafety = tcx.trait_def(new).unsafety; - let mut items = HashMap::new(); + let mut items = BTreeMap::new(); for old_did in tcx.associated_item_def_ids(old).iter() { let item = tcx.associated_item(*old_did); @@ -385,12 +374,13 @@ fn diff_traits(changes: &mut ChangeSet, for (name, item_pair) in items.iter() { match *item_pair { - (Some((old_def, _)), Some((new_def, _))) => { + (Some((old_def, old_item)), Some((new_def, new_item))) => { id_mapping.add_trait_item(old_def, new_def); changes.new_binary(old_def.def_id(), *name, tcx.def_span(new_def.def_id()), true); + diff_method(changes, tcx, old_item, new_item); }, (Some((_, old_item)), None) => { let change_type = TraitItemRemoved { diff --git a/tests/examples/fn.out b/tests/examples/fn.out index 40cdc2ff627de..e31f88f4e44bf 100644 --- a/tests/examples/fn.out +++ b/tests/examples/fn.out @@ -5,7 +5,7 @@ warning: Breaking changes in `bcd` 26 | pub fn bcd(_: u8) {} | ^^^^^^^^^^^^^^^^^^^^ | - = warning: Breaking (FnArityChanged) + = warning: Breaking (TypeChanged { error: ArgCount }) warning: Breaking changes in `cde` --> $REPO_PATH/tests/examples/fn.rs:28:5 @@ -23,7 +23,7 @@ warning: Breaking changes in `def` 32 | pub fn def() {} | ^^^^^^^^^^^^^^^ | - = warning: Breaking (FnArityChanged) + = warning: Breaking (TypeChanged { error: ArgCount }) warning: NonBreaking changes in `efg` --> $REPO_PATH/tests/examples/fn.rs:36:5 diff --git a/tests/examples/trait.out b/tests/examples/trait.out index 4c660c7b5454d..9e78ba26496bf 100644 --- a/tests/examples/trait.out +++ b/tests/examples/trait.out @@ -11,13 +11,11 @@ warning: Breaking changes in `Abc` 28 | | } | |_____^ | -note: TechnicallyBreaking (TraitItemAdded { defaulted: true }) - --> $REPO_PATH/tests/examples/trait.rs:24:9 +warning: Breaking (TraitItemRemoved { defaulted: false }) + --> $REPO_PATH/tests/examples/trait.rs:5:9 | -24 | / fn test6() -> u8 { -25 | | 0 -26 | | } - | |_________^ +5 | fn test2(&self) -> u8; + | ^^^^^^^^^^^^^^^^^^^^^^ warning: Breaking (TraitItemRemoved { defaulted: true }) --> $REPO_PATH/tests/examples/trait.rs:9:9 | @@ -25,16 +23,18 @@ warning: Breaking (TraitItemRemoved { defaulted: true }) 10 | | 0 11 | | } | |_________^ -warning: Breaking (TraitItemRemoved { defaulted: false }) - --> $REPO_PATH/tests/examples/trait.rs:5:9 - | -5 | fn test2(&self) -> u8; - | ^^^^^^^^^^^^^^^^^^^^^^ warning: Breaking (TraitItemAdded { defaulted: false }) --> $REPO_PATH/tests/examples/trait.rs:20:9 | 20 | fn test3(&self) -> u8; | ^^^^^^^^^^^^^^^^^^^^^^ +note: TechnicallyBreaking (TraitItemAdded { defaulted: true }) + --> $REPO_PATH/tests/examples/trait.rs:24:9 + | +24 | / fn test6() -> u8 { +25 | | 0 +26 | | } + | |_________^ warning: Breaking changes in `test7` --> $REPO_PATH/tests/examples/trait.rs:27:9 From 0ab4bb7c174253a68ff2be09c140a9e0d7561433 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 9 Jul 2017 13:18:51 +0200 Subject: [PATCH 122/553] Updated tests. --- tests/examples/fn.out | 60 ++++++++++++++++++++++++++-------------- tests/examples/fn.rs | 20 ++++++++++++-- tests/examples/trait.out | 46 ++++++++++++++++++++---------- tests/examples/trait.rs | 4 +++ 4 files changed, 93 insertions(+), 37 deletions(-) diff --git a/tests/examples/fn.out b/tests/examples/fn.out index e31f88f4e44bf..1a7b745b119e9 100644 --- a/tests/examples/fn.out +++ b/tests/examples/fn.out @@ -1,57 +1,77 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 warning: Breaking changes in `bcd` - --> $REPO_PATH/tests/examples/fn.rs:26:5 + --> $REPO_PATH/tests/examples/fn.rs:36:5 | -26 | pub fn bcd(_: u8) {} +36 | pub fn bcd(_: u8) {} | ^^^^^^^^^^^^^^^^^^^^ | = warning: Breaking (TypeChanged { error: ArgCount }) warning: Breaking changes in `cde` - --> $REPO_PATH/tests/examples/fn.rs:28:5 + --> $REPO_PATH/tests/examples/fn.rs:38:5 | -28 | / pub fn cde() -> u16 { -29 | | 0xcde -30 | | } +38 | / pub fn cde() -> u16 { +39 | | 0xcde +40 | | } | |_____^ | = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: (), found: u16 }) }) warning: Breaking changes in `def` - --> $REPO_PATH/tests/examples/fn.rs:32:5 + --> $REPO_PATH/tests/examples/fn.rs:42:5 | -32 | pub fn def() {} +42 | pub fn def() {} | ^^^^^^^^^^^^^^^ | = warning: Breaking (TypeChanged { error: ArgCount }) warning: NonBreaking changes in `efg` - --> $REPO_PATH/tests/examples/fn.rs:36:5 + --> $REPO_PATH/tests/examples/fn.rs:44:5 | -36 | / pub fn efg(a: A, _: A) -> A { -37 | | a -38 | | } +44 | / pub fn efg(a: A, _: A) -> A { +45 | | a +46 | | } | |_____^ | = note: NonBreaking (TypeParameterAdded { defaulted: true }) warning: Breaking changes in `fgh` - --> $REPO_PATH/tests/examples/fn.rs:40:5 + --> $REPO_PATH/tests/examples/fn.rs:48:5 | -40 | / pub fn fgh(a: u8, _: u16) -> u8 { -41 | | a -42 | | } +48 | / pub fn fgh(a: u8, _: u16) -> u8 { +49 | | a +50 | | } | |_____^ | = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) warning: Breaking changes in `ghi` - --> $REPO_PATH/tests/examples/fn.rs:44:5 + --> $REPO_PATH/tests/examples/fn.rs:52:5 | -44 | / pub fn ghi(a: u8, _: u8) -> u16 { -45 | | a as u16 -46 | | } +52 | / pub fn ghi(a: u8, _: u8) -> u16 { +53 | | a as u16 +54 | | } | |_____^ | = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) +warning: NonBreaking changes in `hij` + --> $REPO_PATH/tests/examples/fn.rs:56:5 + | +56 | / pub const fn hij() -> u8 { +57 | | 0 +58 | | } + | |_____^ + | + = note: NonBreaking (FnConstChanged { now_const: true }) + +warning: Breaking changes in `ijk` + --> $REPO_PATH/tests/examples/fn.rs:60:5 + | +60 | / pub fn ijk() -> u8 { +61 | | 0 +62 | | } + | |_____^ + | + = warning: Breaking (FnConstChanged { now_const: false }) + diff --git a/tests/examples/fn.rs b/tests/examples/fn.rs index a2338cc8dd966..59d2d0423a868 100644 --- a/tests/examples/fn.rs +++ b/tests/examples/fn.rs @@ -1,3 +1,5 @@ +#![feature(const_fn)] + pub mod old { pub fn abc() {} @@ -18,6 +20,14 @@ pub mod old { pub fn ghi(a: u8, _: u8) -> u8 { a } + + pub fn hij() -> u8 { + 0 + } + + pub const fn ijk() -> u8 { + 0 + } } pub mod new { @@ -31,8 +41,6 @@ pub mod new { pub fn def() {} - // TODO: this should be non-breaking (even after we make TypeParameterAdded something - // that is not `Breaking`) pub fn efg(a: A, _: A) -> A { a } @@ -44,4 +52,12 @@ pub mod new { pub fn ghi(a: u8, _: u8) -> u16 { a as u16 } + + pub const fn hij() -> u8 { + 0 + } + + pub fn ijk() -> u8 { + 0 + } } diff --git a/tests/examples/trait.out b/tests/examples/trait.out index 9e78ba26496bf..38abdf02013d4 100644 --- a/tests/examples/trait.out +++ b/tests/examples/trait.out @@ -1,14 +1,14 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 warning: Breaking changes in `Abc` - --> $REPO_PATH/tests/examples/trait.rs:17:5 + --> $REPO_PATH/tests/examples/trait.rs:19:5 | -17 | / pub trait Abc { -18 | | type A; -19 | | fn test(&self) -> u8; -20 | | fn test3(&self) -> u8; +19 | / pub trait Abc { +20 | | type A; +21 | | fn test(&self) -> u8; +22 | | fn test3(&self) -> u8; ... | -27 | | fn test7() -> u16; -28 | | } +31 | | fn test9(&self) -> u8; +32 | | } | |_____^ | warning: Breaking (TraitItemRemoved { defaulted: false }) @@ -24,23 +24,39 @@ warning: Breaking (TraitItemRemoved { defaulted: true }) 11 | | } | |_________^ warning: Breaking (TraitItemAdded { defaulted: false }) - --> $REPO_PATH/tests/examples/trait.rs:20:9 + --> $REPO_PATH/tests/examples/trait.rs:22:9 | -20 | fn test3(&self) -> u8; +22 | fn test3(&self) -> u8; | ^^^^^^^^^^^^^^^^^^^^^^ note: TechnicallyBreaking (TraitItemAdded { defaulted: true }) - --> $REPO_PATH/tests/examples/trait.rs:24:9 + --> $REPO_PATH/tests/examples/trait.rs:26:9 | -24 | / fn test6() -> u8 { -25 | | 0 -26 | | } +26 | / fn test6() -> u8 { +27 | | 0 +28 | | } | |_________^ warning: Breaking changes in `test7` - --> $REPO_PATH/tests/examples/trait.rs:27:9 + --> $REPO_PATH/tests/examples/trait.rs:29:9 | -27 | fn test7() -> u16; +29 | fn test7() -> u16; | ^^^^^^^^^^^^^^^^^^ | = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) +warning: Breaking changes in `test8` + --> $REPO_PATH/tests/examples/trait.rs:30:9 + | +30 | fn test8(_: &Self) -> u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (MethodSelfChanged { now_self: false }) + +warning: TechnicallyBreaking changes in `test9` + --> $REPO_PATH/tests/examples/trait.rs:31:9 + | +31 | fn test9(&self) -> u8; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: TechnicallyBreaking (MethodSelfChanged { now_self: true }) + diff --git a/tests/examples/trait.rs b/tests/examples/trait.rs index 187b07b38956a..16b53d5f3c8f1 100644 --- a/tests/examples/trait.rs +++ b/tests/examples/trait.rs @@ -10,6 +10,8 @@ pub mod old { 0 } fn test7() -> u8; + fn test8(&self) -> u8; + fn test9(_: &Self) -> u8; } } @@ -25,5 +27,7 @@ pub mod new { 0 } fn test7() -> u16; + fn test8(_: &Self) -> u8; + fn test9(&self) -> u8; } } From c6ae9cc06d484f7ff632d8e6b9a7f0c7d688ca03 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 10 Jul 2017 15:02:13 +0200 Subject: [PATCH 123/553] Cleaned up with the newest nightly. --- src/semcheck/traverse.rs | 59 ++-------------------------------------- 1 file changed, 2 insertions(+), 57 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 816532d712c18..52cb8ac81cfe5 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -372,7 +372,7 @@ fn diff_traits(changes: &mut ChangeSet, } - for (name, item_pair) in items.iter() { + for (name, item_pair) in &items { match *item_pair { (Some((old_def, old_item)), Some((new_def, new_item))) => { id_mapping.add_trait_item(old_def, new_def); @@ -605,62 +605,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let new = new.subst(infcx.tcx, new_substs); if let Err(err) = infcx.can_eq(tcx.param_env(new_def_id), old, new) { - // let err = err.fold_with(&mut Resolver::new(tcx, &infcx)); - // TODO: replace with `TypeFoldable` as soon as possible - use rustc::ty::error::ExpectedFound; - use rustc::ty::error::TypeError::*; - use rustc::infer::type_variable::Default; - let mut folder = Resolver::new(&infcx); - let err = match err { - Mismatch => Mismatch, - UnsafetyMismatch(x) => UnsafetyMismatch(x.fold_with(&mut folder)), - AbiMismatch(x) => AbiMismatch(x.fold_with(&mut folder)), - Mutability => Mutability, - TupleSize(x) => TupleSize(x), - FixedArraySize(x) => FixedArraySize(x), - ArgCount => ArgCount, - RegionsDoesNotOutlive(a, b) => { - RegionsDoesNotOutlive(a.fold_with(&mut folder), b.fold_with(&mut folder)) - }, - RegionsNotSame(a, b) => { - RegionsNotSame(a.fold_with(&mut folder), b.fold_with(&mut folder)) - }, - RegionsNoOverlap(a, b) => { - RegionsNoOverlap(a.fold_with(&mut folder), b.fold_with(&mut folder)) - }, - RegionsInsufficientlyPolymorphic(a, b, ref c) => { - let c = c.clone(); - RegionsInsufficientlyPolymorphic(a, b.fold_with(&mut folder), c) - }, - RegionsOverlyPolymorphic(a, b, ref c) => { - let c = c.clone(); - RegionsOverlyPolymorphic(a, b.fold_with(&mut folder), c) - }, - IntMismatch(x) => IntMismatch(x), - FloatMismatch(x) => FloatMismatch(x), - Traits(x) => Traits(x), - VariadicMismatch(x) => VariadicMismatch(x), - CyclicTy => CyclicTy, - ProjectionNameMismatched(x) => ProjectionNameMismatched(x), - ProjectionBoundsLength(x) => ProjectionBoundsLength(x), - Sorts(x) => Sorts(x.fold_with(&mut folder)), - TyParamDefaultMismatch(ExpectedFound { expected, found }) => { - let y = Default { - ty: expected.ty.fold_with(&mut folder), - origin_span: expected.origin_span, - def_id: expected.def_id - }; - let z = Default { - ty: found.ty.fold_with(&mut folder), - origin_span: found.origin_span, - def_id: found.def_id - }; - - TyParamDefaultMismatch(ExpectedFound { expected: y, found: z }) - }, - ExistentialMismatch(x) => ExistentialMismatch(x.fold_with(&mut folder)), - }; - + let err = err.fold_with(&mut Resolver::new(&infcx)); changes.add_binary(TypeChanged { error: err.lift_to_tcx(tcx).unwrap() }, old_def_id, None); From b9bb367665c080aab0d79bbcb94bbc1e68805233 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 11 Jul 2017 12:15:34 +0200 Subject: [PATCH 124/553] First round of refactorings on the cargo plugin. --- src/bin/cargo_semver.rs | 148 ++++++++++++++++++++++++++++------------ 1 file changed, 106 insertions(+), 42 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 8be3785de366d..a480297c15f3d 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -7,13 +7,14 @@ use crates_io::{Crate, Registry}; use cargo::exit_with_error; use cargo::core::{Package, PackageId, Source, SourceId, Workspace}; -use cargo::ops::{compile, Compilation, CompileMode, CompileOptions}; +use cargo::ops::{compile, CompileMode, CompileOptions}; use cargo::sources::registry::RegistrySource; use cargo::util::{human, CargoResult, CliError}; use cargo::util::config::Config; use cargo::util::important_paths::find_root_manifest_for_wd; use std::io::Write; +use std::path::PathBuf; use std::process::{Stdio, Command}; /// Given a crate name, try to locate the corresponding crate on `crates.io`. @@ -35,15 +36,82 @@ fn exact_search(query: &str) -> CargoResult { }) } -/// Compile a crate given it's workspace. -/// -/// The results returned are then used to locate the build artefacts, which in turn are linked -/// together for the actual analysis. -fn generate_rlib<'a>(config: &'a Config, - workspace: &Workspace<'a>) - -> CargoResult> { - let opts = CompileOptions::default(config, CompileMode::Build); - compile(workspace, &opts).map(|c| c) +/// A specification of package name and version. +struct NameAndVersion<'a> { + /// The package's name. + name: &'a str, + /// The package's version, as a semver-string. + version: &'a str, +} + +/// A specification of a package source to fetch remote packages from. +struct SourceInfo<'a> { + /// The source id to be used. + id: SourceId, + /// The registry to be used. + registry: RegistrySource<'a>, +} + +impl<'a> SourceInfo<'a> { + /// Construct a new source info for `crates.io`. + fn new(config: &'a Config) -> CargoResult> { + let source_id = SourceId::crates_io(config)?; + let registry = RegistrySource::remote(&source_id, config); + Ok(SourceInfo { + id: source_id, + registry: registry, + }) + } +} + +/// A specification of a package and it's workspace. +struct WorkInfo<'a> { + /// The package to be compiled. + package: Package, + /// The package's workspace. + workspace: Workspace<'a>, +} + +impl<'a> WorkInfo<'a> { + /// Construct a package/workspace pair for the local directory. + fn local(config: &'a Config) -> CargoResult> { + let manifest_path = find_root_manifest_for_wd(None, config.cwd())?; + + Ok(WorkInfo { + package: Package::for_path(&manifest_path, config)?, + workspace: Workspace::new(&manifest_path, config)?, + }) + } + + /// Construct a package/workspace pair by fetching the package of a specified name and + /// version. + fn remote(config: &'a Config, source: &mut SourceInfo<'a>, info: NameAndVersion) + -> CargoResult> + { + let package_id = PackageId::new(info.name, info.version, &source.id)?; + let package = source.registry.download(&package_id)?; + let workspace = Workspace::ephemeral(package.clone(), config, None, false)?; + + Ok(WorkInfo { + package: package, + workspace: workspace, + }) + } + + /// Obtain the paths to the rlib produced and to the output directory for dependencies. + fn rlib_and_dep_output(&self, config: &'a Config, name: &str) + -> CargoResult<(PathBuf, PathBuf)> + { + let opts = CompileOptions::default(config, CompileMode::Build); + let compilation = compile(&self.workspace, &opts)?; + let rlib = compilation.libraries[self.package.package_id()] + .iter() + .find(|t| t.0.name() == name) + .ok_or_else(|| human("lost a build artifact"))?; + + Ok((rlib.1.clone(), compilation.deps_output)) + } + } /// Perform the heavy lifting. @@ -52,51 +120,47 @@ fn generate_rlib<'a>(config: &'a Config, /// build it as well. /// /// TODO: -/// * split this up -/// * give some structure to the build artefact gathering /// * possibly reduce the complexity by investigating where some of the info can be sourced from /// in a more direct fashion +/// * add proper support to compare two arbitrary versions fn do_main() -> CargoResult<()> { + use std::env::var; let config = Config::default()?; + let mut source = SourceInfo::new(&config)?; - let manifest_path = find_root_manifest_for_wd(None, config.cwd())?; - - let local_package = Package::for_path(&manifest_path, &config)?; - let local_workspace = Workspace::new(&manifest_path, &config)?; - let local_compilation = generate_rlib(&config, &local_workspace)?; - - let name = local_package.name(); - - let local_rlib = local_compilation.libraries[local_package.package_id()] - .iter() - .find(|t| t.0.name() == name) - .ok_or_else(|| human("lost a build artifact"))?; - - let source_id = SourceId::crates_io(&config)?; - let mut registry_source = RegistrySource::remote(&source_id, &config); - - let remote_crate = exact_search(name)?; + let current = + if let (Ok(n), Ok(v)) = (var("RUST_SEMVER_NAME"), var("RUST_SEMVER_CURRENT")) { + let info = NameAndVersion { name: &n, version: &v }; + WorkInfo::remote(&config, &mut source, info)? + } else { + WorkInfo::local(&config)? + }; - let package_id = PackageId::new(name, &remote_crate.max_version, &source_id)?; + let name = current.package.name().to_owned(); - let stable_package = registry_source.download(&package_id)?; - let stable_workspace = Workspace::ephemeral(stable_package, &config, None, false)?; - let stable_compilation = generate_rlib(&config, &stable_workspace)?; + let (stable, stable_version) = if let Ok(v) = var("RUST_SEMVER_STABLE") { + let info = NameAndVersion { name: &name, version: &v }; + let work_info = WorkInfo::remote(&config, &mut source, info)?; + (work_info, v.clone()) + } else { + let stable_crate = exact_search(&name)?; + let info = NameAndVersion { name: &name, version: &stable_crate.max_version }; + let work_info = WorkInfo::remote(&config, &mut source, info)?; + (work_info, stable_crate.max_version.clone()) + }; - let stable_rlib = stable_compilation.libraries[&package_id] - .iter() - .find(|t| t.0.name() == name) - .ok_or_else(|| human("lost a build artifact"))?; + let (current_rlib, current_deps_output) = current.rlib_and_dep_output(&config, &name)?; + let (stable_rlib, stable_deps_output) = stable.rlib_and_dep_output(&config, &name)?; let mut child = Command::new("rust-semverver") .arg("--crate-type=lib") - .args(&["--extern", &*format!("old={}", stable_rlib.1.display())]) - .args(&[format!("-L{}", stable_compilation.deps_output.display())]) - .args(&["--extern", &*format!("new={}", local_rlib.1.display())]) - .args(&[format!("-L{}", local_compilation.deps_output.display())]) + .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())]) .arg("-") .stdin(Stdio::piped()) - .env("RUST_SEMVER_CRATE_VERSION", &remote_crate.max_version) + .env("RUST_SEMVER_CRATE_VERSION", stable_version) .spawn() .map_err(|e| human(format!("could not spawn rustc: {}", e)))?; From 4c9bb2c799b29cd351067d1c6b1c6445eacd776f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 11 Jul 2017 15:54:09 +0200 Subject: [PATCH 125/553] Finished refactoring cargo plugin. --- Cargo.toml | 1 + src/bin/cargo_semver.rs | 145 ++++++++++++++++++++++++++++------------ 2 files changed, 103 insertions(+), 43 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2bd03979c0dfb..207e374dd7fb8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ path = "src/bin/rust_semverver.rs" cargo = "^0.18.0" crates-io = "^0.7.0" semver = "^0.7.0" +# getopts = "^0.2.14" [dev-dependencies] quickcheck = "^0.4.1" diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index a480297c15f3d..8d3d9a134506c 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -1,7 +1,9 @@ #![feature(box_syntax)] +#![feature(rustc_private)] extern crate cargo; extern crate crates_io; +extern crate getopts; use crates_io::{Crate, Registry}; @@ -9,10 +11,12 @@ use cargo::exit_with_error; use cargo::core::{Package, PackageId, Source, SourceId, Workspace}; use cargo::ops::{compile, CompileMode, CompileOptions}; use cargo::sources::registry::RegistrySource; -use cargo::util::{human, CargoResult, CliError}; +use cargo::util::{human, CargoError, CargoResult, CliError}; use cargo::util::config::Config; use cargo::util::important_paths::find_root_manifest_for_wd; +use getopts::{Matches, Options}; + use std::io::Write; use std::path::PathBuf; use std::process::{Stdio, Command}; @@ -74,8 +78,12 @@ struct WorkInfo<'a> { impl<'a> WorkInfo<'a> { /// Construct a package/workspace pair for the local directory. - fn local(config: &'a Config) -> CargoResult> { - let manifest_path = find_root_manifest_for_wd(None, config.cwd())?; + fn local(config: &'a Config, explicit_path: Option) -> CargoResult> { + let manifest_path = if let Some(path) = explicit_path { + find_root_manifest_for_wd(None, &path)? + } else { + find_root_manifest_for_wd(None, config.cwd())? + }; Ok(WorkInfo { package: Package::for_path(&manifest_path, config)?, @@ -123,34 +131,61 @@ impl<'a> WorkInfo<'a> { /// * possibly reduce the complexity by investigating where some of the info can be sourced from /// in a more direct fashion /// * add proper support to compare two arbitrary versions -fn do_main() -> CargoResult<()> { - use std::env::var; - let config = Config::default()?; - let mut source = SourceInfo::new(&config)?; - - let current = - if let (Ok(n), Ok(v)) = (var("RUST_SEMVER_NAME"), var("RUST_SEMVER_CURRENT")) { - let info = NameAndVersion { name: &n, version: &v }; - WorkInfo::remote(&config, &mut source, info)? +fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { + fn parse_arg(opt: &str) -> CargoResult<(&str, &str)> { + let mut split = opt.split('-'); + let name = if let Some(n) = split.next() { + n + } else { + return Err(human("spec has to be of form `name-version`".to_owned())); + }; + let version = if let Some(v) = split.next() { + v } else { - WorkInfo::local(&config)? + return Err(human("spec has to be of form `name-version`".to_owned())); }; + if split.next().is_some() { + return Err(human("spec has to be of form `name-version`".to_owned())); + } + + Ok((name, version)) + } + + let mut source = SourceInfo::new(config)?; + + let current = if let Some(opt) = matches.opt_str("C") { + let (name, version) = parse_arg(&opt)?; + + let info = NameAndVersion { name: name, version: version }; + WorkInfo::remote(config, &mut source, info)? + } else { + WorkInfo::local(config, matches.opt_str("c").map(PathBuf::from))? + }; + let name = current.package.name().to_owned(); - let (stable, stable_version) = if let Ok(v) = var("RUST_SEMVER_STABLE") { - let info = NameAndVersion { name: &name, version: &v }; - let work_info = WorkInfo::remote(&config, &mut source, info)?; - (work_info, v.clone()) + let (stable, stable_version) = if let Some(opt) = matches.opt_str("S") { + let (name, version) = parse_arg(&opt)?; + + let info = NameAndVersion { name: name, version: version }; + let work_info = WorkInfo::remote(config, &mut source, info)?; + + (work_info, version.to_owned()) + } else if let Some(path) = matches.opt_str("s") { + let work_info = WorkInfo::local(config, Some(PathBuf::from(path)))?; + let version = format!("{}", work_info.package.version()); + (work_info, version) } else { let stable_crate = exact_search(&name)?; let info = NameAndVersion { name: &name, version: &stable_crate.max_version }; - let work_info = WorkInfo::remote(&config, &mut source, info)?; + let work_info = WorkInfo::remote(config, &mut source, info)?; + (work_info, stable_crate.max_version.clone()) }; - let (current_rlib, current_deps_output) = current.rlib_and_dep_output(&config, &name)?; - let (stable_rlib, stable_deps_output) = stable.rlib_and_dep_output(&config, &name)?; + let (current_rlib, current_deps_output) = current.rlib_and_dep_output(config, &name)?; + let (stable_rlib, stable_deps_output) = stable.rlib_and_dep_output(config, &name)?; let mut child = Command::new("rust-semverver") .arg("--crate-type=lib") @@ -178,20 +213,9 @@ fn do_main() -> CargoResult<()> { Ok(()) } -const CARGO_SEMVER_HELP: &str = r#"Checks a package's SemVer compatibility with already published versions. - -Usage: - cargo semver [options] - -Common options: - -h, --help Print this message - -V, --version Print version info and exit - -Currently, no other options are supported (this will change in the future) -"#; - -fn help() { - println!("{}", CARGO_SEMVER_HELP); +fn help(opts: &Options) { + let brief = "usage: cargo semver [options] [-- cargo options]"; + print!("{}", opts.usage(brief)); } fn version() { @@ -199,21 +223,56 @@ fn version() { } fn main() { - if std::env::args().any(|arg| arg == "-h" || arg == "--help") { - help(); + fn err(config: &Config, e: Box) -> ! { + exit_with_error(CliError::new(e, 1), &mut config.shell()); + } + + let args: Vec = std::env::args().skip(1).collect(); + + let mut opts = Options::new(); + + opts.optflag("h", "help", "print this message and exit"); + opts.optflag("V", "version", "print version information and exit"); + 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", "SPEC"); + opts.optopt("C", "current-pkg", "use a name-version string as current/new crate", "SPEC"); + + let config = match Config::default() { + Ok(cfg) => cfg, + Err(e) => panic!("can't obtain config: {:?}", e), + }; + + let matches = match opts.parse(&args) { + Ok(m) => m, + Err(f) => err(&config, human(f.to_string())), + }; + + if matches.opt_present("h") { + help(&opts); return; } - if std::env::args().any(|arg| arg == "-V" || arg == "--version") { + if matches.opt_present("V") { version(); return; } - if let Err(e) = do_main() { - if let Ok(config) = Config::default() { - exit_with_error(CliError::new(e, 1), &mut config.shell()); - } else { - panic!("ffs, we can't get a config and errors happened :/"); - } + 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".to_owned(); + err(&config, human(msg)); + } + + 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".to_owned(); + err(&config, human(msg)); + } + + if let Err(e) = do_main(&config, &matches) { + err(&config, e); } } From 9272492533233474d294d5796ec607d5278d5a30 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 11 Jul 2017 23:04:54 +0200 Subject: [PATCH 126/553] Updated debugging machinery. --- src/bin/cargo_semver.rs | 10 ++++++++++ tests/examples.rs | 21 ++++++++++++++++----- tests/helper/test2.rs | 2 ++ 3 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 tests/helper/test2.rs diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 8d3d9a134506c..58e84ad572d80 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -187,6 +187,15 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { let (current_rlib, current_deps_output) = current.rlib_and_dep_output(config, &name)?; let (stable_rlib, stable_deps_output) = stable.rlib_and_dep_output(config, &name)?; + if matches.opt_present("d") { + println!("--crate=type=lib --extern old={} -L{} --extern new={}, -L{} tests/helper/test2.rs", + stable_rlib.display(), + stable_deps_output.display(), + current_rlib.display(), + current_deps_output.display()); + return Ok(()); + } + let mut child = Command::new("rust-semverver") .arg("--crate-type=lib") .args(&["--extern", &*format!("old={}", stable_rlib.display())]) @@ -233,6 +242,7 @@ fn main() { opts.optflag("h", "help", "print this message and exit"); opts.optflag("V", "version", "print version information and exit"); + opts.optflag("d", "debug", "print command to debug and exit"); 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", "SPEC"); diff --git a/tests/examples.rs b/tests/examples.rs index 3b9891295778f..66e58e38aa323 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -100,19 +100,30 @@ fn examples() { let _ = dump.set_permissions(permissions); let _ = writeln!(dump, r#"#!/bin/sh -rustc --crate-type=lib -o liboldandnew.rlib "$1" - +export PATH=./target/debug:$PATH export LD_LIBRARY_PATH={} -export RUST_SEMVERVER_TEST=1 export RUST_LOG=debug export RUST_BACKTRACE=full export RUST_SEMVER_CRATE_VERSION=1.0.0 -arg_str="set args --crate-type=lib --extern oldandnew=liboldandnew.rlib - < tests/helper/test.rs" +if [ "$1" = "-s" ]; then + shift + arg_str="set args $(cargo semver "$@")" + standalone=1 +else + rustc --crate-type=lib -o liboldandnew.rlib "$1" + export RUST_SEMVERVER_TEST=1 + arg_str="set args --crate-type=lib --extern oldandnew=liboldandnew.rlib tests/helper/test.rs" + standalone=0 +fi + src_str="set substitute-path /checkout $(rustc --print sysroot)/lib/rustlib/src/rust" rust-gdb ./target/debug/rust-semverver -iex "$arg_str" -iex "$src_str" -rm liboldandnew.rlib"#, path); + +if [ $standalone = 0 ]; then + rm liboldandnew.rlib +fi"#, path); } assert!(success, "an error occured"); diff --git a/tests/helper/test2.rs b/tests/helper/test2.rs new file mode 100644 index 0000000000000..88c8d225801c7 --- /dev/null +++ b/tests/helper/test2.rs @@ -0,0 +1,2 @@ +extern crate old; +extern crate new; From 9adc1b37b5d9578fd63694c3748a0e8f2ff9ce3a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 12 Jul 2017 18:07:56 +0200 Subject: [PATCH 127/553] Fixes to testing infrastructure. --- src/bin/cargo_semver.rs | 2 +- src/semcheck/mismatch.rs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 58e84ad572d80..ddca2da7c3748 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -188,7 +188,7 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { let (stable_rlib, stable_deps_output) = stable.rlib_and_dep_output(config, &name)?; if matches.opt_present("d") { - println!("--crate=type=lib --extern old={} -L{} --extern new={}, -L{} tests/helper/test2.rs", + println!("--crate-type=lib --extern old={} -L{} --extern new={} -L{} tests/helper/test2.rs", stable_rlib.display(), stable_deps_output.display(), current_rlib.display(), diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index a6209409558d4..d9646da2ba681 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -45,11 +45,12 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> Mismatch<'a, 'gcx, 'tcx> { /// Process the next pair of `DefId`s in the queue and return them. pub fn process(&mut self) { - use rustc::hir::def::Def::Trait; + use rustc::hir::def::Def::*; while let Some((old_did, new_did)) = self.item_queue.pop_front() { - if let Some(Trait(_)) = self.tcx.describe_def(old_did) { - continue; + match self.tcx.describe_def(old_did) { + Some(Trait(_)) | Some(Macro(_, _)) => continue, + _ => (), } let old_ty = self.tcx.type_of(old_did); From 6f766f9e6ec8327df16f3e39f2ddcfa914519153 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 12 Jul 2017 19:47:45 +0200 Subject: [PATCH 128/553] Fixed testing environment. --- tests/examples.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/examples.rs b/tests/examples.rs index 66e58e38aa323..9e32e1db9d0a9 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -102,7 +102,6 @@ fn examples() { let _ = writeln!(dump, r#"#!/bin/sh export PATH=./target/debug:$PATH export LD_LIBRARY_PATH={} -export RUST_LOG=debug export RUST_BACKTRACE=full export RUST_SEMVER_CRATE_VERSION=1.0.0 @@ -117,6 +116,8 @@ else standalone=0 fi +export RUST_LOG=debug + src_str="set substitute-path /checkout $(rustc --print sysroot)/lib/rustlib/src/rust" rust-gdb ./target/debug/rust-semverver -iex "$arg_str" -iex "$src_str" From f0abdb6db1a314dce0239779ac9dda2a47adcfb4 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 12 Jul 2017 19:48:01 +0200 Subject: [PATCH 129/553] Cleaned up resolving machinery for type errors. --- src/semcheck/traverse.rs | 50 +++++----------------------------------- 1 file changed, 6 insertions(+), 44 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 52cb8ac81cfe5..25934ba4f0586 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -11,10 +11,9 @@ use rustc::hir::def::{CtorKind, Def}; use rustc::hir::def_id::DefId; -use rustc::infer::InferCtxt; -use rustc::ty::{AssociatedItem, Region, Ty, TyCtxt}; +use rustc::ty::{AssociatedItem, Ty, TyCtxt}; use rustc::ty::Visibility::Public; -use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder}; +use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; use rustc::ty::subst::{Subst, Substs}; use semcheck::changes::BinaryChangeType; @@ -534,46 +533,6 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } } -struct Resolver<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { - tcx: TyCtxt<'a, 'gcx, 'tcx>, - infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, -} - -impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> Resolver<'a, 'gcx, 'tcx> { - pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) - -> Resolver<'a, 'gcx, 'tcx> - { - Resolver { - tcx: infcx.tcx, - infcx: infcx, - } - } -} - -impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> TypeFolder<'gcx, 'tcx> for Resolver<'a, 'gcx, 'tcx> { - fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { - self.tcx - } - - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if let Ok(t) = self.infcx.fully_resolve(&t) { - t - } else { - panic!("*running around screaming*"); - } - } - - // NB: taken verbatim from: `src/librustc_typeck/check/writeback.rs` - fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> { - match self.infcx.fully_resolve(&r) { - Ok(r) => r, - Err(_) => { - self.tcx.types.re_static - } - } - } -} - /// Compare two types and possibly register the error. fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, @@ -605,7 +564,10 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let new = new.subst(infcx.tcx, new_substs); if let Err(err) = infcx.can_eq(tcx.param_env(new_def_id), old, new) { - let err = err.fold_with(&mut Resolver::new(&infcx)); + let err = match infcx.fully_resolve(&err) { + Ok(res) => res, + Err(err) => panic!("err: {:?}", err), + }; changes.add_binary(TypeChanged { error: err.lift_to_tcx(tcx).unwrap() }, old_def_id, None); From e36e44f1de004a2ed6f1baa5804bfa1d57ff6112 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 13 Jul 2017 11:38:29 +0200 Subject: [PATCH 130/553] Small fixes. Implemented region did recording. Removed some rough edges. --- src/semcheck/traverse.rs | 77 +++++++++++++++++++++++++++++++++------- tests/examples/infer.out | 14 +++++++- 2 files changed, 78 insertions(+), 13 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 25934ba4f0586..f2f7fd6890d77 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -183,6 +183,12 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, diff_adts(changes, id_mapping, tcx, o.def, n.def); }, (Trait(_), Trait(_)) => { + diff_generics(changes, + id_mapping, + tcx, + false, + o_def_id, + n_def_id); diff_traits(changes, id_mapping, tcx, o_def_id, n_def_id); }, // non-matching item pair - register the difference and abort @@ -414,13 +420,15 @@ fn diff_generics(changes: &mut ChangeSet, for i in 0..max(old_gen.regions.len(), new_gen.regions.len()) { match (old_gen.regions.get(i), new_gen.regions.get(i)) { + (Some(old_region), Some(new_region)) => { + id_mapping.add_internal_item(old_region.def_id, new_region.def_id); + }, (Some(_ /* old_region */), None) => { found.push(RegionParameterRemoved); }, (None, Some(_ /* new_region */)) => { found.push(RegionParameterAdded); }, - (Some(_), Some(_)) => (), (None, None) => unreachable!(), } } @@ -485,7 +493,6 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, old: Def, new: Def) { use rustc::hir::def::Def::*; - use rustc::ty::Binder; let old_def_id = old.def_id(); let new_def_id = new.def_id(); @@ -505,10 +512,7 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, tcx.type_of(new_def_id)); }, Fn(_) | Method(_) => { - let old_fn_sig = - Binder(fold_to_new(id_mapping, - tcx, - tcx.type_of(old_def_id).fn_sig(tcx).skip_binder())); + 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, @@ -545,8 +549,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, use rustc::ty::{Lift, ReEarlyBound}; let substs = Substs::identity_for_item(tcx, new_def_id); - - let old = fold_to_new(id_mapping, tcx, &old.subst(tcx, substs)); + let old = fold_to_new(id_mapping, tcx, &old).subst(tcx, substs); tcx.infer_ctxt().enter(|infcx| { let new_substs = if new.is_fn() { @@ -568,6 +571,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, Ok(res) => res, Err(err) => panic!("err: {:?}", err), }; + changes.add_binary(TypeChanged { error: err.lift_to_tcx(tcx).unwrap() }, old_def_id, None); @@ -579,10 +583,47 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, old: &T) -> T where T: TypeFoldable<'tcx> { - use rustc::ty::{AdtDef, Binder, ExistentialProjection, ExistentialTraitRef}; - use rustc::ty::ExistentialPredicate::*; + use rustc::ty::{AdtDef, /*Binder,*/ BoundRegion, EarlyBoundRegion, /*ExistentialProjection, + ExistentialTraitRef,*/ Region, RegionKind}; + // use rustc::ty::ExistentialPredicate::*; use rustc::ty::TypeVariants::*; + fn replace_bound_region_did(id_mapping: &IdMapping, region: &BoundRegion) -> BoundRegion { + use rustc::ty::BoundRegion::BrNamed; + + match *region { + BrNamed(def_id, name) => BrNamed(id_mapping.get_new_id(def_id), name), + reg => reg, + } + } + + fn replace_region_did<'tcx>(id_mapping: &IdMapping, region: Region<'tcx>) -> RegionKind { + use rustc::ty::FreeRegion; + use rustc::ty::RegionKind::*; + + match *region { + ReEarlyBound(early) => { + let new_early = EarlyBoundRegion { + def_id: id_mapping.get_new_id(early.def_id), + index: early.index, + name: early.name, + }; + + ReEarlyBound(new_early) + }, + ReLateBound(index, region) => { + ReLateBound(index, replace_bound_region_did(id_mapping, ®ion)) + }, + ReFree(FreeRegion { scope, bound_region }) => { + ReFree(FreeRegion { + scope: id_mapping.get_new_id(scope), + bound_region: replace_bound_region_did(id_mapping, &bound_region), + }) + }, + reg => reg, + } + } + old.fold_with(&mut BottomUpFolder { tcx: tcx, fldop: |ty| { match ty.sty { TyAdt(&AdtDef { ref did, .. }, substs) if id_mapping.contains_id(*did) => { @@ -590,7 +631,19 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, let new_adt = tcx.adt_def(new_did); tcx.mk_adt(new_adt, substs) }, - TyDynamic(preds, region) => { + TyRef(region, type_and_mut) => { + tcx.mk_ref(tcx.mk_region(replace_region_did(id_mapping, region)), type_and_mut) + }, + TyFnDef(did, substs) => { + tcx.mk_fn_def(id_mapping.get_new_id(did), substs) + }, + /* TyProjection(proj) => { + tcx.mk_projection(id_mapping.get_new_id(proj.item_def_id), proj.substs) + }, */ + TyAnon(did, substs) => { + tcx.mk_anon(id_mapping.get_new_id(did), substs) + }, + /* TODO: TyDynamic(preds, region) => { let new_preds = tcx.mk_existential_predicates(preds.iter().map(|p| { match *p.skip_binder() { Trait(ExistentialTraitRef { def_id: did, substs }) => { @@ -634,7 +687,7 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, })); tcx.mk_dynamic(Binder(new_preds), region) - }, + }, */ _ => ty, } }}) diff --git a/tests/examples/infer.out b/tests/examples/infer.out index 84bd4ceab5d48..13e3377114942 100644 --- a/tests/examples/infer.out +++ b/tests/examples/infer.out @@ -1 +1,13 @@ -version bump: 1.0.0 -> (Patch) -> 1.0.1 +version bump: 1.0.0 -> (Breaking) -> 2.0.0 +warning: Breaking changes in `Hij` + --> $REPO_PATH/tests/examples/infer.rs:41:5 + | +41 | / pub struct Hij<'a> { +42 | | pub field: &'a a::Def, +43 | | pub field2: ::std::rc::Rc, +44 | | } + | |_____^ + | + = warning: Breaking (TypeChanged { error: Traits(ExpectedFound { expected: DefId { krate: CrateNum(12), node: DefIndex(5) => infer/8cd878b::old[0]::a[0]::Abc[0] }, found: DefId { krate: CrateNum(12), node: DefIndex(12) => infer/8cd878b::new[0]::a[0]::Def[0] } }) }) + = warning: Breaking (TypeChanged { error: Traits(ExpectedFound { expected: DefId { krate: CrateNum(12), node: DefIndex(5) => infer/8cd878b::old[0]::a[0]::Abc[0] }, found: DefId { krate: CrateNum(12), node: DefIndex(12) => infer/8cd878b::new[0]::a[0]::Def[0] } }) }) + From 86bdae6ca3d25a92dbd3be438451cf18ca389733 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 13 Jul 2017 11:56:36 +0200 Subject: [PATCH 131/553] Fixed a test regression on newest nightly. --- src/semcheck/traverse.rs | 29 ++++++++++++----------------- tests/examples/infer.out | 14 +------------- 2 files changed, 13 insertions(+), 30 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index f2f7fd6890d77..a627d89169658 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -583,16 +583,16 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, old: &T) -> T where T: TypeFoldable<'tcx> { - use rustc::ty::{AdtDef, /*Binder,*/ BoundRegion, EarlyBoundRegion, /*ExistentialProjection, - ExistentialTraitRef,*/ Region, RegionKind}; - // use rustc::ty::ExistentialPredicate::*; + use rustc::ty::{AdtDef, Binder, BoundRegion, EarlyBoundRegion, ExistentialProjection, + ExistentialTraitRef, Region, RegionKind}; + use rustc::ty::ExistentialPredicate::*; use rustc::ty::TypeVariants::*; fn replace_bound_region_did(id_mapping: &IdMapping, region: &BoundRegion) -> BoundRegion { use rustc::ty::BoundRegion::BrNamed; match *region { - BrNamed(def_id, name) => BrNamed(id_mapping.get_new_id(def_id), name), + BrNamed(def_id, name) => BrNamed(id_mapping.get_new_id(def_id), name), reg => reg, } } @@ -643,7 +643,7 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, TyAnon(did, substs) => { tcx.mk_anon(id_mapping.get_new_id(did), substs) }, - /* TODO: TyDynamic(preds, region) => { + TyDynamic(preds, region) => { let new_preds = tcx.mk_existential_predicates(preds.iter().map(|p| { match *p.skip_binder() { Trait(ExistentialTraitRef { def_id: did, substs }) => { @@ -658,23 +658,18 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, substs: substs }) }, - Projection(ExistentialProjection { trait_ref, item_name, ty }) => { - let ExistentialTraitRef { def_id: did, substs } = trait_ref; - let new_did = if id_mapping.contains_id(did) { - id_mapping.get_new_id(did) + Projection(ExistentialProjection { item_def_id, substs, ty }) => { + let new_did = if id_mapping.contains_id(item_def_id) { + id_mapping.get_new_id(item_def_id) } else { - did + item_def_id }; Projection(ExistentialProjection { - trait_ref: ExistentialTraitRef { - def_id: new_did, - substs: substs, - }, - item_name: item_name, + item_def_id: new_did, + substs: substs, ty: ty, }) - }, AutoTrait(did) => { if id_mapping.contains_id(did) { @@ -687,7 +682,7 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, })); tcx.mk_dynamic(Binder(new_preds), region) - }, */ + }, _ => ty, } }}) diff --git a/tests/examples/infer.out b/tests/examples/infer.out index 13e3377114942..84bd4ceab5d48 100644 --- a/tests/examples/infer.out +++ b/tests/examples/infer.out @@ -1,13 +1 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Breaking changes in `Hij` - --> $REPO_PATH/tests/examples/infer.rs:41:5 - | -41 | / pub struct Hij<'a> { -42 | | pub field: &'a a::Def, -43 | | pub field2: ::std::rc::Rc, -44 | | } - | |_____^ - | - = warning: Breaking (TypeChanged { error: Traits(ExpectedFound { expected: DefId { krate: CrateNum(12), node: DefIndex(5) => infer/8cd878b::old[0]::a[0]::Abc[0] }, found: DefId { krate: CrateNum(12), node: DefIndex(12) => infer/8cd878b::new[0]::a[0]::Def[0] } }) }) - = warning: Breaking (TypeChanged { error: Traits(ExpectedFound { expected: DefId { krate: CrateNum(12), node: DefIndex(5) => infer/8cd878b::old[0]::a[0]::Abc[0] }, found: DefId { krate: CrateNum(12), node: DefIndex(12) => infer/8cd878b::new[0]::a[0]::Def[0] } }) }) - +version bump: 1.0.0 -> (Patch) -> 1.0.1 From e1223e6a935614d9f0847931af9dd577c854ebff Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 13 Jul 2017 12:37:01 +0200 Subject: [PATCH 132/553] Fixed a bug in the handling of associated types. --- src/semcheck/mapping.rs | 1 + src/semcheck/traverse.rs | 14 ++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 8c668df74599a..08b5f01a282fc 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -43,6 +43,7 @@ impl IdMapping { /// Add any trait item pair's old and new `DefId`s. pub fn add_trait_item(&mut self, old: Def, new: Def) { + self.internal_mapping.insert(old.def_id(), new.def_id()); // TODO: fugly self.trait_item_mapping.insert(old.def_id(), (old, new)); } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index a627d89169658..306e5bbcf6d9f 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -359,6 +359,7 @@ fn diff_traits(changes: &mut ChangeSet, tcx: TyCtxt, old: DefId, new: DefId) { + // TODO let _old_unsafety = tcx.trait_def(old).unsafety; let _new_unsafety = tcx.trait_def(new).unsafety; @@ -374,7 +375,6 @@ fn diff_traits(changes: &mut ChangeSet, let item = tcx.associated_item(*new_did); items.entry(item.name).or_insert((None, None)).1 = tcx.describe_def(*new_did).map(|d| (d, item)); - } for (name, item_pair) in &items { @@ -637,9 +637,15 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, TyFnDef(did, substs) => { tcx.mk_fn_def(id_mapping.get_new_id(did), substs) }, - /* TyProjection(proj) => { - tcx.mk_projection(id_mapping.get_new_id(proj.item_def_id), proj.substs) - }, */ + TyProjection(proj) => { + let new_did = if id_mapping.contains_id(proj.item_def_id) { + id_mapping.get_new_id(proj.item_def_id) + } else { + proj.item_def_id + }; + + tcx.mk_projection(new_did, proj.substs) + }, TyAnon(did, substs) => { tcx.mk_anon(id_mapping.get_new_id(did), substs) }, From e73cf21ae76fedc3f395a560bd3bfdea05c6ae9e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 13 Jul 2017 12:46:30 +0200 Subject: [PATCH 133/553] Implemented trait unsafety checks. --- src/semcheck/changes.rs | 3 +++ src/semcheck/traverse.rs | 19 ++++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 0e17a78d786a0..c4813a90b1101 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -161,6 +161,8 @@ pub enum BinaryChangeType<'tcx> { TraitItemAdded { defaulted: bool }, /// A trait's definition removed an item. TraitItemRemoved { defaulted: bool }, + /// A trait's definition changed it's unsafety. + TraitUnsafetyChanged { now_unsafe: bool }, /// A field in a struct or enum has changed it's type. TypeChanged { error: TypeError<'tcx> }, /// An unknown change is any change we don't yet explicitly handle. @@ -189,6 +191,7 @@ impl<'tcx> BinaryChangeType<'tcx> { MethodSelfChanged { now_self: false } | TraitItemAdded { defaulted: false } | TraitItemRemoved { .. } | + TraitUnsafetyChanged { .. } | Unknown => Breaking, MethodSelfChanged { now_self: true } | TraitItemAdded { defaulted: true } | diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 306e5bbcf6d9f..431ba7c170480 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -359,9 +359,18 @@ fn diff_traits(changes: &mut ChangeSet, tcx: TyCtxt, old: DefId, new: DefId) { - // TODO - let _old_unsafety = tcx.trait_def(old).unsafety; - let _new_unsafety = tcx.trait_def(new).unsafety; + use rustc::hir::Unsafety::Unsafe; + + let old_unsafety = tcx.trait_def(old).unsafety; + let new_unsafety = tcx.trait_def(new).unsafety; + + if old_unsafety != new_unsafety { + let change_type = TraitUnsafetyChanged { + now_unsafe: new_unsafety == Unsafe, + }; + + changes.add_binary(change_type, old, None); + } let mut items = BTreeMap::new(); @@ -391,13 +400,13 @@ fn diff_traits(changes: &mut ChangeSet, let change_type = TraitItemRemoved { defaulted: old_item.defaultness.has_value(), }; - changes.add_binary(change_type , old, Some(tcx.def_span(old_item.def_id))); + changes.add_binary(change_type, old, Some(tcx.def_span(old_item.def_id))); }, (None, Some((_, new_item))) => { let change_type = TraitItemAdded { defaulted: new_item.defaultness.has_value(), }; - changes.add_binary(change_type , old, Some(tcx.def_span(new_item.def_id))); + changes.add_binary(change_type, old, Some(tcx.def_span(new_item.def_id))); }, (None, None) => unreachable!(), } From 364516b66c31fba56094356a1966e16565ec4ab6 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 13 Jul 2017 12:55:56 +0200 Subject: [PATCH 134/553] Small improvements to mapping implementation. --- src/semcheck/mapping.rs | 7 +++++-- src/semcheck/traverse.rs | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 08b5f01a282fc..132aaa46e2cc0 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -43,7 +43,6 @@ impl IdMapping { /// Add any trait item pair's old and new `DefId`s. pub fn add_trait_item(&mut self, old: Def, new: Def) { - self.internal_mapping.insert(old.def_id(), new.def_id()); // TODO: fugly self.trait_item_mapping.insert(old.def_id(), (old, new)); } @@ -83,6 +82,8 @@ impl IdMapping { pub fn get_new_id(&self, old: DefId) -> DefId { if let Some(new) = self.toplevel_mapping.get(&old) { new.1.def_id() + } else if let Some(new) = self.trait_item_mapping.get(&old) { + new.1.def_id() } else { self.internal_mapping[&old] } @@ -90,7 +91,9 @@ impl IdMapping { /// Tell us whether a `DefId` is present in the mappings. pub fn contains_id(&self, old: DefId) -> bool { - self.toplevel_mapping.contains_key(&old) || self.internal_mapping.contains_key(&old) + self.toplevel_mapping.contains_key(&old) || + self.trait_item_mapping.contains_key(&old) || + self.internal_mapping.contains_key(&old) } /// Construct a queue of toplevel item pairs' `DefId`s. diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 431ba7c170480..3f2c001119003 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -132,7 +132,6 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, changes.add_binary(ItemMadePublic, o_def_id, None); } - // TODO: extend as needed. match (o.def, n.def) { // (matching) things we don't care about (for now) (Mod(_), Mod(_)) | From e852b6e9982c1c64437b027b473645d75c52942d Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 13 Jul 2017 19:22:27 +0200 Subject: [PATCH 135/553] A lot of cleanup. * renamed some things. * removed some old ideas we won't have to bother about. * improved docs. * misc cleanup. --- src/bin/cargo_semver.rs | 6 +----- src/semcheck/changes.rs | 11 +++-------- src/semcheck/mapping.rs | 14 +++++++------- src/semcheck/mismatch.rs | 25 ++++++------------------- src/semcheck/traverse.rs | 7 +++---- 5 files changed, 20 insertions(+), 43 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index ddca2da7c3748..71c0134f7a2b0 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -126,11 +126,7 @@ impl<'a> WorkInfo<'a> { /// /// Obtain the local crate and compile it, then fetch the latest version from the registry, and /// build it as well. -/// -/// TODO: -/// * possibly reduce the complexity by investigating where some of the info can be sourced from -/// in a more direct fashion -/// * add proper support to compare two arbitrary versions +// TODO: possibly reduce the complexity by finding where some info can be taken from directly fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { fn parse_arg(opt: &str) -> CargoResult<(&str, &str)> { let mut split = opt.split('-'); diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index c4813a90b1101..dab7badadaf64 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -47,12 +47,10 @@ impl<'a> Default for ChangeCategory { } } -/// A change record of a change that introduced or removed an item. +/// A change record of a newly introduced or removed item. /// /// It is important to note that the `Eq` and `Ord` instances are constucted to only -/// regard the span of the associated item export. This allows us to sort them by appearance -/// in the source, but possibly could create conflict later on. -// TODO: regard the origin of the span as well. +/// regard the span of the associated item export. pub enum UnaryChange { /// An item has been added. Addition(Export), @@ -172,7 +170,6 @@ pub enum BinaryChangeType<'tcx> { pub use self::BinaryChangeType::*; impl<'tcx> BinaryChangeType<'tcx> { - // TODO: this will need a lot of changes (it's *very* conservative rn) pub fn to_category(&self) -> ChangeCategory { match *self { ItemMadePrivate | @@ -206,9 +203,7 @@ impl<'tcx> BinaryChangeType<'tcx> { /// /// It is important to note that the `Eq` and `Ord` instances are constucted to only /// regard the *new* span of the associated item export. This allows us to sort them -/// by appearance in the *new* source, but possibly could create conflict later on. -// TODO: we should introduce an invariant that the two exports present are *always* -// tied together. +/// by appearance in the *new* source. pub struct BinaryChange<'tcx> { /// The type of the change affecting the item. changes: Vec<(BinaryChangeType<'tcx>, Option)>, diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 132aaa46e2cc0..5bf7f06c14248 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -41,12 +41,12 @@ impl IdMapping { true } - /// Add any trait item pair's old and new `DefId`s. + /// Add any trait item's old and new `DefId`s. pub fn add_trait_item(&mut self, old: Def, new: Def) { self.trait_item_mapping.insert(old.def_id(), (old, new)); } - /// Add any other item pair's old and new `DefId`s. + /// 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 {:?}!", @@ -57,7 +57,7 @@ impl IdMapping { self.internal_mapping.insert(old, new); } - /// Add any other item pair's old and new `DefId`s, together with a parent entry. + /// Add any other item's old and new `DefId`s, together with a parent entry. pub fn add_subitem(&mut self, parent: DefId, old: DefId, new: DefId) { self.add_internal_item(old, new); self.child_mapping @@ -97,22 +97,22 @@ impl IdMapping { } /// Construct a queue of toplevel item pairs' `DefId`s. - pub fn construct_queue(&self) -> VecDeque<(DefId, DefId)> { + pub fn toplevel_queue(&self) -> VecDeque<(DefId, DefId)> { self.toplevel_mapping .values() .map(|&(old, new)| (old.def_id(), new.def_id())) .collect() } - /// Iterate over the toplevel item pairs. - pub fn toplevel_values<'a>(&'a self) -> impl Iterator + 'a { + /// Iterate over the toplevel and trait item pairs. + pub fn items<'a>(&'a self) -> impl Iterator + 'a { self.toplevel_mapping .values() .chain(self.trait_item_mapping.values()) } /// Iterate over the item pairs of all children of a given item. - pub fn children_values<'a>(&'a self, parent: DefId) + pub fn children_of<'a>(&'a self, parent: DefId) -> Option + 'a> { self.child_mapping diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index d9646da2ba681..a3ec7835713e8 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -37,7 +37,7 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> Mismatch<'a, 'gcx, 'tcx> { { Mismatch { tcx: tcx, - item_queue: id_mapping.construct_queue(), + item_queue: id_mapping.toplevel_queue(), id_mapping: id_mapping, old_crate: old_crate, } @@ -119,22 +119,10 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { Some((a_def.did, b_def.did)) }, (&TyDynamic(a_obj, a_r), &TyDynamic(b_obj, b_r)) => { - // let _ = self.relate(&a_obj, &b_obj); let _ = self.relate(&a_r, &b_r); - if let (Some(a), Some(b)) = (a_obj.principal(), b_obj.principal()) { let _ = self.relate(&a, &b); - /* println!("kinda adding mapping: {:?} => {:?}", - a.skip_binder().def_id, - b.skip_binder().def_id); */ - let a_did = a.skip_binder().def_id; - let b_did = b.skip_binder().def_id; - if !self.id_mapping.contains_id(a_did) && a_did.krate == self.old_crate { - self.id_mapping.add_internal_item(a_did, b_did); - } - - // TODO: Some((a.skip_binder().def_id, b.skip_binder().def_id)) - None + Some((a.skip_binder().def_id, b.skip_binder().def_id)) } else { None } @@ -179,11 +167,10 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { _ => None, }; - if let Some(dids) = matching { - if !self.id_mapping.contains_id(dids.0) && dids.0.krate == self.old_crate { - // println!("adding mapping: {:?} => {:?}", dids.0, dids.1); - self.id_mapping.add_internal_item(dids.0, dids.1); - self.item_queue.push_back(dids); + if let Some((old_did, new_did)) = matching { + if !self.id_mapping.contains_id(old_did) && old_did.krate == self.old_crate { + self.id_mapping.add_internal_item(old_did, new_did); + self.item_queue.push_back((old_did, new_did)); } } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 3f2c001119003..670a6a72cff6f 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -43,12 +43,12 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI } // third pass - for &(old, new) in id_mapping.toplevel_values() { + for &(old, new) in id_mapping.items() { diff_bounds(&mut changes, tcx, old.def_id(), new.def_id()); } // fourth pass - for &(old, new) in id_mapping.toplevel_values() { + for &(old, new) in id_mapping.items() { diff_types(&mut changes, &id_mapping, tcx, old, new); } @@ -169,7 +169,6 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, o_def_id, n_def_id); }, - // ADTs for now (Struct(_), Struct(_)) | (Union(_), Union(_)) | (Enum(_), Enum(_)) => { @@ -532,7 +531,7 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, tcx.mk_fn_ptr(new_fn_sig)); }, Struct(_) | Enum(_) | Union(_) => { - if let Some(children) = id_mapping.children_values(old_def_id) { + if let Some(children) = id_mapping.children_of(old_def_id) { for (o_did, n_did) in children { let o_ty = tcx.type_of(o_did); let n_ty = tcx.type_of(n_did); From c23e8cabad7b7c1581edc113ceed8a2079aede84 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 13 Jul 2017 19:29:16 +0200 Subject: [PATCH 136/553] Moved some debugging logic around. --- src/bin/cargo_semver.rs | 3 +-- tests/examples.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 71c0134f7a2b0..9ef96fd4ee5de 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -25,7 +25,6 @@ use std::process::{Stdio, Command}; /// /// If no crate with the exact name is present, error out. fn exact_search(query: &str) -> CargoResult { - // TODO: maybe we can get this with less constants :) let mut registry = Registry::new("https://crates.io".to_owned(), None); registry @@ -184,7 +183,7 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { let (stable_rlib, stable_deps_output) = stable.rlib_and_dep_output(config, &name)?; if matches.opt_present("d") { - println!("--crate-type=lib --extern old={} -L{} --extern new={} -L{} tests/helper/test2.rs", + println!("--extern old={} -L{} --extern new={} -L{}", stable_rlib.display(), stable_deps_output.display(), current_rlib.display(), diff --git a/tests/examples.rs b/tests/examples.rs index 9e32e1db9d0a9..bc40b6c814369 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -107,7 +107,7 @@ export RUST_SEMVER_CRATE_VERSION=1.0.0 if [ "$1" = "-s" ]; then shift - arg_str="set args $(cargo semver "$@")" + arg_str="set args --crate-type=lib $(cargo semver "$@") tests/helper/test2.rs" standalone=1 else rustc --crate-type=lib -o liboldandnew.rlib "$1" From db6d9adcf7e8700651562ebabf12e90effe7b1cd Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 14 Jul 2017 19:37:19 +0200 Subject: [PATCH 137/553] New integration test suite. --- tests/cases/addition/new.rs | 17 +++ tests/cases/addition/old.rs | 10 ++ tests/cases/addition/stderr | 0 tests/cases/addition/stdout | 37 +++++ tests/cases/addition_path/new.rs | 13 ++ tests/cases/addition_path/old.rs | 11 ++ tests/cases/addition_path/stderr | 0 tests/cases/addition_path/stdout | 19 +++ tests/cases/enums/new.rs | 26 ++++ tests/cases/enums/old.rs | 26 ++++ tests/cases/enums/stderr | 0 tests/cases/enums/stdout | 106 +++++++++++++ tests/cases/func/new.rs | 30 ++++ tests/cases/func/old.rs | 28 ++++ tests/cases/func/stderr | 0 tests/cases/func/stdout | 77 ++++++++++ tests/cases/infer/new.rs | 20 +++ tests/cases/infer/old.rs | 20 +++ tests/cases/infer/stderr | 0 .../infer.out => cases/infer/stdout} | 0 tests/cases/kind_change/new.rs | 3 + tests/cases/kind_change/old.rs | 1 + tests/cases/kind_change/stderr | 0 tests/cases/kind_change/stdout | 17 +++ tests/cases/macros/new.rs | 14 ++ tests/cases/macros/old.rs | 8 + tests/cases/macros/stderr | 0 .../pub_use.out => cases/macros/stdout} | 0 tests/cases/pathologic_paths/new.rs | 17 +++ tests/cases/pathologic_paths/old.rs | 1 + tests/cases/pathologic_paths/stderr | 0 tests/cases/pathologic_paths/stdout | 13 ++ tests/cases/pub_use/new.rs | 7 + tests/cases/pub_use/old.rs | 5 + tests/cases/pub_use/stderr | 0 tests/cases/pub_use/stdout | 1 + tests/cases/removal/new.rs | 10 ++ tests/cases/removal/old.rs | 17 +++ tests/cases/removal/stderr | 0 tests/cases/removal/stdout | 35 +++++ tests/cases/removal_path/new.rs | 3 + tests/cases/removal_path/old.rs | 13 ++ tests/cases/removal_path/stderr | 0 tests/cases/removal_path/stdout | 21 +++ tests/cases/structs/new.rs | 28 ++++ tests/cases/structs/old.rs | 26 ++++ tests/cases/structs/stderr | 0 tests/cases/structs/stdout | 81 ++++++++++ tests/cases/traits/new.rs | 14 ++ tests/cases/traits/old.rs | 14 ++ tests/cases/traits/stderr | 0 tests/cases/traits/stdout | 62 ++++++++ tests/cases/ty_alias/new.rs | 7 + tests/cases/ty_alias/old.rs | 7 + tests/cases/ty_alias/stderr | 0 tests/cases/ty_alias/stdout | 58 +++++++ tests/debug.rs | 42 ++++++ tests/examples.rs | 142 ++++++++---------- tests/examples/addition.out | 37 ----- tests/examples/addition.rs | 32 ---- tests/examples/addition_path.out | 21 --- tests/examples/addition_path.rs | 21 --- tests/examples/enum.out | 106 ------------- tests/examples/enum.rs | 57 ------- tests/examples/fn.out | 77 ---------- tests/examples/fn.rs | 63 -------- tests/examples/infer.rs | 45 ------ tests/examples/kind_change.out | 17 --- tests/examples/kind_change.rs | 9 -- tests/examples/macro.out | 7 - tests/examples/macro.rs | 27 ---- tests/examples/pathologic_paths.out | 13 -- tests/examples/pathologic_paths.rs | 24 --- tests/examples/pub_use.rs | 17 --- tests/examples/removal.out | 35 ----- tests/examples/removal.rs | 32 ---- tests/examples/removal_path.out | 21 --- tests/examples/removal_path.rs | 21 --- tests/examples/struct.out | 81 ---------- tests/examples/struct.rs | 59 -------- tests/examples/trait.out | 62 -------- tests/examples/trait.rs | 33 ---- tests/examples/ty_alias.out | 58 ------- tests/examples/ty_alias.rs | 19 --- tests/helper/test.rs | 3 +- tests/helper/test2.rs | 2 - 86 files changed, 1026 insertions(+), 1080 deletions(-) create mode 100644 tests/cases/addition/new.rs create mode 100644 tests/cases/addition/old.rs create mode 100644 tests/cases/addition/stderr create mode 100644 tests/cases/addition/stdout create mode 100644 tests/cases/addition_path/new.rs create mode 100644 tests/cases/addition_path/old.rs create mode 100644 tests/cases/addition_path/stderr create mode 100644 tests/cases/addition_path/stdout create mode 100644 tests/cases/enums/new.rs create mode 100644 tests/cases/enums/old.rs create mode 100644 tests/cases/enums/stderr create mode 100644 tests/cases/enums/stdout create mode 100644 tests/cases/func/new.rs create mode 100644 tests/cases/func/old.rs create mode 100644 tests/cases/func/stderr create mode 100644 tests/cases/func/stdout create mode 100644 tests/cases/infer/new.rs create mode 100644 tests/cases/infer/old.rs create mode 100644 tests/cases/infer/stderr rename tests/{examples/infer.out => cases/infer/stdout} (100%) create mode 100644 tests/cases/kind_change/new.rs create mode 100644 tests/cases/kind_change/old.rs create mode 100644 tests/cases/kind_change/stderr create mode 100644 tests/cases/kind_change/stdout create mode 100644 tests/cases/macros/new.rs create mode 100644 tests/cases/macros/old.rs create mode 100644 tests/cases/macros/stderr rename tests/{examples/pub_use.out => cases/macros/stdout} (100%) create mode 100644 tests/cases/pathologic_paths/new.rs create mode 100644 tests/cases/pathologic_paths/old.rs create mode 100644 tests/cases/pathologic_paths/stderr create mode 100644 tests/cases/pathologic_paths/stdout create mode 100644 tests/cases/pub_use/new.rs create mode 100644 tests/cases/pub_use/old.rs create mode 100644 tests/cases/pub_use/stderr create mode 100644 tests/cases/pub_use/stdout create mode 100644 tests/cases/removal/new.rs create mode 100644 tests/cases/removal/old.rs create mode 100644 tests/cases/removal/stderr create mode 100644 tests/cases/removal/stdout create mode 100644 tests/cases/removal_path/new.rs create mode 100644 tests/cases/removal_path/old.rs create mode 100644 tests/cases/removal_path/stderr create mode 100644 tests/cases/removal_path/stdout create mode 100644 tests/cases/structs/new.rs create mode 100644 tests/cases/structs/old.rs create mode 100644 tests/cases/structs/stderr create mode 100644 tests/cases/structs/stdout create mode 100644 tests/cases/traits/new.rs create mode 100644 tests/cases/traits/old.rs create mode 100644 tests/cases/traits/stderr create mode 100644 tests/cases/traits/stdout create mode 100644 tests/cases/ty_alias/new.rs create mode 100644 tests/cases/ty_alias/old.rs create mode 100644 tests/cases/ty_alias/stderr create mode 100644 tests/cases/ty_alias/stdout create mode 100644 tests/debug.rs delete mode 100644 tests/examples/addition.out delete mode 100644 tests/examples/addition.rs delete mode 100644 tests/examples/addition_path.out delete mode 100644 tests/examples/addition_path.rs delete mode 100644 tests/examples/enum.out delete mode 100644 tests/examples/enum.rs delete mode 100644 tests/examples/fn.out delete mode 100644 tests/examples/fn.rs delete mode 100644 tests/examples/infer.rs delete mode 100644 tests/examples/kind_change.out delete mode 100644 tests/examples/kind_change.rs delete mode 100644 tests/examples/macro.out delete mode 100644 tests/examples/macro.rs delete mode 100644 tests/examples/pathologic_paths.out delete mode 100644 tests/examples/pathologic_paths.rs delete mode 100644 tests/examples/pub_use.rs delete mode 100644 tests/examples/removal.out delete mode 100644 tests/examples/removal.rs delete mode 100644 tests/examples/removal_path.out delete mode 100644 tests/examples/removal_path.rs delete mode 100644 tests/examples/struct.out delete mode 100644 tests/examples/struct.rs delete mode 100644 tests/examples/trait.out delete mode 100644 tests/examples/trait.rs delete mode 100644 tests/examples/ty_alias.out delete mode 100644 tests/examples/ty_alias.rs delete mode 100644 tests/helper/test2.rs diff --git a/tests/cases/addition/new.rs b/tests/cases/addition/new.rs new file mode 100644 index 0000000000000..5f472077711f4 --- /dev/null +++ b/tests/cases/addition/new.rs @@ -0,0 +1,17 @@ +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; +} diff --git a/tests/cases/addition/old.rs b/tests/cases/addition/old.rs new file mode 100644 index 0000000000000..ddc8b73f64ca1 --- /dev/null +++ b/tests/cases/addition/old.rs @@ -0,0 +1,10 @@ +#[allow(dead_code)] +struct Bcd; + +mod b { + +} + +mod c { + +} diff --git a/tests/cases/addition/stderr b/tests/cases/addition/stderr new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/cases/addition/stdout b/tests/cases/addition/stdout new file mode 100644 index 0000000000000..1f44e13ed52a2 --- /dev/null +++ b/tests/cases/addition/stdout @@ -0,0 +1,37 @@ +version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 +warning: Addition of at least one path to `Abc` (TechnicallyBreaking) + --> $REPO_PATH/tests/cases/addition/new.rs:1:1 + | +1 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + +warning: TechnicallyBreaking changes in `Bcd` + --> $REPO_PATH/tests/cases/addition/new.rs:3:1 + | +3 | pub struct Bcd; + | ^^^^^^^^^^^^^^^ + | + = note: TechnicallyBreaking (ItemMadePublic) + +warning: Addition of at least one path to `a` (TechnicallyBreaking) + --> $REPO_PATH/tests/cases/addition/new.rs:7:1 + | +7 | } + | ^ + +warning: TechnicallyBreaking changes in `b` + --> $REPO_PATH/tests/cases/addition/new.rs:10:5 + | +10 | / #[allow(dead_code)] +11 | | pub struct Cde; +12 | | } + | |_^ + | + = note: TechnicallyBreaking (ItemMadePublic) + +warning: Addition of at least one path to `Cde` (TechnicallyBreaking) + --> $REPO_PATH/tests/cases/addition/new.rs:11:5 + | +11 | pub struct Cde; + | ^^^^^^^^^^^^^^^ + diff --git a/tests/cases/addition_path/new.rs b/tests/cases/addition_path/new.rs new file mode 100644 index 0000000000000..25228c33a0140 --- /dev/null +++ b/tests/cases/addition_path/new.rs @@ -0,0 +1,13 @@ +pub mod a { + pub struct Abc; +} + +pub mod b { + pub use a::*; +} + +pub mod c { + pub use a::Abc; +} + +pub use self::a::Abc; diff --git a/tests/cases/addition_path/old.rs b/tests/cases/addition_path/old.rs new file mode 100644 index 0000000000000..dfb2d9265aa23 --- /dev/null +++ b/tests/cases/addition_path/old.rs @@ -0,0 +1,11 @@ +pub mod a { + pub struct Abc; +} + +pub mod b { + +} + +pub mod c { + +} diff --git a/tests/cases/addition_path/stderr b/tests/cases/addition_path/stderr new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/cases/addition_path/stdout b/tests/cases/addition_path/stdout new file mode 100644 index 0000000000000..e2113ef2faa0b --- /dev/null +++ b/tests/cases/addition_path/stdout @@ -0,0 +1,19 @@ +version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 +warning: Addition of at least one path to `Abc` (TechnicallyBreaking) + --> $REPO_PATH/tests/cases/addition_path/new.rs:6:13 + | +6 | pub use a::*; + | ^^^^^ + +warning: Addition of at least one path to `Abc` (TechnicallyBreaking) + --> $REPO_PATH/tests/cases/addition_path/new.rs:6:13 + | +6 | pub use a::*; + | ^^^^^ + +warning: Addition of at least one path to `Abc` (TechnicallyBreaking) + --> $REPO_PATH/tests/cases/addition_path/new.rs:6:13 + | +6 | pub use a::*; + | ^^^^^ + diff --git a/tests/cases/enums/new.rs b/tests/cases/enums/new.rs new file mode 100644 index 0000000000000..2b56e9fade29f --- /dev/null +++ b/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/tests/cases/enums/old.rs b/tests/cases/enums/old.rs new file mode 100644 index 0000000000000..da5906a57e043 --- /dev/null +++ b/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/tests/cases/enums/stderr b/tests/cases/enums/stderr new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/cases/enums/stdout b/tests/cases/enums/stdout new file mode 100644 index 0000000000000..9d435d5f44b2c --- /dev/null +++ b/tests/cases/enums/stdout @@ -0,0 +1,106 @@ +version bump: 1.0.0 -> (Breaking) -> 2.0.0 +warning: Breaking changes in `Abc` + --> $REPO_PATH/tests/cases/enums/new.rs:1:1 + | +1 | / pub enum Abc { +2 | | Abc, +3 | | } + | |_^ + | +warning: Breaking (VariantAdded) + --> $REPO_PATH/tests/cases/enums/new.rs:2:5 + | +2 | Abc, + | ^^^ + +warning: Breaking changes in `Bcd` + --> $REPO_PATH/tests/cases/enums/new.rs:5:1 + | +5 | / pub enum Bcd { +6 | | +7 | | } + | |_^ + | +warning: Breaking (VariantRemoved) + --> $REPO_PATH/tests/cases/enums/old.rs:6:5 + | +6 | Abc, + | ^^^ + +warning: Breaking changes in `Cde` + --> $REPO_PATH/tests/cases/enums/new.rs:9:1 + | +9 | / pub enum Cde { +10 | | Abc, +11 | | Bcd, +12 | | } + | |_^ + | +warning: Breaking (VariantAdded) + --> $REPO_PATH/tests/cases/enums/new.rs:11:5 + | +11 | Bcd, + | ^^^ + +warning: Breaking changes in `Def` + --> $REPO_PATH/tests/cases/enums/new.rs:14:1 + | +14 | / pub enum Def { +15 | | Abc, +16 | | } + | |_^ + | +warning: Breaking (VariantRemoved) + --> $REPO_PATH/tests/cases/enums/old.rs:15:5 + | +15 | Bcd, + | ^^^ + +warning: Breaking changes in `Efg` + --> $REPO_PATH/tests/cases/enums/new.rs:18:1 + | +18 | / pub enum Efg { +19 | | Abc(u8), +20 | | Bcd, +21 | | Cde { f: u8 }, +... | +25 | | Ghi { g: u8 }, +26 | | } + | |_^ + | +warning: Breaking (VariantStyleChanged { now_struct: false, total_private: true }) + --> $REPO_PATH/tests/cases/enums/new.rs:19:5 + | +19 | Abc(u8), + | ^^^^^^^ +warning: Breaking (VariantStyleChanged { now_struct: false, total_private: true }) + --> $REPO_PATH/tests/cases/enums/new.rs:20:5 + | +20 | Bcd, + | ^^^ +warning: Breaking (VariantStyleChanged { now_struct: true, total_private: true }) + --> $REPO_PATH/tests/cases/enums/new.rs:21:5 + | +21 | Cde { f: u8 }, + | ^^^^^^^^^^^^^ +warning: Breaking (VariantStyleChanged { now_struct: false, total_private: true }) + --> $REPO_PATH/tests/cases/enums/new.rs:22:5 + | +22 | Def, + | ^^^ +warning: Breaking (VariantStyleChanged { now_struct: true, total_private: true }) + --> $REPO_PATH/tests/cases/enums/new.rs:23:5 + | +23 | Efg { f: u8 }, + | ^^^^^^^^^^^^^ +warning: Breaking (VariantFieldRemoved { public: false, total_public: false }) + --> $REPO_PATH/tests/cases/enums/old.rs:25:11 + | +25 | Ghi { f: u8 }, + | ^^^^^ +warning: Breaking (VariantFieldAdded { public: false, total_public: false }) + --> $REPO_PATH/tests/cases/enums/new.rs:25:11 + | +25 | Ghi { g: u8 }, + | ^^^^^ + diff --git a/tests/cases/func/new.rs b/tests/cases/func/new.rs new file mode 100644 index 0000000000000..9239b474a6d8f --- /dev/null +++ b/tests/cases/func/new.rs @@ -0,0 +1,30 @@ +#![feature(const_fn)] +pub fn abc() {} + +pub fn bcd(_: u8) {} + +pub fn cde() -> u16 { + 0xcde +} + +pub fn def() {} + +pub fn efg(a: A, _: A) -> A { + a +} + +pub fn fgh(a: u8, _: u16) -> u8 { + a +} + +pub fn ghi(a: u8, _: u8) -> u16 { + a as u16 +} + +pub const fn hij() -> u8 { + 0 +} + +pub fn ijk() -> u8 { + 0 +} diff --git a/tests/cases/func/old.rs b/tests/cases/func/old.rs new file mode 100644 index 0000000000000..a26077476b075 --- /dev/null +++ b/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/tests/cases/func/stderr b/tests/cases/func/stderr new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/cases/func/stdout b/tests/cases/func/stdout new file mode 100644 index 0000000000000..360390579ae66 --- /dev/null +++ b/tests/cases/func/stdout @@ -0,0 +1,77 @@ +version bump: 1.0.0 -> (Breaking) -> 2.0.0 +warning: Breaking changes in `bcd` + --> $REPO_PATH/tests/cases/func/new.rs:4:1 + | +4 | pub fn bcd(_: u8) {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (TypeChanged { error: ArgCount }) + +warning: Breaking changes in `cde` + --> $REPO_PATH/tests/cases/func/new.rs:6:1 + | +6 | / pub fn cde() -> u16 { +7 | | 0xcde +8 | | } + | |_^ + | + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: (), found: u16 }) }) + +warning: Breaking changes in `def` + --> $REPO_PATH/tests/cases/func/new.rs:10:1 + | +10 | pub fn def() {} + | ^^^^^^^^^^^^^^^ + | + = warning: Breaking (TypeChanged { error: ArgCount }) + +warning: NonBreaking changes in `efg` + --> $REPO_PATH/tests/cases/func/new.rs:12:1 + | +12 | / pub fn efg(a: A, _: A) -> A { +13 | | a +14 | | } + | |_^ + | + = note: NonBreaking (TypeParameterAdded { defaulted: true }) + +warning: Breaking changes in `fgh` + --> $REPO_PATH/tests/cases/func/new.rs:16:1 + | +16 | / pub fn fgh(a: u8, _: u16) -> u8 { +17 | | a +18 | | } + | |_^ + | + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) + +warning: Breaking changes in `ghi` + --> $REPO_PATH/tests/cases/func/new.rs:20:1 + | +20 | / pub fn ghi(a: u8, _: u8) -> u16 { +21 | | a as u16 +22 | | } + | |_^ + | + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) + +warning: NonBreaking changes in `hij` + --> $REPO_PATH/tests/cases/func/new.rs:24:1 + | +24 | / pub const fn hij() -> u8 { +25 | | 0 +26 | | } + | |_^ + | + = note: NonBreaking (FnConstChanged { now_const: true }) + +warning: Breaking changes in `ijk` + --> $REPO_PATH/tests/cases/func/new.rs:28:1 + | +28 | / pub fn ijk() -> u8 { +29 | | 0 +30 | | } + | |_^ + | + = warning: Breaking (FnConstChanged { now_const: false }) + diff --git a/tests/cases/infer/new.rs b/tests/cases/infer/new.rs new file mode 100644 index 0000000000000..2f18b8e0137e3 --- /dev/null +++ b/tests/cases/infer/new.rs @@ -0,0 +1,20 @@ +mod a { + pub trait Def { + + } + + pub struct Opq; +} + +pub fn a(a: A) -> A { + a +} + +pub fn b() -> a::Opq { + a::Opq +} + +pub struct Hij<'a> { + pub field: &'a a::Def, + pub field2: ::std::rc::Rc, +} diff --git a/tests/cases/infer/old.rs b/tests/cases/infer/old.rs new file mode 100644 index 0000000000000..9f14c969f7132 --- /dev/null +++ b/tests/cases/infer/old.rs @@ -0,0 +1,20 @@ +mod a { + pub trait Abc { + + } + + pub struct Klm; +} + +pub fn a(a: A) -> A { + a +} + +pub fn b() -> a::Klm { + a::Klm +} + +pub struct Hij<'a> { + pub field: &'a a::Abc, + pub field2: ::std::rc::Rc, +} diff --git a/tests/cases/infer/stderr b/tests/cases/infer/stderr new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/examples/infer.out b/tests/cases/infer/stdout similarity index 100% rename from tests/examples/infer.out rename to tests/cases/infer/stdout diff --git a/tests/cases/kind_change/new.rs b/tests/cases/kind_change/new.rs new file mode 100644 index 0000000000000..8f2ac73a32a86 --- /dev/null +++ b/tests/cases/kind_change/new.rs @@ -0,0 +1,3 @@ +pub enum Abc { + +} diff --git a/tests/cases/kind_change/old.rs b/tests/cases/kind_change/old.rs new file mode 100644 index 0000000000000..c7b09689bf4ef --- /dev/null +++ b/tests/cases/kind_change/old.rs @@ -0,0 +1 @@ +pub struct Abc; diff --git a/tests/cases/kind_change/stderr b/tests/cases/kind_change/stderr new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/cases/kind_change/stdout b/tests/cases/kind_change/stdout new file mode 100644 index 0000000000000..50e8c8d93ecea --- /dev/null +++ b/tests/cases/kind_change/stdout @@ -0,0 +1,17 @@ +version bump: 1.0.0 -> (Breaking) -> 2.0.0 +warning: Removal of at least one path to `Abc` (Breaking) + --> $REPO_PATH/tests/cases/kind_change/old.rs:1:1 + | +1 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + +warning: Breaking changes in `Abc` + --> $REPO_PATH/tests/cases/kind_change/new.rs:1:1 + | +1 | / pub enum Abc { +2 | | +3 | | } + | |_^ + | + = warning: Breaking (KindDifference) + diff --git a/tests/cases/macros/new.rs b/tests/cases/macros/new.rs new file mode 100644 index 0000000000000..0526103d067f0 --- /dev/null +++ b/tests/cases/macros/new.rs @@ -0,0 +1,14 @@ +#![feature(decl_macro, use_extern_macros)] +pub struct Item; + +#[macro_export] +macro_rules! bar { + () => { + Item + } +} + +#[allow(dead_code)] +fn abc() -> Item { + bar!() +} diff --git a/tests/cases/macros/old.rs b/tests/cases/macros/old.rs new file mode 100644 index 0000000000000..2015cbff0c62c --- /dev/null +++ b/tests/cases/macros/old.rs @@ -0,0 +1,8 @@ +#![feature(decl_macro, use_extern_macros)] +pub struct Item; + +pub macro bar() { Item } + +fn abc() -> Item { + bar!() +} diff --git a/tests/cases/macros/stderr b/tests/cases/macros/stderr new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/examples/pub_use.out b/tests/cases/macros/stdout similarity index 100% rename from tests/examples/pub_use.out rename to tests/cases/macros/stdout diff --git a/tests/cases/pathologic_paths/new.rs b/tests/cases/pathologic_paths/new.rs new file mode 100644 index 0000000000000..bd4c1d7f02959 --- /dev/null +++ b/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/tests/cases/pathologic_paths/old.rs b/tests/cases/pathologic_paths/old.rs new file mode 100644 index 0000000000000..8b137891791fe --- /dev/null +++ b/tests/cases/pathologic_paths/old.rs @@ -0,0 +1 @@ + diff --git a/tests/cases/pathologic_paths/stderr b/tests/cases/pathologic_paths/stderr new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/cases/pathologic_paths/stdout b/tests/cases/pathologic_paths/stdout new file mode 100644 index 0000000000000..0c6f2f7e641ab --- /dev/null +++ b/tests/cases/pathologic_paths/stdout @@ -0,0 +1,13 @@ +version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 +warning: Addition of at least one path to `a` (TechnicallyBreaking) + --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:5:21 + | +5 | pub mod a { blow!($($rest)*); } + | ^^^^^^^^^^^^^^^^^^^ + +warning: Addition of at least one path to `b` (TechnicallyBreaking) + --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:6:21 + | +6 | pub mod b { pub use super::a::*; } + | ^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/cases/pub_use/new.rs b/tests/cases/pub_use/new.rs new file mode 100644 index 0000000000000..b892cbe0ef453 --- /dev/null +++ b/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/tests/cases/pub_use/old.rs b/tests/cases/pub_use/old.rs new file mode 100644 index 0000000000000..0ef477c4a4ab1 --- /dev/null +++ b/tests/cases/pub_use/old.rs @@ -0,0 +1,5 @@ +pub mod a { + pub struct Abc; +} + +pub use a as b; diff --git a/tests/cases/pub_use/stderr b/tests/cases/pub_use/stderr new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/cases/pub_use/stdout b/tests/cases/pub_use/stdout new file mode 100644 index 0000000000000..84bd4ceab5d48 --- /dev/null +++ b/tests/cases/pub_use/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (Patch) -> 1.0.1 diff --git a/tests/cases/removal/new.rs b/tests/cases/removal/new.rs new file mode 100644 index 0000000000000..ddc8b73f64ca1 --- /dev/null +++ b/tests/cases/removal/new.rs @@ -0,0 +1,10 @@ +#[allow(dead_code)] +struct Bcd; + +mod b { + +} + +mod c { + +} diff --git a/tests/cases/removal/old.rs b/tests/cases/removal/old.rs new file mode 100644 index 0000000000000..5f472077711f4 --- /dev/null +++ b/tests/cases/removal/old.rs @@ -0,0 +1,17 @@ +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; +} diff --git a/tests/cases/removal/stderr b/tests/cases/removal/stderr new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/cases/removal/stdout b/tests/cases/removal/stdout new file mode 100644 index 0000000000000..5bc6ac37a19ab --- /dev/null +++ b/tests/cases/removal/stdout @@ -0,0 +1,35 @@ +version bump: 1.0.0 -> (Breaking) -> 2.0.0 +warning: Removal of at least one path to `Abc` (Breaking) + --> $REPO_PATH/tests/cases/removal/old.rs:1:1 + | +1 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + +warning: Removal of at least one path to `a` (Breaking) + --> $REPO_PATH/tests/cases/removal/old.rs:7:1 + | +7 | } + | ^ + +warning: Removal of at least one path to `Cde` (Breaking) + --> $REPO_PATH/tests/cases/removal/old.rs:11:5 + | +11 | pub struct Cde; + | ^^^^^^^^^^^^^^^ + +warning: Breaking changes in `Bcd` + --> $REPO_PATH/tests/cases/removal/new.rs:2:1 + | +2 | struct Bcd; + | ^^^^^^^^^^^ + | + = warning: Breaking (ItemMadePrivate) + +warning: Breaking changes in `b` + --> $REPO_PATH/tests/cases/removal/new.rs:6:1 + | +6 | } + | ^ + | + = warning: Breaking (ItemMadePrivate) + diff --git a/tests/cases/removal_path/new.rs b/tests/cases/removal_path/new.rs new file mode 100644 index 0000000000000..876fd66a58174 --- /dev/null +++ b/tests/cases/removal_path/new.rs @@ -0,0 +1,3 @@ +pub mod a { + pub struct Abc; +} diff --git a/tests/cases/removal_path/old.rs b/tests/cases/removal_path/old.rs new file mode 100644 index 0000000000000..25228c33a0140 --- /dev/null +++ b/tests/cases/removal_path/old.rs @@ -0,0 +1,13 @@ +pub mod a { + pub struct Abc; +} + +pub mod b { + pub use a::*; +} + +pub mod c { + pub use a::Abc; +} + +pub use self::a::Abc; diff --git a/tests/cases/removal_path/stderr b/tests/cases/removal_path/stderr new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/cases/removal_path/stdout b/tests/cases/removal_path/stdout new file mode 100644 index 0000000000000..13486d031aa4f --- /dev/null +++ b/tests/cases/removal_path/stdout @@ -0,0 +1,21 @@ +version bump: 1.0.0 -> (Breaking) -> 2.0.0 +warning: Removal of at least one path to `b` (Breaking) + --> $REPO_PATH/tests/cases/removal_path/old.rs:6:5 + | +6 | / pub use a::*; +7 | | } + | |_^ + +warning: Removal of at least one path to `c` (Breaking) + --> $REPO_PATH/tests/cases/removal_path/old.rs:10:5 + | +10 | / pub use a::Abc; +11 | | } + | |_^ + +warning: Removal of at least one path to `Abc` (Breaking) + --> $REPO_PATH/tests/cases/removal_path/old.rs:13:9 + | +13 | pub use self::a::Abc; + | ^^^^^^^^^^^^ + diff --git a/tests/cases/structs/new.rs b/tests/cases/structs/new.rs new file mode 100644 index 0000000000000..ff1cae4de375c --- /dev/null +++ b/tests/cases/structs/new.rs @@ -0,0 +1,28 @@ +#![allow(dead_code)] +pub struct Abc { + field: B, +} + +pub struct Def { + pub field: A, +} + +pub struct Def2 { + pub field: A, +} + +pub struct Efg { + pub field: u16, +} + +pub struct Fgh { + pub field: u8, +} + +pub struct Ghi { + field: u8, +} + +pub struct Hij { + field: u8, +} diff --git a/tests/cases/structs/old.rs b/tests/cases/structs/old.rs new file mode 100644 index 0000000000000..e06b3a578b3d9 --- /dev/null +++ b/tests/cases/structs/old.rs @@ -0,0 +1,26 @@ +#![allow(dead_code)] +pub struct Abc { + field: A, +} + +pub struct Def { + field: u8, +} + +pub struct Def2 { + pub field: u8, +} + +pub struct Efg { + pub field: u8, +} + +pub struct Fgh { + field: u8, +} + +pub struct Ghi { + pub field: u8, +} + +pub struct Hij(u8); diff --git a/tests/cases/structs/stderr b/tests/cases/structs/stderr new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/cases/structs/stdout b/tests/cases/structs/stdout new file mode 100644 index 0000000000000..9c2f07779443a --- /dev/null +++ b/tests/cases/structs/stdout @@ -0,0 +1,81 @@ +version bump: 1.0.0 -> (Breaking) -> 2.0.0 +warning: TechnicallyBreaking changes in `Def` + --> $REPO_PATH/tests/cases/structs/new.rs:6:1 + | +6 | / pub struct Def { +7 | | pub field: A, +8 | | } + | |_^ + | + = note: NonBreaking (TypeParameterAdded { defaulted: true }) +note: TechnicallyBreaking (ItemMadePublic) + --> $REPO_PATH/tests/cases/structs/new.rs:7:5 + | +7 | pub field: A, + | ^^^^^^^^^^^^ + +warning: Breaking changes in `Def2` + --> $REPO_PATH/tests/cases/structs/new.rs:10:1 + | +10 | / pub struct Def2 { +11 | | pub field: A, +12 | | } + | |_^ + | + = note: NonBreaking (TypeParameterAdded { defaulted: true }) + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) + +warning: Breaking changes in `Efg` + --> $REPO_PATH/tests/cases/structs/new.rs:14:1 + | +14 | / pub struct Efg { +15 | | pub field: u16, +16 | | } + | |_^ + | + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) + +warning: TechnicallyBreaking changes in `Fgh` + --> $REPO_PATH/tests/cases/structs/new.rs:18:1 + | +18 | / pub struct Fgh { +19 | | pub field: u8, +20 | | } + | |_^ + | +note: TechnicallyBreaking (ItemMadePublic) + --> $REPO_PATH/tests/cases/structs/new.rs:19:5 + | +19 | pub field: u8, + | ^^^^^^^^^^^^^ + +warning: Breaking changes in `Ghi` + --> $REPO_PATH/tests/cases/structs/new.rs:22:1 + | +22 | / pub struct Ghi { +23 | | field: u8, +24 | | } + | |_^ + | +warning: Breaking (ItemMadePrivate) + --> $REPO_PATH/tests/cases/structs/new.rs:23:5 + | +23 | field: u8, + | ^^^^^^^^^ + +warning: Breaking changes in `Hij` + --> $REPO_PATH/tests/cases/structs/new.rs:26:1 + | +26 | / pub struct Hij { +27 | | field: u8, +28 | | } + | |_^ + | +warning: Breaking (VariantStyleChanged { now_struct: true, total_private: true }) + --> $REPO_PATH/tests/cases/structs/new.rs:26:1 + | +26 | / pub struct Hij { +27 | | field: u8, +28 | | } + | |_^ + diff --git a/tests/cases/traits/new.rs b/tests/cases/traits/new.rs new file mode 100644 index 0000000000000..682b4501c1d3b --- /dev/null +++ b/tests/cases/traits/new.rs @@ -0,0 +1,14 @@ +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; +} diff --git a/tests/cases/traits/old.rs b/tests/cases/traits/old.rs new file mode 100644 index 0000000000000..682397e8d910a --- /dev/null +++ b/tests/cases/traits/old.rs @@ -0,0 +1,14 @@ +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; +} diff --git a/tests/cases/traits/stderr b/tests/cases/traits/stderr new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/cases/traits/stdout b/tests/cases/traits/stdout new file mode 100644 index 0000000000000..3edd8666ad869 --- /dev/null +++ b/tests/cases/traits/stdout @@ -0,0 +1,62 @@ +version bump: 1.0.0 -> (Breaking) -> 2.0.0 +warning: Breaking changes in `Abc` + --> $REPO_PATH/tests/cases/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: Breaking (TraitItemRemoved { defaulted: false }) + --> $REPO_PATH/tests/cases/traits/old.rs:4:5 + | +4 | fn test2(&self) -> u8; + | ^^^^^^^^^^^^^^^^^^^^^^ +warning: Breaking (TraitItemRemoved { defaulted: true }) + --> $REPO_PATH/tests/cases/traits/old.rs:8:5 + | +8 | / fn test5() -> u8 { +9 | | 0 +10 | | } + | |_____^ +warning: Breaking (TraitItemAdded { defaulted: false }) + --> $REPO_PATH/tests/cases/traits/new.rs:4:5 + | +4 | fn test3(&self) -> u8; + | ^^^^^^^^^^^^^^^^^^^^^^ +note: TechnicallyBreaking (TraitItemAdded { defaulted: true }) + --> $REPO_PATH/tests/cases/traits/new.rs:8:5 + | +8 | / fn test6() -> u8 { +9 | | 0 +10 | | } + | |_____^ + +warning: Breaking changes in `test7` + --> $REPO_PATH/tests/cases/traits/new.rs:11:5 + | +11 | fn test7() -> u16; + | ^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) + +warning: Breaking changes in `test8` + --> $REPO_PATH/tests/cases/traits/new.rs:12:5 + | +12 | fn test8(_: &Self) -> u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (MethodSelfChanged { now_self: false }) + +warning: TechnicallyBreaking changes in `test9` + --> $REPO_PATH/tests/cases/traits/new.rs:13:5 + | +13 | fn test9(&self) -> u8; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: TechnicallyBreaking (MethodSelfChanged { now_self: true }) + diff --git a/tests/cases/ty_alias/new.rs b/tests/cases/ty_alias/new.rs new file mode 100644 index 0000000000000..cf912a36fa4ff --- /dev/null +++ b/tests/cases/ty_alias/new.rs @@ -0,0 +1,7 @@ +pub type A = u16; +pub type B<'a, 'b : 'a, T> = (&'a T, &'b T); +pub type C = T; +pub type D<'a, T, U=Box> = (&'a T, U); +pub type E<'a, T, U> = (&'a T, U); +pub type F<'a> = &'a u8; +pub type G<'a> = (&'a u8); diff --git a/tests/cases/ty_alias/old.rs b/tests/cases/ty_alias/old.rs new file mode 100644 index 0000000000000..833da24169297 --- /dev/null +++ b/tests/cases/ty_alias/old.rs @@ -0,0 +1,7 @@ +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/tests/cases/ty_alias/stderr b/tests/cases/ty_alias/stderr new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/cases/ty_alias/stdout b/tests/cases/ty_alias/stdout new file mode 100644 index 0000000000000..0d57e6102f1bb --- /dev/null +++ b/tests/cases/ty_alias/stdout @@ -0,0 +1,58 @@ +version bump: 1.0.0 -> (Breaking) -> 2.0.0 +warning: Breaking changes in `A` + --> $REPO_PATH/tests/cases/ty_alias/new.rs:1:1 + | +1 | pub type A = u16; + | ^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) + +warning: Breaking changes in `B` + --> $REPO_PATH/tests/cases/ty_alias/new.rs:2:1 + | +2 | pub type B<'a, 'b : 'a, T> = (&'a T, &'b T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (RegionParameterAdded) + +warning: Breaking changes in `C` + --> $REPO_PATH/tests/cases/ty_alias/new.rs:3:1 + | +3 | pub type C = T; + | ^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (RegionParameterRemoved) + +warning: Breaking changes in `D` + --> $REPO_PATH/tests/cases/ty_alias/new.rs:4:1 + | +4 | pub type D<'a, T, U=Box> = (&'a T, U); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: NonBreaking (TypeParameterAdded { defaulted: true }) + = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: &'a T, found: (&'a T, std::boxed::Box) }) }) + +warning: Breaking changes in `E` + --> $REPO_PATH/tests/cases/ty_alias/new.rs:5:1 + | +5 | pub type E<'a, T, U> = (&'a T, U); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (TypeParameterAdded { defaulted: false }) + +warning: Breaking changes in `F` + --> $REPO_PATH/tests/cases/ty_alias/new.rs:6:1 + | +6 | pub type F<'a> = &'a u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (TypeParameterRemoved { defaulted: true }) + +warning: Breaking changes in `G` + --> $REPO_PATH/tests/cases/ty_alias/new.rs:7:1 + | +7 | pub type G<'a> = (&'a u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: Breaking (TypeParameterRemoved { defaulted: false }) + diff --git a/tests/debug.rs b/tests/debug.rs new file mode 100644 index 0000000000000..5ff84fcecbd01 --- /dev/null +++ b/tests/debug.rs @@ -0,0 +1,42 @@ +use std::env; +use std::fs::File; +use std::io::Write; +use std::os::unix::fs::PermissionsExt; +use std::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"); + + 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#"#!/bin/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 "$@") tests/helper/test.rs" +else + rustc --crate-type=lib -o libold.rlib "$1/old.rs" + rustc --crate-type=lib -o libnew.rlib "$1/new.rs" + arg_str="set args --crate-type=lib --extern old=libold.rlib --extern new=libnew.rlib tests/helper/test.rs" +fi + +export RUST_LOG=debug + +src_str="set substitute-path /checkout $(rustc --print sysroot)/lib/rustlib/src/rust" + +rust-gdb ./target/debug/rust-semverver -iex "$arg_str" -iex "$src_str" + +rm lib*.rlib +"#, path); + } +} diff --git a/tests/examples.rs b/tests/examples.rs index bc40b6c814369..1e230e74f3f52 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -1,45 +1,51 @@ use std::env; use std::fs::File; -use std::io::Write; -use std::os::unix::fs::PermissionsExt; use std::os::unix::io::{AsRawFd, FromRawFd}; use std::path::Path; use std::process::{Command, Stdio}; -#[test] -fn examples() { - let mut success = true; +macro_rules! test { + ($name:ident, $path:expr) => { + #[test] + fn $name() { + let mut success = true; - let current_dir = env::current_dir().expect("could not determine current dir"); - let subst = format!("s#{}#$REPO_PATH#g", current_dir.to_str().unwrap()); + let current_dir = env::current_dir().expect("could not determine current dir"); + let subst = format!("s#{}#$REPO_PATH#g", current_dir.to_str().unwrap()); + let path = Path::new($path); - for file in std::fs::read_dir("tests/examples") - .expect("could not read dir") - .map(|f| f.expect("could not get file info").path()) { - if file.extension().map_or(false, |e| e == "rs") { - let out_file = file.with_extension("out"); - let output = File::create(&out_file).expect("could not create file"); - let fd = output.as_raw_fd(); - let err = unsafe { Stdio::from_raw_fd(fd) }; - let out = unsafe { Stdio::from_raw_fd(fd) }; + let out_file = path.join("stdout"); + let stdout = File::create(&out_file).expect("could not create `stdout` file"); + let err_file = path.join("stderr"); + let stderr = File::create(&err_file).expect("could not create `stderr` file"); - let compile_success = Command::new("rustc") - .args(&["--crate-type=lib", "-o", "liboldandnew.rlib"]) - .arg(file) + let old_rlib = path.join("libold.rlib"); + let new_rlib = path.join("libnew.rlib"); + + success &= Command::new("rustc") + .args(&["--crate-type=lib", "-o", old_rlib.to_str().unwrap()]) + .arg(path.join("old.rs")) .env("RUST_BACKTRACE", "full") .stdin(Stdio::null()) .status() .expect("could not run rustc") .success(); - success &= compile_success; + success &= Command::new("rustc") + .args(&["--crate-type=lib", "-o", new_rlib.to_str().unwrap()]) + .arg(path.join("new.rs")) + .env("RUST_BACKTRACE", "full") + .stdin(Stdio::null()) + .status() + .expect("could not run rustc") + .success(); - if compile_success { + if success { let mut sed_child = Command::new("sed") .arg(&subst) .stdin(Stdio::piped()) - .stdout(out) - .stderr(err) + .stdout(stdout) + .stderr(stderr) .spawn() .expect("could not run sed"); @@ -50,82 +56,52 @@ fn examples() { panic!("could not pipe to sed"); }; - let mut child = Command::new("./target/debug/rust-semverver") + success &= Command::new("./target/debug/rust-semverver") .args(&["--crate-type=lib", - "--extern", - "oldandnew=liboldandnew.rlib", - "-"]) - .env("RUST_SEMVERVER_TEST", "1") + "--extern", &format!("old={}", old_rlib.to_str().unwrap()), + "--extern", &format!("new={}", new_rlib.to_str().unwrap()), + "tests/helper/test.rs"]) .env("RUST_LOG", "debug") .env("RUST_BACKTRACE", "full") .env("RUST_SEMVER_CRATE_VERSION", "1.0.0") .stdin(Stdio::piped()) .stdout(out_pipe) .stderr(err_pipe) - .spawn() - .expect("could not run rust-semverver"); - - if let Some(ref mut stdin) = child.stdin { - stdin - .write_fmt(format_args!("extern crate oldandnew;")) - .expect("could not pipe to rust-semverver"); - } else { - panic!("could not pipe to rustc"); - } + .status() + .expect("could not run rust-semverver") + .success(); - success &= child.wait().expect("could not wait for child").success(); success &= sed_child.wait().expect("could not wait for sed child").success(); success &= Command::new("git") - .args(&["diff", "--exit-code", out_file.to_str().unwrap()]) + .args(&["diff", "--quiet", + out_file.to_str().unwrap(), err_file.to_str().unwrap()]) .status() .expect("could not run git diff") .success(); } - } - } - - Command::new("rm") - .arg("liboldandnew.rlib") - .status() - .expect("could not run rm"); - - 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"); - - 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#"#!/bin/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 "$@") tests/helper/test2.rs" - standalone=1 -else - rustc --crate-type=lib -o liboldandnew.rlib "$1" - export RUST_SEMVERVER_TEST=1 - arg_str="set args --crate-type=lib --extern oldandnew=liboldandnew.rlib tests/helper/test.rs" - standalone=0 -fi -export RUST_LOG=debug - -src_str="set substitute-path /checkout $(rustc --print sysroot)/lib/rustlib/src/rust" - -rust-gdb ./target/debug/rust-semverver -iex "$arg_str" -iex "$src_str" + Command::new("rm") + .args(&[old_rlib.to_str().unwrap(), new_rlib.to_str().unwrap()]) + .status() + .expect("could not run rm"); -if [ $standalone = 0 ]; then - rm liboldandnew.rlib -fi"#, path); + assert!(success, "an error occured"); + } } - - assert!(success, "an error occured"); } + +test!(addition, "tests/cases/addition"); +test!(addition_path, "tests/cases/addition_path"); +test!(enums, "tests/cases/enums"); +test!(func, "tests/cases/func"); +test!(infer, "tests/cases/infer"); +test!(kind_change, "tests/cases/kind_change"); +test!(macros, "tests/cases/macros"); +test!(pathologic_paths, "tests/cases/pathologic_paths"); +test!(pub_use, "tests/cases/pub_use"); +test!(removal, "tests/cases/removal"); +test!(removal_path, "tests/cases/removal_path"); +test!(structs, "tests/cases/structs"); +test!(traits, "tests/cases/traits"); +test!(ty_alias, "tests/cases/ty_alias"); diff --git a/tests/examples/addition.out b/tests/examples/addition.out deleted file mode 100644 index a15f9f1e4212a..0000000000000 --- a/tests/examples/addition.out +++ /dev/null @@ -1,37 +0,0 @@ -version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 -warning: Addition of at least one path to `Abc` (TechnicallyBreaking) - --> $REPO_PATH/tests/examples/addition.rs:15:5 - | -15 | pub struct Abc; - | ^^^^^^^^^^^^^^^ - -warning: TechnicallyBreaking changes in `Bcd` - --> $REPO_PATH/tests/examples/addition.rs:17:5 - | -17 | pub struct Bcd; - | ^^^^^^^^^^^^^^^ - | - = note: TechnicallyBreaking (ItemMadePublic) - -warning: Addition of at least one path to `a` (TechnicallyBreaking) - --> $REPO_PATH/tests/examples/addition.rs:21:5 - | -21 | } - | ^ - -warning: TechnicallyBreaking changes in `b` - --> $REPO_PATH/tests/examples/addition.rs:24:9 - | -24 | / #[allow(dead_code)] -25 | | pub struct Cde; -26 | | } - | |_____^ - | - = note: TechnicallyBreaking (ItemMadePublic) - -warning: Addition of at least one path to `Cde` (TechnicallyBreaking) - --> $REPO_PATH/tests/examples/addition.rs:25:9 - | -25 | pub struct Cde; - | ^^^^^^^^^^^^^^^ - diff --git a/tests/examples/addition.rs b/tests/examples/addition.rs deleted file mode 100644 index b0deed0ce1ea8..0000000000000 --- a/tests/examples/addition.rs +++ /dev/null @@ -1,32 +0,0 @@ -pub mod old { - #[allow(dead_code)] - struct Bcd; - - mod b { - - } - - mod c { - - } -} - -pub mod new { - 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; - } -} diff --git a/tests/examples/addition_path.out b/tests/examples/addition_path.out deleted file mode 100644 index 0c5b799b1b71f..0000000000000 --- a/tests/examples/addition_path.out +++ /dev/null @@ -1,21 +0,0 @@ -version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 -warning: Addition of at least one path to `b` (TechnicallyBreaking) - --> $REPO_PATH/tests/examples/addition_path.rs:13:9 - | -13 | / pub use new::a::*; -14 | | } - | |_____^ - -warning: Addition of at least one path to `c` (TechnicallyBreaking) - --> $REPO_PATH/tests/examples/addition_path.rs:17:9 - | -17 | / pub use new::a::Abc; -18 | | } - | |_____^ - -warning: Addition of at least one path to `Abc` (TechnicallyBreaking) - --> $REPO_PATH/tests/examples/addition_path.rs:20:13 - | -20 | pub use self::a::Abc; - | ^^^^^^^^^^^^ - diff --git a/tests/examples/addition_path.rs b/tests/examples/addition_path.rs deleted file mode 100644 index 875092736b679..0000000000000 --- a/tests/examples/addition_path.rs +++ /dev/null @@ -1,21 +0,0 @@ -pub mod old { - pub mod a { - pub struct Abc; - } -} - -pub mod new { - pub mod a { - pub struct Abc; - } - - pub mod b { - pub use new::a::*; - } - - pub mod c { - pub use new::a::Abc; - } - - pub use self::a::Abc; -} diff --git a/tests/examples/enum.out b/tests/examples/enum.out deleted file mode 100644 index bc35ea5c5fb54..0000000000000 --- a/tests/examples/enum.out +++ /dev/null @@ -1,106 +0,0 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Breaking changes in `Abc` - --> $REPO_PATH/tests/examples/enum.rs:31:5 - | -31 | / pub enum Abc { -32 | | Abc, -33 | | } - | |_____^ - | -warning: Breaking (VariantAdded) - --> $REPO_PATH/tests/examples/enum.rs:32:9 - | -32 | Abc, - | ^^^ - -warning: Breaking changes in `Bcd` - --> $REPO_PATH/tests/examples/enum.rs:35:5 - | -35 | / pub enum Bcd { -36 | | -37 | | } - | |_____^ - | -warning: Breaking (VariantRemoved) - --> $REPO_PATH/tests/examples/enum.rs:7:9 - | -7 | Abc, - | ^^^ - -warning: Breaking changes in `Cde` - --> $REPO_PATH/tests/examples/enum.rs:39:5 - | -39 | / pub enum Cde { -40 | | Abc, -41 | | Bcd, -42 | | } - | |_____^ - | -warning: Breaking (VariantAdded) - --> $REPO_PATH/tests/examples/enum.rs:41:9 - | -41 | Bcd, - | ^^^ - -warning: Breaking changes in `Def` - --> $REPO_PATH/tests/examples/enum.rs:44:5 - | -44 | / pub enum Def { -45 | | Abc, -46 | | } - | |_____^ - | -warning: Breaking (VariantRemoved) - --> $REPO_PATH/tests/examples/enum.rs:16:9 - | -16 | Bcd, - | ^^^ - -warning: Breaking changes in `Efg` - --> $REPO_PATH/tests/examples/enum.rs:48:5 - | -48 | / pub enum Efg { -49 | | Abc(u8), -50 | | Bcd, -51 | | Cde { f: u8 }, -... | -55 | | Ghi { g: u8 }, -56 | | } - | |_____^ - | -warning: Breaking (VariantStyleChanged { now_struct: false, total_private: true }) - --> $REPO_PATH/tests/examples/enum.rs:49:9 - | -49 | Abc(u8), - | ^^^^^^^ -warning: Breaking (VariantStyleChanged { now_struct: false, total_private: true }) - --> $REPO_PATH/tests/examples/enum.rs:50:9 - | -50 | Bcd, - | ^^^ -warning: Breaking (VariantStyleChanged { now_struct: true, total_private: true }) - --> $REPO_PATH/tests/examples/enum.rs:51:9 - | -51 | Cde { f: u8 }, - | ^^^^^^^^^^^^^ -warning: Breaking (VariantStyleChanged { now_struct: false, total_private: true }) - --> $REPO_PATH/tests/examples/enum.rs:52:9 - | -52 | Def, - | ^^^ -warning: Breaking (VariantStyleChanged { now_struct: true, total_private: true }) - --> $REPO_PATH/tests/examples/enum.rs:53:9 - | -53 | Efg { f: u8 }, - | ^^^^^^^^^^^^^ -warning: Breaking (VariantFieldRemoved { public: false, total_public: false }) - --> $REPO_PATH/tests/examples/enum.rs:26:15 - | -26 | Ghi { f: u8 }, - | ^^^^^ -warning: Breaking (VariantFieldAdded { public: false, total_public: false }) - --> $REPO_PATH/tests/examples/enum.rs:55:15 - | -55 | Ghi { g: u8 }, - | ^^^^^ - diff --git a/tests/examples/enum.rs b/tests/examples/enum.rs deleted file mode 100644 index 7790d7df12f5d..0000000000000 --- a/tests/examples/enum.rs +++ /dev/null @@ -1,57 +0,0 @@ -pub mod old { - 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 }, - } -} - -pub mod new { - 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/tests/examples/fn.out b/tests/examples/fn.out deleted file mode 100644 index 1a7b745b119e9..0000000000000 --- a/tests/examples/fn.out +++ /dev/null @@ -1,77 +0,0 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Breaking changes in `bcd` - --> $REPO_PATH/tests/examples/fn.rs:36:5 - | -36 | pub fn bcd(_: u8) {} - | ^^^^^^^^^^^^^^^^^^^^ - | - = warning: Breaking (TypeChanged { error: ArgCount }) - -warning: Breaking changes in `cde` - --> $REPO_PATH/tests/examples/fn.rs:38:5 - | -38 | / pub fn cde() -> u16 { -39 | | 0xcde -40 | | } - | |_____^ - | - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: (), found: u16 }) }) - -warning: Breaking changes in `def` - --> $REPO_PATH/tests/examples/fn.rs:42:5 - | -42 | pub fn def() {} - | ^^^^^^^^^^^^^^^ - | - = warning: Breaking (TypeChanged { error: ArgCount }) - -warning: NonBreaking changes in `efg` - --> $REPO_PATH/tests/examples/fn.rs:44:5 - | -44 | / pub fn efg(a: A, _: A) -> A { -45 | | a -46 | | } - | |_____^ - | - = note: NonBreaking (TypeParameterAdded { defaulted: true }) - -warning: Breaking changes in `fgh` - --> $REPO_PATH/tests/examples/fn.rs:48:5 - | -48 | / pub fn fgh(a: u8, _: u16) -> u8 { -49 | | a -50 | | } - | |_____^ - | - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) - -warning: Breaking changes in `ghi` - --> $REPO_PATH/tests/examples/fn.rs:52:5 - | -52 | / pub fn ghi(a: u8, _: u8) -> u16 { -53 | | a as u16 -54 | | } - | |_____^ - | - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) - -warning: NonBreaking changes in `hij` - --> $REPO_PATH/tests/examples/fn.rs:56:5 - | -56 | / pub const fn hij() -> u8 { -57 | | 0 -58 | | } - | |_____^ - | - = note: NonBreaking (FnConstChanged { now_const: true }) - -warning: Breaking changes in `ijk` - --> $REPO_PATH/tests/examples/fn.rs:60:5 - | -60 | / pub fn ijk() -> u8 { -61 | | 0 -62 | | } - | |_____^ - | - = warning: Breaking (FnConstChanged { now_const: false }) - diff --git a/tests/examples/fn.rs b/tests/examples/fn.rs deleted file mode 100644 index 59d2d0423a868..0000000000000 --- a/tests/examples/fn.rs +++ /dev/null @@ -1,63 +0,0 @@ -#![feature(const_fn)] - -pub mod old { - 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 - } -} - -pub mod new { - pub fn abc() {} - - pub fn bcd(_: u8) {} - - pub fn cde() -> u16 { - 0xcde - } - - pub fn def() {} - - pub fn efg(a: A, _: A) -> A { - a - } - - pub fn fgh(a: u8, _: u16) -> u8 { - a - } - - pub fn ghi(a: u8, _: u8) -> u16 { - a as u16 - } - - pub const fn hij() -> u8 { - 0 - } - - pub fn ijk() -> u8 { - 0 - } -} diff --git a/tests/examples/infer.rs b/tests/examples/infer.rs deleted file mode 100644 index 7e1360a9bdc6e..0000000000000 --- a/tests/examples/infer.rs +++ /dev/null @@ -1,45 +0,0 @@ -pub mod old { - mod a { - pub trait Abc { - - } - - pub struct Klm; - } - - pub fn a(a: A) -> A { - a - } - - pub fn b() -> a::Klm { - a::Klm - } - - pub struct Hij<'a> { - pub field: &'a a::Abc, - pub field2: ::std::rc::Rc, - } -} - -pub mod new { - mod a { - pub trait Def { - - } - - pub struct Opq; - } - - pub fn a(a: A) -> A { - a - } - - pub fn b() -> a::Opq { - a::Opq - } - - pub struct Hij<'a> { - pub field: &'a a::Def, - pub field2: ::std::rc::Rc, - } -} diff --git a/tests/examples/kind_change.out b/tests/examples/kind_change.out deleted file mode 100644 index 606ccdc18d6eb..0000000000000 --- a/tests/examples/kind_change.out +++ /dev/null @@ -1,17 +0,0 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Removal of at least one path to `Abc` (Breaking) - --> $REPO_PATH/tests/examples/kind_change.rs:2:5 - | -2 | pub struct Abc; - | ^^^^^^^^^^^^^^^ - -warning: Breaking changes in `Abc` - --> $REPO_PATH/tests/examples/kind_change.rs:6:5 - | -6 | / pub enum Abc { -7 | | -8 | | } - | |_____^ - | - = warning: Breaking (KindDifference) - diff --git a/tests/examples/kind_change.rs b/tests/examples/kind_change.rs deleted file mode 100644 index 5821f14a0e3f8..0000000000000 --- a/tests/examples/kind_change.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod old { - pub struct Abc; -} - -pub mod new { - pub enum Abc { - - } -} diff --git a/tests/examples/macro.out b/tests/examples/macro.out deleted file mode 100644 index 7576b93137454..0000000000000 --- a/tests/examples/macro.out +++ /dev/null @@ -1,7 +0,0 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Removal of at least one path to `bar` (Breaking) - --> $REPO_PATH/tests/examples/macro.rs:6:9 - | -6 | pub macro bar() { Item } - | ^^^^^^^^^^^^^^^^^^^^ - diff --git a/tests/examples/macro.rs b/tests/examples/macro.rs deleted file mode 100644 index 87c3382706c43..0000000000000 --- a/tests/examples/macro.rs +++ /dev/null @@ -1,27 +0,0 @@ -#![feature(decl_macro, use_extern_macros)] - -pub mod old { - pub struct Item; - - pub macro bar() { Item } - - fn abc() -> Item { - bar!() - } -} - -pub mod new { - pub struct Item; - - #[macro_export] - macro_rules! bar { - () => { - Item - } - } - - #[allow(dead_code)] - fn abc() -> Item { - bar!() - } -} diff --git a/tests/examples/pathologic_paths.out b/tests/examples/pathologic_paths.out deleted file mode 100644 index 4c5c82f4f5c4c..0000000000000 --- a/tests/examples/pathologic_paths.out +++ /dev/null @@ -1,13 +0,0 @@ -version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 -warning: Addition of at least one path to `a` (TechnicallyBreaking) - --> $REPO_PATH/tests/examples/pathologic_paths.rs:11:25 - | -11 | pub mod a { blow!($($rest)*); } - | ^^^^^^^^^^^^^^^^^^^ - -warning: Addition of at least one path to `b` (TechnicallyBreaking) - --> $REPO_PATH/tests/examples/pathologic_paths.rs:12:25 - | -12 | pub mod b { pub use super::a::*; } - | ^^^^^^^^^^^^^^^^^^^^^^ - diff --git a/tests/examples/pathologic_paths.rs b/tests/examples/pathologic_paths.rs deleted file mode 100644 index 2dfa6cbb4282f..0000000000000 --- a/tests/examples/pathologic_paths.rs +++ /dev/null @@ -1,24 +0,0 @@ -#![recursion_limit="128"] - -pub mod old { - -} - -pub mod new { - macro_rules! blow { - () => {}; - (_ $($rest:tt)*) => { - pub mod a { blow!($($rest)*); } - pub mod b { pub use super::a::*; } - } - } - - blow!(_ _ _ _ _ _ _ _ - _ _ _ _ _ _ _ _ - _ _ _ _ _ _ _ _ - _ _ _ _ _ _ _ _ - _ _ _ _ _ _ _ _ - _ _ _ _ _ _ _ _ - _ _ _ _ _ _ _ _ - _ _ _ _ _ _ _ _); -} diff --git a/tests/examples/pub_use.rs b/tests/examples/pub_use.rs deleted file mode 100644 index 0b0115755a774..0000000000000 --- a/tests/examples/pub_use.rs +++ /dev/null @@ -1,17 +0,0 @@ -pub mod old { - pub mod a { - pub struct Abc; - } - - pub use old::a as b; -} - -pub mod new { - pub mod a { - pub struct Abc; - } - - pub mod b { - pub use new::a::*; - } -} diff --git a/tests/examples/removal.out b/tests/examples/removal.out deleted file mode 100644 index d830637f69c78..0000000000000 --- a/tests/examples/removal.out +++ /dev/null @@ -1,35 +0,0 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Removal of at least one path to `Abc` (Breaking) - --> $REPO_PATH/tests/examples/removal.rs:2:5 - | -2 | pub struct Abc; - | ^^^^^^^^^^^^^^^ - -warning: Removal of at least one path to `a` (Breaking) - --> $REPO_PATH/tests/examples/removal.rs:8:5 - | -8 | } - | ^ - -warning: Removal of at least one path to `Cde` (Breaking) - --> $REPO_PATH/tests/examples/removal.rs:12:9 - | -12 | pub struct Cde; - | ^^^^^^^^^^^^^^^ - -warning: Breaking changes in `Bcd` - --> $REPO_PATH/tests/examples/removal.rs:23:5 - | -23 | struct Bcd; - | ^^^^^^^^^^^ - | - = warning: Breaking (ItemMadePrivate) - -warning: Breaking changes in `b` - --> $REPO_PATH/tests/examples/removal.rs:27:5 - | -27 | } - | ^ - | - = warning: Breaking (ItemMadePrivate) - diff --git a/tests/examples/removal.rs b/tests/examples/removal.rs deleted file mode 100644 index 8082edc86287d..0000000000000 --- a/tests/examples/removal.rs +++ /dev/null @@ -1,32 +0,0 @@ -pub mod old { - 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 new { - #[allow(dead_code)] - struct Bcd; - - mod b { - - } - - mod c { - - } -} diff --git a/tests/examples/removal_path.out b/tests/examples/removal_path.out deleted file mode 100644 index fbb112308f12e..0000000000000 --- a/tests/examples/removal_path.out +++ /dev/null @@ -1,21 +0,0 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Removal of at least one path to `b` (Breaking) - --> $REPO_PATH/tests/examples/removal_path.rs:7:9 - | -7 | / pub use old::a::*; -8 | | } - | |_____^ - -warning: Removal of at least one path to `c` (Breaking) - --> $REPO_PATH/tests/examples/removal_path.rs:11:9 - | -11 | / pub use old::a::Abc; -12 | | } - | |_____^ - -warning: Removal of at least one path to `Abc` (Breaking) - --> $REPO_PATH/tests/examples/removal_path.rs:14:13 - | -14 | pub use self::a::Abc; - | ^^^^^^^^^^^^ - diff --git a/tests/examples/removal_path.rs b/tests/examples/removal_path.rs deleted file mode 100644 index 533c34e989f71..0000000000000 --- a/tests/examples/removal_path.rs +++ /dev/null @@ -1,21 +0,0 @@ -pub mod old { - pub mod a { - pub struct Abc; - } - - pub mod b { - pub use old::a::*; - } - - pub mod c { - pub use old::a::Abc; - } - - pub use self::a::Abc; -} - -pub mod new { - pub mod a { - pub struct Abc; - } -} diff --git a/tests/examples/struct.out b/tests/examples/struct.out deleted file mode 100644 index 91822eb4c1bbd..0000000000000 --- a/tests/examples/struct.out +++ /dev/null @@ -1,81 +0,0 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: TechnicallyBreaking changes in `Def` - --> $REPO_PATH/tests/examples/struct.rs:36:5 - | -36 | / pub struct Def { -37 | | pub field: A, -38 | | } - | |_____^ - | - = note: NonBreaking (TypeParameterAdded { defaulted: true }) -note: TechnicallyBreaking (ItemMadePublic) - --> $REPO_PATH/tests/examples/struct.rs:37:9 - | -37 | pub field: A, - | ^^^^^^^^^^^^ - -warning: Breaking changes in `Def2` - --> $REPO_PATH/tests/examples/struct.rs:40:5 - | -40 | / pub struct Def2 { -41 | | pub field: A, -42 | | } - | |_____^ - | - = note: NonBreaking (TypeParameterAdded { defaulted: true }) - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) - -warning: Breaking changes in `Efg` - --> $REPO_PATH/tests/examples/struct.rs:44:5 - | -44 | / pub struct Efg { -45 | | pub field: u16, -46 | | } - | |_____^ - | - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) - -warning: TechnicallyBreaking changes in `Fgh` - --> $REPO_PATH/tests/examples/struct.rs:48:5 - | -48 | / pub struct Fgh { -49 | | pub field: u8, -50 | | } - | |_____^ - | -note: TechnicallyBreaking (ItemMadePublic) - --> $REPO_PATH/tests/examples/struct.rs:49:9 - | -49 | pub field: u8, - | ^^^^^^^^^^^^^ - -warning: Breaking changes in `Ghi` - --> $REPO_PATH/tests/examples/struct.rs:52:5 - | -52 | / pub struct Ghi { -53 | | field: u8, -54 | | } - | |_____^ - | -warning: Breaking (ItemMadePrivate) - --> $REPO_PATH/tests/examples/struct.rs:53:9 - | -53 | field: u8, - | ^^^^^^^^^ - -warning: Breaking changes in `Hij` - --> $REPO_PATH/tests/examples/struct.rs:56:5 - | -56 | / pub struct Hij { -57 | | field: u8, -58 | | } - | |_____^ - | -warning: Breaking (VariantStyleChanged { now_struct: true, total_private: true }) - --> $REPO_PATH/tests/examples/struct.rs:56:5 - | -56 | / pub struct Hij { -57 | | field: u8, -58 | | } - | |_____^ - diff --git a/tests/examples/struct.rs b/tests/examples/struct.rs deleted file mode 100644 index f0c1c89fd0d92..0000000000000 --- a/tests/examples/struct.rs +++ /dev/null @@ -1,59 +0,0 @@ -#[allow(dead_code)] -pub mod old { - pub struct Abc { - field: A, - } - - pub struct Def { - field: u8, - } - - pub struct Def2 { - pub field: u8, - } - - pub struct Efg { - pub field: u8, - } - - pub struct Fgh { - field: u8, - } - - pub struct Ghi { - pub field: u8, - } - - pub struct Hij(u8); -} - -#[allow(dead_code)] -pub mod new { - pub struct Abc { - field: B, - } - - pub struct Def { - pub field: A, - } - - pub struct Def2 { - pub field: A, - } - - pub struct Efg { - pub field: u16, - } - - pub struct Fgh { - pub field: u8, - } - - pub struct Ghi { - field: u8, - } - - pub struct Hij { - field: u8, - } -} diff --git a/tests/examples/trait.out b/tests/examples/trait.out deleted file mode 100644 index 38abdf02013d4..0000000000000 --- a/tests/examples/trait.out +++ /dev/null @@ -1,62 +0,0 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Breaking changes in `Abc` - --> $REPO_PATH/tests/examples/trait.rs:19:5 - | -19 | / pub trait Abc { -20 | | type A; -21 | | fn test(&self) -> u8; -22 | | fn test3(&self) -> u8; -... | -31 | | fn test9(&self) -> u8; -32 | | } - | |_____^ - | -warning: Breaking (TraitItemRemoved { defaulted: false }) - --> $REPO_PATH/tests/examples/trait.rs:5:9 - | -5 | fn test2(&self) -> u8; - | ^^^^^^^^^^^^^^^^^^^^^^ -warning: Breaking (TraitItemRemoved { defaulted: true }) - --> $REPO_PATH/tests/examples/trait.rs:9:9 - | -9 | / fn test5() -> u8 { -10 | | 0 -11 | | } - | |_________^ -warning: Breaking (TraitItemAdded { defaulted: false }) - --> $REPO_PATH/tests/examples/trait.rs:22:9 - | -22 | fn test3(&self) -> u8; - | ^^^^^^^^^^^^^^^^^^^^^^ -note: TechnicallyBreaking (TraitItemAdded { defaulted: true }) - --> $REPO_PATH/tests/examples/trait.rs:26:9 - | -26 | / fn test6() -> u8 { -27 | | 0 -28 | | } - | |_________^ - -warning: Breaking changes in `test7` - --> $REPO_PATH/tests/examples/trait.rs:29:9 - | -29 | fn test7() -> u16; - | ^^^^^^^^^^^^^^^^^^ - | - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) - -warning: Breaking changes in `test8` - --> $REPO_PATH/tests/examples/trait.rs:30:9 - | -30 | fn test8(_: &Self) -> u8; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: Breaking (MethodSelfChanged { now_self: false }) - -warning: TechnicallyBreaking changes in `test9` - --> $REPO_PATH/tests/examples/trait.rs:31:9 - | -31 | fn test9(&self) -> u8; - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: TechnicallyBreaking (MethodSelfChanged { now_self: true }) - diff --git a/tests/examples/trait.rs b/tests/examples/trait.rs deleted file mode 100644 index 16b53d5f3c8f1..0000000000000 --- a/tests/examples/trait.rs +++ /dev/null @@ -1,33 +0,0 @@ -pub mod old { - 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 mod new { - 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; - } -} diff --git a/tests/examples/ty_alias.out b/tests/examples/ty_alias.out deleted file mode 100644 index 84ed1a8fa82cf..0000000000000 --- a/tests/examples/ty_alias.out +++ /dev/null @@ -1,58 +0,0 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Breaking changes in `A` - --> $REPO_PATH/tests/examples/ty_alias.rs:12:5 - | -12 | pub type A = u16; - | ^^^^^^^^^^^^^^^^^ - | - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) - -warning: Breaking changes in `B` - --> $REPO_PATH/tests/examples/ty_alias.rs:13:5 - | -13 | pub type B<'a, 'b : 'a, T> = (&'a T, &'b T); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: Breaking (RegionParameterAdded) - -warning: Breaking changes in `C` - --> $REPO_PATH/tests/examples/ty_alias.rs:14:5 - | -14 | pub type C = T; - | ^^^^^^^^^^^^^^^^^^ - | - = warning: Breaking (RegionParameterRemoved) - -warning: Breaking changes in `D` - --> $REPO_PATH/tests/examples/ty_alias.rs:15:5 - | -15 | pub type D<'a, T, U=Box> = (&'a T, U); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: NonBreaking (TypeParameterAdded { defaulted: true }) - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: &'a T, found: (&'a T, std::boxed::Box) }) }) - -warning: Breaking changes in `E` - --> $REPO_PATH/tests/examples/ty_alias.rs:16:5 - | -16 | pub type E<'a, T, U> = (&'a T, U); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: Breaking (TypeParameterAdded { defaulted: false }) - -warning: Breaking changes in `F` - --> $REPO_PATH/tests/examples/ty_alias.rs:17:5 - | -17 | pub type F<'a> = &'a u8; - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: Breaking (TypeParameterRemoved { defaulted: true }) - -warning: Breaking changes in `G` - --> $REPO_PATH/tests/examples/ty_alias.rs:18:5 - | -18 | pub type G<'a> = (&'a u8); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: Breaking (TypeParameterRemoved { defaulted: false }) - diff --git a/tests/examples/ty_alias.rs b/tests/examples/ty_alias.rs deleted file mode 100644 index 46300f3a38c31..0000000000000 --- a/tests/examples/ty_alias.rs +++ /dev/null @@ -1,19 +0,0 @@ -pub mod old { - 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; -} - -pub mod new { - pub type A = u16; - pub type B<'a, 'b : 'a, T> = (&'a T, &'b T); - pub type C = T; - pub type D<'a, T, U=Box> = (&'a T, U); - pub type E<'a, T, U> = (&'a T, U); - pub type F<'a> = &'a u8; - pub type G<'a> = (&'a u8); -} diff --git a/tests/helper/test.rs b/tests/helper/test.rs index b892b3f4f0838..88c8d225801c7 100644 --- a/tests/helper/test.rs +++ b/tests/helper/test.rs @@ -1 +1,2 @@ -extern crate oldandnew; +extern crate old; +extern crate new; diff --git a/tests/helper/test2.rs b/tests/helper/test2.rs deleted file mode 100644 index 88c8d225801c7..0000000000000 --- a/tests/helper/test2.rs +++ /dev/null @@ -1,2 +0,0 @@ -extern crate old; -extern crate new; From c088f6d8ca9fea32a2f559e0dd631e59a56e12df Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 14 Jul 2017 20:10:29 +0200 Subject: [PATCH 138/553] Cleaned up the new test system. --- tests/cases/addition/stderr | 0 tests/cases/addition_path/stderr | 0 tests/cases/enums/stderr | 0 tests/cases/func/stderr | 0 tests/cases/infer/stderr | 0 tests/cases/kind_change/stderr | 0 tests/cases/macros/stderr | 0 tests/cases/pathologic_paths/stderr | 0 tests/cases/pub_use/stderr | 0 tests/cases/removal/stderr | 0 tests/cases/removal_path/stderr | 0 tests/cases/structs/stderr | 0 tests/cases/traits/stderr | 0 tests/cases/ty_alias/stderr | 0 tests/examples.rs | 11 ++++------- 15 files changed, 4 insertions(+), 7 deletions(-) delete mode 100644 tests/cases/addition/stderr delete mode 100644 tests/cases/addition_path/stderr delete mode 100644 tests/cases/enums/stderr delete mode 100644 tests/cases/func/stderr delete mode 100644 tests/cases/infer/stderr delete mode 100644 tests/cases/kind_change/stderr delete mode 100644 tests/cases/macros/stderr delete mode 100644 tests/cases/pathologic_paths/stderr delete mode 100644 tests/cases/pub_use/stderr delete mode 100644 tests/cases/removal/stderr delete mode 100644 tests/cases/removal_path/stderr delete mode 100644 tests/cases/structs/stderr delete mode 100644 tests/cases/traits/stderr delete mode 100644 tests/cases/ty_alias/stderr diff --git a/tests/cases/addition/stderr b/tests/cases/addition/stderr deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/tests/cases/addition_path/stderr b/tests/cases/addition_path/stderr deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/tests/cases/enums/stderr b/tests/cases/enums/stderr deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/tests/cases/func/stderr b/tests/cases/func/stderr deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/tests/cases/infer/stderr b/tests/cases/infer/stderr deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/tests/cases/kind_change/stderr b/tests/cases/kind_change/stderr deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/tests/cases/macros/stderr b/tests/cases/macros/stderr deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/tests/cases/pathologic_paths/stderr b/tests/cases/pathologic_paths/stderr deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/tests/cases/pub_use/stderr b/tests/cases/pub_use/stderr deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/tests/cases/removal/stderr b/tests/cases/removal/stderr deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/tests/cases/removal_path/stderr b/tests/cases/removal_path/stderr deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/tests/cases/structs/stderr b/tests/cases/structs/stderr deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/tests/cases/traits/stderr b/tests/cases/traits/stderr deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/tests/cases/ty_alias/stderr b/tests/cases/ty_alias/stderr deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/tests/examples.rs b/tests/examples.rs index 1e230e74f3f52..9a82b668083db 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -15,13 +15,12 @@ macro_rules! test { let path = Path::new($path); let out_file = path.join("stdout"); - let stdout = File::create(&out_file).expect("could not create `stdout` file"); - let err_file = path.join("stderr"); - let stderr = File::create(&err_file).expect("could not create `stderr` file"); let old_rlib = path.join("libold.rlib"); let new_rlib = path.join("libnew.rlib"); + let stdout = File::create(&out_file).expect("could not create `stdout` file"); + success &= Command::new("rustc") .args(&["--crate-type=lib", "-o", old_rlib.to_str().unwrap()]) .arg(path.join("old.rs")) @@ -45,11 +44,10 @@ macro_rules! test { .arg(&subst) .stdin(Stdio::piped()) .stdout(stdout) - .stderr(stderr) .spawn() .expect("could not run sed"); - let (err_pipe, out_pipe) = if let Some(ref mut stdin) = sed_child.stdin { + let (err_pipe, out_pipe) = if let Some(ref stdin) = sed_child.stdin { let fd = stdin.as_raw_fd(); unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } } else { @@ -74,8 +72,7 @@ macro_rules! test { success &= sed_child.wait().expect("could not wait for sed child").success(); success &= Command::new("git") - .args(&["diff", "--quiet", - out_file.to_str().unwrap(), err_file.to_str().unwrap()]) + .args(&["diff", "--quiet", out_file.to_str().unwrap()]) .status() .expect("could not run git diff") .success(); From e8b738ef5e143a8dd4681156c841b8f3bb440664 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 14 Jul 2017 22:24:56 +0200 Subject: [PATCH 139/553] New change representation. --- src/semcheck/changes.rs | 266 +++++++++++----------------- src/semcheck/traverse.rs | 25 ++- tests/cases/addition/stdout | 38 ++-- tests/cases/addition_path/stdout | 26 +-- tests/cases/kind_change/stdout | 8 +- tests/cases/pathologic_paths/stdout | 16 +- tests/cases/removal/stdout | 42 +++-- tests/cases/removal_path/stdout | 46 ++++- 8 files changed, 256 insertions(+), 211 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index dab7badadaf64..f53b2c8617ebd 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -6,17 +6,16 @@ //! version as well. The ordering of changes and output generation is performed using these data //! structures, too. -use rustc::hir::def::Export; use rustc::hir::def_id::DefId; use rustc::session::Session; use rustc::ty::error::TypeError; use semver::Version; -use std::collections::{BTreeMap, HashMap}; +use std::collections::{BTreeSet, BTreeMap, HashMap}; use std::cmp::Ordering; -use syntax::symbol::{Ident, Symbol}; +use syntax::symbol::Symbol; use syntax_pos::Span; @@ -47,86 +46,100 @@ impl<'a> Default for ChangeCategory { } } -/// A change record of a newly introduced or removed item. +/// A change record of newly introduced or removed paths to an item. /// /// It is important to note that the `Eq` and `Ord` instances are constucted to only -/// regard the span of the associated item export. -pub enum UnaryChange { - /// An item has been added. - Addition(Export), - /// An item has been removed. - Removal(Export), +/// regard the span of the associated item definition. +pub struct PathChange { + /// The name of the item. + name: Symbol, + /// The definition span of the item. + def_span: Span, + /// The set of spans of newly added exports of the item. + additions: BTreeSet, + /// The set of spans of removed exports of the item. + removals: BTreeSet, } -impl UnaryChange { - /// Get the change's category. - pub fn to_category(&self) -> ChangeCategory { - match *self { - UnaryChange::Addition(_) => TechnicallyBreaking, - UnaryChange::Removal(_) => Breaking, +impl PathChange { + /// Construct a new empty change record for an item. + fn new(name: Symbol, def_span: Span) -> PathChange { + PathChange { + name: name, + def_span: def_span, + additions: BTreeSet::new(), + removals: BTreeSet::new(), } } - /// Get the change item's sole export. - fn export(&self) -> &Export { - match *self { - UnaryChange::Addition(ref e) | UnaryChange::Removal(ref e) => e, + fn insert(&mut self, span: Span, add: bool) { + if add { + self.additions.insert(span); + } else { + self.removals.insert(span); } } - /// Get the change item's sole span. - pub fn span(&self) -> &Span { - &self.export().span - } - - /// Get the change item's ident. - pub fn ident(&self) -> &Ident { - &self.export().ident + /// Get the change's category. + pub fn to_category(&self) -> ChangeCategory { + if !self.removals.is_empty() { + Breaking + } else if !self.additions.is_empty() { + TechnicallyBreaking + } else { + Patch + } } - /// Render the change's type to a string. - pub fn type_(&self) -> &'static str { - match *self { - UnaryChange::Addition(_) => "Addition", - UnaryChange::Removal(_) => "Removal", - } + /// Get the change item's definition span. + pub fn span(&self) -> &Span { + &self.def_span } /// Report the change. fn report(&self, session: &Session) { - let msg = format!("{} of at least one path to `{}` ({:?})", - self.type_(), - self.ident(), - self.to_category()); - let mut builder = session.struct_span_warn(self.export().span, &msg); + if self.to_category() == Patch { + return; + } + + let msg = format!("Path changes to `{}`", self.name); + let mut builder = session.struct_span_warn(self.def_span, &msg); + + for removed_span in &self.removals { + builder.span_warn(*removed_span, "Breaking: removed path"); + } + + for added_span in &self.additions { + builder.span_note(*added_span, "TechnicallyBreaking: added path"); + } builder.emit(); } } -impl PartialEq for UnaryChange { - fn eq(&self, other: &UnaryChange) -> bool { +impl PartialEq for PathChange { + fn eq(&self, other: &PathChange) -> bool { self.span() == other.span() } } -impl Eq for UnaryChange {} +impl Eq for PathChange {} -impl PartialOrd for UnaryChange { - fn partial_cmp(&self, other: &UnaryChange) -> Option { +impl PartialOrd for PathChange { + fn partial_cmp(&self, other: &PathChange) -> Option { self.span().partial_cmp(other.span()) } } -impl Ord for UnaryChange { - fn cmp(&self, other: &UnaryChange) -> Ordering { +impl Ord for PathChange { + fn cmp(&self, other: &PathChange) -> Ordering { self.span().cmp(other.span()) } } /// The types of changes we identify between items present in both crate versions. #[derive(Clone, Debug)] -pub enum BinaryChangeType<'tcx> { +pub enum ChangeType<'tcx> { /// An item has been made public. ItemMadePublic, /// An item has been made private @@ -167,9 +180,9 @@ pub enum BinaryChangeType<'tcx> { Unknown, } -pub use self::BinaryChangeType::*; +pub use self::ChangeType::*; -impl<'tcx> BinaryChangeType<'tcx> { +impl<'tcx> ChangeType<'tcx> { pub fn to_category(&self) -> ChangeCategory { match *self { ItemMadePrivate | @@ -204,9 +217,9 @@ impl<'tcx> BinaryChangeType<'tcx> { /// It is important to note that the `Eq` and `Ord` instances are constucted to only /// regard the *new* span of the associated item export. This allows us to sort them /// by appearance in the *new* source. -pub struct BinaryChange<'tcx> { +pub struct Change<'tcx> { /// The type of the change affecting the item. - changes: Vec<(BinaryChangeType<'tcx>, Option)>, + changes: Vec<(ChangeType<'tcx>, Option)>, /// The most severe change category already recorded for the item. max: ChangeCategory, /// The symbol associated with the change item. @@ -217,10 +230,10 @@ pub struct BinaryChange<'tcx> { output: bool } -impl<'tcx> BinaryChange<'tcx> { +impl<'tcx> Change<'tcx> { /// Construct a new empty change record for an item. - fn new(name: Symbol, span: Span, output: bool) -> BinaryChange<'tcx> { - BinaryChange { + fn new(name: Symbol, span: Span, output: bool) -> Change<'tcx> { + Change { changes: Vec::new(), max: ChangeCategory::default(), name: name, @@ -230,7 +243,7 @@ impl<'tcx> BinaryChange<'tcx> { } /// Add another change type to the change record. - fn add(&mut self, type_: BinaryChangeType<'tcx>, span: Option) { + fn add(&mut self, type_: ChangeType<'tcx>, span: Option) { let cat = type_.to_category(); if cat > self.max { @@ -285,161 +298,84 @@ impl<'tcx> BinaryChange<'tcx> { } } -impl<'tcx> PartialEq for BinaryChange<'tcx> { - fn eq(&self, other: &BinaryChange) -> bool { +impl<'tcx> PartialEq for Change<'tcx> { + fn eq(&self, other: &Change) -> bool { self.new_span() == other.new_span() } } -impl<'tcx> Eq for BinaryChange<'tcx> {} +impl<'tcx> Eq for Change<'tcx> {} -impl<'tcx> PartialOrd for BinaryChange<'tcx> { - fn partial_cmp(&self, other: &BinaryChange<'tcx>) -> Option { +impl<'tcx> PartialOrd for Change<'tcx> { + fn partial_cmp(&self, other: &Change<'tcx>) -> Option { self.new_span().partial_cmp(other.new_span()) } } -impl<'tcx> Ord for BinaryChange<'tcx> { - fn cmp(&self, other: &BinaryChange<'tcx>) -> Ordering { +impl<'tcx> Ord for Change<'tcx> { + fn cmp(&self, other: &Change<'tcx>) -> Ordering { self.new_span().cmp(other.new_span()) } } -/// A change record for any item. -/// -/// Consists of all information we need to compute semantic versioning properties of -/// the change(s) performed on it, as well as data we use to output it in a nice fashion. -#[derive(PartialEq, Eq, PartialOrd, Ord)] -pub enum Change<'tcx> { - /// A wrapper around a unary change. - Unary(UnaryChange), - /// A wrapper around a binary change set. - Binary(BinaryChange<'tcx>), -} - -impl<'tcx> Change<'tcx> { - /// Construct a new addition-change for the given export. - fn new_addition(item: Export) -> Change<'tcx> { - Change::Unary(UnaryChange::Addition(item)) - } - - /// Construct a new removal-change for the given export. - fn new_removal(item: Export) -> Change<'tcx> { - Change::Unary(UnaryChange::Removal(item)) - } - - /// Construct a new binary change for the given exports. - fn new_binary(name: Symbol, span: Span, output: bool) -> Change<'tcx> { - Change::Binary(BinaryChange::new(name, span, output)) - } - - /// Add a change type to a given binary change. - fn add(&mut self, type_: BinaryChangeType<'tcx>, span: Option) { - match *self { - Change::Unary(_) => panic!("can't add binary change types to unary change"), - Change::Binary(ref mut b) => b.add(type_, span), - } - } - - /// Get the change's representative span. - fn span(&self) -> &Span { - match *self { - Change::Unary(ref u) => u.span(), - Change::Binary(ref b) => b.new_span(), - } - } - - /// Get the change's category. - fn to_category(&self) -> ChangeCategory { - match *self { - Change::Unary(ref u) => u.to_category(), - Change::Binary(ref b) => b.to_category(), - } - } - - /// Report the change. - fn report(&self, session: &Session) { - match *self { - Change::Unary(ref u) => u.report(session), - Change::Binary(ref b) => b.report(session), - } - } -} - -/// An identifier used to unambiguously refer to items we record changes for. -#[derive(Clone, PartialEq, Eq, Hash)] -pub enum ChangeKey { - /// An item referred to using the old definition's id. - /// This includes items that have been removed *or* changed. - OldKey(DefId), - /// An item referred to using the new definition's id. - /// This includes items that have been added *only* - NewKey(DefId), -} - /// The total set of changes recorded for two crate versions. #[derive(Default)] pub struct ChangeSet<'tcx> { + /// The currently recorded path manipulations. + path_changes: HashMap, /// The currently recorded changes. - changes: HashMap>, + changes: HashMap>, /// The mapping of spans to changes, for ordering purposes. - spans: BTreeMap, + spans: BTreeMap, /// The most severe change category already recorded. max: ChangeCategory, } impl<'tcx> ChangeSet<'tcx> { - /// Add a new addition-change for the given export. - pub fn new_addition(&mut self, item: Export) { - self.new_unary_change(Change::new_addition(item), ChangeKey::NewKey(item.def.def_id())); - } + /// Add a new unary change entry for the given exports. + pub fn new_unary(&mut self, old: DefId, name: Symbol, def_span: Span, span: Span, add: bool) { + self.spans.insert(def_span, old); - /// Add a new removal-change for the given export. - pub fn new_removal(&mut self, item: Export) { - self.new_unary_change(Change::new_removal(item), ChangeKey::NewKey(item.def.def_id())); - } + let change = self.path_changes + .entry(old) + .or_insert_with(|| PathChange::new(name, def_span)); + + change.insert(span, add); - /// Add a new (unary) change for the given key. - fn new_unary_change(&mut self, change: Change<'tcx>, key: ChangeKey) { let cat = change.to_category(); if cat > self.max { self.max = cat.clone(); } - - self.spans.insert(*change.span(), key.clone()); - self.changes.insert(key, change); } /// Add a new binary change entry for the given exports. - pub fn new_binary(&mut self, old_did: DefId, name: Symbol, span: Span, output: bool) { - let key = ChangeKey::OldKey(old_did); - let change = Change::new_binary(name, span, output); + pub fn new_binary(&mut self, old: DefId, name: Symbol, span: Span, output: bool) { + let change = Change::new(name, span, output); - self.spans.insert(*change.span(), key.clone()); - self.changes.insert(key, change); + self.spans.insert(*change.new_span(), old); + self.changes.insert(old, change); } /// Add a new binary change to an already existing entry. - pub fn add_binary(&mut self, type_: BinaryChangeType<'tcx>, old: DefId, span: Option) { - let key = ChangeKey::OldKey(old); + pub fn add_binary(&mut self, type_: ChangeType<'tcx>, old: DefId, span: Option) { let cat = type_.to_category(); if cat > self.max { self.max = cat.clone(); } - self.changes.get_mut(&key).unwrap().add(type_, span); + self.changes.get_mut(&old).unwrap().add(type_, span); } /// 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, key: DefId) -> bool { + pub fn item_breaking(&self, old: DefId) -> bool { // we only care about items that were present before, since only those can get breaking // changes (additions don't count). self.changes - .get(&ChangeKey::OldKey(key)) + .get(&old) .map(|changes| changes.to_category() == Breaking) .unwrap_or(false) } @@ -459,7 +395,13 @@ impl<'tcx> ChangeSet<'tcx> { } for key in self.spans.values() { - self.changes[key].report(session); + if let Some(change) = self.path_changes.get(key) { + change.report(session); + } + + if let Some(change) = self.changes.get(key) { + change.report(session); + } } } } @@ -547,9 +489,9 @@ pub mod tests { pub type BinaryChange_ = (Span_, Span_); - fn build_binary_change(t: BinaryChangeType, s1: Span, s2: Span) -> BinaryChange { + fn build_binary_change(t: ChangeType, s1: Span, s2: Span) -> Change { let mut interner = Interner::new(); - let mut change = BinaryChange::new(interner.intern("test"), s2, true); + let mut change = Change::new(interner.intern("test"), s2, true); change.add(t, Some(s1)); change diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 670a6a72cff6f..c0857675894b9 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -16,8 +16,8 @@ use rustc::ty::Visibility::Public; use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; use rustc::ty::subst::{Subst, Substs}; -use semcheck::changes::BinaryChangeType; -use semcheck::changes::BinaryChangeType::*; +use semcheck::changes::ChangeType; +use semcheck::changes::ChangeType::*; use semcheck::changes::ChangeSet; use semcheck::mapping::{IdMapping, NameMapping}; use semcheck::mismatch::Mismatch; @@ -98,7 +98,10 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, }; if o_vis != n_vis { - changes.new_binary(o.def.def_id(), o.ident.name, n.span, true); + changes.new_binary(o_did, + o.ident.name, + tcx.def_span(o_did), + true); if o_vis == Public && n_vis != Public { changes.add_binary(ItemMadePrivate, o_did, None); @@ -198,12 +201,22 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, } (Some(o), None) => { if old_vis == Public && cstore.visibility(o.def.def_id()) == Public { - changes.new_removal(o); + let o_did = o.def.def_id(); + changes.new_unary(o_did, + o.ident.name, + tcx.def_span(o_did), + o.span, + false); } } (None, Some(n)) => { if new_vis == Public && cstore.visibility(n.def.def_id()) == Public { - changes.new_addition(n); + let n_did = n.def.def_id(); + changes.new_unary(n_did, + n.ident.name, + tcx.def_span(n_did), + n.span, + true); } } (None, None) => unreachable!(), @@ -478,7 +491,7 @@ fn diff_bounds<'a, 'tcx>(_changes: &mut ChangeSet, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _old: DefId, _new: DefId) - -> (Vec>, Vec<(DefId, DefId)>) + -> (Vec>, Vec<(DefId, DefId)>) { /* let res = Default::default(); diff --git a/tests/cases/addition/stdout b/tests/cases/addition/stdout index 1f44e13ed52a2..20dedfeda08f6 100644 --- a/tests/cases/addition/stdout +++ b/tests/cases/addition/stdout @@ -1,5 +1,19 @@ version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 -warning: Addition of at least one path to `Abc` (TechnicallyBreaking) +warning: TechnicallyBreaking changes in `b` + --> $REPO_PATH/tests/cases/addition/old.rs:6:1 + | +6 | } + | ^ + | + = note: TechnicallyBreaking (ItemMadePublic) + +warning: Path changes to `Abc` + --> $REPO_PATH/tests/cases/addition/new.rs:1:1 + | +1 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + | +note: TechnicallyBreaking: added path --> $REPO_PATH/tests/cases/addition/new.rs:1:1 | 1 | pub struct Abc; @@ -13,23 +27,25 @@ warning: TechnicallyBreaking changes in `Bcd` | = note: TechnicallyBreaking (ItemMadePublic) -warning: Addition of at least one path to `a` (TechnicallyBreaking) +warning: Path changes to `a` + --> $REPO_PATH/tests/cases/addition/new.rs:7:1 + | +7 | } + | ^ + | +note: TechnicallyBreaking: added path --> $REPO_PATH/tests/cases/addition/new.rs:7:1 | 7 | } | ^ -warning: TechnicallyBreaking changes in `b` - --> $REPO_PATH/tests/cases/addition/new.rs:10:5 +warning: Path changes to `Cde` + --> $REPO_PATH/tests/cases/addition/new.rs:11:5 | -10 | / #[allow(dead_code)] -11 | | pub struct Cde; -12 | | } - | |_^ +11 | pub struct Cde; + | ^^^^^^^^^^^^^^^ | - = note: TechnicallyBreaking (ItemMadePublic) - -warning: Addition of at least one path to `Cde` (TechnicallyBreaking) +note: TechnicallyBreaking: added path --> $REPO_PATH/tests/cases/addition/new.rs:11:5 | 11 | pub struct Cde; diff --git a/tests/cases/addition_path/stdout b/tests/cases/addition_path/stdout index e2113ef2faa0b..43175753d7666 100644 --- a/tests/cases/addition_path/stdout +++ b/tests/cases/addition_path/stdout @@ -1,19 +1,23 @@ version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 -warning: Addition of at least one path to `Abc` (TechnicallyBreaking) - --> $REPO_PATH/tests/cases/addition_path/new.rs:6:13 +warning: Path changes to `Abc` + --> $REPO_PATH/tests/cases/addition_path/new.rs:2:5 | -6 | pub use a::*; - | ^^^^^ - -warning: Addition of at least one path to `Abc` (TechnicallyBreaking) - --> $REPO_PATH/tests/cases/addition_path/new.rs:6:13 +2 | pub struct Abc; + | ^^^^^^^^^^^^^^^ | -6 | pub use a::*; - | ^^^^^ - -warning: Addition of at least one path to `Abc` (TechnicallyBreaking) +note: TechnicallyBreaking: added path --> $REPO_PATH/tests/cases/addition_path/new.rs:6:13 | 6 | pub use a::*; | ^^^^^ +note: TechnicallyBreaking: added path + --> $REPO_PATH/tests/cases/addition_path/new.rs:10:13 + | +10| pub use a::Abc; + | ^^^^^^ +note: TechnicallyBreaking: added path + --> $REPO_PATH/tests/cases/addition_path/new.rs:13:9 + | +13| pub use self::a::Abc; + | ^^^^^^^^^^^^ diff --git a/tests/cases/kind_change/stdout b/tests/cases/kind_change/stdout index 50e8c8d93ecea..0dc76711a3e65 100644 --- a/tests/cases/kind_change/stdout +++ b/tests/cases/kind_change/stdout @@ -1,5 +1,11 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Removal of at least one path to `Abc` (Breaking) +warning: Path changes to `Abc` + --> $REPO_PATH/tests/cases/kind_change/old.rs:1:1 + | +1 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + | +warning: Breaking: removed path --> $REPO_PATH/tests/cases/kind_change/old.rs:1:1 | 1 | pub struct Abc; diff --git a/tests/cases/pathologic_paths/stdout b/tests/cases/pathologic_paths/stdout index 0c6f2f7e641ab..64bf2568d5620 100644 --- a/tests/cases/pathologic_paths/stdout +++ b/tests/cases/pathologic_paths/stdout @@ -1,11 +1,23 @@ version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 -warning: Addition of at least one path to `a` (TechnicallyBreaking) +warning: Path changes to `a` + --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:5:21 + | +5 | pub mod a { blow!($($rest)*); } + | ^^^^^^^^^^^^^^^^^^^ + | +note: TechnicallyBreaking: added path --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:5:21 | 5 | pub mod a { blow!($($rest)*); } | ^^^^^^^^^^^^^^^^^^^ -warning: Addition of at least one path to `b` (TechnicallyBreaking) +warning: Path changes to `b` + --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:6:21 + | +6 | pub mod b { pub use super::a::*; } + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: TechnicallyBreaking: added path --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:6:21 | 6 | pub mod b { pub use super::a::*; } diff --git a/tests/cases/removal/stdout b/tests/cases/removal/stdout index 5bc6ac37a19ab..40245f545bb08 100644 --- a/tests/cases/removal/stdout +++ b/tests/cases/removal/stdout @@ -1,17 +1,45 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Removal of at least one path to `Abc` (Breaking) +warning: Path changes to `Abc` + --> $REPO_PATH/tests/cases/removal/old.rs:1:1 + | +1 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + | +warning: Breaking: removed path --> $REPO_PATH/tests/cases/removal/old.rs:1:1 | 1 | pub struct Abc; | ^^^^^^^^^^^^^^^ -warning: Removal of at least one path to `a` (Breaking) +warning: Path changes to `a` + --> $REPO_PATH/tests/cases/removal/old.rs:7:1 + | +7 | } + | ^ + | +warning: Breaking: removed path --> $REPO_PATH/tests/cases/removal/old.rs:7:1 | 7 | } | ^ -warning: Removal of at least one path to `Cde` (Breaking) +warning: Breaking changes in `b` + --> $REPO_PATH/tests/cases/removal/old.rs:10:5 + | +10 | / #[allow(dead_code)] +11 | | pub struct Cde; +12 | | } + | |_^ + | + = warning: Breaking (ItemMadePrivate) + +warning: Path changes to `Cde` + --> $REPO_PATH/tests/cases/removal/old.rs:11:5 + | +11 | pub struct Cde; + | ^^^^^^^^^^^^^^^ + | +warning: Breaking: removed path --> $REPO_PATH/tests/cases/removal/old.rs:11:5 | 11 | pub struct Cde; @@ -25,11 +53,3 @@ warning: Breaking changes in `Bcd` | = warning: Breaking (ItemMadePrivate) -warning: Breaking changes in `b` - --> $REPO_PATH/tests/cases/removal/new.rs:6:1 - | -6 | } - | ^ - | - = warning: Breaking (ItemMadePrivate) - diff --git a/tests/cases/removal_path/stdout b/tests/cases/removal_path/stdout index 13486d031aa4f..4aa496f80824f 100644 --- a/tests/cases/removal_path/stdout +++ b/tests/cases/removal_path/stdout @@ -1,21 +1,53 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Removal of at least one path to `b` (Breaking) +warning: Path changes to `Abc` + --> $REPO_PATH/tests/cases/removal_path/old.rs:2:5 + | +2 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + | +warning: Breaking: removed path + --> $REPO_PATH/tests/cases/removal_path/old.rs:13:9 + | +13| pub use self::a::Abc; + | ^^^^^^^^^^^^ + +warning: Path changes to `b` + --> $REPO_PATH/tests/cases/removal_path/old.rs:6:5 + | +6 | / pub use a::*; +7 | | } + | |_^ + | +warning: Breaking: removed path --> $REPO_PATH/tests/cases/removal_path/old.rs:6:5 | 6 | / pub use a::*; 7 | | } | |_^ -warning: Removal of at least one path to `c` (Breaking) +warning: Path changes to `c` --> $REPO_PATH/tests/cases/removal_path/old.rs:10:5 | 10 | / pub use a::Abc; 11 | | } | |_^ - -warning: Removal of at least one path to `Abc` (Breaking) - --> $REPO_PATH/tests/cases/removal_path/old.rs:13:9 | -13 | pub use self::a::Abc; - | ^^^^^^^^^^^^ +warning: Breaking: removed path + --> $REPO_PATH/tests/cases/removal_path/old.rs:10:5 + | +10 | / pub use a::Abc; +11 | | } + | |_^ + +warning: Path changes to `Abc` + --> $REPO_PATH/tests/cases/removal_path/old.rs:2:5 + | +2 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + | +warning: Breaking: removed path + --> $REPO_PATH/tests/cases/removal_path/old.rs:13:9 + | +13| pub use self::a::Abc; + | ^^^^^^^^^^^^ From de5af8eae5983b607478e362965e5137a58eb4e5 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 15 Jul 2017 12:34:13 +0200 Subject: [PATCH 140/553] Pending test rewrite. --- src/semcheck/changes.rs | 76 +++++++++++++++++++++------------------- src/semcheck/traverse.rs | 18 +++++----- tests/examples.rs | 12 ++++--- 3 files changed, 55 insertions(+), 51 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index f53b2c8617ebd..74679b1babecb 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -72,6 +72,7 @@ impl PathChange { } } + /// Insert a new span addition or deletion. fn insert(&mut self, span: Span, add: bool) { if add { self.additions.insert(span); @@ -286,8 +287,7 @@ impl<'tcx> Change<'tcx> { } else { builder.span_note(span, &sub_msg,); } - // change.1 == None from here on. - } else if cat == Breaking { + } else if cat == Breaking { // change.1 == None from here on. builder.warn(&sub_msg); } else { builder.note(&sub_msg); @@ -321,9 +321,9 @@ impl<'tcx> Ord for Change<'tcx> { /// The total set of changes recorded for two crate versions. #[derive(Default)] pub struct ChangeSet<'tcx> { - /// The currently recorded path manipulations. + /// The currently recorded path changes. path_changes: HashMap, - /// The currently recorded changes. + /// The currently recorded regular changes. changes: HashMap>, /// The mapping of spans to changes, for ordering purposes. spans: BTreeMap, @@ -332,8 +332,18 @@ pub struct ChangeSet<'tcx> { } impl<'tcx> ChangeSet<'tcx> { - /// Add a new unary change entry for the given exports. - pub fn new_unary(&mut self, old: DefId, name: Symbol, def_span: Span, span: Span, add: bool) { + /// Add a new path addition for the given item. + pub fn new_path_addition(&mut self, old: DefId, name: Symbol, def_span: Span, span: Span) { + self.new_path(old, name, def_span, span, true); + } + + /// Add a new path removal for the given item. + pub fn new_path_removal(&mut self, old: DefId, name: Symbol, def_span: Span, span: Span) { + self.new_path(old, name, def_span, span, false); + } + + /// Add a new path change entry for the given item. + fn new_path(&mut self, old: DefId, name: Symbol, def_span: Span, span: Span, add: bool) { self.spans.insert(def_span, old); let change = self.path_changes @@ -349,7 +359,7 @@ impl<'tcx> ChangeSet<'tcx> { } } - /// Add a new binary change entry for the given exports. + /// Add a new binary change entry for the given items. pub fn new_binary(&mut self, old: DefId, name: Symbol, span: Span, output: bool) { let change = Change::new(name, span, output); @@ -372,8 +382,7 @@ impl<'tcx> ChangeSet<'tcx> { /// /// The expected `DefId` is obviously an *old* one. pub fn item_breaking(&self, old: DefId) -> bool { - // we only care about items that were present before, since only those can get breaking - // changes (additions don't count). + // we only care about items that were present in both versions. self.changes .get(&old) .map(|changes| changes.to_category() == Breaking) @@ -441,6 +450,7 @@ pub mod tests { } } + /* // we don't need this type elsewhere, so we define it here. #[derive(Clone, Debug)] pub enum UnaryChangeType { @@ -485,11 +495,11 @@ pub mod tests { UnaryChangeType::Addition => UnaryChange::Addition(export), UnaryChangeType::Removal => UnaryChange::Removal(export), } - } + } */ - pub type BinaryChange_ = (Span_, Span_); + pub type Change_ = (Span_, Span_); - fn build_binary_change(t: ChangeType, s1: Span, s2: Span) -> Change { + fn build_change(t: ChangeType, s1: Span, s2: Span) -> Change { let mut interner = Interner::new(); let mut change = Change::new(interner.intern("test"), s2, true); change.add(t, Some(s1)); @@ -498,7 +508,7 @@ pub mod tests { } quickcheck! { - /// The `Ord` instance of `Change` is transitive. + /* /// The `Ord` instance of `Change` is transitive. fn ord_uchange_transitive(c1: UnaryChange_, c2: UnaryChange_, c3: UnaryChange_) -> bool { let ch1 = build_unary_change(c1.0, c1.1.inner()); let ch2 = build_unary_change(c2.0, c2.1.inner()); @@ -519,14 +529,12 @@ pub mod tests { } res - } + } */ - fn ord_bchange_transitive(c1: BinaryChange_, c2: BinaryChange_, c3: BinaryChange_) - -> bool - { - let ch1 = build_binary_change(Unknown, c1.0.inner(), c1.1.inner()); - let ch2 = build_binary_change(Unknown, c2.0.inner(), c2.1.inner()); - let ch3 = build_binary_change(Unknown, c3.0.inner(), c3.1.inner()); + fn ord_change_transitive(c1: Change_, c2: Change_, c3: Change_) -> bool { + let ch1 = build_change(Unknown, c1.0.inner(), c1.1.inner()); + let ch2 = build_change(Unknown, c2.0.inner(), c2.1.inner()); + let ch3 = build_change(Unknown, c3.0.inner(), c3.1.inner()); let mut res = true; @@ -545,7 +553,7 @@ pub mod tests { res } - /// The maximal change category for a change set gets computed correctly. + /* /// The maximal change category for a change set gets computed correctly. fn max_uchange(changes: Vec) -> bool { let mut set = ChangeSet::default(); @@ -558,31 +566,27 @@ pub mod tests { } set.max == max - } + } */ - /// The maximal change category for a change set gets computed correctly. - fn max_bchange(changes: Vec) -> bool { + /* /// The maximal change category for a change set gets computed correctly. + fn max_change(changes: Vec) -> bool { let mut set = ChangeSet::default(); let max = changes.iter().map(|_| Unknown.to_category()).max().unwrap_or(Patch); for &(ref span1, ref span2) in changes.iter() { - let change = - build_binary_change(Unknown, - span1.clone().inner(), - span2.clone().inner()); + let change = build_change(Unknown, span1.clone().inner(), span2.clone().inner()); let did = DefId { krate: LOCAL_CRATE, index: CRATE_DEF_INDEX, }; - let key = ChangeKey::OldKey(did); - set.new_unary_change(Change::Binary(change), key); + // set.new_binary(change, did); } set.max == max - } + } */ - /// Difference in spans implies difference in `Change`s. + /* /// Difference in spans implies difference in `Change`s. fn uchange_span_neq(c1: UnaryChange_, c2: UnaryChange_) -> bool { let s1 = c1.1.inner(); let s2 = c2.1.inner(); @@ -595,16 +599,16 @@ pub mod tests { } else { true } - } + } */ /// Difference in spans implies difference in `Change`s. - fn bchange_span_neq(c1: BinaryChange_, c2: BinaryChange_) -> bool { + fn bchange_span_neq(c1: Change_, c2: Change_) -> bool { let s1 = c1.0.inner(); let s2 = c2.0.inner(); if s1 != s2 { - let ch1 = build_binary_change(Unknown, c1.1.inner(), s1); - let ch2 = build_binary_change(Unknown, c2.1.inner(), s2); + let ch1 = build_change(Unknown, c1.1.inner(), s1); + let ch2 = build_change(Unknown, c2.1.inner(), s2); ch1 != ch2 } else { diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index c0857675894b9..af8eeaafce0c4 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -202,21 +202,19 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, (Some(o), None) => { if old_vis == Public && cstore.visibility(o.def.def_id()) == Public { let o_did = o.def.def_id(); - changes.new_unary(o_did, - o.ident.name, - tcx.def_span(o_did), - o.span, - false); + changes.new_path_removal(o_did, + o.ident.name, + tcx.def_span(o_did), + o.span); } } (None, Some(n)) => { if new_vis == Public && cstore.visibility(n.def.def_id()) == Public { let n_did = n.def.def_id(); - changes.new_unary(n_did, - n.ident.name, - tcx.def_span(n_did), - n.span, - true); + changes.new_path_addition(n_did, + n.ident.name, + tcx.def_span(n_did), + n.span); } } (None, None) => unreachable!(), diff --git a/tests/examples.rs b/tests/examples.rs index 9a82b668083db..a543c338ce8ef 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -62,7 +62,7 @@ macro_rules! test { .env("RUST_LOG", "debug") .env("RUST_BACKTRACE", "full") .env("RUST_SEMVER_CRATE_VERSION", "1.0.0") - .stdin(Stdio::piped()) + .stdin(Stdio::null()) .stdout(out_pipe) .stderr(err_pipe) .status() @@ -78,10 +78,12 @@ macro_rules! test { .success(); } - Command::new("rm") - .args(&[old_rlib.to_str().unwrap(), new_rlib.to_str().unwrap()]) - .status() - .expect("could not run rm"); + if success { + Command::new("rm") + .args(&[old_rlib.to_str().unwrap(), new_rlib.to_str().unwrap()]) + .status() + .expect("could not run rm"); + } assert!(success, "an error occured"); } From ebef6f365a12ec84f1abb2a9fe268369faa255ab Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 15 Jul 2017 12:38:40 +0200 Subject: [PATCH 141/553] Ripped out the old testing approaches traces in the compiler driver. --- src/bin/rust_semverver.rs | 95 +++++++++++---------------------------- 1 file changed, 25 insertions(+), 70 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index c7fd0306ae68c..7137102066c1b 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -31,77 +31,32 @@ fn callback(state: &driver::CompileState, version: &str) { let tcx = state.tcx.unwrap(); let cstore = &tcx.sess.cstore; - let (old_did, new_did) = if std::env::var("RUST_SEMVERVER_TEST").is_err() { - // this is an actual program run - let cnums = cstore - .crates() - .iter() - .fold((None, None), |(o, n), crate_num| { - let name = cstore.crate_name(*crate_num); - if name == "old" { - (Some(*crate_num), n) - } else if name == "new" { - (o, Some(*crate_num)) - } else { - (o, n) - } - }); - if let (Some(c0), Some(c1)) = cnums { - (DefId { - krate: c0, - index: CRATE_DEF_INDEX, - }, - DefId { - krate: c1, - index: CRATE_DEF_INDEX, - }) - } else { - tcx.sess.err("could not find crate `old` and/or `new`"); - return; - } - } else { - // we are testing, so just fetch the *modules* `old` and `new` from a crate `oldandnew` - let cnum = cstore - .crates() - .iter() - .fold(None, - |k, crate_num| if cstore.crate_name(*crate_num) == "oldandnew" { - Some(*crate_num) - } else { - k - }); - - let mod_did = if let Some(c) = cnum { - DefId { - krate: c, - index: CRATE_DEF_INDEX, + let cnums = cstore + .crates() + .iter() + .fold((None, None), |(o, n), crate_num| { + let name = cstore.crate_name(*crate_num); + if name == "old" { + (Some(*crate_num), n) + } else if name == "new" { + (o, Some(*crate_num)) + } else { + (o, n) } - } else { - tcx.sess.err("could not find crate `oldandnew`"); - return; - }; - - let mut children = cstore.item_children(mod_did, tcx.sess); - - let dids = children - .drain(..) - .fold((None, None), |(o, n), child| { - let child_name = String::from(&*child.ident.name.as_str()); - if child_name == "old" { - (Some(child.def.def_id()), n) - } else if child_name == "new" { - (o, Some(child.def.def_id())) - } else { - (o, n) - } - }); - - if let (Some(o), Some(n)) = dids { - (o, n) - } else { - tcx.sess.err("could not find module `new` and/or `old` in crate `oldandnew`"); - return; - } + }); + + let (old_did, new_did) = if let (Some(c0), Some(c1)) = cnums { + (DefId { + krate: c0, + index: CRATE_DEF_INDEX, + }, + DefId { + krate: c1, + index: CRATE_DEF_INDEX, + }) + } else { + tcx.sess.err("could not find crate `old` and/or `new`"); + return; }; let changes = run_analysis(tcx, old_did, new_did); From 3faa4b78294bfd1e69ae54f811a8589ce1ad8f8b Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 15 Jul 2017 12:50:39 +0200 Subject: [PATCH 142/553] Improved debug scripts. --- tests/debug.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tests/debug.rs b/tests/debug.rs index 5ff84fcecbd01..ec0107aede8d6 100644 --- a/tests/debug.rs +++ b/tests/debug.rs @@ -25,9 +25,15 @@ if [ "$1" = "-s" ]; then shift arg_str="set args --crate-type=lib $(cargo semver "$@") tests/helper/test.rs" else - rustc --crate-type=lib -o libold.rlib "$1/old.rs" - rustc --crate-type=lib -o libnew.rlib "$1/new.rs" - arg_str="set args --crate-type=lib --extern old=libold.rlib --extern new=libnew.rlib tests/helper/test.rs" + 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 @@ -36,7 +42,8 @@ src_str="set substitute-path /checkout $(rustc --print sysroot)/lib/rustlib/src/ rust-gdb ./target/debug/rust-semverver -iex "$arg_str" -iex "$src_str" -rm lib*.rlib -"#, path); +if [ $del = 1 ]; then + rm "$1/lib*.rlib" +fi"#, path); } } From 61dbf88b6b45ea0d8b48f7171b3a1cea2d0daea4 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 16 Jul 2017 13:00:42 +0200 Subject: [PATCH 143/553] Fixed path confusion. We now represent changes in a simpler and more robust manner. Also, a few problems cuased by the previous approach have been resolved. For instance, struct constructors are blacklisted from all toplevel analysis facilities. All in all, the spans printed for each change item became a bit more intuitive. --- src/semcheck/changes.rs | 51 ++++++++++------- src/semcheck/traverse.rs | 38 ++++++++++--- tests/cases/addition/stdout | 26 +++++---- tests/cases/addition_path/new.rs | 8 +++ tests/cases/addition_path/stdout | 12 ++++ tests/cases/kind_change/stdout | 12 ---- tests/cases/removal/stdout | 30 +++++----- tests/cases/removal_path/new.rs | 8 +++ tests/cases/removal_path/stdout | 42 ++------------ tests/examples.rs | 98 +++++++++++++++++--------------- 10 files changed, 172 insertions(+), 153 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 74679b1babecb..2892b0c9f7536 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -332,39 +332,48 @@ pub struct ChangeSet<'tcx> { } impl<'tcx> ChangeSet<'tcx> { - /// Add a new path addition for the given item. - pub fn new_path_addition(&mut self, old: DefId, name: Symbol, def_span: Span, span: Span) { - self.new_path(old, name, def_span, span, true); + /// Add a new path change entry for the given item. + pub fn new_path(&mut self, old: DefId, name: Symbol, def_span: Span) { + if !self.spans.contains_key(&def_span) { + self.spans.insert(def_span, old); + self.path_changes + .entry(old) + .or_insert_with(|| PathChange::new(name, def_span)); + } } - /// Add a new path removal for the given item. - pub fn new_path_removal(&mut self, old: DefId, name: Symbol, def_span: Span, span: Span) { - self.new_path(old, name, def_span, span, false); + pub fn add_path_addition(&mut self, old: DefId, span: Span) { + self.add_path(old, span, true); } - /// Add a new path change entry for the given item. - fn new_path(&mut self, old: DefId, name: Symbol, def_span: Span, span: Span, add: bool) { - self.spans.insert(def_span, old); - - let change = self.path_changes - .entry(old) - .or_insert_with(|| PathChange::new(name, def_span)); - - change.insert(span, add); + pub fn add_path_removal(&mut self, old: DefId, span: Span) { + self.add_path(old, span, false); + } - let cat = change.to_category(); + /// 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.clone(); } + + self.path_changes.get_mut(&old).unwrap().insert(span, add); } /// Add a new binary change entry for the given items. - pub fn new_binary(&mut self, old: DefId, name: Symbol, span: Span, output: bool) { - let change = Change::new(name, span, output); - - self.spans.insert(*change.new_span(), old); - self.changes.insert(old, change); + pub fn new_binary(&mut self, + old_did: DefId, + new_did: DefId, + name: Symbol, + old_span: Span, + new_span: Span, + output: bool) { + let change = Change::new(name, new_span, output); + + self.spans.insert(old_span, old_did); + self.spans.insert(new_span, new_did); + self.changes.insert(old_did, change); } /// Add a new binary change to an already existing entry. diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index af8eeaafce0c4..82784cd6a6edf 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -99,8 +99,10 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, if o_vis != n_vis { changes.new_binary(o_did, + n_did, o.ident.name, tcx.def_span(o_did), + tcx.def_span(n_did), true); if o_vis == Public && n_vis != Public { @@ -113,6 +115,11 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, mod_queue.push_back((o_did, n_did, o_vis, n_vis)); } } else if id_mapping.add_export(o.def, n.def) { + // struct constructors are weird/hard - let's go shopping! + if let (StructCtor(_, _), StructCtor(_, _)) = (o.def, n.def) { + continue; + } + let o_def_id = o.def.def_id(); let n_def_id = n.def.def_id(); let o_vis = if old_vis == Public { @@ -127,7 +134,12 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, }; let output = o_vis == Public || n_vis == Public; - changes.new_binary(o.def.def_id(), o.ident.name, n.span, output); + changes.new_binary(o.def.def_id(), + n.def.def_id(), + o.ident.name, + tcx.def_span(o.def.def_id()), + tcx.def_span(n.def.def_id()), + output); if o_vis == Public && n_vis != Public { changes.add_binary(ItemMadePrivate, o_def_id, None); @@ -200,21 +212,27 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, } } (Some(o), None) => { + // struct constructors are weird/hard - let's go shopping! + if let StructCtor(_, _) = o.def { + continue; + } + if old_vis == Public && cstore.visibility(o.def.def_id()) == Public { let o_did = o.def.def_id(); - changes.new_path_removal(o_did, - o.ident.name, - tcx.def_span(o_did), - o.span); + changes.new_path(o_did, o.ident.name, tcx.def_span(o_did)); + changes.add_path_removal(o_did, o.span); } } (None, Some(n)) => { + // struct constructors are weird/hard - let's go shopping! + if let StructCtor(_, _) = n.def { + continue; + } + if new_vis == Public && cstore.visibility(n.def.def_id()) == Public { let n_did = n.def.def_id(); - changes.new_path_addition(n_did, - n.ident.name, - tcx.def_span(n_did), - n.span); + changes.new_path(n_did, n.ident.name, tcx.def_span(n_did)); + changes.add_path_addition(n_did, n.span); } } (None, None) => unreachable!(), @@ -400,7 +418,9 @@ fn diff_traits(changes: &mut ChangeSet, (Some((old_def, old_item)), Some((new_def, new_item))) => { id_mapping.add_trait_item(old_def, new_def); changes.new_binary(old_def.def_id(), + new_def.def_id(), *name, + tcx.def_span(old_def.def_id()), tcx.def_span(new_def.def_id()), true); diff_method(changes, tcx, old_item, new_item); diff --git a/tests/cases/addition/stdout b/tests/cases/addition/stdout index 20dedfeda08f6..217032fd7d85c 100644 --- a/tests/cases/addition/stdout +++ b/tests/cases/addition/stdout @@ -1,12 +1,22 @@ version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 -warning: TechnicallyBreaking changes in `b` - --> $REPO_PATH/tests/cases/addition/old.rs:6:1 +warning: TechnicallyBreaking changes in `Bcd` + --> $REPO_PATH/tests/cases/addition/new.rs:3:1 | -6 | } - | ^ +3 | pub struct Bcd; + | ^^^^^^^^^^^^^^^ | = note: TechnicallyBreaking (ItemMadePublic) +warning: TechnicallyBreaking changes in `b` + --> $REPO_PATH/tests/cases/addition/new.rs:10:5 + | +10 | / #[allow(dead_code)] +11 | | pub struct Cde; +12 | | } + | |_^ + | + = note: TechnicallyBreaking (ItemMadePublic) + warning: Path changes to `Abc` --> $REPO_PATH/tests/cases/addition/new.rs:1:1 | @@ -19,14 +29,6 @@ note: TechnicallyBreaking: added path 1 | pub struct Abc; | ^^^^^^^^^^^^^^^ -warning: TechnicallyBreaking changes in `Bcd` - --> $REPO_PATH/tests/cases/addition/new.rs:3:1 - | -3 | pub struct Bcd; - | ^^^^^^^^^^^^^^^ - | - = note: TechnicallyBreaking (ItemMadePublic) - warning: Path changes to `a` --> $REPO_PATH/tests/cases/addition/new.rs:7:1 | diff --git a/tests/cases/addition_path/new.rs b/tests/cases/addition_path/new.rs index 25228c33a0140..2c49d124b6471 100644 --- a/tests/cases/addition_path/new.rs +++ b/tests/cases/addition_path/new.rs @@ -11,3 +11,11 @@ pub mod c { } pub use self::a::Abc; + +pub mod d { + +} + +mod e { + +} diff --git a/tests/cases/addition_path/stdout b/tests/cases/addition_path/stdout index 43175753d7666..54548cbac732a 100644 --- a/tests/cases/addition_path/stdout +++ b/tests/cases/addition_path/stdout @@ -21,3 +21,15 @@ note: TechnicallyBreaking: added path 13| pub use self::a::Abc; | ^^^^^^^^^^^^ +warning: Path changes to `d` + --> $REPO_PATH/tests/cases/addition_path/new.rs:17:1 + | +17 | } + | ^ + | +note: TechnicallyBreaking: added path + --> $REPO_PATH/tests/cases/addition_path/new.rs:17:1 + | +17 | } + | ^ + diff --git a/tests/cases/kind_change/stdout b/tests/cases/kind_change/stdout index 0dc76711a3e65..0c93d057cc336 100644 --- a/tests/cases/kind_change/stdout +++ b/tests/cases/kind_change/stdout @@ -1,16 +1,4 @@ version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Path changes to `Abc` - --> $REPO_PATH/tests/cases/kind_change/old.rs:1:1 - | -1 | pub struct Abc; - | ^^^^^^^^^^^^^^^ - | -warning: Breaking: removed path - --> $REPO_PATH/tests/cases/kind_change/old.rs:1:1 - | -1 | pub struct Abc; - | ^^^^^^^^^^^^^^^ - warning: Breaking changes in `Abc` --> $REPO_PATH/tests/cases/kind_change/new.rs:1:1 | diff --git a/tests/cases/removal/stdout b/tests/cases/removal/stdout index 40245f545bb08..1098a3d743c87 100644 --- a/tests/cases/removal/stdout +++ b/tests/cases/removal/stdout @@ -11,6 +11,14 @@ warning: Breaking: removed path 1 | pub struct Abc; | ^^^^^^^^^^^^^^^ +warning: Breaking changes in `Bcd` + --> $REPO_PATH/tests/cases/removal/new.rs:2:1 + | +2 | struct Bcd; + | ^^^^^^^^^^^ + | + = warning: Breaking (ItemMadePrivate) + warning: Path changes to `a` --> $REPO_PATH/tests/cases/removal/old.rs:7:1 | @@ -24,14 +32,12 @@ warning: Breaking: removed path | ^ warning: Breaking changes in `b` - --> $REPO_PATH/tests/cases/removal/old.rs:10:5 - | -10 | / #[allow(dead_code)] -11 | | pub struct Cde; -12 | | } - | |_^ - | - = warning: Breaking (ItemMadePrivate) + --> $REPO_PATH/tests/cases/removal/new.rs:6:1 + | +6 | } + | ^ + | + = warning: Breaking (ItemMadePrivate) warning: Path changes to `Cde` --> $REPO_PATH/tests/cases/removal/old.rs:11:5 @@ -45,11 +51,3 @@ warning: Breaking: removed path 11 | pub struct Cde; | ^^^^^^^^^^^^^^^ -warning: Breaking changes in `Bcd` - --> $REPO_PATH/tests/cases/removal/new.rs:2:1 - | -2 | struct Bcd; - | ^^^^^^^^^^^ - | - = warning: Breaking (ItemMadePrivate) - diff --git a/tests/cases/removal_path/new.rs b/tests/cases/removal_path/new.rs index 876fd66a58174..dfb2d9265aa23 100644 --- a/tests/cases/removal_path/new.rs +++ b/tests/cases/removal_path/new.rs @@ -1,3 +1,11 @@ pub mod a { pub struct Abc; } + +pub mod b { + +} + +pub mod c { + +} diff --git a/tests/cases/removal_path/stdout b/tests/cases/removal_path/stdout index 4aa496f80824f..83a6e8a5e89c9 100644 --- a/tests/cases/removal_path/stdout +++ b/tests/cases/removal_path/stdout @@ -6,45 +6,15 @@ warning: Path changes to `Abc` | ^^^^^^^^^^^^^^^ | warning: Breaking: removed path - --> $REPO_PATH/tests/cases/removal_path/old.rs:13:9 - | -13| pub use self::a::Abc; - | ^^^^^^^^^^^^ - -warning: Path changes to `b` - --> $REPO_PATH/tests/cases/removal_path/old.rs:6:5 - | -6 | / pub use a::*; -7 | | } - | |_^ + --> $REPO_PATH/tests/cases/removal_path/old.rs:6:13 | +6 | pub use a::*; + | ^^^^^ warning: Breaking: removed path - --> $REPO_PATH/tests/cases/removal_path/old.rs:6:5 - | -6 | / pub use a::*; -7 | | } - | |_^ - -warning: Path changes to `c` - --> $REPO_PATH/tests/cases/removal_path/old.rs:10:5 - | -10 | / pub use a::Abc; -11 | | } - | |_^ - | -warning: Breaking: removed path - --> $REPO_PATH/tests/cases/removal_path/old.rs:10:5 - | -10 | / pub use a::Abc; -11 | | } - | |_^ - -warning: Path changes to `Abc` - --> $REPO_PATH/tests/cases/removal_path/old.rs:2:5 - | -2 | pub struct Abc; - | ^^^^^^^^^^^^^^^ + --> $REPO_PATH/tests/cases/removal_path/old.rs:10:13 | +10| pub use a::Abc; + | ^^^^^^ warning: Breaking: removed path --> $REPO_PATH/tests/cases/removal_path/old.rs:13:9 | diff --git a/tests/examples.rs b/tests/examples.rs index a543c338ce8ef..483f9c58d63a7 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -30,6 +30,8 @@ macro_rules! test { .expect("could not run rustc") .success(); + assert!(success, "couldn't compile old"); + success &= Command::new("rustc") .args(&["--crate-type=lib", "-o", new_rlib.to_str().unwrap()]) .arg(path.join("new.rs")) @@ -39,53 +41,55 @@ macro_rules! test { .expect("could not run rustc") .success(); - if success { - let mut sed_child = Command::new("sed") - .arg(&subst) - .stdin(Stdio::piped()) - .stdout(stdout) - .spawn() - .expect("could not run sed"); - - let (err_pipe, out_pipe) = if let Some(ref stdin) = sed_child.stdin { - let fd = stdin.as_raw_fd(); - unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } - } else { - panic!("could not pipe to sed"); - }; - - success &= Command::new("./target/debug/rust-semverver") - .args(&["--crate-type=lib", - "--extern", &format!("old={}", old_rlib.to_str().unwrap()), - "--extern", &format!("new={}", new_rlib.to_str().unwrap()), - "tests/helper/test.rs"]) - .env("RUST_LOG", "debug") - .env("RUST_BACKTRACE", "full") - .env("RUST_SEMVER_CRATE_VERSION", "1.0.0") - .stdin(Stdio::null()) - .stdout(out_pipe) - .stderr(err_pipe) - .status() - .expect("could not run rust-semverver") - .success(); - - success &= sed_child.wait().expect("could not wait for sed child").success(); - - success &= Command::new("git") - .args(&["diff", "--quiet", out_file.to_str().unwrap()]) - .status() - .expect("could not run git diff") - .success(); - } - - if success { - Command::new("rm") - .args(&[old_rlib.to_str().unwrap(), new_rlib.to_str().unwrap()]) - .status() - .expect("could not run rm"); - } - - assert!(success, "an error occured"); + assert!(success, "couldn't compile new"); + + let mut sed_child = Command::new("sed") + .arg(&subst) + .stdin(Stdio::piped()) + .stdout(stdout) + .spawn() + .expect("could not run sed"); + + let (err_pipe, out_pipe) = if let Some(ref stdin) = sed_child.stdin { + let fd = stdin.as_raw_fd(); + unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } + } else { + panic!("could not pipe to sed"); + }; + + success &= Command::new("./target/debug/rust-semverver") + .args(&["--crate-type=lib", + "--extern", &format!("old={}", old_rlib.to_str().unwrap()), + "--extern", &format!("new={}", new_rlib.to_str().unwrap()), + "tests/helper/test.rs"]) + .env("RUST_LOG", "debug") + .env("RUST_BACKTRACE", "full") + .env("RUST_SEMVER_CRATE_VERSION", "1.0.0") + .stdin(Stdio::null()) + .stdout(out_pipe) + .stderr(err_pipe) + .status() + .expect("could not run rust-semverver") + .success(); + + assert!(success, "rust-semverver"); + + success &= sed_child.wait().expect("could not wait for sed child").success(); + + assert!(success, "sed"); + + success &= Command::new("git") + .args(&["diff", "--quiet", out_file.to_str().unwrap()]) + .status() + .expect("could not run git diff") + .success(); + + assert!(success, "git"); + + Command::new("rm") + .args(&[old_rlib.to_str().unwrap(), new_rlib.to_str().unwrap()]) + .status() + .expect("could not run rm"); } } } From c81e6c21bcbe2073184e14bb3a761ad5151f5482 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 16 Jul 2017 13:07:14 +0200 Subject: [PATCH 144/553] Added a mix test. --- tests/cases/mix/new.rs | 6 ++++++ tests/cases/mix/old.rs | 6 ++++++ tests/cases/mix/stdout | 41 +++++++++++++++++++++++++++++++++++++++++ tests/examples.rs | 1 + 4 files changed, 54 insertions(+) create mode 100644 tests/cases/mix/new.rs create mode 100644 tests/cases/mix/old.rs create mode 100644 tests/cases/mix/stdout diff --git a/tests/cases/mix/new.rs b/tests/cases/mix/new.rs new file mode 100644 index 0000000000000..c618839fe00ce --- /dev/null +++ b/tests/cases/mix/new.rs @@ -0,0 +1,6 @@ +pub mod a { + pub enum Abc {} + pub struct Def; +} + +pub use self::a::Def; diff --git a/tests/cases/mix/old.rs b/tests/cases/mix/old.rs new file mode 100644 index 0000000000000..fedaf4a01dab6 --- /dev/null +++ b/tests/cases/mix/old.rs @@ -0,0 +1,6 @@ +pub mod a { + pub struct Abc; + pub enum Def {} +} + +pub use self::a::Abc; diff --git a/tests/cases/mix/stdout b/tests/cases/mix/stdout new file mode 100644 index 0000000000000..554488bf907e2 --- /dev/null +++ b/tests/cases/mix/stdout @@ -0,0 +1,41 @@ +version bump: 1.0.0 -> (Breaking) -> 2.0.0 +warning: Path changes to `Abc` + --> $REPO_PATH/tests/cases/mix/old.rs:2:5 + | +2 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + | +warning: Breaking: removed path + --> $REPO_PATH/tests/cases/mix/old.rs:6:9 + | +6 | pub use self::a::Abc; + | ^^^^^^^^^^^^ + +warning: Breaking changes in `Abc` + --> $REPO_PATH/tests/cases/mix/new.rs:2:5 + | +2 | pub enum Abc {} + | ^^^^^^^^^^^^^^^ + | + = warning: Breaking (KindDifference) + +warning: Breaking changes in `Def` + --> $REPO_PATH/tests/cases/mix/new.rs:3:5 + | +3 | pub struct Def; + | ^^^^^^^^^^^^^^^ + | + = warning: Breaking (KindDifference) + +warning: Path changes to `Def` + --> $REPO_PATH/tests/cases/mix/new.rs:3:5 + | +3 | pub struct Def; + | ^^^^^^^^^^^^^^^ + | +note: TechnicallyBreaking: added path + --> $REPO_PATH/tests/cases/mix/new.rs:6:9 + | +6 | pub use self::a::Def; + | ^^^^^^^^^^^^ + diff --git a/tests/examples.rs b/tests/examples.rs index 483f9c58d63a7..5fad9695d52a3 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -101,6 +101,7 @@ test!(func, "tests/cases/func"); test!(infer, "tests/cases/infer"); test!(kind_change, "tests/cases/kind_change"); test!(macros, "tests/cases/macros"); +test!(mix, "tests/cases/mix"); test!(pathologic_paths, "tests/cases/pathologic_paths"); test!(pub_use, "tests/cases/pub_use"); test!(removal, "tests/cases/removal"); From 82ecc020ab2376d9b09bae0d1946a5060ca402cc Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 16 Jul 2017 14:55:22 +0200 Subject: [PATCH 145/553] Nicer error reporting for #3. --- src/semcheck/changes.rs | 112 ++++++++++++++++++++++------ src/semcheck/traverse.rs | 44 +++++------ tests/cases/addition/stdout | 22 +++--- tests/cases/addition_path/stdout | 14 ++-- tests/cases/enums/stdout | 34 ++++----- tests/cases/func/stdout | 34 ++++----- tests/cases/infer/stdout | 2 +- tests/cases/kind_change/stdout | 6 +- tests/cases/macros/stdout | 2 +- tests/cases/mix/new.rs | 4 + tests/cases/mix/old.rs | 4 + tests/cases/mix/stdout | 38 ++++++---- tests/cases/pathologic_paths/stdout | 10 +-- tests/cases/pub_use/stdout | 2 +- tests/cases/removal/stdout | 22 +++--- tests/cases/removal_path/stdout | 10 +-- tests/cases/structs/stdout | 30 ++++---- tests/cases/traits/stdout | 24 +++--- tests/cases/ty_alias/stdout | 32 ++++---- 19 files changed, 268 insertions(+), 178 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 2892b0c9f7536..cacc1d4be1aa3 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -1,10 +1,9 @@ //! Change representation. //! //! This module provides data types to represent, store and record changes found in various -//! analysis passes. We distinguish between "unary" and "binary" changes, depending on whether -//! there is a single item affected in one crate version or a matching item in the other crate -//! version as well. The ordering of changes and output generation is performed using these data -//! structures, too. +//! 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 these data structures, too. use rustc::hir::def_id::DefId; use rustc::session::Session; @@ -14,6 +13,7 @@ use semver::Version; use std::collections::{BTreeSet, BTreeMap, HashMap}; use std::cmp::Ordering; +use std::fmt; use syntax::symbol::Symbol; @@ -46,6 +46,19 @@ impl<'a> Default for ChangeCategory { } } +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) + } +} + /// A change record of newly introduced or removed paths to an item. /// /// It is important to note that the `Eq` and `Ord` instances are constucted to only @@ -103,15 +116,15 @@ impl PathChange { return; } - let msg = format!("Path changes to `{}`", self.name); + let msg = format!("path changes to `{}`", self.name); let mut builder = session.struct_span_warn(self.def_span, &msg); for removed_span in &self.removals { - builder.span_warn(*removed_span, "Breaking: removed path"); + builder.span_warn(*removed_span, "removed path (breaking)"); } for added_span in &self.additions { - builder.span_note(*added_span, "TechnicallyBreaking: added path"); + builder.span_note(*added_span, "added path (technically breaking)"); } builder.emit(); @@ -213,6 +226,61 @@ impl<'tcx> ChangeType<'tcx> { } } +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", + 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 } => + "public variant field added to variant with no private fields", + VariantFieldAdded { public: true, total_public: false } => + "public variant field added to variant with private fields", + VariantFieldAdded { public: false, total_public: true } => + "variant field added to variant with no private fields", + VariantFieldAdded { public: false, total_public: false } => + "variant field added to variant with private fields", + VariantFieldRemoved { public: true, total_public: true } => + "public variant field removed from variant with no private fields", + VariantFieldRemoved { public: true, total_public: false } => + "public variant field removed from variant with private fields", + VariantFieldRemoved { public: false, total_public: true } => + "variant field removed from variant with no private fields", + VariantFieldRemoved { public: false, total_public: false } => + "variant field removed from variant with private fields", + VariantStyleChanged { now_struct: true, total_private: true } => + "variant with no public fields changed to a struct variant", + VariantStyleChanged { now_struct: true, total_private: false } => + "variant changed to a struct variant", + VariantStyleChanged { now_struct: false, total_private: true } => + "variant with no public fields changed to a tuple variant", + VariantStyleChanged { now_struct: false, total_private: false } => + "variant changed to a tuple variant", + 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 } => "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), + Unknown => "unknown change", + }; + write!(f, "{}", desc) + } +} + /// A change record of an item kept between versions. /// /// It is important to note that the `Eq` and `Ord` instances are constucted to only @@ -275,12 +343,12 @@ impl<'tcx> Change<'tcx> { return; } - let msg = format!("{:?} changes in `{}`", self.max, self.ident()); + let msg = format!("{} changes in `{}`", self.max, self.ident()); let mut builder = session.struct_span_warn(self.new_span, &msg); for change in &self.changes { let cat = change.0.to_category(); - let sub_msg = format!("{:?} ({:?})", cat, change.0); + let sub_msg = format!("{} ({})", change.0, cat); if let Some(span) = change.1 { if cat == Breaking { builder.span_warn(span, &sub_msg); @@ -334,18 +402,20 @@ pub struct ChangeSet<'tcx> { impl<'tcx> ChangeSet<'tcx> { /// Add a new path change entry for the given item. pub fn new_path(&mut self, old: DefId, name: Symbol, def_span: Span) { - if !self.spans.contains_key(&def_span) { - self.spans.insert(def_span, old); - self.path_changes - .entry(old) - .or_insert_with(|| PathChange::new(name, def_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); } @@ -361,8 +431,8 @@ impl<'tcx> ChangeSet<'tcx> { self.path_changes.get_mut(&old).unwrap().insert(span, add); } - /// Add a new binary change entry for the given items. - pub fn new_binary(&mut self, + /// Add a new change entry for the given items. + pub fn new_change(&mut self, old_did: DefId, new_did: DefId, name: Symbol, @@ -376,8 +446,8 @@ impl<'tcx> ChangeSet<'tcx> { self.changes.insert(old_did, change); } - /// Add a new binary change to an already existing entry. - pub fn add_binary(&mut self, type_: ChangeType<'tcx>, old: DefId, span: Option) { + /// Add a new change to an already existing entry. + pub fn add_change(&mut self, type_: ChangeType<'tcx>, old: DefId, span: Option) { let cat = type_.to_category(); if cat > self.max { @@ -407,9 +477,9 @@ impl<'tcx> ChangeSet<'tcx> { Breaking => new_version.increment_major(), } - println!("version bump: {} -> ({:?}) -> {}", version, self.max, new_version); + println!("version bump: {} -> ({}) -> {}", version, self.max, new_version); } else { - println!("max change: {} (could not parse) -> {:?}", version, self.max); + println!("max change: {}, could not parse {}", self.max, version); } for key in self.spans.values() { diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 82784cd6a6edf..538f256e20199 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -98,7 +98,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, }; if o_vis != n_vis { - changes.new_binary(o_did, + changes.new_change(o_did, n_did, o.ident.name, tcx.def_span(o_did), @@ -106,9 +106,9 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, true); if o_vis == Public && n_vis != Public { - changes.add_binary(ItemMadePrivate, o_did, None); + changes.add_change(ItemMadePrivate, o_did, None); } else if o_vis != Public && n_vis == Public { - changes.add_binary(ItemMadePublic, o_did, None); + changes.add_change(ItemMadePublic, o_did, None); } } @@ -134,7 +134,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, }; let output = o_vis == Public || n_vis == Public; - changes.new_binary(o.def.def_id(), + changes.new_change(o.def.def_id(), n.def.def_id(), o.ident.name, tcx.def_span(o.def.def_id()), @@ -142,9 +142,9 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, output); if o_vis == Public && n_vis != Public { - changes.add_binary(ItemMadePrivate, o_def_id, None); + changes.add_change(ItemMadePrivate, o_def_id, None); } else if o_vis != Public && n_vis == Public { - changes.add_binary(ItemMadePublic, o_def_id, None); + changes.add_change(ItemMadePublic, o_def_id, None); } match (o.def, n.def) { @@ -206,7 +206,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, }, // non-matching item pair - register the difference and abort _ => { - changes.add_binary(KindDifference, o_def_id, None); + changes.add_change(KindDifference, o_def_id, None); }, } } @@ -250,14 +250,14 @@ fn diff_fn(changes: &mut ChangeSet, tcx: TyCtxt, old: Def, new: Def) { let new_const = tcx.is_const_fn(new_def_id); if old_const != new_const { - changes.add_binary(FnConstChanged { now_const: new_const }, old_def_id, None); + changes.add_change(FnConstChanged { now_const: new_const }, old_def_id, None); } } /// Given two method items, perform structural checks. fn diff_method(changes: &mut ChangeSet, tcx: TyCtxt, old: AssociatedItem, new: AssociatedItem) { if old.method_has_self_argument != new.method_has_self_argument { - changes.add_binary(MethodSelfChanged { now_self: new.method_has_self_argument }, + changes.add_change(MethodSelfChanged { now_self: new.method_has_self_argument }, old.def_id, None); } @@ -326,7 +326,7 @@ fn diff_adts(changes: &mut ChangeSet, now_struct: new.ctor_kind == CtorKind::Fictive, total_private: total_private, }; - changes.add_binary(c, old_def_id, Some(tcx.def_span(new.did))); + changes.add_change(c, old_def_id, Some(tcx.def_span(new.did))); continue; } @@ -337,11 +337,11 @@ fn diff_adts(changes: &mut ChangeSet, id_mapping.add_subitem(old_def_id, o.did, n.did); if o.vis != Public && n.vis == Public { - changes.add_binary(ItemMadePublic, + changes.add_change(ItemMadePublic, old_def_id, Some(tcx.def_span(n.did))); } else if o.vis == Public && n.vis != Public { - changes.add_binary(ItemMadePrivate, + changes.add_change(ItemMadePrivate, old_def_id, Some(tcx.def_span(n.did))); } @@ -351,14 +351,14 @@ fn diff_adts(changes: &mut ChangeSet, public: o.vis == Public, total_public: total_public }; - changes.add_binary(c, old_def_id, Some(tcx.def_span(o.did))); + changes.add_change(c, old_def_id, Some(tcx.def_span(o.did))); }, (None, Some(n)) => { let c = VariantFieldAdded { public: n.vis == Public, total_public: total_public }; - changes.add_binary(c, old_def_id, Some(tcx.def_span(n.did))); + changes.add_change(c, old_def_id, Some(tcx.def_span(n.did))); }, (None, None) => unreachable!(), } @@ -367,10 +367,10 @@ fn diff_adts(changes: &mut ChangeSet, fields.clear(); }, (Some(old), None) => { - changes.add_binary(VariantRemoved, old_def_id, Some(tcx.def_span(old.did))); + changes.add_change(VariantRemoved, old_def_id, Some(tcx.def_span(old.did))); }, (None, Some(new)) => { - changes.add_binary(VariantAdded, old_def_id, Some(tcx.def_span(new.did))); + changes.add_change(VariantAdded, old_def_id, Some(tcx.def_span(new.did))); }, (None, None) => unreachable!(), } @@ -396,7 +396,7 @@ fn diff_traits(changes: &mut ChangeSet, now_unsafe: new_unsafety == Unsafe, }; - changes.add_binary(change_type, old, None); + changes.add_change(change_type, old, None); } let mut items = BTreeMap::new(); @@ -417,7 +417,7 @@ fn diff_traits(changes: &mut ChangeSet, match *item_pair { (Some((old_def, old_item)), Some((new_def, new_item))) => { id_mapping.add_trait_item(old_def, new_def); - changes.new_binary(old_def.def_id(), + changes.new_change(old_def.def_id(), new_def.def_id(), *name, tcx.def_span(old_def.def_id()), @@ -429,13 +429,13 @@ fn diff_traits(changes: &mut ChangeSet, let change_type = TraitItemRemoved { defaulted: old_item.defaultness.has_value(), }; - changes.add_binary(change_type, old, Some(tcx.def_span(old_item.def_id))); + changes.add_change(change_type, old, Some(tcx.def_span(old_item.def_id))); }, (None, Some((_, new_item))) => { let change_type = TraitItemAdded { defaulted: new_item.defaultness.has_value(), }; - changes.add_binary(change_type, old, Some(tcx.def_span(new_item.def_id))); + changes.add_change(change_type, old, Some(tcx.def_span(new_item.def_id))); }, (None, None) => unreachable!(), } @@ -496,7 +496,7 @@ fn diff_generics(changes: &mut ChangeSet, } for change_type in found.drain(..) { - changes.add_binary(change_type, old, None); + changes.add_change(change_type, old, None); } } @@ -610,7 +610,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, Err(err) => panic!("err: {:?}", err), }; - changes.add_binary(TypeChanged { error: err.lift_to_tcx(tcx).unwrap() }, + changes.add_change(TypeChanged { error: err.lift_to_tcx(tcx).unwrap() }, old_def_id, None); } diff --git a/tests/cases/addition/stdout b/tests/cases/addition/stdout index 217032fd7d85c..9fcd03ffbc36d 100644 --- a/tests/cases/addition/stdout +++ b/tests/cases/addition/stdout @@ -1,13 +1,13 @@ -version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 -warning: TechnicallyBreaking changes in `Bcd` +version bump: 1.0.0 -> (technically breaking) -> 1.1.0 +warning: technically breaking changes in `Bcd` --> $REPO_PATH/tests/cases/addition/new.rs:3:1 | 3 | pub struct Bcd; | ^^^^^^^^^^^^^^^ | - = note: TechnicallyBreaking (ItemMadePublic) + = note: item made public (technically breaking) -warning: TechnicallyBreaking changes in `b` +warning: technically breaking changes in `b` --> $REPO_PATH/tests/cases/addition/new.rs:10:5 | 10 | / #[allow(dead_code)] @@ -15,39 +15,39 @@ warning: TechnicallyBreaking changes in `b` 12 | | } | |_^ | - = note: TechnicallyBreaking (ItemMadePublic) + = note: item made public (technically breaking) -warning: Path changes to `Abc` +warning: path changes to `Abc` --> $REPO_PATH/tests/cases/addition/new.rs:1:1 | 1 | pub struct Abc; | ^^^^^^^^^^^^^^^ | -note: TechnicallyBreaking: added path +note: added path (technically breaking) --> $REPO_PATH/tests/cases/addition/new.rs:1:1 | 1 | pub struct Abc; | ^^^^^^^^^^^^^^^ -warning: Path changes to `a` +warning: path changes to `a` --> $REPO_PATH/tests/cases/addition/new.rs:7:1 | 7 | } | ^ | -note: TechnicallyBreaking: added path +note: added path (technically breaking) --> $REPO_PATH/tests/cases/addition/new.rs:7:1 | 7 | } | ^ -warning: Path changes to `Cde` +warning: path changes to `Cde` --> $REPO_PATH/tests/cases/addition/new.rs:11:5 | 11 | pub struct Cde; | ^^^^^^^^^^^^^^^ | -note: TechnicallyBreaking: added path +note: added path (technically breaking) --> $REPO_PATH/tests/cases/addition/new.rs:11:5 | 11 | pub struct Cde; diff --git a/tests/cases/addition_path/stdout b/tests/cases/addition_path/stdout index 54548cbac732a..372a0108eb81b 100644 --- a/tests/cases/addition_path/stdout +++ b/tests/cases/addition_path/stdout @@ -1,33 +1,33 @@ -version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 -warning: Path changes to `Abc` +version bump: 1.0.0 -> (technically breaking) -> 1.1.0 +warning: path changes to `Abc` --> $REPO_PATH/tests/cases/addition_path/new.rs:2:5 | 2 | pub struct Abc; | ^^^^^^^^^^^^^^^ | -note: TechnicallyBreaking: added path +note: added path (technically breaking) --> $REPO_PATH/tests/cases/addition_path/new.rs:6:13 | 6 | pub use a::*; | ^^^^^ -note: TechnicallyBreaking: added path +note: added path (technically breaking) --> $REPO_PATH/tests/cases/addition_path/new.rs:10:13 | 10| pub use a::Abc; | ^^^^^^ -note: TechnicallyBreaking: added path +note: added path (technically breaking) --> $REPO_PATH/tests/cases/addition_path/new.rs:13:9 | 13| pub use self::a::Abc; | ^^^^^^^^^^^^ -warning: Path changes to `d` +warning: path changes to `d` --> $REPO_PATH/tests/cases/addition_path/new.rs:17:1 | 17 | } | ^ | -note: TechnicallyBreaking: added path +note: added path (technically breaking) --> $REPO_PATH/tests/cases/addition_path/new.rs:17:1 | 17 | } diff --git a/tests/cases/enums/stdout b/tests/cases/enums/stdout index 9d435d5f44b2c..6beb03a6ec747 100644 --- a/tests/cases/enums/stdout +++ b/tests/cases/enums/stdout @@ -1,5 +1,5 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Breaking changes in `Abc` +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: breaking changes in `Abc` --> $REPO_PATH/tests/cases/enums/new.rs:1:1 | 1 | / pub enum Abc { @@ -7,13 +7,13 @@ warning: Breaking changes in `Abc` 3 | | } | |_^ | -warning: Breaking (VariantAdded) +warning: enum variant added (breaking) --> $REPO_PATH/tests/cases/enums/new.rs:2:5 | 2 | Abc, | ^^^ -warning: Breaking changes in `Bcd` +warning: breaking changes in `Bcd` --> $REPO_PATH/tests/cases/enums/new.rs:5:1 | 5 | / pub enum Bcd { @@ -21,13 +21,13 @@ warning: Breaking changes in `Bcd` 7 | | } | |_^ | -warning: Breaking (VariantRemoved) +warning: enum variant removed (breaking) --> $REPO_PATH/tests/cases/enums/old.rs:6:5 | 6 | Abc, | ^^^ -warning: Breaking changes in `Cde` +warning: breaking changes in `Cde` --> $REPO_PATH/tests/cases/enums/new.rs:9:1 | 9 | / pub enum Cde { @@ -36,13 +36,13 @@ warning: Breaking changes in `Cde` 12 | | } | |_^ | -warning: Breaking (VariantAdded) +warning: enum variant added (breaking) --> $REPO_PATH/tests/cases/enums/new.rs:11:5 | 11 | Bcd, | ^^^ -warning: Breaking changes in `Def` +warning: breaking changes in `Def` --> $REPO_PATH/tests/cases/enums/new.rs:14:1 | 14 | / pub enum Def { @@ -50,13 +50,13 @@ warning: Breaking changes in `Def` 16 | | } | |_^ | -warning: Breaking (VariantRemoved) +warning: enum variant removed (breaking) --> $REPO_PATH/tests/cases/enums/old.rs:15:5 | 15 | Bcd, | ^^^ -warning: Breaking changes in `Efg` +warning: breaking changes in `Efg` --> $REPO_PATH/tests/cases/enums/new.rs:18:1 | 18 | / pub enum Efg { @@ -68,37 +68,37 @@ warning: Breaking changes in `Efg` 26 | | } | |_^ | -warning: Breaking (VariantStyleChanged { now_struct: false, total_private: true }) +warning: variant with no public fields changed to a tuple variant (breaking) --> $REPO_PATH/tests/cases/enums/new.rs:19:5 | 19 | Abc(u8), | ^^^^^^^ -warning: Breaking (VariantStyleChanged { now_struct: false, total_private: true }) +warning: variant with no public fields changed to a tuple variant (breaking) --> $REPO_PATH/tests/cases/enums/new.rs:20:5 | 20 | Bcd, | ^^^ -warning: Breaking (VariantStyleChanged { now_struct: true, total_private: true }) +warning: variant with no public fields changed to a struct variant (breaking) --> $REPO_PATH/tests/cases/enums/new.rs:21:5 | 21 | Cde { f: u8 }, | ^^^^^^^^^^^^^ -warning: Breaking (VariantStyleChanged { now_struct: false, total_private: true }) +warning: variant with no public fields changed to a tuple variant (breaking) --> $REPO_PATH/tests/cases/enums/new.rs:22:5 | 22 | Def, | ^^^ -warning: Breaking (VariantStyleChanged { now_struct: true, total_private: true }) +warning: variant with no public fields changed to a struct variant (breaking) --> $REPO_PATH/tests/cases/enums/new.rs:23:5 | 23 | Efg { f: u8 }, | ^^^^^^^^^^^^^ -warning: Breaking (VariantFieldRemoved { public: false, total_public: false }) +warning: variant field removed from variant with private fields (breaking) --> $REPO_PATH/tests/cases/enums/old.rs:25:11 | 25 | Ghi { f: u8 }, | ^^^^^ -warning: Breaking (VariantFieldAdded { public: false, total_public: false }) +warning: variant field added to variant with private fields (breaking) --> $REPO_PATH/tests/cases/enums/new.rs:25:11 | 25 | Ghi { g: u8 }, diff --git a/tests/cases/func/stdout b/tests/cases/func/stdout index 360390579ae66..21c12867c5976 100644 --- a/tests/cases/func/stdout +++ b/tests/cases/func/stdout @@ -1,13 +1,13 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Breaking changes in `bcd` +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: breaking changes in `bcd` --> $REPO_PATH/tests/cases/func/new.rs:4:1 | 4 | pub fn bcd(_: u8) {} | ^^^^^^^^^^^^^^^^^^^^ | - = warning: Breaking (TypeChanged { error: ArgCount }) + = warning: type error: incorrect number of function parameters (breaking) -warning: Breaking changes in `cde` +warning: breaking changes in `cde` --> $REPO_PATH/tests/cases/func/new.rs:6:1 | 6 | / pub fn cde() -> u16 { @@ -15,17 +15,17 @@ warning: Breaking changes in `cde` 8 | | } | |_^ | - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: (), found: u16 }) }) + = warning: type error: expected (), found u16 (breaking) -warning: Breaking changes in `def` +warning: breaking changes in `def` --> $REPO_PATH/tests/cases/func/new.rs:10:1 | 10 | pub fn def() {} | ^^^^^^^^^^^^^^^ | - = warning: Breaking (TypeChanged { error: ArgCount }) + = warning: type error: incorrect number of function parameters (breaking) -warning: NonBreaking changes in `efg` +warning: non-breaking changes in `efg` --> $REPO_PATH/tests/cases/func/new.rs:12:1 | 12 | / pub fn efg(a: A, _: A) -> A { @@ -33,9 +33,9 @@ warning: NonBreaking changes in `efg` 14 | | } | |_^ | - = note: NonBreaking (TypeParameterAdded { defaulted: true }) + = note: defaulted type parameter added (non-breaking) -warning: Breaking changes in `fgh` +warning: breaking changes in `fgh` --> $REPO_PATH/tests/cases/func/new.rs:16:1 | 16 | / pub fn fgh(a: u8, _: u16) -> u8 { @@ -43,9 +43,9 @@ warning: Breaking changes in `fgh` 18 | | } | |_^ | - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) + = warning: type error: expected u8, found u16 (breaking) -warning: Breaking changes in `ghi` +warning: breaking changes in `ghi` --> $REPO_PATH/tests/cases/func/new.rs:20:1 | 20 | / pub fn ghi(a: u8, _: u8) -> u16 { @@ -53,9 +53,9 @@ warning: Breaking changes in `ghi` 22 | | } | |_^ | - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) + = warning: type error: expected u8, found u16 (breaking) -warning: NonBreaking changes in `hij` +warning: non-breaking changes in `hij` --> $REPO_PATH/tests/cases/func/new.rs:24:1 | 24 | / pub const fn hij() -> u8 { @@ -63,9 +63,9 @@ warning: NonBreaking changes in `hij` 26 | | } | |_^ | - = note: NonBreaking (FnConstChanged { now_const: true }) + = note: fn item made const (non-breaking) -warning: Breaking changes in `ijk` +warning: breaking changes in `ijk` --> $REPO_PATH/tests/cases/func/new.rs:28:1 | 28 | / pub fn ijk() -> u8 { @@ -73,5 +73,5 @@ warning: Breaking changes in `ijk` 30 | | } | |_^ | - = warning: Breaking (FnConstChanged { now_const: false }) + = warning: fn item made non-const (breaking) diff --git a/tests/cases/infer/stdout b/tests/cases/infer/stdout index 84bd4ceab5d48..f8c2af4c949b7 100644 --- a/tests/cases/infer/stdout +++ b/tests/cases/infer/stdout @@ -1 +1 @@ -version bump: 1.0.0 -> (Patch) -> 1.0.1 +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/tests/cases/kind_change/stdout b/tests/cases/kind_change/stdout index 0c93d057cc336..0edbc7e33ad96 100644 --- a/tests/cases/kind_change/stdout +++ b/tests/cases/kind_change/stdout @@ -1,5 +1,5 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Breaking changes in `Abc` +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: breaking changes in `Abc` --> $REPO_PATH/tests/cases/kind_change/new.rs:1:1 | 1 | / pub enum Abc { @@ -7,5 +7,5 @@ warning: Breaking changes in `Abc` 3 | | } | |_^ | - = warning: Breaking (KindDifference) + = warning: item kind changed (breaking) diff --git a/tests/cases/macros/stdout b/tests/cases/macros/stdout index 84bd4ceab5d48..f8c2af4c949b7 100644 --- a/tests/cases/macros/stdout +++ b/tests/cases/macros/stdout @@ -1 +1 @@ -version bump: 1.0.0 -> (Patch) -> 1.0.1 +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/tests/cases/mix/new.rs b/tests/cases/mix/new.rs index c618839fe00ce..553516bd87ccd 100644 --- a/tests/cases/mix/new.rs +++ b/tests/cases/mix/new.rs @@ -3,4 +3,8 @@ pub mod a { pub struct Def; } +pub mod b { + pub use a::Abc; +} + pub use self::a::Def; diff --git a/tests/cases/mix/old.rs b/tests/cases/mix/old.rs index fedaf4a01dab6..f9f33b93b541f 100644 --- a/tests/cases/mix/old.rs +++ b/tests/cases/mix/old.rs @@ -3,4 +3,8 @@ pub mod a { pub enum Def {} } +pub mod b { + +} + pub use self::a::Abc; diff --git a/tests/cases/mix/stdout b/tests/cases/mix/stdout index 554488bf907e2..9ab4197b80e40 100644 --- a/tests/cases/mix/stdout +++ b/tests/cases/mix/stdout @@ -1,41 +1,53 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Path changes to `Abc` +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: path changes to `Abc` --> $REPO_PATH/tests/cases/mix/old.rs:2:5 | 2 | pub struct Abc; | ^^^^^^^^^^^^^^^ | -warning: Breaking: removed path - --> $REPO_PATH/tests/cases/mix/old.rs:6:9 +warning: removed path (breaking) + --> $REPO_PATH/tests/cases/mix/old.rs:10:9 | -6 | pub use self::a::Abc; +10| pub use self::a::Abc; | ^^^^^^^^^^^^ -warning: Breaking changes in `Abc` +warning: breaking changes in `Abc` --> $REPO_PATH/tests/cases/mix/new.rs:2:5 | 2 | pub enum Abc {} | ^^^^^^^^^^^^^^^ | - = warning: Breaking (KindDifference) + = warning: item kind changed (breaking) -warning: Breaking changes in `Def` +warning: breaking changes in `Def` --> $REPO_PATH/tests/cases/mix/new.rs:3:5 | 3 | pub struct Def; | ^^^^^^^^^^^^^^^ | - = warning: Breaking (KindDifference) + = warning: item kind changed (breaking) -warning: Path changes to `Def` +warning: path changes to `Abc` + --> $REPO_PATH/tests/cases/mix/new.rs:2:5 + | +2 | pub enum Abc {} + | ^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> $REPO_PATH/tests/cases/mix/new.rs:7:13 + | +7 | pub use a::Abc; + | ^^^^^^ + +warning: path changes to `Def` --> $REPO_PATH/tests/cases/mix/new.rs:3:5 | 3 | pub struct Def; | ^^^^^^^^^^^^^^^ | -note: TechnicallyBreaking: added path - --> $REPO_PATH/tests/cases/mix/new.rs:6:9 +note: added path (technically breaking) + --> $REPO_PATH/tests/cases/mix/new.rs:10:9 | -6 | pub use self::a::Def; +10| pub use self::a::Def; | ^^^^^^^^^^^^ diff --git a/tests/cases/pathologic_paths/stdout b/tests/cases/pathologic_paths/stdout index 64bf2568d5620..9fcf3b6e35838 100644 --- a/tests/cases/pathologic_paths/stdout +++ b/tests/cases/pathologic_paths/stdout @@ -1,23 +1,23 @@ -version bump: 1.0.0 -> (TechnicallyBreaking) -> 1.1.0 -warning: Path changes to `a` +version bump: 1.0.0 -> (technically breaking) -> 1.1.0 +warning: path changes to `a` --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:5:21 | 5 | pub mod a { blow!($($rest)*); } | ^^^^^^^^^^^^^^^^^^^ | -note: TechnicallyBreaking: added path +note: added path (technically breaking) --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:5:21 | 5 | pub mod a { blow!($($rest)*); } | ^^^^^^^^^^^^^^^^^^^ -warning: Path changes to `b` +warning: path changes to `b` --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:6:21 | 6 | pub mod b { pub use super::a::*; } | ^^^^^^^^^^^^^^^^^^^^^^ | -note: TechnicallyBreaking: added path +note: added path (technically breaking) --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:6:21 | 6 | pub mod b { pub use super::a::*; } diff --git a/tests/cases/pub_use/stdout b/tests/cases/pub_use/stdout index 84bd4ceab5d48..f8c2af4c949b7 100644 --- a/tests/cases/pub_use/stdout +++ b/tests/cases/pub_use/stdout @@ -1 +1 @@ -version bump: 1.0.0 -> (Patch) -> 1.0.1 +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/tests/cases/removal/stdout b/tests/cases/removal/stdout index 1098a3d743c87..3800937d8a6fb 100644 --- a/tests/cases/removal/stdout +++ b/tests/cases/removal/stdout @@ -1,51 +1,51 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Path changes to `Abc` +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: path changes to `Abc` --> $REPO_PATH/tests/cases/removal/old.rs:1:1 | 1 | pub struct Abc; | ^^^^^^^^^^^^^^^ | -warning: Breaking: removed path +warning: removed path (breaking) --> $REPO_PATH/tests/cases/removal/old.rs:1:1 | 1 | pub struct Abc; | ^^^^^^^^^^^^^^^ -warning: Breaking changes in `Bcd` +warning: breaking changes in `Bcd` --> $REPO_PATH/tests/cases/removal/new.rs:2:1 | 2 | struct Bcd; | ^^^^^^^^^^^ | - = warning: Breaking (ItemMadePrivate) + = warning: item made private (breaking) -warning: Path changes to `a` +warning: path changes to `a` --> $REPO_PATH/tests/cases/removal/old.rs:7:1 | 7 | } | ^ | -warning: Breaking: removed path +warning: removed path (breaking) --> $REPO_PATH/tests/cases/removal/old.rs:7:1 | 7 | } | ^ -warning: Breaking changes in `b` +warning: breaking changes in `b` --> $REPO_PATH/tests/cases/removal/new.rs:6:1 | 6 | } | ^ | - = warning: Breaking (ItemMadePrivate) + = warning: item made private (breaking) -warning: Path changes to `Cde` +warning: path changes to `Cde` --> $REPO_PATH/tests/cases/removal/old.rs:11:5 | 11 | pub struct Cde; | ^^^^^^^^^^^^^^^ | -warning: Breaking: removed path +warning: removed path (breaking) --> $REPO_PATH/tests/cases/removal/old.rs:11:5 | 11 | pub struct Cde; diff --git a/tests/cases/removal_path/stdout b/tests/cases/removal_path/stdout index 83a6e8a5e89c9..35cdaae23254d 100644 --- a/tests/cases/removal_path/stdout +++ b/tests/cases/removal_path/stdout @@ -1,21 +1,21 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Path changes to `Abc` +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: path changes to `Abc` --> $REPO_PATH/tests/cases/removal_path/old.rs:2:5 | 2 | pub struct Abc; | ^^^^^^^^^^^^^^^ | -warning: Breaking: removed path +warning: removed path (breaking) --> $REPO_PATH/tests/cases/removal_path/old.rs:6:13 | 6 | pub use a::*; | ^^^^^ -warning: Breaking: removed path +warning: removed path (breaking) --> $REPO_PATH/tests/cases/removal_path/old.rs:10:13 | 10| pub use a::Abc; | ^^^^^^ -warning: Breaking: removed path +warning: removed path (breaking) --> $REPO_PATH/tests/cases/removal_path/old.rs:13:9 | 13| pub use self::a::Abc; diff --git a/tests/cases/structs/stdout b/tests/cases/structs/stdout index 9c2f07779443a..1e187d7327e35 100644 --- a/tests/cases/structs/stdout +++ b/tests/cases/structs/stdout @@ -1,5 +1,5 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: TechnicallyBreaking changes in `Def` +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: technically breaking changes in `Def` --> $REPO_PATH/tests/cases/structs/new.rs:6:1 | 6 | / pub struct Def { @@ -7,14 +7,14 @@ warning: TechnicallyBreaking changes in `Def` 8 | | } | |_^ | - = note: NonBreaking (TypeParameterAdded { defaulted: true }) -note: TechnicallyBreaking (ItemMadePublic) + = note: defaulted type parameter added (non-breaking) +note: item made public (technically breaking) --> $REPO_PATH/tests/cases/structs/new.rs:7:5 | 7 | pub field: A, | ^^^^^^^^^^^^ -warning: Breaking changes in `Def2` +warning: breaking changes in `Def2` --> $REPO_PATH/tests/cases/structs/new.rs:10:1 | 10 | / pub struct Def2 { @@ -22,10 +22,10 @@ warning: Breaking changes in `Def2` 12 | | } | |_^ | - = note: NonBreaking (TypeParameterAdded { defaulted: true }) - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) + = note: defaulted type parameter added (non-breaking) + = warning: type error: expected u8, found u16 (breaking) -warning: Breaking changes in `Efg` +warning: breaking changes in `Efg` --> $REPO_PATH/tests/cases/structs/new.rs:14:1 | 14 | / pub struct Efg { @@ -33,9 +33,9 @@ warning: Breaking changes in `Efg` 16 | | } | |_^ | - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) + = warning: type error: expected u8, found u16 (breaking) -warning: TechnicallyBreaking changes in `Fgh` +warning: technically breaking changes in `Fgh` --> $REPO_PATH/tests/cases/structs/new.rs:18:1 | 18 | / pub struct Fgh { @@ -43,13 +43,13 @@ warning: TechnicallyBreaking changes in `Fgh` 20 | | } | |_^ | -note: TechnicallyBreaking (ItemMadePublic) +note: item made public (technically breaking) --> $REPO_PATH/tests/cases/structs/new.rs:19:5 | 19 | pub field: u8, | ^^^^^^^^^^^^^ -warning: Breaking changes in `Ghi` +warning: breaking changes in `Ghi` --> $REPO_PATH/tests/cases/structs/new.rs:22:1 | 22 | / pub struct Ghi { @@ -57,13 +57,13 @@ warning: Breaking changes in `Ghi` 24 | | } | |_^ | -warning: Breaking (ItemMadePrivate) +warning: item made private (breaking) --> $REPO_PATH/tests/cases/structs/new.rs:23:5 | 23 | field: u8, | ^^^^^^^^^ -warning: Breaking changes in `Hij` +warning: breaking changes in `Hij` --> $REPO_PATH/tests/cases/structs/new.rs:26:1 | 26 | / pub struct Hij { @@ -71,7 +71,7 @@ warning: Breaking changes in `Hij` 28 | | } | |_^ | -warning: Breaking (VariantStyleChanged { now_struct: true, total_private: true }) +warning: variant with no public fields changed to a struct variant (breaking) --> $REPO_PATH/tests/cases/structs/new.rs:26:1 | 26 | / pub struct Hij { diff --git a/tests/cases/traits/stdout b/tests/cases/traits/stdout index 3edd8666ad869..4e24dde49f3ca 100644 --- a/tests/cases/traits/stdout +++ b/tests/cases/traits/stdout @@ -1,5 +1,5 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Breaking changes in `Abc` +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: breaking changes in `Abc` --> $REPO_PATH/tests/cases/traits/new.rs:1:1 | 1 | / pub trait Abc { @@ -11,24 +11,24 @@ warning: Breaking changes in `Abc` 14 | | } | |_^ | -warning: Breaking (TraitItemRemoved { defaulted: false }) +warning: removed item from trait (breaking) --> $REPO_PATH/tests/cases/traits/old.rs:4:5 | 4 | fn test2(&self) -> u8; | ^^^^^^^^^^^^^^^^^^^^^^ -warning: Breaking (TraitItemRemoved { defaulted: true }) +warning: removed defaulted item from trait (breaking) --> $REPO_PATH/tests/cases/traits/old.rs:8:5 | 8 | / fn test5() -> u8 { 9 | | 0 10 | | } | |_____^ -warning: Breaking (TraitItemAdded { defaulted: false }) +warning: added item to trait (breaking) --> $REPO_PATH/tests/cases/traits/new.rs:4:5 | 4 | fn test3(&self) -> u8; | ^^^^^^^^^^^^^^^^^^^^^^ -note: TechnicallyBreaking (TraitItemAdded { defaulted: true }) +note: added defaulted item to trait (technically breaking) --> $REPO_PATH/tests/cases/traits/new.rs:8:5 | 8 | / fn test6() -> u8 { @@ -36,27 +36,27 @@ note: TechnicallyBreaking (TraitItemAdded { defaulted: true }) 10 | | } | |_____^ -warning: Breaking changes in `test7` +warning: breaking changes in `test7` --> $REPO_PATH/tests/cases/traits/new.rs:11:5 | 11 | fn test7() -> u16; | ^^^^^^^^^^^^^^^^^^ | - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) + = warning: type error: expected u8, found u16 (breaking) -warning: Breaking changes in `test8` +warning: breaking changes in `test8` --> $REPO_PATH/tests/cases/traits/new.rs:12:5 | 12 | fn test8(_: &Self) -> u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: Breaking (MethodSelfChanged { now_self: false }) + = warning: removed self-argument from method (breaking) -warning: TechnicallyBreaking changes in `test9` +warning: technically breaking changes in `test9` --> $REPO_PATH/tests/cases/traits/new.rs:13:5 | 13 | fn test9(&self) -> u8; | ^^^^^^^^^^^^^^^^^^^^^^ | - = note: TechnicallyBreaking (MethodSelfChanged { now_self: true }) + = note: added self-argument to method (technically breaking) diff --git a/tests/cases/ty_alias/stdout b/tests/cases/ty_alias/stdout index 0d57e6102f1bb..30562d822b72d 100644 --- a/tests/cases/ty_alias/stdout +++ b/tests/cases/ty_alias/stdout @@ -1,58 +1,58 @@ -version bump: 1.0.0 -> (Breaking) -> 2.0.0 -warning: Breaking changes in `A` +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: breaking changes in `A` --> $REPO_PATH/tests/cases/ty_alias/new.rs:1:1 | 1 | pub type A = u16; | ^^^^^^^^^^^^^^^^^ | - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: u8, found: u16 }) }) + = warning: type error: expected u8, found u16 (breaking) -warning: Breaking changes in `B` +warning: breaking changes in `B` --> $REPO_PATH/tests/cases/ty_alias/new.rs:2:1 | 2 | pub type B<'a, 'b : 'a, T> = (&'a T, &'b T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: Breaking (RegionParameterAdded) + = warning: region parameter added (breaking) -warning: Breaking changes in `C` +warning: breaking changes in `C` --> $REPO_PATH/tests/cases/ty_alias/new.rs:3:1 | 3 | pub type C = T; | ^^^^^^^^^^^^^^^^^^ | - = warning: Breaking (RegionParameterRemoved) + = warning: region parameter removed (breaking) -warning: Breaking changes in `D` +warning: breaking changes in `D` --> $REPO_PATH/tests/cases/ty_alias/new.rs:4:1 | 4 | pub type D<'a, T, U=Box> = (&'a T, U); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: NonBreaking (TypeParameterAdded { defaulted: true }) - = warning: Breaking (TypeChanged { error: Sorts(ExpectedFound { expected: &'a T, found: (&'a T, std::boxed::Box) }) }) + = note: defaulted type parameter added (non-breaking) + = warning: type error: expected reference, found tuple (breaking) -warning: Breaking changes in `E` +warning: breaking changes in `E` --> $REPO_PATH/tests/cases/ty_alias/new.rs:5:1 | 5 | pub type E<'a, T, U> = (&'a T, U); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: Breaking (TypeParameterAdded { defaulted: false }) + = warning: type parameter added (breaking) -warning: Breaking changes in `F` +warning: breaking changes in `F` --> $REPO_PATH/tests/cases/ty_alias/new.rs:6:1 | 6 | pub type F<'a> = &'a u8; | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: Breaking (TypeParameterRemoved { defaulted: true }) + = warning: defaulted type parameter removed (breaking) -warning: Breaking changes in `G` +warning: breaking changes in `G` --> $REPO_PATH/tests/cases/ty_alias/new.rs:7:1 | 7 | pub type G<'a> = (&'a u8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: Breaking (TypeParameterRemoved { defaulted: false }) + = warning: type parameter removed (breaking) From 16c4b65f11322a18345d6cded3fdfcd2975f1e7f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 17 Jul 2017 16:46:19 +0200 Subject: [PATCH 146/553] Revived some unit tests. --- src/semcheck/changes.rs | 43 ++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index cacc1d4be1aa3..e5711b9737251 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -586,12 +586,29 @@ pub mod tests { change } + pub type PathChange_ = (Span_, Vec<(bool, Span_)>); + + fn build_path_change(s1: Span, mut spans: Vec<(bool, Span)>) -> PathChange { + let mut interner = Interner::new(); + let mut change = PathChange::new(interner.intern("test"), s1); + + for (add, span) in spans.drain(..) { + change.insert(span, add); + } + + change + } + quickcheck! { - /* /// The `Ord` instance of `Change` is transitive. - fn ord_uchange_transitive(c1: UnaryChange_, c2: UnaryChange_, c3: UnaryChange_) -> bool { - let ch1 = build_unary_change(c1.0, c1.1.inner()); - let ch2 = build_unary_change(c2.0, c2.1.inner()); - let ch3 = build_unary_change(c3.0, c3.1.inner()); + /// The `Ord` instance of `Change` is transitive. + fn ord_pchange_transitive(c1: PathChange_, c2: PathChange_, c3: PathChange_) -> bool { + let s1 = c1.1.iter().map(|&(add, ref s)| (add, s.clone().inner())).collect(); + let s2 = c2.1.iter().map(|&(add, ref s)| (add, s.clone().inner())).collect(); + let s3 = c3.1.iter().map(|&(add, ref s)| (add, s.clone().inner())).collect(); + + let ch1 = build_path_change(c1.0.inner(), s1); + let ch2 = build_path_change(c2.0.inner(), s2); + let ch3 = build_path_change(c3.0.inner(), s3); let mut res = true; @@ -608,7 +625,7 @@ pub mod tests { } res - } */ + } fn ord_change_transitive(c1: Change_, c2: Change_, c3: Change_) -> bool { let ch1 = build_change(Unknown, c1.0.inner(), c1.1.inner()); @@ -665,20 +682,20 @@ pub mod tests { set.max == max } */ - /* /// Difference in spans implies difference in `Change`s. - fn uchange_span_neq(c1: UnaryChange_, c2: UnaryChange_) -> bool { - let s1 = c1.1.inner(); - let s2 = c2.1.inner(); + /// Difference in spans implies difference in `Change`s. + fn pchange_span_neq(c1: PathChange_, c2: PathChange_) -> bool { + let s1 = c1.1.iter().map(|&(add, ref s)| (add, s.clone().inner())).collect(); + let s2 = c2.1.iter().map(|&(add, ref s)| (add, s.clone().inner())).collect(); if s1 != s2 { - let ch1 = build_unary_change(c1.0, s1); - let ch2 = build_unary_change(c2.0, s2); + let ch1 = build_path_change(c1.0.inner(), s1); + let ch2 = build_path_change(c2.0.inner(), s2); ch1 != ch2 } else { true } - } */ + } /// Difference in spans implies difference in `Change`s. fn bchange_span_neq(c1: Change_, c2: Change_) -> bool { From f5d831b310400935b5b549e8f9acf6e47297c4ea Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 17 Jul 2017 16:54:47 +0200 Subject: [PATCH 147/553] Removed old testing cruft. --- src/semcheck/changes.rs | 42 +++++------------------------------------ 1 file changed, 5 insertions(+), 37 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index e5711b9737251..9c43b79c66ab1 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -522,10 +522,10 @@ pub mod tests { let a: u32 = Arbitrary::arbitrary(g); let b: u32 = Arbitrary::arbitrary(g); Span_(Span { - lo: BytePos(min(a, b)), - hi: BytePos(max(a, b)), - ctxt: SyntaxContext::empty(), - }) + lo: BytePos(min(a, b)), + hi: BytePos(max(a, b)), + ctxt: SyntaxContext::empty(), + }) } } @@ -542,39 +542,7 @@ pub mod tests { g.choose(&[UnaryChangeType::Removal, UnaryChangeType::Addition]).unwrap().clone() } } - - impl<'a> From<&'a UnaryChangeType> for ChangeCategory { - fn from(change: &UnaryChangeType) -> ChangeCategory { - match *change { - UnaryChangeType::Addition => TechnicallyBreaking, - UnaryChangeType::Removal => Breaking, - } - } - } - - pub type UnaryChange_ = (UnaryChangeType, Span_); - - /// We build these by hand, because symbols can't be sent between threads. - fn build_unary_change(t: UnaryChangeType, s: Span) -> UnaryChange { - let mut interner = Interner::new(); - let ident = Ident { - name: interner.intern("test"), - ctxt: SyntaxContext::empty(), - }; - let export = Export { - ident: ident, - def: Def::Mod(DefId { - krate: LOCAL_CRATE, - index: CRATE_DEF_INDEX, - }), - span: s, - }; - - match t { - UnaryChangeType::Addition => UnaryChange::Addition(export), - UnaryChangeType::Removal => UnaryChange::Removal(export), - } - } */ + */ pub type Change_ = (Span_, Span_); From 718467e8f3b9cbfd7c47a74be22a7abf17001afe Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 17 Jul 2017 22:51:41 +0200 Subject: [PATCH 148/553] Finished reimplementing unit tests. Also, fixed a temporary build failure caused by a LibreSSL update. --- Cargo.toml | 3 + src/semcheck/changes.rs | 243 +++++++++++++++++++++++++++++++--------- 2 files changed, 190 insertions(+), 56 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 207e374dd7fb8..be8f69a70aeff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,3 +22,6 @@ semver = "^0.7.0" [dev-dependencies] quickcheck = "^0.4.1" + +[replace] +"openssl-sys:0.9.13" = { git = "https://github.com/ibabushkin/rust-openssl", branch = "libressl-tmp" } diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 9c43b79c66ab1..e2938a8c6713c 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -499,14 +499,13 @@ pub mod tests { use quickcheck::*; pub use super::*; - use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; - use rustc::hir::def::Def; + use rustc::hir::def_id::DefId; use std::cmp::{max, min}; use syntax_pos::BytePos; use syntax_pos::hygiene::SyntaxContext; - use syntax_pos::symbol::{Ident, Interner}; + use syntax_pos::symbol::Interner; #[derive(Clone, Debug)] pub struct Span_(Span); @@ -529,32 +528,130 @@ pub mod tests { } } - /* - // we don't need this type elsewhere, so we define it here. #[derive(Clone, Debug)] - pub enum UnaryChangeType { - Removal, - Addition, + pub struct DefId_(DefId); + + impl DefId_ { + pub fn inner(self) -> DefId { + self.0 + } + } + + impl Arbitrary for DefId_ { + fn arbitrary(g: &mut G) -> DefId_ { + use rustc::hir::def_id::{DefId, CrateNum, DefIndex}; + + let a: u32 = Arbitrary::arbitrary(g); + let b: u32 = Arbitrary::arbitrary(g); + DefId_(DefId { + krate: CrateNum::new(a as usize), + index: DefIndex::new(b as usize), + }) + } } - impl Arbitrary for UnaryChangeType { - fn arbitrary(g: &mut G) -> UnaryChangeType { - g.choose(&[UnaryChangeType::Removal, UnaryChangeType::Addition]).unwrap().clone() + // a rip-off of the real `ChangeType` - but this one can be 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 }, + VariantFieldRemoved { public: bool, total_public: bool }, + VariantStyleChanged { now_struct: bool, total_private: bool }, + FnConstChanged { now_const: bool }, + MethodSelfChanged { now_self: bool }, + TraitItemAdded { defaulted: 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 } => + VariantFieldAdded { public, total_public }, + ChangeType_::VariantFieldRemoved { public, total_public } => + VariantFieldRemoved { public, total_public }, + ChangeType_::VariantStyleChanged { now_struct, total_private } => + VariantStyleChanged { now_struct, total_private }, + ChangeType_::FnConstChanged { now_const } => + FnConstChanged { now_const }, + ChangeType_::MethodSelfChanged { now_self } => + MethodSelfChanged { now_self }, + ChangeType_::TraitItemAdded { defaulted } => + TraitItemAdded { defaulted }, + ChangeType_::TraitItemRemoved { defaulted } => + TraitItemRemoved { defaulted }, + ChangeType_::TraitUnsafetyChanged { now_unsafe } => + TraitUnsafetyChanged { now_unsafe }, + ChangeType_::Unknown => Unknown, + } } } - */ - pub type Change_ = (Span_, Span_); + impl Arbitrary for ChangeType_ { + fn arbitrary(g: &mut G) -> ChangeType_ { + use self::ChangeType_::*; + + let b1 = Arbitrary::arbitrary(g); + let b2 = Arbitrary::arbitrary(g); + + g.choose(&[ItemMadePublic, + ItemMadePrivate, + KindDifference, + RegionParameterAdded, + RegionParameterRemoved, + TypeParameterAdded { defaulted: b1 }, + TypeParameterRemoved { defaulted: b1 }, + VariantAdded, + VariantRemoved, + VariantFieldAdded { public: b1, total_public: b2 }, + VariantFieldRemoved { public: b1, total_public: b2 }, + VariantStyleChanged { now_struct: b1, total_private: b2 }, + FnConstChanged { now_const: b1 }, + MethodSelfChanged { now_self: b1 }, + TraitItemAdded { defaulted: b1 }, + TraitItemRemoved { defaulted: b1 }, + TraitUnsafetyChanged { now_unsafe: b1 }, + Unknown]).unwrap().clone() + } + } - fn build_change(t: ChangeType, s1: Span, s2: Span) -> Change { + pub type Change_ = (DefId_, DefId_, Span_, Span_, bool, Vec<(ChangeType_, Option)>); + + fn build_change<'a>(s1: Span, output: bool, mut changes: Vec<(ChangeType_, Option)>) + -> Change<'a> + { let mut interner = Interner::new(); - let mut change = Change::new(interner.intern("test"), s2, true); - change.add(t, Some(s1)); + let mut change = Change::new(interner.intern("test"), s1, output); + + for (type_, span) in changes.drain(..) { + change.add(type_.inner(), span.map(|s| s.inner())); + } change } - pub type PathChange_ = (Span_, Vec<(bool, Span_)>); + pub type PathChange_ = (DefId_, Span_, Vec<(bool, Span_)>); fn build_path_change(s1: Span, mut spans: Vec<(bool, Span)>) -> PathChange { let mut interner = Interner::new(); @@ -568,15 +665,15 @@ pub mod tests { } quickcheck! { - /// The `Ord` instance of `Change` is transitive. + /// The `Ord` instance of `PathChange` is transitive. fn ord_pchange_transitive(c1: PathChange_, c2: PathChange_, c3: PathChange_) -> bool { - let s1 = c1.1.iter().map(|&(add, ref s)| (add, s.clone().inner())).collect(); - let s2 = c2.1.iter().map(|&(add, ref s)| (add, s.clone().inner())).collect(); - let s3 = c3.1.iter().map(|&(add, ref s)| (add, s.clone().inner())).collect(); + 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.0.inner(), s1); - let ch2 = build_path_change(c2.0.inner(), s2); - let ch3 = build_path_change(c3.0.inner(), s3); + 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; @@ -595,10 +692,11 @@ pub mod tests { res } + /// The `Ord` instance of `Change` is transitive. fn ord_change_transitive(c1: Change_, c2: Change_, c3: Change_) -> bool { - let ch1 = build_change(Unknown, c1.0.inner(), c1.1.inner()); - let ch2 = build_change(Unknown, c2.0.inner(), c2.1.inner()); - let ch3 = build_change(Unknown, c3.0.inner(), c3.1.inner()); + 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; @@ -617,47 +715,80 @@ pub mod tests { res } - /* /// The maximal change category for a change set gets computed correctly. - fn max_uchange(changes: Vec) -> bool { + /// The maximal change category for a change set gets computed correctly. + fn max_pchange(changes: Vec) -> bool { let mut set = ChangeSet::default(); - let max = changes.iter().map(|c| From::from(&c.0)).max().unwrap_or(Patch); - - for &(ref change, ref span) in changes.iter() { - let change = build_unary_change(change.clone(), span.clone().inner()); - let key = ChangeKey::NewKey(change.export().def.def_id()); - set.new_unary_change(Change::Unary(change), key); + let mut interner = Interner::new(); + 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(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 gets computed correctly. + /// The maximal change category for a change set gets computed correctly. fn max_change(changes: Vec) -> bool { let mut set = ChangeSet::default(); - let max = changes.iter().map(|_| Unknown.to_category()).max().unwrap_or(Patch); - - for &(ref span1, ref span2) in changes.iter() { - let change = build_change(Unknown, span1.clone().inner(), span2.clone().inner()); - let did = DefId { - krate: LOCAL_CRATE, - index: CRATE_DEF_INDEX, - }; - // set.new_binary(change, did); + let mut interner = Interner::new(); + let name = interner.intern("test"); + + let max = changes + .iter() + .flat_map(|change| change.5.iter()) + .map(|&(ref type_, _)| type_.inner().to_category()) + .max() + .unwrap_or(Patch); + + for &(ref o_did, ref n_did, ref o_span, ref n_span, out, ref sub) in &changes { + let old_did = o_did.clone().inner(); + set.new_change(old_did, + n_did.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_did, + span_.clone().map(|s| s.inner())); + } } set.max == max - } */ + } - /// Difference in spans implies difference in `Change`s. + /// Difference in spans implies difference in `PathChange`s. fn pchange_span_neq(c1: PathChange_, c2: PathChange_) -> bool { - let s1 = c1.1.iter().map(|&(add, ref s)| (add, s.clone().inner())).collect(); - let s2 = c2.1.iter().map(|&(add, ref s)| (add, s.clone().inner())).collect(); + 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(c1.0.inner(), s1); - let ch2 = build_path_change(c2.0.inner(), s2); + let ch1 = build_path_change(s1, v1); + let ch2 = build_path_change(s2, v2); ch1 != ch2 } else { @@ -667,12 +798,12 @@ pub mod tests { /// Difference in spans implies difference in `Change`s. fn bchange_span_neq(c1: Change_, c2: Change_) -> bool { - let s1 = c1.0.inner(); - let s2 = c2.0.inner(); + let s1 = c1.3.clone().inner(); + let s2 = c2.3.clone().inner(); if s1 != s2 { - let ch1 = build_change(Unknown, c1.1.inner(), s1); - let ch2 = build_change(Unknown, c2.1.inner(), 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 { From ebae0f40672e6d275d3e99f03bf607502a1b3850 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 17 Jul 2017 23:17:24 +0200 Subject: [PATCH 149/553] Improved rust source debugging in debug script. --- tests/debug.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/debug.rs b/tests/debug.rs index ec0107aede8d6..d2f91bf8a9a26 100644 --- a/tests/debug.rs +++ b/tests/debug.rs @@ -38,7 +38,11 @@ fi export RUST_LOG=debug -src_str="set substitute-path /checkout $(rustc --print sysroot)/lib/rustlib/src/rust" +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" From 25f1ec56757bcc2c44c989d329529ffc6461178e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 18 Jul 2017 23:06:04 +0200 Subject: [PATCH 150/553] Added a check for comparable substs. --- src/semcheck/mismatch.rs | 124 +++++++++++++++++++++++---------------- src/semcheck/traverse.rs | 27 +++++---- tests/debug.rs | 2 +- 3 files changed, 90 insertions(+), 63 deletions(-) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index a3ec7835713e8..1a75a7c681574 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -9,6 +9,7 @@ use rustc::ty; use rustc::ty::{Ty, TyCtxt}; use rustc::ty::Visibility::Public; use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; +use rustc::ty::subst::Substs; use semcheck::mapping::IdMapping; @@ -58,6 +59,18 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> Mismatch<'a, 'gcx, 'tcx> { let _ = self.relate(&old_ty, &new_ty); } } + + fn check_substs(&self, a_substs: &'tcx Substs<'tcx>, b_substs: &'tcx Substs<'tcx>) + -> bool + { + for (a, b) in a_substs.iter().zip(b_substs) { + if a.as_type().is_some() != b.as_type().is_some() { + return false; + } + } + + true + } } impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { @@ -88,82 +101,93 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { use rustc::ty::TypeVariants::*; - // TODO: maybe fetch def ids from TyFnDef, TyClosure, TyAnon, TyProjection + // TODO: maybe fetch def ids from TyFnDef, TyClosure, TyAnon let matching = match (&a.sty, &b.sty) { - (&TyInfer(_), _) | (_, &TyInfer(_)) => { - // As the original function this is ripped off of, we don't handle these cases. - panic!("var types encountered in Mismatch::tys") - }, (&TyAdt(a_def, a_substs), &TyAdt(b_def, 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) { - if self.id_mapping.contains_id(field.did) { - let a_field_ty = field.ty(self.tcx, a_substs); - let b_field_ty = - b_fields[&self.id_mapping.get_new_id(field.did)] - .ty(self.tcx, b_substs); - - let _ = self.relate(&a_field_ty, &b_field_ty); + 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) { + if self.id_mapping.contains_id(field.did) { + let a_field_ty = field.ty(self.tcx, a_substs); + let b_field_ty = + b_fields[&self.id_mapping.get_new_id(field.did)] + .ty(self.tcx, b_substs); + + let _ = self.relate(&a_field_ty, &b_field_ty)?; + } } - } - Some((a_def.did, b_def.did)) - }, - (&TyDynamic(a_obj, a_r), &TyDynamic(b_obj, b_r)) => { - let _ = self.relate(&a_r, &b_r); - if let (Some(a), Some(b)) = (a_obj.principal(), b_obj.principal()) { - let _ = self.relate(&a, &b); - Some((a.skip_binder().def_id, b.skip_binder().def_id)) + Some((a_def.did, b_def.did)) } else { None } }, + (&TyArray(a_t, _), &TyArray(b_t, _)) | + (&TySlice(a_t), &TySlice(b_t)) => { + let _ = self.relate(&a_t, &b_t)?; + None + }, (&TyRawPtr(a_mt), &TyRawPtr(b_mt)) => { - let _ = self.relate(&a_mt, &b_mt); + let _ = self.relate(&a_mt, &b_mt)?; None }, (&TyRef(a_r, a_mt), &TyRef(b_r, b_mt)) => { - let _ = self.relate(&a_r, &b_r); - let _ = self.relate(&a_mt, &b_mt); + let _ = self.relate(&a_r, &b_r)?; + let _ = self.relate(&a_mt, &b_mt)?; None }, - (&TyArray(a_t, _), &TyArray(b_t, _)) | - (&TySlice(a_t), &TySlice(b_t)) => { - let _ = self.relate(&a_t, &b_t); + (&TyFnDef(a_def_id, a_substs), &TyFnDef(_, 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())?; + } + None }, - (&TyTuple(as_, _), &TyTuple(bs, _)) => { - let _ = as_.iter().zip(bs).map(|(a, b)| self.relate(a, b)); + (&TyFnPtr(a_fty), &TyFnPtr(b_fty)) => { + let _ = self.relate(&a_fty, &b_fty)?; None }, - (&TyFnDef(a_def_id, a_substs), &TyFnDef(_, 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()); - None + (&TyDynamic(a_obj, a_r), &TyDynamic(b_obj, b_r)) => { + // TODO + let _ = self.relate(&a_r, &b_r)?; + if let (Some(a), Some(b)) = (a_obj.principal(), b_obj.principal()) { + let _ = self.relate(&a, &b); // TODO: kill this? + Some((a.skip_binder().def_id, b.skip_binder().def_id)) + } else { + None + } }, - (&TyFnPtr(a_fty), &TyFnPtr(b_fty)) => { - let _ = self.relate(&a_fty, &b_fty); + (&TyTuple(as_, _), &TyTuple(bs, _)) => { + let _ = as_.iter().zip(bs).map(|(a, b)| self.relate(a, b)); None }, (&TyProjection(a_data), &TyProjection(b_data)) => { - let _ = self.relate(&a_data, &b_data); - None + let _ = self.relate(&a_data, &b_data)?; + Some((a_data.item_def_id, b_data.item_def_id)) }, (&TyAnon(_, a_substs), &TyAnon(_, b_substs)) => { - let _ = ty::relate::relate_substs(self, None, a_substs, b_substs); + // TODO: kill this part? or do something with the result + if self.check_substs(a_substs, b_substs) { + let _ = ty::relate::relate_substs(self, None, a_substs, b_substs)?; + } None }, + (&TyInfer(_), _) | (_, &TyInfer(_)) => { + // As the original function this is ripped off of, we don't handle these cases. + panic!("var types encountered in Mismatch::tys") + }, _ => None, }; diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 538f256e20199..614f515c36e67 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -675,18 +675,6 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, TyFnDef(did, substs) => { tcx.mk_fn_def(id_mapping.get_new_id(did), substs) }, - TyProjection(proj) => { - let new_did = if id_mapping.contains_id(proj.item_def_id) { - id_mapping.get_new_id(proj.item_def_id) - } else { - proj.item_def_id - }; - - tcx.mk_projection(new_did, proj.substs) - }, - TyAnon(did, substs) => { - tcx.mk_anon(id_mapping.get_new_id(did), substs) - }, TyDynamic(preds, region) => { let new_preds = tcx.mk_existential_predicates(preds.iter().map(|p| { match *p.skip_binder() { @@ -727,6 +715,21 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.mk_dynamic(Binder(new_preds), region) }, + TyProjection(proj) => { + let new_did = if id_mapping.contains_id(proj.item_def_id) { + id_mapping.get_new_id(proj.item_def_id) + } else { + proj.item_def_id + }; + + tcx.mk_projection(new_did, proj.substs) + }, + TyAnon(did, substs) => { + tcx.mk_anon(id_mapping.get_new_id(did), substs) + }, + /* TODO: TyParam(param) => { + + }, */ _ => ty, } }}) diff --git a/tests/debug.rs b/tests/debug.rs index d2f91bf8a9a26..fb07bc57480db 100644 --- a/tests/debug.rs +++ b/tests/debug.rs @@ -23,7 +23,7 @@ export RUST_SEMVER_CRATE_VERSION=1.0.0 if [ "$1" = "-s" ]; then shift - arg_str="set args --crate-type=lib $(cargo semver "$@") tests/helper/test.rs" + 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" From ee294f61a1b6bcc834e82b78d8a0f6ac582a147e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 18 Jul 2017 23:54:18 +0200 Subject: [PATCH 151/553] Add more mismatch processing. --- src/semcheck/mismatch.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 1a75a7c681574..5d4040c892ee8 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -101,7 +101,7 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { use rustc::ty::TypeVariants::*; - // TODO: maybe fetch def ids from TyFnDef, TyClosure, TyAnon + // TODO: maybe fetch def ids from TyClosure let matching = match (&a.sty, &b.sty) { (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs)) => { if self.check_substs(a_substs, b_substs) { @@ -145,7 +145,7 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { let _ = self.relate(&a_mt, &b_mt)?; None }, - (&TyFnDef(a_def_id, a_substs), &TyFnDef(_, b_substs)) => { + (&TyFnDef(a_def_id, a_substs), &TyFnDef(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); @@ -153,7 +153,7 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { let _ = self.relate(a_sig.skip_binder(), b_sig.skip_binder())?; } - None + Some((a_def_id, b_def_id)) }, (&TyFnPtr(a_fty), &TyFnPtr(b_fty)) => { let _ = self.relate(&a_fty, &b_fty)?; @@ -177,12 +177,12 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { let _ = self.relate(&a_data, &b_data)?; Some((a_data.item_def_id, b_data.item_def_id)) }, - (&TyAnon(_, a_substs), &TyAnon(_, b_substs)) => { - // TODO: kill this part? or do something with the result + (&TyAnon(a_def_id, a_substs), &TyAnon(b_def_id, b_substs)) => { if self.check_substs(a_substs, b_substs) { let _ = ty::relate::relate_substs(self, None, a_substs, b_substs)?; } - None + + Some((a_def_id, b_def_id)) }, (&TyInfer(_), _) | (_, &TyInfer(_)) => { // As the original function this is ripped off of, we don't handle these cases. From b016e26939cf3da57a17d8156e25e79bf573daeb Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 20 Jul 2017 11:11:09 +0200 Subject: [PATCH 152/553] Implemented type folding for `TyParam`. Previously, if type parameters were present and a region parameter got added, there was a case when the type parameter indices which haven't been translated at all caused all sorts of mayhem. Now that we record the correspondence between type parameter definitions, we can properly translate `TyParam` variants in `fold_to_new`. --- src/semcheck/mapping.rs | 22 ++++++++++------ src/semcheck/traverse.rs | 54 +++++++++++++++++++++++++++++++--------- 2 files changed, 56 insertions(+), 20 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 5bf7f06c14248..fe31f3fee10aa 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -5,8 +5,9 @@ use rustc::hir::def::{Def, Export}; use rustc::hir::def_id::DefId; +use rustc::ty::TypeParameterDef; -use std::collections::{BTreeSet, HashMap, HashSet, VecDeque}; +use std::collections::{BTreeSet, HashMap, VecDeque}; use syntax::ast::Name; @@ -25,7 +26,7 @@ pub struct IdMapping { /// Children mapping, allowing us to enumerate descendants in `AdtDef`s. child_mapping: HashMap>, /// Set of new defaulted type parameters. - defaulted_type_params: HashSet, + type_params: HashMap, } impl IdMapping { @@ -66,16 +67,21 @@ impl IdMapping { .insert(old); } - /// Record that a `DefId` represents a newly added defaulted type parameter. - pub fn add_defaulted_type_param(&mut self, new: DefId) { - self.defaulted_type_params - .insert(new); + /// Record that a `DefId` represents a new type parameter. + pub fn add_type_param(&mut self, new: TypeParameterDef) { + self.type_params.insert(new.def_id, new); + } + + /// Get the type parameter represented by a given `DefId`. + pub fn get_type_param(&self, def_id: &DefId) -> TypeParameterDef { + self.type_params[def_id] } /// Check whether a `DefId` represents a newly added defaulted type parameter. pub fn is_defaulted_type_param(&self, new: &DefId) -> bool { - self.defaulted_type_params - .contains(new) + self.type_params + .get(new) + .map_or(false, |def| def.has_default) } /// Get the new `DefId` associated with the given old one. diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 614f515c36e67..3f218163d4be7 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -22,7 +22,7 @@ use semcheck::changes::ChangeSet; use semcheck::mapping::{IdMapping, NameMapping}; use semcheck::mismatch::Mismatch; -use std::collections::{BTreeMap, HashSet, VecDeque}; +use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; /// The main entry point to our analysis passes. /// @@ -416,13 +416,18 @@ fn diff_traits(changes: &mut ChangeSet, for (name, item_pair) in &items { match *item_pair { (Some((old_def, old_item)), Some((new_def, new_item))) => { + let old_def_id = old_def.def_id(); + let new_def_id = new_def.def_id(); + id_mapping.add_trait_item(old_def, new_def); changes.new_change(old_def.def_id(), new_def.def_id(), *name, - tcx.def_span(old_def.def_id()), - tcx.def_span(new_def.def_id()), + tcx.def_span(old_def_id), + tcx.def_span(new_def_id), true); + + 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) => { @@ -481,15 +486,16 @@ fn diff_generics(changes: &mut ChangeSet, found.push(TypeParameterRemoved { defaulted: false }); found.push(TypeParameterAdded { defaulted: true }); } + + id_mapping.add_internal_item(old_type.def_id, new_type.def_id); + id_mapping.add_type_param(*new_type); }, (Some(old_type), None) => { found.push(TypeParameterRemoved { defaulted: old_type.has_default }); }, (None, Some(new_type)) => { // FIXME: is_fn could be used in a more elegant fashion found.push(TypeParameterAdded { defaulted: new_type.has_default || is_fn }); - if new_type.has_default { - id_mapping.add_defaulted_type_param(new_type.def_id); - } + id_mapping.add_type_param(*new_type); }, (None, None) => unreachable!(), } @@ -587,7 +593,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, use rustc::ty::{Lift, ReEarlyBound}; let substs = Substs::identity_for_item(tcx, new_def_id); - let old = fold_to_new(id_mapping, tcx, &old).subst(tcx, substs); + let old = fold_to_new(id_mapping, tcx, old_def_id, &old).subst(tcx, substs); tcx.infer_ctxt().enter(|infcx| { let new_substs = if new.is_fn() { @@ -617,8 +623,11 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, }); } -/// Fold a type of an old item to be comparable with a new type. -fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, old: &T) -> T +/// Fold a type of an old item to be comparable with a new item. +fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + old_def_id: DefId, + old: &T) -> T where T: TypeFoldable<'tcx> { use rustc::ty::{AdtDef, Binder, BoundRegion, EarlyBoundRegion, ExistentialProjection, @@ -662,6 +671,21 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, } } + let mut index_map = HashMap::new(); + let old_generics = tcx.generics_of(old_def_id); + + for type_ in &old_generics.types { + index_map.insert(type_.index, type_.def_id); + } + + if let Some(did) = old_generics.parent { + let parent_generics = tcx.generics_of(did); + + for type_ in &parent_generics.types { + index_map.insert(type_.index, type_.def_id); + } + } + old.fold_with(&mut BottomUpFolder { tcx: tcx, fldop: |ty| { match ty.sty { TyAdt(&AdtDef { ref did, .. }, substs) if id_mapping.contains_id(*did) => { @@ -727,9 +751,15 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, TyAnon(did, substs) => { tcx.mk_anon(id_mapping.get_new_id(did), substs) }, - /* TODO: TyParam(param) => { - - }, */ + TyParam(param) => { + if param.idx != 0 { // `Self` is special + let old_did = index_map[¶m.idx]; + let new_did = id_mapping.get_new_id(old_did); + tcx.mk_param_from_def(&id_mapping.get_type_param(&new_did)) + } else { + tcx.mk_ty(TyParam(param)) + } + }, _ => ty, } }}) From 6fc7023c200a973973f937cf46b075c9c22c4513 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 20 Jul 2017 14:58:36 +0200 Subject: [PATCH 153/553] Implemented checks for breaking traits. We don't check trait items if the trait itself suffered breaking changes. --- src/semcheck/mapping.rs | 20 +++++++++++------ src/semcheck/traverse.rs | 32 ++++++++++++++++----------- tests/cases/traits/new.rs | 14 ++++++++++++ tests/cases/traits/old.rs | 12 ++++++++++ tests/cases/traits/stdout | 46 ++++++++++++++++++++++++++++++++------- 5 files changed, 96 insertions(+), 28 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index fe31f3fee10aa..99b019c7c9d23 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -17,10 +17,10 @@ use syntax::ast::Name; /// losslessly. The *access* to the stored data happens through the same API, however. #[derive(Default)] pub struct IdMapping { - /// Toplevel items' old `DefId` mapped to new `DefId`, as well as old and new exports. + /// Toplevel items' old `DefId` mapped to old and new `Def`. toplevel_mapping: HashMap, - /// Trait items' old `DefId` mapped to new `DefId`. - trait_item_mapping: HashMap, + /// Trait items' old `DefId` mapped to old and new `Def`. + trait_item_mapping: HashMap, /// Other item's old `DefId` mapped to new `DefId`. internal_mapping: HashMap, /// Children mapping, allowing us to enumerate descendants in `AdtDef`s. @@ -43,8 +43,8 @@ impl IdMapping { } /// Add any trait item's old and new `DefId`s. - pub fn add_trait_item(&mut self, old: Def, new: Def) { - self.trait_item_mapping.insert(old.def_id(), (old, new)); + pub fn add_trait_item(&mut self, old: Def, new: Def, trait_def_id: DefId) { + self.trait_item_mapping.insert(old.def_id(), (old, new, trait_def_id)); } /// Add any other item's old and new `DefId`s. @@ -95,6 +95,11 @@ impl IdMapping { } } + /// Return the `DefId` of the trait a given item belongs to. + pub fn get_trait_def(&self, item_def_id: &DefId) -> Option { + self.trait_item_mapping.get(item_def_id).map(|t| t.2) + } + /// Tell us whether a `DefId` is present in the mappings. pub fn contains_id(&self, old: DefId) -> bool { self.toplevel_mapping.contains_key(&old) || @@ -111,10 +116,11 @@ impl IdMapping { } /// Iterate over the toplevel and trait item pairs. - pub fn items<'a>(&'a self) -> impl Iterator + 'a { + pub fn items<'a>(&'a self) -> impl Iterator + 'a { self.toplevel_mapping .values() - .chain(self.trait_item_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. diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 3f218163d4be7..0e36f2a8b026a 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -43,12 +43,12 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI } // third pass - for &(old, new) in id_mapping.items() { + for (old, new) in id_mapping.items() { diff_bounds(&mut changes, tcx, old.def_id(), new.def_id()); } // fourth pass - for &(old, new) in id_mapping.items() { + for (old, new) in id_mapping.items() { diff_types(&mut changes, &id_mapping, tcx, old, new); } @@ -134,11 +134,11 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, }; let output = o_vis == Public || n_vis == Public; - changes.new_change(o.def.def_id(), - n.def.def_id(), + changes.new_change(o_def_id, + n_def_id, o.ident.name, - tcx.def_span(o.def.def_id()), - tcx.def_span(n.def.def_id()), + tcx.def_span(o_def_id), + tcx.def_span(n_def_id), output); if o_vis == Public && n_vis != Public { @@ -419,13 +419,13 @@ fn diff_traits(changes: &mut ChangeSet, let old_def_id = old_def.def_id(); let new_def_id = new_def.def_id(); - id_mapping.add_trait_item(old_def, new_def); - changes.new_change(old_def.def_id(), - new_def.def_id(), + id_mapping.add_trait_item(old_def, new_def, old); + changes.new_change(old_def_id, + new_def_id, *name, tcx.def_span(old_def_id), tcx.def_span(new_def_id), - true); + true); // TODO: bad to do this unconditionally diff_generics(changes, id_mapping, tcx, true, old_def_id, new_def_id); diff_method(changes, tcx, old_item, new_item); @@ -541,7 +541,9 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let old_def_id = old.def_id(); let new_def_id = new.def_id(); - if changes.item_breaking(old_def_id) { + if changes.item_breaking(old_def_id) || + id_mapping.get_trait_def(&old_def_id) + .map_or(false, |did| changes.item_breaking(did)) { return; } @@ -754,8 +756,12 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, TyParam(param) => { if param.idx != 0 { // `Self` is special let old_did = index_map[¶m.idx]; - let new_did = id_mapping.get_new_id(old_did); - tcx.mk_param_from_def(&id_mapping.get_type_param(&new_did)) + if id_mapping.contains_id(old_did) { + let new_did = id_mapping.get_new_id(old_did); + tcx.mk_param_from_def(&id_mapping.get_type_param(&new_did)) + } else { + tcx.mk_ty(TyParam(param)) + } } else { tcx.mk_ty(TyParam(param)) } diff --git a/tests/cases/traits/new.rs b/tests/cases/traits/new.rs index 682b4501c1d3b..c8ed72e475e9d 100644 --- a/tests/cases/traits/new.rs +++ b/tests/cases/traits/new.rs @@ -12,3 +12,17 @@ pub trait Abc { fn test8(_: &Self) -> u8; fn test9(&self) -> u8; } + +pub trait Bcd {} + +pub trait Cde {} + +pub trait Def { + // The method is not broken - the impls are, but calls should work as expected, as + // long as a proper impl is presented. Maybe this will need some more careful handling. + fn def(&self, a: B) -> bool; +} + +pub trait Efg { + fn efg(&self, a: A) -> bool; +} diff --git a/tests/cases/traits/old.rs b/tests/cases/traits/old.rs index 682397e8d910a..87104729f9d5d 100644 --- a/tests/cases/traits/old.rs +++ b/tests/cases/traits/old.rs @@ -12,3 +12,15 @@ pub trait Abc { fn test8(&self) -> u8; fn test9(_: &Self) -> u8; } + +pub trait Bcd {} + +pub trait Cde {} + +pub trait Def { + fn def(&self, a: A) -> bool; +} + +pub trait Efg { + fn efg(&self, a: B) -> bool; +} diff --git a/tests/cases/traits/stdout b/tests/cases/traits/stdout index 4e24dde49f3ca..3c209b5f7e373 100644 --- a/tests/cases/traits/stdout +++ b/tests/cases/traits/stdout @@ -36,14 +36,6 @@ note: added defaulted item to trait (technically breaking) 10 | | } | |_____^ -warning: breaking changes in `test7` - --> $REPO_PATH/tests/cases/traits/new.rs:11:5 - | -11 | fn test7() -> u16; - | ^^^^^^^^^^^^^^^^^^ - | - = warning: type error: expected u8, found u16 (breaking) - warning: breaking changes in `test8` --> $REPO_PATH/tests/cases/traits/new.rs:12:5 | @@ -60,3 +52,41 @@ warning: technically breaking changes in `test9` | = note: added self-argument to method (technically breaking) +warning: breaking changes in `Bcd` + --> $REPO_PATH/tests/cases/traits/new.rs:16:1 + | +16 | pub trait Bcd {} + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: type parameter added (breaking) + +warning: breaking changes in `Cde` + --> $REPO_PATH/tests/cases/traits/new.rs:18:1 + | +18 | pub trait Cde {} + | ^^^^^^^^^^^^^^^^ + | + = warning: type parameter removed (breaking) + +warning: breaking changes in `Def` + --> $REPO_PATH/tests/cases/traits/new.rs:20:1 + | +20 | / pub trait Def { +21 | | // The method is not broken - the impls are, but calls should work as expected, as +22 | | // long as a proper impl is presented. Maybe this will need some more careful handling. +23 | | fn def(&self, a: B) -> bool; +24 | | } + | |_^ + | + = warning: type parameter added (breaking) + +warning: breaking changes in `Efg` + --> $REPO_PATH/tests/cases/traits/new.rs:26:1 + | +26 | / pub trait Efg { +27 | | fn efg(&self, a: A) -> bool; +28 | | } + | |_^ + | + = warning: type parameter removed (breaking) + From c64a89b7b98bcc3f3b2a5375b9ceb473b9c21dbc Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 20 Jul 2017 17:39:43 +0200 Subject: [PATCH 154/553] Implemented more sane checks for breaking trait items. Fixes #20. --- src/semcheck/changes.rs | 43 ++++++++++++++++++++++++++++++++++++++- src/semcheck/traverse.rs | 2 +- tests/cases/traits/stdout | 8 ++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index e2938a8c6713c..f2e8ebe180e99 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -322,6 +322,38 @@ impl<'tcx> Change<'tcx> { self.changes.push((type_, span)); } + /// Check whether a trait item contains breaking changes preventing further analysis of it's + /// child items. + 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, + RegionParameterAdded | + MethodSelfChanged { now_self: true } | + TraitItemAdded { .. } | + TraitItemRemoved { .. } | + ItemMadePublic | + TypeParameterAdded { .. } | + TraitUnsafetyChanged { .. } | + FnConstChanged { now_const: true } => (), + } + } + + false + } + /// Get the change's category. fn to_category(&self) -> ChangeCategory { self.max.clone() @@ -464,7 +496,16 @@ impl<'tcx> ChangeSet<'tcx> { // we only care about items that were present in both versions. self.changes .get(&old) - .map(|changes| changes.to_category() == Breaking) + .map(|change| change.to_category() == Breaking) + .unwrap_or(false) + } + + /// 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(|change| change.trait_item_breaking()) .unwrap_or(false) } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 0e36f2a8b026a..8ffb823272c35 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -543,7 +543,7 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, if changes.item_breaking(old_def_id) || id_mapping.get_trait_def(&old_def_id) - .map_or(false, |did| changes.item_breaking(did)) { + .map_or(false, |did| changes.trait_item_breaking(did)) { return; } diff --git a/tests/cases/traits/stdout b/tests/cases/traits/stdout index 3c209b5f7e373..5d891631f6525 100644 --- a/tests/cases/traits/stdout +++ b/tests/cases/traits/stdout @@ -36,6 +36,14 @@ note: added defaulted item to trait (technically breaking) 10 | | } | |_____^ +warning: breaking changes in `test7` + --> $REPO_PATH/tests/cases/traits/new.rs:11:5 + | +11 | fn test7() -> u16; + | ^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected u8, found u16 (breaking) + warning: breaking changes in `test8` --> $REPO_PATH/tests/cases/traits/new.rs:12:5 | From 3836591e86412804be3b43d2ad251c2b0bb3ba35 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 21 Jul 2017 11:02:20 +0200 Subject: [PATCH 155/553] Small fixes to help debugging the serde crash of the day. --- Cargo.toml | 3 - src/bin/rust_semverver.rs | 14 +- tests/cases/serde_traits/new.rs | 244 ++++++++++++++++++++++++++++++++ tests/cases/serde_traits/old.rs | 244 ++++++++++++++++++++++++++++++++ tests/cases/serde_traits/stdout | 1 + tests/examples.rs | 116 +++++++-------- 6 files changed, 555 insertions(+), 67 deletions(-) create mode 100644 tests/cases/serde_traits/new.rs create mode 100644 tests/cases/serde_traits/old.rs create mode 100644 tests/cases/serde_traits/stdout diff --git a/Cargo.toml b/Cargo.toml index be8f69a70aeff..207e374dd7fb8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,3 @@ semver = "^0.7.0" [dev-dependencies] quickcheck = "^0.4.1" - -[replace] -"openssl-sys:0.9.13" = { git = "https://github.com/ibabushkin/rust-openssl", branch = "libressl-tmp" } diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 7137102066c1b..a1e49a0342eb5 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -13,7 +13,7 @@ extern crate syntax; use semverver::semcheck::run_analysis; use rustc::hir::def_id::*; -use rustc::session::{config, CompileIncomplete, Session}; +use rustc::session::{config, Session}; use rustc::session::config::{Input, ErrorOutputType}; use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; @@ -155,7 +155,7 @@ fn main() { .expect("need to specify SYSROOT env var during compilation, or use rustup") }; - rustc_driver::in_rustc_thread(|| { + let result = rustc_driver::run(|| { let args: Vec = if std::env::args().any(|s| s == "--sysroot") { std::env::args().collect() } else { @@ -172,10 +172,8 @@ fn main() { }; let mut cc = SemVerVerCompilerCalls::new(version); - let (result, _) = rustc_driver::run_compiler(&args, &mut cc, None, None); - if let Err(CompileIncomplete::Errored(_)) = result { - std::process::exit(1); - } - }) - .expect("rustc thread failed"); + rustc_driver::run_compiler(&args, &mut cc, None, None) + }); + + std::process::exit(result as i32); } diff --git a/tests/cases/serde_traits/new.rs b/tests/cases/serde_traits/new.rs new file mode 100644 index 0000000000000..f3635a2937bdc --- /dev/null +++ b/tests/cases/serde_traits/new.rs @@ -0,0 +1,244 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub trait Error {} + +pub trait Deserializer<'de>: Sized { + type Error: Error; + + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_bool(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_i8(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_i16(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_i32(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_i64(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_u8(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_u16(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_u32(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_u64(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_f32(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_f64(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_char(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_str(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_string(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_bytes(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_byte_buf(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_option(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_unit(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_unit_struct( + self, + name: &'static str, + visitor: V, + ) -> Result + where + V: Visitor<'de>; + + fn deserialize_newtype_struct( + self, + name: &'static str, + visitor: V, + ) -> Result + where + V: Visitor<'de>; + + fn deserialize_seq(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_tuple(self, len: usize, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_tuple_struct( + self, + name: &'static str, + len: usize, + visitor: V, + ) -> Result + where + V: Visitor<'de>; + + fn deserialize_map(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_struct( + self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>; + + fn deserialize_enum( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>; + + fn deserialize_identifier(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_ignored_any(self, visitor: V) -> Result + where + V: Visitor<'de>; +} + +pub trait Visitor<'de>: Sized { + type Value; + + fn visit_bool(self, v: bool) -> Result + where + E: Error; + + fn visit_i8(self, v: i8) -> Result + where + E: Error; + + fn visit_i16(self, v: i16) -> Result + where + E: Error; + + fn visit_i32(self, v: i32) -> Result + where + E: Error; + + fn visit_i64(self, v: i64) -> Result + where + E: Error; + + fn visit_u8(self, v: u8) -> Result + where + E: Error; + + fn visit_u16(self, v: u16) -> Result + where + E: Error; + + fn visit_u32(self, v: u32) -> Result + where + E: Error; + + fn visit_u64(self, v: u64) -> Result + where + E: Error; + + fn visit_f32(self, v: f32) -> Result + where + E: Error; + + fn visit_f64(self, v: f64) -> Result + where + E: Error; + + fn visit_char(self, v: char) -> Result + where + E: Error; + + fn visit_str(self, v: &str) -> Result + where + E: Error; + + fn visit_borrowed_str(self, v: &'de str) -> Result + where + E: Error; + + fn visit_string(self, v: String) -> Result + where + E: Error; + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: Error; + + fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result + where + E: Error; + + fn visit_byte_buf(self, v: Vec) -> Result + where + E: Error; + + fn visit_none(self) -> Result + where + E: Error; + + fn visit_some(self, deserializer: D) -> Result + where + D: Deserializer<'de>; + + fn visit_unit(self) -> Result + where + E: Error; + + fn visit_newtype_struct(self, deserializer: D) -> Result + where + D: Deserializer<'de>; +} diff --git a/tests/cases/serde_traits/old.rs b/tests/cases/serde_traits/old.rs new file mode 100644 index 0000000000000..f3635a2937bdc --- /dev/null +++ b/tests/cases/serde_traits/old.rs @@ -0,0 +1,244 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub trait Error {} + +pub trait Deserializer<'de>: Sized { + type Error: Error; + + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_bool(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_i8(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_i16(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_i32(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_i64(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_u8(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_u16(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_u32(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_u64(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_f32(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_f64(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_char(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_str(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_string(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_bytes(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_byte_buf(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_option(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_unit(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_unit_struct( + self, + name: &'static str, + visitor: V, + ) -> Result + where + V: Visitor<'de>; + + fn deserialize_newtype_struct( + self, + name: &'static str, + visitor: V, + ) -> Result + where + V: Visitor<'de>; + + fn deserialize_seq(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_tuple(self, len: usize, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_tuple_struct( + self, + name: &'static str, + len: usize, + visitor: V, + ) -> Result + where + V: Visitor<'de>; + + fn deserialize_map(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_struct( + self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>; + + fn deserialize_enum( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>; + + fn deserialize_identifier(self, visitor: V) -> Result + where + V: Visitor<'de>; + + fn deserialize_ignored_any(self, visitor: V) -> Result + where + V: Visitor<'de>; +} + +pub trait Visitor<'de>: Sized { + type Value; + + fn visit_bool(self, v: bool) -> Result + where + E: Error; + + fn visit_i8(self, v: i8) -> Result + where + E: Error; + + fn visit_i16(self, v: i16) -> Result + where + E: Error; + + fn visit_i32(self, v: i32) -> Result + where + E: Error; + + fn visit_i64(self, v: i64) -> Result + where + E: Error; + + fn visit_u8(self, v: u8) -> Result + where + E: Error; + + fn visit_u16(self, v: u16) -> Result + where + E: Error; + + fn visit_u32(self, v: u32) -> Result + where + E: Error; + + fn visit_u64(self, v: u64) -> Result + where + E: Error; + + fn visit_f32(self, v: f32) -> Result + where + E: Error; + + fn visit_f64(self, v: f64) -> Result + where + E: Error; + + fn visit_char(self, v: char) -> Result + where + E: Error; + + fn visit_str(self, v: &str) -> Result + where + E: Error; + + fn visit_borrowed_str(self, v: &'de str) -> Result + where + E: Error; + + fn visit_string(self, v: String) -> Result + where + E: Error; + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: Error; + + fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result + where + E: Error; + + fn visit_byte_buf(self, v: Vec) -> Result + where + E: Error; + + fn visit_none(self) -> Result + where + E: Error; + + fn visit_some(self, deserializer: D) -> Result + where + D: Deserializer<'de>; + + fn visit_unit(self) -> Result + where + E: Error; + + fn visit_newtype_struct(self, deserializer: D) -> Result + where + D: Deserializer<'de>; +} diff --git a/tests/cases/serde_traits/stdout b/tests/cases/serde_traits/stdout new file mode 100644 index 0000000000000..f8c2af4c949b7 --- /dev/null +++ b/tests/cases/serde_traits/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/tests/examples.rs b/tests/examples.rs index 5fad9695d52a3..e3e54f604b90e 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -19,65 +19,68 @@ macro_rules! test { let old_rlib = path.join("libold.rlib"); let new_rlib = path.join("libnew.rlib"); - let stdout = File::create(&out_file).expect("could not create `stdout` file"); - - success &= Command::new("rustc") - .args(&["--crate-type=lib", "-o", old_rlib.to_str().unwrap()]) - .arg(path.join("old.rs")) - .env("RUST_BACKTRACE", "full") - .stdin(Stdio::null()) - .status() - .expect("could not run rustc") - .success(); - - assert!(success, "couldn't compile old"); - - success &= Command::new("rustc") - .args(&["--crate-type=lib", "-o", new_rlib.to_str().unwrap()]) - .arg(path.join("new.rs")) - .env("RUST_BACKTRACE", "full") - .stdin(Stdio::null()) - .status() - .expect("could not run rustc") - .success(); - - assert!(success, "couldn't compile new"); - - let mut sed_child = Command::new("sed") - .arg(&subst) - .stdin(Stdio::piped()) - .stdout(stdout) - .spawn() - .expect("could not run sed"); - - let (err_pipe, out_pipe) = if let Some(ref stdin) = sed_child.stdin { - let fd = stdin.as_raw_fd(); - unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } - } else { - panic!("could not pipe to sed"); - }; - - success &= Command::new("./target/debug/rust-semverver") - .args(&["--crate-type=lib", - "--extern", &format!("old={}", old_rlib.to_str().unwrap()), - "--extern", &format!("new={}", new_rlib.to_str().unwrap()), - "tests/helper/test.rs"]) - .env("RUST_LOG", "debug") - .env("RUST_BACKTRACE", "full") - .env("RUST_SEMVER_CRATE_VERSION", "1.0.0") - .stdin(Stdio::null()) - .stdout(out_pipe) - .stderr(err_pipe) - .status() - .expect("could not run rust-semverver") - .success(); - - assert!(success, "rust-semverver"); - - success &= sed_child.wait().expect("could not wait for sed child").success(); + { + let stdout = File::create(&out_file).expect("could not create `stdout` file"); + + success &= Command::new("rustc") + .args(&["--crate-type=lib", "-o", old_rlib.to_str().unwrap()]) + .arg(path.join("old.rs")) + .env("RUST_BACKTRACE", "full") + .stdin(Stdio::null()) + .status() + .expect("could not run rustc") + .success(); + + assert!(success, "couldn't compile old"); + + success &= Command::new("rustc") + .args(&["--crate-type=lib", "-o", new_rlib.to_str().unwrap()]) + .arg(path.join("new.rs")) + .env("RUST_BACKTRACE", "full") + .stdin(Stdio::null()) + .status() + .expect("could not run rustc") + .success(); + + assert!(success, "couldn't compile new"); + + let mut sed_child = Command::new("sed") + .arg(&subst) + .stdin(Stdio::piped()) + .stdout(stdout) + .spawn() + .expect("could not run sed"); + + let (err_pipe, out_pipe) = if let Some(ref stdin) = sed_child.stdin { + let fd = stdin.as_raw_fd(); + unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } + } else { + panic!("could not pipe to sed"); + }; + + success &= Command::new("./target/debug/rust-semverver") + .args(&["--crate-type=lib", + "--extern", &format!("old={}", old_rlib.to_str().unwrap()), + "--extern", &format!("new={}", new_rlib.to_str().unwrap()), + "tests/helper/test.rs"]) + .env("RUST_LOG", "debug") + .env("RUST_BACKTRACE", "full") + .env("RUST_SEMVER_CRATE_VERSION", "1.0.0") + .stdin(Stdio::null()) + .stdout(out_pipe) + .stderr(err_pipe) + .status() + .expect("could not run rust-semverver") + .success(); + + assert!(success, "rust-semverver"); + + success &= sed_child.wait().expect("could not wait for sed child").success(); + } assert!(success, "sed"); + eprintln!("path: {}", out_file.to_str().unwrap()); success &= Command::new("git") .args(&["diff", "--quiet", out_file.to_str().unwrap()]) .status() @@ -106,6 +109,7 @@ test!(pathologic_paths, "tests/cases/pathologic_paths"); test!(pub_use, "tests/cases/pub_use"); test!(removal, "tests/cases/removal"); test!(removal_path, "tests/cases/removal_path"); +test!(serde_traits, "tests/cases/serde_traits"); test!(structs, "tests/cases/structs"); test!(traits, "tests/cases/traits"); test!(ty_alias, "tests/cases/ty_alias"); From acaaf7c3e514ef658185fd4bf7da0a6a1ec8b24d Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 22 Jul 2017 12:53:36 +0200 Subject: [PATCH 156/553] Avoid crashes when region inference comes into play. Some of the implemented behaviour still needs fixes, as documented by the new test. --- src/semcheck/traverse.rs | 50 ++++--- tests/cases/regions/new.rs | 17 +++ tests/cases/regions/old.rs | 17 +++ tests/cases/regions/stdout | 49 +++++++ tests/cases/serde_traits/new.rs | 244 -------------------------------- tests/cases/serde_traits/old.rs | 244 -------------------------------- tests/cases/serde_traits/stdout | 1 - tests/examples.rs | 4 +- 8 files changed, 116 insertions(+), 510 deletions(-) create mode 100644 tests/cases/regions/new.rs create mode 100644 tests/cases/regions/old.rs create mode 100644 tests/cases/regions/stdout delete mode 100644 tests/cases/serde_traits/new.rs delete mode 100644 tests/cases/serde_traits/old.rs delete mode 100644 tests/cases/serde_traits/stdout diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 8ffb823272c35..470a43e3d6dd8 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -592,7 +592,12 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, old: Ty<'tcx>, new: Ty<'tcx>) { use syntax_pos::DUMMY_SP; + use rustc::infer::InferOk; + use rustc::middle::free_region::FreeRegionMap; + use rustc::middle::region::RegionMaps; + use rustc::traits::ObligationCause; use rustc::ty::{Lift, ReEarlyBound}; + use rustc::ty::TypeVariants::*; let substs = Substs::identity_for_item(tcx, new_def_id); let old = fold_to_new(id_mapping, tcx, old_def_id, &old).subst(tcx, substs); @@ -612,11 +617,26 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let new = new.subst(infcx.tcx, new_substs); - if let Err(err) = infcx.can_eq(tcx.param_env(new_def_id), old, new) { - let err = match infcx.fully_resolve(&err) { - Ok(res) => res, - Err(err) => panic!("err: {:?}", err), - }; + let param_env = tcx.param_env(new_def_id); + let origin = &ObligationCause::dummy(); + let error = infcx.at(origin, param_env).eq(old, new); + + if let Err(err) = error { + let region_maps = RegionMaps::new(); + let mut free_regions = FreeRegionMap::new(); + free_regions.relate_free_regions_from_predicates(¶m_env.caller_bounds); + infcx.resolve_regions_and_report_errors(new_def_id, ®ion_maps, &free_regions); + + let err = infcx.resolve_type_vars_if_possible(&err); + let err = err.fold_with(&mut BottomUpFolder { tcx: infcx.tcx, fldop: |ty| { + match ty.sty { + TyRef(region, tm) if region.needs_infer() => { + infcx.tcx.mk_ref(tcx.types.re_erased, tm) + }, + TyInfer(_) => tcx.mk_ty(TyError), + _ => ty, + } + }}); changes.add_change(TypeChanged { error: err.lift_to_tcx(tcx).unwrap() }, old_def_id, @@ -632,21 +652,13 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, old: &T) -> T where T: TypeFoldable<'tcx> { - use rustc::ty::{AdtDef, Binder, BoundRegion, EarlyBoundRegion, ExistentialProjection, + use rustc::ty::{AdtDef, Binder, EarlyBoundRegion, ExistentialProjection, ExistentialTraitRef, Region, RegionKind}; use rustc::ty::ExistentialPredicate::*; use rustc::ty::TypeVariants::*; - fn replace_bound_region_did(id_mapping: &IdMapping, region: &BoundRegion) -> BoundRegion { - use rustc::ty::BoundRegion::BrNamed; - - match *region { - BrNamed(def_id, name) => BrNamed(id_mapping.get_new_id(def_id), name), - reg => reg, - } - } - fn replace_region_did<'tcx>(id_mapping: &IdMapping, region: Region<'tcx>) -> RegionKind { + use rustc::ty::BoundRegion::BrNamed; use rustc::ty::FreeRegion; use rustc::ty::RegionKind::*; @@ -660,13 +672,13 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, ReEarlyBound(new_early) }, - ReLateBound(index, region) => { - ReLateBound(index, replace_bound_region_did(id_mapping, ®ion)) - }, ReFree(FreeRegion { scope, bound_region }) => { ReFree(FreeRegion { scope: id_mapping.get_new_id(scope), - bound_region: replace_bound_region_did(id_mapping, &bound_region), + bound_region: match bound_region { + BrNamed(def_id, name) => BrNamed(id_mapping.get_new_id(def_id), name), + reg => reg, + }, }) }, reg => reg, diff --git a/tests/cases/regions/new.rs b/tests/cases/regions/new.rs new file mode 100644 index 0000000000000..b99ca05947923 --- /dev/null +++ b/tests/cases/regions/new.rs @@ -0,0 +1,17 @@ +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::IntoIter; + +pub type E = T; + +pub fn abc(_: &bool) { } + +pub fn def(_: bool) { } + +pub fn efg(_: &str) { } + +pub fn fgh(_: &'static str) { } diff --git a/tests/cases/regions/old.rs b/tests/cases/regions/old.rs new file mode 100644 index 0000000000000..494ba7e6cc273 --- /dev/null +++ b/tests/cases/regions/old.rs @@ -0,0 +1,17 @@ +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::Item; + +pub type E = T::Item; + +pub fn abc(_: bool) { } + +pub fn def(_: &bool) { } + +pub fn efg(_: &'static str) { } + +pub fn fgh(_: &str) { } diff --git a/tests/cases/regions/stdout b/tests/cases/regions/stdout new file mode 100644 index 0000000000000..0a32f06942292 --- /dev/null +++ b/tests/cases/regions/stdout @@ -0,0 +1,49 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: breaking changes in `D` + --> $REPO_PATH/tests/cases/regions/new.rs:7:1 + | +7 | pub type D = T::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected std::iter::IntoIterator::Item, found std::iter::IntoIterator::IntoIter (breaking) + +warning: breaking changes in `E` + --> $REPO_PATH/tests/cases/regions/new.rs:9:1 + | +9 | pub type E = T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected associated type, found type parameter (breaking) + +warning: breaking changes in `abc` + --> $REPO_PATH/tests/cases/regions/new.rs:11:1 + | +11 | pub fn abc(_: &bool) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected bool, found reference (breaking) + +warning: breaking changes in `def` + --> $REPO_PATH/tests/cases/regions/new.rs:13:1 + | +13 | pub fn def(_: bool) { } + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected reference, found bool (breaking) + +warning: breaking changes in `efg` + --> $REPO_PATH/tests/cases/regions/new.rs:15:1 + | +15 | pub fn efg(_: &str) { } + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected bound lifetime parameterBrAnon(0), found concrete lifetime (breaking) + +warning: breaking changes in `fgh` + --> $REPO_PATH/tests/cases/regions/new.rs:17:1 + | +17 | pub fn fgh(_: &'static str) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected bound lifetime parameterBrAnon(0), found concrete lifetime (breaking) + diff --git a/tests/cases/serde_traits/new.rs b/tests/cases/serde_traits/new.rs deleted file mode 100644 index f3635a2937bdc..0000000000000 --- a/tests/cases/serde_traits/new.rs +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright 2017 Serde Developers -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub trait Error {} - -pub trait Deserializer<'de>: Sized { - type Error: Error; - - fn deserialize_any(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_bool(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_i8(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_i16(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_i32(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_i64(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_u8(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_u16(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_u32(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_u64(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_f32(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_f64(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_char(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_str(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_string(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_bytes(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_byte_buf(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_option(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_unit(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_unit_struct( - self, - name: &'static str, - visitor: V, - ) -> Result - where - V: Visitor<'de>; - - fn deserialize_newtype_struct( - self, - name: &'static str, - visitor: V, - ) -> Result - where - V: Visitor<'de>; - - fn deserialize_seq(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_tuple(self, len: usize, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_tuple_struct( - self, - name: &'static str, - len: usize, - visitor: V, - ) -> Result - where - V: Visitor<'de>; - - fn deserialize_map(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_struct( - self, - name: &'static str, - fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>; - - fn deserialize_enum( - self, - name: &'static str, - variants: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>; - - fn deserialize_identifier(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_ignored_any(self, visitor: V) -> Result - where - V: Visitor<'de>; -} - -pub trait Visitor<'de>: Sized { - type Value; - - fn visit_bool(self, v: bool) -> Result - where - E: Error; - - fn visit_i8(self, v: i8) -> Result - where - E: Error; - - fn visit_i16(self, v: i16) -> Result - where - E: Error; - - fn visit_i32(self, v: i32) -> Result - where - E: Error; - - fn visit_i64(self, v: i64) -> Result - where - E: Error; - - fn visit_u8(self, v: u8) -> Result - where - E: Error; - - fn visit_u16(self, v: u16) -> Result - where - E: Error; - - fn visit_u32(self, v: u32) -> Result - where - E: Error; - - fn visit_u64(self, v: u64) -> Result - where - E: Error; - - fn visit_f32(self, v: f32) -> Result - where - E: Error; - - fn visit_f64(self, v: f64) -> Result - where - E: Error; - - fn visit_char(self, v: char) -> Result - where - E: Error; - - fn visit_str(self, v: &str) -> Result - where - E: Error; - - fn visit_borrowed_str(self, v: &'de str) -> Result - where - E: Error; - - fn visit_string(self, v: String) -> Result - where - E: Error; - - fn visit_bytes(self, v: &[u8]) -> Result - where - E: Error; - - fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result - where - E: Error; - - fn visit_byte_buf(self, v: Vec) -> Result - where - E: Error; - - fn visit_none(self) -> Result - where - E: Error; - - fn visit_some(self, deserializer: D) -> Result - where - D: Deserializer<'de>; - - fn visit_unit(self) -> Result - where - E: Error; - - fn visit_newtype_struct(self, deserializer: D) -> Result - where - D: Deserializer<'de>; -} diff --git a/tests/cases/serde_traits/old.rs b/tests/cases/serde_traits/old.rs deleted file mode 100644 index f3635a2937bdc..0000000000000 --- a/tests/cases/serde_traits/old.rs +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright 2017 Serde Developers -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub trait Error {} - -pub trait Deserializer<'de>: Sized { - type Error: Error; - - fn deserialize_any(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_bool(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_i8(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_i16(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_i32(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_i64(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_u8(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_u16(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_u32(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_u64(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_f32(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_f64(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_char(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_str(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_string(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_bytes(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_byte_buf(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_option(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_unit(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_unit_struct( - self, - name: &'static str, - visitor: V, - ) -> Result - where - V: Visitor<'de>; - - fn deserialize_newtype_struct( - self, - name: &'static str, - visitor: V, - ) -> Result - where - V: Visitor<'de>; - - fn deserialize_seq(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_tuple(self, len: usize, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_tuple_struct( - self, - name: &'static str, - len: usize, - visitor: V, - ) -> Result - where - V: Visitor<'de>; - - fn deserialize_map(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_struct( - self, - name: &'static str, - fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>; - - fn deserialize_enum( - self, - name: &'static str, - variants: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>; - - fn deserialize_identifier(self, visitor: V) -> Result - where - V: Visitor<'de>; - - fn deserialize_ignored_any(self, visitor: V) -> Result - where - V: Visitor<'de>; -} - -pub trait Visitor<'de>: Sized { - type Value; - - fn visit_bool(self, v: bool) -> Result - where - E: Error; - - fn visit_i8(self, v: i8) -> Result - where - E: Error; - - fn visit_i16(self, v: i16) -> Result - where - E: Error; - - fn visit_i32(self, v: i32) -> Result - where - E: Error; - - fn visit_i64(self, v: i64) -> Result - where - E: Error; - - fn visit_u8(self, v: u8) -> Result - where - E: Error; - - fn visit_u16(self, v: u16) -> Result - where - E: Error; - - fn visit_u32(self, v: u32) -> Result - where - E: Error; - - fn visit_u64(self, v: u64) -> Result - where - E: Error; - - fn visit_f32(self, v: f32) -> Result - where - E: Error; - - fn visit_f64(self, v: f64) -> Result - where - E: Error; - - fn visit_char(self, v: char) -> Result - where - E: Error; - - fn visit_str(self, v: &str) -> Result - where - E: Error; - - fn visit_borrowed_str(self, v: &'de str) -> Result - where - E: Error; - - fn visit_string(self, v: String) -> Result - where - E: Error; - - fn visit_bytes(self, v: &[u8]) -> Result - where - E: Error; - - fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result - where - E: Error; - - fn visit_byte_buf(self, v: Vec) -> Result - where - E: Error; - - fn visit_none(self) -> Result - where - E: Error; - - fn visit_some(self, deserializer: D) -> Result - where - D: Deserializer<'de>; - - fn visit_unit(self) -> Result - where - E: Error; - - fn visit_newtype_struct(self, deserializer: D) -> Result - where - D: Deserializer<'de>; -} diff --git a/tests/cases/serde_traits/stdout b/tests/cases/serde_traits/stdout deleted file mode 100644 index f8c2af4c949b7..0000000000000 --- a/tests/cases/serde_traits/stdout +++ /dev/null @@ -1 +0,0 @@ -version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/tests/examples.rs b/tests/examples.rs index e3e54f604b90e..83bf658b3bae0 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -59,7 +59,7 @@ macro_rules! test { }; success &= Command::new("./target/debug/rust-semverver") - .args(&["--crate-type=lib", + .args(&["--crate-type=lib", "-Zverbose", "--extern", &format!("old={}", old_rlib.to_str().unwrap()), "--extern", &format!("new={}", new_rlib.to_str().unwrap()), "tests/helper/test.rs"]) @@ -107,9 +107,9 @@ test!(macros, "tests/cases/macros"); test!(mix, "tests/cases/mix"); test!(pathologic_paths, "tests/cases/pathologic_paths"); test!(pub_use, "tests/cases/pub_use"); +test!(regions, "tests/cases/regions"); test!(removal, "tests/cases/removal"); test!(removal_path, "tests/cases/removal_path"); -test!(serde_traits, "tests/cases/serde_traits"); test!(structs, "tests/cases/structs"); test!(traits, "tests/cases/traits"); test!(ty_alias, "tests/cases/ty_alias"); From 7aa83d304b3ade1dfcdef854a61d97cb7ecfa6a5 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 22 Jul 2017 13:17:55 +0200 Subject: [PATCH 157/553] Added an assertion to guard against future improvements. Once it doesn't hold, we can return to improve our depending code. --- src/semcheck/traverse.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 470a43e3d6dd8..d56ee55acc4bd 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -619,7 +619,10 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let param_env = tcx.param_env(new_def_id); let origin = &ObligationCause::dummy(); - let error = infcx.at(origin, param_env).eq(old, new); + let error = infcx + .at(origin, param_env) + .eq(old, new) + .map(|InferOk { obligations: o, .. }| { assert_eq!(o, vec![]); }); if let Err(err) = error { let region_maps = RegionMaps::new(); From 1a69751476f81c0737207b12073907f72716e269 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 22 Jul 2017 13:48:48 +0200 Subject: [PATCH 158/553] Fixed a few small issues: trait item handling and clippy. Trait items from traits that are not accessible from outside the crate are no longer treated as public. --- src/semcheck/traverse.rs | 14 ++++++++++---- tests/cases/traits/new.rs | 6 ++++++ tests/cases/traits/old.rs | 6 ++++++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index d56ee55acc4bd..46320148499e2 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -202,7 +202,12 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, false, o_def_id, n_def_id); - diff_traits(changes, id_mapping, tcx, o_def_id, n_def_id); + diff_traits(changes, + id_mapping, + tcx, + o_def_id, + n_def_id, + output); }, // non-matching item pair - register the difference and abort _ => { @@ -385,7 +390,8 @@ fn diff_traits(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, old: DefId, - new: DefId) { + new: DefId, + output: bool) { use rustc::hir::Unsafety::Unsafe; let old_unsafety = tcx.trait_def(old).unsafety; @@ -425,7 +431,7 @@ fn diff_traits(changes: &mut ChangeSet, *name, tcx.def_span(old_def_id), tcx.def_span(new_def_id), - true); // TODO: bad to do this unconditionally + output); diff_generics(changes, id_mapping, tcx, true, old_def_id, new_def_id); diff_method(changes, tcx, old_item, new_item); @@ -627,7 +633,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, if let Err(err) = error { let region_maps = RegionMaps::new(); let mut free_regions = FreeRegionMap::new(); - free_regions.relate_free_regions_from_predicates(¶m_env.caller_bounds); + free_regions.relate_free_regions_from_predicates(param_env.caller_bounds); infcx.resolve_regions_and_report_errors(new_def_id, ®ion_maps, &free_regions); let err = infcx.resolve_type_vars_if_possible(&err); diff --git a/tests/cases/traits/new.rs b/tests/cases/traits/new.rs index c8ed72e475e9d..00e9d1247a7ad 100644 --- a/tests/cases/traits/new.rs +++ b/tests/cases/traits/new.rs @@ -26,3 +26,9 @@ pub trait Def { pub trait Efg { fn efg(&self, a: A) -> bool; } + +mod fgh { + pub trait Fgh { + fn fgh(&self) -> u8; + } +} diff --git a/tests/cases/traits/old.rs b/tests/cases/traits/old.rs index 87104729f9d5d..c9229aa8f4bb9 100644 --- a/tests/cases/traits/old.rs +++ b/tests/cases/traits/old.rs @@ -24,3 +24,9 @@ pub trait Def { pub trait Efg { fn efg(&self, a: B) -> bool; } + +mod fgh { + pub trait Fgh { + fn fgh(&self) -> bool; + } +} From 74f375647984e8014b2d6d703e1babb192255c7d Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 22 Jul 2017 14:20:30 +0200 Subject: [PATCH 159/553] Addressed necessary changes in mismatch handling. --- src/semcheck/mismatch.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 5d4040c892ee8..db675db9779a2 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -101,7 +101,6 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { use rustc::ty::TypeVariants::*; - // TODO: maybe fetch def ids from TyClosure let matching = match (&a.sty, &b.sty) { (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs)) => { if self.check_substs(a_substs, b_substs) { @@ -160,13 +159,14 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { None }, (&TyDynamic(a_obj, a_r), &TyDynamic(b_obj, b_r)) => { - // TODO let _ = self.relate(&a_r, &b_r)?; - if let (Some(a), Some(b)) = (a_obj.principal(), b_obj.principal()) { - let _ = self.relate(&a, &b); // TODO: kill this? - Some((a.skip_binder().def_id, b.skip_binder().def_id)) - } else { - None + + match (a_obj.principal(), b_obj.principal()) { + (Some(a), Some(b)) if self.check_substs(a.0.substs, b.0.substs) => { + let _ = self.relate(&a.0.substs, &b.0.substs)?; + Some((a.skip_binder().def_id, b.skip_binder().def_id)) + }, + _ => None, } }, (&TyTuple(as_, _), &TyTuple(bs, _)) => { From 92c4f19c02fc41be2c2398d5733492972dd9e355 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 22 Jul 2017 22:29:31 +0200 Subject: [PATCH 160/553] Cleaned up represenatation of definition additions and removals. --- src/semcheck/changes.rs | 12 ++++++++++-- tests/cases/addition/stdout | 18 +++--------------- tests/cases/addition_path/stdout | 6 +----- tests/cases/pathologic_paths/stdout | 12 ++---------- tests/cases/removal/stdout | 18 +++--------------- 5 files changed, 19 insertions(+), 47 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index f2e8ebe180e99..58d366365bc0b 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -120,11 +120,19 @@ impl PathChange { let mut builder = session.struct_span_warn(self.def_span, &msg); for removed_span in &self.removals { - builder.span_warn(*removed_span, "removed path (breaking)"); + if *removed_span == self.def_span { + builder.note("removed definition (breaking)"); + } else { + builder.span_warn(*removed_span, "removed path (breaking)"); + } } for added_span in &self.additions { - builder.span_note(*added_span, "added path (technically breaking)"); + if *added_span == self.def_span { + builder.note("added definition (technically breaking)"); + } else { + builder.span_note(*added_span, "added path (technically breaking)"); + } } builder.emit(); diff --git a/tests/cases/addition/stdout b/tests/cases/addition/stdout index 9fcd03ffbc36d..f055ada1b54b9 100644 --- a/tests/cases/addition/stdout +++ b/tests/cases/addition/stdout @@ -23,11 +23,7 @@ warning: path changes to `Abc` 1 | pub struct Abc; | ^^^^^^^^^^^^^^^ | -note: added path (technically breaking) - --> $REPO_PATH/tests/cases/addition/new.rs:1:1 - | -1 | pub struct Abc; - | ^^^^^^^^^^^^^^^ + = note: added definition (technically breaking) warning: path changes to `a` --> $REPO_PATH/tests/cases/addition/new.rs:7:1 @@ -35,11 +31,7 @@ warning: path changes to `a` 7 | } | ^ | -note: added path (technically breaking) - --> $REPO_PATH/tests/cases/addition/new.rs:7:1 - | -7 | } - | ^ + = note: added definition (technically breaking) warning: path changes to `Cde` --> $REPO_PATH/tests/cases/addition/new.rs:11:5 @@ -47,9 +39,5 @@ warning: path changes to `Cde` 11 | pub struct Cde; | ^^^^^^^^^^^^^^^ | -note: added path (technically breaking) - --> $REPO_PATH/tests/cases/addition/new.rs:11:5 - | -11 | pub struct Cde; - | ^^^^^^^^^^^^^^^ + = note: added definition (technically breaking) diff --git a/tests/cases/addition_path/stdout b/tests/cases/addition_path/stdout index 372a0108eb81b..d10d3201cba1b 100644 --- a/tests/cases/addition_path/stdout +++ b/tests/cases/addition_path/stdout @@ -27,9 +27,5 @@ warning: path changes to `d` 17 | } | ^ | -note: added path (technically breaking) - --> $REPO_PATH/tests/cases/addition_path/new.rs:17:1 - | -17 | } - | ^ + = note: added definition (technically breaking) diff --git a/tests/cases/pathologic_paths/stdout b/tests/cases/pathologic_paths/stdout index 9fcf3b6e35838..3caab879b7026 100644 --- a/tests/cases/pathologic_paths/stdout +++ b/tests/cases/pathologic_paths/stdout @@ -5,11 +5,7 @@ warning: path changes to `a` 5 | pub mod a { blow!($($rest)*); } | ^^^^^^^^^^^^^^^^^^^ | -note: added path (technically breaking) - --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:5:21 - | -5 | pub mod a { blow!($($rest)*); } - | ^^^^^^^^^^^^^^^^^^^ + = note: added definition (technically breaking) warning: path changes to `b` --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:6:21 @@ -17,9 +13,5 @@ warning: path changes to `b` 6 | pub mod b { pub use super::a::*; } | ^^^^^^^^^^^^^^^^^^^^^^ | -note: added path (technically breaking) - --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:6:21 - | -6 | pub mod b { pub use super::a::*; } - | ^^^^^^^^^^^^^^^^^^^^^^ + = note: added definition (technically breaking) diff --git a/tests/cases/removal/stdout b/tests/cases/removal/stdout index 3800937d8a6fb..cc94b5c867e68 100644 --- a/tests/cases/removal/stdout +++ b/tests/cases/removal/stdout @@ -5,11 +5,7 @@ warning: path changes to `Abc` 1 | pub struct Abc; | ^^^^^^^^^^^^^^^ | -warning: removed path (breaking) - --> $REPO_PATH/tests/cases/removal/old.rs:1:1 - | -1 | pub struct Abc; - | ^^^^^^^^^^^^^^^ + = note: removed definition (breaking) warning: breaking changes in `Bcd` --> $REPO_PATH/tests/cases/removal/new.rs:2:1 @@ -25,11 +21,7 @@ warning: path changes to `a` 7 | } | ^ | -warning: removed path (breaking) - --> $REPO_PATH/tests/cases/removal/old.rs:7:1 - | -7 | } - | ^ + = note: removed definition (breaking) warning: breaking changes in `b` --> $REPO_PATH/tests/cases/removal/new.rs:6:1 @@ -45,9 +37,5 @@ warning: path changes to `Cde` 11 | pub struct Cde; | ^^^^^^^^^^^^^^^ | -warning: removed path (breaking) - --> $REPO_PATH/tests/cases/removal/old.rs:11:5 - | -11 | pub struct Cde; - | ^^^^^^^^^^^^^^^ + = note: removed definition (breaking) From 63377fc0e74dca71134e5ad46a25fa27d9f10882 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 22 Jul 2017 22:39:02 +0200 Subject: [PATCH 161/553] Added a swap-test for an edge case in path change recovery. --- tests/cases/swap/new.rs | 7 +++++++ tests/cases/swap/old.rs | 7 +++++++ tests/cases/swap/stdout | 1 + tests/cases/traits/dump | 12 ++++++++++++ tests/examples.rs | 1 + 5 files changed, 28 insertions(+) create mode 100644 tests/cases/swap/new.rs create mode 100644 tests/cases/swap/old.rs create mode 100644 tests/cases/swap/stdout create mode 100644 tests/cases/traits/dump diff --git a/tests/cases/swap/new.rs b/tests/cases/swap/new.rs new file mode 100644 index 0000000000000..2ee685eb5ef46 --- /dev/null +++ b/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/tests/cases/swap/old.rs b/tests/cases/swap/old.rs new file mode 100644 index 0000000000000..8cc7e4a0538c7 --- /dev/null +++ b/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/tests/cases/swap/stdout b/tests/cases/swap/stdout new file mode 100644 index 0000000000000..f8c2af4c949b7 --- /dev/null +++ b/tests/cases/swap/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/tests/cases/traits/dump b/tests/cases/traits/dump new file mode 100644 index 0000000000000..39016fb73f227 --- /dev/null +++ b/tests/cases/traits/dump @@ -0,0 +1,12 @@ +13:28:48 eddyb | you need a fulfillment context that you put in all the bounds of the new item +13:28:59 eddyb | (and assuming you used the translated old bounds as the ParamEnv) +13:29:11 eddyb | (or rather, translated tcx.param_env(old_def_id)) +13:29:30 eddyb | you should be able to call the resolve_or_error or whatever it is thing +13:29:55 eddyb | once you do that, impls are pretty easy +13:30:03 twk | no, I didn't yet do this :P. But it seems I'll find most of what I need from browsing ParamEnv and friends +13:30:20 eddyb | rustc::traits::fulfill +13:30:22 eddyb | that's the important part +13:31:07 twk | okay, I'll report back once there's something which doesn't fall over all the time +13:31:09 eddyb | so for impls: for every old impl, e.g. impl Trait for X, check that X: Trait still holds, after translating (both X and Trait) to the new +13:31:37 eddyb | it's the same fulfillment context thing as making sure the bounds are satisfied +13:31:48 twk | hm, okay diff --git a/tests/examples.rs b/tests/examples.rs index 83bf658b3bae0..c7c7988cf410c 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -111,5 +111,6 @@ test!(regions, "tests/cases/regions"); test!(removal, "tests/cases/removal"); test!(removal_path, "tests/cases/removal_path"); test!(structs, "tests/cases/structs"); +test!(swap, "tests/cases/swap"); test!(traits, "tests/cases/traits"); test!(ty_alias, "tests/cases/ty_alias"); From 59e9b189f22d1d786ebbb054fb270e2fbdf3ef58 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 23 Jul 2017 11:01:03 +0200 Subject: [PATCH 162/553] A delayed path removal processing scheme. Fixes #19. --- src/semcheck/traverse.rs | 33 +++++++++++++++++++++++++++------ tests/cases/mix/stdout | 17 +++++------------ tests/cases/removal_path/stdout | 2 +- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 46320148499e2..5778db102e3c6 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -74,6 +74,10 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, let mut visited = HashSet::new(); let mut children = NameMapping::default(); let mut mod_queue = VecDeque::new(); + // 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(); mod_queue.push_back((old, new, Public, Public)); @@ -222,10 +226,11 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, continue; } - if old_vis == Public && cstore.visibility(o.def.def_id()) == Public { - let o_did = o.def.def_id(); - changes.new_path(o_did, o.ident.name, tcx.def_span(o_did)); - changes.add_path_removal(o_did, o.span); + let o_did = o.def.def_id(); + + if old_vis == Public && cstore.visibility(o_did) == Public { + // delay the handling of removals until the id mapping is complete + removals.push(o); } } (None, Some(n)) => { @@ -234,8 +239,9 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, continue; } - if new_vis == Public && cstore.visibility(n.def.def_id()) == Public { - let n_did = n.def.def_id(); + let n_did = n.def.def_id(); + + if new_vis == Public && cstore.visibility(n_did) == Public { changes.new_path(n_did, n.ident.name, tcx.def_span(n_did)); changes.add_path_addition(n_did, n.span); } @@ -244,6 +250,21 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, } } } + + // finally, process item removals + for o in removals.drain(..) { + let o_did = o.def.def_id(); + + // reuse an already existing path change entry, if possible + if id_mapping.contains_id(o_did) { + let n_did = id_mapping.get_new_id(o_did); + changes.new_path(n_did, o.ident.name, tcx.def_span(n_did)); + changes.add_path_removal(n_did, o.span); + } else { + changes.new_path(o_did, o.ident.name, tcx.def_span(o_did)); + changes.add_path_removal(o_did, o.span); + } + } } /// Given two fn items, perform structural checks. diff --git a/tests/cases/mix/stdout b/tests/cases/mix/stdout index 9ab4197b80e40..0d97584e7d951 100644 --- a/tests/cases/mix/stdout +++ b/tests/cases/mix/stdout @@ -1,16 +1,4 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 -warning: path changes to `Abc` - --> $REPO_PATH/tests/cases/mix/old.rs:2:5 - | -2 | pub struct Abc; - | ^^^^^^^^^^^^^^^ - | -warning: removed path (breaking) - --> $REPO_PATH/tests/cases/mix/old.rs:10:9 - | -10| pub use self::a::Abc; - | ^^^^^^^^^^^^ - warning: breaking changes in `Abc` --> $REPO_PATH/tests/cases/mix/new.rs:2:5 | @@ -33,6 +21,11 @@ warning: path changes to `Abc` 2 | pub enum Abc {} | ^^^^^^^^^^^^^^^ | +warning: removed path (breaking) + --> $REPO_PATH/tests/cases/mix/old.rs:10:9 + | +10| pub use self::a::Abc; + | ^^^^^^^^^^^^ note: added path (technically breaking) --> $REPO_PATH/tests/cases/mix/new.rs:7:13 | diff --git a/tests/cases/removal_path/stdout b/tests/cases/removal_path/stdout index 35cdaae23254d..6d20e64c5fb52 100644 --- a/tests/cases/removal_path/stdout +++ b/tests/cases/removal_path/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 warning: path changes to `Abc` - --> $REPO_PATH/tests/cases/removal_path/old.rs:2:5 + --> $REPO_PATH/tests/cases/removal_path/new.rs:2:5 | 2 | pub struct Abc; | ^^^^^^^^^^^^^^^ From 0320bc27b2277fe654f86980f96a3634422488fe Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 23 Jul 2017 12:56:30 +0200 Subject: [PATCH 163/553] Misc improvements to docs and item naming. Some removals. --- src/bin/cargo_semver.rs | 14 ++++-- src/bin/rust_semverver.rs | 26 +++++----- src/semcheck/changes.rs | 94 ++++++++++++++++++++--------------- src/semcheck/mapping.rs | 13 ++--- src/semcheck/mismatch.rs | 24 ++++----- src/semcheck/traverse.rs | 100 +++++++++++++++++++------------------- 6 files changed, 147 insertions(+), 124 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 9ef96fd4ee5de..791f3bce2abf1 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -105,7 +105,7 @@ impl<'a> WorkInfo<'a> { }) } - /// Obtain the paths to the rlib produced and to the output directory for dependencies. + /// Obtain the paths to the produced rlib and the dependency output directory. fn rlib_and_dep_output(&self, config: &'a Config, name: &str) -> CargoResult<(PathBuf, PathBuf)> { @@ -123,8 +123,8 @@ impl<'a> WorkInfo<'a> { /// Perform the heavy lifting. /// -/// Obtain the local crate and compile it, then fetch the latest version from the registry, and -/// build it as well. +/// Obtain the two versions of the crate to be analyzed as specified by command line arguments +/// and/or defaults, and dispatch the actual analysis. // TODO: possibly reduce the complexity by finding where some info can be taken from directly fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { fn parse_arg(opt: &str) -> CargoResult<(&str, &str)> { @@ -204,8 +204,7 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { .map_err(|e| human(format!("could not spawn rustc: {}", e)))?; if let Some(ref mut stdin) = child.stdin { - stdin - .write_fmt(format_args!("extern crate new; extern crate old;"))?; + stdin.write_fmt(format_args!("extern crate new; extern crate old;"))?; } else { return Err(human("could not pipe to rustc (wtf?)")); } @@ -217,15 +216,20 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { Ok(()) } +/// Print a help message. fn help(opts: &Options) { let brief = "usage: cargo semver [options] [-- cargo options]"; print!("{}", opts.usage(brief)); } +/// Print a version message. fn version() { println!("{}", env!("CARGO_PKG_VERSION")); } +/// Main entry point. +/// +/// Parse CLI arguments, handle their semantics, and provide for proper error handling. fn main() { fn err(config: &Config, e: Box) -> ! { exit_with_error(CliError::new(e, 1), &mut config.shell()); diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index a1e49a0342eb5..319455f7c8b16 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -23,9 +23,9 @@ use std::process::Command; use syntax::ast; -/// After the typechecker has finished it's work, we perform our checks. +/// After the typechecker has finished it's work, perform our checks. /// -/// To compare the two well-typed crates, we first find the aptly named crates `new` and `old`, +/// To compare the two well-typed crates, first find the aptly named crates `new` and `old`, /// find their root modules and then proceed to walk their module trees. fn callback(state: &driver::CompileState, version: &str) { let tcx = state.tcx.unwrap(); @@ -45,7 +45,7 @@ fn callback(state: &driver::CompileState, version: &str) { } }); - let (old_did, new_did) = if let (Some(c0), Some(c1)) = cnums { + let (old_def_id, new_def_id) = if let (Some(c0), Some(c1)) = cnums { (DefId { krate: c0, index: CRATE_DEF_INDEX, @@ -59,18 +59,21 @@ fn callback(state: &driver::CompileState, version: &str) { return; }; - let changes = run_analysis(tcx, old_did, new_did); + let changes = run_analysis(tcx, old_def_id, new_def_id); changes.output(tcx.sess, version); } -/// Our wrapper to control compilation. +/// A wrapper to control compilation. struct SemVerVerCompilerCalls { + /// The wrapped compilation handle. default: RustcDefaultCalls, + /// The version of the old crate. version: String, } impl SemVerVerCompilerCalls { + /// Construct a new compilation wrapper, given a version string. pub fn new(version: String) -> SemVerVerCompilerCalls { SemVerVerCompilerCalls { default: RustcDefaultCalls, @@ -119,13 +122,14 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { matches: &getopts::Matches) -> driver::CompileController<'a> { let mut controller = self.default.build_controller(sess, matches); - - let old_callback = std::mem::replace(&mut controller.after_analysis.callback, box |_| {}); + let old_callback = + std::mem::replace(&mut controller.after_analysis.callback, box |_| {}); let version = self.version.clone(); + controller.after_analysis.callback = box move |state| { - callback(state, &version); - old_callback(state); - }; + callback(state, &version); + old_callback(state); + }; controller.after_analysis.stop = Compilation::Stop; controller @@ -168,7 +172,7 @@ fn main() { let version = if let Ok(ver) = std::env::var("RUST_SEMVER_CRATE_VERSION") { ver } else { - std::process::exit(1); + "no_version".to_owned() }; let mut cc = SemVerVerCompilerCalls::new(version); diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 58d366365bc0b..cebcd2506498c 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -3,7 +3,10 @@ //! 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 these data structures, too. +//! 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 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::session::Session; @@ -21,9 +24,10 @@ use syntax_pos::Span; /// 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. +/// 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. /// /// [1]: https://github.com/rust-lang/rfcs/blob/master/text/1105-api-evolution.md #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] @@ -61,8 +65,9 @@ impl<'a> fmt::Display for ChangeCategory { /// A change record of newly introduced or removed paths to an item. /// -/// It is important to note that the `Eq` and `Ord` instances are constucted to only -/// regard the span of the associated item definition. +/// It is important to note that the `Eq` and `Ord` instances are constucted 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. name: Symbol, @@ -72,10 +77,11 @@ pub struct PathChange { additions: BTreeSet, /// The set of spans of removed exports of the item. removals: BTreeSet, + // TODO: do we need an `output` member here as well? } impl PathChange { - /// Construct a new empty change record for an item. + /// Construct a new empty path change record for an item. fn new(name: Symbol, def_span: Span) -> PathChange { PathChange { name: name, @@ -85,7 +91,7 @@ impl PathChange { } } - /// Insert a new span addition or deletion. + /// 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); @@ -110,7 +116,7 @@ impl PathChange { &self.def_span } - /// Report the change. + /// Report the change in a structured manner. fn report(&self, session: &Session) { if self.to_category() == Patch { return; @@ -205,6 +211,7 @@ pub enum ChangeType<'tcx> { pub use self::ChangeType::*; impl<'tcx> ChangeType<'tcx> { + /// Get the change type's category. pub fn to_category(&self) -> ChangeCategory { match *self { ItemMadePrivate | @@ -289,19 +296,19 @@ impl<'a> fmt::Display for ChangeType<'a> { } } -/// A change record of an item kept between versions. +/// A change record of an item present in both crate versions. /// /// It is important to note that the `Eq` and `Ord` instances are constucted to only -/// regard the *new* span of the associated item export. This allows us to sort them +/// 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 type of the change affecting the item. + /// The types of changes affecting the item, with optional subspans. changes: Vec<(ChangeType<'tcx>, Option)>, /// The most severe change category already recorded for the item. max: ChangeCategory, - /// The symbol associated with the change item. + /// The name of the item. name: Symbol, - /// The new span associated with the change item. + /// The new definition span of the item. new_span: Span, /// Whether to output changes. Used to distinguish all-private items. output: bool @@ -319,8 +326,8 @@ impl<'tcx> Change<'tcx> { } } - /// Add another change type to the change record. - fn add(&mut self, type_: ChangeType<'tcx>, span: Option) { + /// Insert another change type into an existing path change record. + fn insert(&mut self, type_: ChangeType<'tcx>, span: Option) { let cat = type_.to_category(); if cat > self.max { @@ -332,6 +339,8 @@ impl<'tcx> Change<'tcx> { /// 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 { @@ -372,18 +381,13 @@ impl<'tcx> Change<'tcx> { &self.new_span } - /// Get the ident of the change item. - fn ident(&self) -> &Symbol { - &self.name - } - - /// Report the change. + /// Report the change in a structured manner. fn report(&self, session: &Session) { if self.max == Patch || !self.output { return; } - let msg = format!("{} changes in `{}`", self.max, self.ident()); + let msg = format!("{} changes in `{}`", self.max, self.name); let mut builder = session.struct_span_warn(self.new_span, &msg); for change in &self.changes { @@ -441,7 +445,7 @@ pub struct ChangeSet<'tcx> { impl<'tcx> ChangeSet<'tcx> { /// Add a new path change entry for the given item. - pub fn new_path(&mut self, old: DefId, name: Symbol, def_span: Span) { + pub fn new_path_change(&mut self, old: DefId, name: Symbol, def_span: Span) { self.spans .entry(def_span) .or_insert_with(|| old); @@ -473,17 +477,17 @@ impl<'tcx> ChangeSet<'tcx> { /// Add a new change entry for the given items. pub fn new_change(&mut self, - old_did: DefId, - new_did: DefId, + old_def_id: DefId, + new_def_id: DefId, name: Symbol, old_span: Span, new_span: Span, output: bool) { let change = Change::new(name, new_span, output); - self.spans.insert(old_span, old_did); - self.spans.insert(new_span, new_did); - self.changes.insert(old_did, change); + 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 to an already existing entry. @@ -494,7 +498,7 @@ impl<'tcx> ChangeSet<'tcx> { self.max = cat.clone(); } - self.changes.get_mut(&old).unwrap().add(type_, span); + self.changes.get_mut(&old).unwrap().insert(type_, span); } /// Check whether an item with the given id has undergone breaking changes. @@ -556,6 +560,7 @@ pub mod tests { use syntax_pos::hygiene::SyntaxContext; use syntax_pos::symbol::Interner; + /// A wrapper for `Span` that can be randomly generated. #[derive(Clone, Debug)] pub struct Span_(Span); @@ -577,6 +582,7 @@ pub mod tests { } } + /// A wrapper for `DefId` that can be randomly generated. #[derive(Clone, Debug)] pub struct DefId_(DefId); @@ -599,7 +605,7 @@ pub mod tests { } } - // a rip-off of the real `ChangeType` - but this one can be generated. + /// a rip-off of the real `ChangeType` that can be randomly generated. #[derive(Clone, Debug)] pub enum ChangeType_ { ItemMadePublic, @@ -685,8 +691,10 @@ pub mod tests { } } + /// A wrapper type used to construct `Change`s. pub type Change_ = (DefId_, DefId_, Span_, Span_, bool, Vec<(ChangeType_, Option)>); + /// Construct `Change`s from things that can be generated. fn build_change<'a>(s1: Span, output: bool, mut changes: Vec<(ChangeType_, Option)>) -> Change<'a> { @@ -694,14 +702,16 @@ pub mod tests { let mut change = Change::new(interner.intern("test"), s1, output); for (type_, span) in changes.drain(..) { - change.add(type_.inner(), span.map(|s| s.inner())); + 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, mut spans: Vec<(bool, Span)>) -> PathChange { let mut interner = Interner::new(); let mut change = PathChange::new(interner.intern("test"), s1); @@ -764,7 +774,8 @@ pub mod tests { res } - /// The maximal change category for a change set gets computed correctly. + /// The maximal change category for a change set with regular changes only gets computed + /// correctly. fn max_pchange(changes: Vec) -> bool { let mut set = ChangeSet::default(); @@ -780,7 +791,7 @@ pub mod tests { for &(ref did, ref span, ref spans) in &changes { let def_id = did.clone().inner(); - set.new_path(def_id, name, span.clone().inner()); + set.new_path_change(def_id, name, span.clone().inner()); for &(add, ref span) in spans { if add { @@ -794,7 +805,8 @@ pub mod tests { set.max == max } - /// The maximal change category for a change set gets computed correctly. + /// The maximal change category for a change set with path changes only gets computed + /// correctly. fn max_change(changes: Vec) -> bool { let mut set = ChangeSet::default(); @@ -808,10 +820,10 @@ pub mod tests { .max() .unwrap_or(Patch); - for &(ref o_did, ref n_did, ref o_span, ref n_span, out, ref sub) in &changes { - let old_did = o_did.clone().inner(); - set.new_change(old_did, - n_did.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(), @@ -819,7 +831,7 @@ pub mod tests { for &(ref type_, ref span_) in sub { set.add_change(type_.clone().inner(), - old_did, + old_def_id, span_.clone().map(|s| s.inner())); } } @@ -827,6 +839,8 @@ pub mod tests { set.max == max } + // TODO: a test for mixed change sets + /// 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(); diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 99b019c7c9d23..6cbef888a9596 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -11,21 +11,22 @@ use std::collections::{BTreeSet, HashMap, VecDeque}; use syntax::ast::Name; -/// A mapping from old to new `DefId`s, as well as exports. +/// A mapping from old to new `DefId`s, as well as associated definitions, if applicable. /// -/// Exports 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. +/// 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. #[derive(Default)] pub struct IdMapping { /// Toplevel items' old `DefId` mapped to old and new `Def`. toplevel_mapping: HashMap, /// Trait items' old `DefId` mapped to old and new `Def`. trait_item_mapping: HashMap, - /// Other item's old `DefId` mapped to new `DefId`. + /// Other items' old `DefId` mapped to new `DefId`. internal_mapping: HashMap, /// Children mapping, allowing us to enumerate descendants in `AdtDef`s. child_mapping: HashMap>, - /// Set of new defaulted type parameters. + /// Map of type parameters' `DefId`s and their definitions. type_params: HashMap, } @@ -100,7 +101,7 @@ impl IdMapping { self.trait_item_mapping.get(item_def_id).map(|t| t.2) } - /// Tell us whether a `DefId` is present in the mappings. + /// Check whether a `DefId` is present in the mappings. pub fn contains_id(&self, old: DefId) -> bool { self.toplevel_mapping.contains_key(&old) || self.trait_item_mapping.contains_key(&old) || diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index db675db9779a2..3f03cb9181a21 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -1,6 +1,6 @@ //! 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 yet not matched with other items are +//! Any two items' types found in the same place which are not matched yet with other items are //! essentially just 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. @@ -48,21 +48,20 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> Mismatch<'a, 'gcx, 'tcx> { pub fn process(&mut self) { use rustc::hir::def::Def::*; - while let Some((old_did, new_did)) = self.item_queue.pop_front() { - match self.tcx.describe_def(old_did) { + while let Some((old_def_id, new_def_id)) = self.item_queue.pop_front() { + match self.tcx.describe_def(old_def_id) { Some(Trait(_)) | Some(Macro(_, _)) => continue, _ => (), } - let old_ty = self.tcx.type_of(old_did); - let new_ty = self.tcx.type_of(new_did); + let old_ty = self.tcx.type_of(old_def_id); + let new_ty = self.tcx.type_of(new_def_id); let _ = self.relate(&old_ty, &new_ty); } } - fn check_substs(&self, a_substs: &'tcx Substs<'tcx>, b_substs: &'tcx Substs<'tcx>) - -> bool - { + /// Ensure that the pair of given `Substs` is suitable for being related. + fn check_substs(&self, a_substs: &'tcx Substs<'tcx>, b_substs: &'tcx Substs<'tcx>) -> bool { for (a, b) in a_substs.iter().zip(b_substs) { if a.as_type().is_some() != b.as_type().is_some() { return false; @@ -191,10 +190,11 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { _ => None, }; - if let Some((old_did, new_did)) = matching { - if !self.id_mapping.contains_id(old_did) && old_did.krate == self.old_crate { - self.id_mapping.add_internal_item(old_did, new_did); - self.item_queue.push_back((old_did, new_did)); + if let Some((old_def_id, new_def_id)) = matching { + // TODO: implement proper crate tracking and fix this then. + if !self.id_mapping.contains_id(old_def_id) && old_def_id.krate == self.old_crate { + self.id_mapping.add_internal_item(old_def_id, new_def_id); + self.item_queue.push_back((old_def_id, new_def_id)); } } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 5778db102e3c6..2e5860de44e7d 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -81,42 +81,42 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, mod_queue.push_back((old, new, Public, Public)); - while let Some((old_did, new_did, old_vis, new_vis)) = mod_queue.pop_front() { - children.add(cstore.item_children(old_did, tcx.sess), - cstore.item_children(new_did, tcx.sess)); + while let Some((old_def_id, new_def_id, old_vis, new_vis)) = mod_queue.pop_front() { + children.add(cstore.item_children(old_def_id, tcx.sess), + cstore.item_children(new_def_id, tcx.sess)); for items in children.drain() { match items { (Some(o), Some(n)) => { - if let (Mod(o_did), Mod(n_did)) = (o.def, n.def) { - if visited.insert((o_did, n_did)) { + if let (Mod(o_def_id), Mod(n_def_id)) = (o.def, n.def) { + if visited.insert((o_def_id, n_def_id)) { let o_vis = if old_vis == Public { - cstore.visibility(o_did) + cstore.visibility(o_def_id) } else { old_vis }; let n_vis = if new_vis == Public { - cstore.visibility(n_did) + cstore.visibility(n_def_id) } else { new_vis }; if o_vis != n_vis { - changes.new_change(o_did, - n_did, + changes.new_change(o_def_id, + n_def_id, o.ident.name, - tcx.def_span(o_did), - tcx.def_span(n_did), + tcx.def_span(o_def_id), + tcx.def_span(n_def_id), true); if o_vis == Public && n_vis != Public { - changes.add_change(ItemMadePrivate, o_did, None); + changes.add_change(ItemMadePrivate, o_def_id, None); } else if o_vis != Public && n_vis == Public { - changes.add_change(ItemMadePublic, o_did, None); + changes.add_change(ItemMadePublic, o_def_id, None); } } - mod_queue.push_back((o_did, n_did, o_vis, n_vis)); + mod_queue.push_back((o_def_id, n_def_id, o_vis, n_vis)); } } else if id_mapping.add_export(o.def, n.def) { // struct constructors are weird/hard - let's go shopping! @@ -226,9 +226,9 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, continue; } - let o_did = o.def.def_id(); + let o_def_id = o.def.def_id(); - if old_vis == Public && cstore.visibility(o_did) == Public { + if old_vis == Public && cstore.visibility(o_def_id) == Public { // delay the handling of removals until the id mapping is complete removals.push(o); } @@ -239,11 +239,11 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, continue; } - let n_did = n.def.def_id(); + let n_def_id = n.def.def_id(); - if new_vis == Public && cstore.visibility(n_did) == Public { - changes.new_path(n_did, n.ident.name, tcx.def_span(n_did)); - changes.add_path_addition(n_did, n.span); + if new_vis == Public && cstore.visibility(n_def_id) == Public { + 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); } } (None, None) => unreachable!(), @@ -253,16 +253,16 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, // finally, process item removals for o in removals.drain(..) { - let o_did = o.def.def_id(); + let o_def_id = o.def.def_id(); // reuse an already existing path change entry, if possible - if id_mapping.contains_id(o_did) { - let n_did = id_mapping.get_new_id(o_did); - changes.new_path(n_did, o.ident.name, tcx.def_span(n_did)); - changes.add_path_removal(n_did, o.span); + if id_mapping.contains_id(o_def_id) { + let n_def_id = id_mapping.get_new_id(o_def_id); + 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 { - changes.new_path(o_did, o.ident.name, tcx.def_span(o_did)); - changes.add_path_removal(o_did, o.span); + 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); } } } @@ -293,8 +293,8 @@ fn diff_method(changes: &mut ChangeSet, tcx: TyCtxt, old: AssociatedItem, new: A /// Given two ADT items, perform structural checks. /// -/// This establishes the needed correspondence relationship between non-toplevel items such as -/// enum variants, struct fields etc. +/// 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, @@ -405,8 +405,8 @@ fn diff_adts(changes: &mut ChangeSet, /// Given two trait items, perform structural checks. /// -/// This establishes the needed correspondence relationship between non-toplevel items found in -/// the trait definition. +/// This establishes the needed correspondence between non-toplevel items found in the trait +/// definition. fn diff_traits(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, @@ -428,16 +428,16 @@ fn diff_traits(changes: &mut ChangeSet, let mut items = BTreeMap::new(); - for old_did in tcx.associated_item_def_ids(old).iter() { - let item = tcx.associated_item(*old_did); + for old_def_id in tcx.associated_item_def_ids(old).iter() { + let item = tcx.associated_item(*old_def_id); items.entry(item.name).or_insert((None, None)).0 = - tcx.describe_def(*old_did).map(|d| (d, item)); + tcx.describe_def(*old_def_id).map(|d| (d, item)); } - for new_did in tcx.associated_item_def_ids(new).iter() { - let item = tcx.associated_item(*new_did); + for new_def_id in tcx.associated_item_def_ids(new).iter() { + let item = tcx.associated_item(*new_def_id); items.entry(item.name).or_insert((None, None)).1 = - tcx.describe_def(*new_did).map(|d| (d, item)); + tcx.describe_def(*new_def_id).map(|d| (d, item)); } for (name, item_pair) in &items { @@ -598,9 +598,9 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, }, Struct(_) | Enum(_) | Union(_) => { if let Some(children) = id_mapping.children_of(old_def_id) { - for (o_did, n_did) in children { - let o_ty = tcx.type_of(o_did); - let n_ty = tcx.type_of(n_did); + 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); } @@ -733,8 +733,8 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, old.fold_with(&mut BottomUpFolder { tcx: tcx, fldop: |ty| { match ty.sty { TyAdt(&AdtDef { ref did, .. }, substs) if id_mapping.contains_id(*did) => { - let new_did = id_mapping.get_new_id(*did); - let new_adt = tcx.adt_def(new_did); + let new_def_id = id_mapping.get_new_id(*did); + let new_adt = tcx.adt_def(new_def_id); tcx.mk_adt(new_adt, substs) }, TyRef(region, type_and_mut) => { @@ -747,26 +747,26 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, let new_preds = tcx.mk_existential_predicates(preds.iter().map(|p| { match *p.skip_binder() { Trait(ExistentialTraitRef { def_id: did, substs }) => { - let new_did = if id_mapping.contains_id(did) { + let new_def_id = if id_mapping.contains_id(did) { id_mapping.get_new_id(did) } else { did }; Trait(ExistentialTraitRef { - def_id: new_did, + def_id: new_def_id, substs: substs }) }, Projection(ExistentialProjection { item_def_id, substs, ty }) => { - let new_did = if id_mapping.contains_id(item_def_id) { + let new_def_id = if id_mapping.contains_id(item_def_id) { id_mapping.get_new_id(item_def_id) } else { item_def_id }; Projection(ExistentialProjection { - item_def_id: new_did, + item_def_id: new_def_id, substs: substs, ty: ty, }) @@ -784,13 +784,13 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx.mk_dynamic(Binder(new_preds), region) }, TyProjection(proj) => { - let new_did = if id_mapping.contains_id(proj.item_def_id) { + let new_def_id = if id_mapping.contains_id(proj.item_def_id) { id_mapping.get_new_id(proj.item_def_id) } else { proj.item_def_id }; - tcx.mk_projection(new_did, proj.substs) + tcx.mk_projection(new_def_id, proj.substs) }, TyAnon(did, substs) => { tcx.mk_anon(id_mapping.get_new_id(did), substs) @@ -799,8 +799,8 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, if param.idx != 0 { // `Self` is special let old_did = index_map[¶m.idx]; if id_mapping.contains_id(old_did) { - let new_did = id_mapping.get_new_id(old_did); - tcx.mk_param_from_def(&id_mapping.get_type_param(&new_did)) + let new_def_id = id_mapping.get_new_id(old_did); + tcx.mk_param_from_def(&id_mapping.get_type_param(&new_def_id)) } else { tcx.mk_ty(TyParam(param)) } From 7b98be837e29f7534a71b60498c684cb5ad0cb1a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 23 Jul 2017 13:13:20 +0200 Subject: [PATCH 164/553] Improved tests. --- src/semcheck/changes.rs | 50 ++++++++++++++++++++++++++++++-- tests/cases/addition_path/new.rs | 4 +++ tests/cases/addition_path/old.rs | 4 +++ tests/cases/removal_path/new.rs | 4 +++ tests/cases/removal_path/old.rs | 4 +++ 5 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index cebcd2506498c..f81a317c42198 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -77,7 +77,6 @@ pub struct PathChange { additions: BTreeSet, /// The set of spans of removed exports of the item. removals: BTreeSet, - // TODO: do we need an `output` member here as well? } impl PathChange { @@ -839,7 +838,54 @@ pub mod tests { set.max == max } - // TODO: a test for mixed change sets + fn max_pchange_or_change(pchanges: Vec, changes: Vec) -> bool { + let mut set = ChangeSet::default(); + + let mut interner = Interner::new(); + 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() + .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 { diff --git a/tests/cases/addition_path/new.rs b/tests/cases/addition_path/new.rs index 2c49d124b6471..974eedc5f59ae 100644 --- a/tests/cases/addition_path/new.rs +++ b/tests/cases/addition_path/new.rs @@ -19,3 +19,7 @@ pub mod d { mod e { } + +mod f { + pub use a::Abc; +} diff --git a/tests/cases/addition_path/old.rs b/tests/cases/addition_path/old.rs index dfb2d9265aa23..552dd103cce41 100644 --- a/tests/cases/addition_path/old.rs +++ b/tests/cases/addition_path/old.rs @@ -9,3 +9,7 @@ pub mod b { pub mod c { } + +mod f { + +} diff --git a/tests/cases/removal_path/new.rs b/tests/cases/removal_path/new.rs index dfb2d9265aa23..d4c860740fea5 100644 --- a/tests/cases/removal_path/new.rs +++ b/tests/cases/removal_path/new.rs @@ -9,3 +9,7 @@ pub mod b { pub mod c { } + +mod d { + +} diff --git a/tests/cases/removal_path/old.rs b/tests/cases/removal_path/old.rs index 25228c33a0140..15ce872a6b5d3 100644 --- a/tests/cases/removal_path/old.rs +++ b/tests/cases/removal_path/old.rs @@ -11,3 +11,7 @@ pub mod c { } pub use self::a::Abc; + +mod d { + pub use a::Abc; +} From 60ac97fe8526e32a3637c4f6dc556758593fa758 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 23 Jul 2017 13:56:52 +0200 Subject: [PATCH 165/553] Updated the README. --- README.md | 86 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 75 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 16b2e9c588c14..09b50a3df9a32 100644 --- a/README.md +++ b/README.md @@ -2,22 +2,86 @@ [![Build Status](https://travis-ci.org/ibabushkin/rust-semverver.svg?branch=master)](https://travis-ci.org/ibabushkin/rust-semverver) This repository is hosting a proof-of-concept implementation of an automatic tool checking -rust library crates for semantic versioning adherence. The goal is to provide an automated -command akin to `cargo clippy` that analyzes the current crate's souce code for changes -compared to the most recent version on `crates.io`. +rust library crates for semantic versioning adherence, developed during the Google Summer +of Code 2017. The goal is to provide an automated command akin to `cargo clippy` that +analyzes the current crate's source code for changes compared to the most recent version +on `crates.io`. ## Background The approach taken is to compile both versions of the crate to `rlib`s and to link them as -dependencies of a third crate. Then, a custom compiler driver is run on the resulting -crate and all necessary analysis is performed in that context. +dependencies of a third, empty, crate. Then, a custom compiler driver is run on the +resulting crate and all necessary analysis is performed in that context. -The general concepts and aspects of the algorithms used are outlined in more detail in the -[proposal](https://summerofcode.withgoogle.com/projects/#5063973872336896). +More information on the inner workings will be provided soon. ## Installation -This is currently irrelevant, as the functionality is not yet implemented. Please check -back later. +The tool is implemented as a cargo plugin. As of now, it can be obtained from this git +repository and compiled from source, provided you have a recent Rust nightly installed: + +```sh +$ rustup update nightly +$ rustup default nightly +$ git clone https://github.com/ibabushkin/rust-semverver +$ cd rust-semverver +$ cargo install +``` + +At this point, the current development version can be invoked using `cargo semver` in any +directory your project resides in. If you prefer not to install to `~/.cargo/bin`, you can +invoke it like so after building with a regular `cargo build`: + +```sh +PATH=/path/to/repo/target/debug:$PATH cargo semver +``` + +If you have built using `cargo build --release` instead, change the path to point to the +`release` subdirectory of the `target` directory. ## Usage -This is currently irrelevant, as the functionality is not yet implemented. Please check -back later. +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] [-- cargo options] + +Options: + -h, --help print this message and exit + -V, --version print version information and exit + -d, --debug print command to debug and exit + -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 SPEC + use a name-version string as stable/old crate + -C, --current-pkg SPEC + use a name-version string as current/new crate +``` + +## 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. According to the RFC, +most changes are already recognized correctly, even though trait- and inherent +implementations are not yet handled, and some type checks behave incorrectly. + +At the time of writing, the following types of changes are recognized and classified +correctly: + +* items moving from `pub` to non-`pub` +* 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 +* additions of new and removals of old enum variants +* additions of new and removals of old 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 to and from methods +* addition and removal of (posslibly defaulted) trait items +* changes to the unsafety of a trait +* type changes of all toplevel items + +Yet, the results presented to the user are merely an approximation of the required +versioning policy, especially at such an early stage of development. From 363a56bd9049bd4bbadea6a566b4ef0b5ac30094 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 23 Jul 2017 17:29:57 +0200 Subject: [PATCH 166/553] Implemented crate tracking mechanism for #17. --- src/semcheck/mapping.rs | 27 +++++++++++++++++++++++++-- src/semcheck/mismatch.rs | 10 +++------- src/semcheck/traverse.rs | 4 ++-- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 6cbef888a9596..fc26922d8cf82 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -4,7 +4,7 @@ //! map used to temporarily match up unsorted item sequences' elements by name. use rustc::hir::def::{Def, Export}; -use rustc::hir::def_id::DefId; +use rustc::hir::def_id::{CrateNum, DefId}; use rustc::ty::TypeParameterDef; use std::collections::{BTreeSet, HashMap, VecDeque}; @@ -16,8 +16,11 @@ use syntax::ast::Name; /// 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. -#[derive(Default)] pub struct IdMapping { + /// The old crate. + old_crate: CrateNum, + /// The new crate. + new_crate: CrateNum, /// Toplevel items' old `DefId` mapped to old and new `Def`. toplevel_mapping: HashMap, /// Trait items' old `DefId` mapped to old and new `Def`. @@ -31,6 +34,18 @@ pub struct IdMapping { } impl IdMapping { + pub fn new(old_crate: CrateNum, new_crate: CrateNum) -> IdMapping { + IdMapping { + old_crate: old_crate, + new_crate: new_crate, + toplevel_mapping: HashMap::new(), + trait_item_mapping: HashMap::new(), + internal_mapping: HashMap::new(), + child_mapping: HashMap::new(), + type_params: HashMap::new(), + } + } + /// Register two exports representing the same item across versions. pub fn add_export(&mut self, old: Def, new: Def) -> bool { if self.toplevel_mapping.contains_key(&old.def_id()) { @@ -132,6 +147,14 @@ impl IdMapping { .get(&parent) .map(|m| m.iter().map(move |old| (*old, self.internal_mapping[old]))) } + + pub fn in_old_crate(&self, did: DefId) -> bool { + self.old_crate == did.krate + } + + pub fn in_new_crate(&self, did: DefId) -> bool { + self.new_crate == did.krate + } } /// A mapping from names to pairs of old and new exports. diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 3f03cb9181a21..caf78435f378a 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -4,7 +4,7 @@ //! essentially just 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 rustc::hir::def_id::{CrateNum, DefId}; +use rustc::hir::def_id::DefId; use rustc::ty; use rustc::ty::{Ty, TyCtxt}; use rustc::ty::Visibility::Public; @@ -27,20 +27,17 @@ pub struct Mismatch<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { item_queue: VecDeque<(DefId, DefId)>, /// The id mapping to use. id_mapping: &'a mut IdMapping, - /// The old crate. - old_crate: CrateNum, } impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> Mismatch<'a, 'gcx, 'tcx> { /// Construct a new mismtach type relation. - pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, old_crate: CrateNum, id_mapping: &'a mut IdMapping) + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a mut IdMapping) -> Mismatch<'a, 'gcx, 'tcx> { Mismatch { tcx: tcx, item_queue: id_mapping.toplevel_queue(), id_mapping: id_mapping, - old_crate: old_crate, } } @@ -191,8 +188,7 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { }; if let Some((old_def_id, new_def_id)) = matching { - // TODO: implement proper crate tracking and fix this then. - if !self.id_mapping.contains_id(old_def_id) && old_def_id.krate == self.old_crate { + if !self.id_mapping.contains_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_def_id, new_def_id)); } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 2e5860de44e7d..fc08e411c256b 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -31,14 +31,14 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI -> ChangeSet<'tcx> { let mut changes = Default::default(); - let mut id_mapping = Default::default(); + let mut id_mapping = IdMapping::new(old.krate, new.krate); // first pass diff_structure(&mut changes, &mut id_mapping, tcx, old, new); // second pass { - let mut mismatch = Mismatch::new(tcx, old.krate, &mut id_mapping); + let mut mismatch = Mismatch::new(tcx, &mut id_mapping); mismatch.process(); } From d5944074ecf1fb49e9934d923e43ac8bc3237f98 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 23 Jul 2017 22:23:26 +0200 Subject: [PATCH 167/553] Improved the mapping handling. Closes #17. This uses the newly added crate tracking to make errors more discoverable and code more obvious in it's current behaviour. --- src/semcheck/mapping.rs | 60 ++++++++++++++++++++++++++++++++-------- src/semcheck/mismatch.rs | 17 ++++++------ src/semcheck/traverse.rs | 31 ++++++--------------- 3 files changed, 66 insertions(+), 42 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index fc26922d8cf82..deb51d695f200 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -7,7 +7,7 @@ use rustc::hir::def::{Def, Export}; use rustc::hir::def_id::{CrateNum, DefId}; use rustc::ty::TypeParameterDef; -use std::collections::{BTreeSet, HashMap, VecDeque}; +use std::collections::{BTreeSet, HashMap, HashSet, VecDeque}; use syntax::ast::Name; @@ -23,6 +23,8 @@ pub struct IdMapping { new_crate: CrateNum, /// Toplevel items' old `DefId` mapped to old and new `Def`. toplevel_mapping: HashMap, + /// The set of toplevel items that have been removed. + removed_items: HashSet, /// Trait items' old `DefId` mapped to old and new `Def`. trait_item_mapping: HashMap, /// Other items' old `DefId` mapped to new `DefId`. @@ -39,6 +41,7 @@ impl IdMapping { old_crate: old_crate, new_crate: new_crate, toplevel_mapping: HashMap::new(), + removed_items: HashSet::new(), trait_item_mapping: HashMap::new(), internal_mapping: HashMap::new(), child_mapping: HashMap::new(), @@ -48,19 +51,30 @@ impl IdMapping { /// Register two exports representing the same item across versions. pub fn add_export(&mut self, old: Def, new: Def) -> bool { - if self.toplevel_mapping.contains_key(&old.def_id()) { + let old_def_id = old.def_id(); + + 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)); + .insert(old_def_id, (old, new)); true } + /// Register that an old item has no corresponding new item. + pub fn add_removal(&mut self, old: DefId) { + self.removed_items.insert(old); + } + /// Add any trait item's old and new `DefId`s. pub fn add_trait_item(&mut self, old: Def, new: Def, trait_def_id: DefId) { - self.trait_item_mapping.insert(old.def_id(), (old, new, trait_def_id)); + 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, trait_def_id)); } /// Add any other item's old and new `DefId`s. @@ -70,12 +84,14 @@ impl IdMapping { old, self.internal_mapping[&old], new); + assert!(self.in_old_crate(old)); self.internal_mapping.insert(old, new); } /// Add any other item's old and new `DefId`s, together with a parent entry. pub fn add_subitem(&mut self, parent: DefId, old: DefId, new: DefId) { + // NB: we rely on the assers in `add_internal_item` here. self.add_internal_item(old, new); self.child_mapping .entry(parent) @@ -85,16 +101,18 @@ impl IdMapping { /// Record that a `DefId` represents a new type parameter. pub fn add_type_param(&mut self, new: TypeParameterDef) { + assert!(self.in_new_crate(new.def_id)); self.type_params.insert(new.def_id, new); } /// Get the type parameter represented by a given `DefId`. - pub fn get_type_param(&self, def_id: &DefId) -> TypeParameterDef { - self.type_params[def_id] + pub fn get_type_param(&self, did: &DefId) -> TypeParameterDef { + self.type_params[did] } /// Check whether a `DefId` represents a newly added defaulted type parameter. pub fn is_defaulted_type_param(&self, new: &DefId) -> bool { + // TODO? self.type_params .get(new) .map_or(false, |def| def.has_default) @@ -102,12 +120,30 @@ impl IdMapping { /// Get the new `DefId` associated with the given old one. pub fn get_new_id(&self, old: DefId) -> DefId { - if let Some(new) = self.toplevel_mapping.get(&old) { - new.1.def_id() - } else if let Some(new) = self.trait_item_mapping.get(&old) { - new.1.def_id() + assert!(!self.in_new_crate(old)); + + if self.in_old_crate(old) && !self.removed_items.contains(&old) { + if let Some(new) = self.toplevel_mapping.get(&old) { + new.1.def_id() + } else if let Some(new) = self.trait_item_mapping.get(&old) { + new.1.def_id() + } else { + self.internal_mapping[&old] + } + } else { + old + } + } + + /// Get the new `DefId` associated with the given old one, respecting possibly removed + /// traits that are a parent of the given `DefId`. + pub fn get_new_trait_item_id(&self, old: DefId, trait_id: DefId) -> DefId { + assert!(!self.in_new_crate(trait_id)); + + if !self.removed_items.contains(&trait_id) { + self.get_new_id(old) } else { - self.internal_mapping[&old] + old } } @@ -148,10 +184,12 @@ impl IdMapping { .map(|m| m.iter().map(move |old| (*old, self.internal_mapping[old]))) } + /// 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 } + /// 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 } diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index caf78435f378a..af3c4192cc476 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -111,14 +111,12 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { .collect(); for field in a_adt.all_fields().filter(|f| f.vis == Public) { - if self.id_mapping.contains_id(field.did) { - let a_field_ty = field.ty(self.tcx, a_substs); - let b_field_ty = - b_fields[&self.id_mapping.get_new_id(field.did)] - .ty(self.tcx, b_substs); - - let _ = self.relate(&a_field_ty, &b_field_ty)?; - } + let a_field_ty = field.ty(self.tcx, a_substs); + let b_field_ty = + b_fields[&self.id_mapping.get_new_id(field.did)] + .ty(self.tcx, b_substs); + + let _ = self.relate(&a_field_ty, &b_field_ty)?; } Some((a_def.did, b_def.did)) @@ -188,7 +186,8 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { }; if let Some((old_def_id, new_def_id)) = matching { - if !self.id_mapping.contains_id(old_def_id) && self.id_mapping.in_old_crate(old_def_id) { + if !self.id_mapping.contains_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_def_id, new_def_id)); } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index fc08e411c256b..49e357b36bb0a 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -261,6 +261,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, 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_removal(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); } @@ -732,7 +733,7 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, old.fold_with(&mut BottomUpFolder { tcx: tcx, fldop: |ty| { match ty.sty { - TyAdt(&AdtDef { ref did, .. }, substs) if id_mapping.contains_id(*did) => { + TyAdt(&AdtDef { ref did, .. }, substs) if id_mapping.in_old_crate(*did) => { let new_def_id = id_mapping.get_new_id(*did); let new_adt = tcx.adt_def(new_def_id); tcx.mk_adt(new_adt, substs) @@ -747,11 +748,7 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, let new_preds = tcx.mk_existential_predicates(preds.iter().map(|p| { match *p.skip_binder() { Trait(ExistentialTraitRef { def_id: did, substs }) => { - let new_def_id = if id_mapping.contains_id(did) { - id_mapping.get_new_id(did) - } else { - did - }; + let new_def_id = id_mapping.get_new_id(did); Trait(ExistentialTraitRef { def_id: new_def_id, @@ -759,11 +756,7 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, }) }, Projection(ExistentialProjection { item_def_id, substs, ty }) => { - let new_def_id = if id_mapping.contains_id(item_def_id) { - id_mapping.get_new_id(item_def_id) - } else { - item_def_id - }; + let new_def_id = id_mapping.get_new_id(item_def_id); Projection(ExistentialProjection { item_def_id: new_def_id, @@ -772,11 +765,7 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, }) }, AutoTrait(did) => { - if id_mapping.contains_id(did) { - AutoTrait(id_mapping.get_new_id(did)) - } else { - AutoTrait(did) - } + AutoTrait(id_mapping.get_new_id(did)) }, } })); @@ -784,11 +773,9 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, tcx.mk_dynamic(Binder(new_preds), region) }, TyProjection(proj) => { - let new_def_id = if id_mapping.contains_id(proj.item_def_id) { - id_mapping.get_new_id(proj.item_def_id) - } else { - proj.item_def_id - }; + let trait_def_id = tcx.associated_item(proj.item_def_id).container.id(); + let new_def_id = + id_mapping.get_new_trait_item_id(proj.item_def_id, trait_def_id); tcx.mk_projection(new_def_id, proj.substs) }, @@ -798,7 +785,7 @@ fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, TyParam(param) => { if param.idx != 0 { // `Self` is special let old_did = index_map[¶m.idx]; - if id_mapping.contains_id(old_did) { + if id_mapping.in_old_crate(old_did) { let new_def_id = id_mapping.get_new_id(old_did); tcx.mk_param_from_def(&id_mapping.get_type_param(&new_def_id)) } else { From 73446bdd87951f06d575bbc30e7f4fe6b4904499 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 23 Jul 2017 22:40:49 +0200 Subject: [PATCH 168/553] Implemented a few new tests. --- tests/cases/addition_use/new.rs | 8 ++++++++ tests/cases/addition_use/old.rs | 4 ++++ tests/cases/addition_use/stdout | 29 +++++++++++++++++++++++++++++ tests/cases/removal_use/new.rs | 4 ++++ tests/cases/removal_use/old.rs | 8 ++++++++ tests/cases/removal_use/stdout | 29 +++++++++++++++++++++++++++++ tests/examples.rs | 2 ++ 7 files changed, 84 insertions(+) create mode 100644 tests/cases/addition_use/new.rs create mode 100644 tests/cases/addition_use/old.rs create mode 100644 tests/cases/addition_use/stdout create mode 100644 tests/cases/removal_use/new.rs create mode 100644 tests/cases/removal_use/old.rs create mode 100644 tests/cases/removal_use/stdout diff --git a/tests/cases/addition_use/new.rs b/tests/cases/addition_use/new.rs new file mode 100644 index 0000000000000..64d1e65a5233b --- /dev/null +++ b/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 Bcd, +} diff --git a/tests/cases/addition_use/old.rs b/tests/cases/addition_use/old.rs new file mode 100644 index 0000000000000..0f3c61ee435b0 --- /dev/null +++ b/tests/cases/addition_use/old.rs @@ -0,0 +1,4 @@ +pub struct Def<'a> { + pub field1: (), + pub field2: &'a (), +} diff --git a/tests/cases/addition_use/stdout b/tests/cases/addition_use/stdout new file mode 100644 index 0000000000000..dc8b96fbf106f --- /dev/null +++ b/tests/cases/addition_use/stdout @@ -0,0 +1,29 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: breaking changes in `Def` + --> $REPO_PATH/tests/cases/addition_use/new.rs:5:1 + | +5 | / pub struct Def<'a> { +6 | | pub field1: Abc, +7 | | pub field2: &'a Bcd, +8 | | } + | |_^ + | + = warning: type error: expected (), found struct `new::Abc` (breaking) + = warning: type error: expected (), found trait new::Bcd (breaking) + +warning: path changes to `Abc` + --> $REPO_PATH/tests/cases/addition_use/new.rs:1:1 + | +1 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + +warning: path changes to `Bcd` + --> $REPO_PATH/tests/cases/addition_use/new.rs:3:1 + | +3 | pub trait Bcd {} + | ^^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + diff --git a/tests/cases/removal_use/new.rs b/tests/cases/removal_use/new.rs new file mode 100644 index 0000000000000..0f3c61ee435b0 --- /dev/null +++ b/tests/cases/removal_use/new.rs @@ -0,0 +1,4 @@ +pub struct Def<'a> { + pub field1: (), + pub field2: &'a (), +} diff --git a/tests/cases/removal_use/old.rs b/tests/cases/removal_use/old.rs new file mode 100644 index 0000000000000..64d1e65a5233b --- /dev/null +++ b/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 Bcd, +} diff --git a/tests/cases/removal_use/stdout b/tests/cases/removal_use/stdout new file mode 100644 index 0000000000000..1b48121097d9b --- /dev/null +++ b/tests/cases/removal_use/stdout @@ -0,0 +1,29 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: path changes to `Abc` + --> $REPO_PATH/tests/cases/removal_use/old.rs:1:1 + | +1 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + | + = note: removed definition (breaking) + +warning: path changes to `Bcd` + --> $REPO_PATH/tests/cases/removal_use/old.rs:3:1 + | +3 | pub trait Bcd {} + | ^^^^^^^^^^^^^^^^ + | + = note: removed definition (breaking) + +warning: breaking changes in `Def` + --> $REPO_PATH/tests/cases/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 old::Bcd, found () (breaking) + diff --git a/tests/examples.rs b/tests/examples.rs index c7c7988cf410c..39590447942a8 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -99,6 +99,7 @@ macro_rules! test { test!(addition, "tests/cases/addition"); test!(addition_path, "tests/cases/addition_path"); +test!(addition_use, "tests/cases/addition_use"); test!(enums, "tests/cases/enums"); test!(func, "tests/cases/func"); test!(infer, "tests/cases/infer"); @@ -110,6 +111,7 @@ test!(pub_use, "tests/cases/pub_use"); test!(regions, "tests/cases/regions"); test!(removal, "tests/cases/removal"); test!(removal_path, "tests/cases/removal_path"); +test!(removal_use, "tests/cases/removal_use"); test!(structs, "tests/cases/structs"); test!(swap, "tests/cases/swap"); test!(traits, "tests/cases/traits"); From 9ce161cfe7cef531aea4645cc4b6bf75692c1954 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 24 Jul 2017 17:33:18 +0200 Subject: [PATCH 169/553] Refactored DefId translation mechanism to allow for reuse. --- src/semcheck/mapping.rs | 1 - src/semcheck/mod.rs | 1 + src/semcheck/translate.rs | 143 ++++++++++++++++++++++++++++++++++++++ src/semcheck/traverse.rs | 132 ++--------------------------------- tests/cases/traits/dump | 27 +++---- 5 files changed, 164 insertions(+), 140 deletions(-) create mode 100644 src/semcheck/translate.rs diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index deb51d695f200..4f29c93764e38 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -112,7 +112,6 @@ impl IdMapping { /// Check whether a `DefId` represents a newly added defaulted type parameter. pub fn is_defaulted_type_param(&self, new: &DefId) -> bool { - // TODO? self.type_params .get(new) .map_or(false, |def| def.has_default) diff --git a/src/semcheck/mod.rs b/src/semcheck/mod.rs index 5bbe48119bcd4..1bf94c2125786 100644 --- a/src/semcheck/mod.rs +++ b/src/semcheck/mod.rs @@ -5,6 +5,7 @@ pub mod changes; mod mapping; mod mismatch; +mod translate; mod traverse; pub use self::traverse::run_analysis; diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs new file mode 100644 index 0000000000000..c2dab821dbaca --- /dev/null +++ b/src/semcheck/translate.rs @@ -0,0 +1,143 @@ +use rustc::hir::def_id::DefId; +use rustc::ty::{Region, Ty, TyCtxt}; +use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; + +use semcheck::mapping::IdMapping; + +use std::collections::HashMap; + +/// Translate all old `DefId`s in the object to their new counterparts, if possible. +pub fn translate<'a, 'tcx, T>(id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + index_map: &HashMap, + old: &T) -> T + where T: TypeFoldable<'tcx> +{ + use rustc::ty::{AdtDef, Binder, ExistentialProjection, ExistentialTraitRef}; + use rustc::ty::ExistentialPredicate::*; + use rustc::ty::TypeVariants::*; + + old.fold_with(&mut BottomUpFolder { tcx: tcx, fldop: |ty| { + match ty.sty { + TyAdt(&AdtDef { ref did, .. }, substs) if id_mapping.in_old_crate(*did) => { + let new_def_id = id_mapping.get_new_id(*did); + let new_adt = tcx.adt_def(new_def_id); + tcx.mk_adt(new_adt, substs) + }, + TyRef(region, type_and_mut) => { + tcx.mk_ref(translate_region(tcx, id_mapping, region), type_and_mut) + }, + TyFnDef(did, substs) => { + tcx.mk_fn_def(id_mapping.get_new_id(did), substs) + }, + TyDynamic(preds, region) => { + let new_preds = tcx.mk_existential_predicates(preds.iter().map(|p| { + match *p.skip_binder() { + Trait(ExistentialTraitRef { def_id: did, substs }) => { + let new_def_id = id_mapping.get_new_id(did); + + Trait(ExistentialTraitRef { + def_id: new_def_id, + substs: substs + }) + }, + Projection(ExistentialProjection { item_def_id, substs, ty }) => { + let new_def_id = id_mapping.get_new_id(item_def_id); + + Projection(ExistentialProjection { + item_def_id: new_def_id, + substs: substs, + ty: ty, + }) + }, + AutoTrait(did) => { + AutoTrait(id_mapping.get_new_id(did)) + }, + } + })); + + tcx.mk_dynamic(Binder(new_preds), region) + }, + TyProjection(proj) => { + let trait_def_id = tcx.associated_item(proj.item_def_id).container.id(); + let new_def_id = + id_mapping.get_new_trait_item_id(proj.item_def_id, trait_def_id); + + tcx.mk_projection(new_def_id, proj.substs) + }, + TyAnon(did, substs) => { + tcx.mk_anon(id_mapping.get_new_id(did), substs) + }, + TyParam(param) => { + if param.idx != 0 { // `Self` is special + let old_def_id = index_map[¶m.idx]; + if id_mapping.in_old_crate(old_def_id) { + let new_def_id = id_mapping.get_new_id(old_def_id); + tcx.mk_param_from_def(&id_mapping.get_type_param(&new_def_id)) + } else { + tcx.mk_ty(TyParam(param)) + } + } else { + tcx.mk_ty(TyParam(param)) + } + }, + _ => ty, + } + }}) +} + +/// Translate all old `DefId`s in the region to their new counterparts, if possible. +pub fn translate_region<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + id_mapping: &IdMapping, + region: Region<'tcx>) -> Region<'tcx> { + use rustc::ty::{EarlyBoundRegion, FreeRegion}; + use rustc::ty::BoundRegion::BrNamed; + use rustc::ty::RegionKind::*; + + tcx.mk_region(match *region { + ReEarlyBound(early) => { + let new_early = EarlyBoundRegion { + def_id: id_mapping.get_new_id(early.def_id), + index: early.index, + name: early.name, + }; + + ReEarlyBound(new_early) + }, + ReFree(FreeRegion { scope, bound_region }) => { + ReFree(FreeRegion { + scope: id_mapping.get_new_id(scope), + bound_region: match bound_region { + BrNamed(def_id, name) => BrNamed(id_mapping.get_new_id(def_id), name), + reg => reg, + }, + }) + }, + reg => reg, + }) +} + +/// Translate all old `DefId`s in the type to their new counterparts, if possible. +/// +/// This computes the mapping of type parameters needed as well. +pub fn translate_item_type<'a, 'tcx>(id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + old_def_id: DefId, + old: Ty<'tcx>) -> Ty<'tcx> { + let mut index_map = HashMap::new(); + let old_generics = tcx.generics_of(old_def_id); + + for type_ in &old_generics.types { + index_map.insert(type_.index, type_.def_id); + } + + if let Some(did) = old_generics.parent { + let parent_generics = tcx.generics_of(did); + + for type_ in &parent_generics.types { + index_map.insert(type_.index, type_.def_id); + } + } + + translate(id_mapping, tcx, &index_map, &old) +} diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 49e357b36bb0a..188533cb88ecf 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -21,8 +21,9 @@ use semcheck::changes::ChangeType::*; use semcheck::changes::ChangeSet; use semcheck::mapping::{IdMapping, NameMapping}; use semcheck::mismatch::Mismatch; +use semcheck::translate::translate_item_type; -use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; +use std::collections::{BTreeMap, HashSet, VecDeque}; /// The main entry point to our analysis passes. /// @@ -545,7 +546,8 @@ fn diff_bounds<'a, 'tcx>(_changes: &mut ChangeSet, _new: DefId) -> (Vec>, Vec<(DefId, DefId)>) { - /* let res = Default::default(); + /* let old_param_env = tcx.param_env(old); + let res = Default::default(); let old_preds = tcx.predicates_of(old).predicates; let new_preds = tcx.predicates_of(new).predicates; @@ -628,7 +630,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, use rustc::ty::TypeVariants::*; let substs = Substs::identity_for_item(tcx, new_def_id); - let old = fold_to_new(id_mapping, tcx, old_def_id, &old).subst(tcx, substs); + let old = translate_item_type(id_mapping, tcx, old_def_id, old).subst(tcx, substs); tcx.infer_ctxt().enter(|infcx| { let new_substs = if new.is_fn() { @@ -675,127 +677,3 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } }); } - -/// Fold a type of an old item to be comparable with a new item. -fn fold_to_new<'a, 'tcx, T>(id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - old_def_id: DefId, - old: &T) -> T - where T: TypeFoldable<'tcx> -{ - use rustc::ty::{AdtDef, Binder, EarlyBoundRegion, ExistentialProjection, - ExistentialTraitRef, Region, RegionKind}; - use rustc::ty::ExistentialPredicate::*; - use rustc::ty::TypeVariants::*; - - fn replace_region_did<'tcx>(id_mapping: &IdMapping, region: Region<'tcx>) -> RegionKind { - use rustc::ty::BoundRegion::BrNamed; - use rustc::ty::FreeRegion; - use rustc::ty::RegionKind::*; - - match *region { - ReEarlyBound(early) => { - let new_early = EarlyBoundRegion { - def_id: id_mapping.get_new_id(early.def_id), - index: early.index, - name: early.name, - }; - - ReEarlyBound(new_early) - }, - ReFree(FreeRegion { scope, bound_region }) => { - ReFree(FreeRegion { - scope: id_mapping.get_new_id(scope), - bound_region: match bound_region { - BrNamed(def_id, name) => BrNamed(id_mapping.get_new_id(def_id), name), - reg => reg, - }, - }) - }, - reg => reg, - } - } - - let mut index_map = HashMap::new(); - let old_generics = tcx.generics_of(old_def_id); - - for type_ in &old_generics.types { - index_map.insert(type_.index, type_.def_id); - } - - if let Some(did) = old_generics.parent { - let parent_generics = tcx.generics_of(did); - - for type_ in &parent_generics.types { - index_map.insert(type_.index, type_.def_id); - } - } - - old.fold_with(&mut BottomUpFolder { tcx: tcx, fldop: |ty| { - match ty.sty { - TyAdt(&AdtDef { ref did, .. }, substs) if id_mapping.in_old_crate(*did) => { - let new_def_id = id_mapping.get_new_id(*did); - let new_adt = tcx.adt_def(new_def_id); - tcx.mk_adt(new_adt, substs) - }, - TyRef(region, type_and_mut) => { - tcx.mk_ref(tcx.mk_region(replace_region_did(id_mapping, region)), type_and_mut) - }, - TyFnDef(did, substs) => { - tcx.mk_fn_def(id_mapping.get_new_id(did), substs) - }, - TyDynamic(preds, region) => { - let new_preds = tcx.mk_existential_predicates(preds.iter().map(|p| { - match *p.skip_binder() { - Trait(ExistentialTraitRef { def_id: did, substs }) => { - let new_def_id = id_mapping.get_new_id(did); - - Trait(ExistentialTraitRef { - def_id: new_def_id, - substs: substs - }) - }, - Projection(ExistentialProjection { item_def_id, substs, ty }) => { - let new_def_id = id_mapping.get_new_id(item_def_id); - - Projection(ExistentialProjection { - item_def_id: new_def_id, - substs: substs, - ty: ty, - }) - }, - AutoTrait(did) => { - AutoTrait(id_mapping.get_new_id(did)) - }, - } - })); - - tcx.mk_dynamic(Binder(new_preds), region) - }, - TyProjection(proj) => { - let trait_def_id = tcx.associated_item(proj.item_def_id).container.id(); - let new_def_id = - id_mapping.get_new_trait_item_id(proj.item_def_id, trait_def_id); - - tcx.mk_projection(new_def_id, proj.substs) - }, - TyAnon(did, substs) => { - tcx.mk_anon(id_mapping.get_new_id(did), substs) - }, - TyParam(param) => { - if param.idx != 0 { // `Self` is special - let old_did = index_map[¶m.idx]; - if id_mapping.in_old_crate(old_did) { - let new_def_id = id_mapping.get_new_id(old_did); - tcx.mk_param_from_def(&id_mapping.get_type_param(&new_def_id)) - } else { - tcx.mk_ty(TyParam(param)) - } - } else { - tcx.mk_ty(TyParam(param)) - } - }, - _ => ty, - } - }}) -} diff --git a/tests/cases/traits/dump b/tests/cases/traits/dump index 39016fb73f227..681311cf8672e 100644 --- a/tests/cases/traits/dump +++ b/tests/cases/traits/dump @@ -1,12 +1,15 @@ -13:28:48 eddyb | you need a fulfillment context that you put in all the bounds of the new item -13:28:59 eddyb | (and assuming you used the translated old bounds as the ParamEnv) -13:29:11 eddyb | (or rather, translated tcx.param_env(old_def_id)) -13:29:30 eddyb | you should be able to call the resolve_or_error or whatever it is thing -13:29:55 eddyb | once you do that, impls are pretty easy -13:30:03 twk | no, I didn't yet do this :P. But it seems I'll find most of what I need from browsing ParamEnv and friends -13:30:20 eddyb | rustc::traits::fulfill -13:30:22 eddyb | that's the important part -13:31:07 twk | okay, I'll report back once there's something which doesn't fall over all the time -13:31:09 eddyb | so for impls: for every old impl, e.g. impl Trait for X, check that X: Trait still holds, after translating (both X and Trait) to the new -13:31:37 eddyb | it's the same fulfillment context thing as making sure the bounds are satisfied -13:31:48 twk | hm, okay + you need a fulfillment context that you put in all the bounds of the new item + (and assuming you used the translated old bounds as the ParamEnv) + (or rather, translated tcx.param_env(old_def_id)) + you should be able to call the resolve_or_error or whatever it is thing + once you do that, impls are pretty easy + + it seems I'll find most of what I need from browsing ParamEnv and friends + + rustc::traits::fulfill that's the important part + + okay, I'll report back once there's something which doesn't fall over all the time + + so for impls: for every old impl, e.g. impl Trait for X, check that X: Trait still holds, + after translating (both X and Trait) to the new + it's the same fulfillment context thing as making sure the bounds are satisfied From 8a8f5c04c688863e7d095ebd7acb3a39d93e0af7 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 24 Jul 2017 19:19:12 +0200 Subject: [PATCH 170/553] Implemented param env translation. --- src/lib.rs | 1 + src/semcheck/translate.rs | 140 ++++++++++++++++++++++++++++++++------ 2 files changed, 120 insertions(+), 21 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1857d2c26122d..2d4e6ea720330 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ extern crate quickcheck; extern crate rustc; +extern crate rustc_data_structures; extern crate rustc_errors; extern crate semver; extern crate syntax; diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index c2dab821dbaca..a5857bb8f2610 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -1,16 +1,39 @@ use rustc::hir::def_id::DefId; -use rustc::ty::{Region, Ty, TyCtxt}; +use rustc::ty::{ParamEnv, Predicate, Region, Ty, TyCtxt}; use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; +use rustc_data_structures::accumulate_vec::AccumulateVec; + use semcheck::mapping::IdMapping; use std::collections::HashMap; +/// Construct an parameter index map for an item. +fn construct_index_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old_def_id: DefId) + -> HashMap +{ + let mut index_map = HashMap::new(); + let old_generics = tcx.generics_of(old_def_id); + + for type_ in &old_generics.types { + index_map.insert(type_.index, type_.def_id); + } + if let Some(did) = old_generics.parent { + let parent_generics = tcx.generics_of(did); + + for type_ in &parent_generics.types { + index_map.insert(type_.index, type_.def_id); + } + } + + index_map +} + /// Translate all old `DefId`s in the object to their new counterparts, if possible. -pub fn translate<'a, 'tcx, T>(id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - index_map: &HashMap, - old: &T) -> T +fn translate<'a, 'tcx, T>(id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + index_map: &HashMap, + old: &T) -> T where T: TypeFoldable<'tcx> { use rustc::ty::{AdtDef, Binder, ExistentialProjection, ExistentialTraitRef}; @@ -25,7 +48,7 @@ pub fn translate<'a, 'tcx, T>(id_mapping: &IdMapping, tcx.mk_adt(new_adt, substs) }, TyRef(region, type_and_mut) => { - tcx.mk_ref(translate_region(tcx, id_mapping, region), type_and_mut) + tcx.mk_ref(translate_region(id_mapping, tcx, region), type_and_mut) }, TyFnDef(did, substs) => { tcx.mk_fn_def(id_mapping.get_new_id(did), substs) @@ -87,9 +110,9 @@ pub fn translate<'a, 'tcx, T>(id_mapping: &IdMapping, } /// Translate all old `DefId`s in the region to their new counterparts, if possible. -pub fn translate_region<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - id_mapping: &IdMapping, - region: Region<'tcx>) -> Region<'tcx> { +fn translate_region<'a, 'tcx>(id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + region: Region<'tcx>) -> Region<'tcx> { use rustc::ty::{EarlyBoundRegion, FreeRegion}; use rustc::ty::BoundRegion::BrNamed; use rustc::ty::RegionKind::*; @@ -124,20 +147,95 @@ pub fn translate_item_type<'a, 'tcx>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, old_def_id: DefId, old: Ty<'tcx>) -> Ty<'tcx> { - let mut index_map = HashMap::new(); - let old_generics = tcx.generics_of(old_def_id); + translate(id_mapping, tcx, &construct_index_map(tcx, old_def_id), &old) +} - for type_ in &old_generics.types { - index_map.insert(type_.index, type_.def_id); +/// Translate all old `DefId`s in the predicate to their new counterparts, if possible. +fn translate_predicate<'a, 'tcx>(id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + index_map: &HashMap, + predicate: Predicate<'tcx>) -> Predicate<'tcx> { + use rustc::ty::{EquatePredicate, OutlivesPredicate, ProjectionPredicate, ProjectionTy, + SubtypePredicate, TraitPredicate, TraitRef}; + + match predicate { + Predicate::Trait(trait_predicate) => { + Predicate::Trait(trait_predicate.map_bound(|t_pred| { + TraitPredicate { + trait_ref: TraitRef { + def_id: id_mapping.get_new_id(t_pred.trait_ref.def_id), + substs: t_pred.trait_ref.substs, + } + } + })) + }, + Predicate::Equate(equate_predicate) => { + Predicate::Equate(equate_predicate.map_bound(|e_pred| { + let l = translate(id_mapping, tcx, index_map, &e_pred.0); + let r = translate(id_mapping, tcx, index_map, &e_pred.1); + EquatePredicate(l, r) + })) + }, + Predicate::RegionOutlives(region_outlives_predicate) => { + Predicate::RegionOutlives(region_outlives_predicate.map_bound(|r_pred| { + let l = translate_region(id_mapping, tcx, &r_pred.0); + let r = translate_region(id_mapping, tcx, &r_pred.1); + OutlivesPredicate(l, r) + })) + }, + Predicate::TypeOutlives(type_outlives_predicate) => { + Predicate::TypeOutlives(type_outlives_predicate.map_bound(|r_pred| { + let l = translate(id_mapping, tcx, index_map, &r_pred.0); + let r = translate_region(id_mapping, tcx, &r_pred.1); + OutlivesPredicate(l, r) + })) + }, + Predicate::Projection(projection_predicate) => { + Predicate::Projection(projection_predicate.map_bound(|p_pred| { + ProjectionPredicate { + projection_ty: ProjectionTy { + substs: p_pred.projection_ty.substs, // TODO: maybe this needs handling + item_def_id: id_mapping.get_new_id(p_pred.projection_ty.item_def_id), + }, + ty: translate(id_mapping, tcx, index_map, &p_pred.ty), + } + })) + }, + Predicate::WellFormed(ty) => + Predicate::WellFormed(translate(id_mapping, tcx, index_map, &ty)), + Predicate::ObjectSafe(did) => Predicate::ObjectSafe(id_mapping.get_new_id(did)), + Predicate::ClosureKind(did, kind) => + Predicate::ClosureKind(id_mapping.get_new_id(did), kind), + Predicate::Subtype(subtype_predicate) => { + Predicate::Subtype(subtype_predicate.map_bound(|s_pred| { + let l = translate(id_mapping, tcx, index_map, &s_pred.a); + let r = translate(id_mapping, tcx, index_map, &s_pred.b); + SubtypePredicate { + a_is_expected: s_pred.a_is_expected, + a: l, + b: r, + } + })) + }, } +} - if let Some(did) = old_generics.parent { - let parent_generics = tcx.generics_of(did); - - for type_ in &parent_generics.types { - index_map.insert(type_.index, type_.def_id); - } +/// Translate all old `DefId`s in the `ParamEnv` to their new counterparts, if possible. +/// +/// This computes the mapping of type parameters needed as well. +pub fn translate_param_env<'a, 'tcx>(id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + old_def_id: DefId, + param_env: ParamEnv<'tcx>) -> ParamEnv<'tcx> { + let index_map = construct_index_map(tcx, old_def_id); + let res = param_env + .caller_bounds + .iter() + .map(|p| translate_predicate(id_mapping, tcx, &index_map, *p)) + .collect::>(); + + ParamEnv { + caller_bounds: tcx.intern_predicates(&res), + reveal: param_env.reveal, } - - translate(id_mapping, tcx, &index_map, &old) } From 920d27b2f89477a098ba97b2319d3e6fe7105549 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 25 Jul 2017 12:11:18 +0200 Subject: [PATCH 171/553] Fixed crashes in the framework for bound comparisons. --- src/semcheck/translate.rs | 6 +++--- src/semcheck/traverse.rs | 35 +++++++++++++++++++++++++---------- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index a5857bb8f2610..698dea29583c8 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -178,15 +178,15 @@ fn translate_predicate<'a, 'tcx>(id_mapping: &IdMapping, }, Predicate::RegionOutlives(region_outlives_predicate) => { Predicate::RegionOutlives(region_outlives_predicate.map_bound(|r_pred| { - let l = translate_region(id_mapping, tcx, &r_pred.0); - let r = translate_region(id_mapping, tcx, &r_pred.1); + let l = translate_region(id_mapping, tcx, r_pred.0); + let r = translate_region(id_mapping, tcx, r_pred.1); OutlivesPredicate(l, r) })) }, Predicate::TypeOutlives(type_outlives_predicate) => { Predicate::TypeOutlives(type_outlives_predicate.map_bound(|r_pred| { let l = translate(id_mapping, tcx, index_map, &r_pred.0); - let r = translate_region(id_mapping, tcx, &r_pred.1); + let r = translate_region(id_mapping, tcx, r_pred.1); OutlivesPredicate(l, r) })) }, diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 188533cb88ecf..059c9a8da7cb2 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -21,7 +21,7 @@ use semcheck::changes::ChangeType::*; use semcheck::changes::ChangeSet; use semcheck::mapping::{IdMapping, NameMapping}; use semcheck::mismatch::Mismatch; -use semcheck::translate::translate_item_type; +use semcheck::translate::{translate_item_type, translate_param_env}; use std::collections::{BTreeMap, HashSet, VecDeque}; @@ -45,7 +45,7 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI // third pass for (old, new) in id_mapping.items() { - diff_bounds(&mut changes, tcx, old.def_id(), new.def_id()); + diff_bounds(&mut changes, &id_mapping, tcx, old, new); } // fourth pass @@ -540,12 +540,29 @@ fn diff_generics(changes: &mut ChangeSet, // being exported. /// Given two items, compare the bounds on their type and region parameters. -fn diff_bounds<'a, 'tcx>(_changes: &mut ChangeSet, - _tcx: TyCtxt<'a, 'tcx, 'tcx>, - _old: DefId, - _new: DefId) - -> (Vec>, Vec<(DefId, DefId)>) -{ +fn diff_bounds<'a, 'tcx>(changes: &mut ChangeSet, + id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + old: Def, + new: Def) { + use rustc::hir::def::Def::Macro; + + let old_def_id = old.def_id(); + let new_def_id = new.def_id(); + + 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; + } + + if let Macro(_, _) = old { + return; // TODO: more cases like this one + } + + let old_param_env = + translate_param_env(id_mapping, tcx, old_def_id, tcx.param_env(old_def_id)); + /* let old_param_env = tcx.param_env(old); let res = Default::default(); @@ -553,8 +570,6 @@ fn diff_bounds<'a, 'tcx>(_changes: &mut ChangeSet, let new_preds = tcx.predicates_of(new).predicates; res */ - - Default::default() } // Below functions constitute the fourth and last pass of analysis, in which the types of From 53c389e6ab78adc4a60f8235dc3f1d4cad9de310 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 25 Jul 2017 12:29:19 +0200 Subject: [PATCH 172/553] Added more tests for macros. Closes #15. It seems the issues we had have been resolved upstream. --- tests/cases/macros/new.rs | 16 +++++++++++++-- tests/cases/macros/old.rs | 20 ++++++++++++++++++- tests/cases/macros/stdout | 42 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/tests/cases/macros/new.rs b/tests/cases/macros/new.rs index 0526103d067f0..bcc4bb969f8de 100644 --- a/tests/cases/macros/new.rs +++ b/tests/cases/macros/new.rs @@ -1,6 +1,8 @@ #![feature(decl_macro, use_extern_macros)] pub struct Item; +pub macro foo() { Item } + #[macro_export] macro_rules! bar { () => { @@ -8,7 +10,17 @@ macro_rules! bar { } } -#[allow(dead_code)] -fn abc() -> Item { +pub macro baz() { Item } + +pub macro quux1() { Item } + +#[macro_export] +macro_rules! quux2 { + () => { + Item + } +} + +pub fn abc() -> Item { bar!() } diff --git a/tests/cases/macros/old.rs b/tests/cases/macros/old.rs index 2015cbff0c62c..b1fc107f5c978 100644 --- a/tests/cases/macros/old.rs +++ b/tests/cases/macros/old.rs @@ -1,8 +1,26 @@ #![feature(decl_macro, use_extern_macros)] pub struct Item; +pub macro foo() { Item } + pub macro bar() { Item } -fn abc() -> 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/tests/cases/macros/stdout b/tests/cases/macros/stdout index f8c2af4c949b7..80e4c7aede282 100644 --- a/tests/cases/macros/stdout +++ b/tests/cases/macros/stdout @@ -1 +1,41 @@ -version bump: 1.0.0 -> (patch) -> 1.0.1 +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: path changes to `qux1` + --> $REPO_PATH/tests/cases/macros/old.rs:15:5 + | +15 | pub macro qux1() { Item } + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: removed definition (breaking) + +warning: path changes to `qux2` + --> $REPO_PATH/tests/cases/macros/old.rs:18:1 + | +18 | / macro_rules! qux2 { +19 | | () => { +20 | | Item +21 | | } +22 | | } + | |_^ + | + = note: removed definition (breaking) + +warning: path changes to `quux1` + --> $REPO_PATH/tests/cases/macros/new.rs:15:5 + | +15 | pub macro quux1() { Item } + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + +warning: path changes to `quux2` + --> $REPO_PATH/tests/cases/macros/new.rs:18:1 + | +18 | / macro_rules! quux2 { +19 | | () => { +20 | | Item +21 | | } +22 | | } + | |_^ + | + = note: added definition (technically breaking) + From 72e3374c84f34f305755fea7d36401cf388b6ada Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 25 Jul 2017 18:26:57 +0200 Subject: [PATCH 173/553] First attempt to correctly diff trait bounds. --- src/semcheck/translate.rs | 1 + src/semcheck/traverse.rs | 63 +++++++++++++++++---------------------- 2 files changed, 28 insertions(+), 36 deletions(-) diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 698dea29583c8..7b80234ed9f00 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -18,6 +18,7 @@ fn construct_index_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old_def_id: DefId) for type_ in &old_generics.types { index_map.insert(type_.index, type_.def_id); } + if let Some(did) = old_generics.parent { let parent_generics = tcx.generics_of(did); diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 059c9a8da7cb2..0daf5f51b1a87 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -11,12 +11,12 @@ use rustc::hir::def::{CtorKind, Def}; use rustc::hir::def_id::DefId; +use rustc::traits::{FulfillmentContext, Obligation, ObligationCause}; use rustc::ty::{AssociatedItem, Ty, TyCtxt}; use rustc::ty::Visibility::Public; use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; use rustc::ty::subst::{Subst, Substs}; -use semcheck::changes::ChangeType; use semcheck::changes::ChangeType::*; use semcheck::changes::ChangeSet; use semcheck::mapping::{IdMapping, NameMapping}; @@ -540,36 +540,11 @@ fn diff_generics(changes: &mut ChangeSet, // being exported. /// Given two items, compare the bounds on their type and region parameters. -fn diff_bounds<'a, 'tcx>(changes: &mut ChangeSet, - id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - old: Def, - new: Def) { - use rustc::hir::def::Def::Macro; - - let old_def_id = old.def_id(); - let new_def_id = new.def_id(); - - 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; - } - - if let Macro(_, _) = old { - return; // TODO: more cases like this one - } - - let old_param_env = - translate_param_env(id_mapping, tcx, old_def_id, tcx.param_env(old_def_id)); - - /* let old_param_env = tcx.param_env(old); - let res = Default::default(); - - let old_preds = tcx.predicates_of(old).predicates; - let new_preds = tcx.predicates_of(new).predicates; - - res */ +fn diff_bounds<'a, 'tcx>(_changes: &mut ChangeSet, + _id_mapping: &IdMapping, + _tcx: TyCtxt<'a, 'tcx, 'tcx>, + _old: Def, + _new: Def) { } // Below functions constitute the fourth and last pass of analysis, in which the types of @@ -640,7 +615,6 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, use rustc::infer::InferOk; use rustc::middle::free_region::FreeRegionMap; use rustc::middle::region::RegionMaps; - use rustc::traits::ObligationCause; use rustc::ty::{Lift, ReEarlyBound}; use rustc::ty::TypeVariants::*; @@ -662,17 +636,34 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let new = new.subst(infcx.tcx, new_substs); - let param_env = tcx.param_env(new_def_id); - let origin = &ObligationCause::dummy(); + let old_param_env = + translate_param_env(id_mapping, tcx, old_def_id, tcx.param_env(old_def_id)); + let new_param_env = tcx.param_env(new_def_id); + + let cause = ObligationCause::dummy(); + + let mut fulfill_cx = FulfillmentContext::new(); + + for predicate in new_param_env.caller_bounds.iter() { + let obligation = Obligation::new(cause.clone(), old_param_env, *predicate); + fulfill_cx.register_predicate_obligation(&infcx, obligation); + } + + if let Err(error) = fulfill_cx.select_all_or_error(&infcx) { + // println!("old param env: {:?}", old_param_env); + // println!("new param env: {:?}", new_param_env); + // println!("could not fulfill obligation: {:?}", error); + } + let error = infcx - .at(origin, param_env) + .at(&cause, new_param_env) .eq(old, new) .map(|InferOk { obligations: o, .. }| { assert_eq!(o, vec![]); }); if let Err(err) = error { let region_maps = RegionMaps::new(); let mut free_regions = FreeRegionMap::new(); - free_regions.relate_free_regions_from_predicates(param_env.caller_bounds); + free_regions.relate_free_regions_from_predicates(new_param_env.caller_bounds); infcx.resolve_regions_and_report_errors(new_def_id, ®ion_maps, &free_regions); let err = infcx.resolve_type_vars_if_possible(&err); From 56a0d41da9fccc0c768508a4b3226f05e71c951d Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 25 Jul 2017 19:55:05 +0200 Subject: [PATCH 174/553] Fixed bounds checking. Uses type inference results from type comparison. Also, improved the handling of type parmeters being added etc. --- src/semcheck/traverse.rs | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 0daf5f51b1a87..58cc0717f0cd7 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -623,7 +623,16 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, tcx.infer_ctxt().enter(|infcx| { let new_substs = if new.is_fn() { - infcx.fresh_substs_for_item(DUMMY_SP, new_def_id) + let has_self = tcx.generics_of(new_def_id).has_self; + Substs::for_item(infcx.tcx, new_def_id, |def, _| { + infcx.region_var_for_def(DUMMY_SP, def) + }, |def, substs| { + if def.index == 0 && has_self { // `Self` is special + tcx.mk_param_from_def(def) + } else { + infcx.type_var_for_def(DUMMY_SP, def, substs) + } + }) } else { Substs::for_item(tcx, new_def_id, |def, _| { tcx.mk_region(ReEarlyBound(def.to_early_bound_region_data())) @@ -638,10 +647,9 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let old_param_env = translate_param_env(id_mapping, tcx, old_def_id, tcx.param_env(old_def_id)); - let new_param_env = tcx.param_env(new_def_id); + let new_param_env = tcx.param_env(new_def_id).subst(infcx.tcx, new_substs); let cause = ObligationCause::dummy(); - let mut fulfill_cx = FulfillmentContext::new(); for predicate in new_param_env.caller_bounds.iter() { @@ -649,12 +657,6 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, fulfill_cx.register_predicate_obligation(&infcx, obligation); } - if let Err(error) = fulfill_cx.select_all_or_error(&infcx) { - // println!("old param env: {:?}", old_param_env); - // println!("new param env: {:?}", new_param_env); - // println!("could not fulfill obligation: {:?}", error); - } - let error = infcx .at(&cause, new_param_env) .eq(old, new) @@ -681,5 +683,11 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, old_def_id, None); } + + if let Err(error) = fulfill_cx.select_all_or_error(&infcx) { + println!("old param env: {:?}", old_param_env); + println!("new param env: {:?}", new_param_env); + println!("could not fulfill obligation: {:?}", error); + } }); } From 3f98d91b3771e2425516110739bdc1eb61c51d6e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 26 Jul 2017 16:54:04 +0200 Subject: [PATCH 175/553] Implemented a rough version of bounds checking. Code can be simplified and cleaned up still, but the functionality should be essentially complete. --- src/semcheck/changes.rs | 16 ++++++++++++-- src/semcheck/mapping.rs | 2 +- src/semcheck/traverse.rs | 44 ++++++++++++++++++++++++++++----------- tests/cases/bounds/new.rs | 11 ++++++++++ tests/cases/bounds/old.rs | 11 ++++++++++ tests/cases/bounds/stdout | 37 ++++++++++++++++++++++++++++++++ tests/examples.rs | 1 + 7 files changed, 107 insertions(+), 15 deletions(-) create mode 100644 tests/cases/bounds/new.rs create mode 100644 tests/cases/bounds/old.rs create mode 100644 tests/cases/bounds/stdout diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index f81a317c42198..c68e782775df0 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -10,6 +10,7 @@ use rustc::hir::def_id::DefId; use rustc::session::Session; +use rustc::ty::Predicate; use rustc::ty::error::TypeError; use semver::Version; @@ -165,7 +166,7 @@ impl Ord for PathChange { } /// The types of changes we identify between items present in both crate versions. -#[derive(Clone, Debug)] +#[derive(Debug)] pub enum ChangeType<'tcx> { /// An item has been made public. ItemMadePublic, @@ -203,6 +204,10 @@ pub enum ChangeType<'tcx> { TraitUnsafetyChanged { now_unsafe: bool }, /// A field in a struct or enum has changed it's type. TypeChanged { error: TypeError<'tcx> }, + /// An item's bounds have been tightened. + BoundsTightened { error: Predicate<'tcx> }, + /// An item's bounds have been loosened. + BoundsLoosened { error: Predicate<'tcx> }, /// An unknown change is any change we don't yet explicitly handle. Unknown, } @@ -230,9 +235,11 @@ impl<'tcx> ChangeType<'tcx> { TraitItemAdded { defaulted: false } | TraitItemRemoved { .. } | TraitUnsafetyChanged { .. } | + BoundsTightened { .. } | Unknown => Breaking, MethodSelfChanged { now_self: true } | TraitItemAdded { defaulted: true } | + BoundsLoosened { .. } | ItemMadePublic => TechnicallyBreaking, TypeParameterAdded { defaulted: true } | FnConstChanged { now_const: true } => NonBreaking, @@ -289,6 +296,9 @@ impl<'a> fmt::Display for ChangeType<'a> { TraitUnsafetyChanged { now_unsafe: true } => "trait made unsafe", TraitUnsafetyChanged { now_unsafe: false } => "trait no longer unsafe", TypeChanged { ref error } => return write!(f, "type error: {}", error), + // TODO: print bounds + BoundsTightened { .. } => return write!(f, "tightened bounds"), + BoundsLoosened { .. } => return write!(f, "loosened bounds"), Unknown => "unknown change", }; write!(f, "{}", desc) @@ -363,7 +373,9 @@ impl<'tcx> Change<'tcx> { ItemMadePublic | TypeParameterAdded { .. } | TraitUnsafetyChanged { .. } | - FnConstChanged { now_const: true } => (), + FnConstChanged { now_const: true } | + BoundsTightened { .. } | + BoundsLoosened { .. } => (), } } diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 4f29c93764e38..c3d22a33742a5 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -91,7 +91,7 @@ impl IdMapping { /// Add any other item's old and new `DefId`s, together with a parent entry. pub fn add_subitem(&mut self, parent: DefId, old: DefId, new: DefId) { - // NB: we rely on the assers in `add_internal_item` here. + // NB: we rely on the asserts in `add_internal_item` here. self.add_internal_item(old, new); self.child_mapping .entry(parent) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 58cc0717f0cd7..adb20c3e45487 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -328,8 +328,6 @@ fn diff_adts(changes: &mut ChangeSet, for items in variants.values() { match *items { (Some(old), Some(new)) => { - id_mapping.add_subitem(old_def_id, old.did, new.did); - for field in &old.fields { fields.entry(field.name).or_insert((None, None)).0 = Some(field); } @@ -650,12 +648,6 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let new_param_env = tcx.param_env(new_def_id).subst(infcx.tcx, new_substs); let cause = ObligationCause::dummy(); - let mut fulfill_cx = FulfillmentContext::new(); - - for predicate in new_param_env.caller_bounds.iter() { - let obligation = Obligation::new(cause.clone(), old_param_env, *predicate); - fulfill_cx.register_predicate_obligation(&infcx, obligation); - } let error = infcx .at(&cause, new_param_env) @@ -684,10 +676,38 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, None); } - if let Err(error) = fulfill_cx.select_all_or_error(&infcx) { - println!("old param env: {:?}", old_param_env); - println!("new param env: {:?}", new_param_env); - println!("could not fulfill obligation: {:?}", error); + let mut fulfill_cx = FulfillmentContext::new(); + + for predicate in new_param_env.caller_bounds.iter() { + let obligation = Obligation::new(cause.clone(), old_param_env, *predicate); + fulfill_cx.register_predicate_obligation(&infcx, obligation); + } + + if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) { + for err in &errors { + let err_type = BoundsTightened { + error: err.obligation.predicate.lift_to_tcx(tcx).unwrap() + }; + + changes.add_change(err_type, old_def_id, None); + } + } else { + let mut fulfill_cx_rev = FulfillmentContext::new(); + + for predicate in old_param_env.caller_bounds.iter() { + let obligation = Obligation::new(cause.clone(), new_param_env, *predicate); + fulfill_cx_rev.register_predicate_obligation(&infcx, obligation); + } + + if let Err(errors) = fulfill_cx_rev.select_all_or_error(&infcx) { + for err in &errors { + let err_type = BoundsLoosened { + error: err.obligation.predicate.lift_to_tcx(tcx).unwrap() + }; + + changes.add_change(err_type, old_def_id, None); + } + } } }); } diff --git a/tests/cases/bounds/new.rs b/tests/cases/bounds/new.rs new file mode 100644 index 0000000000000..e35f3d7f2531e --- /dev/null +++ b/tests/cases/bounds/new.rs @@ -0,0 +1,11 @@ +pub struct Abc { + pub a: A, +} + +pub struct Def { + pub d: A, +} + +pub fn abc(_: A) {} + +pub fn def(_: A) {} diff --git a/tests/cases/bounds/old.rs b/tests/cases/bounds/old.rs new file mode 100644 index 0000000000000..9e96307b71ca8 --- /dev/null +++ b/tests/cases/bounds/old.rs @@ -0,0 +1,11 @@ +pub struct Abc { + pub a: A, +} + +pub struct Def { + pub d: A, +} + +pub fn abc(_: A) {} + +pub fn def(_: A) {} diff --git a/tests/cases/bounds/stdout b/tests/cases/bounds/stdout new file mode 100644 index 0000000000000..d3036d78960b8 --- /dev/null +++ b/tests/cases/bounds/stdout @@ -0,0 +1,37 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: breaking changes in `Abc` + --> $REPO_PATH/tests/cases/bounds/new.rs:1:1 + | +1 | / pub struct Abc { +2 | | pub a: A, +3 | | } + | |_^ + | + = warning: tightened bounds (breaking) + +warning: technically breaking changes in `Def` + --> $REPO_PATH/tests/cases/bounds/new.rs:5:1 + | +5 | / pub struct Def { +6 | | pub d: A, +7 | | } + | |_^ + | + = note: loosened bounds (technically breaking) + +warning: breaking changes in `abc` + --> $REPO_PATH/tests/cases/bounds/new.rs:9:1 + | +9 | pub fn abc(_: A) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: tightened bounds (breaking) + +warning: technically breaking changes in `def` + --> $REPO_PATH/tests/cases/bounds/new.rs:11:1 + | +11 | pub fn def(_: A) {} + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: loosened bounds (technically breaking) + diff --git a/tests/examples.rs b/tests/examples.rs index 39590447942a8..c9bd5c6ecb700 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -100,6 +100,7 @@ macro_rules! test { test!(addition, "tests/cases/addition"); test!(addition_path, "tests/cases/addition_path"); test!(addition_use, "tests/cases/addition_use"); +test!(bounds, "tests/cases/bounds"); test!(enums, "tests/cases/enums"); test!(func, "tests/cases/func"); test!(infer, "tests/cases/infer"); From b8895173e1c5e80fb54e0ebc767d2e261f36b8d2 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 26 Jul 2017 17:15:29 +0200 Subject: [PATCH 176/553] Simplified bounds check output. --- src/semcheck/changes.rs | 18 ++++++++---------- src/semcheck/traverse.rs | 20 ++++---------------- tests/cases/bounds/stdout | 28 ++++++++++++++++++++++++---- 3 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index c68e782775df0..19fd396badbe6 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -10,7 +10,6 @@ use rustc::hir::def_id::DefId; use rustc::session::Session; -use rustc::ty::Predicate; use rustc::ty::error::TypeError; use semver::Version; @@ -205,9 +204,9 @@ pub enum ChangeType<'tcx> { /// A field in a struct or enum has changed it's type. TypeChanged { error: TypeError<'tcx> }, /// An item's bounds have been tightened. - BoundsTightened { error: Predicate<'tcx> }, + BoundsTightened, /// An item's bounds have been loosened. - BoundsLoosened { error: Predicate<'tcx> }, + BoundsLoosened, /// An unknown change is any change we don't yet explicitly handle. Unknown, } @@ -235,11 +234,11 @@ impl<'tcx> ChangeType<'tcx> { TraitItemAdded { defaulted: false } | TraitItemRemoved { .. } | TraitUnsafetyChanged { .. } | - BoundsTightened { .. } | + BoundsTightened | Unknown => Breaking, MethodSelfChanged { now_self: true } | TraitItemAdded { defaulted: true } | - BoundsLoosened { .. } | + BoundsLoosened | ItemMadePublic => TechnicallyBreaking, TypeParameterAdded { defaulted: true } | FnConstChanged { now_const: true } => NonBreaking, @@ -296,9 +295,8 @@ impl<'a> fmt::Display for ChangeType<'a> { TraitUnsafetyChanged { now_unsafe: true } => "trait made unsafe", TraitUnsafetyChanged { now_unsafe: false } => "trait no longer unsafe", TypeChanged { ref error } => return write!(f, "type error: {}", error), - // TODO: print bounds - BoundsTightened { .. } => return write!(f, "tightened bounds"), - BoundsLoosened { .. } => return write!(f, "loosened bounds"), + BoundsTightened => "tightened bounds", + BoundsLoosened => "loosened bounds", Unknown => "unknown change", }; write!(f, "{}", desc) @@ -374,8 +372,8 @@ impl<'tcx> Change<'tcx> { TypeParameterAdded { .. } | TraitUnsafetyChanged { .. } | FnConstChanged { now_const: true } | - BoundsTightened { .. } | - BoundsLoosened { .. } => (), + BoundsTightened | + BoundsLoosened => (), } } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index adb20c3e45487..af942844bf222 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -683,14 +683,8 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, fulfill_cx.register_predicate_obligation(&infcx, obligation); } - if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) { - for err in &errors { - let err_type = BoundsTightened { - error: err.obligation.predicate.lift_to_tcx(tcx).unwrap() - }; - - changes.add_change(err_type, old_def_id, None); - } + if fulfill_cx.select_all_or_error(&infcx).is_err() { + changes.add_change(BoundsTightened, old_def_id, Some(tcx.def_span(old_def_id))); } else { let mut fulfill_cx_rev = FulfillmentContext::new(); @@ -699,14 +693,8 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, fulfill_cx_rev.register_predicate_obligation(&infcx, obligation); } - if let Err(errors) = fulfill_cx_rev.select_all_or_error(&infcx) { - for err in &errors { - let err_type = BoundsLoosened { - error: err.obligation.predicate.lift_to_tcx(tcx).unwrap() - }; - - changes.add_change(err_type, old_def_id, None); - } + if fulfill_cx_rev.select_all_or_error(&infcx).is_err() { + changes.add_change(BoundsLoosened, old_def_id, Some(tcx.def_span(old_def_id))); } } }); diff --git a/tests/cases/bounds/stdout b/tests/cases/bounds/stdout index d3036d78960b8..d061c1ac9e700 100644 --- a/tests/cases/bounds/stdout +++ b/tests/cases/bounds/stdout @@ -7,7 +7,13 @@ warning: breaking changes in `Abc` 3 | | } | |_^ | - = warning: tightened bounds (breaking) +warning: tightened bounds (breaking) + --> $REPO_PATH/tests/cases/bounds/old.rs:1:1 + | +1 | / pub struct Abc { +2 | | pub a: A, +3 | | } + | |_^ warning: technically breaking changes in `Def` --> $REPO_PATH/tests/cases/bounds/new.rs:5:1 @@ -17,7 +23,13 @@ warning: technically breaking changes in `Def` 7 | | } | |_^ | - = note: loosened bounds (technically breaking) +note: loosened bounds (technically breaking) + --> $REPO_PATH/tests/cases/bounds/old.rs:5:1 + | +5 | / pub struct Def { +6 | | pub d: A, +7 | | } + | |_^ warning: breaking changes in `abc` --> $REPO_PATH/tests/cases/bounds/new.rs:9:1 @@ -25,7 +37,11 @@ warning: breaking changes in `abc` 9 | pub fn abc(_: A) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: tightened bounds (breaking) +warning: tightened bounds (breaking) + --> $REPO_PATH/tests/cases/bounds/old.rs:9:1 + | +9 | pub fn abc(_: A) {} + | ^^^^^^^^^^^^^^^^^^^^^^ warning: technically breaking changes in `def` --> $REPO_PATH/tests/cases/bounds/new.rs:11:1 @@ -33,5 +49,9 @@ warning: technically breaking changes in `def` 11 | pub fn def(_: A) {} | ^^^^^^^^^^^^^^^^^^^^^^ | - = note: loosened bounds (technically breaking) +note: loosened bounds (technically breaking) + --> $REPO_PATH/tests/cases/bounds/old.rs:11:1 + | +11 | pub fn def(_: A) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 12387c72b4bcf98267f463d65a0333197578ba83 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 26 Jul 2017 22:11:41 +0200 Subject: [PATCH 177/553] Implemented smarter bounds checks. --- src/semcheck/changes.rs | 17 ++++++----- src/semcheck/translate.rs | 29 +++++++++++++++++- src/semcheck/traverse.rs | 62 ++++++++++++++++++++++++++++----------- tests/cases/bounds/stdout | 8 ++--- 4 files changed, 86 insertions(+), 30 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 19fd396badbe6..3ac4e2625e7e3 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -10,6 +10,7 @@ use rustc::hir::def_id::DefId; use rustc::session::Session; +use rustc::ty::Predicate; use rustc::ty::error::TypeError; use semver::Version; @@ -204,9 +205,9 @@ pub enum ChangeType<'tcx> { /// A field in a struct or enum has changed it's type. TypeChanged { error: TypeError<'tcx> }, /// An item's bounds have been tightened. - BoundsTightened, + BoundsTightened { pred: Predicate<'tcx> }, /// An item's bounds have been loosened. - BoundsLoosened, + BoundsLoosened { pred: Predicate<'tcx> }, /// An unknown change is any change we don't yet explicitly handle. Unknown, } @@ -234,11 +235,11 @@ impl<'tcx> ChangeType<'tcx> { TraitItemAdded { defaulted: false } | TraitItemRemoved { .. } | TraitUnsafetyChanged { .. } | - BoundsTightened | + BoundsTightened { .. } | Unknown => Breaking, MethodSelfChanged { now_self: true } | TraitItemAdded { defaulted: true } | - BoundsLoosened | + BoundsLoosened { .. } | ItemMadePublic => TechnicallyBreaking, TypeParameterAdded { defaulted: true } | FnConstChanged { now_const: true } => NonBreaking, @@ -295,8 +296,8 @@ impl<'a> fmt::Display for ChangeType<'a> { 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 => "tightened bounds", - BoundsLoosened => "loosened bounds", + BoundsTightened { ref pred } => return write!(f, "added bound: `{}`", pred), + BoundsLoosened { ref pred } => return write!(f, "removed bound: `{}`", pred), Unknown => "unknown change", }; write!(f, "{}", desc) @@ -372,8 +373,8 @@ impl<'tcx> Change<'tcx> { TypeParameterAdded { .. } | TraitUnsafetyChanged { .. } | FnConstChanged { now_const: true } | - BoundsTightened | - BoundsLoosened => (), + BoundsTightened { .. } | + BoundsLoosened { .. } => (), } } diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 7b80234ed9f00..01bb08e250323 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -1,6 +1,6 @@ use rustc::hir::def_id::DefId; use rustc::ty::{ParamEnv, Predicate, Region, Ty, TyCtxt}; -use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; +use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder}; use rustc_data_structures::accumulate_vec::AccumulateVec; @@ -240,3 +240,30 @@ pub fn translate_param_env<'a, 'tcx>(id_mapping: &IdMapping, reveal: param_env.reveal, } } + +/// A simple closure folder for regions and types. +pub struct BottomUpRegionFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a, F, G> + where F: FnMut(Ty<'tcx>) -> Ty<'tcx>, + G: FnMut(Region<'tcx>) -> Region<'tcx>, +{ + pub tcx: TyCtxt<'a, 'gcx, 'tcx>, + pub fldop_t: F, + pub fldop_r: G, +} + +impl<'a, 'gcx, 'tcx, F, G> TypeFolder<'gcx, 'tcx> for BottomUpRegionFolder<'a, 'gcx, 'tcx, F, G> + where F: FnMut(Ty<'tcx>) -> Ty<'tcx>, + G: FnMut(Region<'tcx>) -> Region<'tcx>, +{ + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + let t1 = ty.super_fold_with(self); + (self.fldop_t)(t1) + } + + fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> { + let r1 = r.super_fold_with(self); + (self.fldop_r)(r1) + } +} diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index af942844bf222..a67cf2221ca94 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -14,14 +14,14 @@ use rustc::hir::def_id::DefId; use rustc::traits::{FulfillmentContext, Obligation, ObligationCause}; use rustc::ty::{AssociatedItem, Ty, TyCtxt}; use rustc::ty::Visibility::Public; -use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; +use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::{Subst, Substs}; use semcheck::changes::ChangeType::*; use semcheck::changes::ChangeSet; use semcheck::mapping::{IdMapping, NameMapping}; use semcheck::mismatch::Mismatch; -use semcheck::translate::{translate_item_type, translate_param_env}; +use semcheck::translate::{BottomUpRegionFolder, translate_item_type, translate_param_env}; use std::collections::{BTreeMap, HashSet, VecDeque}; @@ -654,14 +654,14 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, .eq(old, new) .map(|InferOk { obligations: o, .. }| { assert_eq!(o, vec![]); }); - if let Err(err) = error { - let region_maps = RegionMaps::new(); - let mut free_regions = FreeRegionMap::new(); - free_regions.relate_free_regions_from_predicates(new_param_env.caller_bounds); - infcx.resolve_regions_and_report_errors(new_def_id, ®ion_maps, &free_regions); + let region_maps = RegionMaps::new(); + let mut free_regions = FreeRegionMap::new(); + free_regions.relate_free_regions_from_predicates(new_param_env.caller_bounds); + infcx.resolve_regions_and_report_errors(new_def_id, ®ion_maps, &free_regions); - let err = infcx.resolve_type_vars_if_possible(&err); - let err = err.fold_with(&mut BottomUpFolder { tcx: infcx.tcx, fldop: |ty| { + let mut folder = BottomUpRegionFolder { + tcx: infcx.tcx, + fldop_t: |ty| { match ty.sty { TyRef(region, tm) if region.needs_infer() => { infcx.tcx.mk_ref(tcx.types.re_erased, tm) @@ -669,11 +669,21 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, TyInfer(_) => tcx.mk_ty(TyError), _ => ty, } - }}); + }, + fldop_r: |reg| { + if reg.needs_infer() { + tcx.types.re_erased + } else { + reg + } + }, + }; + + if let Err(err) = error { + let err = infcx.resolve_type_vars_if_possible(&err); + let err = err.fold_with(&mut folder).lift_to_tcx(tcx).unwrap(); - changes.add_change(TypeChanged { error: err.lift_to_tcx(tcx).unwrap() }, - old_def_id, - None); + changes.add_change(TypeChanged { error: err }, old_def_id, None); } let mut fulfill_cx = FulfillmentContext::new(); @@ -683,8 +693,17 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, fulfill_cx.register_predicate_obligation(&infcx, obligation); } - if fulfill_cx.select_all_or_error(&infcx).is_err() { - changes.add_change(BoundsTightened, old_def_id, Some(tcx.def_span(old_def_id))); + if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) { + for err in &errors { + let pred = infcx.resolve_type_vars_if_possible(&err.obligation.predicate); + let pred = pred.fold_with(&mut folder); + + let err_type = BoundsTightened { + pred: pred.lift_to_tcx(tcx).unwrap(), + }; + + changes.add_change(err_type, old_def_id, Some(tcx.def_span(old_def_id))); + } } else { let mut fulfill_cx_rev = FulfillmentContext::new(); @@ -693,8 +712,17 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, fulfill_cx_rev.register_predicate_obligation(&infcx, obligation); } - if fulfill_cx_rev.select_all_or_error(&infcx).is_err() { - changes.add_change(BoundsLoosened, old_def_id, Some(tcx.def_span(old_def_id))); + if let Err(errors) = fulfill_cx_rev.select_all_or_error(&infcx) { + for err in &errors { + let pred = infcx.resolve_type_vars_if_possible(&err.obligation.predicate); + let pred = pred.fold_with(&mut folder); + + let err_type = BoundsLoosened { + pred: pred.lift_to_tcx(tcx).unwrap(), + }; + + changes.add_change(err_type, old_def_id, Some(tcx.def_span(old_def_id))); + } } } }); diff --git a/tests/cases/bounds/stdout b/tests/cases/bounds/stdout index d061c1ac9e700..60e9238fff63c 100644 --- a/tests/cases/bounds/stdout +++ b/tests/cases/bounds/stdout @@ -7,7 +7,7 @@ warning: breaking changes in `Abc` 3 | | } | |_^ | -warning: tightened bounds (breaking) +warning: added bound: `A: std::clone::Clone` (breaking) --> $REPO_PATH/tests/cases/bounds/old.rs:1:1 | 1 | / pub struct Abc { @@ -23,7 +23,7 @@ warning: technically breaking changes in `Def` 7 | | } | |_^ | -note: loosened bounds (technically breaking) +note: removed bound: `A: std::clone::Clone` (technically breaking) --> $REPO_PATH/tests/cases/bounds/old.rs:5:1 | 5 | / pub struct Def { @@ -37,7 +37,7 @@ warning: breaking changes in `abc` 9 | pub fn abc(_: A) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -warning: tightened bounds (breaking) +warning: added bound: `A: std::clone::Clone` (breaking) --> $REPO_PATH/tests/cases/bounds/old.rs:9:1 | 9 | pub fn abc(_: A) {} @@ -49,7 +49,7 @@ warning: technically breaking changes in `def` 11 | pub fn def(_: A) {} | ^^^^^^^^^^^^^^^^^^^^^^ | -note: loosened bounds (technically breaking) +note: removed bound: `A: std::clone::Clone` (technically breaking) --> $REPO_PATH/tests/cases/bounds/old.rs:11:1 | 11 | pub fn def(_: A) {} From 42ccd2cd74ad3fe1728f6e50f753f48bcd04adda Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 26 Jul 2017 22:44:37 +0200 Subject: [PATCH 178/553] Fixed tests by undoing an unnecessary change. Oops. --- src/semcheck/traverse.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index a67cf2221ca94..76f1c5492137b 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -654,11 +654,6 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, .eq(old, new) .map(|InferOk { obligations: o, .. }| { assert_eq!(o, vec![]); }); - let region_maps = RegionMaps::new(); - let mut free_regions = FreeRegionMap::new(); - free_regions.relate_free_regions_from_predicates(new_param_env.caller_bounds); - infcx.resolve_regions_and_report_errors(new_def_id, ®ion_maps, &free_regions); - let mut folder = BottomUpRegionFolder { tcx: infcx.tcx, fldop_t: |ty| { @@ -680,6 +675,11 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, }; if let Err(err) = error { + let region_maps = RegionMaps::new(); + let mut free_regions = FreeRegionMap::new(); + free_regions.relate_free_regions_from_predicates(new_param_env.caller_bounds); + infcx.resolve_regions_and_report_errors(new_def_id, ®ion_maps, &free_regions); + let err = infcx.resolve_type_vars_if_possible(&err); let err = err.fold_with(&mut folder).lift_to_tcx(tcx).unwrap(); From fff5b478cade8f2dae8ad3b3adb650cc34c17ed7 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 27 Jul 2017 15:55:13 +0200 Subject: [PATCH 179/553] First version of trait impl comparison. * For now, only traits defined in the crate being analyzed are examined. * No proper error reporting yet. * No checks for minor changes. --- src/semcheck/mapping.rs | 2 +- src/semcheck/translate.rs | 6 +- src/semcheck/traverse.rs | 105 ++++++++++++++++++++++++++++++++- tests/cases/trait_impls/new.rs | 11 ++++ tests/cases/trait_impls/old.rs | 9 +++ tests/cases/trait_impls/stdout | 2 + tests/examples.rs | 1 + 7 files changed, 131 insertions(+), 5 deletions(-) create mode 100644 tests/cases/trait_impls/new.rs create mode 100644 tests/cases/trait_impls/old.rs create mode 100644 tests/cases/trait_impls/stdout diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index c3d22a33742a5..03958c2baec3e 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -25,7 +25,7 @@ pub struct IdMapping { toplevel_mapping: HashMap, /// The set of toplevel items that have been removed. removed_items: HashSet, - /// Trait items' old `DefId` mapped to old and new `Def`. + /// Trait items' old `DefId` mapped to old and new `Def`, and the enclosing trait's `DefId`. trait_item_mapping: HashMap, /// Other items' old `DefId` mapped to new `DefId`. internal_mapping: HashMap, diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 01bb08e250323..a558ce89cf809 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -153,9 +153,9 @@ pub fn translate_item_type<'a, 'tcx>(id_mapping: &IdMapping, /// Translate all old `DefId`s in the predicate to their new counterparts, if possible. fn translate_predicate<'a, 'tcx>(id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - index_map: &HashMap, - predicate: Predicate<'tcx>) -> Predicate<'tcx> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + index_map: &HashMap, + predicate: Predicate<'tcx>) -> Predicate<'tcx> { use rustc::ty::{EquatePredicate, OutlivesPredicate, ProjectionPredicate, ProjectionTy, SubtypePredicate, TraitPredicate, TraitRef}; diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 76f1c5492137b..38460a2a06be4 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -51,6 +51,7 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI // fourth pass for (old, new) in id_mapping.items() { diff_types(&mut changes, &id_mapping, tcx, old, new); + diff_trait_impls(&mut changes, &id_mapping, tcx, old, new); } changes @@ -601,6 +602,37 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } } +/// Given two traits, compare their implementations. +fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + old: Def, + new: Def) { + use rustc::hir::def::Def::Trait; + + if let (Trait(old_def_id), Trait(new_def_id)) = (old, new) { + if changes.trait_item_breaking(old_def_id) { + return; + } + + tcx.trait_def(old_def_id).for_each_impl(tcx, |old_impl_def_id| { + let mut matching = false; + + for new_impl_def_id in tcx.trait_impls_of(new_def_id).iter() { + matching |= cmp_impls(id_mapping, tcx, old_impl_def_id, new_impl_def_id); + + if matching { + break; + } + } + + if !matching { + println!("impl breaks: {:?}", old_impl_def_id); + } + }); + } +} + /// Compare two types and possibly register the error. fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, @@ -609,12 +641,12 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, new_def_id: DefId, old: Ty<'tcx>, new: Ty<'tcx>) { - use syntax_pos::DUMMY_SP; use rustc::infer::InferOk; use rustc::middle::free_region::FreeRegionMap; use rustc::middle::region::RegionMaps; use rustc::ty::{Lift, ReEarlyBound}; use rustc::ty::TypeVariants::*; + use syntax_pos::DUMMY_SP; let substs = Substs::identity_for_item(tcx, new_def_id); let old = translate_item_type(id_mapping, tcx, old_def_id, old).subst(tcx, substs); @@ -727,3 +759,74 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } }); } + +/// Compare two implementations and indicate whether the new one is compatible with the old one. +fn cmp_impls<'a, 'tcx>(id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + old_def_id: DefId, + new_def_id: DefId) -> bool { + use rustc::infer::InferOk; + use syntax_pos::DUMMY_SP; + + let old = tcx + .impl_trait_ref(old_def_id) + .and_then(|trait_ref| trait_ref.substs.get(0)) + .and_then(|kind| kind.as_type()) + .unwrap(); + let new = tcx + .impl_trait_ref(new_def_id) + .and_then(|trait_ref| trait_ref.substs.get(0)) + .and_then(|kind| kind.as_type()) + .unwrap(); + + let substs = Substs::identity_for_item(tcx, new_def_id); + + if substs.len() < Substs::identity_for_item(tcx, old_def_id).len() { + // type parameters have been removed, so this can't match. + // FIXME: very ugly, find a better way if possible + return false; + } + + let old = translate_item_type(id_mapping, tcx, old_def_id, old).subst(tcx, substs); + + tcx.infer_ctxt().enter(|infcx| { + let new_substs = { + Substs::for_item(infcx.tcx, new_def_id, |def, _| { + infcx.region_var_for_def(DUMMY_SP, def) + }, |def, substs| { + // TODO: strictly speaking, this shouldn't happen. + if def.index == 0 { // `Self` is special + tcx.mk_param_from_def(def) + } else { + infcx.type_var_for_def(DUMMY_SP, def, substs) + } + }) + }; + + let new = new.subst(infcx.tcx, new_substs); + + let old_param_env = + translate_param_env(id_mapping, tcx, old_def_id, tcx.param_env(old_def_id)); + let new_param_env = tcx.param_env(new_def_id).subst(infcx.tcx, new_substs); + + let cause = ObligationCause::dummy(); + + let error = infcx + .at(&cause, new_param_env) + .eq(old, new) + .map(|InferOk { obligations: o, .. }| { assert_eq!(o, vec![]); }); + + if error.is_err() { + return false; + } + + let mut fulfill_cx = FulfillmentContext::new(); + + for predicate in new_param_env.caller_bounds.iter() { + let obligation = Obligation::new(cause.clone(), old_param_env, *predicate); + fulfill_cx.register_predicate_obligation(&infcx, obligation); + } + + fulfill_cx.select_all_or_error(&infcx).is_ok() + }) +} diff --git a/tests/cases/trait_impls/new.rs b/tests/cases/trait_impls/new.rs new file mode 100644 index 0000000000000..a700772bc3e38 --- /dev/null +++ b/tests/cases/trait_impls/new.rs @@ -0,0 +1,11 @@ +pub struct Def; + +pub trait Abc { } + +impl Abc for Option { } + +impl Abc for Def { } + +impl Abc for Box { } + +impl Abc for Box { } diff --git a/tests/cases/trait_impls/old.rs b/tests/cases/trait_impls/old.rs new file mode 100644 index 0000000000000..deaa8655a3805 --- /dev/null +++ b/tests/cases/trait_impls/old.rs @@ -0,0 +1,9 @@ +pub struct Def; + +pub trait Abc { } + +impl Abc for Option { } + +impl Abc for Def { } + +impl Abc for Box { } diff --git a/tests/cases/trait_impls/stdout b/tests/cases/trait_impls/stdout new file mode 100644 index 0000000000000..fd15e52981918 --- /dev/null +++ b/tests/cases/trait_impls/stdout @@ -0,0 +1,2 @@ +impl breaks: DefId { krate: CrateNum(12), node: DefIndex(7) => old/8cd878b::{{impl}}[2] } +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/tests/examples.rs b/tests/examples.rs index c9bd5c6ecb700..d0fbb0e573a81 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -116,4 +116,5 @@ test!(removal_use, "tests/cases/removal_use"); test!(structs, "tests/cases/structs"); test!(swap, "tests/cases/swap"); test!(traits, "tests/cases/traits"); +test!(trait_impls, "tests/cases/trait_impls"); test!(ty_alias, "tests/cases/ty_alias"); From f3392971e42eecef4796c6062646b13c84df95ab Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 27 Jul 2017 16:31:29 +0200 Subject: [PATCH 180/553] Proper error reporting for trait impl changes. --- src/semcheck/changes.rs | 12 +++++++++++- src/semcheck/traverse.rs | 12 +++++++++++- tests/cases/trait_impls/stdout | 11 +++++++++-- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 3ac4e2625e7e3..cd72f2909d5e8 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -208,6 +208,10 @@ pub enum ChangeType<'tcx> { BoundsTightened { pred: Predicate<'tcx> }, /// An item's bounds have been loosened. BoundsLoosened { pred: Predicate<'tcx> }, + /// A trait impl has been specialized or removed for some types. + TraitImplTightened, + /// A trait impl has been generalized or newly added for some types. + TraitImplLoosened, /// An unknown change is any change we don't yet explicitly handle. Unknown, } @@ -236,10 +240,12 @@ impl<'tcx> ChangeType<'tcx> { TraitItemRemoved { .. } | TraitUnsafetyChanged { .. } | BoundsTightened { .. } | + TraitImplTightened | Unknown => Breaking, MethodSelfChanged { now_self: true } | TraitItemAdded { defaulted: true } | BoundsLoosened { .. } | + TraitImplLoosened | ItemMadePublic => TechnicallyBreaking, TypeParameterAdded { defaulted: true } | FnConstChanged { now_const: true } => NonBreaking, @@ -298,6 +304,8 @@ impl<'a> fmt::Display for ChangeType<'a> { TypeChanged { ref error } => return write!(f, "type error: {}", error), BoundsTightened { ref pred } => return write!(f, "added bound: `{}`", pred), BoundsLoosened { ref pred } => return write!(f, "removed bound: `{}`", pred), + TraitImplTightened => "trait impl specialized or removed", + TraitImplLoosened => "trait impl generalized or newly added", Unknown => "unknown change", }; write!(f, "{}", desc) @@ -374,7 +382,9 @@ impl<'tcx> Change<'tcx> { TraitUnsafetyChanged { .. } | FnConstChanged { now_const: true } | BoundsTightened { .. } | - BoundsLoosened { .. } => (), + BoundsLoosened { .. } | + TraitImplTightened | + TraitImplLoosened => (), } } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 38460a2a06be4..fc932e2be5c6c 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -25,6 +25,8 @@ use semcheck::translate::{BottomUpRegionFolder, translate_item_type, translate_p use std::collections::{BTreeMap, HashSet, VecDeque}; +use syntax::symbol::Symbol; + /// The main entry point to our analysis passes. /// /// Set up the necessary data structures and run the analysis passes. @@ -626,8 +628,16 @@ fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } } + let impl_span = tcx.def_span(old_impl_def_id); + if !matching { - println!("impl breaks: {:?}", old_impl_def_id); + changes.new_change(old_def_id, + new_def_id, + Symbol::intern("impl"), + impl_span, + impl_span, + true); + changes.add_change(TraitImplTightened, old_def_id, None); } }); } diff --git a/tests/cases/trait_impls/stdout b/tests/cases/trait_impls/stdout index fd15e52981918..e0ec591bc527e 100644 --- a/tests/cases/trait_impls/stdout +++ b/tests/cases/trait_impls/stdout @@ -1,2 +1,9 @@ -impl breaks: DefId { krate: CrateNum(12), node: DefIndex(7) => old/8cd878b::{{impl}}[2] } -version bump: 1.0.0 -> (patch) -> 1.0.1 +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: breaking changes in `impl` + --> $REPO_PATH/tests/cases/trait_impls/old.rs:9:1 + | +9 | impl Abc for Box { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: trait impl specialized or removed (breaking) + From 48e15c40811e87415f36854fae7b199259785fda Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 27 Jul 2017 19:50:41 +0200 Subject: [PATCH 181/553] Implemented trait impl checks for outside traits as well. --- src/semcheck/traverse.rs | 79 +++++++++++++++++++--------------- tests/cases/trait_impls/new.rs | 2 +- tests/cases/trait_impls/old.rs | 8 +++- tests/cases/trait_impls/stdout | 14 +++++- 4 files changed, 66 insertions(+), 37 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index fc932e2be5c6c..037751312a340 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -23,7 +23,7 @@ use semcheck::mapping::{IdMapping, NameMapping}; use semcheck::mismatch::Mismatch; use semcheck::translate::{BottomUpRegionFolder, translate_item_type, translate_param_env}; -use std::collections::{BTreeMap, HashSet, VecDeque}; +use std::collections::{BTreeSet, BTreeMap, HashMap, HashSet, VecDeque}; use syntax::symbol::Symbol; @@ -36,6 +36,8 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI let mut changes = Default::default(); let mut id_mapping = IdMapping::new(old.krate, new.krate); + // TODO: deriving(Trait) ? + // first pass diff_structure(&mut changes, &mut id_mapping, tcx, old, new); @@ -53,9 +55,10 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI // fourth pass for (old, new) in id_mapping.items() { diff_types(&mut changes, &id_mapping, tcx, old, new); - diff_trait_impls(&mut changes, &id_mapping, tcx, old, new); } + diff_trait_impls(&mut changes, &id_mapping, tcx); + changes } @@ -604,42 +607,49 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } } -/// Given two traits, compare their implementations. +/// Compare the implementations of traits. fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - old: Def, - new: Def) { - use rustc::hir::def::Def::Trait; - - if let (Trait(old_def_id), Trait(new_def_id)) = (old, new) { - if changes.trait_item_breaking(old_def_id) { - return; - } + tcx: TyCtxt<'a, 'tcx, 'tcx>) { + let mut new_impls = HashMap::new(); + let all_impls = tcx.sess.cstore.implementations_of_trait(None); + + // construct a set of implementations for each trait outside of the old crate. + for new_impl_def_id in all_impls.iter().filter(|&did| !id_mapping.in_old_crate(*did)) { + new_impls + .entry(tcx.impl_trait_ref(*new_impl_def_id).unwrap().def_id) + .or_insert_with(BTreeSet::new) + .insert(*new_impl_def_id); + } - tcx.trait_def(old_def_id).for_each_impl(tcx, |old_impl_def_id| { - let mut matching = false; + // for each implementation in the old crate, ... + for old_impl_def_id in all_impls.iter().filter(|&did| id_mapping.in_old_crate(*did)) { + // ... compute trait `DefId`s, ... + let old_trait_def_id = tcx.impl_trait_ref(*old_impl_def_id).unwrap().def_id; + let new_trait_def_id = id_mapping.get_new_id(old_trait_def_id); - for new_impl_def_id in tcx.trait_impls_of(new_def_id).iter() { - matching |= cmp_impls(id_mapping, tcx, old_impl_def_id, new_impl_def_id); + let mut matched = false; - if matching { - break; - } + // ... and try to match them up with new or outside impls. + for new_impl_def_id in &new_impls[&new_trait_def_id] { + matched |= cmp_impls(id_mapping, tcx, *old_impl_def_id, *new_impl_def_id); + + if matched { + break; } + } - let impl_span = tcx.def_span(old_impl_def_id); + if !matched { + let impl_span = tcx.def_span(*old_impl_def_id); - if !matching { - changes.new_change(old_def_id, - new_def_id, - Symbol::intern("impl"), - impl_span, - impl_span, - true); - changes.add_change(TraitImplTightened, old_def_id, None); - } - }); + changes.new_change(*old_impl_def_id, + *old_impl_def_id, + Symbol::intern("impl"), + impl_span, + impl_span, + true); + changes.add_change(TraitImplTightened, *old_impl_def_id, None); + } } } @@ -789,14 +799,15 @@ fn cmp_impls<'a, 'tcx>(id_mapping: &IdMapping, .and_then(|kind| kind.as_type()) .unwrap(); - let substs = Substs::identity_for_item(tcx, new_def_id); + let old_generics = tcx.generics_of(old_def_id); + let new_generics = tcx.generics_of(new_def_id); - if substs.len() < Substs::identity_for_item(tcx, old_def_id).len() { - // type parameters have been removed, so this can't match. - // FIXME: very ugly, find a better way if possible + if old_generics.regions.len() > new_generics.regions.len() || + old_generics.types.len() > new_generics.types.len() { return false; } + let substs = Substs::identity_for_item(tcx, new_def_id); let old = translate_item_type(id_mapping, tcx, old_def_id, old).subst(tcx, substs); tcx.infer_ctxt().enter(|infcx| { diff --git a/tests/cases/trait_impls/new.rs b/tests/cases/trait_impls/new.rs index a700772bc3e38..2d385c59d34d4 100644 --- a/tests/cases/trait_impls/new.rs +++ b/tests/cases/trait_impls/new.rs @@ -8,4 +8,4 @@ impl Abc for Def { } impl Abc for Box { } -impl Abc for Box { } +impl Abc for Box { } diff --git a/tests/cases/trait_impls/old.rs b/tests/cases/trait_impls/old.rs index deaa8655a3805..c3d64c6d460aa 100644 --- a/tests/cases/trait_impls/old.rs +++ b/tests/cases/trait_impls/old.rs @@ -6,4 +6,10 @@ impl Abc for Option { } impl Abc for Def { } -impl Abc for Box { } +impl Abc for Vec { } + +impl Clone for Def { + fn clone(&self) -> Def { + Def + } +} diff --git a/tests/cases/trait_impls/stdout b/tests/cases/trait_impls/stdout index e0ec591bc527e..a385d4be4d942 100644 --- a/tests/cases/trait_impls/stdout +++ b/tests/cases/trait_impls/stdout @@ -2,8 +2,20 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 warning: breaking changes in `impl` --> $REPO_PATH/tests/cases/trait_impls/old.rs:9:1 | -9 | impl Abc for Box { } +9 | impl Abc for Vec { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: trait impl specialized or removed (breaking) +warning: breaking changes in `impl` + --> $REPO_PATH/tests/cases/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) + From e248085b615288713ed5305191d974d2006d85a7 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 28 Jul 2017 20:04:15 +0200 Subject: [PATCH 182/553] Implemented first steps for a reverse `DefId` mapping. --- src/semcheck/mapping.rs | 65 ++++++++++++++++++++++++++-------------- src/semcheck/traverse.rs | 8 ++--- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 03958c2baec3e..56467f1793044 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -23,14 +23,17 @@ pub struct IdMapping { new_crate: CrateNum, /// Toplevel items' old `DefId` mapped to old and new `Def`. toplevel_mapping: HashMap, - /// The set of toplevel items that have been removed. - removed_items: HashSet, + /// The set of items that have been removed or added and thus have no corresponding item in + /// the other crate. + non_mapped_items: HashSet, /// Trait items' old `DefId` mapped to old and new `Def`, and the enclosing trait's `DefId`. trait_item_mapping: HashMap, /// Other items' old `DefId` mapped to new `DefId`. internal_mapping: HashMap, /// Children mapping, allowing us to enumerate descendants in `AdtDef`s. child_mapping: HashMap>, + /// New `DefId`s mapped to their old counterparts. + reverse_mapping: HashMap, /// Map of type parameters' `DefId`s and their definitions. type_params: HashMap, } @@ -41,15 +44,17 @@ impl IdMapping { old_crate: old_crate, new_crate: new_crate, toplevel_mapping: HashMap::new(), - removed_items: HashSet::new(), + non_mapped_items: HashSet::new(), trait_item_mapping: HashMap::new(), internal_mapping: HashMap::new(), child_mapping: HashMap::new(), + reverse_mapping: HashMap::new(), type_params: HashMap::new(), } } /// Register two exports representing the same item across versions. + // TODO pub fn add_export(&mut self, old: Def, new: Def) -> bool { let old_def_id = old.def_id(); @@ -57,24 +62,25 @@ impl IdMapping { return false; } - self.toplevel_mapping - .insert(old_def_id, (old, new)); + 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_removal(&mut self, old: DefId) { - self.removed_items.insert(old); + 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: Def, new: Def, trait_def_id: DefId) { + pub fn add_trait_item(&mut self, old: Def, new: Def, 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, trait_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 any other item's old and new `DefId`s. @@ -85,24 +91,25 @@ impl IdMapping { 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, parent: DefId, old: DefId, new: DefId) { + 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(parent) + .entry(old_parent) .or_insert_with(Default::default) .insert(old); } - /// Record that a `DefId` represents a new type parameter. - pub fn add_type_param(&mut self, new: TypeParameterDef) { - assert!(self.in_new_crate(new.def_id)); - self.type_params.insert(new.def_id, new); + /// Record that a `DefId` represents a type parameter. + pub fn add_type_param(&mut self, param: TypeParameterDef) { + self.type_params.insert(param.def_id, param); } /// Get the type parameter represented by a given `DefId`. @@ -110,18 +117,17 @@ impl IdMapping { self.type_params[did] } - /// Check whether a `DefId` represents a newly added defaulted type parameter. - pub fn is_defaulted_type_param(&self, new: &DefId) -> bool { - self.type_params - .get(new) - .map_or(false, |def| def.has_default) + /// Check whether a `DefId` represents a non-mapped defaulted type parameter. + pub fn is_non_mapped_defaulted_type_param(&self, new: &DefId) -> bool { + self.non_mapped_items.contains(new) && + self.type_params.get(new).map_or(false, |def| def.has_default) } /// Get the new `DefId` associated with the given old one. pub fn get_new_id(&self, old: DefId) -> DefId { assert!(!self.in_new_crate(old)); - if self.in_old_crate(old) && !self.removed_items.contains(&old) { + if self.in_old_crate(old) && !self.non_mapped_items.contains(&old) { if let Some(new) = self.toplevel_mapping.get(&old) { new.1.def_id() } else if let Some(new) = self.trait_item_mapping.get(&old) { @@ -134,12 +140,24 @@ impl IdMapping { } } + /// Get the old `DefId` associated with the given new one. + pub fn get_old_id(&self, new: DefId) -> DefId { + assert!(!self.in_old_crate(new)); + + if self.in_new_crate(new) && !self.non_mapped_items.contains(&new) { + self.reverse_mapping[&new] + } else { + new + } + } + /// Get the new `DefId` associated with the given old one, respecting possibly removed /// traits that are a parent of the given `DefId`. + // TODO: write a reverse equivalent... pub fn get_new_trait_item_id(&self, old: DefId, trait_id: DefId) -> DefId { assert!(!self.in_new_crate(trait_id)); - if !self.removed_items.contains(&trait_id) { + if !self.non_mapped_items.contains(&trait_id) { self.get_new_id(old) } else { old @@ -147,11 +165,13 @@ impl IdMapping { } /// Return the `DefId` of the trait a given item belongs to. + // TODO pub fn get_trait_def(&self, item_def_id: &DefId) -> Option { self.trait_item_mapping.get(item_def_id).map(|t| t.2) } /// Check whether a `DefId` is present in the mappings. + // TODO pub fn contains_id(&self, old: DefId) -> bool { self.toplevel_mapping.contains_key(&old) || self.trait_item_mapping.contains_key(&old) || @@ -175,6 +195,7 @@ impl IdMapping { } /// Iterate over the item pairs of all children of a given item. + // TODO pub fn children_of<'a>(&'a self, parent: DefId) -> Option + 'a> { diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 037751312a340..93b66891aaaae 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -36,8 +36,6 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI let mut changes = Default::default(); let mut id_mapping = IdMapping::new(old.krate, new.krate); - // TODO: deriving(Trait) ? - // first pass diff_structure(&mut changes, &mut id_mapping, tcx, old, new); @@ -268,7 +266,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, 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_removal(o_def_id); + 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); } @@ -521,10 +519,12 @@ fn diff_generics(changes: &mut ChangeSet, } 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) => { found.push(TypeParameterRemoved { defaulted: old_type.has_default }); + id_mapping.add_type_param(*old_type); }, (None, Some(new_type)) => { // FIXME: is_fn could be used in a more elegant fashion found.push(TypeParameterAdded { defaulted: new_type.has_default || is_fn }); @@ -686,7 +686,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } else { Substs::for_item(tcx, new_def_id, |def, _| { tcx.mk_region(ReEarlyBound(def.to_early_bound_region_data())) - }, |def, _| if id_mapping.is_defaulted_type_param(&def.def_id) { + }, |def, _| if id_mapping.is_non_mapped_defaulted_type_param(&def.def_id) { tcx.type_of(def.def_id) } else { tcx.mk_param_from_def(def) From 11dcda3173d0e20ce03d116a78e744a584eb9ac9 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 28 Jul 2017 22:21:57 +0200 Subject: [PATCH 183/553] Some work to parametrize the translation mechanisms by direction. --- src/semcheck/translate.rs | 309 ++++++++++++++++++++++++++++++++++---- 1 file changed, 276 insertions(+), 33 deletions(-) diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index a558ce89cf809..2784cf57c0ebd 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -8,18 +8,261 @@ use semcheck::mapping::IdMapping; use std::collections::HashMap; +struct TranslationContext<'a, 'tcx, F1, F2, F3> + where 'tcx: 'a, + F1: Fn(&IdMapping, DefId) -> bool, + F2: Fn(&IdMapping, DefId) -> DefId, + F3: Fn(&IdMapping, DefId, DefId) -> DefId, +{ + tcx: TyCtxt<'a, 'tcx, 'tcx>, + id_mapping: &'a IdMapping, + needs_translation: F1, + translate_orig: F2, + translate_orig_trait: F3, +} + +impl<'a, 'tcx, F1, F2, F3> TranslationContext<'a, 'tcx, F1, F2, F3> + where 'tcx: 'a, + F1: Fn(&IdMapping, DefId) -> bool, + F2: Fn(&IdMapping, DefId) -> DefId, + F3: Fn(&IdMapping, DefId, DefId) -> DefId, +{ + fn construct_index_map(&self, orig_def_id: DefId) -> HashMap { + let mut index_map = HashMap::new(); + let orig_generics = self.tcx.generics_of(orig_def_id); + + for type_ in &orig_generics.types { + index_map.insert(type_.index, type_.def_id); + } + + if let Some(did) = orig_generics.parent { + let parent_generics = self.tcx.generics_of(did); + + for type_ in &parent_generics.types { + index_map.insert(type_.index, type_.def_id); + } + } + + index_map + } + + fn needs_translation(&self, def_id: DefId) -> bool { + (self.needs_translation)(self.id_mapping, def_id) + } + + fn translate_orig(&self, def_id: DefId) -> DefId { + (self.translate_orig)(self.id_mapping, def_id) + } + + fn translate_orig_trait(&self, item_def_id: DefId, trait_def_id: DefId) -> DefId { + (self.translate_orig_trait)(self.id_mapping, item_def_id, trait_def_id) + } + + fn translate>(&self, index_map: &HashMap, orig: &T) -> T { + use rustc::ty::{AdtDef, Binder, ExistentialProjection, ExistentialTraitRef}; + use rustc::ty::ExistentialPredicate::*; + use rustc::ty::TypeVariants::*; + + orig.fold_with(&mut BottomUpFolder { tcx: self.tcx, fldop: |ty| { + match ty.sty { + TyAdt(&AdtDef { ref did, .. }, substs) if self.needs_translation(*did) => { + let target_def_id = self.id_mapping.get_new_id(*did); + let target_adt = self.tcx.adt_def(target_def_id); + self.tcx.mk_adt(target_adt, substs) + }, + TyRef(region, type_and_mut) => { + self.tcx.mk_ref(self.translate_region(region), type_and_mut) + }, + TyFnDef(did, substs) => { + self.tcx.mk_fn_def(self.translate_orig(did), substs) + }, + TyDynamic(preds, region) => { + let target_preds = self.tcx.mk_existential_predicates(preds.iter().map(|p| { + match *p.skip_binder() { + Trait(ExistentialTraitRef { def_id: did, substs }) => { + let target_def_id = self.translate_orig(did); + + Trait(ExistentialTraitRef { + def_id: target_def_id, + substs: substs + }) + }, + Projection(ExistentialProjection { item_def_id, substs, ty }) => { + let target_def_id = self.translate_orig(item_def_id); + + Projection(ExistentialProjection { + item_def_id: target_def_id, + substs: substs, + ty: ty, + }) + }, + AutoTrait(did) => { + AutoTrait(self.translate_orig(did)) + }, + } + })); + + self.tcx.mk_dynamic(Binder(target_preds), region) + }, + TyProjection(proj) => { + let trait_def_id = self.tcx.associated_item(proj.item_def_id).container.id(); + let target_def_id = + self.translate_orig_trait(proj.item_def_id, trait_def_id); + + self.tcx.mk_projection(target_def_id, proj.substs) + }, + TyAnon(did, substs) => { + self.tcx.mk_anon(self.translate_orig(did), substs) + }, + TyParam(param) => { + if param.idx != 0 { // `Self` is special + let orig_def_id = index_map[¶m.idx]; + if self.needs_translation(orig_def_id) { + let target_def_id = self.translate_orig(orig_def_id); + let type_param = self.id_mapping.get_type_param(&target_def_id); + self.tcx.mk_param_from_def(&type_param) + } else { + self.tcx.mk_ty(TyParam(param)) + } + } else { + self.tcx.mk_ty(TyParam(param)) + } + }, + _ => ty, + } + }}) + } + + fn translate_region(&self, region: Region<'tcx>) -> Region<'tcx> { + use rustc::ty::{EarlyBoundRegion, FreeRegion}; + use rustc::ty::BoundRegion::BrNamed; + use rustc::ty::RegionKind::*; + + 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, + }) + } + + 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) + } + + fn translate_predicate(&self, index_map: &HashMap, predicate: Predicate<'tcx>) + -> Predicate<'tcx> + { + use rustc::ty::{EquatePredicate, OutlivesPredicate, ProjectionPredicate, ProjectionTy, + SubtypePredicate, TraitPredicate, TraitRef}; + + match predicate { + Predicate::Trait(trait_predicate) => { + Predicate::Trait(trait_predicate.map_bound(|t_pred| { + TraitPredicate { + trait_ref: TraitRef { + def_id: self.translate_orig(t_pred.trait_ref.def_id), + substs: t_pred.trait_ref.substs, + } + } + })) + }, + Predicate::Equate(equate_predicate) => { + Predicate::Equate(equate_predicate.map_bound(|e_pred| { + let l = self.translate(index_map, &e_pred.0); + let r = self.translate(index_map, &e_pred.1); + EquatePredicate(l, r) + })) + }, + Predicate::RegionOutlives(region_outlives_predicate) => { + Predicate::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) + })) + }, + Predicate::TypeOutlives(type_outlives_predicate) => { + Predicate::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) + })) + }, + Predicate::Projection(projection_predicate) => { + Predicate::Projection(projection_predicate.map_bound(|p_pred| { + ProjectionPredicate { + projection_ty: ProjectionTy { + // TODO: maybe this needs handling + substs: p_pred.projection_ty.substs, + item_def_id: self.translate_orig(p_pred.projection_ty.item_def_id), + }, + ty: self.translate(index_map, &p_pred.ty), + } + })) + }, + Predicate::WellFormed(ty) => + Predicate::WellFormed(self.translate(index_map, &ty)), + Predicate::ObjectSafe(did) => Predicate::ObjectSafe(self.translate_orig(did)), + Predicate::ClosureKind(did, kind) => + Predicate::ClosureKind(self.translate_orig(did), kind), + Predicate::Subtype(subtype_predicate) => { + Predicate::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, + } + })) + }, + } + } + + pub fn translate_param_env(&self, orig_def_id: DefId, param_env: ParamEnv<'tcx>) + -> ParamEnv<'tcx> + { + let index_map = self.construct_index_map(orig_def_id); + let res = param_env + .caller_bounds + .iter() + .map(|p| self.translate_predicate(&index_map, *p)) + .collect::>(); + + ParamEnv { + caller_bounds: self.tcx.intern_predicates(&res), + reveal: param_env.reveal, + } + } +} + /// Construct an parameter index map for an item. -fn construct_index_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old_def_id: DefId) +fn construct_index_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, orig_def_id: DefId) -> HashMap { let mut index_map = HashMap::new(); - let old_generics = tcx.generics_of(old_def_id); + let orig_generics = tcx.generics_of(orig_def_id); - for type_ in &old_generics.types { + for type_ in &orig_generics.types { index_map.insert(type_.index, type_.def_id); } - if let Some(did) = old_generics.parent { + if let Some(did) = orig_generics.parent { let parent_generics = tcx.generics_of(did); for type_ in &parent_generics.types { @@ -30,23 +273,23 @@ fn construct_index_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old_def_id: DefId) index_map } -/// Translate all old `DefId`s in the object to their new counterparts, if possible. +/// Translate all original `DefId`s in the object to their target counterparts, if possible. fn translate<'a, 'tcx, T>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, index_map: &HashMap, - old: &T) -> T + orig: &T) -> T where T: TypeFoldable<'tcx> { use rustc::ty::{AdtDef, Binder, ExistentialProjection, ExistentialTraitRef}; use rustc::ty::ExistentialPredicate::*; use rustc::ty::TypeVariants::*; - old.fold_with(&mut BottomUpFolder { tcx: tcx, fldop: |ty| { + orig.fold_with(&mut BottomUpFolder { tcx: tcx, fldop: |ty| { match ty.sty { TyAdt(&AdtDef { ref did, .. }, substs) if id_mapping.in_old_crate(*did) => { - let new_def_id = id_mapping.get_new_id(*did); - let new_adt = tcx.adt_def(new_def_id); - tcx.mk_adt(new_adt, substs) + let target_def_id = id_mapping.get_new_id(*did); + let target_adt = tcx.adt_def(target_def_id); + tcx.mk_adt(target_adt, substs) }, TyRef(region, type_and_mut) => { tcx.mk_ref(translate_region(id_mapping, tcx, region), type_and_mut) @@ -55,21 +298,21 @@ fn translate<'a, 'tcx, T>(id_mapping: &IdMapping, tcx.mk_fn_def(id_mapping.get_new_id(did), substs) }, TyDynamic(preds, region) => { - let new_preds = tcx.mk_existential_predicates(preds.iter().map(|p| { + let target_preds = tcx.mk_existential_predicates(preds.iter().map(|p| { match *p.skip_binder() { Trait(ExistentialTraitRef { def_id: did, substs }) => { - let new_def_id = id_mapping.get_new_id(did); + let target_def_id = id_mapping.get_new_id(did); Trait(ExistentialTraitRef { - def_id: new_def_id, + def_id: target_def_id, substs: substs }) }, Projection(ExistentialProjection { item_def_id, substs, ty }) => { - let new_def_id = id_mapping.get_new_id(item_def_id); + let target_def_id = id_mapping.get_new_id(item_def_id); Projection(ExistentialProjection { - item_def_id: new_def_id, + item_def_id: target_def_id, substs: substs, ty: ty, }) @@ -80,24 +323,24 @@ fn translate<'a, 'tcx, T>(id_mapping: &IdMapping, } })); - tcx.mk_dynamic(Binder(new_preds), region) + tcx.mk_dynamic(Binder(target_preds), region) }, TyProjection(proj) => { let trait_def_id = tcx.associated_item(proj.item_def_id).container.id(); - let new_def_id = + let target_def_id = id_mapping.get_new_trait_item_id(proj.item_def_id, trait_def_id); - tcx.mk_projection(new_def_id, proj.substs) + tcx.mk_projection(target_def_id, proj.substs) }, TyAnon(did, substs) => { tcx.mk_anon(id_mapping.get_new_id(did), substs) }, TyParam(param) => { if param.idx != 0 { // `Self` is special - let old_def_id = index_map[¶m.idx]; - if id_mapping.in_old_crate(old_def_id) { - let new_def_id = id_mapping.get_new_id(old_def_id); - tcx.mk_param_from_def(&id_mapping.get_type_param(&new_def_id)) + let orig_def_id = index_map[¶m.idx]; + if id_mapping.in_old_crate(orig_def_id) { + let target_def_id = id_mapping.get_new_id(orig_def_id); + tcx.mk_param_from_def(&id_mapping.get_type_param(&target_def_id)) } else { tcx.mk_ty(TyParam(param)) } @@ -110,7 +353,7 @@ fn translate<'a, 'tcx, T>(id_mapping: &IdMapping, }}) } -/// Translate all old `DefId`s in the region to their new counterparts, if possible. +/// Translate all original `DefId`s in the region to their target counterparts, if possible. fn translate_region<'a, 'tcx>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, region: Region<'tcx>) -> Region<'tcx> { @@ -120,13 +363,13 @@ fn translate_region<'a, 'tcx>(id_mapping: &IdMapping, tcx.mk_region(match *region { ReEarlyBound(early) => { - let new_early = EarlyBoundRegion { + let target_early = EarlyBoundRegion { def_id: id_mapping.get_new_id(early.def_id), index: early.index, name: early.name, }; - ReEarlyBound(new_early) + ReEarlyBound(target_early) }, ReFree(FreeRegion { scope, bound_region }) => { ReFree(FreeRegion { @@ -141,17 +384,17 @@ fn translate_region<'a, 'tcx>(id_mapping: &IdMapping, }) } -/// Translate all old `DefId`s in the type to their new counterparts, if possible. +/// Translate all original `DefId`s in the type to their target counterparts, if possible. /// /// This computes the mapping of type parameters needed as well. pub fn translate_item_type<'a, 'tcx>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, - old_def_id: DefId, - old: Ty<'tcx>) -> Ty<'tcx> { - translate(id_mapping, tcx, &construct_index_map(tcx, old_def_id), &old) + orig_def_id: DefId, + orig: Ty<'tcx>) -> Ty<'tcx> { + translate(id_mapping, tcx, &construct_index_map(tcx, orig_def_id), &orig) } -/// Translate all old `DefId`s in the predicate to their new counterparts, if possible. +/// Translate all original `DefId`s in the predicate to their target counterparts, if possible. fn translate_predicate<'a, 'tcx>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, index_map: &HashMap, @@ -221,14 +464,14 @@ fn translate_predicate<'a, 'tcx>(id_mapping: &IdMapping, } } -/// Translate all old `DefId`s in the `ParamEnv` to their new counterparts, if possible. +/// Translate all original `DefId`s in the `ParamEnv` to their target counterparts, if possible. /// /// This computes the mapping of type parameters needed as well. pub fn translate_param_env<'a, 'tcx>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, - old_def_id: DefId, + orig_def_id: DefId, param_env: ParamEnv<'tcx>) -> ParamEnv<'tcx> { - let index_map = construct_index_map(tcx, old_def_id); + let index_map = construct_index_map(tcx, orig_def_id); let res = param_env .caller_bounds .iter() From b54c8f01d5d3fa4e922b891735d826db76eeffbe Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 29 Jul 2017 00:15:42 +0200 Subject: [PATCH 184/553] First steps towards more correct bounds checks. --- src/semcheck/mapping.rs | 15 +- src/semcheck/translate.rs | 302 +++++++------------------------------- src/semcheck/traverse.rs | 86 ++++++++--- 3 files changed, 135 insertions(+), 268 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 56467f1793044..4daae9f7e4690 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -142,6 +142,7 @@ impl IdMapping { /// Get the old `DefId` associated with the given new one. pub fn get_old_id(&self, new: DefId) -> DefId { + println!("new: {:?}", new); assert!(!self.in_old_crate(new)); if self.in_new_crate(new) && !self.non_mapped_items.contains(&new) { @@ -153,7 +154,6 @@ impl IdMapping { /// Get the new `DefId` associated with the given old one, respecting possibly removed /// traits that are a parent of the given `DefId`. - // TODO: write a reverse equivalent... pub fn get_new_trait_item_id(&self, old: DefId, trait_id: DefId) -> DefId { assert!(!self.in_new_crate(trait_id)); @@ -164,8 +164,19 @@ impl IdMapping { } } + /// Get the old `DefId` associated with the given new one, respecting possibly added + /// traits that are a parent of the given `DefId`. + pub fn get_old_trait_item_id(&self, new: DefId, trait_id: DefId) -> DefId { + assert!(!self.in_old_crate(trait_id)); + + if !self.non_mapped_items.contains(&trait_id) { + self.get_old_id(new) + } else { + new + } + } + /// Return the `DefId` of the trait a given item belongs to. - // TODO pub fn get_trait_def(&self, item_def_id: &DefId) -> Option { self.trait_item_mapping.get(item_def_id).map(|t| t.2) } diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 2784cf57c0ebd..1aa46588eb2b9 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -8,25 +8,63 @@ use semcheck::mapping::IdMapping; use std::collections::HashMap; -struct TranslationContext<'a, 'tcx, F1, F2, F3> - where 'tcx: 'a, - F1: Fn(&IdMapping, DefId) -> bool, +pub struct TranslationContext<'a, 'gcx, 'tcx/*, F1, F2, F3*/> + where 'gcx: 'tcx + 'a, + 'tcx: 'a, + /* F1: Fn(&IdMapping, DefId) -> bool, F2: Fn(&IdMapping, DefId) -> DefId, - F3: Fn(&IdMapping, DefId, DefId) -> DefId, + F3: Fn(&IdMapping, DefId, DefId) -> DefId, */ { - tcx: TyCtxt<'a, 'tcx, 'tcx>, + tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping, - needs_translation: F1, - translate_orig: F2, - translate_orig_trait: F3, + needs_translation: fn(&IdMapping, DefId) -> bool, // F1, + translate_orig: fn(&IdMapping, DefId) -> DefId, // F2, + translate_orig_trait: fn(&IdMapping, DefId, DefId) -> DefId, // F3, } -impl<'a, 'tcx, F1, F2, F3> TranslationContext<'a, 'tcx, F1, F2, F3> - where 'tcx: 'a, - F1: Fn(&IdMapping, DefId) -> bool, +impl<'a, 'gcx, 'tcx/*, F1, F2, F3*/> TranslationContext<'a, 'gcx, 'tcx/*, F1, F2, F3*/> + /* F1: Fn(&IdMapping, DefId) -> bool, F2: Fn(&IdMapping, DefId) -> DefId, - F3: Fn(&IdMapping, DefId, DefId) -> DefId, + F3: Fn(&IdMapping, DefId, DefId) -> DefId,*/ { + // TODO: check whether the function pointers force us to use dynamic dispatch + pub fn to_new(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping) + -> TranslationContext<'a, 'gcx, 'tcx/*, F1, F2, F3*/> + { + TranslationContext { + tcx: tcx, + id_mapping: id_mapping, + needs_translation: |id_mapping, orig_def_id| { + id_mapping.in_old_crate(orig_def_id) + }, + translate_orig: |id_mapping, orig_def_id| { + id_mapping.get_new_id(orig_def_id) + }, + translate_orig_trait: |id_mapping, orig_def_id, trait_def_id| { + id_mapping.get_new_trait_item_id(orig_def_id, trait_def_id) + }, + } + } + + // TODO: check whether the function pointers force us to use dynamic dispatch + pub fn to_old(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping) + -> TranslationContext<'a, 'gcx, 'tcx/*, F1, F2, F3*/> + { + TranslationContext { + tcx: tcx, + id_mapping: id_mapping, + needs_translation: |id_mapping, orig_def_id| { + id_mapping.in_new_crate(orig_def_id) + }, + translate_orig: |id_mapping, orig_def_id| { + id_mapping.get_old_id(orig_def_id) + }, + translate_orig_trait: |id_mapping, orig_def_id, trait_def_id| { + id_mapping.get_old_trait_item_id(orig_def_id, trait_def_id) + }, + } + } + fn construct_index_map(&self, orig_def_id: DefId) -> HashMap { let mut index_map = HashMap::new(); let orig_generics = self.tcx.generics_of(orig_def_id); @@ -234,6 +272,13 @@ impl<'a, 'tcx, F1, F2, F3> TranslationContext<'a, 'tcx, F1, F2, F3> } } + pub fn translate_predicates(&self, orig_def_id: DefId, orig_preds: Vec>) + -> Vec> + { + let index_map = self.construct_index_map(orig_def_id); + orig_preds.iter().map(|p| self.translate_predicate(&index_map, *p)).collect() + } + pub fn translate_param_env(&self, orig_def_id: DefId, param_env: ParamEnv<'tcx>) -> ParamEnv<'tcx> { @@ -251,239 +296,6 @@ impl<'a, 'tcx, F1, F2, F3> TranslationContext<'a, 'tcx, F1, F2, F3> } } -/// Construct an parameter index map for an item. -fn construct_index_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, orig_def_id: DefId) - -> HashMap -{ - let mut index_map = HashMap::new(); - let orig_generics = tcx.generics_of(orig_def_id); - - for type_ in &orig_generics.types { - index_map.insert(type_.index, type_.def_id); - } - - if let Some(did) = orig_generics.parent { - let parent_generics = tcx.generics_of(did); - - for type_ in &parent_generics.types { - index_map.insert(type_.index, type_.def_id); - } - } - - index_map -} - -/// Translate all original `DefId`s in the object to their target counterparts, if possible. -fn translate<'a, 'tcx, T>(id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - index_map: &HashMap, - orig: &T) -> T - where T: TypeFoldable<'tcx> -{ - use rustc::ty::{AdtDef, Binder, ExistentialProjection, ExistentialTraitRef}; - use rustc::ty::ExistentialPredicate::*; - use rustc::ty::TypeVariants::*; - - orig.fold_with(&mut BottomUpFolder { tcx: tcx, fldop: |ty| { - match ty.sty { - TyAdt(&AdtDef { ref did, .. }, substs) if id_mapping.in_old_crate(*did) => { - let target_def_id = id_mapping.get_new_id(*did); - let target_adt = tcx.adt_def(target_def_id); - tcx.mk_adt(target_adt, substs) - }, - TyRef(region, type_and_mut) => { - tcx.mk_ref(translate_region(id_mapping, tcx, region), type_and_mut) - }, - TyFnDef(did, substs) => { - tcx.mk_fn_def(id_mapping.get_new_id(did), substs) - }, - TyDynamic(preds, region) => { - let target_preds = tcx.mk_existential_predicates(preds.iter().map(|p| { - match *p.skip_binder() { - Trait(ExistentialTraitRef { def_id: did, substs }) => { - let target_def_id = id_mapping.get_new_id(did); - - Trait(ExistentialTraitRef { - def_id: target_def_id, - substs: substs - }) - }, - Projection(ExistentialProjection { item_def_id, substs, ty }) => { - let target_def_id = id_mapping.get_new_id(item_def_id); - - Projection(ExistentialProjection { - item_def_id: target_def_id, - substs: substs, - ty: ty, - }) - }, - AutoTrait(did) => { - AutoTrait(id_mapping.get_new_id(did)) - }, - } - })); - - tcx.mk_dynamic(Binder(target_preds), region) - }, - TyProjection(proj) => { - let trait_def_id = tcx.associated_item(proj.item_def_id).container.id(); - let target_def_id = - id_mapping.get_new_trait_item_id(proj.item_def_id, trait_def_id); - - tcx.mk_projection(target_def_id, proj.substs) - }, - TyAnon(did, substs) => { - tcx.mk_anon(id_mapping.get_new_id(did), substs) - }, - TyParam(param) => { - if param.idx != 0 { // `Self` is special - let orig_def_id = index_map[¶m.idx]; - if id_mapping.in_old_crate(orig_def_id) { - let target_def_id = id_mapping.get_new_id(orig_def_id); - tcx.mk_param_from_def(&id_mapping.get_type_param(&target_def_id)) - } else { - tcx.mk_ty(TyParam(param)) - } - } else { - tcx.mk_ty(TyParam(param)) - } - }, - _ => ty, - } - }}) -} - -/// Translate all original `DefId`s in the region to their target counterparts, if possible. -fn translate_region<'a, 'tcx>(id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - region: Region<'tcx>) -> Region<'tcx> { - use rustc::ty::{EarlyBoundRegion, FreeRegion}; - use rustc::ty::BoundRegion::BrNamed; - use rustc::ty::RegionKind::*; - - tcx.mk_region(match *region { - ReEarlyBound(early) => { - let target_early = EarlyBoundRegion { - def_id: id_mapping.get_new_id(early.def_id), - index: early.index, - name: early.name, - }; - - ReEarlyBound(target_early) - }, - ReFree(FreeRegion { scope, bound_region }) => { - ReFree(FreeRegion { - scope: id_mapping.get_new_id(scope), - bound_region: match bound_region { - BrNamed(def_id, name) => BrNamed(id_mapping.get_new_id(def_id), name), - reg => reg, - }, - }) - }, - reg => reg, - }) -} - -/// Translate all original `DefId`s in the type to their target counterparts, if possible. -/// -/// This computes the mapping of type parameters needed as well. -pub fn translate_item_type<'a, 'tcx>(id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - orig_def_id: DefId, - orig: Ty<'tcx>) -> Ty<'tcx> { - translate(id_mapping, tcx, &construct_index_map(tcx, orig_def_id), &orig) -} - -/// Translate all original `DefId`s in the predicate to their target counterparts, if possible. -fn translate_predicate<'a, 'tcx>(id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - index_map: &HashMap, - predicate: Predicate<'tcx>) -> Predicate<'tcx> { - use rustc::ty::{EquatePredicate, OutlivesPredicate, ProjectionPredicate, ProjectionTy, - SubtypePredicate, TraitPredicate, TraitRef}; - - match predicate { - Predicate::Trait(trait_predicate) => { - Predicate::Trait(trait_predicate.map_bound(|t_pred| { - TraitPredicate { - trait_ref: TraitRef { - def_id: id_mapping.get_new_id(t_pred.trait_ref.def_id), - substs: t_pred.trait_ref.substs, - } - } - })) - }, - Predicate::Equate(equate_predicate) => { - Predicate::Equate(equate_predicate.map_bound(|e_pred| { - let l = translate(id_mapping, tcx, index_map, &e_pred.0); - let r = translate(id_mapping, tcx, index_map, &e_pred.1); - EquatePredicate(l, r) - })) - }, - Predicate::RegionOutlives(region_outlives_predicate) => { - Predicate::RegionOutlives(region_outlives_predicate.map_bound(|r_pred| { - let l = translate_region(id_mapping, tcx, r_pred.0); - let r = translate_region(id_mapping, tcx, r_pred.1); - OutlivesPredicate(l, r) - })) - }, - Predicate::TypeOutlives(type_outlives_predicate) => { - Predicate::TypeOutlives(type_outlives_predicate.map_bound(|r_pred| { - let l = translate(id_mapping, tcx, index_map, &r_pred.0); - let r = translate_region(id_mapping, tcx, r_pred.1); - OutlivesPredicate(l, r) - })) - }, - Predicate::Projection(projection_predicate) => { - Predicate::Projection(projection_predicate.map_bound(|p_pred| { - ProjectionPredicate { - projection_ty: ProjectionTy { - substs: p_pred.projection_ty.substs, // TODO: maybe this needs handling - item_def_id: id_mapping.get_new_id(p_pred.projection_ty.item_def_id), - }, - ty: translate(id_mapping, tcx, index_map, &p_pred.ty), - } - })) - }, - Predicate::WellFormed(ty) => - Predicate::WellFormed(translate(id_mapping, tcx, index_map, &ty)), - Predicate::ObjectSafe(did) => Predicate::ObjectSafe(id_mapping.get_new_id(did)), - Predicate::ClosureKind(did, kind) => - Predicate::ClosureKind(id_mapping.get_new_id(did), kind), - Predicate::Subtype(subtype_predicate) => { - Predicate::Subtype(subtype_predicate.map_bound(|s_pred| { - let l = translate(id_mapping, tcx, index_map, &s_pred.a); - let r = translate(id_mapping, tcx, index_map, &s_pred.b); - SubtypePredicate { - a_is_expected: s_pred.a_is_expected, - a: l, - b: r, - } - })) - }, - } -} - -/// Translate all original `DefId`s in the `ParamEnv` to their target counterparts, if possible. -/// -/// This computes the mapping of type parameters needed as well. -pub fn translate_param_env<'a, 'tcx>(id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - orig_def_id: DefId, - param_env: ParamEnv<'tcx>) -> ParamEnv<'tcx> { - let index_map = construct_index_map(tcx, orig_def_id); - let res = param_env - .caller_bounds - .iter() - .map(|p| translate_predicate(id_mapping, tcx, &index_map, *p)) - .collect::>(); - - ParamEnv { - caller_bounds: tcx.intern_predicates(&res), - reveal: param_env.reveal, - } -} - /// A simple closure folder for regions and types. pub struct BottomUpRegionFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a, F, G> where F: FnMut(Ty<'tcx>) -> Ty<'tcx>, diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 93b66891aaaae..75e2b13a863bf 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -11,8 +11,9 @@ use rustc::hir::def::{CtorKind, Def}; use rustc::hir::def_id::DefId; +use rustc::infer::InferCtxt; use rustc::traits::{FulfillmentContext, Obligation, ObligationCause}; -use rustc::ty::{AssociatedItem, Ty, TyCtxt}; +use rustc::ty::{AssociatedItem, ParamEnv, Predicate, Ty, TyCtxt}; use rustc::ty::Visibility::Public; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::{Subst, Substs}; @@ -21,7 +22,7 @@ use semcheck::changes::ChangeType::*; use semcheck::changes::ChangeSet; use semcheck::mapping::{IdMapping, NameMapping}; use semcheck::mismatch::Mismatch; -use semcheck::translate::{BottomUpRegionFolder, translate_item_type, translate_param_env}; +use semcheck::translate::{BottomUpRegionFolder, TranslationContext}; use std::collections::{BTreeSet, BTreeMap, HashMap, HashSet, VecDeque}; @@ -668,8 +669,10 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, use rustc::ty::TypeVariants::*; use syntax_pos::DUMMY_SP; + let to_new = TranslationContext::to_new(tcx, id_mapping); + let substs = Substs::identity_for_item(tcx, new_def_id); - let old = translate_item_type(id_mapping, tcx, old_def_id, old).subst(tcx, substs); + let old = to_new.translate_item_type(old_def_id, old).subst(tcx, substs); tcx.infer_ctxt().enter(|infcx| { let new_substs = if new.is_fn() { @@ -695,8 +698,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let new = new.subst(infcx.tcx, new_substs); - let old_param_env = - translate_param_env(id_mapping, tcx, old_def_id, tcx.param_env(old_def_id)); + let old_param_env = to_new.translate_param_env(old_def_id, tcx.param_env(old_def_id)); let new_param_env = tcx.param_env(new_def_id).subst(infcx.tcx, new_substs); let cause = ObligationCause::dummy(); @@ -740,10 +742,13 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let mut fulfill_cx = FulfillmentContext::new(); - for predicate in new_param_env.caller_bounds.iter() { - let obligation = Obligation::new(cause.clone(), old_param_env, *predicate); - fulfill_cx.register_predicate_obligation(&infcx, obligation); - } + register_bounds(&infcx, + new_param_env, + old_param_env, + &mut fulfill_cx, + new_def_id, + new_substs, + None); if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) { for err in &errors { @@ -758,11 +763,16 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } } else { let mut fulfill_cx_rev = FulfillmentContext::new(); + let to_old = TranslationContext::to_old(infcx.tcx, id_mapping); + let to_new = TranslationContext::to_new(infcx.tcx, id_mapping); - for predicate in old_param_env.caller_bounds.iter() { - let obligation = Obligation::new(cause.clone(), new_param_env, *predicate); - fulfill_cx_rev.register_predicate_obligation(&infcx, obligation); - } + register_bounds(&infcx, + old_param_env, + new_param_env, + &mut fulfill_cx_rev, + old_def_id, + substs, + Some(&to_new)); if let Err(errors) = fulfill_cx_rev.select_all_or_error(&infcx) { for err in &errors { @@ -788,6 +798,8 @@ fn cmp_impls<'a, 'tcx>(id_mapping: &IdMapping, use rustc::infer::InferOk; use syntax_pos::DUMMY_SP; + let to_new = TranslationContext::to_new(tcx, id_mapping); + let old = tcx .impl_trait_ref(old_def_id) .and_then(|trait_ref| trait_ref.substs.get(0)) @@ -808,7 +820,7 @@ fn cmp_impls<'a, 'tcx>(id_mapping: &IdMapping, } let substs = Substs::identity_for_item(tcx, new_def_id); - let old = translate_item_type(id_mapping, tcx, old_def_id, old).subst(tcx, substs); + let old = to_new.translate_item_type(old_def_id, old).subst(tcx, substs); tcx.infer_ctxt().enter(|infcx| { let new_substs = { @@ -826,8 +838,7 @@ fn cmp_impls<'a, 'tcx>(id_mapping: &IdMapping, let new = new.subst(infcx.tcx, new_substs); - let old_param_env = - translate_param_env(id_mapping, tcx, old_def_id, tcx.param_env(old_def_id)); + let old_param_env = to_new.translate_param_env(old_def_id, tcx.param_env(old_def_id)); let new_param_env = tcx.param_env(new_def_id).subst(infcx.tcx, new_substs); let cause = ObligationCause::dummy(); @@ -842,12 +853,45 @@ fn cmp_impls<'a, 'tcx>(id_mapping: &IdMapping, } let mut fulfill_cx = FulfillmentContext::new(); - - for predicate in new_param_env.caller_bounds.iter() { - let obligation = Obligation::new(cause.clone(), old_param_env, *predicate); - fulfill_cx.register_predicate_obligation(&infcx, obligation); - } + register_bounds(&infcx, + new_param_env, + old_param_env, + &mut fulfill_cx, + new_def_id, + substs, + None); fulfill_cx.select_all_or_error(&infcx).is_ok() }) } + +fn register_bounds<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, + current_param_env: ParamEnv<'tcx>, + given_param_env: ParamEnv<'tcx>, + fulfill_cx: &mut FulfillmentContext<'tcx>, + def_id: DefId, + substs: &Substs<'tcx>, + trans_ctx: Option<&TranslationContext<'a, 'gcx, 'tcx>>) { + use rustc::traits::{normalize, Normalized, SelectionContext}; + + let mut selcx = SelectionContext::new(infcx); + let predicates = infcx.tcx.predicates_of(def_id).instantiate(infcx.tcx, substs); + let cause = ObligationCause::dummy(); + let Normalized { value, obligations } = + normalize(&mut selcx, current_param_env, cause.clone(), &predicates); + + for obligation in obligations { + fulfill_cx.register_predicate_obligation(infcx, obligation); + } + + let predicates = if let Some(trans_ctx) = trans_ctx { + trans_ctx.translate_predicates(def_id, value.predicates) + } else { + value.predicates + }; + + for predicate in predicates { + let obligation = Obligation::new(cause.clone(), given_param_env, predicate); + fulfill_cx.register_predicate_obligation(infcx, obligation); + } +} From 7ea8172003a0ecdf48599188891d03fe81e9e7dd Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 29 Jul 2017 16:49:48 +0200 Subject: [PATCH 185/553] Implemented a working bounds checking context. --- src/semcheck/mapping.rs | 22 +++--- src/semcheck/mismatch.rs | 2 +- src/semcheck/translate.rs | 43 ++++++----- src/semcheck/traverse.rs | 157 +++++++++++++++++++++----------------- tests/cases/traits/dump | 8 ++ 5 files changed, 135 insertions(+), 97 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 4daae9f7e4690..d52ffb3a4048b 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -15,7 +15,7 @@ use syntax::ast::Name; /// /// 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. +/// however. A reverse mapping is also included, but only for `DefId` lookup. pub struct IdMapping { /// The old crate. old_crate: CrateNum, @@ -39,6 +39,7 @@ pub struct IdMapping { } impl IdMapping { + /// Construct a new mapping with the given crate information. pub fn new(old_crate: CrateNum, new_crate: CrateNum) -> IdMapping { IdMapping { old_crate: old_crate, @@ -54,7 +55,6 @@ impl IdMapping { } /// Register two exports representing the same item across versions. - // TODO pub fn add_export(&mut self, old: Def, new: Def) -> bool { let old_def_id = old.def_id(); @@ -118,9 +118,9 @@ impl IdMapping { } /// Check whether a `DefId` represents a non-mapped defaulted type parameter. - pub fn is_non_mapped_defaulted_type_param(&self, new: &DefId) -> bool { - self.non_mapped_items.contains(new) && - self.type_params.get(new).map_or(false, |def| def.has_default) + 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| def.has_default) } /// Get the new `DefId` associated with the given old one. @@ -142,7 +142,6 @@ impl IdMapping { /// Get the old `DefId` associated with the given new one. pub fn get_old_id(&self, new: DefId) -> DefId { - println!("new: {:?}", new); assert!(!self.in_old_crate(new)); if self.in_new_crate(new) && !self.non_mapped_items.contains(&new) { @@ -181,14 +180,18 @@ impl IdMapping { self.trait_item_mapping.get(item_def_id).map(|t| t.2) } - /// Check whether a `DefId` is present in the mappings. - // TODO - pub fn contains_id(&self, old: DefId) -> bool { + /// 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<(DefId, DefId)> { self.toplevel_mapping @@ -206,7 +209,6 @@ impl IdMapping { } /// Iterate over the item pairs of all children of a given item. - // TODO pub fn children_of<'a>(&'a self, parent: DefId) -> Option + 'a> { diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index af3c4192cc476..f1915c8c7909b 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -186,7 +186,7 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { }; if let Some((old_def_id, new_def_id)) = matching { - if !self.id_mapping.contains_id(old_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_def_id, new_def_id)); diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 1aa46588eb2b9..9306f81d72dd1 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -8,25 +8,22 @@ use semcheck::mapping::IdMapping; use std::collections::HashMap; -pub struct TranslationContext<'a, 'gcx, 'tcx/*, F1, F2, F3*/> - where 'gcx: 'tcx + 'a, - 'tcx: 'a, - /* F1: Fn(&IdMapping, DefId) -> bool, - F2: Fn(&IdMapping, DefId) -> DefId, - F3: Fn(&IdMapping, DefId, DefId) -> DefId, */ -{ +/// The context in which `DefId` translation happens. +pub struct TranslationContext<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> { + /// The type context to use. tcx: TyCtxt<'a, 'gcx, 'tcx>, + /// The id mapping to use. id_mapping: &'a IdMapping, - needs_translation: fn(&IdMapping, DefId) -> bool, // F1, - translate_orig: fn(&IdMapping, DefId) -> DefId, // F2, - translate_orig_trait: fn(&IdMapping, DefId, DefId) -> DefId, // F3, + /// 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) -> DefId, + /// Elementary operation to translate a `DefId` of a trait item. + translate_orig_trait: fn(&IdMapping, DefId, DefId) -> DefId, } -impl<'a, 'gcx, 'tcx/*, F1, F2, F3*/> TranslationContext<'a, 'gcx, 'tcx/*, F1, F2, F3*/> - /* F1: Fn(&IdMapping, DefId) -> bool, - F2: Fn(&IdMapping, DefId) -> DefId, - F3: Fn(&IdMapping, DefId, DefId) -> DefId,*/ -{ +impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { + /// Construct a translation context translating to the new crate's `DefId`s. // TODO: check whether the function pointers force us to use dynamic dispatch pub fn to_new(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping) -> TranslationContext<'a, 'gcx, 'tcx/*, F1, F2, F3*/> @@ -46,6 +43,7 @@ impl<'a, 'gcx, 'tcx/*, F1, F2, F3*/> TranslationContext<'a, 'gcx, 'tcx/*, F1, F2 } } + /// Construct a translation context translating to the old crate's `DefId`s. // TODO: check whether the function pointers force us to use dynamic dispatch pub fn to_old(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping) -> TranslationContext<'a, 'gcx, 'tcx/*, F1, F2, F3*/> @@ -65,6 +63,7 @@ impl<'a, 'gcx, 'tcx/*, F1, F2, F3*/> TranslationContext<'a, 'gcx, 'tcx/*, F1, F2 } } + /// Construct a type parameter index map for translation. fn construct_index_map(&self, orig_def_id: DefId) -> HashMap { let mut index_map = HashMap::new(); let orig_generics = self.tcx.generics_of(orig_def_id); @@ -84,18 +83,22 @@ impl<'a, 'gcx, 'tcx/*, F1, F2, F3*/> TranslationContext<'a, 'gcx, 'tcx/*, F1, F2 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) } + /// Translate a `DefId` of a trait item. fn translate_orig_trait(&self, item_def_id: DefId, trait_def_id: DefId) -> DefId { (self.translate_orig_trait)(self.id_mapping, item_def_id, trait_def_id) } + /// Fold a structure, translating all `DefId`s reachable by the folder. fn translate>(&self, index_map: &HashMap, orig: &T) -> T { use rustc::ty::{AdtDef, Binder, ExistentialProjection, ExistentialTraitRef}; use rustc::ty::ExistentialPredicate::*; @@ -171,6 +174,7 @@ impl<'a, 'gcx, 'tcx/*, F1, F2, F3*/> TranslationContext<'a, 'gcx, 'tcx/*, F1, F2 }}) } + /// Translate a region. fn translate_region(&self, region: Region<'tcx>) -> Region<'tcx> { use rustc::ty::{EarlyBoundRegion, FreeRegion}; use rustc::ty::BoundRegion::BrNamed; @@ -199,10 +203,12 @@ impl<'a, 'gcx, 'tcx/*, F1, F2, F3*/> TranslationContext<'a, 'gcx, 'tcx/*, F1, F2 }) } + /// 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. fn translate_predicate(&self, index_map: &HashMap, predicate: Predicate<'tcx>) -> Predicate<'tcx> { @@ -215,7 +221,7 @@ impl<'a, 'gcx, 'tcx/*, F1, F2, F3*/> TranslationContext<'a, 'gcx, 'tcx/*, F1, F2 TraitPredicate { trait_ref: TraitRef { def_id: self.translate_orig(t_pred.trait_ref.def_id), - substs: t_pred.trait_ref.substs, + substs: self.translate(index_map, &t_pred.trait_ref.substs), } } })) @@ -245,8 +251,7 @@ impl<'a, 'gcx, 'tcx/*, F1, F2, F3*/> TranslationContext<'a, 'gcx, 'tcx/*, F1, F2 Predicate::Projection(projection_predicate.map_bound(|p_pred| { ProjectionPredicate { projection_ty: ProjectionTy { - // TODO: maybe this needs handling - substs: p_pred.projection_ty.substs, + substs: self.translate(index_map, &p_pred.projection_ty.substs), item_def_id: self.translate_orig(p_pred.projection_ty.item_def_id), }, ty: self.translate(index_map, &p_pred.ty), @@ -272,6 +277,7 @@ impl<'a, 'gcx, 'tcx/*, F1, F2, F3*/> TranslationContext<'a, 'gcx, 'tcx/*, F1, F2 } } + /// Translate a vector of predicates. pub fn translate_predicates(&self, orig_def_id: DefId, orig_preds: Vec>) -> Vec> { @@ -279,6 +285,7 @@ impl<'a, 'gcx, 'tcx/*, F1, F2, F3*/> TranslationContext<'a, 'gcx, 'tcx/*, F1, F2 orig_preds.iter().map(|p| self.translate_predicate(&index_map, *p)).collect() } + /// Translate a `ParamEnv`. pub fn translate_param_env(&self, orig_def_id: DefId, param_env: ParamEnv<'tcx>) -> ParamEnv<'tcx> { diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 75e2b13a863bf..6654c2209a7ee 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -12,8 +12,8 @@ use rustc::hir::def::{CtorKind, Def}; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; -use rustc::traits::{FulfillmentContext, Obligation, ObligationCause}; -use rustc::ty::{AssociatedItem, ParamEnv, Predicate, Ty, TyCtxt}; +use rustc::traits::{FulfillmentContext, FulfillmentError, Obligation, ObligationCause}; +use rustc::ty::{AssociatedItem, ParamEnv, Ty, TyCtxt}; use rustc::ty::Visibility::Public; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::{Subst, Substs}; @@ -56,6 +56,7 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI diff_types(&mut changes, &id_mapping, tcx, old, new); } + // fourth pass still diff_trait_impls(&mut changes, &id_mapping, tcx); changes @@ -69,6 +70,7 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI /// 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. +// TODO: clean up and simplify. fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -80,10 +82,11 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, let mut visited = HashSet::new(); let mut children = NameMapping::default(); let mut mod_queue = VecDeque::new(); - // 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. + // 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(); mod_queue.push_back((old, new, Public, Public)); @@ -248,8 +251,8 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, let n_def_id = n.def.def_id(); if new_vis == Public && cstore.visibility(n_def_id) == Public { - 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); + // delay the handling of additions until the id mapping is complete + additions.push(n); } } (None, None) => unreachable!(), @@ -257,12 +260,23 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, } } - // finally, process item removals - for o in removals.drain(..) { + // finally, process item additions and removals + for n in additions { + let n_def_id = n.def.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.def.def_id(); // reuse an already existing path change entry, if possible - if id_mapping.contains_id(o_def_id) { + if id_mapping.contains_old_id(o_def_id) { let n_def_id = id_mapping.get_new_id(o_def_id); 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); @@ -526,10 +540,12 @@ fn diff_generics(changes: &mut ChangeSet, (Some(old_type), None) => { found.push(TypeParameterRemoved { defaulted: old_type.has_default }); id_mapping.add_type_param(*old_type); + id_mapping.add_non_mapped(old_type.def_id); }, (None, Some(new_type)) => { // FIXME: is_fn could be used in a more elegant fashion found.push(TypeParameterAdded { defaulted: new_type.has_default || is_fn }); id_mapping.add_type_param(*new_type); + id_mapping.add_non_mapped(new_type.def_id); }, (None, None) => unreachable!(), } @@ -670,6 +686,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, use syntax_pos::DUMMY_SP; let to_new = TranslationContext::to_new(tcx, id_mapping); + let to_old = TranslationContext::to_old(tcx, id_mapping); let substs = Substs::identity_for_item(tcx, new_def_id); let old = to_new.translate_item_type(old_def_id, old).subst(tcx, substs); @@ -700,6 +717,10 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let old_param_env = to_new.translate_param_env(old_def_id, tcx.param_env(old_def_id)); let new_param_env = tcx.param_env(new_def_id).subst(infcx.tcx, new_substs); + let new_param_env_trans = + to_old + .translate_param_env(new_def_id, tcx.param_env(new_def_id)) + .subst(infcx.tcx, new_substs); let cause = ObligationCause::dummy(); @@ -740,17 +761,10 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, changes.add_change(TypeChanged { error: err }, old_def_id, None); } - let mut fulfill_cx = FulfillmentContext::new(); + let mut bound_cx = BoundContext::new(&infcx, old_param_env); + bound_cx.register(new_def_id, new_substs); - register_bounds(&infcx, - new_param_env, - old_param_env, - &mut fulfill_cx, - new_def_id, - new_substs, - None); - - if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) { + if let Some(errors) = bound_cx.get_errors() { for err in &errors { let pred = infcx.resolve_type_vars_if_possible(&err.obligation.predicate); let pred = pred.fold_with(&mut folder); @@ -762,19 +776,10 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, changes.add_change(err_type, old_def_id, Some(tcx.def_span(old_def_id))); } } else { - let mut fulfill_cx_rev = FulfillmentContext::new(); - let to_old = TranslationContext::to_old(infcx.tcx, id_mapping); - let to_new = TranslationContext::to_new(infcx.tcx, id_mapping); - - register_bounds(&infcx, - old_param_env, - new_param_env, - &mut fulfill_cx_rev, - old_def_id, - substs, - Some(&to_new)); - - if let Err(errors) = fulfill_cx_rev.select_all_or_error(&infcx) { + let mut rev_bound_cx = BoundContext::new(&infcx, new_param_env_trans); + rev_bound_cx.register(old_def_id, substs); + + if let Some(errors) = rev_bound_cx.get_errors() { for err in &errors { let pred = infcx.resolve_type_vars_if_possible(&err.obligation.predicate); let pred = pred.fold_with(&mut folder); @@ -852,46 +857,62 @@ fn cmp_impls<'a, 'tcx>(id_mapping: &IdMapping, return false; } - let mut fulfill_cx = FulfillmentContext::new(); - register_bounds(&infcx, - new_param_env, - old_param_env, - &mut fulfill_cx, - new_def_id, - substs, - None); - - fulfill_cx.select_all_or_error(&infcx).is_ok() + let mut bound_cx = BoundContext::new(&infcx, old_param_env); + bound_cx.register(new_def_id, substs); + bound_cx.get_errors().is_none() }) } -fn register_bounds<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, - current_param_env: ParamEnv<'tcx>, - given_param_env: ParamEnv<'tcx>, - fulfill_cx: &mut FulfillmentContext<'tcx>, - def_id: DefId, - substs: &Substs<'tcx>, - trans_ctx: Option<&TranslationContext<'a, 'gcx, 'tcx>>) { - use rustc::traits::{normalize, Normalized, SelectionContext}; - - let mut selcx = SelectionContext::new(infcx); - let predicates = infcx.tcx.predicates_of(def_id).instantiate(infcx.tcx, substs); - let cause = ObligationCause::dummy(); - let Normalized { value, obligations } = - normalize(&mut selcx, current_param_env, cause.clone(), &predicates); - - for obligation in obligations { - fulfill_cx.register_predicate_obligation(infcx, obligation); +/// The context in which bounds analysis happens. +pub struct BoundContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { + /// The inference context to use. + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + /// The fulfillment context to use. + fulfill_cx: FulfillmentContext<'tcx>, + /// The param env to be assumed. + given_param_env: ParamEnv<'tcx>, +} + +impl<'a, 'gcx, 'tcx> BoundContext<'a, 'gcx, 'tcx> { + /// Construct a new bound context. + pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, given_param_env: ParamEnv<'tcx>) -> Self { + BoundContext { + infcx: infcx, + fulfill_cx: FulfillmentContext::new(), + given_param_env: given_param_env, + } } - let predicates = if let Some(trans_ctx) = trans_ctx { - trans_ctx.translate_predicates(def_id, value.predicates) - } else { - value.predicates - }; + /// Register the bounds of an item. + pub fn register(&mut self, checked_def_id: DefId, substs: &Substs<'tcx>) { + use rustc::traits::{normalize, Normalized, 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 predicates { - let obligation = Obligation::new(cause.clone(), given_param_env, predicate); - fulfill_cx.register_predicate_obligation(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); + } + } + + /// Return inference errors, if any. + pub fn get_errors(&mut self) -> Option>> { + if let Err(err) = self.fulfill_cx.select_all_or_error(self.infcx) { + Some(err) + } else { + None + } } } diff --git a/tests/cases/traits/dump b/tests/cases/traits/dump index 681311cf8672e..c2a7b3b819d07 100644 --- a/tests/cases/traits/dump +++ b/tests/cases/traits/dump @@ -13,3 +13,11 @@ so for impls: for every old impl, e.g. impl Trait for X, check that X: Trait still holds, after translating (both X and Trait) to the new it's the same fulfillment context thing as making sure the bounds are satisfied + +given param_env: ParamEnv { caller_bounds: Slice([Binder(TraitPredicate())]), reveal: UserFacing } +predicates: [Binder(TraitPredicate())] +obligations: [] + +given param_env: ParamEnv { caller_bounds: Slice([Binder(TraitPredicate(<::A as std::marker::Sized>)), Binder(TraitPredicate())]), reveal: UserFacing } +predicates: [Binder(TraitPredicate()), Binder(TraitPredicate(<_#0t as std::marker::Sized>))] +obligations: [Obligation(predicate=Binder(TraitPredicate()),depth=0)] From 5718f4ceba06f4878627996088af3f492cd60a98 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 29 Jul 2017 16:56:26 +0200 Subject: [PATCH 186/553] Extended trait tests. --- tests/cases/traits/new.rs | 6 ++++++ tests/cases/traits/old.rs | 6 ++++++ tests/cases/traits/stdout | 26 ++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/tests/cases/traits/new.rs b/tests/cases/traits/new.rs index 00e9d1247a7ad..7928b36be444c 100644 --- a/tests/cases/traits/new.rs +++ b/tests/cases/traits/new.rs @@ -32,3 +32,9 @@ mod fgh { fn fgh(&self) -> u8; } } + +pub trait Ghi { } + +pub trait Hij { + type A; +} diff --git a/tests/cases/traits/old.rs b/tests/cases/traits/old.rs index c9229aa8f4bb9..629282cdde257 100644 --- a/tests/cases/traits/old.rs +++ b/tests/cases/traits/old.rs @@ -30,3 +30,9 @@ mod fgh { fn fgh(&self) -> bool; } } + +pub trait Ghi { + type A; +} + +pub trait Hij { } diff --git a/tests/cases/traits/stdout b/tests/cases/traits/stdout index 5d891631f6525..ed366282e1a56 100644 --- a/tests/cases/traits/stdout +++ b/tests/cases/traits/stdout @@ -98,3 +98,29 @@ warning: breaking changes in `Efg` | = warning: type parameter removed (breaking) +warning: breaking changes in `Ghi` + --> $REPO_PATH/tests/cases/traits/new.rs:36:1 + | +36 | pub trait Ghi { } + | ^^^^^^^^^^^^^^^^^ + | +warning: removed item from trait (breaking) + --> $REPO_PATH/tests/cases/traits/old.rs:35:5 + | +35 | type A; + | ^^^^^^^ + +warning: breaking changes in `Hij` + --> $REPO_PATH/tests/cases/traits/new.rs:38:1 + | +38 | / pub trait Hij { +39 | | type A; +40 | | } + | |_^ + | +warning: added item to trait (breaking) + --> $REPO_PATH/tests/cases/traits/new.rs:39:5 + | +39 | type A; + | ^^^^^^^ + From 093127753264961ff0154e6e2a6a20e479d1417e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 30 Jul 2017 13:09:27 +0200 Subject: [PATCH 187/553] Fixed minor bugs and discovered more major ones. --- src/semcheck/mapping.rs | 32 ++++++++++++++++++-------------- src/semcheck/mismatch.rs | 12 ++++++++---- src/semcheck/translate.rs | 9 +++++---- src/semcheck/traverse.rs | 10 ++++++++-- 4 files changed, 39 insertions(+), 24 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index d52ffb3a4048b..07274cb6171a1 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -124,54 +124,58 @@ impl IdMapping { } /// Get the new `DefId` associated with the given old one. - pub fn get_new_id(&self, old: DefId) -> DefId { + pub fn get_new_id(&self, old: DefId) -> Option { assert!(!self.in_new_crate(old)); - if self.in_old_crate(old) && !self.non_mapped_items.contains(&old) { + if self.in_old_crate(old) { if let Some(new) = self.toplevel_mapping.get(&old) { - new.1.def_id() + Some(new.1.def_id()) } else if let Some(new) = self.trait_item_mapping.get(&old) { - new.1.def_id() + Some(new.1.def_id()) + } else if let Some(new_def_id) = self.internal_mapping.get(&old) { + Some(*new_def_id) } else { - self.internal_mapping[&old] + None } } else { - old + Some(old) } } /// Get the old `DefId` associated with the given new one. - pub fn get_old_id(&self, new: DefId) -> DefId { + pub fn get_old_id(&self, new: DefId) -> Option { assert!(!self.in_old_crate(new)); - if self.in_new_crate(new) && !self.non_mapped_items.contains(&new) { - self.reverse_mapping[&new] + if self.in_new_crate(new) { + self.reverse_mapping.get(&new).map(|did| *did) } else { - new + Some(new) } } /// Get the new `DefId` associated with the given old one, respecting possibly removed /// traits that are a parent of the given `DefId`. - pub fn get_new_trait_item_id(&self, old: DefId, trait_id: DefId) -> DefId { + pub fn get_new_trait_item_id(&self, old: DefId, trait_id: DefId) -> Option { assert!(!self.in_new_crate(trait_id)); + // TODO: this body is now nonsensical. reevaluate. if !self.non_mapped_items.contains(&trait_id) { self.get_new_id(old) } else { - old + Some(old) } } /// Get the old `DefId` associated with the given new one, respecting possibly added /// traits that are a parent of the given `DefId`. - pub fn get_old_trait_item_id(&self, new: DefId, trait_id: DefId) -> DefId { + pub fn get_old_trait_item_id(&self, new: DefId, trait_id: DefId) -> Option { assert!(!self.in_old_crate(trait_id)); + // TODO: this body is now nonsensical. reevaluate. if !self.non_mapped_items.contains(&trait_id) { self.get_old_id(new) } else { - new + Some(new) } } diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index f1915c8c7909b..856d7985203fc 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -112,11 +112,15 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { for field in a_adt.all_fields().filter(|f| f.vis == Public) { let a_field_ty = field.ty(self.tcx, a_substs); - let b_field_ty = - b_fields[&self.id_mapping.get_new_id(field.did)] - .ty(self.tcx, b_substs); - let _ = self.relate(&a_field_ty, &b_field_ty)?; + 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)?; + } } Some((a_def.did, b_def.did)) diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 9306f81d72dd1..d9cf921e850b0 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -17,9 +17,9 @@ pub struct TranslationContext<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> { /// 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) -> DefId, + translate_orig: fn(&IdMapping, DefId) -> Option, /// Elementary operation to translate a `DefId` of a trait item. - translate_orig_trait: fn(&IdMapping, DefId, DefId) -> DefId, + translate_orig_trait: fn(&IdMapping, DefId, DefId) -> Option, } impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { @@ -90,12 +90,13 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { /// Translate a `DefId`. fn translate_orig(&self, def_id: DefId) -> DefId { - (self.translate_orig)(self.id_mapping, def_id) + (self.translate_orig)(self.id_mapping, def_id).unwrap_or(def_id) } /// Translate a `DefId` of a trait item. fn translate_orig_trait(&self, item_def_id: DefId, trait_def_id: DefId) -> DefId { (self.translate_orig_trait)(self.id_mapping, item_def_id, trait_def_id) + .unwrap_or(item_def_id) } /// Fold a structure, translating all `DefId`s reachable by the folder. @@ -107,7 +108,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { orig.fold_with(&mut BottomUpFolder { tcx: self.tcx, fldop: |ty| { match ty.sty { TyAdt(&AdtDef { ref did, .. }, substs) if self.needs_translation(*did) => { - let target_def_id = self.id_mapping.get_new_id(*did); + let target_def_id = self.translate_orig(*did); let target_adt = self.tcx.adt_def(target_def_id); self.tcx.mk_adt(target_adt, substs) }, diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 6654c2209a7ee..5d832fe486c46 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -277,7 +277,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, // 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); + 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 { @@ -481,12 +481,14 @@ fn diff_traits(changes: &mut ChangeSet, 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 = TraitItemAdded { defaulted: new_item.defaultness.has_value(), }; 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!(), } @@ -643,7 +645,11 @@ fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, for old_impl_def_id in all_impls.iter().filter(|&did| id_mapping.in_old_crate(*did)) { // ... compute trait `DefId`s, ... let old_trait_def_id = tcx.impl_trait_ref(*old_impl_def_id).unwrap().def_id; - let new_trait_def_id = id_mapping.get_new_id(old_trait_def_id); + let new_trait_def_id = if let Some(did) = id_mapping.get_new_id(old_trait_def_id) { + did + } else { + continue; + }; let mut matched = false; From 0294cfa961f5a2e9589fa12dc659b2b0cf0d1d98 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 30 Jul 2017 13:27:03 +0200 Subject: [PATCH 188/553] Added logging. This will hopefully allow us to make bug searching easier. --- Cargo.toml | 3 ++- src/bin/rust_semverver.rs | 19 ++++++++++++------- src/lib.rs | 3 +++ src/semcheck/translate.rs | 10 ++++++++-- tests/examples.rs | 1 - 5 files changed, 25 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 207e374dd7fb8..71b81324313f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,8 +17,9 @@ path = "src/bin/rust_semverver.rs" [dependencies] cargo = "^0.18.0" crates-io = "^0.7.0" +env_logger = "^0.4.0" +log = "^0.3.0" semver = "^0.7.0" -# getopts = "^0.2.14" [dev-dependencies] quickcheck = "^0.4.1" diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 319455f7c8b16..a00e3f1a59225 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -1,6 +1,7 @@ #![feature(box_syntax)] #![feature(rustc_private)] +extern crate env_logger; extern crate getopts; extern crate rustc; extern crate rustc_driver; @@ -141,6 +142,10 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { /// Find the sysroot before passing our args to the compiler driver, after registering our custom /// compiler driver. fn main() { + if env_logger::init().is_err() { + eprintln!("ERROR: could not initialize logger"); + } + let home = option_env!("RUSTUP_HOME"); let toolchain = option_env!("RUSTUP_TOOLCHAIN"); let sys_root = if let (Some(home), Some(toolchain)) = (home, toolchain) { @@ -149,13 +154,13 @@ fn main() { option_env!("SYSROOT") .map(|s| s.to_owned()) .or_else(|| { - Command::new("rustc") - .args(&["--print", "sysroot"]) - .output() - .ok() - .and_then(|out| String::from_utf8(out.stdout).ok()) - .map(|s| s.trim().to_owned()) - }) + Command::new("rustc") + .args(&["--print", "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 compilation, or use rustup") }; diff --git a/src/lib.rs b/src/lib.rs index 2d4e6ea720330..6e4f63f5a7d57 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,9 @@ #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] +#[macro_use] +extern crate log; + #[cfg(test)] #[macro_use] extern crate quickcheck; diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index d9cf921e850b0..acbb3cd2e7d65 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -90,13 +90,19 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { /// Translate a `DefId`. fn translate_orig(&self, def_id: DefId) -> DefId { - (self.translate_orig)(self.id_mapping, def_id).unwrap_or(def_id) + (self.translate_orig)(self.id_mapping, def_id).unwrap_or_else(|| { + warn!("not mapped: {:?}", def_id); + def_id + }) } /// Translate a `DefId` of a trait item. fn translate_orig_trait(&self, item_def_id: DefId, trait_def_id: DefId) -> DefId { (self.translate_orig_trait)(self.id_mapping, item_def_id, trait_def_id) - .unwrap_or(item_def_id) + .unwrap_or_else(|| { + warn!("not mapped: {:?} / {:?}", item_def_id, trait_def_id); + item_def_id + }) } /// Fold a structure, translating all `DefId`s reachable by the folder. diff --git a/tests/examples.rs b/tests/examples.rs index d0fbb0e573a81..a98f78bdce723 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -63,7 +63,6 @@ macro_rules! test { "--extern", &format!("old={}", old_rlib.to_str().unwrap()), "--extern", &format!("new={}", new_rlib.to_str().unwrap()), "tests/helper/test.rs"]) - .env("RUST_LOG", "debug") .env("RUST_BACKTRACE", "full") .env("RUST_SEMVER_CRATE_VERSION", "1.0.0") .stdin(Stdio::null()) From c958c50f0d3fe5356aa20b3f91cebe1e0d32831b Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 30 Jul 2017 16:18:11 +0200 Subject: [PATCH 189/553] Further debugging. --- src/semcheck/translate.rs | 10 ++++++---- src/semcheck/traverse.rs | 24 ++++++++++++++++-------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index acbb3cd2e7d65..b06626e66f512 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -91,7 +91,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { /// Translate a `DefId`. fn translate_orig(&self, def_id: DefId) -> DefId { (self.translate_orig)(self.id_mapping, def_id).unwrap_or_else(|| { - warn!("not mapped: {:?}", def_id); + info!("not mapped: {:?}", def_id); def_id }) } @@ -100,7 +100,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { fn translate_orig_trait(&self, item_def_id: DefId, trait_def_id: DefId) -> DefId { (self.translate_orig_trait)(self.id_mapping, item_def_id, trait_def_id) .unwrap_or_else(|| { - warn!("not mapped: {:?} / {:?}", item_def_id, trait_def_id); + info!("not mapped: {:?} / {:?}", item_def_id, trait_def_id); item_def_id }) } @@ -167,13 +167,15 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { let orig_def_id = index_map[¶m.idx]; if self.needs_translation(orig_def_id) { 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); self.tcx.mk_param_from_def(&type_param) } else { - self.tcx.mk_ty(TyParam(param)) + ty } } else { - self.tcx.mk_ty(TyParam(param)) + ty } }, _ => ty, diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 5d832fe486c46..11f80da7028b8 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -535,6 +535,9 @@ fn diff_generics(changes: &mut ChangeSet, found.push(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); @@ -691,6 +694,8 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, use rustc::ty::TypeVariants::*; use syntax_pos::DUMMY_SP; + info!("comparing types of {:?} / {:?}:\n {:?} / {:?}", old_def_id, new_def_id, old, new); + let to_new = TranslationContext::to_new(tcx, id_mapping); let to_old = TranslationContext::to_old(tcx, id_mapping); @@ -724,9 +729,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let old_param_env = to_new.translate_param_env(old_def_id, tcx.param_env(old_def_id)); let new_param_env = tcx.param_env(new_def_id).subst(infcx.tcx, new_substs); let new_param_env_trans = - to_old - .translate_param_env(new_def_id, tcx.param_env(new_def_id)) - .subst(infcx.tcx, new_substs); + to_old.translate_param_env(new_def_id, tcx.param_env(new_def_id)); let cause = ObligationCause::dummy(); @@ -830,8 +833,13 @@ fn cmp_impls<'a, 'tcx>(id_mapping: &IdMapping, return false; } + debug!("old env: {:?}", tcx.param_env(old_def_id)); + debug!("new env: {:?}", tcx.param_env(new_def_id)); + let substs = Substs::identity_for_item(tcx, new_def_id); - let old = to_new.translate_item_type(old_def_id, old).subst(tcx, substs); + debug!("to translate: {:?}", old); + // debug!("translated: {:?}", to_new.translate_item_type(old_def_id, old)); + // let old = to_new.translate_item_type(old_def_id, old).subst(tcx, substs); tcx.infer_ctxt().enter(|infcx| { let new_substs = { @@ -847,12 +855,12 @@ fn cmp_impls<'a, 'tcx>(id_mapping: &IdMapping, }) }; - let new = new.subst(infcx.tcx, new_substs); + // let new = new.subst(infcx.tcx, new_substs); let old_param_env = to_new.translate_param_env(old_def_id, tcx.param_env(old_def_id)); - let new_param_env = tcx.param_env(new_def_id).subst(infcx.tcx, new_substs); + // let new_param_env = tcx.param_env(new_def_id).subst(infcx.tcx, new_substs); - let cause = ObligationCause::dummy(); + /* let cause = ObligationCause::dummy(); let error = infcx .at(&cause, new_param_env) @@ -861,7 +869,7 @@ fn cmp_impls<'a, 'tcx>(id_mapping: &IdMapping, if error.is_err() { return false; - } + } */ let mut bound_cx = BoundContext::new(&infcx, old_param_env); bound_cx.register(new_def_id, substs); From 7f0794df5a9bbfcad041f4b10172c541b2d02f45 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 30 Jul 2017 23:29:00 +0200 Subject: [PATCH 190/553] Rewrote trait impl checking. --- src/semcheck/translate.rs | 13 ++++- src/semcheck/traverse.rs | 114 +++++++++----------------------------- 2 files changed, 38 insertions(+), 89 deletions(-) diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index b06626e66f512..23b5c1d9ff76b 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -1,5 +1,5 @@ use rustc::hir::def_id::DefId; -use rustc::ty::{ParamEnv, Predicate, Region, Ty, TyCtxt}; +use rustc::ty::{ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt}; use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder}; use rustc_data_structures::accumulate_vec::AccumulateVec; @@ -310,6 +310,17 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { reveal: param_env.reveal, } } + + /// Translate a `TraitRef`. + 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), + } + } } /// A simple closure folder for regions and types. diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 11f80da7028b8..9467f848b9cda 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -13,7 +13,7 @@ use rustc::hir::def::{CtorKind, Def}; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; use rustc::traits::{FulfillmentContext, FulfillmentError, Obligation, ObligationCause}; -use rustc::ty::{AssociatedItem, ParamEnv, Ty, TyCtxt}; +use rustc::ty::{AssociatedItem, ParamEnv, TraitRef, Ty, TyCtxt}; use rustc::ty::Visibility::Public; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::{Subst, Substs}; @@ -633,39 +633,15 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let mut new_impls = HashMap::new(); let all_impls = tcx.sess.cstore.implementations_of_trait(None); - // construct a set of implementations for each trait outside of the old crate. - for new_impl_def_id in all_impls.iter().filter(|&did| !id_mapping.in_old_crate(*did)) { - new_impls - .entry(tcx.impl_trait_ref(*new_impl_def_id).unwrap().def_id) - .or_insert_with(BTreeSet::new) - .insert(*new_impl_def_id); - } - - // for each implementation in the old crate, ... for old_impl_def_id in all_impls.iter().filter(|&did| id_mapping.in_old_crate(*did)) { - // ... compute trait `DefId`s, ... let old_trait_def_id = tcx.impl_trait_ref(*old_impl_def_id).unwrap().def_id; - let new_trait_def_id = if let Some(did) = id_mapping.get_new_id(old_trait_def_id) { - did - } else { + if id_mapping.get_new_id(old_trait_def_id).is_none() { continue; - }; - - let mut matched = false; - - // ... and try to match them up with new or outside impls. - for new_impl_def_id in &new_impls[&new_trait_def_id] { - matched |= cmp_impls(id_mapping, tcx, *old_impl_def_id, *new_impl_def_id); - - if matched { - break; - } } - if !matched { + if !match_impl(id_mapping, tcx, *old_impl_def_id) { let impl_span = tcx.def_span(*old_impl_def_id); changes.new_change(*old_impl_def_id, @@ -805,74 +781,24 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } /// Compare two implementations and indicate whether the new one is compatible with the old one. -fn cmp_impls<'a, 'tcx>(id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - old_def_id: DefId, - new_def_id: DefId) -> bool { - use rustc::infer::InferOk; - use syntax_pos::DUMMY_SP; - +fn match_impl<'a, 'tcx>(id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + old_def_id: DefId) -> bool { let to_new = TranslationContext::to_new(tcx, id_mapping); - - let old = tcx - .impl_trait_ref(old_def_id) - .and_then(|trait_ref| trait_ref.substs.get(0)) - .and_then(|kind| kind.as_type()) - .unwrap(); - let new = tcx - .impl_trait_ref(new_def_id) - .and_then(|trait_ref| trait_ref.substs.get(0)) - .and_then(|kind| kind.as_type()) - .unwrap(); - - let old_generics = tcx.generics_of(old_def_id); - let new_generics = tcx.generics_of(new_def_id); - - if old_generics.regions.len() > new_generics.regions.len() || - old_generics.types.len() > new_generics.types.len() { - return false; - } - - debug!("old env: {:?}", tcx.param_env(old_def_id)); - debug!("new env: {:?}", tcx.param_env(new_def_id)); - - let substs = Substs::identity_for_item(tcx, new_def_id); - debug!("to translate: {:?}", old); - // debug!("translated: {:?}", to_new.translate_item_type(old_def_id, old)); - // let old = to_new.translate_item_type(old_def_id, old).subst(tcx, substs); + debug!("matching: {:?}", old_def_id); tcx.infer_ctxt().enter(|infcx| { - let new_substs = { - Substs::for_item(infcx.tcx, new_def_id, |def, _| { - infcx.region_var_for_def(DUMMY_SP, def) - }, |def, substs| { - // TODO: strictly speaking, this shouldn't happen. - if def.index == 0 { // `Self` is special - tcx.mk_param_from_def(def) - } else { - infcx.type_var_for_def(DUMMY_SP, def, substs) - } - }) - }; - - // let new = new.subst(infcx.tcx, new_substs); - let old_param_env = to_new.translate_param_env(old_def_id, tcx.param_env(old_def_id)); - // let new_param_env = tcx.param_env(new_def_id).subst(infcx.tcx, new_substs); + debug!("env: {:?}", old_param_env); - /* let cause = ObligationCause::dummy(); - - let error = infcx - .at(&cause, new_param_env) - .eq(old, new) - .map(|InferOk { obligations: o, .. }| { assert_eq!(o, vec![]); }); - - if error.is_err() { - return false; - } */ + let old = tcx + .impl_trait_ref(old_def_id) + .unwrap(); + debug!("trait ref: {:?}", old); let mut bound_cx = BoundContext::new(&infcx, old_param_env); - bound_cx.register(new_def_id, substs); + bound_cx.register_trait_ref(to_new.translate_trait_ref(old_def_id, &old)); + // bound_cx.register(new_def_id, substs); bound_cx.get_errors().is_none() }) } @@ -921,9 +847,21 @@ impl<'a, 'gcx, 'tcx> BoundContext<'a, 'gcx, 'tcx> { } } + /// Register the trait bound represented by a `TraitRef`. + pub fn register_trait_ref(&mut self, checked_trait_ref: TraitRef<'tcx>) { + use rustc::ty::{Binder, Predicate, TraitPredicate}; + + let predicate = Predicate::Trait(Binder(TraitPredicate { + trait_ref: checked_trait_ref, + let obligation = + Obligation::new(ObligationCause::dummy(), self.given_param_env, predicate); + self.fulfill_cx.register_predicate_obligation(self.infcx, obligation); + } + /// Return inference errors, if any. pub fn get_errors(&mut self) -> Option>> { if let Err(err) = self.fulfill_cx.select_all_or_error(self.infcx) { + debug!("err: {:?}", err); Some(err) } else { None From 523b45bfe06bdc66f7d13824253783a670ba7a5e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 31 Jul 2017 01:32:42 +0200 Subject: [PATCH 191/553] Fixed a typo that broke the last commit. --- src/semcheck/traverse.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 9467f848b9cda..1db48de7339f8 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -24,7 +24,7 @@ use semcheck::mapping::{IdMapping, NameMapping}; use semcheck::mismatch::Mismatch; use semcheck::translate::{BottomUpRegionFolder, TranslationContext}; -use std::collections::{BTreeSet, BTreeMap, HashMap, HashSet, VecDeque}; +use std::collections::{BTreeMap, HashSet, VecDeque}; use syntax::symbol::Symbol; @@ -853,6 +853,7 @@ impl<'a, 'gcx, 'tcx> BoundContext<'a, 'gcx, 'tcx> { let predicate = Predicate::Trait(Binder(TraitPredicate { trait_ref: checked_trait_ref, + })); let obligation = Obligation::new(ObligationCause::dummy(), self.given_param_env, predicate); self.fulfill_cx.register_predicate_obligation(self.infcx, obligation); From 3770893fbc4bbf6b1f3474805b36aa4b16a1c419 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 31 Jul 2017 21:18:54 +0200 Subject: [PATCH 192/553] Implemented optional parameter translation and fixed substs translation. --- src/semcheck/translate.rs | 263 +++++++++++++++++++++++++++++--------- src/semcheck/traverse.rs | 26 +++- 2 files changed, 224 insertions(+), 65 deletions(-) diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 23b5c1d9ff76b..4ec6d2d0427c2 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -1,8 +1,7 @@ use rustc::hir::def_id::DefId; use rustc::ty::{ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt}; use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder}; - -use rustc_data_structures::accumulate_vec::AccumulateVec; +use rustc::ty::subst::Substs; use semcheck::mapping::IdMapping; @@ -14,6 +13,8 @@ pub struct TranslationContext<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, '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`. @@ -25,12 +26,13 @@ pub struct TranslationContext<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { /// Construct a translation context translating to the new crate's `DefId`s. // TODO: check whether the function pointers force us to use dynamic dispatch - pub fn to_new(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping) - -> TranslationContext<'a, 'gcx, 'tcx/*, F1, F2, F3*/> + pub fn to_new(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping, translate_params: bool) + -> TranslationContext<'a, 'gcx, 'tcx> { TranslationContext { tcx: tcx, id_mapping: id_mapping, + translate_params: translate_params, needs_translation: |id_mapping, orig_def_id| { id_mapping.in_old_crate(orig_def_id) }, @@ -45,12 +47,13 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { /// Construct a translation context translating to the old crate's `DefId`s. // TODO: check whether the function pointers force us to use dynamic dispatch - pub fn to_old(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping) + pub fn to_old(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping, translate_params: bool) -> TranslationContext<'a, 'gcx, 'tcx/*, F1, F2, F3*/> { TranslationContext { tcx: tcx, id_mapping: id_mapping, + translate_params: translate_params, needs_translation: |id_mapping, orig_def_id| { id_mapping.in_new_crate(orig_def_id) }, @@ -96,13 +99,83 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { }) } - /// Translate a `DefId` of a trait item. - fn translate_orig_trait(&self, item_def_id: DefId, trait_def_id: DefId) -> DefId { - (self.translate_orig_trait)(self.id_mapping, item_def_id, trait_def_id) - .unwrap_or_else(|| { - info!("not mapped: {:?} / {:?}", item_def_id, trait_def_id); - item_def_id - }) + /// Translate a `DefId` of a toplevel item and it's substs. + fn translate_orig_substs(&self, + index_map: &HashMap, + orig_def_id: DefId, + orig_substs: &Substs<'tcx>) -> Option<(DefId, &'tcx Substs<'tcx>)> { + self.translate_orig_opt_trait_substs(index_map, orig_def_id, None, orig_substs) + } + + /// Translate a `DefId` of a trait item and it's substs. + fn translate_orig_trait_substs(&self, + index_map: &HashMap, + orig_def_id: DefId, + orig_trait_def_id: DefId, + orig_substs: &Substs<'tcx>) + -> Option<(DefId, &'tcx Substs<'tcx>)> + { + self.translate_orig_opt_trait_substs(index_map, + orig_def_id, + Some(orig_trait_def_id), + orig_substs) + } + + /// Translate a `DefId` of any item and it's substs. + fn translate_orig_opt_trait_substs(&self, + index_map: &HashMap, + orig_def_id: DefId, + orig_trait_def_id: Option, + orig_substs: &Substs<'tcx>) + -> Option<(DefId, &'tcx Substs<'tcx>)> + { + use rustc::ty::ReEarlyBound; + use std::cell::Cell; + + let target_def_id = if let Some(orig_trait_def_id) = orig_trait_def_id { + (self.translate_orig_trait)(self.id_mapping, orig_def_id, orig_trait_def_id) + } else { + (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 = Substs::for_item(self.tcx, target_def_id, |def, _| { + if !success.get() { + self.tcx.mk_region(ReEarlyBound(def.to_early_bound_region_data())) + } else if let Some(region) = orig_substs + .get(def.index as usize) + .and_then(|k| k.as_region()) + { + self.translate_region(region) + } else { + success.set(false); + self.tcx.mk_region(ReEarlyBound(def.to_early_bound_region_data())) + } + + }, |def, _| { + if !success.get() { + self.tcx.mk_param_from_def(def) + } else if let Some(type_) = orig_substs + .get(def.index as usize) + .and_then(|k| k.as_type()) + { + self.translate(index_map, &type_) + } else if self.id_mapping.is_non_mapped_defaulted_type_param(&def.def_id) { + self.tcx.type_of(def.def_id) + } else { + success.set(false); + self.tcx.mk_param_from_def(def) + } + }); + + if success.get() { + return Some((target_def_id, target_substs)); + } + } + + None } /// Fold a structure, translating all `DefId`s reachable by the folder. @@ -114,35 +187,61 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { orig.fold_with(&mut BottomUpFolder { tcx: self.tcx, fldop: |ty| { match ty.sty { TyAdt(&AdtDef { ref did, .. }, substs) if self.needs_translation(*did) => { - let target_def_id = self.translate_orig(*did); - let target_adt = self.tcx.adt_def(target_def_id); - self.tcx.mk_adt(target_adt, substs) + if let Some((target_def_id, target_substs)) = + self.translate_orig_substs(index_map, *did, substs) + { + let target_adt = self.tcx.adt_def(target_def_id); + self.tcx.mk_adt(target_adt, target_substs) + } else { + self.tcx.types.err + } }, TyRef(region, type_and_mut) => { self.tcx.mk_ref(self.translate_region(region), type_and_mut) }, TyFnDef(did, substs) => { - self.tcx.mk_fn_def(self.translate_orig(did), substs) + 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 { + self.tcx.types.err + } }, TyDynamic(preds, region) => { + // hacky error catching mechanism + use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; + let mut success = true; + let err_pred = AutoTrait(DefId::local(CRATE_DEF_INDEX)); + let target_preds = self.tcx.mk_existential_predicates(preds.iter().map(|p| { match *p.skip_binder() { Trait(ExistentialTraitRef { def_id: did, substs }) => { - let target_def_id = self.translate_orig(did); - - Trait(ExistentialTraitRef { - def_id: target_def_id, - substs: substs - }) + if let Some((target_def_id, target_substs)) = + self.translate_orig_substs(index_map, did, substs) + { + Trait(ExistentialTraitRef { + def_id: target_def_id, + substs: target_substs + }) + } else { + success = false; + err_pred + } }, Projection(ExistentialProjection { item_def_id, substs, ty }) => { - let target_def_id = self.translate_orig(item_def_id); - - Projection(ExistentialProjection { - item_def_id: target_def_id, - substs: substs, - ty: ty, - }) + 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, + substs: target_substs, + ty: ty, + }) + } else { + success = false; + err_pred + } }, AutoTrait(did) => { AutoTrait(self.translate_orig(did)) @@ -150,20 +249,36 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { } })); - self.tcx.mk_dynamic(Binder(target_preds), region) + if success { + self.tcx.mk_dynamic(Binder(target_preds), region) + } else { + self.tcx.types.err + } }, TyProjection(proj) => { let trait_def_id = self.tcx.associated_item(proj.item_def_id).container.id(); - let target_def_id = - self.translate_orig_trait(proj.item_def_id, trait_def_id); - - self.tcx.mk_projection(target_def_id, proj.substs) + if let Some((target_def_id, target_substs)) = + self.translate_orig_trait_substs(index_map, + proj.item_def_id, + trait_def_id, + proj.substs) { + self.tcx.mk_projection(target_def_id, target_substs) + } else { + self.tcx.types.err + } }, TyAnon(did, substs) => { - self.tcx.mk_anon(self.translate_orig(did), substs) + if let Some((target_def_id, target_substs)) = + self.translate_orig_substs(index_map, did, substs) + { + self.tcx.mk_anon(target_def_id, target_substs) + } else { + self.tcx.types.err + } }, TyParam(param) => { - if param.idx != 0 { // `Self` is special + // TODO: we should check `has_self`! + if param.idx != 0 && self.translate_params { // `Self` is special let orig_def_id = index_map[¶m.idx]; if self.needs_translation(orig_def_id) { let target_def_id = self.translate_orig(orig_def_id); @@ -189,6 +304,10 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { use rustc::ty::BoundRegion::BrNamed; use rustc::ty::RegionKind::*; + if !self.translate_params { + return region; + } + self.tcx.mk_region(match *region { ReEarlyBound(early) => { let target_early = EarlyBoundRegion { @@ -219,20 +338,25 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { /// Translate a predicate. fn translate_predicate(&self, index_map: &HashMap, predicate: Predicate<'tcx>) - -> Predicate<'tcx> + -> Option> { - use rustc::ty::{EquatePredicate, OutlivesPredicate, ProjectionPredicate, ProjectionTy, - SubtypePredicate, TraitPredicate, TraitRef}; + use rustc::ty::{Binder, EquatePredicate, OutlivesPredicate, ProjectionPredicate, + ProjectionTy, SubtypePredicate, TraitPredicate, TraitRef}; - match predicate { + Some(match predicate { Predicate::Trait(trait_predicate) => { - Predicate::Trait(trait_predicate.map_bound(|t_pred| { + Predicate::Trait(Binder(if let Some((target_def_id, target_substs)) = + self.translate_orig_substs(index_map, + trait_predicate.0.trait_ref.def_id, + &trait_predicate.0.trait_ref.substs) { TraitPredicate { trait_ref: TraitRef { - def_id: self.translate_orig(t_pred.trait_ref.def_id), - substs: self.translate(index_map, &t_pred.trait_ref.substs), + def_id: target_def_id, + substs: target_substs, } } + } else { + return None; })) }, Predicate::Equate(equate_predicate) => { @@ -257,14 +381,19 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { })) }, Predicate::Projection(projection_predicate) => { - Predicate::Projection(projection_predicate.map_bound(|p_pred| { + Predicate::Projection(Binder(if let Some((target_def_id, target_substs)) = + self.translate_orig_substs(index_map, + projection_predicate.0.projection_ty.item_def_id, + &projection_predicate.0.projection_ty.substs) { ProjectionPredicate { projection_ty: ProjectionTy { - substs: self.translate(index_map, &p_pred.projection_ty.substs), - item_def_id: self.translate_orig(p_pred.projection_ty.item_def_id), + substs: target_substs, + item_def_id: target_def_id, }, - ty: self.translate(index_map, &p_pred.ty), + ty: self.translate(index_map, &projection_predicate.0.ty), } + } else { + return None; })) }, Predicate::WellFormed(ty) => @@ -283,32 +412,46 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { } })) }, - } + }) } /// Translate a vector of predicates. pub fn translate_predicates(&self, orig_def_id: DefId, orig_preds: Vec>) - -> Vec> + -> Option>> { let index_map = self.construct_index_map(orig_def_id); - orig_preds.iter().map(|p| self.translate_predicate(&index_map, *p)).collect() + 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`. pub fn translate_param_env(&self, orig_def_id: DefId, param_env: ParamEnv<'tcx>) - -> ParamEnv<'tcx> + -> Option> { let index_map = self.construct_index_map(orig_def_id); - let res = param_env - .caller_bounds - .iter() - .map(|p| self.translate_predicate(&index_map, *p)) - .collect::>(); - - ParamEnv { - caller_bounds: self.tcx.intern_predicates(&res), - reveal: param_env.reveal, + let mut target_preds = Vec::with_capacity(param_env.caller_bounds.len()); + + for orig_pred in param_env.caller_bounds { + if let Some(target_pred) = self.translate_predicate(&index_map, *orig_pred) { + target_preds.push(target_pred); + } else { + return None; + } } + + Some(ParamEnv { + caller_bounds: self.tcx.intern_predicates(&target_preds), + reveal: param_env.reveal, + }) } /// Translate a `TraitRef`. diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 1db48de7339f8..9e95b45becbb6 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -672,11 +672,11 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, info!("comparing types of {:?} / {:?}:\n {:?} / {:?}", old_def_id, new_def_id, old, new); - let to_new = TranslationContext::to_new(tcx, id_mapping); - let to_old = TranslationContext::to_old(tcx, id_mapping); + let to_new = TranslationContext::to_new(tcx, id_mapping, false); + let to_old = TranslationContext::to_old(tcx, id_mapping, false); let substs = Substs::identity_for_item(tcx, new_def_id); - let old = to_new.translate_item_type(old_def_id, old).subst(tcx, substs); + let old = to_new.translate_item_type(old_def_id, old); tcx.infer_ctxt().enter(|infcx| { let new_substs = if new.is_fn() { @@ -701,8 +701,10 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, }; let new = new.subst(infcx.tcx, new_substs); + let old = old.subst(infcx.tcx, substs); let old_param_env = to_new.translate_param_env(old_def_id, tcx.param_env(old_def_id)); + let new_param_env = tcx.param_env(new_def_id).subst(infcx.tcx, new_substs); let new_param_env_trans = to_old.translate_param_env(new_def_id, tcx.param_env(new_def_id)); @@ -746,6 +748,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, changes.add_change(TypeChanged { error: err }, old_def_id, None); } + let old_param_env = if let Some(env) = old_param_env { env } else { return; }; let mut bound_cx = BoundContext::new(&infcx, old_param_env); bound_cx.register(new_def_id, new_substs); @@ -761,6 +764,11 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, changes.add_change(err_type, old_def_id, Some(tcx.def_span(old_def_id))); } } else { + let new_param_env_trans = if let Some(env) = new_param_env_trans { + env + } else { + return; + }; let mut rev_bound_cx = BoundContext::new(&infcx, new_param_env_trans); rev_bound_cx.register(old_def_id, substs); @@ -784,17 +792,25 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, fn match_impl<'a, 'tcx>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, old_def_id: DefId) -> bool { - let to_new = TranslationContext::to_new(tcx, id_mapping); + let to_new = TranslationContext::to_new(tcx, id_mapping, false); debug!("matching: {:?}", old_def_id); tcx.infer_ctxt().enter(|infcx| { - let old_param_env = to_new.translate_param_env(old_def_id, tcx.param_env(old_def_id)); + let old_param_env = if let Some(env) = + to_new.translate_param_env(old_def_id, tcx.param_env(old_def_id)) + { + env + } else { + return false; + }; + debug!("env: {:?}", old_param_env); let old = tcx .impl_trait_ref(old_def_id) .unwrap(); debug!("trait ref: {:?}", old); + debug!("translated ref: {:?}", to_new.translate_trait_ref(old_def_id, &old)); let mut bound_cx = BoundContext::new(&infcx, old_param_env); bound_cx.register_trait_ref(to_new.translate_trait_ref(old_def_id, &old)); From c378462e3181e2361eebee845dd067feca27c51c Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 31 Jul 2017 21:53:52 +0200 Subject: [PATCH 193/553] Implemented backwards impl checks. --- src/semcheck/traverse.rs | 44 +++++++++++++++++++++++++++------- tests/cases/trait_impls/new.rs | 6 +++++ tests/cases/trait_impls/stdout | 38 +++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 9 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 9e95b45becbb6..c5fccbb10af56 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -653,6 +653,25 @@ fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, changes.add_change(TraitImplTightened, *old_impl_def_id, None); } } + + for new_impl_def_id in all_impls.iter().filter(|&did| id_mapping.in_new_crate(*did)) { + let new_trait_def_id = tcx.impl_trait_ref(*new_impl_def_id).unwrap().def_id; + if id_mapping.get_old_id(new_trait_def_id).is_none() { + continue; + } + + if !match_impl(id_mapping, tcx, *new_impl_def_id) { + let impl_span = tcx.def_span(*new_impl_def_id); + + changes.new_change(*new_impl_def_id, + *new_impl_def_id, + Symbol::intern("impl"), + impl_span, + impl_span, + true); + changes.add_change(TraitImplLoosened, *new_impl_def_id, None); + } + } } /// Compare two types and possibly register the error. @@ -701,7 +720,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, }; let new = new.subst(infcx.tcx, new_substs); - let old = old.subst(infcx.tcx, substs); + // let old = old.subst(infcx.tcx, substs); let old_param_env = to_new.translate_param_env(old_def_id, tcx.param_env(old_def_id)); @@ -791,13 +810,21 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, /// Compare two implementations and indicate whether the new one is compatible with the old one. fn match_impl<'a, 'tcx>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, - old_def_id: DefId) -> bool { - let to_new = TranslationContext::to_new(tcx, id_mapping, false); - debug!("matching: {:?}", old_def_id); + orig_def_id: DefId) -> bool { + let trans = if id_mapping.in_old_crate(orig_def_id) { + TranslationContext::to_new(tcx, id_mapping, false) + } else if id_mapping.in_new_crate(orig_def_id) { + TranslationContext::to_old(tcx, id_mapping, false) + } else { + // not reached, but apparently we don't care. + return true; + }; + + debug!("matching: {:?}", orig_def_id); tcx.infer_ctxt().enter(|infcx| { let old_param_env = if let Some(env) = - to_new.translate_param_env(old_def_id, tcx.param_env(old_def_id)) + trans.translate_param_env(orig_def_id, tcx.param_env(orig_def_id)) { env } else { @@ -807,14 +834,13 @@ fn match_impl<'a, 'tcx>(id_mapping: &IdMapping, debug!("env: {:?}", old_param_env); let old = tcx - .impl_trait_ref(old_def_id) + .impl_trait_ref(orig_def_id) .unwrap(); debug!("trait ref: {:?}", old); - debug!("translated ref: {:?}", to_new.translate_trait_ref(old_def_id, &old)); + debug!("translated ref: {:?}", trans.translate_trait_ref(orig_def_id, &old)); let mut bound_cx = BoundContext::new(&infcx, old_param_env); - bound_cx.register_trait_ref(to_new.translate_trait_ref(old_def_id, &old)); - // bound_cx.register(new_def_id, substs); + bound_cx.register_trait_ref(trans.translate_trait_ref(orig_def_id, &old)); bound_cx.get_errors().is_none() }) } diff --git a/tests/cases/trait_impls/new.rs b/tests/cases/trait_impls/new.rs index 2d385c59d34d4..691a526965329 100644 --- a/tests/cases/trait_impls/new.rs +++ b/tests/cases/trait_impls/new.rs @@ -1,3 +1,5 @@ +use std::cell::Cell; + pub struct Def; pub trait Abc { } @@ -9,3 +11,7 @@ impl Abc for Def { } impl Abc for Box { } impl Abc for Box { } + +impl Abc for () { } + +impl Abc for Cell<(bool, T)> { } diff --git a/tests/cases/trait_impls/stdout b/tests/cases/trait_impls/stdout index a385d4be4d942..7ee4d8ba6fb6a 100644 --- a/tests/cases/trait_impls/stdout +++ b/tests/cases/trait_impls/stdout @@ -1,3 +1,9 @@ +impl DefId { krate: CrateNum(13), node: DefIndex(7) => new/8cd878b::{{impl}}[1] }, DefId { krate: CrateNum(13), node: DefIndex(5) => new/8cd878b::Abc[0] } +impl DefId { krate: CrateNum(13), node: DefIndex(8) => new/8cd878b::{{impl}}[2] }, DefId { krate: CrateNum(13), node: DefIndex(5) => new/8cd878b::Abc[0] } +impl DefId { krate: CrateNum(13), node: DefIndex(10) => new/8cd878b::{{impl}}[4] }, DefId { krate: CrateNum(13), node: DefIndex(5) => new/8cd878b::Abc[0] } +impl DefId { krate: CrateNum(13), node: DefIndex(11) => new/8cd878b::{{impl}}[5] }, DefId { krate: CrateNum(13), node: DefIndex(5) => new/8cd878b::Abc[0] } +impl DefId { krate: CrateNum(13), node: DefIndex(9) => new/8cd878b::{{impl}}[3] }, DefId { krate: CrateNum(13), node: DefIndex(5) => new/8cd878b::Abc[0] } +impl DefId { krate: CrateNum(13), node: DefIndex(6) => new/8cd878b::{{impl}}[0] }, DefId { krate: CrateNum(13), node: DefIndex(5) => new/8cd878b::Abc[0] } version bump: 1.0.0 -> (breaking) -> 2.0.0 warning: breaking changes in `impl` --> $REPO_PATH/tests/cases/trait_impls/old.rs:9:1 @@ -19,3 +25,35 @@ warning: breaking changes in `impl` | = warning: trait impl specialized or removed (breaking) +warning: technically breaking changes in `impl` + --> $REPO_PATH/tests/cases/trait_impls/new.rs:11:1 + | +11 | impl Abc for Box { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `impl` + --> $REPO_PATH/tests/cases/trait_impls/new.rs:13:1 + | +13 | impl Abc for Box { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `impl` + --> $REPO_PATH/tests/cases/trait_impls/new.rs:15:1 + | +15 | impl Abc for () { } + | ^^^^^^^^^^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `impl` + --> $REPO_PATH/tests/cases/trait_impls/new.rs:17:1 + | +17 | impl Abc for Cell<(bool, T)> { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + From abb8c61fd981c92e819787d7fc7db57ca7effaa2 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 31 Jul 2017 23:22:53 +0200 Subject: [PATCH 194/553] Adressed some clippy warning. --- src/semcheck/mapping.rs | 2 +- src/semcheck/translate.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 07274cb6171a1..2f4e4376d5568 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -147,7 +147,7 @@ impl IdMapping { assert!(!self.in_old_crate(new)); if self.in_new_crate(new) { - self.reverse_mapping.get(&new).map(|did| *did) + self.reverse_mapping.get(&new).cloned() } else { Some(new) } diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 4ec6d2d0427c2..108105f1285f6 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -348,7 +348,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { Predicate::Trait(Binder(if let Some((target_def_id, target_substs)) = self.translate_orig_substs(index_map, trait_predicate.0.trait_ref.def_id, - &trait_predicate.0.trait_ref.substs) { + trait_predicate.0.trait_ref.substs) { TraitPredicate { trait_ref: TraitRef { def_id: target_def_id, @@ -384,7 +384,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { Predicate::Projection(Binder(if let Some((target_def_id, target_substs)) = self.translate_orig_substs(index_map, projection_predicate.0.projection_ty.item_def_id, - &projection_predicate.0.projection_ty.substs) { + projection_predicate.0.projection_ty.substs) { ProjectionPredicate { projection_ty: ProjectionTy { substs: target_substs, From b623329364aeabed19eba441f09c262ab3935d0b Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 1 Aug 2017 13:58:43 +0200 Subject: [PATCH 195/553] Fixed a few bugs. --- src/semcheck/translate.rs | 15 ++++++++++----- tests/cases/trait_impls/stdout | 6 ------ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 108105f1285f6..deecb67289597 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -129,6 +129,9 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { orig_substs: &Substs<'tcx>) -> Option<(DefId, &'tcx Substs<'tcx>)> { + debug!("translating w/ substs: did: {:?} (trait did: {:?}), substs: {:?}", + orig_def_id, orig_trait_def_id, orig_substs); + use rustc::ty::ReEarlyBound; use std::cell::Cell; @@ -164,6 +167,8 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { self.translate(index_map, &type_) } else if self.id_mapping.is_non_mapped_defaulted_type_param(&def.def_id) { 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) @@ -193,7 +198,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { let target_adt = self.tcx.adt_def(target_def_id); self.tcx.mk_adt(target_adt, target_substs) } else { - self.tcx.types.err + ty } }, TyRef(region, type_and_mut) => { @@ -205,7 +210,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { { self.tcx.mk_fn_def(target_def_id, target_substs) } else { - self.tcx.types.err + ty } }, TyDynamic(preds, region) => { @@ -252,7 +257,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { if success { self.tcx.mk_dynamic(Binder(target_preds), region) } else { - self.tcx.types.err + ty } }, TyProjection(proj) => { @@ -264,7 +269,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { proj.substs) { self.tcx.mk_projection(target_def_id, target_substs) } else { - self.tcx.types.err + ty } }, TyAnon(did, substs) => { @@ -273,7 +278,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { { self.tcx.mk_anon(target_def_id, target_substs) } else { - self.tcx.types.err + ty } }, TyParam(param) => { diff --git a/tests/cases/trait_impls/stdout b/tests/cases/trait_impls/stdout index 7ee4d8ba6fb6a..1c2996a431ac5 100644 --- a/tests/cases/trait_impls/stdout +++ b/tests/cases/trait_impls/stdout @@ -1,9 +1,3 @@ -impl DefId { krate: CrateNum(13), node: DefIndex(7) => new/8cd878b::{{impl}}[1] }, DefId { krate: CrateNum(13), node: DefIndex(5) => new/8cd878b::Abc[0] } -impl DefId { krate: CrateNum(13), node: DefIndex(8) => new/8cd878b::{{impl}}[2] }, DefId { krate: CrateNum(13), node: DefIndex(5) => new/8cd878b::Abc[0] } -impl DefId { krate: CrateNum(13), node: DefIndex(10) => new/8cd878b::{{impl}}[4] }, DefId { krate: CrateNum(13), node: DefIndex(5) => new/8cd878b::Abc[0] } -impl DefId { krate: CrateNum(13), node: DefIndex(11) => new/8cd878b::{{impl}}[5] }, DefId { krate: CrateNum(13), node: DefIndex(5) => new/8cd878b::Abc[0] } -impl DefId { krate: CrateNum(13), node: DefIndex(9) => new/8cd878b::{{impl}}[3] }, DefId { krate: CrateNum(13), node: DefIndex(5) => new/8cd878b::Abc[0] } -impl DefId { krate: CrateNum(13), node: DefIndex(6) => new/8cd878b::{{impl}}[0] }, DefId { krate: CrateNum(13), node: DefIndex(5) => new/8cd878b::Abc[0] } version bump: 1.0.0 -> (breaking) -> 2.0.0 warning: breaking changes in `impl` --> $REPO_PATH/tests/cases/trait_impls/old.rs:9:1 From 51f14977b172203741418db8d5b48a07cc0b62f9 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 1 Aug 2017 14:27:26 +0200 Subject: [PATCH 196/553] Some cleanup on duplication and naming. --- src/semcheck/translate.rs | 37 ++++++++++++++----------------------- src/semcheck/traverse.rs | 8 ++++---- 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index deecb67289597..8682d6d9c8103 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -26,8 +26,9 @@ pub struct TranslationContext<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { /// Construct a translation context translating to the new crate's `DefId`s. // TODO: check whether the function pointers force us to use dynamic dispatch - pub fn to_new(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping, translate_params: bool) - -> TranslationContext<'a, 'gcx, 'tcx> + pub fn target_new(tcx: TyCtxt<'a, 'gcx, 'tcx>, + id_mapping: &'a IdMapping, + translate_params: bool) -> TranslationContext<'a, 'gcx, 'tcx> { TranslationContext { tcx: tcx, @@ -47,9 +48,9 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { /// Construct a translation context translating to the old crate's `DefId`s. // TODO: check whether the function pointers force us to use dynamic dispatch - pub fn to_old(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping, translate_params: bool) - -> TranslationContext<'a, 'gcx, 'tcx/*, F1, F2, F3*/> - { + pub fn target_old(tcx: TyCtxt<'a, 'gcx, 'tcx>, + id_mapping: &'a IdMapping, + translate_params: bool) -> TranslationContext<'a, 'gcx, 'tcx> { TranslationContext { tcx: tcx, id_mapping: id_mapping, @@ -420,15 +421,15 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { }) } - /// Translate a vector of predicates. - pub fn translate_predicates(&self, orig_def_id: DefId, orig_preds: Vec>) + /// Translate a slice of predicates. + fn translate_predicates(&self, orig_def_id: DefId, orig_preds: &[Predicate<'tcx>]) -> Option>> { let index_map = self.construct_index_map(orig_def_id); let mut target_preds = Vec::with_capacity(orig_preds.len()); for orig_pred in orig_preds { - if let Some(target_pred) = self.translate_predicate(&index_map, orig_pred) { + if let Some(target_pred) = self.translate_predicate(&index_map, *orig_pred) { target_preds.push(target_pred); } else { return None; @@ -442,21 +443,11 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { pub fn translate_param_env(&self, orig_def_id: DefId, param_env: ParamEnv<'tcx>) -> Option> { - let index_map = self.construct_index_map(orig_def_id); - let mut target_preds = Vec::with_capacity(param_env.caller_bounds.len()); - - for orig_pred in param_env.caller_bounds { - if let Some(target_pred) = self.translate_predicate(&index_map, *orig_pred) { - target_preds.push(target_pred); - } else { - return None; - } - } - - Some(ParamEnv { - caller_bounds: self.tcx.intern_predicates(&target_preds), - reveal: param_env.reveal, - }) + self.translate_predicates(orig_def_id, param_env.caller_bounds) + .map(|target_preds| ParamEnv { + caller_bounds: self.tcx.intern_predicates(&target_preds), + reveal: param_env.reveal, + }) } /// Translate a `TraitRef`. diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index c5fccbb10af56..02973564ad94d 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -691,8 +691,8 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, info!("comparing types of {:?} / {:?}:\n {:?} / {:?}", old_def_id, new_def_id, old, new); - let to_new = TranslationContext::to_new(tcx, id_mapping, false); - let to_old = TranslationContext::to_old(tcx, id_mapping, false); + let to_new = TranslationContext::target_new(tcx, id_mapping, false); + let to_old = TranslationContext::target_old(tcx, id_mapping, false); let substs = Substs::identity_for_item(tcx, new_def_id); let old = to_new.translate_item_type(old_def_id, old); @@ -812,9 +812,9 @@ fn match_impl<'a, 'tcx>(id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, orig_def_id: DefId) -> bool { let trans = if id_mapping.in_old_crate(orig_def_id) { - TranslationContext::to_new(tcx, id_mapping, false) + TranslationContext::target_new(tcx, id_mapping, false) } else if id_mapping.in_new_crate(orig_def_id) { - TranslationContext::to_old(tcx, id_mapping, false) + TranslationContext::target_old(tcx, id_mapping, false) } else { // not reached, but apparently we don't care. return true; From de6a13345ea91c78749d7398a03c15b1f9d6b7ea Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 1 Aug 2017 18:42:26 +0200 Subject: [PATCH 197/553] Removed some old chatlog notes. --- tests/cases/traits/dump | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 tests/cases/traits/dump diff --git a/tests/cases/traits/dump b/tests/cases/traits/dump deleted file mode 100644 index c2a7b3b819d07..0000000000000 --- a/tests/cases/traits/dump +++ /dev/null @@ -1,23 +0,0 @@ - you need a fulfillment context that you put in all the bounds of the new item - (and assuming you used the translated old bounds as the ParamEnv) - (or rather, translated tcx.param_env(old_def_id)) - you should be able to call the resolve_or_error or whatever it is thing - once you do that, impls are pretty easy - - it seems I'll find most of what I need from browsing ParamEnv and friends - - rustc::traits::fulfill that's the important part - - okay, I'll report back once there's something which doesn't fall over all the time - - so for impls: for every old impl, e.g. impl Trait for X, check that X: Trait still holds, - after translating (both X and Trait) to the new - it's the same fulfillment context thing as making sure the bounds are satisfied - -given param_env: ParamEnv { caller_bounds: Slice([Binder(TraitPredicate())]), reveal: UserFacing } -predicates: [Binder(TraitPredicate())] -obligations: [] - -given param_env: ParamEnv { caller_bounds: Slice([Binder(TraitPredicate(<::A as std::marker::Sized>)), Binder(TraitPredicate())]), reveal: UserFacing } -predicates: [Binder(TraitPredicate()), Binder(TraitPredicate(<_#0t as std::marker::Sized>))] -obligations: [Obligation(predicate=Binder(TraitPredicate()),depth=0)] From d2908544ec938443c196b183206ce53a997237cf Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 1 Aug 2017 23:41:32 +0200 Subject: [PATCH 198/553] Implemented inherent item collection. --- src/semcheck/mapping.rs | 50 +++++++++++++++++++++++++++++++++++++++- src/semcheck/traverse.rs | 22 ++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 2f4e4376d5568..910a12e103bb7 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -5,12 +5,40 @@ use rustc::hir::def::{Def, Export}; use rustc::hir::def_id::{CrateNum, DefId}; -use rustc::ty::TypeParameterDef; +use rustc::ty::{AssociatedKind, TypeParameterDef}; use std::collections::{BTreeSet, HashMap, HashSet, VecDeque}; use syntax::ast::Name; +/// A description of an item found in an inherent impl. +// TODO: switch to a derived `Hash` instance +#[derive(PartialEq, Eq)] +pub struct InherentEntry { + /// The parent item's `DefId`. + parent_def_id: DefId, + /// The kind of the item. + kind: AssociatedKind, + /// The item's name. + name: Name, +} + +use std::hash::{Hash, Hasher}; +impl Hash for InherentEntry { + fn hash(&self, state: &mut H) { + self.parent_def_id.hash(state); + match self.kind { + AssociatedKind::Method => 0, + AssociatedKind::Type => 1, + AssociatedKind::Const => 2, + }.hash(state); + self.name.hash(state); + } +} + +/// A set of pairs of impl- and item `DefId` 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 @@ -36,6 +64,8 @@ pub struct IdMapping { reverse_mapping: HashMap, /// Map of type parameters' `DefId`s and their definitions. type_params: HashMap, + /// Map of items from inherent impls' descriptors to the impls they are declared in. + inherent_items: HashMap, } impl IdMapping { @@ -51,6 +81,7 @@ impl IdMapping { child_mapping: HashMap::new(), reverse_mapping: HashMap::new(), type_params: HashMap::new(), + inherent_items: HashMap::new(), } } @@ -123,6 +154,23 @@ impl IdMapping { self.type_params.get(def_id).map_or(false, |def| def.has_default) } + /// Record an item from an inherent impl. + pub fn add_inherent_item(&mut self, + parent_def_id: DefId, + kind: AssociatedKind, + name: Name, + impl_def_id: DefId, + item_def_id: DefId) { + self.inherent_items + .entry(InherentEntry { + parent_def_id: parent_def_id, + kind: kind, + name: name, + }) + .or_insert_with(Default::default) + .insert((impl_def_id, item_def_id)); + } + /// Get the new `DefId` associated with the given old one. pub fn get_new_id(&self, old: DefId) -> Option { assert!(!self.in_new_crate(old)); diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 02973564ad94d..5db506039cc19 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -420,6 +420,28 @@ fn diff_adts(changes: &mut ChangeSet, (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.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.name, + *impl_def_id, + *item_def_id); + } + } } /// Given two trait items, perform structural checks. From eb2139fd4bdda085cb401dd71ccc4950da8e24dc Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 2 Aug 2017 18:56:19 +0200 Subject: [PATCH 199/553] Basic infrastructure for inherent impl checks. --- src/semcheck/mapping.rs | 15 +++++++++++---- src/semcheck/traverse.rs | 16 ++++++++++++++++ tests/cases/inherent_impls/new.rs | 11 +++++++++++ tests/cases/inherent_impls/old.rs | 11 +++++++++++ tests/cases/inherent_impls/stdout | 1 + tests/examples.rs | 1 + 6 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 tests/cases/inherent_impls/new.rs create mode 100644 tests/cases/inherent_impls/old.rs create mode 100644 tests/cases/inherent_impls/stdout diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 910a12e103bb7..c1b031eb597af 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -13,14 +13,14 @@ use syntax::ast::Name; /// A description of an item found in an inherent impl. // TODO: switch to a derived `Hash` instance -#[derive(PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq)] pub struct InherentEntry { /// The parent item's `DefId`. - parent_def_id: DefId, + pub parent_def_id: DefId, /// The kind of the item. - kind: AssociatedKind, + pub kind: AssociatedKind, /// The item's name. - name: Name, + pub name: Name, } use std::hash::{Hash, Hasher}; @@ -269,6 +269,13 @@ impl IdMapping { .map(|m| m.iter().map(move |old| (*old, self.internal_mapping[old]))) } + /// Iterate over all items in inherent impls. + pub fn inherent_impls<'a>(&'a self) + -> impl Iterator + { + self.inherent_items.iter() + } + /// Check whether a `DefId` belongs to an item in the old crate. pub fn in_old_crate(&self, did: DefId) -> bool { self.old_crate == did.krate diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 5db506039cc19..74cf2b62fadb2 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -57,6 +57,7 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI } // fourth pass still + diff_inherent_impls(&mut changes, &id_mapping, tcx); diff_trait_impls(&mut changes, &id_mapping, tcx); changes @@ -651,6 +652,21 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } } +/// Compare the inherent implementations of items. +fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>) { + for (item, impls) in id_mapping.inherent_impls() { + if id_mapping.in_old_crate(item.parent_def_id) { + + } else if id_mapping.in_new_crate(item.parent_def_id) { + + } else { + unreachable!(); + } + } +} + /// Compare the implementations of traits. fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, diff --git a/tests/cases/inherent_impls/new.rs b/tests/cases/inherent_impls/new.rs new file mode 100644 index 0000000000000..effebd23d5d3f --- /dev/null +++ b/tests/cases/inherent_impls/new.rs @@ -0,0 +1,11 @@ +pub struct Abc { } + +impl Abc { + const a: u8 = 3; + + pub fn abc(&self) -> u8 { + 0 + } + + fn def(&self) { } +} diff --git a/tests/cases/inherent_impls/old.rs b/tests/cases/inherent_impls/old.rs new file mode 100644 index 0000000000000..effebd23d5d3f --- /dev/null +++ b/tests/cases/inherent_impls/old.rs @@ -0,0 +1,11 @@ +pub struct Abc { } + +impl Abc { + const a: u8 = 3; + + pub fn abc(&self) -> u8 { + 0 + } + + fn def(&self) { } +} diff --git a/tests/cases/inherent_impls/stdout b/tests/cases/inherent_impls/stdout new file mode 100644 index 0000000000000..f8c2af4c949b7 --- /dev/null +++ b/tests/cases/inherent_impls/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/tests/examples.rs b/tests/examples.rs index a98f78bdce723..767936c50e93a 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -103,6 +103,7 @@ test!(bounds, "tests/cases/bounds"); test!(enums, "tests/cases/enums"); test!(func, "tests/cases/func"); test!(infer, "tests/cases/infer"); +test!(inherent_impls, "tests/cases/inherent_impls"); test!(kind_change, "tests/cases/kind_change"); test!(macros, "tests/cases/macros"); test!(mix, "tests/cases/mix"); From e08b5bea54b078ab5f289183a7e6e97f8db14c77 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 2 Aug 2017 20:45:06 +0200 Subject: [PATCH 200/553] Implemented the machinery to recognize method removal or addition. --- src/semcheck/changes.rs | 14 ++++++- src/semcheck/mapping.rs | 8 ++++ src/semcheck/translate.rs | 12 +++++- src/semcheck/traverse.rs | 83 +++++++++++++++++++++++++++++++-------- 4 files changed, 98 insertions(+), 19 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index cd72f2909d5e8..a468c4a9f1ab6 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -166,7 +166,7 @@ impl Ord for PathChange { } /// The types of changes we identify between items present in both crate versions. -#[derive(Debug)] +#[derive(Clone, Debug)] pub enum ChangeType<'tcx> { /// An item has been made public. ItemMadePublic, @@ -212,6 +212,10 @@ pub enum ChangeType<'tcx> { TraitImplTightened, /// A trait impl has been generalized or newly added for some types. 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 is any change we don't yet explicitly handle. Unknown, } @@ -241,11 +245,13 @@ impl<'tcx> ChangeType<'tcx> { TraitUnsafetyChanged { .. } | BoundsTightened { .. } | TraitImplTightened | + AssociatedItemRemoved | Unknown => Breaking, MethodSelfChanged { now_self: true } | TraitItemAdded { defaulted: true } | BoundsLoosened { .. } | TraitImplLoosened | + AssociatedItemAdded | ItemMadePublic => TechnicallyBreaking, TypeParameterAdded { defaulted: true } | FnConstChanged { now_const: true } => NonBreaking, @@ -306,6 +312,8 @@ impl<'a> fmt::Display for ChangeType<'a> { BoundsLoosened { ref pred } => 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) @@ -384,7 +392,9 @@ impl<'tcx> Change<'tcx> { BoundsTightened { .. } | BoundsLoosened { .. } | TraitImplTightened | - TraitImplLoosened => (), + TraitImplLoosened | + AssociatedItemAdded | + AssociatedItemRemoved => (), } } diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index c1b031eb597af..6b33fd068bfc7 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -171,6 +171,14 @@ impl IdMapping { .insert((impl_def_id, item_def_id)); } + /// Get the impl data for an inherent item. + pub fn get_inherent_impls(&self, inherent_entry: &InherentEntry) + -> Option<&InherentImplSet> + { + self.inherent_items + .get(inherent_entry) + } + /// Get the new `DefId` associated with the given old one. pub fn get_new_id(&self, old: DefId) -> Option { assert!(!self.in_new_crate(old)); diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 8682d6d9c8103..f9af111f9ebf7 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -3,7 +3,7 @@ use rustc::ty::{ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt}; use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder}; use rustc::ty::subst::Substs; -use semcheck::mapping::IdMapping; +use semcheck::mapping::{IdMapping, InherentEntry}; use std::collections::HashMap; @@ -460,6 +460,16 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { substs: self.translate(&index_map, &orig_trait_ref.substs), } } + + /// Translate an `InherentEntry`. + pub fn translate_inherent_entry(&self, orig_entry: &InherentEntry) -> Option { + (self.translate_orig)(self.id_mapping, orig_entry.parent_def_id) + .map(|parent_def_id| InherentEntry { + parent_def_id: parent_def_id, + kind: orig_entry.kind, + name: orig_entry.name, + }) + } } /// A simple closure folder for regions and types. diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 74cf2b62fadb2..a46f7320cffa5 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -20,7 +20,7 @@ use rustc::ty::subst::{Subst, Substs}; use semcheck::changes::ChangeType::*; use semcheck::changes::ChangeSet; -use semcheck::mapping::{IdMapping, NameMapping}; +use semcheck::mapping::{IdMapping, InherentEntry, InherentImplSet, NameMapping}; use semcheck::mismatch::Mismatch; use semcheck::translate::{BottomUpRegionFolder, TranslationContext}; @@ -656,13 +656,51 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>) { - for (item, impls) in id_mapping.inherent_impls() { - if id_mapping.in_old_crate(item.parent_def_id) { - - } else if id_mapping.in_new_crate(item.parent_def_id) { + 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() { + let (trans, err_type) = if id_mapping.in_old_crate(orig_item.parent_def_id) { + (&to_new, AssociatedItemRemoved) + } else if id_mapping.in_new_crate(orig_item.parent_def_id) { + (&to_old, AssociatedItemAdded) } else { - unreachable!(); + unreachable!() + }; + + for &(orig_impl_def_id, orig_item_def_id) in orig_impls { + let target_impls = if let Some(impls) = trans + .translate_inherent_entry(orig_item) + .and_then(|item| id_mapping.get_inherent_impls(&item)) + { + impls + } else { + continue; + }; + + let match_found = target_impls + .iter() + .any(|&(target_impl_def_id, target_item_def_id)| { + match_inherent_impl(id_mapping, + tcx, + trans, + orig_impl_def_id, + orig_item_def_id, + target_impl_def_id, + target_item_def_id) + }); + + if !match_found { + 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, + true); + changes.add_change(err_type.clone(), orig_item_def_id, None); + } } } } @@ -679,7 +717,7 @@ fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, continue; } - if !match_impl(id_mapping, tcx, *old_impl_def_id) { + if !match_trait_impl(id_mapping, tcx, *old_impl_def_id) { let impl_span = tcx.def_span(*old_impl_def_id); changes.new_change(*old_impl_def_id, @@ -698,7 +736,7 @@ fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, continue; } - if !match_impl(id_mapping, tcx, *new_impl_def_id) { + if !match_trait_impl(id_mapping, tcx, *new_impl_def_id) { let impl_span = tcx.def_span(*new_impl_def_id); changes.new_change(*new_impl_def_id, @@ -845,10 +883,11 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, }); } -/// Compare two implementations and indicate whether the new one is compatible with the old one. -fn match_impl<'a, 'tcx>(id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - orig_def_id: DefId) -> bool { +/// Compare two implementations and indicate whether the target one is compatible with the +/// original one. +fn match_trait_impl<'a, 'tcx>(id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + orig_def_id: DefId) -> bool { let trans = if id_mapping.in_old_crate(orig_def_id) { TranslationContext::target_new(tcx, id_mapping, false) } else if id_mapping.in_new_crate(orig_def_id) { @@ -871,18 +910,30 @@ fn match_impl<'a, 'tcx>(id_mapping: &IdMapping, debug!("env: {:?}", old_param_env); - let old = tcx + let orig = tcx .impl_trait_ref(orig_def_id) .unwrap(); - debug!("trait ref: {:?}", old); - debug!("translated ref: {:?}", trans.translate_trait_ref(orig_def_id, &old)); + 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, &old)); + bound_cx.register_trait_ref(trans.translate_trait_ref(orig_def_id, &orig)); bound_cx.get_errors().is_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<'a, 'tcx>(id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + trans: &TranslationContext<'a, 'tcx, 'tcx>, + orig_impl_def_id: DefId, + orig_item_def_id: DefId, + target_impl_def_id: DefId, + target_item_def_id: DefId) -> bool { + true +} + /// The context in which bounds analysis happens. pub struct BoundContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { /// The inference context to use. From 5496070b2d94c52d7ee1109f5042cbc4932d1351 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 2 Aug 2017 22:16:24 +0200 Subject: [PATCH 201/553] Some work to refactor `cmp_types` into smaller pieces. By transforming it into a context structure, we can reuse it in the inherent impl checking stage properly. --- src/semcheck/traverse.rs | 75 +++++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 9 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index a46f7320cffa5..3cdeaf343ed56 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -798,16 +798,10 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let new = new.subst(infcx.tcx, new_substs); // let old = old.subst(infcx.tcx, substs); - let old_param_env = to_new.translate_param_env(old_def_id, tcx.param_env(old_def_id)); - let new_param_env = tcx.param_env(new_def_id).subst(infcx.tcx, new_substs); - let new_param_env_trans = - to_old.translate_param_env(new_def_id, tcx.param_env(new_def_id)); - - let cause = ObligationCause::dummy(); let error = infcx - .at(&cause, new_param_env) + .at(&ObligationCause::dummy(), new_param_env) .eq(old, new) .map(|InferOk { obligations: o, .. }| { assert_eq!(o, vec![]); }); @@ -843,7 +837,13 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, changes.add_change(TypeChanged { error: err }, old_def_id, None); } - let old_param_env = if let Some(env) = old_param_env { env } else { return; }; + let old_param_env = if let Some(env) = + to_new.translate_param_env(old_def_id, tcx.param_env(old_def_id)) + { + env + } else { + return; + }; let mut bound_cx = BoundContext::new(&infcx, old_param_env); bound_cx.register(new_def_id, new_substs); @@ -859,7 +859,9 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, changes.add_change(err_type, old_def_id, Some(tcx.def_span(old_def_id))); } } else { - let new_param_env_trans = if let Some(env) = new_param_env_trans { + let new_param_env_trans = if let Some(env) = + to_old.translate_param_env(new_def_id, tcx.param_env(new_def_id)) + { env } else { return; @@ -1000,3 +1002,58 @@ impl<'a, 'gcx, 'tcx> BoundContext<'a, 'gcx, 'tcx> { } } } + +pub struct TypeComparisonContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + id_mapping: &'a IdMapping, + forward_trans: TranslationContext<'a, 'gcx, 'tcx>, + backward_trans: TranslationContext<'a, 'gcx, 'tcx>, +} + +impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { + pub fn target_new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping) -> Self { + TypeComparisonContext { + infcx: infcx, + id_mapping: id_mapping, + forward_trans: TranslationContext::target_new(infcx.tcx, id_mapping, false), + backward_trans: TranslationContext::target_old(infcx.tcx, id_mapping, false), + } + } + + pub fn target_old(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping) -> Self { + TypeComparisonContext { + infcx: infcx, + id_mapping: id_mapping, + forward_trans: TranslationContext::target_old(infcx.tcx, id_mapping, false), + backward_trans: TranslationContext::target_new(infcx.tcx, id_mapping, false), + } + } + + fn compute_target_infer_substs(&self, target_def_id: DefId) -> &Substs<'tcx> { + use syntax_pos::DUMMY_SP; + + let has_self = self.infcx.tcx.generics_of(target_def_id).has_self; + + Substs::for_item(self.infcx.tcx, target_def_id, |def, _| { + self.infcx.region_var_for_def(DUMMY_SP, def) + }, |def, substs| { + if def.index == 0 && has_self { // `Self` is special + self.infcx.tcx.mk_param_from_def(def) + } else { + self.infcx.type_var_for_def(DUMMY_SP, def, substs) + } + }) + } + + fn compute_target_default_substs(&self, target_def_id: DefId) -> &Substs<'tcx> { + use rustc::ty::ReEarlyBound; + + Substs::for_item(self.infcx.tcx, target_def_id, |def, _| { + self.infcx.tcx.mk_region(ReEarlyBound(def.to_early_bound_region_data())) + }, |def, _| if self.id_mapping.is_non_mapped_defaulted_type_param(&def.def_id) { + self.infcx.tcx.type_of(def.def_id) + } else { + self.infcx.tcx.mk_param_from_def(def) + }) + } +} From 8b16c585fd9d8254f99430a8dfc014f192b762af Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 3 Aug 2017 12:43:10 +0200 Subject: [PATCH 202/553] Moved type error folding to a dedicated struct. --- src/semcheck/translate.rs | 44 ++++++++++++++---------- src/semcheck/traverse.rs | 70 ++++++++++++++++++++++++++------------- 2 files changed, 74 insertions(+), 40 deletions(-) diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index f9af111f9ebf7..1e9fe6ba09546 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -1,6 +1,7 @@ use rustc::hir::def_id::DefId; use rustc::ty::{ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt}; use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder}; +use rustc::infer::InferCtxt; use rustc::ty::subst::Substs; use semcheck::mapping::{IdMapping, InherentEntry}; @@ -25,7 +26,6 @@ pub struct TranslationContext<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { /// Construct a translation context translating to the new crate's `DefId`s. - // TODO: check whether the function pointers force us to use dynamic dispatch pub fn target_new(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping, translate_params: bool) -> TranslationContext<'a, 'gcx, 'tcx> @@ -47,7 +47,6 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { } /// Construct a translation context translating to the old crate's `DefId`s. - // TODO: check whether the function pointers force us to use dynamic dispatch pub fn target_old(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping, translate_params: bool) -> TranslationContext<'a, 'gcx, 'tcx> { @@ -472,29 +471,40 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { } } -/// A simple closure folder for regions and types. -pub struct BottomUpRegionFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a, F, G> - where F: FnMut(Ty<'tcx>) -> Ty<'tcx>, - G: FnMut(Region<'tcx>) -> Region<'tcx>, -{ - pub tcx: TyCtxt<'a, 'gcx, 'tcx>, - pub fldop_t: F, - pub fldop_r: G, +pub struct InferenceCleanupFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, } -impl<'a, 'gcx, 'tcx, F, G> TypeFolder<'gcx, 'tcx> for BottomUpRegionFolder<'a, 'gcx, 'tcx, F, G> - where F: FnMut(Ty<'tcx>) -> Ty<'tcx>, - G: FnMut(Region<'tcx>) -> Region<'tcx>, -{ - fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } +impl<'a, 'gcx, 'tcx> InferenceCleanupFolder<'a, 'gcx, 'tcx> { + pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self { + InferenceCleanupFolder { + infcx: infcx, + } + } +} + +impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceCleanupFolder<'a, 'gcx, 'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + use rustc::ty::TypeVariants::{TyError, TyInfer, TyRef}; + let t1 = ty.super_fold_with(self); - (self.fldop_t)(t1) + match t1.sty { + TyRef(region, tm) if region.needs_infer() => { + self.infcx.tcx.mk_ref(self.infcx.tcx.types.re_erased, tm) + }, + TyInfer(_) => self.infcx.tcx.mk_ty(TyError), + _ => t1, + } } fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> { let r1 = r.super_fold_with(self); - (self.fldop_r)(r1) + if r1.needs_infer() { + self.infcx.tcx.types.re_erased + } else { + r1 + } } } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 3cdeaf343ed56..000f57ddadddb 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -13,16 +13,17 @@ use rustc::hir::def::{CtorKind, Def}; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; use rustc::traits::{FulfillmentContext, FulfillmentError, Obligation, ObligationCause}; -use rustc::ty::{AssociatedItem, ParamEnv, TraitRef, Ty, TyCtxt}; -use rustc::ty::Visibility::Public; +use rustc::ty::{AssociatedItem, ParamEnv, Region, TraitRef, Ty, TyCtxt}; +use rustc::ty::error::TypeError; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::{Subst, Substs}; +use rustc::ty::Visibility::Public; use semcheck::changes::ChangeType::*; use semcheck::changes::ChangeSet; use semcheck::mapping::{IdMapping, InherentEntry, InherentImplSet, NameMapping}; use semcheck::mismatch::Mismatch; -use semcheck::translate::{BottomUpRegionFolder, TranslationContext}; +use semcheck::translate::{InferenceCleanupFolder, TranslationContext}; use std::collections::{BTreeMap, HashSet, VecDeque}; @@ -570,7 +571,7 @@ fn diff_generics(changes: &mut ChangeSet, id_mapping.add_type_param(*old_type); id_mapping.add_non_mapped(old_type.def_id); }, - (None, Some(new_type)) => { // FIXME: is_fn could be used in a more elegant fashion + (None, Some(new_type)) => { found.push(TypeParameterAdded { defaulted: new_type.has_default || is_fn }); id_mapping.add_type_param(*new_type); id_mapping.add_non_mapped(new_type.def_id); @@ -805,25 +806,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, .eq(old, new) .map(|InferOk { obligations: o, .. }| { assert_eq!(o, vec![]); }); - let mut folder = BottomUpRegionFolder { - tcx: infcx.tcx, - fldop_t: |ty| { - match ty.sty { - TyRef(region, tm) if region.needs_infer() => { - infcx.tcx.mk_ref(tcx.types.re_erased, tm) - }, - TyInfer(_) => tcx.mk_ty(TyError), - _ => ty, - } - }, - fldop_r: |reg| { - if reg.needs_infer() { - tcx.types.re_erased - } else { - reg - } - }, - }; + let mut folder = InferenceCleanupFolder::new(&infcx); if let Err(err) = error { let region_maps = RegionMaps::new(); @@ -1006,6 +989,7 @@ impl<'a, 'gcx, 'tcx> BoundContext<'a, 'gcx, 'tcx> { pub struct TypeComparisonContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping, + folder: InferenceCleanupFolder<'a, 'gcx, 'tcx>, forward_trans: TranslationContext<'a, 'gcx, 'tcx>, backward_trans: TranslationContext<'a, 'gcx, 'tcx>, } @@ -1015,6 +999,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { TypeComparisonContext { infcx: infcx, id_mapping: id_mapping, + folder: InferenceCleanupFolder::new(&infcx), forward_trans: TranslationContext::target_new(infcx.tcx, id_mapping, false), backward_trans: TranslationContext::target_old(infcx.tcx, id_mapping, false), } @@ -1024,6 +1009,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { TypeComparisonContext { infcx: infcx, id_mapping: id_mapping, + folder: InferenceCleanupFolder::new(&infcx), forward_trans: TranslationContext::target_old(infcx.tcx, id_mapping, false), backward_trans: TranslationContext::target_new(infcx.tcx, id_mapping, false), } @@ -1056,4 +1042,42 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { self.infcx.tcx.mk_param_from_def(def) }) } + + fn check_type_error(&mut self, + target_def_id: DefId, + target_param_env: ParamEnv<'tcx>, + orig: Ty<'tcx>, + target: Ty<'tcx>) -> Option> { + use rustc::infer::InferOk; + use rustc::middle::free_region::FreeRegionMap; + use rustc::middle::region::RegionMaps; + use rustc::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 region_maps = RegionMaps::new(); + let mut free_regions = FreeRegionMap::new(); + + free_regions.relate_free_regions_from_predicates(target_param_env.caller_bounds); + self.infcx.resolve_regions_and_report_errors(target_def_id, + ®ion_maps, + &free_regions); + + let err = + self.infcx + .resolve_type_vars_if_possible(&err) + .fold_with(&mut self.folder) + .lift_to_tcx(self.infcx.tcx) + .unwrap(); + + Some(err) + } else { + None + } + } } From db98070432e22ddce9f777d5e7e73557997aa667 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 3 Aug 2017 13:27:21 +0200 Subject: [PATCH 203/553] Implemented all main building blocks of the type checking context. --- src/semcheck/traverse.rs | 50 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 000f57ddadddb..c21f5f7b5a307 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -13,7 +13,7 @@ use rustc::hir::def::{CtorKind, Def}; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; use rustc::traits::{FulfillmentContext, FulfillmentError, Obligation, ObligationCause}; -use rustc::ty::{AssociatedItem, ParamEnv, Region, TraitRef, Ty, TyCtxt}; +use rustc::ty::{AssociatedItem, ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt}; use rustc::ty::error::TypeError; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::{Subst, Substs}; @@ -1080,4 +1080,52 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { None } } + + fn check_bounds_error(&mut self, + orig_def_id: DefId, + target_def_id: DefId, + orig_param_env: Option>, + target_param_env: Option>, + orig_substs: &Substs<'tcx>, + target_substs: &Substs<'tcx>) -> Option>> { + let orig_param_env = if let Some(env) = orig_param_env { + env + } else { + return None; + }; + + let mut bound_cx = BoundContext::new(self.infcx, orig_param_env); + bound_cx.register(target_def_id, target_substs); + + if let Some(errors) = bound_cx.get_errors() { + return Some(errors + .iter() + .map(|err| + self.infcx + .resolve_type_vars_if_possible(&err.obligation.predicate) + .fold_with(&mut self.folder)) + .collect()) + } + + let target_param_env = if let Some(env) = target_param_env { + env + } else { + return None; + }; + + let mut rev_bound_cx = BoundContext::new(self.infcx, target_param_env); + rev_bound_cx.register(orig_def_id, orig_substs); + + if let Some(errors) = rev_bound_cx.get_errors() { + return Some(errors + .iter() + .map(|err| + self.infcx + .resolve_type_vars_if_possible(&err.obligation.predicate) + .fold_with(&mut self.folder)) + .collect()) + } + + None + } } From 77854be038e5d6d6b9692832a0dda504ca290c7a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 3 Aug 2017 14:54:05 +0200 Subject: [PATCH 204/553] Refactored type comparison logic. We now have a way more flexible type comparison context we can use in other passes as well. A small regression remains, however. --- src/semcheck/translate.rs | 1 + src/semcheck/traverse.rs | 174 ++++++++++++-------------------------- 2 files changed, 53 insertions(+), 122 deletions(-) diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 1e9fe6ba09546..9454e7e83c72c 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -471,6 +471,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { } } +#[derive(Copy, Clone)] pub struct InferenceCleanupFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index c21f5f7b5a307..ae24d49480601 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -13,7 +13,7 @@ use rustc::hir::def::{CtorKind, Def}; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; use rustc::traits::{FulfillmentContext, FulfillmentError, Obligation, ObligationCause}; -use rustc::ty::{AssociatedItem, ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt}; +use rustc::ty::{AssociatedItem, ParamEnv, Predicate, TraitRef, Ty, TyCtxt}; use rustc::ty::error::TypeError; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::{Subst, Substs}; @@ -21,7 +21,7 @@ use rustc::ty::Visibility::Public; use semcheck::changes::ChangeType::*; use semcheck::changes::ChangeSet; -use semcheck::mapping::{IdMapping, InherentEntry, InherentImplSet, NameMapping}; +use semcheck::mapping::{IdMapping, NameMapping}; use semcheck::mismatch::Mismatch; use semcheck::translate::{InferenceCleanupFolder, TranslationContext}; @@ -759,110 +759,54 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, new_def_id: DefId, old: Ty<'tcx>, new: Ty<'tcx>) { - use rustc::infer::InferOk; - use rustc::middle::free_region::FreeRegionMap; - use rustc::middle::region::RegionMaps; - use rustc::ty::{Lift, ReEarlyBound}; - use rustc::ty::TypeVariants::*; - use syntax_pos::DUMMY_SP; - info!("comparing types of {:?} / {:?}:\n {:?} / {:?}", old_def_id, new_def_id, old, new); - let to_new = TranslationContext::target_new(tcx, id_mapping, false); - let to_old = TranslationContext::target_old(tcx, id_mapping, false); + tcx.infer_ctxt().enter(|infcx| { + let compcx = TypeComparisonContext::target_new(&infcx, id_mapping); - let substs = Substs::identity_for_item(tcx, new_def_id); - let old = to_new.translate_item_type(old_def_id, old); + let old_substs = Substs::identity_for_item(infcx.tcx, new_def_id); + let old = compcx.forward_trans.translate_item_type(old_def_id, old); + // let old = old.subst(infcx.tcx, old_substs); - tcx.infer_ctxt().enter(|infcx| { let new_substs = if new.is_fn() { - let has_self = tcx.generics_of(new_def_id).has_self; - Substs::for_item(infcx.tcx, new_def_id, |def, _| { - infcx.region_var_for_def(DUMMY_SP, def) - }, |def, substs| { - if def.index == 0 && has_self { // `Self` is special - tcx.mk_param_from_def(def) - } else { - infcx.type_var_for_def(DUMMY_SP, def, substs) - } - }) + compcx.compute_target_infer_substs(new_def_id) } else { - Substs::for_item(tcx, new_def_id, |def, _| { - tcx.mk_region(ReEarlyBound(def.to_early_bound_region_data())) - }, |def, _| if id_mapping.is_non_mapped_defaulted_type_param(&def.def_id) { - tcx.type_of(def.def_id) - } else { - tcx.mk_param_from_def(def) - }) + compcx.compute_target_default_substs(new_def_id) }; - let new = new.subst(infcx.tcx, new_substs); - // let old = old.subst(infcx.tcx, substs); - - let new_param_env = tcx.param_env(new_def_id).subst(infcx.tcx, new_substs); - - let error = infcx - .at(&ObligationCause::dummy(), new_param_env) - .eq(old, new) - .map(|InferOk { obligations: o, .. }| { assert_eq!(o, vec![]); }); - - let mut folder = InferenceCleanupFolder::new(&infcx); - - if let Err(err) = error { - let region_maps = RegionMaps::new(); - let mut free_regions = FreeRegionMap::new(); - free_regions.relate_free_regions_from_predicates(new_param_env.caller_bounds); - infcx.resolve_regions_and_report_errors(new_def_id, ®ion_maps, &free_regions); - let err = infcx.resolve_type_vars_if_possible(&err); - let err = err.fold_with(&mut folder).lift_to_tcx(tcx).unwrap(); + let new_param_env = infcx.tcx.param_env(new_def_id).subst(infcx.tcx, new_substs); + if let Some(err) = compcx.check_type_error(tcx, new_def_id, new_param_env, old, new) { changes.add_change(TypeChanged { error: err }, old_def_id, None); } - let old_param_env = if let Some(env) = - to_new.translate_param_env(old_def_id, tcx.param_env(old_def_id)) - { - env - } else { - return; - }; - let mut bound_cx = BoundContext::new(&infcx, old_param_env); - bound_cx.register(new_def_id, new_substs); - - if let Some(errors) = bound_cx.get_errors() { - for err in &errors { - let pred = infcx.resolve_type_vars_if_possible(&err.obligation.predicate); - let pred = pred.fold_with(&mut folder); + let old_param_env = compcx + .forward_trans + .translate_param_env(old_def_id, tcx.param_env(old_def_id)); + let new_param_env = compcx + .backward_trans + .translate_param_env(new_def_id, tcx.param_env(new_def_id)); + if let Some(errors) = + compcx.check_bounds_error(tcx, old_param_env, new_def_id, new_substs) + { + for err in errors { let err_type = BoundsTightened { - pred: pred.lift_to_tcx(tcx).unwrap(), + pred: err, }; changes.add_change(err_type, old_def_id, Some(tcx.def_span(old_def_id))); } - } else { - let new_param_env_trans = if let Some(env) = - to_old.translate_param_env(new_def_id, tcx.param_env(new_def_id)) - { - env - } else { - return; - }; - let mut rev_bound_cx = BoundContext::new(&infcx, new_param_env_trans); - rev_bound_cx.register(old_def_id, substs); - - if let Some(errors) = rev_bound_cx.get_errors() { - for err in &errors { - let pred = infcx.resolve_type_vars_if_possible(&err.obligation.predicate); - let pred = pred.fold_with(&mut folder); - - let err_type = BoundsLoosened { - pred: pred.lift_to_tcx(tcx).unwrap(), - }; + } else if let Some(errors) = + compcx.check_bounds_error(tcx, new_param_env, old_def_id, old_substs) + { + for err in errors { + let err_type = BoundsLoosened { + pred: err, + }; - changes.add_change(err_type, old_def_id, Some(tcx.def_span(old_def_id))); - } + changes.add_change(err_type, old_def_id, Some(tcx.def_span(old_def_id))); } } }); @@ -990,8 +934,8 @@ pub struct TypeComparisonContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping, folder: InferenceCleanupFolder<'a, 'gcx, 'tcx>, - forward_trans: TranslationContext<'a, 'gcx, 'tcx>, - backward_trans: TranslationContext<'a, 'gcx, 'tcx>, + pub forward_trans: TranslationContext<'a, 'gcx, 'tcx>, + pub backward_trans: TranslationContext<'a, 'gcx, 'tcx>, } impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { @@ -1043,11 +987,12 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { }) } - fn check_type_error(&mut self, - target_def_id: DefId, - target_param_env: ParamEnv<'tcx>, - orig: Ty<'tcx>, - target: Ty<'tcx>) -> Option> { + fn check_type_error<'b, 'tcx2>(&self, + lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, + target_def_id: DefId, + target_param_env: ParamEnv<'tcx>, + orig: Ty<'tcx>, + target: Ty<'tcx>) -> Option> { use rustc::infer::InferOk; use rustc::middle::free_region::FreeRegionMap; use rustc::middle::region::RegionMaps; @@ -1071,8 +1016,8 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { let err = self.infcx .resolve_type_vars_if_possible(&err) - .fold_with(&mut self.folder) - .lift_to_tcx(self.infcx.tcx) + .fold_with(&mut self.folder.clone()) + .lift_to_tcx(lift_tcx) .unwrap(); Some(err) @@ -1081,13 +1026,15 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { } } - fn check_bounds_error(&mut self, - orig_def_id: DefId, - target_def_id: DefId, - orig_param_env: Option>, - target_param_env: Option>, - orig_substs: &Substs<'tcx>, - target_substs: &Substs<'tcx>) -> Option>> { + fn check_bounds_error<'b, 'tcx2>(&self, + lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, + orig_param_env: Option>, + target_def_id: DefId, + target_substs: &Substs<'tcx>) + -> Option>> + { + use rustc::ty::Lift; + let orig_param_env = if let Some(env) = orig_param_env { env } else { @@ -1103,26 +1050,9 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { .map(|err| self.infcx .resolve_type_vars_if_possible(&err.obligation.predicate) - .fold_with(&mut self.folder)) - .collect()) - } - - let target_param_env = if let Some(env) = target_param_env { - env - } else { - return None; - }; - - let mut rev_bound_cx = BoundContext::new(self.infcx, target_param_env); - rev_bound_cx.register(orig_def_id, orig_substs); - - if let Some(errors) = rev_bound_cx.get_errors() { - return Some(errors - .iter() - .map(|err| - self.infcx - .resolve_type_vars_if_possible(&err.obligation.predicate) - .fold_with(&mut self.folder)) + .fold_with(&mut self.folder.clone()) + .lift_to_tcx(lift_tcx) + .unwrap()) .collect()) } From 02fd9edc48ce0a801aca513d685a98c0bbeac01a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 4 Aug 2017 00:54:12 +0200 Subject: [PATCH 205/553] Fixed a regression. --- src/semcheck/traverse.rs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index ae24d49480601..0b0e26a6a1436 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -788,6 +788,12 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, .backward_trans .translate_param_env(new_def_id, tcx.param_env(new_def_id)); + let old_param_env = if let Some(env) = old_param_env { + env + } else { + return; + }; + if let Some(errors) = compcx.check_bounds_error(tcx, old_param_env, new_def_id, new_substs) { @@ -798,7 +804,15 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, changes.add_change(err_type, old_def_id, Some(tcx.def_span(old_def_id))); } - } else if let Some(errors) = + } + + let new_param_env = if let Some(env) = new_param_env { + env + } else { + return; + }; + + if let Some(errors) = compcx.check_bounds_error(tcx, new_param_env, old_def_id, old_substs) { for err in errors { @@ -1028,19 +1042,13 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { fn check_bounds_error<'b, 'tcx2>(&self, lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, - orig_param_env: Option>, + orig_param_env: ParamEnv<'tcx>, target_def_id: DefId, target_substs: &Substs<'tcx>) -> Option>> { use rustc::ty::Lift; - let orig_param_env = if let Some(env) = orig_param_env { - env - } else { - return None; - }; - let mut bound_cx = BoundContext::new(self.infcx, orig_param_env); bound_cx.register(target_def_id, target_substs); From d07e05ba853527f453183a16f49aa83a38cf5ecb Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 4 Aug 2017 01:36:13 +0200 Subject: [PATCH 206/553] Some cleanup. --- src/semcheck/mapping.rs | 16 +--------------- src/semcheck/translate.rs | 2 +- src/semcheck/traverse.rs | 4 ++-- 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 6b33fd068bfc7..ff5f4bda7d315 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -12,8 +12,7 @@ use std::collections::{BTreeSet, HashMap, HashSet, VecDeque}; use syntax::ast::Name; /// A description of an item found in an inherent impl. -// TODO: switch to a derived `Hash` instance -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Hash)] pub struct InherentEntry { /// The parent item's `DefId`. pub parent_def_id: DefId, @@ -23,19 +22,6 @@ pub struct InherentEntry { pub name: Name, } -use std::hash::{Hash, Hasher}; -impl Hash for InherentEntry { - fn hash(&self, state: &mut H) { - self.parent_def_id.hash(state); - match self.kind { - AssociatedKind::Method => 0, - AssociatedKind::Type => 1, - AssociatedKind::Const => 2, - }.hash(state); - self.name.hash(state); - } -} - /// A set of pairs of impl- and item `DefId` for inherent associated items. pub type InherentImplSet = BTreeSet<(DefId, DefId)>; diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 9454e7e83c72c..1f5c92f58eb42 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -471,7 +471,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { } } -#[derive(Copy, Clone)] +#[derive(Clone)] pub struct InferenceCleanupFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 0b0e26a6a1436..f50091595c3ce 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -957,7 +957,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { TypeComparisonContext { infcx: infcx, id_mapping: id_mapping, - folder: InferenceCleanupFolder::new(&infcx), + folder: InferenceCleanupFolder::new(infcx), forward_trans: TranslationContext::target_new(infcx.tcx, id_mapping, false), backward_trans: TranslationContext::target_old(infcx.tcx, id_mapping, false), } @@ -967,7 +967,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { TypeComparisonContext { infcx: infcx, id_mapping: id_mapping, - folder: InferenceCleanupFolder::new(&infcx), + folder: InferenceCleanupFolder::new(infcx), forward_trans: TranslationContext::target_old(infcx.tcx, id_mapping, false), backward_trans: TranslationContext::target_new(infcx.tcx, id_mapping, false), } From 225b413738dac0148b85a7583d4e7db45b8ee0ca Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 4 Aug 2017 11:12:44 +0200 Subject: [PATCH 207/553] Removed some cruft. --- src/semcheck/mapping.rs | 26 --------------- src/semcheck/translate.rs | 53 ++++--------------------------- src/semcheck/traverse.rs | 14 ++++---- tests/cases/inherent_impls/new.rs | 4 ++- tests/cases/inherent_impls/old.rs | 4 ++- 5 files changed, 20 insertions(+), 81 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index ff5f4bda7d315..a493bf774a312 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -195,32 +195,6 @@ impl IdMapping { } } - /// Get the new `DefId` associated with the given old one, respecting possibly removed - /// traits that are a parent of the given `DefId`. - pub fn get_new_trait_item_id(&self, old: DefId, trait_id: DefId) -> Option { - assert!(!self.in_new_crate(trait_id)); - - // TODO: this body is now nonsensical. reevaluate. - if !self.non_mapped_items.contains(&trait_id) { - self.get_new_id(old) - } else { - Some(old) - } - } - - /// Get the old `DefId` associated with the given new one, respecting possibly added - /// traits that are a parent of the given `DefId`. - pub fn get_old_trait_item_id(&self, new: DefId, trait_id: DefId) -> Option { - assert!(!self.in_old_crate(trait_id)); - - // TODO: this body is now nonsensical. reevaluate. - if !self.non_mapped_items.contains(&trait_id) { - self.get_old_id(new) - } else { - Some(new) - } - } - /// Return the `DefId` of the trait a given item belongs to. pub fn get_trait_def(&self, item_def_id: &DefId) -> Option { self.trait_item_mapping.get(item_def_id).map(|t| t.2) diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 1f5c92f58eb42..39e3585a9da47 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -20,8 +20,6 @@ pub struct TranslationContext<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> { needs_translation: fn(&IdMapping, DefId) -> bool, /// Elementary operation to translate a `DefId`. translate_orig: fn(&IdMapping, DefId) -> Option, - /// Elementary operation to translate a `DefId` of a trait item. - translate_orig_trait: fn(&IdMapping, DefId, DefId) -> Option, } impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { @@ -40,9 +38,6 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { translate_orig: |id_mapping, orig_def_id| { id_mapping.get_new_id(orig_def_id) }, - translate_orig_trait: |id_mapping, orig_def_id, trait_def_id| { - id_mapping.get_new_trait_item_id(orig_def_id, trait_def_id) - }, } } @@ -60,9 +55,6 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { translate_orig: |id_mapping, orig_def_id| { id_mapping.get_old_id(orig_def_id) }, - translate_orig_trait: |id_mapping, orig_def_id, trait_def_id| { - id_mapping.get_old_trait_item_id(orig_def_id, trait_def_id) - }, } } @@ -99,47 +91,18 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { }) } - /// Translate a `DefId` of a toplevel item and it's substs. + /// Translate a `DefId` of any item and it's substs. fn translate_orig_substs(&self, index_map: &HashMap, orig_def_id: DefId, orig_substs: &Substs<'tcx>) -> Option<(DefId, &'tcx Substs<'tcx>)> { - self.translate_orig_opt_trait_substs(index_map, orig_def_id, None, orig_substs) - } - - /// Translate a `DefId` of a trait item and it's substs. - fn translate_orig_trait_substs(&self, - index_map: &HashMap, - orig_def_id: DefId, - orig_trait_def_id: DefId, - orig_substs: &Substs<'tcx>) - -> Option<(DefId, &'tcx Substs<'tcx>)> - { - self.translate_orig_opt_trait_substs(index_map, - orig_def_id, - Some(orig_trait_def_id), - orig_substs) - } - - /// Translate a `DefId` of any item and it's substs. - fn translate_orig_opt_trait_substs(&self, - index_map: &HashMap, - orig_def_id: DefId, - orig_trait_def_id: Option, - orig_substs: &Substs<'tcx>) - -> Option<(DefId, &'tcx Substs<'tcx>)> - { - debug!("translating w/ substs: did: {:?} (trait did: {:?}), substs: {:?}", - orig_def_id, orig_trait_def_id, orig_substs); + debug!("translating w/ substs: did: {:?}, substs: {:?}", + orig_def_id, orig_substs); use rustc::ty::ReEarlyBound; use std::cell::Cell; - let target_def_id = if let Some(orig_trait_def_id) = orig_trait_def_id { - (self.translate_orig_trait)(self.id_mapping, orig_def_id, orig_trait_def_id) - } else { - (self.translate_orig)(self.id_mapping, orig_def_id) - }; + 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); @@ -261,12 +224,10 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { } }, TyProjection(proj) => { - let trait_def_id = self.tcx.associated_item(proj.item_def_id).container.id(); if let Some((target_def_id, target_substs)) = - self.translate_orig_trait_substs(index_map, - proj.item_def_id, - trait_def_id, - proj.substs) { + self.translate_orig_substs(index_map, + proj.item_def_id, + proj.substs) { self.tcx.mk_projection(target_def_id, target_substs) } else { ty diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index f50091595c3ce..f69e79925c490 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -867,13 +867,13 @@ fn match_trait_impl<'a, 'tcx>(id_mapping: &IdMapping, /// Compare an item pair in two inherent implementations and indicate whether the target one is /// compatible with the original one. -fn match_inherent_impl<'a, 'tcx>(id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - trans: &TranslationContext<'a, 'tcx, 'tcx>, - orig_impl_def_id: DefId, - orig_item_def_id: DefId, - target_impl_def_id: DefId, - target_item_def_id: DefId) -> bool { +fn match_inherent_impl<'a, 'tcx>(_id_mapping: &IdMapping, + _tcx: TyCtxt<'a, 'tcx, 'tcx>, + _trans: &TranslationContext<'a, 'tcx, 'tcx>, + _orig_impl_def_id: DefId, + _orig_item_def_id: DefId, + _target_impl_def_id: DefId, + _target_item_def_id: DefId) -> bool { true } diff --git a/tests/cases/inherent_impls/new.rs b/tests/cases/inherent_impls/new.rs index effebd23d5d3f..fbcd6812e3bf1 100644 --- a/tests/cases/inherent_impls/new.rs +++ b/tests/cases/inherent_impls/new.rs @@ -1,7 +1,9 @@ +#[allow(dead_code)] pub struct Abc { } +#[allow(dead_code)] impl Abc { - const a: u8 = 3; + const A: u8 = 3; pub fn abc(&self) -> u8 { 0 diff --git a/tests/cases/inherent_impls/old.rs b/tests/cases/inherent_impls/old.rs index effebd23d5d3f..fbcd6812e3bf1 100644 --- a/tests/cases/inherent_impls/old.rs +++ b/tests/cases/inherent_impls/old.rs @@ -1,7 +1,9 @@ +#[allow(dead_code)] pub struct Abc { } +#[allow(dead_code)] impl Abc { - const a: u8 = 3; + const A: u8 = 3; pub fn abc(&self) -> u8 { 0 From 6181a1d1ca1b919e62d8564c8b330f8bf5246e75 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 4 Aug 2017 11:58:25 +0200 Subject: [PATCH 208/553] Added docs and separated components a bit. --- src/semcheck/mod.rs | 1 + src/semcheck/traverse.rs | 200 +---------------------------------- src/semcheck/typeck.rs | 219 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 223 insertions(+), 197 deletions(-) create mode 100644 src/semcheck/typeck.rs diff --git a/src/semcheck/mod.rs b/src/semcheck/mod.rs index 1bf94c2125786..15653b884f3f5 100644 --- a/src/semcheck/mod.rs +++ b/src/semcheck/mod.rs @@ -7,5 +7,6 @@ mod mapping; mod mismatch; mod translate; mod traverse; +mod typeck; pub use self::traverse::run_analysis; diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index f69e79925c490..946595d085466 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -11,11 +11,7 @@ use rustc::hir::def::{CtorKind, Def}; use rustc::hir::def_id::DefId; -use rustc::infer::InferCtxt; -use rustc::traits::{FulfillmentContext, FulfillmentError, Obligation, ObligationCause}; -use rustc::ty::{AssociatedItem, ParamEnv, Predicate, TraitRef, Ty, TyCtxt}; -use rustc::ty::error::TypeError; -use rustc::ty::fold::TypeFoldable; +use rustc::ty::{AssociatedItem, Ty, TyCtxt}; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::Visibility::Public; @@ -23,7 +19,8 @@ use semcheck::changes::ChangeType::*; use semcheck::changes::ChangeSet; use semcheck::mapping::{IdMapping, NameMapping}; use semcheck::mismatch::Mismatch; -use semcheck::translate::{InferenceCleanupFolder, TranslationContext}; +use semcheck::translate::TranslationContext; +use semcheck::typeck::{BoundContext, TypeComparisonContext}; use std::collections::{BTreeMap, HashSet, VecDeque}; @@ -876,194 +873,3 @@ fn match_inherent_impl<'a, 'tcx>(_id_mapping: &IdMapping, _target_item_def_id: DefId) -> bool { true } - -/// The context in which bounds analysis happens. -pub struct BoundContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { - /// The inference context to use. - infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - /// The fulfillment context to use. - fulfill_cx: FulfillmentContext<'tcx>, - /// The param env to be assumed. - given_param_env: ParamEnv<'tcx>, -} - -impl<'a, 'gcx, 'tcx> BoundContext<'a, 'gcx, 'tcx> { - /// Construct a new bound context. - pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, given_param_env: ParamEnv<'tcx>) -> Self { - BoundContext { - infcx: infcx, - fulfill_cx: FulfillmentContext::new(), - given_param_env: given_param_env, - } - } - - /// Register the bounds of an item. - pub fn register(&mut self, checked_def_id: DefId, substs: &Substs<'tcx>) { - use rustc::traits::{normalize, Normalized, 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::ty::{Binder, Predicate, TraitPredicate}; - - let predicate = Predicate::Trait(Binder(TraitPredicate { - trait_ref: checked_trait_ref, - })); - let obligation = - Obligation::new(ObligationCause::dummy(), self.given_param_env, predicate); - self.fulfill_cx.register_predicate_obligation(self.infcx, obligation); - } - - /// Return inference errors, if any. - pub fn get_errors(&mut self) -> Option>> { - if let Err(err) = self.fulfill_cx.select_all_or_error(self.infcx) { - debug!("err: {:?}", err); - Some(err) - } else { - None - } - } -} - -pub struct TypeComparisonContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { - infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - id_mapping: &'a IdMapping, - folder: InferenceCleanupFolder<'a, 'gcx, 'tcx>, - pub forward_trans: TranslationContext<'a, 'gcx, 'tcx>, - pub backward_trans: TranslationContext<'a, 'gcx, 'tcx>, -} - -impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { - pub fn target_new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping) -> Self { - TypeComparisonContext { - infcx: infcx, - id_mapping: id_mapping, - folder: InferenceCleanupFolder::new(infcx), - forward_trans: TranslationContext::target_new(infcx.tcx, id_mapping, false), - backward_trans: TranslationContext::target_old(infcx.tcx, id_mapping, false), - } - } - - pub fn target_old(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping) -> Self { - TypeComparisonContext { - infcx: infcx, - id_mapping: id_mapping, - folder: InferenceCleanupFolder::new(infcx), - forward_trans: TranslationContext::target_old(infcx.tcx, id_mapping, false), - backward_trans: TranslationContext::target_new(infcx.tcx, id_mapping, false), - } - } - - fn compute_target_infer_substs(&self, target_def_id: DefId) -> &Substs<'tcx> { - use syntax_pos::DUMMY_SP; - - let has_self = self.infcx.tcx.generics_of(target_def_id).has_self; - - Substs::for_item(self.infcx.tcx, target_def_id, |def, _| { - self.infcx.region_var_for_def(DUMMY_SP, def) - }, |def, substs| { - if def.index == 0 && has_self { // `Self` is special - self.infcx.tcx.mk_param_from_def(def) - } else { - self.infcx.type_var_for_def(DUMMY_SP, def, substs) - } - }) - } - - fn compute_target_default_substs(&self, target_def_id: DefId) -> &Substs<'tcx> { - use rustc::ty::ReEarlyBound; - - Substs::for_item(self.infcx.tcx, target_def_id, |def, _| { - self.infcx.tcx.mk_region(ReEarlyBound(def.to_early_bound_region_data())) - }, |def, _| if self.id_mapping.is_non_mapped_defaulted_type_param(&def.def_id) { - self.infcx.tcx.type_of(def.def_id) - } else { - self.infcx.tcx.mk_param_from_def(def) - }) - } - - fn check_type_error<'b, 'tcx2>(&self, - lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, - target_def_id: DefId, - target_param_env: ParamEnv<'tcx>, - orig: Ty<'tcx>, - target: Ty<'tcx>) -> Option> { - use rustc::infer::InferOk; - use rustc::middle::free_region::FreeRegionMap; - use rustc::middle::region::RegionMaps; - use rustc::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 region_maps = RegionMaps::new(); - let mut free_regions = FreeRegionMap::new(); - - free_regions.relate_free_regions_from_predicates(target_param_env.caller_bounds); - self.infcx.resolve_regions_and_report_errors(target_def_id, - ®ion_maps, - &free_regions); - - let err = - self.infcx - .resolve_type_vars_if_possible(&err) - .fold_with(&mut self.folder.clone()) - .lift_to_tcx(lift_tcx) - .unwrap(); - - Some(err) - } else { - None - } - } - - fn check_bounds_error<'b, 'tcx2>(&self, - lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, - orig_param_env: ParamEnv<'tcx>, - target_def_id: DefId, - target_substs: &Substs<'tcx>) - -> Option>> - { - use rustc::ty::Lift; - - let mut bound_cx = BoundContext::new(self.infcx, orig_param_env); - bound_cx.register(target_def_id, target_substs); - - if let Some(errors) = bound_cx.get_errors() { - return Some(errors - .iter() - .map(|err| - self.infcx - .resolve_type_vars_if_possible(&err.obligation.predicate) - .fold_with(&mut self.folder.clone()) - .lift_to_tcx(lift_tcx) - .unwrap()) - .collect()) - } - - None - } -} diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs new file mode 100644 index 0000000000000..7ccc74f961709 --- /dev/null +++ b/src/semcheck/typeck.rs @@ -0,0 +1,219 @@ +//! 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 rustc::hir::def_id::DefId; +use rustc::infer::InferCtxt; +use rustc::traits::{FulfillmentContext, FulfillmentError, Obligation, ObligationCause}; +use rustc::ty::{ParamEnv, Predicate, TraitRef, Ty, TyCtxt}; +use rustc::ty::error::TypeError; +use rustc::ty::fold::TypeFoldable; +use rustc::ty::subst::Substs; + +use semcheck::mapping::IdMapping; +use semcheck::translate::{InferenceCleanupFolder, TranslationContext}; + +/// The context in which bounds analysis happens. +pub struct BoundContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { + /// The inference context to use. + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + /// The fulfillment context to use. + fulfill_cx: FulfillmentContext<'tcx>, + /// The param env to be assumed. + given_param_env: ParamEnv<'tcx>, +} + +impl<'a, 'gcx, 'tcx> BoundContext<'a, 'gcx, 'tcx> { + /// Construct a new bound context. + pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, given_param_env: ParamEnv<'tcx>) -> Self { + BoundContext { + infcx: infcx, + fulfill_cx: FulfillmentContext::new(), + given_param_env: given_param_env, + } + } + + /// Register the bounds of an item. + pub fn register(&mut self, checked_def_id: DefId, substs: &Substs<'tcx>) { + use rustc::traits::{normalize, Normalized, 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::ty::{Binder, Predicate, TraitPredicate}; + + let predicate = Predicate::Trait(Binder(TraitPredicate { + trait_ref: checked_trait_ref, + })); + let obligation = + Obligation::new(ObligationCause::dummy(), self.given_param_env, predicate); + self.fulfill_cx.register_predicate_obligation(self.infcx, obligation); + } + + /// Return inference errors, if any. + pub fn get_errors(&mut self) -> Option>> { + if let Err(err) = self.fulfill_cx.select_all_or_error(self.infcx) { + debug!("err: {:?}", err); + Some(err) + } else { + None + } + } +} + +/// The context in which types and their bounds can be compared. +pub struct TypeComparisonContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { + /// The inference context to use. + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + /// The index mapping to use. + id_mapping: &'a IdMapping, + /// The folder to clean up found errors of inference artifacts. + folder: InferenceCleanupFolder<'a, 'gcx, 'tcx>, + /// The translation context translating from original to target items. + pub forward_trans: TranslationContext<'a, 'gcx, 'tcx>, + /// The translation context translating from target to original items. + pub backward_trans: TranslationContext<'a, 'gcx, 'tcx>, +} + +impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { + /// Construct a new context where the original item is old. + pub fn target_new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping) -> Self { + TypeComparisonContext { + infcx: infcx, + id_mapping: id_mapping, + folder: InferenceCleanupFolder::new(infcx), + forward_trans: TranslationContext::target_new(infcx.tcx, id_mapping, false), + backward_trans: TranslationContext::target_old(infcx.tcx, id_mapping, false), + } + } + + /// Construct a new context where the original item is new. + pub fn target_old(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping) -> Self { + TypeComparisonContext { + infcx: infcx, + id_mapping: id_mapping, + folder: InferenceCleanupFolder::new(infcx), + forward_trans: TranslationContext::target_old(infcx.tcx, id_mapping, false), + backward_trans: TranslationContext::target_new(infcx.tcx, id_mapping, false), + } + } + + /// 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) -> &Substs<'tcx> { + use syntax_pos::DUMMY_SP; + + let has_self = self.infcx.tcx.generics_of(target_def_id).has_self; + + Substs::for_item(self.infcx.tcx, target_def_id, |def, _| { + self.infcx.region_var_for_def(DUMMY_SP, def) + }, |def, substs| { + if def.index == 0 && has_self { // `Self` is special + self.infcx.tcx.mk_param_from_def(def) + } else { + self.infcx.type_var_for_def(DUMMY_SP, def, substs) + } + }) + } + + /// Construct a set of subsitutions for an item, which normalizes defaults. + pub fn compute_target_default_substs(&self, target_def_id: DefId) -> &Substs<'tcx> { + use rustc::ty::ReEarlyBound; + + Substs::for_item(self.infcx.tcx, target_def_id, |def, _| { + self.infcx.tcx.mk_region(ReEarlyBound(def.to_early_bound_region_data())) + }, |def, _| if self.id_mapping.is_non_mapped_defaulted_type_param(&def.def_id) { + self.infcx.tcx.type_of(def.def_id) + } else { + self.infcx.tcx.mk_param_from_def(def) + }) + } + + /// Check for type mismatches for a pair of items. + pub fn check_type_error<'b, 'tcx2>(&self, + lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, + target_def_id: DefId, + target_param_env: ParamEnv<'tcx>, + orig: Ty<'tcx>, + target: Ty<'tcx>) -> Option> { + use rustc::infer::InferOk; + use rustc::middle::free_region::FreeRegionMap; + use rustc::middle::region::RegionMaps; + use rustc::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 region_maps = RegionMaps::new(); + let mut free_regions = FreeRegionMap::new(); + + free_regions.relate_free_regions_from_predicates(target_param_env.caller_bounds); + self.infcx.resolve_regions_and_report_errors(target_def_id, + ®ion_maps, + &free_regions); + + let err = + self.infcx + .resolve_type_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 for a pair of items. + pub fn check_bounds_error<'b, 'tcx2>(&self, + lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, + orig_param_env: ParamEnv<'tcx>, + target_def_id: DefId, + target_substs: &Substs<'tcx>) + -> Option>> + { + use rustc::ty::Lift; + + let mut bound_cx = BoundContext::new(self.infcx, orig_param_env); + bound_cx.register(target_def_id, target_substs); + + if let Some(errors) = bound_cx.get_errors() { + return Some(errors + .iter() + .map(|err| + self.infcx + .resolve_type_vars_if_possible(&err.obligation.predicate) + .fold_with(&mut self.folder.clone()) + .lift_to_tcx(lift_tcx) + .unwrap()) + .collect()) + } + + None + } +} From ce81a1dd3d9fcceee64651ab026e5dee9b6c1c16 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 4 Aug 2017 17:02:27 +0200 Subject: [PATCH 209/553] A first approximation of inherent impl checking. --- src/semcheck/mapping.rs | 13 ++++- src/semcheck/traverse.rs | 86 +++++++++++++++++++++++++------ src/semcheck/typeck.rs | 24 +++++---- tests/cases/inherent_impls/new.rs | 17 ++++++ tests/cases/inherent_impls/old.rs | 17 ++++++ tests/cases/inherent_impls/stdout | 22 +++++++- 6 files changed, 151 insertions(+), 28 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index a493bf774a312..9c01fc142150a 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -7,6 +7,7 @@ use rustc::hir::def::{Def, Export}; use rustc::hir::def_id::{CrateNum, DefId}; use rustc::ty::{AssociatedKind, TypeParameterDef}; +use std::cell::Cell; use std::collections::{BTreeSet, HashMap, HashSet, VecDeque}; use syntax::ast::Name; @@ -52,6 +53,8 @@ pub struct IdMapping { type_params: HashMap, /// Map of items from inherent impls' descriptors to the impls they are declared in. inherent_items: HashMap, + /// A match that has been just found and needs to be temporarily added to the mapping. + current_match: Cell>, } impl IdMapping { @@ -68,6 +71,7 @@ impl IdMapping { reverse_mapping: HashMap::new(), type_params: HashMap::new(), inherent_items: HashMap::new(), + current_match: Cell::new(None), } } @@ -176,6 +180,8 @@ impl IdMapping { Some(new.1.def_id()) } else if let Some(new_def_id) = self.internal_mapping.get(&old) { Some(*new_def_id) + } else if let Some(def_id_pair) = self.current_match.get() { + Some(def_id_pair.1) } else { None } @@ -189,7 +195,7 @@ impl IdMapping { assert!(!self.in_old_crate(new)); if self.in_new_crate(new) { - self.reverse_mapping.get(&new).cloned() + self.reverse_mapping.get(&new).cloned().or(self.current_match.get().map(|p| p.0)) } else { Some(new) } @@ -212,6 +218,11 @@ impl IdMapping { self.reverse_mapping.contains_key(&new) } + /// Temporarily register a `DefId` pair. + pub fn register_current_match(&self, old: DefId, new: DefId) { + self.current_match.set(Some((old, new))); + } + /// Construct a queue of toplevel item pairs' `DefId`s. pub fn toplevel_queue(&self) -> VecDeque<(DefId, DefId)> { self.toplevel_mapping diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 946595d085466..e03a98664eae0 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -658,21 +658,31 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let to_old = TranslationContext::target_old(tcx, id_mapping, false); for (orig_item, orig_impls) in id_mapping.inherent_impls() { - let (trans, err_type) = if id_mapping.in_old_crate(orig_item.parent_def_id) { - (&to_new, AssociatedItemRemoved) - } else if id_mapping.in_new_crate(orig_item.parent_def_id) { - (&to_old, AssociatedItemAdded) - } else { - unreachable!() - }; + let (forward_trans, err_type) = + if id_mapping.in_old_crate(orig_item.parent_def_id) { + (&to_new, AssociatedItemRemoved) + } else if id_mapping.in_new_crate(orig_item.parent_def_id) { + (&to_old, AssociatedItemAdded) + } else { + unreachable!() + }; for &(orig_impl_def_id, orig_item_def_id) in orig_impls { - let target_impls = if let Some(impls) = trans + 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 { + 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, + true); + changes.add_change(err_type.clone(), orig_item_def_id, None); continue; }; @@ -681,7 +691,6 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, .any(|&(target_impl_def_id, target_item_def_id)| { match_inherent_impl(id_mapping, tcx, - trans, orig_impl_def_id, orig_item_def_id, target_impl_def_id, @@ -864,12 +873,55 @@ fn match_trait_impl<'a, 'tcx>(id_mapping: &IdMapping, /// Compare an item pair in two inherent implementations and indicate whether the target one is /// compatible with the original one. -fn match_inherent_impl<'a, 'tcx>(_id_mapping: &IdMapping, - _tcx: TyCtxt<'a, 'tcx, 'tcx>, - _trans: &TranslationContext<'a, 'tcx, 'tcx>, - _orig_impl_def_id: DefId, - _orig_item_def_id: DefId, - _target_impl_def_id: DefId, - _target_item_def_id: DefId) -> bool { - true +fn match_inherent_impl<'a, 'tcx>(id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + orig_impl_def_id: DefId, + orig_item_def_id: DefId, + target_impl_def_id: DefId, + target_item_def_id: DefId) -> bool { + tcx.infer_ctxt().enter(|infcx| { + let compcx = if id_mapping.in_old_crate(orig_impl_def_id) { + id_mapping.register_current_match(orig_item_def_id, target_item_def_id); + TypeComparisonContext::target_new(&infcx, id_mapping) + } else { + id_mapping.register_current_match(target_item_def_id, orig_item_def_id); + TypeComparisonContext::target_old(&infcx, id_mapping) + }; + + 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_impl_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() { + return false; + } + + let orig = compcx + .forward_trans + .translate_item_type(orig_item_def_id, infcx.tcx.type_of(orig_item_def_id)); + let target = infcx.tcx.type_of(target_item_def_id).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 { + println!("err: {:?}", err); + } + + true + }) } diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs index 7ccc74f961709..fe84e4ac5d4c1 100644 --- a/src/semcheck/typeck.rs +++ b/src/semcheck/typeck.rs @@ -98,23 +98,29 @@ pub struct TypeComparisonContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { /// Construct a new context where the original item is old. pub fn target_new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping) -> Self { - TypeComparisonContext { - infcx: infcx, - id_mapping: id_mapping, - folder: InferenceCleanupFolder::new(infcx), - forward_trans: TranslationContext::target_new(infcx.tcx, id_mapping, false), - backward_trans: TranslationContext::target_old(infcx.tcx, id_mapping, false), - } + 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) } /// Construct a new context where the original item is new. pub fn target_old(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping) -> 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) + } + + /// Construct a new context given a pair of translation contexts. + fn from_trans(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + id_mapping: &'a IdMapping, + forward_trans: TranslationContext<'a, 'gcx, 'tcx>, + backward_trans: TranslationContext<'a, 'gcx, 'tcx>) -> Self { TypeComparisonContext { infcx: infcx, id_mapping: id_mapping, folder: InferenceCleanupFolder::new(infcx), - forward_trans: TranslationContext::target_old(infcx.tcx, id_mapping, false), - backward_trans: TranslationContext::target_new(infcx.tcx, id_mapping, false), + forward_trans: forward_trans, + backward_trans: backward_trans, } } diff --git a/tests/cases/inherent_impls/new.rs b/tests/cases/inherent_impls/new.rs index fbcd6812e3bf1..890211ce862f7 100644 --- a/tests/cases/inherent_impls/new.rs +++ b/tests/cases/inherent_impls/new.rs @@ -11,3 +11,20 @@ impl Abc { fn def(&self) { } } + +#[allow(dead_code)] +pub struct Def { + field: A, +} + +impl Def { + pub fn def(&self) -> u8 { + 0 + } +} + +impl Def { + pub fn def(&self) -> u8 { + 0 + } +} diff --git a/tests/cases/inherent_impls/old.rs b/tests/cases/inherent_impls/old.rs index fbcd6812e3bf1..c4e45f4479b79 100644 --- a/tests/cases/inherent_impls/old.rs +++ b/tests/cases/inherent_impls/old.rs @@ -11,3 +11,20 @@ impl Abc { fn def(&self) { } } + +#[allow(dead_code)] +pub struct Def { + field: A, +} + +impl Def { + pub fn def(&self) -> u8 { + 0 + } +} + +impl Def { + pub fn def(&self) -> u8 { + 0 + } +} diff --git a/tests/cases/inherent_impls/stdout b/tests/cases/inherent_impls/stdout index f8c2af4c949b7..f4d4c462c940d 100644 --- a/tests/cases/inherent_impls/stdout +++ b/tests/cases/inherent_impls/stdout @@ -1 +1,21 @@ -version bump: 1.0.0 -> (patch) -> 1.0.1 +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: breaking changes in `def` + --> $REPO_PATH/tests/cases/inherent_impls/old.rs:21:5 + | +21 | / pub fn def(&self) -> u8 { +22 | | 0 +23 | | } + | |_____^ + | + = warning: removed item in inherent impl (breaking) + +warning: technically breaking changes in `def` + --> $REPO_PATH/tests/cases/inherent_impls/new.rs:27:5 + | +27 | / pub fn def(&self) -> u8 { +28 | | 0 +29 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + From b41b266711b3713420319eafd552991bfc87cea1 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 5 Aug 2017 13:53:35 +0200 Subject: [PATCH 210/553] A rough draft of the complete inherent impl matching. --- src/semcheck/mapping.rs | 13 +++++- src/semcheck/traverse.rs | 85 +++++++++++++++++++++++++++++++++++++--- src/semcheck/typeck.rs | 8 ++-- 3 files changed, 93 insertions(+), 13 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 9c01fc142150a..583bdfb02e238 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -181,7 +181,11 @@ impl IdMapping { } else if let Some(new_def_id) = self.internal_mapping.get(&old) { Some(*new_def_id) } else if let Some(def_id_pair) = self.current_match.get() { - Some(def_id_pair.1) + if def_id_pair.0 == old { + Some(def_id_pair.1) + } else { + None + } } else { None } @@ -195,7 +199,12 @@ impl IdMapping { assert!(!self.in_old_crate(new)); if self.in_new_crate(new) { - self.reverse_mapping.get(&new).cloned().or(self.current_match.get().map(|p| p.0)) + self.reverse_mapping + .get(&new) + .cloned() + .or(self.current_match + .get() + .and_then(|p| if p.1 == new { Some(p.0) } else { None })) } else { Some(new) } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index e03a98664eae0..1b7ca45d80a3a 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -689,7 +689,8 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let match_found = target_impls .iter() .any(|&(target_impl_def_id, target_item_def_id)| { - match_inherent_impl(id_mapping, + match_inherent_impl(changes, + id_mapping, tcx, orig_impl_def_id, orig_item_def_id, @@ -839,11 +840,8 @@ fn match_trait_impl<'a, 'tcx>(id_mapping: &IdMapping, orig_def_id: DefId) -> bool { let trans = if id_mapping.in_old_crate(orig_def_id) { TranslationContext::target_new(tcx, id_mapping, false) - } else if id_mapping.in_new_crate(orig_def_id) { - TranslationContext::target_old(tcx, id_mapping, false) } else { - // not reached, but apparently we don't care. - return true; + TranslationContext::target_old(tcx, id_mapping, false) }; debug!("matching: {:?}", orig_def_id); @@ -873,7 +871,8 @@ fn match_trait_impl<'a, 'tcx>(id_mapping: &IdMapping, /// Compare an item pair in two inherent implementations and indicate whether the target one is /// compatible with the original one. -fn match_inherent_impl<'a, 'tcx>(id_mapping: &IdMapping, +fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, orig_impl_def_id: DefId, orig_item_def_id: DefId, @@ -904,6 +903,25 @@ fn match_inherent_impl<'a, 'tcx>(id_mapping: &IdMapping, target_self); if error.is_some() { + // `Self` on the impls isn't equal - no impl match found. + 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 found. + return false + } + } else { + // The bounds could not have been translated - no impl match found. return false; } @@ -920,6 +938,61 @@ fn match_inherent_impl<'a, 'tcx>(id_mapping: &IdMapping, if let Some(err) = error { println!("err: {:?}", err); + changes.add_change(TypeChanged { error: err }, orig_item_def_id, None); + } + + let orig_param_env = compcx + .forward_trans + .translate_param_env(orig_item_def_id, tcx.param_env(orig_item_def_id)); + let target_param_env = compcx + .backward_trans + .translate_param_env(target_item_def_id, tcx.param_env(target_item_def_id)); + + let orig_param_env = if let Some(env) = orig_param_env { + env + } else { + // The bounds on the item could not have been translated - impl match found. + return true; + }; + + if let Some(errors) = + compcx.check_bounds_error(tcx, orig_param_env, target_item_def_id, target_substs) + { + for err in errors { + println!("err preds forward: {:?}", err); + + let err_type = BoundsTightened { + pred: err, + }; + + changes.add_change(err_type, + orig_item_def_id, + Some(tcx.def_span(orig_item_def_id))); + } + } + + let target_param_env = if let Some(env) = target_param_env { + env + } else { + // The bounds on the item could not have been translated - impl match found. + return true; + }; + + let orig_substs = Substs::identity_for_item(tcx, target_item_def_id); + if let Some(errors) = + compcx.check_bounds_error(tcx, target_param_env, orig_item_def_id, orig_substs) + { + for err in errors { + println!("err preds backward: {:?}", err); + + let err_type = BoundsLoosened { + pred: err, + }; + + changes.add_change(err_type, + orig_item_def_id, + Some(tcx.def_span(orig_item_def_id))); + } } true diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs index fe84e4ac5d4c1..c111c348035e2 100644 --- a/src/semcheck/typeck.rs +++ b/src/semcheck/typeck.rs @@ -208,8 +208,9 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { let mut bound_cx = BoundContext::new(self.infcx, orig_param_env); bound_cx.register(target_def_id, target_substs); - if let Some(errors) = bound_cx.get_errors() { - return Some(errors + bound_cx + .get_errors() + .map(|errors| errors .iter() .map(|err| self.infcx @@ -218,8 +219,5 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { .lift_to_tcx(lift_tcx) .unwrap()) .collect()) - } - - None } } From 72b09513d32ef30d1501fa9a3bf7e6b440122535 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 5 Aug 2017 14:15:28 +0200 Subject: [PATCH 211/553] More through comparison of inherent items. --- src/semcheck/traverse.rs | 43 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 1b7ca45d80a3a..ae4105262e19c 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -668,20 +668,20 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, }; for &(orig_impl_def_id, orig_item_def_id) in orig_impls { + 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, + true); + 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 { - 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, - true); changes.add_change(err_type.clone(), orig_item_def_id, None); continue; }; @@ -699,14 +699,6 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, }); if !match_found { - 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, - true); changes.add_change(err_type.clone(), orig_item_def_id, None); } } @@ -879,12 +871,12 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, target_impl_def_id: DefId, target_item_def_id: DefId) -> bool { tcx.infer_ctxt().enter(|infcx| { - let compcx = if id_mapping.in_old_crate(orig_impl_def_id) { + let (compcx, register_errors) = if id_mapping.in_old_crate(orig_impl_def_id) { id_mapping.register_current_match(orig_item_def_id, target_item_def_id); - TypeComparisonContext::target_new(&infcx, id_mapping) + (TypeComparisonContext::target_new(&infcx, id_mapping), true) } else { id_mapping.register_current_match(target_item_def_id, orig_item_def_id); - TypeComparisonContext::target_old(&infcx, id_mapping) + (TypeComparisonContext::target_old(&infcx, id_mapping), false) }; let orig_self = compcx @@ -925,6 +917,16 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, return false; } + if !register_errors { + // checking backwards, impl match found. + return true; + } + + let orig_item = tcx.associated_item(orig_item_def_id); + let target_item = tcx.associated_item(target_item_def_id); + + diff_method(changes, tcx, orig_item, target_item); + let orig = compcx .forward_trans .translate_item_type(orig_item_def_id, infcx.tcx.type_of(orig_item_def_id)); @@ -937,7 +939,6 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, target); if let Some(err) = error { - println!("err: {:?}", err); changes.add_change(TypeChanged { error: err }, orig_item_def_id, None); } @@ -959,8 +960,6 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, compcx.check_bounds_error(tcx, orig_param_env, target_item_def_id, target_substs) { for err in errors { - println!("err preds forward: {:?}", err); - let err_type = BoundsTightened { pred: err, }; From 21edcc5e79800ff7571465feeec01a611d572f5f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 5 Aug 2017 17:17:45 +0200 Subject: [PATCH 212/553] Fixed a slew of bugs regarding accessibility of associated items. --- src/semcheck/changes.rs | 10 +++ src/semcheck/traverse.rs | 127 +++++++++++++++++++----------- tests/cases/inherent_impls/new.rs | 6 +- tests/cases/inherent_impls/stdout | 16 +++- 4 files changed, 108 insertions(+), 51 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index a468c4a9f1ab6..e305f18d8a88e 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -531,6 +531,16 @@ impl<'tcx> ChangeSet<'tcx> { 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) { + self.changes.get_mut(&old).map(|change| change.output = true); + } + /// Check whether an item with the given id has undergone breaking changes. /// /// The expected `DefId` is obviously an *old* one. diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index ae4105262e19c..2c6df54cd7b67 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -308,6 +308,15 @@ fn diff_method(changes: &mut ChangeSet, tcx: TyCtxt, old: AssociatedItem, new: A None); } + let old_pub = old.vis == Public; + let new_pub = new.vis == Public; + + if old_pub && !new_pub { + changes.add_change(ItemMadePrivate, old.def_id, None); + } else if !old_pub && new_pub { + changes.add_change(ItemMadePublic, old.def_id, None); + } + diff_fn(changes, tcx, Def::Method(old.def_id), Def::Method(new.def_id)); } @@ -667,17 +676,21 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, unreachable!() }; + let parent_output = changes.get_output(orig_item.parent_def_id); + 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, - true); + parent_output && orig_assoc_item.vis == Public); let target_impls = if let Some(impls) = forward_trans - .translate_inherent_entry(orig_item) + .translate_inherent_entry(&orig_item) .and_then(|item| id_mapping.get_inherent_impls(&item)) { impls @@ -689,13 +702,19 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, 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, - orig_item_def_id, target_impl_def_id, - target_item_def_id) + orig_assoc_item, + target_assoc_item) }); if !match_found { @@ -754,72 +773,76 @@ fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, - old_def_id: DefId, - new_def_id: DefId, - old: Ty<'tcx>, - new: Ty<'tcx>) { - info!("comparing types of {:?} / {:?}:\n {:?} / {:?}", old_def_id, new_def_id, old, new); + orig_def_id: DefId, + target_def_id: DefId, + orig: Ty<'tcx>, + target: Ty<'tcx>) { + info!("comparing types of {:?} / {:?}:\n {:?} / {:?}", + orig_def_id, target_def_id, orig, target); tcx.infer_ctxt().enter(|infcx| { let compcx = TypeComparisonContext::target_new(&infcx, id_mapping); - let old_substs = Substs::identity_for_item(infcx.tcx, new_def_id); - let old = compcx.forward_trans.translate_item_type(old_def_id, old); - // let old = old.subst(infcx.tcx, old_substs); + let orig_substs = Substs::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); - let new_substs = if new.is_fn() { - compcx.compute_target_infer_substs(new_def_id) + let target_substs = if target.is_fn() { + compcx.compute_target_infer_substs(target_def_id) } else { - compcx.compute_target_default_substs(new_def_id) + compcx.compute_target_default_substs(target_def_id) }; - let new = new.subst(infcx.tcx, new_substs); + let target = target.subst(infcx.tcx, target_substs); - let new_param_env = infcx.tcx.param_env(new_def_id).subst(infcx.tcx, new_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, new_def_id, new_param_env, old, new) { - changes.add_change(TypeChanged { error: err }, old_def_id, None); + if let Some(err) = + compcx.check_type_error(tcx, target_def_id, target_param_env, orig, target) + { + changes.add_change(TypeChanged { error: err }, orig_def_id, None); } - let old_param_env = compcx + let orig_param_env = compcx .forward_trans - .translate_param_env(old_def_id, tcx.param_env(old_def_id)); - let new_param_env = compcx + .translate_param_env(orig_def_id, tcx.param_env(orig_def_id)); + let target_param_env = compcx .backward_trans - .translate_param_env(new_def_id, tcx.param_env(new_def_id)); + .translate_param_env(target_def_id, tcx.param_env(target_def_id)); - let old_param_env = if let Some(env) = old_param_env { + let orig_param_env = if let Some(env) = orig_param_env { env } else { return; }; if let Some(errors) = - compcx.check_bounds_error(tcx, old_param_env, new_def_id, new_substs) + compcx.check_bounds_error(tcx, orig_param_env, target_def_id, target_substs) { for err in errors { let err_type = BoundsTightened { pred: err, }; - changes.add_change(err_type, old_def_id, Some(tcx.def_span(old_def_id))); + changes.add_change(err_type, orig_def_id, Some(tcx.def_span(orig_def_id))); } } - let new_param_env = if let Some(env) = new_param_env { + let target_param_env = if let Some(env) = target_param_env { env } else { return; }; if let Some(errors) = - compcx.check_bounds_error(tcx, new_param_env, old_def_id, old_substs) + compcx.check_bounds_error(tcx, target_param_env, orig_def_id, orig_substs) { for err in errors { let err_type = BoundsLoosened { pred: err, }; - changes.add_change(err_type, old_def_id, Some(tcx.def_span(old_def_id))); + changes.add_change(err_type, orig_def_id, Some(tcx.def_span(orig_def_id))); } } }); @@ -867,9 +890,14 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, orig_impl_def_id: DefId, - orig_item_def_id: DefId, target_impl_def_id: DefId, - target_item_def_id: DefId) -> bool { + orig_item: AssociatedItem, + target_item: AssociatedItem) -> bool { + use rustc::ty::AssociatedKind; + + 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) { id_mapping.register_current_match(orig_item_def_id, target_item_def_id); @@ -883,7 +911,7 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, .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_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); @@ -895,7 +923,7 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, target_self); if error.is_some() { - // `Self` on the impls isn't equal - no impl match found. + // `Self` on the impls isn't equal - no impl match. return false; } @@ -909,28 +937,37 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, target_impl_def_id, target_substs); if errors.is_some() { - // The bounds on the impls have been tightened - no impl match found. + // The bounds on the impls have been tightened - no impl match. return false } } else { - // The bounds could not have been translated - no impl match found. + // The bounds could not have been translated - no impl match. return false; } if !register_errors { - // checking backwards, impl match found. + // checking backwards, impls match. return true; } - let orig_item = tcx.associated_item(orig_item_def_id); - let target_item = tcx.associated_item(target_item_def_id); - - diff_method(changes, tcx, orig_item, target_item); + let (orig, target) = match (orig_item.kind, target_item.kind) { + (AssociatedKind::Const, AssociatedKind::Const) => { + (infcx.tcx.type_of(orig_item_def_id), infcx.tcx.type_of(target_item_def_id)) + }, + (AssociatedKind::Method, AssociatedKind::Method) => { + diff_method(changes, tcx, orig_item, target_item); + (infcx.tcx.type_of(orig_item_def_id), infcx.tcx.type_of(target_item_def_id)) + }, + (AssociatedKind::Type, AssociatedKind::Type) => { + (infcx.tcx.type_of(orig_item_def_id), infcx.tcx.type_of(target_item_def_id)) + }, + _ => { + unreachable!(); + }, + }; - let orig = compcx - .forward_trans - .translate_item_type(orig_item_def_id, infcx.tcx.type_of(orig_item_def_id)); - let target = infcx.tcx.type_of(target_item_def_id).subst(infcx.tcx, target_substs); + 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, @@ -982,8 +1019,6 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, compcx.check_bounds_error(tcx, target_param_env, orig_item_def_id, orig_substs) { for err in errors { - println!("err preds backward: {:?}", err); - let err_type = BoundsLoosened { pred: err, }; diff --git a/tests/cases/inherent_impls/new.rs b/tests/cases/inherent_impls/new.rs index 890211ce862f7..3ed96db6fa5d2 100644 --- a/tests/cases/inherent_impls/new.rs +++ b/tests/cases/inherent_impls/new.rs @@ -18,9 +18,13 @@ pub struct Def { } impl Def { - pub fn def(&self) -> u8 { + pub fn def(&self) -> u16 { 0 } + + pub fn abc() { } + + fn abc2() { } } impl Def { diff --git a/tests/cases/inherent_impls/stdout b/tests/cases/inherent_impls/stdout index f4d4c462c940d..5a186de1f3b1a 100644 --- a/tests/cases/inherent_impls/stdout +++ b/tests/cases/inherent_impls/stdout @@ -9,12 +9,20 @@ warning: breaking changes in `def` | = warning: removed item in inherent impl (breaking) +warning: technically breaking changes in `abc` + --> $REPO_PATH/tests/cases/inherent_impls/new.rs:25:5 + | +25 | pub fn abc() { } + | ^^^^^^^^^^^^^^^^ + | + = note: added item in inherent impl (technically breaking) + warning: technically breaking changes in `def` - --> $REPO_PATH/tests/cases/inherent_impls/new.rs:27:5 + --> $REPO_PATH/tests/cases/inherent_impls/new.rs:31:5 | -27 | / pub fn def(&self) -> u8 { -28 | | 0 -29 | | } +31 | / pub fn def(&self) -> u8 { +32 | | 0 +33 | | } | |_____^ | = note: added item in inherent impl (technically breaking) From 59ca252275d863dff8d256d4f8b9c489beecb97e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 5 Aug 2017 17:30:48 +0200 Subject: [PATCH 213/553] Cleanup and bugfixes. We now properly replace function types with function pointers when comparing types of inherent impl items. Just as we do for all others. --- src/semcheck/mapping.rs | 3 ++- src/semcheck/traverse.rs | 12 ++++++------ tests/cases/inherent_impls/old.rs | 4 ++++ tests/cases/inherent_impls/stdout | 18 ++++++++++++++++++ 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 583bdfb02e238..41686d1caa075 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -202,7 +202,8 @@ impl IdMapping { self.reverse_mapping .get(&new) .cloned() - .or(self.current_match + .or_else(|| + self.current_match .get() .and_then(|p| if p.1 == new { Some(p.0) } else { None })) } else { diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 2c6df54cd7b67..e3b3047d0e5cd 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -690,7 +690,7 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, parent_output && orig_assoc_item.vis == Public); let target_impls = if let Some(impls) = forward_trans - .translate_inherent_entry(&orig_item) + .translate_inherent_entry(orig_item) .and_then(|item| id_mapping.get_inherent_impls(&item)) { impls @@ -951,15 +951,15 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } let (orig, target) = match (orig_item.kind, target_item.kind) { - (AssociatedKind::Const, AssociatedKind::Const) => { + (AssociatedKind::Const, AssociatedKind::Const) | + (AssociatedKind::Type, AssociatedKind::Type) => { (infcx.tcx.type_of(orig_item_def_id), infcx.tcx.type_of(target_item_def_id)) }, (AssociatedKind::Method, AssociatedKind::Method) => { diff_method(changes, tcx, orig_item, target_item); - (infcx.tcx.type_of(orig_item_def_id), infcx.tcx.type_of(target_item_def_id)) - }, - (AssociatedKind::Type, AssociatedKind::Type) => { - (infcx.tcx.type_of(orig_item_def_id), infcx.tcx.type_of(target_item_def_id)) + 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!(); diff --git a/tests/cases/inherent_impls/old.rs b/tests/cases/inherent_impls/old.rs index c4e45f4479b79..6a3e1c66a32b1 100644 --- a/tests/cases/inherent_impls/old.rs +++ b/tests/cases/inherent_impls/old.rs @@ -27,4 +27,8 @@ impl Def { pub fn def(&self) -> u8 { 0 } + + pub fn ghi() { } + + fn ghi2() { } } diff --git a/tests/cases/inherent_impls/stdout b/tests/cases/inherent_impls/stdout index 5a186de1f3b1a..e7db35db8c336 100644 --- a/tests/cases/inherent_impls/stdout +++ b/tests/cases/inherent_impls/stdout @@ -9,6 +9,24 @@ warning: breaking changes in `def` | = warning: removed item in inherent impl (breaking) +warning: breaking changes in `def` + --> $REPO_PATH/tests/cases/inherent_impls/old.rs:27:5 + | +27 | / pub fn def(&self) -> u8 { +28 | | 0 +29 | | } + | |_____^ + | + = warning: type error: expected u8, found u16 (breaking) + +warning: breaking changes in `ghi` + --> $REPO_PATH/tests/cases/inherent_impls/old.rs:31:5 + | +31 | pub fn ghi() { } + | ^^^^^^^^^^^^^^^^ + | + = warning: removed item in inherent impl (breaking) + warning: technically breaking changes in `abc` --> $REPO_PATH/tests/cases/inherent_impls/new.rs:25:5 | From 456b7be15bab875e8de6764be4456064a45a4e45 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 5 Aug 2017 19:02:11 +0200 Subject: [PATCH 214/553] Collapsed bound checking into a method on `TypeComparisonContext`. --- src/semcheck/traverse.rs | 104 +++++---------------------------------- src/semcheck/typeck.rs | 69 ++++++++++++++++++++++++-- 2 files changed, 78 insertions(+), 95 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index e3b3047d0e5cd..d0dfec85cbf5d 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -803,48 +803,12 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, changes.add_change(TypeChanged { error: err }, orig_def_id, None); } - let orig_param_env = compcx - .forward_trans - .translate_param_env(orig_def_id, tcx.param_env(orig_def_id)); - let target_param_env = compcx - .backward_trans - .translate_param_env(target_def_id, tcx.param_env(target_def_id)); - - let orig_param_env = if let Some(env) = orig_param_env { - env - } else { - return; - }; - - if let Some(errors) = - compcx.check_bounds_error(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, Some(tcx.def_span(orig_def_id))); - } - } - - let target_param_env = if let Some(env) = target_param_env { - env - } else { - return; - }; - - if let Some(errors) = - compcx.check_bounds_error(tcx, target_param_env, orig_def_id, orig_substs) - { - for err in errors { - let err_type = BoundsLoosened { - pred: err, - }; - - changes.add_change(err_type, orig_def_id, Some(tcx.def_span(orig_def_id))); - } - } + compcx.check_bounds_bidirectional(changes, + tcx, + orig_def_id, + target_def_id, + orig_substs, + target_substs); }); } @@ -907,6 +871,7 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, (TypeComparisonContext::target_old(&infcx, id_mapping), false) }; + let orig_substs = Substs::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)); @@ -979,55 +944,12 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, changes.add_change(TypeChanged { error: err }, orig_item_def_id, None); } - let orig_param_env = compcx - .forward_trans - .translate_param_env(orig_item_def_id, tcx.param_env(orig_item_def_id)); - let target_param_env = compcx - .backward_trans - .translate_param_env(target_item_def_id, tcx.param_env(target_item_def_id)); - - let orig_param_env = if let Some(env) = orig_param_env { - env - } else { - // The bounds on the item could not have been translated - impl match found. - return true; - }; - - if let Some(errors) = - compcx.check_bounds_error(tcx, orig_param_env, target_item_def_id, target_substs) - { - for err in errors { - let err_type = BoundsTightened { - pred: err, - }; - - changes.add_change(err_type, - orig_item_def_id, - Some(tcx.def_span(orig_item_def_id))); - } - } - - let target_param_env = if let Some(env) = target_param_env { - env - } else { - // The bounds on the item could not have been translated - impl match found. - return true; - }; - - let orig_substs = Substs::identity_for_item(tcx, target_item_def_id); - if let Some(errors) = - compcx.check_bounds_error(tcx, target_param_env, orig_item_def_id, orig_substs) - { - for err in errors { - let err_type = BoundsLoosened { - pred: err, - }; - - changes.add_change(err_type, - orig_item_def_id, - Some(tcx.def_span(orig_item_def_id))); - } - } + compcx.check_bounds_bidirectional(changes, + tcx, + orig_item_def_id, + target_item_def_id, + orig_substs, + target_substs); true }) diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs index c111c348035e2..c829a34fc0e7e 100644 --- a/src/semcheck/typeck.rs +++ b/src/semcheck/typeck.rs @@ -11,6 +11,7 @@ use rustc::ty::error::TypeError; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::Substs; +use semcheck::changes::ChangeSet; use semcheck::mapping::IdMapping; use semcheck::translate::{InferenceCleanupFolder, TranslationContext}; @@ -197,10 +198,10 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { /// Check for trait bound mismatches for a pair of items. pub fn check_bounds_error<'b, 'tcx2>(&self, - lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, - orig_param_env: ParamEnv<'tcx>, - target_def_id: DefId, - target_substs: &Substs<'tcx>) + lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, + orig_param_env: ParamEnv<'tcx>, + target_def_id: DefId, + target_substs: &Substs<'tcx>) -> Option>> { use rustc::ty::Lift; @@ -220,4 +221,64 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { .unwrap()) .collect()) } + + /// Check the bounds on an item in both directions and register changes found. + pub fn check_bounds_bidirectional<'b, 'tcx2>(&self, + changes: &mut ChangeSet<'tcx2>, + lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, + orig_def_id: DefId, + target_def_id: DefId, + orig_substs: &Substs<'tcx>, + target_substs: &Substs<'tcx>) { + use semcheck::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 target_param_env = self + .backward_trans + .translate_param_env(target_def_id, tcx.param_env(target_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, + Some(tcx.def_span(orig_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, + }; + + changes.add_change(err_type, + orig_def_id, + Some(tcx.def_span(orig_def_id))); + } + } + } } From ed844c1790c2ac5b0e26bbcbc19eeac47db8a105 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 5 Aug 2017 22:09:48 +0200 Subject: [PATCH 215/553] Some cleanup. --- src/semcheck/traverse.rs | 2 ++ src/semcheck/typeck.rs | 8 ++------ tests/cases/bounds/stdout | 28 ++++----------------------- tests/cases/inherent_impls/new.rs | 7 +++++++ tests/cases/inherent_impls/old.rs | 7 +++++++ tests/cases/inherent_impls/stdout | 32 +++++++++++++++---------------- 6 files changed, 38 insertions(+), 46 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index d0dfec85cbf5d..a8d79569aab89 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -910,6 +910,8 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, 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; diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs index c829a34fc0e7e..0bcc0bfcfd082 100644 --- a/src/semcheck/typeck.rs +++ b/src/semcheck/typeck.rs @@ -255,9 +255,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { pred: err, }; - changes.add_change(err_type, - orig_def_id, - Some(tcx.def_span(orig_def_id))); + changes.add_change(err_type, orig_def_id, None); } } @@ -275,9 +273,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { pred: err, }; - changes.add_change(err_type, - orig_def_id, - Some(tcx.def_span(orig_def_id))); + changes.add_change(err_type, orig_def_id, None); } } } diff --git a/tests/cases/bounds/stdout b/tests/cases/bounds/stdout index 60e9238fff63c..5dbd95a52ab0e 100644 --- a/tests/cases/bounds/stdout +++ b/tests/cases/bounds/stdout @@ -7,13 +7,7 @@ warning: breaking changes in `Abc` 3 | | } | |_^ | -warning: added bound: `A: std::clone::Clone` (breaking) - --> $REPO_PATH/tests/cases/bounds/old.rs:1:1 - | -1 | / pub struct Abc { -2 | | pub a: A, -3 | | } - | |_^ + = warning: added bound: `A: std::clone::Clone` (breaking) warning: technically breaking changes in `Def` --> $REPO_PATH/tests/cases/bounds/new.rs:5:1 @@ -23,13 +17,7 @@ warning: technically breaking changes in `Def` 7 | | } | |_^ | -note: removed bound: `A: std::clone::Clone` (technically breaking) - --> $REPO_PATH/tests/cases/bounds/old.rs:5:1 - | -5 | / pub struct Def { -6 | | pub d: A, -7 | | } - | |_^ + = note: removed bound: `A: std::clone::Clone` (technically breaking) warning: breaking changes in `abc` --> $REPO_PATH/tests/cases/bounds/new.rs:9:1 @@ -37,11 +25,7 @@ warning: breaking changes in `abc` 9 | pub fn abc(_: A) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -warning: added bound: `A: std::clone::Clone` (breaking) - --> $REPO_PATH/tests/cases/bounds/old.rs:9:1 - | -9 | pub fn abc(_: A) {} - | ^^^^^^^^^^^^^^^^^^^^^^ + = warning: added bound: `A: std::clone::Clone` (breaking) warning: technically breaking changes in `def` --> $REPO_PATH/tests/cases/bounds/new.rs:11:1 @@ -49,9 +33,5 @@ warning: technically breaking changes in `def` 11 | pub fn def(_: A) {} | ^^^^^^^^^^^^^^^^^^^^^^ | -note: removed bound: `A: std::clone::Clone` (technically breaking) - --> $REPO_PATH/tests/cases/bounds/old.rs:11:1 - | -11 | pub fn def(_: A) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: removed bound: `A: std::clone::Clone` (technically breaking) diff --git a/tests/cases/inherent_impls/new.rs b/tests/cases/inherent_impls/new.rs index 3ed96db6fa5d2..423749148fb50 100644 --- a/tests/cases/inherent_impls/new.rs +++ b/tests/cases/inherent_impls/new.rs @@ -10,6 +10,11 @@ impl Abc { } fn def(&self) { } + + // TODO + /* pub fn ghi(&self, _: A) -> u8 { + 0 + } */ } #[allow(dead_code)] @@ -17,6 +22,7 @@ pub struct Def { field: A, } +#[allow(dead_code)] impl Def { pub fn def(&self) -> u16 { 0 @@ -27,6 +33,7 @@ impl Def { fn abc2() { } } +#[allow(dead_code)] impl Def { pub fn def(&self) -> u8 { 0 diff --git a/tests/cases/inherent_impls/old.rs b/tests/cases/inherent_impls/old.rs index 6a3e1c66a32b1..3dc7c003f7da8 100644 --- a/tests/cases/inherent_impls/old.rs +++ b/tests/cases/inherent_impls/old.rs @@ -10,6 +10,11 @@ impl Abc { } fn def(&self) { } + + // TODO + /* pub fn ghi(&self, a: A) -> A { + a + } */ } #[allow(dead_code)] @@ -17,12 +22,14 @@ pub struct Def { field: A, } +#[allow(dead_code)] impl Def { pub fn def(&self) -> u8 { 0 } } +#[allow(dead_code)] impl Def { pub fn def(&self) -> u8 { 0 diff --git a/tests/cases/inherent_impls/stdout b/tests/cases/inherent_impls/stdout index e7db35db8c336..a78f5086eb6e6 100644 --- a/tests/cases/inherent_impls/stdout +++ b/tests/cases/inherent_impls/stdout @@ -1,46 +1,46 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 warning: breaking changes in `def` - --> $REPO_PATH/tests/cases/inherent_impls/old.rs:21:5 + --> $REPO_PATH/tests/cases/inherent_impls/old.rs:27:5 | -21 | / pub fn def(&self) -> u8 { -22 | | 0 -23 | | } +27 | / pub fn def(&self) -> u8 { +28 | | 0 +29 | | } | |_____^ | = warning: removed item in inherent impl (breaking) warning: breaking changes in `def` - --> $REPO_PATH/tests/cases/inherent_impls/old.rs:27:5 + --> $REPO_PATH/tests/cases/inherent_impls/old.rs:34:5 | -27 | / pub fn def(&self) -> u8 { -28 | | 0 -29 | | } +34 | / pub fn def(&self) -> u8 { +35 | | 0 +36 | | } | |_____^ | = warning: type error: expected u8, found u16 (breaking) warning: breaking changes in `ghi` - --> $REPO_PATH/tests/cases/inherent_impls/old.rs:31:5 + --> $REPO_PATH/tests/cases/inherent_impls/old.rs:38:5 | -31 | pub fn ghi() { } +38 | pub fn ghi() { } | ^^^^^^^^^^^^^^^^ | = warning: removed item in inherent impl (breaking) warning: technically breaking changes in `abc` - --> $REPO_PATH/tests/cases/inherent_impls/new.rs:25:5 + --> $REPO_PATH/tests/cases/inherent_impls/new.rs:31:5 | -25 | pub fn abc() { } +31 | pub fn abc() { } | ^^^^^^^^^^^^^^^^ | = note: added item in inherent impl (technically breaking) warning: technically breaking changes in `def` - --> $REPO_PATH/tests/cases/inherent_impls/new.rs:31:5 + --> $REPO_PATH/tests/cases/inherent_impls/new.rs:38:5 | -31 | / pub fn def(&self) -> u8 { -32 | | 0 -33 | | } +38 | / pub fn def(&self) -> u8 { +39 | | 0 +40 | | } | |_____^ | = note: added item in inherent impl (technically breaking) From 2b1444eee988fe6d1b40ba8b94eb2cad67429be7 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 6 Aug 2017 13:31:34 +0200 Subject: [PATCH 216/553] Fixed a few small bugs. --- src/semcheck/traverse.rs | 6 ++++++ src/semcheck/typeck.rs | 4 ++++ tests/cases/infer_regress/new.rs | 3 +++ tests/cases/infer_regress/old.rs | 5 +++++ tests/cases/infer_regress/stdout | 17 +++++++++++++++++ tests/dump | 28 ++++++++++++++++++++++++++++ tests/examples.rs | 1 + 7 files changed, 64 insertions(+) create mode 100644 tests/cases/infer_regress/new.rs create mode 100644 tests/cases/infer_regress/old.rs create mode 100644 tests/cases/infer_regress/stdout create mode 100644 tests/dump diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index a8d79569aab89..e03749c846c12 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -801,6 +801,9 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, compcx.check_type_error(tcx, target_def_id, target_param_env, orig, target) { changes.add_change(TypeChanged { error: err }, orig_def_id, None); + + // bail out after a type error + return; } compcx.check_bounds_bidirectional(changes, @@ -944,6 +947,9 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, if let Some(err) = error { changes.add_change(TypeChanged { error: err }, orig_item_def_id, None); + + // bail out after a type error + return true; } compcx.check_bounds_bidirectional(changes, diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs index 0bcc0bfcfd082..ac6d457d16052 100644 --- a/src/semcheck/typeck.rs +++ b/src/semcheck/typeck.rs @@ -205,6 +205,10 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { -> Option>> { use rustc::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); diff --git a/tests/cases/infer_regress/new.rs b/tests/cases/infer_regress/new.rs new file mode 100644 index 0000000000000..188823ab39b6e --- /dev/null +++ b/tests/cases/infer_regress/new.rs @@ -0,0 +1,3 @@ +pub fn abc(_: A) { } + +pub struct Abc(A, ()); diff --git a/tests/cases/infer_regress/old.rs b/tests/cases/infer_regress/old.rs new file mode 100644 index 0000000000000..cad3da0abdbd2 --- /dev/null +++ b/tests/cases/infer_regress/old.rs @@ -0,0 +1,5 @@ +pub fn abc(a: A) -> A { + a +} + +pub struct Abc(A, A); diff --git a/tests/cases/infer_regress/stdout b/tests/cases/infer_regress/stdout new file mode 100644 index 0000000000000..b8b6f296231f0 --- /dev/null +++ b/tests/cases/infer_regress/stdout @@ -0,0 +1,17 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: breaking changes in `abc` + --> $REPO_PATH/tests/cases/infer_regress/new.rs:1:1 + | +1 | pub fn abc(_: A) { } + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected type parameter, found () (breaking) + +warning: breaking changes in `Abc` + --> $REPO_PATH/tests/cases/infer_regress/new.rs:3:1 + | +3 | pub struct Abc(A, ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected type parameter, found () (breaking) + diff --git a/tests/dump b/tests/dump new file mode 100644 index 0000000000000..80277b9de29f9 --- /dev/null +++ b/tests/dump @@ -0,0 +1,28 @@ + we can't use the trait system for inherent impls + you have to basically have a (DefId, AssociatedKind, hir::Name) => Vec map + and manually do what the trait system does for trait impls + namely, generate fresh infer vars for the impl you want to match *against*, substitute that + in its type_of (which is its Self) and then eq the type you want to check against that + if it didn't error, the substs containing infer vars which you substituted in type_of are + the params of the impl which you can then substitute in the associated items' signature + sooo example + old: impl Foo { fn foo() {} } + new: impl Foo { fn foo() {} } + (Foo, Method, "foo") => the one foo method in each + or rather + (old::Foo, Method, "foo") => old::...::foo + (new::Foo, Method, "foo") => new::...::foo + checking if old::...::foo is still valid means translating its "owner" (old::Foo), then + pairing it with the fact that it's a Method and its name, to get (new::Foo, Method, "foo") + which means for each in [new::...::foo] (well it's one element but you get the idea) + you generate fresh substs. in this case T => $1 + substitute, so you get new::Foo<$1> + match that against translate(old::Foo), i.e. new::Foo + that will succeed and leave $1 equal to u8 + which means your substs are now T => u8 + oh I should've given it a signature. image it's -> u8 in old and -> T in new + so the signature of the new method, substituted, is still -> u8 + and when you compare them that will succeed + but if the new method were -> Option then for T => u8 it'd be -> Option which is wrong + and you'd notice the mismatch + it's not that hard as long as you keep your code modular diff --git a/tests/examples.rs b/tests/examples.rs index 767936c50e93a..416b2532ceebd 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -103,6 +103,7 @@ test!(bounds, "tests/cases/bounds"); test!(enums, "tests/cases/enums"); test!(func, "tests/cases/func"); test!(infer, "tests/cases/infer"); +test!(infer_regress, "tests/cases/infer_regress"); test!(inherent_impls, "tests/cases/inherent_impls"); test!(kind_change, "tests/cases/kind_change"); test!(macros, "tests/cases/macros"); From ded88b948837d35675b55a0913662f3c811ba0ca Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 6 Aug 2017 14:02:12 +0200 Subject: [PATCH 217/553] Added bound checking on trait definitions. Closes #23. --- src/semcheck/traverse.rs | 32 +++++++++++++++++++++++++++++--- tests/cases/traits/new.rs | 8 ++++++++ tests/cases/traits/old.rs | 8 ++++++++ tests/cases/traits/stdout | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 3 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index e03749c846c12..6061b61add32d 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -54,7 +54,7 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI diff_types(&mut changes, &id_mapping, tcx, old, new); } - // fourth pass still + // fourth pass on impls diff_inherent_impls(&mut changes, &id_mapping, tcx); diff_trait_impls(&mut changes, &id_mapping, tcx); @@ -655,6 +655,9 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } } }, + Trait(_) => { + cmp_bounds(changes, id_mapping, tcx, old_def_id, new_def_id); + }, _ => (), } } @@ -769,7 +772,7 @@ fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } } -/// Compare two types and possibly register the error. +/// Compare two types and their trait bounds and possibly register the error. fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -777,7 +780,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, target_def_id: DefId, orig: Ty<'tcx>, target: Ty<'tcx>) { - info!("comparing types of {:?} / {:?}:\n {:?} / {:?}", + info!("comparing types and bounds of {:?} / {:?}:\n {:?} / {:?}", orig_def_id, target_def_id, orig, target); tcx.infer_ctxt().enter(|infcx| { @@ -815,6 +818,29 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, }); } +/// Compare two sets of trait bounds and possibly register the error. +fn cmp_bounds<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, '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); + + let orig_substs = Substs::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); + }) +} + /// Compare two implementations and indicate whether the target one is compatible with the /// original one. fn match_trait_impl<'a, 'tcx>(id_mapping: &IdMapping, diff --git a/tests/cases/traits/new.rs b/tests/cases/traits/new.rs index 7928b36be444c..a82c7958369c7 100644 --- a/tests/cases/traits/new.rs +++ b/tests/cases/traits/new.rs @@ -38,3 +38,11 @@ pub trait Ghi { } pub trait Hij { type A; } + +pub trait Klm : Clone { } + +pub trait Nop { } + +pub trait Qrs { } + +pub trait Tuv { } diff --git a/tests/cases/traits/old.rs b/tests/cases/traits/old.rs index 629282cdde257..cf392b4aecfee 100644 --- a/tests/cases/traits/old.rs +++ b/tests/cases/traits/old.rs @@ -36,3 +36,11 @@ pub trait Ghi { } pub trait Hij { } + +pub trait Klm { } + +pub trait Nop : Clone { } + +pub trait Qrs { } + +pub trait Tuv { } diff --git a/tests/cases/traits/stdout b/tests/cases/traits/stdout index ed366282e1a56..887928cfc848d 100644 --- a/tests/cases/traits/stdout +++ b/tests/cases/traits/stdout @@ -124,3 +124,35 @@ warning: added item to trait (breaking) 39 | type A; | ^^^^^^^ +warning: breaking changes in `Klm` + --> $REPO_PATH/tests/cases/traits/new.rs:42:1 + | +42 | pub trait Klm : Clone { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: added bound: `Self: std::clone::Clone` (breaking) + +warning: technically breaking changes in `Nop` + --> $REPO_PATH/tests/cases/traits/new.rs:44:1 + | +44 | pub trait Nop { } + | ^^^^^^^^^^^^^^^^^ + | + = note: removed bound: `Self: std::clone::Clone` (technically breaking) + +warning: breaking changes in `Qrs` + --> $REPO_PATH/tests/cases/traits/new.rs:46:1 + | +46 | pub trait Qrs { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: added bound: `A: std::clone::Clone` (breaking) + +warning: technically breaking changes in `Tuv` + --> $REPO_PATH/tests/cases/traits/new.rs:48:1 + | +48 | pub trait Tuv { } + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: removed bound: `A: std::clone::Clone` (technically breaking) + From bc474014d582cea08f156bc6e519bbdb28ace8a3 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 6 Aug 2017 14:18:06 +0200 Subject: [PATCH 218/553] Made bound loosening on trait definitions breaking. The rationale is that either trait implementations could rely on bounds being present. Removing them breaks the implementation. --- src/semcheck/changes.rs | 12 +++++++++--- src/semcheck/traverse.rs | 3 +++ src/semcheck/typeck.rs | 2 ++ tests/cases/traits/stdout | 8 ++++---- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index e305f18d8a88e..8636b05971bf6 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -207,7 +207,7 @@ pub enum ChangeType<'tcx> { /// An item's bounds have been tightened. BoundsTightened { pred: Predicate<'tcx> }, /// An item's bounds have been loosened. - BoundsLoosened { pred: Predicate<'tcx> }, + BoundsLoosened { pred: Predicate<'tcx>, trait_def: bool }, /// A trait impl has been specialized or removed for some types. TraitImplTightened, /// A trait impl has been generalized or newly added for some types. @@ -244,12 +244,13 @@ impl<'tcx> ChangeType<'tcx> { TraitItemRemoved { .. } | TraitUnsafetyChanged { .. } | BoundsTightened { .. } | + BoundsLoosened { trait_def: true, .. } | TraitImplTightened | AssociatedItemRemoved | Unknown => Breaking, MethodSelfChanged { now_self: true } | TraitItemAdded { defaulted: true } | - BoundsLoosened { .. } | + BoundsLoosened { trait_def: false, .. } | TraitImplLoosened | AssociatedItemAdded | ItemMadePublic => TechnicallyBreaking, @@ -309,7 +310,12 @@ impl<'a> fmt::Display for ChangeType<'a> { 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 } => return write!(f, "removed 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", diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 6061b61add32d..419fe49c68e2a 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -811,6 +811,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, compcx.check_bounds_bidirectional(changes, tcx, + false, orig_def_id, target_def_id, orig_substs, @@ -834,6 +835,7 @@ fn cmp_bounds<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, compcx.check_bounds_bidirectional(changes, tcx, + true, orig_def_id, target_def_id, orig_substs, @@ -980,6 +982,7 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, compcx.check_bounds_bidirectional(changes, tcx, + false, orig_item_def_id, target_item_def_id, orig_substs, diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs index ac6d457d16052..6845f69bcae38 100644 --- a/src/semcheck/typeck.rs +++ b/src/semcheck/typeck.rs @@ -230,6 +230,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { pub fn check_bounds_bidirectional<'b, 'tcx2>(&self, changes: &mut ChangeSet<'tcx2>, lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, + trait_def: bool, orig_def_id: DefId, target_def_id: DefId, orig_substs: &Substs<'tcx>, @@ -275,6 +276,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { for err in errors { let err_type = BoundsLoosened { pred: err, + trait_def: trait_def, }; changes.add_change(err_type, orig_def_id, None); diff --git a/tests/cases/traits/stdout b/tests/cases/traits/stdout index 887928cfc848d..8ee8b3c459460 100644 --- a/tests/cases/traits/stdout +++ b/tests/cases/traits/stdout @@ -132,13 +132,13 @@ warning: breaking changes in `Klm` | = warning: added bound: `Self: std::clone::Clone` (breaking) -warning: technically breaking changes in `Nop` +warning: breaking changes in `Nop` --> $REPO_PATH/tests/cases/traits/new.rs:44:1 | 44 | pub trait Nop { } | ^^^^^^^^^^^^^^^^^ | - = note: removed bound: `Self: std::clone::Clone` (technically breaking) + = warning: removed bound on trait definition: `Self: std::clone::Clone` (breaking) warning: breaking changes in `Qrs` --> $REPO_PATH/tests/cases/traits/new.rs:46:1 @@ -148,11 +148,11 @@ warning: breaking changes in `Qrs` | = warning: added bound: `A: std::clone::Clone` (breaking) -warning: technically breaking changes in `Tuv` +warning: breaking changes in `Tuv` --> $REPO_PATH/tests/cases/traits/new.rs:48:1 | 48 | pub trait Tuv { } | ^^^^^^^^^^^^^^^^^^^^ | - = note: removed bound: `A: std::clone::Clone` (technically breaking) + = warning: removed bound on trait definition: `A: std::clone::Clone` (breaking) From 915972fd6eea3a59c2540df9aaadb9907bce3739 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 6 Aug 2017 14:25:35 +0200 Subject: [PATCH 219/553] Improved existing test cases after cleaning regressions. --- tests/cases/inherent_impls/new.rs | 5 ++-- tests/cases/inherent_impls/old.rs | 5 ++-- tests/cases/inherent_impls/stdout | 42 +++++++++++++++++++------------ 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/tests/cases/inherent_impls/new.rs b/tests/cases/inherent_impls/new.rs index 423749148fb50..0b0e506c59d80 100644 --- a/tests/cases/inherent_impls/new.rs +++ b/tests/cases/inherent_impls/new.rs @@ -11,10 +11,9 @@ impl Abc { fn def(&self) { } - // TODO - /* pub fn ghi(&self, _: A) -> u8 { + pub fn ghi(&self, _: A) -> u8 { 0 - } */ + } } #[allow(dead_code)] diff --git a/tests/cases/inherent_impls/old.rs b/tests/cases/inherent_impls/old.rs index 3dc7c003f7da8..26b10adb934eb 100644 --- a/tests/cases/inherent_impls/old.rs +++ b/tests/cases/inherent_impls/old.rs @@ -11,10 +11,9 @@ impl Abc { fn def(&self) { } - // TODO - /* pub fn ghi(&self, a: A) -> A { + pub fn ghi(&self, a: A) -> A { a - } */ + } } #[allow(dead_code)] diff --git a/tests/cases/inherent_impls/stdout b/tests/cases/inherent_impls/stdout index a78f5086eb6e6..68e2875a56331 100644 --- a/tests/cases/inherent_impls/stdout +++ b/tests/cases/inherent_impls/stdout @@ -1,46 +1,56 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: breaking changes in `ghi` + --> $REPO_PATH/tests/cases/inherent_impls/old.rs:14:5 + | +14 | / pub fn ghi(&self, a: A) -> A { +15 | | a +16 | | } + | |_____^ + | + = warning: type error: expected type parameter, found u8 (breaking) + warning: breaking changes in `def` - --> $REPO_PATH/tests/cases/inherent_impls/old.rs:27:5 + --> $REPO_PATH/tests/cases/inherent_impls/old.rs:26:5 | -27 | / pub fn def(&self) -> u8 { -28 | | 0 -29 | | } +26 | / pub fn def(&self) -> u8 { +27 | | 0 +28 | | } | |_____^ | = warning: removed item in inherent impl (breaking) warning: breaking changes in `def` - --> $REPO_PATH/tests/cases/inherent_impls/old.rs:34:5 + --> $REPO_PATH/tests/cases/inherent_impls/old.rs:33:5 | -34 | / pub fn def(&self) -> u8 { -35 | | 0 -36 | | } +33 | / pub fn def(&self) -> u8 { +34 | | 0 +35 | | } | |_____^ | = warning: type error: expected u8, found u16 (breaking) warning: breaking changes in `ghi` - --> $REPO_PATH/tests/cases/inherent_impls/old.rs:38:5 + --> $REPO_PATH/tests/cases/inherent_impls/old.rs:37:5 | -38 | pub fn ghi() { } +37 | pub fn ghi() { } | ^^^^^^^^^^^^^^^^ | = warning: removed item in inherent impl (breaking) warning: technically breaking changes in `abc` - --> $REPO_PATH/tests/cases/inherent_impls/new.rs:31:5 + --> $REPO_PATH/tests/cases/inherent_impls/new.rs:30:5 | -31 | pub fn abc() { } +30 | pub fn abc() { } | ^^^^^^^^^^^^^^^^ | = note: added item in inherent impl (technically breaking) warning: technically breaking changes in `def` - --> $REPO_PATH/tests/cases/inherent_impls/new.rs:38:5 + --> $REPO_PATH/tests/cases/inherent_impls/new.rs:37:5 | -38 | / pub fn def(&self) -> u8 { -39 | | 0 -40 | | } +37 | / pub fn def(&self) -> u8 { +38 | | 0 +39 | | } | |_____^ | = note: added item in inherent impl (technically breaking) From c478d56c77d282ba756b73f0c4c529aba071b42d Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 6 Aug 2017 14:52:08 +0200 Subject: [PATCH 220/553] Clippy cleanup. Modulo false positives, fixed all warnings. --- src/semcheck/traverse.rs | 48 ++++++++++++++++++---------------------- src/semcheck/typeck.rs | 29 ++++++++++++++++++------ 2 files changed, 43 insertions(+), 34 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 419fe49c68e2a..2bc7057ab2066 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -13,6 +13,7 @@ use rustc::hir::def::{CtorKind, Def}; use rustc::hir::def_id::DefId; use rustc::ty::{AssociatedItem, Ty, TyCtxt}; use rustc::ty::subst::{Subst, Substs}; +use rustc::ty::Visibility; use rustc::ty::Visibility::Public; use semcheck::changes::ChangeType::*; @@ -75,8 +76,20 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefId) { + use rustc::middle::cstore::CrateStore; use rustc::hir::def::Def::*; + use std::rc::Rc; + + // get the visibility of the inner item, given the outer item's visibility + fn get_vis(cstore: &Rc, outer_vis: Visibility, def_id: DefId) -> Visibility { + if outer_vis == Public { + cstore.visibility(def_id) + } else { + outer_vis + } + } + let cstore = &tcx.sess.cstore; let mut visited = HashSet::new(); let mut children = NameMapping::default(); @@ -98,16 +111,8 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, (Some(o), Some(n)) => { if let (Mod(o_def_id), Mod(n_def_id)) = (o.def, n.def) { if visited.insert((o_def_id, n_def_id)) { - let o_vis = if old_vis == Public { - cstore.visibility(o_def_id) - } else { - old_vis - }; - let n_vis = if new_vis == Public { - cstore.visibility(n_def_id) - } else { - new_vis - }; + let o_vis = get_vis(cstore, old_vis, o_def_id); + let n_vis = get_vis(cstore, new_vis, n_def_id); if o_vis != n_vis { changes.new_change(o_def_id, @@ -134,16 +139,8 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, let o_def_id = o.def.def_id(); let n_def_id = n.def.def_id(); - let o_vis = if old_vis == Public { - cstore.visibility(o_def_id) - } else { - old_vis - }; - let n_vis = if new_vis == Public { - cstore.visibility(n_def_id) - } else { - new_vis - }; + let o_vis = get_vis(cstore, old_vis, o_def_id); + let n_vis = get_vis(cstore, new_vis, n_def_id); let output = o_vis == Public || n_vis == Public; changes.new_change(o_def_id, @@ -784,7 +781,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, orig_def_id, target_def_id, orig, target); tcx.infer_ctxt().enter(|infcx| { - let compcx = TypeComparisonContext::target_new(&infcx, id_mapping); + let compcx = TypeComparisonContext::target_new(&infcx, id_mapping, false); let orig_substs = Substs::identity_for_item(infcx.tcx, target_def_id); let orig = compcx.forward_trans.translate_item_type(orig_def_id, orig); @@ -811,7 +808,6 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, compcx.check_bounds_bidirectional(changes, tcx, - false, orig_def_id, target_def_id, orig_substs, @@ -828,14 +824,13 @@ fn cmp_bounds<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, info!("comparing bounds of {:?} / {:?}", orig_def_id, target_def_id); tcx.infer_ctxt().enter(|infcx| { - let compcx = TypeComparisonContext::target_new(&infcx, id_mapping); + let compcx = TypeComparisonContext::target_new(&infcx, id_mapping, true); let orig_substs = Substs::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, - true, orig_def_id, target_def_id, orig_substs, @@ -896,10 +891,10 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, tcx.infer_ctxt().enter(|infcx| { let (compcx, register_errors) = if id_mapping.in_old_crate(orig_impl_def_id) { id_mapping.register_current_match(orig_item_def_id, target_item_def_id); - (TypeComparisonContext::target_new(&infcx, id_mapping), true) + (TypeComparisonContext::target_new(&infcx, id_mapping, false), true) } else { id_mapping.register_current_match(target_item_def_id, orig_item_def_id); - (TypeComparisonContext::target_old(&infcx, id_mapping), false) + (TypeComparisonContext::target_old(&infcx, id_mapping, false), false) }; let orig_substs = Substs::identity_for_item(infcx.tcx, target_item_def_id); @@ -982,7 +977,6 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, compcx.check_bounds_bidirectional(changes, tcx, - false, orig_item_def_id, target_item_def_id, orig_substs, diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs index 6845f69bcae38..32cd31295fbd5 100644 --- a/src/semcheck/typeck.rs +++ b/src/semcheck/typeck.rs @@ -94,34 +94,50 @@ pub struct TypeComparisonContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { pub forward_trans: TranslationContext<'a, 'gcx, 'tcx>, /// The translation context translating from target to original items. pub backward_trans: TranslationContext<'a, 'gcx, 'tcx>, + /// Whether we are checking a trait definition. + checking_trait_def: bool, } impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { /// Construct a new context where the original item is old. - pub fn target_new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a IdMapping) -> Self { + pub fn target_new(infcx: &'a InferCtxt<'a, 'gcx, '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) + 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, 'gcx, 'tcx>, id_mapping: &'a IdMapping) -> Self { + pub fn target_old(infcx: &'a InferCtxt<'a, 'gcx, '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) + 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, 'gcx, 'tcx>, id_mapping: &'a IdMapping, forward_trans: TranslationContext<'a, 'gcx, 'tcx>, - backward_trans: TranslationContext<'a, 'gcx, 'tcx>) -> Self { + backward_trans: TranslationContext<'a, 'gcx, 'tcx>, + checking_trait_def: bool) -> Self { TypeComparisonContext { infcx: infcx, id_mapping: id_mapping, folder: InferenceCleanupFolder::new(infcx), forward_trans: forward_trans, backward_trans: backward_trans, + checking_trait_def: checking_trait_def, } } @@ -230,7 +246,6 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { pub fn check_bounds_bidirectional<'b, 'tcx2>(&self, changes: &mut ChangeSet<'tcx2>, lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, - trait_def: bool, orig_def_id: DefId, target_def_id: DefId, orig_substs: &Substs<'tcx>, @@ -276,7 +291,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { for err in errors { let err_type = BoundsLoosened { pred: err, - trait_def: trait_def, + trait_def: self.checking_trait_def, }; changes.add_change(err_type, orig_def_id, None); From 33794027ed8fa43dedfb771eda90c28bc3af74a3 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 6 Aug 2017 17:23:50 +0200 Subject: [PATCH 221/553] Added typechecking to consts and statics. --- src/semcheck/changes.rs | 7 +++++++ src/semcheck/traverse.rs | 15 +++++++++++---- tests/cases/consts/new.rs | 9 +++++++++ tests/cases/consts/old.rs | 9 +++++++++ tests/cases/consts/stdout | 0 tests/cases/pathologic_paths/stdout | 17 ----------------- tests/cases/pub_use/stdout | 1 - tests/examples.rs | 1 + 8 files changed, 37 insertions(+), 22 deletions(-) create mode 100644 tests/cases/consts/new.rs create mode 100644 tests/cases/consts/old.rs create mode 100644 tests/cases/consts/stdout diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 8636b05971bf6..7779e38fb3e17 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -174,6 +174,8 @@ pub enum ChangeType<'tcx> { ItemMadePrivate, /// An item has changed it's kind. KindDifference, + /// A `static` item changed it's mutablity. + StaticMutabilityChanged { now_mut: bool }, /// A region parameter has been added to an item. RegionParameterAdded, /// A region parameter has been removed from an item. @@ -228,6 +230,7 @@ impl<'tcx> ChangeType<'tcx> { match *self { ItemMadePrivate | KindDifference | + StaticMutabilityChanged { now_mut: false } | RegionParameterAdded | RegionParameterRemoved | TypeParameterAdded { defaulted: false } | @@ -254,6 +257,7 @@ impl<'tcx> ChangeType<'tcx> { TraitImplLoosened | AssociatedItemAdded | ItemMadePublic => TechnicallyBreaking, + StaticMutabilityChanged { now_mut: true } | TypeParameterAdded { defaulted: true } | FnConstChanged { now_const: true } => NonBreaking, } @@ -266,6 +270,8 @@ impl<'a> fmt::Display for ChangeType<'a> { 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", RegionParameterAdded => "region parameter added", RegionParameterRemoved => "region parameter removed", TypeParameterAdded { defaulted: true } => "defaulted type parameter added", @@ -387,6 +393,7 @@ impl<'tcx> Change<'tcx> { FnConstChanged { now_const: false } | MethodSelfChanged { now_self: false } | Unknown => return true, + StaticMutabilityChanged { .. } | RegionParameterAdded | MethodSelfChanged { now_self: true } | TraitItemAdded { .. } | diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 2bc7057ab2066..9b7e79a2d7712 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -70,7 +70,6 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI /// 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. -// TODO: clean up and simplify. fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -81,7 +80,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, use std::rc::Rc; - // get the visibility of the inner item, given the outer item's visibility + // Get the visibility of the inner item, given the outer item's visibility. fn get_vis(cstore: &Rc, outer_vis: Visibility, def_id: DefId) -> Visibility { if outer_vis == Public { cstore.visibility(def_id) @@ -173,8 +172,16 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, (Macro(_, _), Macro(_, _)) | (Variant(_), Variant(_)) | (Const(_), Const(_)) | - (Static(_, _), Static(_, _)) | (Err, Err) => {}, + (Static(_, old_mut), Static(_, new_mut)) => { + if old_mut != new_mut { + let change_type = StaticMutabilityChanged { + now_mut: new_mut, + }; + + changes.add_change(change_type, o_def_id, None); + } + }, (Fn(_), Fn(_)) | (Method(_), Method(_)) => { diff_generics(changes, @@ -621,7 +628,7 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } match old { - TyAlias(_) => { + TyAlias(_) | Const(_) | Static(_, _) => { cmp_types(changes, id_mapping, tcx, diff --git a/tests/cases/consts/new.rs b/tests/cases/consts/new.rs new file mode 100644 index 0000000000000..05808e455ae0b --- /dev/null +++ b/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/tests/cases/consts/old.rs b/tests/cases/consts/old.rs new file mode 100644 index 0000000000000..4afed7b450b4a --- /dev/null +++ b/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/tests/cases/consts/stdout b/tests/cases/consts/stdout new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/cases/pathologic_paths/stdout b/tests/cases/pathologic_paths/stdout index 3caab879b7026..e69de29bb2d1d 100644 --- a/tests/cases/pathologic_paths/stdout +++ b/tests/cases/pathologic_paths/stdout @@ -1,17 +0,0 @@ -version bump: 1.0.0 -> (technically breaking) -> 1.1.0 -warning: path changes to `a` - --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:5:21 - | -5 | pub mod a { blow!($($rest)*); } - | ^^^^^^^^^^^^^^^^^^^ - | - = note: added definition (technically breaking) - -warning: path changes to `b` - --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:6:21 - | -6 | pub mod b { pub use super::a::*; } - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: added definition (technically breaking) - diff --git a/tests/cases/pub_use/stdout b/tests/cases/pub_use/stdout index f8c2af4c949b7..e69de29bb2d1d 100644 --- a/tests/cases/pub_use/stdout +++ b/tests/cases/pub_use/stdout @@ -1 +0,0 @@ -version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/tests/examples.rs b/tests/examples.rs index 416b2532ceebd..1bf892ca995ed 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -100,6 +100,7 @@ test!(addition, "tests/cases/addition"); test!(addition_path, "tests/cases/addition_path"); test!(addition_use, "tests/cases/addition_use"); test!(bounds, "tests/cases/bounds"); +test!(consts, "tests/cases/consts"); test!(enums, "tests/cases/enums"); test!(func, "tests/cases/func"); test!(infer, "tests/cases/infer"); From 603da57aa4390dd4de727413833ed86e669b0a9b Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 6 Aug 2017 17:31:17 +0200 Subject: [PATCH 222/553] Fixed visible/invisible change bug. Non-reported changes (that is, changes to private items) were used to compute the change category maximum. This is now fixed. --- src/semcheck/changes.rs | 3 ++- tests/cases/max_priv/new.rs | 2 ++ tests/cases/max_priv/old.rs | 2 ++ tests/cases/max_priv/stdout | 1 + tests/examples.rs | 1 + 5 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 tests/cases/max_priv/new.rs create mode 100644 tests/cases/max_priv/old.rs create mode 100644 tests/cases/max_priv/stdout diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 7779e38fb3e17..e33a3f924bd15 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -537,7 +537,7 @@ impl<'tcx> ChangeSet<'tcx> { pub fn add_change(&mut self, type_: ChangeType<'tcx>, old: DefId, span: Option) { let cat = type_.to_category(); - if cat > self.max { + if cat > self.max && self.get_output(old) { self.max = cat.clone(); } @@ -551,6 +551,7 @@ impl<'tcx> ChangeSet<'tcx> { /// Set up reporting for the changes associated with a given `DefId`. pub fn set_output(&mut self, old: DefId) { + // FIXME: possibly recompute the maximum change category too (just to be safe). self.changes.get_mut(&old).map(|change| change.output = true); } diff --git a/tests/cases/max_priv/new.rs b/tests/cases/max_priv/new.rs new file mode 100644 index 0000000000000..5fee028301763 --- /dev/null +++ b/tests/cases/max_priv/new.rs @@ -0,0 +1,2 @@ +#[allow(dead_code)] +const A: u16 = 0; diff --git a/tests/cases/max_priv/old.rs b/tests/cases/max_priv/old.rs new file mode 100644 index 0000000000000..60c0e3ce84f2e --- /dev/null +++ b/tests/cases/max_priv/old.rs @@ -0,0 +1,2 @@ +#[allow(dead_code)] +const A: u8 = 0; diff --git a/tests/cases/max_priv/stdout b/tests/cases/max_priv/stdout new file mode 100644 index 0000000000000..f8c2af4c949b7 --- /dev/null +++ b/tests/cases/max_priv/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/tests/examples.rs b/tests/examples.rs index 1bf892ca995ed..859e010c5abde 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -108,6 +108,7 @@ test!(infer_regress, "tests/cases/infer_regress"); test!(inherent_impls, "tests/cases/inherent_impls"); test!(kind_change, "tests/cases/kind_change"); test!(macros, "tests/cases/macros"); +test!(max_priv, "tests/cases/max_priv"); test!(mix, "tests/cases/mix"); test!(pathologic_paths, "tests/cases/pathologic_paths"); test!(pub_use, "tests/cases/pub_use"); From a2c78874f3687cb8d4c60459e992495bdd6d8671 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 6 Aug 2017 17:49:29 +0200 Subject: [PATCH 223/553] Fixed tests after a user error and improved change handling. --- src/semcheck/changes.rs | 22 +++++++++++++------ tests/cases/consts/stdout | 33 +++++++++++++++++++++++++++++ tests/cases/pathologic_paths/stdout | 17 +++++++++++++++ tests/cases/pub_use/stdout | 1 + 4 files changed, 67 insertions(+), 6 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index e33a3f924bd15..e76acfabcced8 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -31,7 +31,7 @@ use syntax_pos::Span; /// exotic and/or unlikely scenarios. /// /// [1]: https://github.com/rust-lang/rfcs/blob/master/text/1105-api-evolution.md -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum ChangeCategory { /// Patch change - no change to the public API of a crate. Patch, @@ -416,7 +416,7 @@ impl<'tcx> Change<'tcx> { /// Get the change's category. fn to_category(&self) -> ChangeCategory { - self.max.clone() + self.max } /// Get the new span of the change item. @@ -512,7 +512,7 @@ impl<'tcx> ChangeSet<'tcx> { let cat = if add { TechnicallyBreaking } else { Breaking }; if cat > self.max { - self.max = cat.clone(); + self.max = cat; } self.path_changes.get_mut(&old).unwrap().insert(span, add); @@ -538,7 +538,7 @@ impl<'tcx> ChangeSet<'tcx> { let cat = type_.to_category(); if cat > self.max && self.get_output(old) { - self.max = cat.clone(); + self.max = cat; } self.changes.get_mut(&old).unwrap().insert(type_, span); @@ -551,8 +551,18 @@ impl<'tcx> ChangeSet<'tcx> { /// Set up reporting for the changes associated with a given `DefId`. pub fn set_output(&mut self, old: DefId) { - // FIXME: possibly recompute the maximum change category too (just to be safe). - self.changes.get_mut(&old).map(|change| change.output = true); + let max = &mut self.max; + self.changes + .get_mut(&old) + .map(|change| { + 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. diff --git a/tests/cases/consts/stdout b/tests/cases/consts/stdout index e69de29bb2d1d..ade8d64178667 100644 --- a/tests/cases/consts/stdout +++ b/tests/cases/consts/stdout @@ -0,0 +1,33 @@ +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: breaking changes in `A` + --> $REPO_PATH/tests/cases/consts/new.rs:1:1 + | +1 | pub const A: u16 = 0; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected u8, found u16 (breaking) + +warning: breaking changes in `B` + --> $REPO_PATH/tests/cases/consts/new.rs:3:1 + | +3 | pub static B: u16 = 1; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected u8, found u16 (breaking) + +warning: breaking changes in `D` + --> $REPO_PATH/tests/cases/consts/new.rs:7:1 + | +7 | pub static D: bool = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: static item made immutable (breaking) + +warning: non-breaking changes in `E` + --> $REPO_PATH/tests/cases/consts/new.rs:9:1 + | +9 | pub static mut E: bool = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: static item made mutable (non-breaking) + diff --git a/tests/cases/pathologic_paths/stdout b/tests/cases/pathologic_paths/stdout index e69de29bb2d1d..3caab879b7026 100644 --- a/tests/cases/pathologic_paths/stdout +++ b/tests/cases/pathologic_paths/stdout @@ -0,0 +1,17 @@ +version bump: 1.0.0 -> (technically breaking) -> 1.1.0 +warning: path changes to `a` + --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:5:21 + | +5 | pub mod a { blow!($($rest)*); } + | ^^^^^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + +warning: path changes to `b` + --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:6:21 + | +6 | pub mod b { pub use super::a::*; } + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + diff --git a/tests/cases/pub_use/stdout b/tests/cases/pub_use/stdout index e69de29bb2d1d..f8c2af4c949b7 100644 --- a/tests/cases/pub_use/stdout +++ b/tests/cases/pub_use/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (patch) -> 1.0.1 From 415e5af4c5f767583e8de6f72b6dcf63d0a17338 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 6 Aug 2017 20:03:23 +0200 Subject: [PATCH 224/553] Cleanup and explanatory comments. --- src/semcheck/changes.rs | 1 + src/semcheck/mapping.rs | 19 ------- src/semcheck/traverse.rs | 104 ++++++++++++++++++++++++++------------- 3 files changed, 70 insertions(+), 54 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index e76acfabcced8..6706bf41ea356 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -879,6 +879,7 @@ pub mod tests { let max = changes .iter() + .filter(|change| change.4) .flat_map(|change| change.5.iter()) .map(|&(ref type_, _)| type_.inner().to_category()) .max() diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 41686d1caa075..238df334073cb 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -7,7 +7,6 @@ use rustc::hir::def::{Def, Export}; use rustc::hir::def_id::{CrateNum, DefId}; use rustc::ty::{AssociatedKind, TypeParameterDef}; -use std::cell::Cell; use std::collections::{BTreeSet, HashMap, HashSet, VecDeque}; use syntax::ast::Name; @@ -53,8 +52,6 @@ pub struct IdMapping { type_params: HashMap, /// Map of items from inherent impls' descriptors to the impls they are declared in. inherent_items: HashMap, - /// A match that has been just found and needs to be temporarily added to the mapping. - current_match: Cell>, } impl IdMapping { @@ -71,7 +68,6 @@ impl IdMapping { reverse_mapping: HashMap::new(), type_params: HashMap::new(), inherent_items: HashMap::new(), - current_match: Cell::new(None), } } @@ -180,12 +176,6 @@ impl IdMapping { Some(new.1.def_id()) } else if let Some(new_def_id) = self.internal_mapping.get(&old) { Some(*new_def_id) - } else if let Some(def_id_pair) = self.current_match.get() { - if def_id_pair.0 == old { - Some(def_id_pair.1) - } else { - None - } } else { None } @@ -202,10 +192,6 @@ impl IdMapping { self.reverse_mapping .get(&new) .cloned() - .or_else(|| - self.current_match - .get() - .and_then(|p| if p.1 == new { Some(p.0) } else { None })) } else { Some(new) } @@ -228,11 +214,6 @@ impl IdMapping { self.reverse_mapping.contains_key(&new) } - /// Temporarily register a `DefId` pair. - pub fn register_current_match(&self, old: DefId, new: DefId) { - self.current_match.set(Some((old, new))); - } - /// Construct a queue of toplevel item pairs' `DefId`s. pub fn toplevel_queue(&self) -> VecDeque<(DefId, DefId)> { self.toplevel_mapping diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 9b7e79a2d7712..9f199940bb0c2 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -99,14 +99,17 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, 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(cstore.item_children(old_def_id, tcx.sess), cstore.item_children(new_def_id, tcx.sess)); for items in children.drain() { match items { + // an item pair is found (Some(o), Some(n)) => { if let (Mod(o_def_id), Mod(n_def_id)) = (o.def, n.def) { if visited.insert((o_def_id, n_def_id)) { @@ -121,6 +124,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, tcx.def_span(n_def_id), true); + // FIXME: simplify these conditions ;) if o_vis == Public && n_vis != Public { changes.add_change(ItemMadePrivate, o_def_id, None); } else if o_vis != Public && n_vis == Public { @@ -156,7 +160,12 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, } match (o.def, n.def) { - // (matching) things we don't care about (for now) + // matching items we don't care about because they are either + // impossible to encounter at this stage (Mod, AssociatedTy, PrimTy, + // TyParam, SelfTy, StructCtor, VariantCtor, AssociatedConst, Local, + // Upvar, Label, Variant, Err), whose analysis is out scope for us + // (GlobalAsm, Macro), or which don't requite further analysis at + // this stage (Const) (Mod(_), Mod(_)) | (AssociatedTy(_), AssociatedTy(_)) | (PrimTy(_), PrimTy(_)) | @@ -173,6 +182,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, (Variant(_), Variant(_)) | (Const(_), Const(_)) | (Err, Err) => {}, + // statics are subject to mutability comparison (Static(_, old_mut), Static(_, new_mut)) => { if old_mut != new_mut { let change_type = StaticMutabilityChanged { @@ -182,6 +192,8 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, changes.add_change(change_type, o_def_id, None); } }, + // functions can declare generics and have structural properties + // that need to be compared (Fn(_), Fn(_)) | (Method(_), Method(_)) => { diff_generics(changes, @@ -192,6 +204,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, n_def_id); diff_fn(changes, tcx, o.def, n.def); }, + // type aliases can declare generics, too (TyAlias(_), TyAlias(_)) => { diff_generics(changes, id_mapping, @@ -200,6 +213,9 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, 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(_)) => { @@ -211,6 +227,9 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, n_def_id); diff_adts(changes, id_mapping, tcx, o.def, n.def); }, + // 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(_)) => { diff_generics(changes, id_mapping, @@ -225,13 +244,15 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, n_def_id, output); }, - // non-matching item pair - register the difference and abort + // a non-matching item pair - register the change and abort further + // analysis _ => { changes.add_change(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 StructCtor(_, _) = o.def { @@ -245,6 +266,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, removals.push(o); } } + // only a new item is found (None, Some(n)) => { // struct constructors are weird/hard - let's go shopping! if let StructCtor(_, _) = n.def { @@ -327,7 +349,7 @@ fn diff_method(changes: &mut ChangeSet, tcx: TyCtxt, old: AssociatedItem, new: A /// 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. +/// struct- and enum fields etc. fn diff_adts(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, @@ -596,8 +618,7 @@ fn diff_generics(changes: &mut ChangeSet, } // Below functions constitute the third pass of analysis, in which parameter bounds of matching -// items are compared for changes and used to determine matching relationships between items not -// being exported. +// items are used to determine matching relationships between items not being exported. /// Given two items, compare the bounds on their type and region parameters. fn diff_bounds<'a, 'tcx>(_changes: &mut ChangeSet, @@ -607,8 +628,8 @@ fn diff_bounds<'a, 'tcx>(_changes: &mut ChangeSet, _new: Def) { } -// Below functions constitute the fourth and last pass of analysis, in which the types of -// matching items are compared for changes. +// Below functions constitute the fourth and last 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<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, @@ -621,6 +642,7 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, 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)) { @@ -628,6 +650,7 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } match old { + // type aliases, consts and statics just need their type to be checked TyAlias(_) | Const(_) | Static(_, _) => { cmp_types(changes, id_mapping, @@ -637,6 +660,7 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, tcx.type_of(old_def_id), tcx.type_of(new_def_id)); }, + // functions and methods require us to compare their signatures, not types Fn(_) | Method(_) => { 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); @@ -649,6 +673,7 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, tcx.mk_fn_ptr(old_fn_sig), tcx.mk_fn_ptr(new_fn_sig)); }, + // ADTs' types are compared field-wise Struct(_) | Enum(_) | Union(_) => { if let Some(children) = id_mapping.children_of(old_def_id) { for (o_def_id, n_def_id) in children { @@ -659,6 +684,7 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } } }, + // a trait definition has no type, so only it's trait bounds are compared Trait(_) => { cmp_bounds(changes, id_mapping, tcx, old_def_id, new_def_id); }, @@ -666,7 +692,7 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } } -/// Compare the inherent implementations of items. +/// Compare the inherent implementations of all matching items. fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>) { @@ -674,6 +700,7 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, 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, AssociatedItemRemoved) @@ -683,8 +710,10 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, 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); @@ -696,6 +725,7 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, 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)) @@ -706,6 +736,7 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, 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)| { @@ -724,6 +755,7 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, target_assoc_item) }); + // otherwise, it has been essentially added/removed if !match_found { changes.add_change(err_type.clone(), orig_item_def_id, None); } @@ -731,24 +763,26 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } } -/// Compare the implementations of traits. +/// Compare the implementations of all matching traits. fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>) { let all_impls = tcx.sess.cstore.implementations_of_trait(None); + // for each trait impl in the old crate, ... for old_impl_def_id in all_impls.iter().filter(|&did| id_mapping.in_old_crate(*did)) { let old_trait_def_id = tcx.impl_trait_ref(*old_impl_def_id).unwrap().def_id; if id_mapping.get_new_id(old_trait_def_id).is_none() { continue; } + // ... try to match it with a new counterpart if !match_trait_impl(id_mapping, tcx, *old_impl_def_id) { let impl_span = tcx.def_span(*old_impl_def_id); changes.new_change(*old_impl_def_id, *old_impl_def_id, - Symbol::intern("impl"), + Symbol::intern("impl"), // FIXME: find something more fitting impl_span, impl_span, true); @@ -756,18 +790,20 @@ fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } } + // for each trait impl in the new crate, ... for new_impl_def_id in all_impls.iter().filter(|&did| id_mapping.in_new_crate(*did)) { let new_trait_def_id = tcx.impl_trait_ref(*new_impl_def_id).unwrap().def_id; if id_mapping.get_old_id(new_trait_def_id).is_none() { continue; } + // ... try to match it with an old counterpart if !match_trait_impl(id_mapping, tcx, *new_impl_def_id) { let impl_span = tcx.def_span(*new_impl_def_id); changes.new_change(*new_impl_def_id, *new_impl_def_id, - Symbol::intern("impl"), + Symbol::intern("impl"), // FIXME: find something more fitting impl_span, impl_span, true); @@ -776,7 +812,7 @@ fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } } -/// Compare two types and their trait bounds and possibly register the error. +/// Compare two types and their trait bounds, possibly registering the resulting change. fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -794,6 +830,7 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, 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 { @@ -808,21 +845,19 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, compcx.check_type_error(tcx, target_def_id, target_param_env, orig, target) { changes.add_change(TypeChanged { error: err }, orig_def_id, None); - - // bail out after a type error - return; + } 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); } - - compcx.check_bounds_bidirectional(changes, - tcx, - orig_def_id, - target_def_id, - orig_substs, - target_substs); }); } -/// Compare two sets of trait bounds and possibly register the error. +/// Compare the trait bounds of two items, possibly registering the resulting change. fn cmp_bounds<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -897,10 +932,10 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, tcx.infer_ctxt().enter(|infcx| { let (compcx, register_errors) = if id_mapping.in_old_crate(orig_impl_def_id) { - id_mapping.register_current_match(orig_item_def_id, target_item_def_id); + // id_mapping.register_current_match(orig_item_def_id, target_item_def_id); (TypeComparisonContext::target_new(&infcx, id_mapping, false), true) } else { - id_mapping.register_current_match(target_item_def_id, orig_item_def_id); + // id_mapping.register_current_match(target_item_def_id, orig_item_def_id); (TypeComparisonContext::target_old(&infcx, id_mapping, false), false) }; @@ -950,6 +985,7 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, 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) { (AssociatedKind::Const, AssociatedKind::Const) | (AssociatedKind::Type, AssociatedKind::Type) => { @@ -977,18 +1013,16 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, if let Some(err) = error { changes.add_change(TypeChanged { error: err }, orig_item_def_id, None); - - // bail out after a type error - return true; + } 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); } - compcx.check_bounds_bidirectional(changes, - tcx, - orig_item_def_id, - target_item_def_id, - orig_substs, - target_substs); - true }) } From 0e95d42b1f2ac8453136df135a229bd570f12df1 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 6 Aug 2017 20:18:39 +0200 Subject: [PATCH 225/553] Simplified some bits further. --- src/bin/cargo_semver.rs | 2 ++ src/semcheck/mismatch.rs | 13 ++++++------- src/semcheck/translate.rs | 18 +++++------------- src/semcheck/traverse.rs | 4 ++-- 4 files changed, 15 insertions(+), 22 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 791f3bce2abf1..5ffe63caba99d 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -95,6 +95,8 @@ impl<'a> WorkInfo<'a> { fn remote(config: &'a Config, source: &mut SourceInfo<'a>, info: NameAndVersion) -> CargoResult> { + // TODO: fall back to locally cached package instance, or better yet, search for it + // first. let package_id = PackageId::new(info.name, info.version, &source.id)?; let package = source.registry.download(&package_id)?; let workspace = Workspace::ephemeral(package.clone(), config, None, false)?; diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 856d7985203fc..4f6bd42d190fe 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -20,7 +20,7 @@ use std::collections::{HashMap, VecDeque}; /// 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. -pub struct Mismatch<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { +pub struct MismatchRelation<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { /// The type context used. tcx: TyCtxt<'a, 'gcx, 'tcx>, /// The queue to append found item pairings. @@ -29,12 +29,11 @@ pub struct Mismatch<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { id_mapping: &'a mut IdMapping, } -impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> Mismatch<'a, 'gcx, 'tcx> { +impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> MismatchRelation<'a, 'gcx, 'tcx> { /// Construct a new mismtach type relation. - pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a mut IdMapping) - -> Mismatch<'a, 'gcx, 'tcx> + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a mut IdMapping) -> Self { - Mismatch { + MismatchRelation { tcx: tcx, item_queue: id_mapping.toplevel_queue(), id_mapping: id_mapping, @@ -69,7 +68,7 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> Mismatch<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, 'tcx> { fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.tcx } @@ -184,7 +183,7 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Mismatch<'a, 'gcx, 'tcx> { }, (&TyInfer(_), _) | (_, &TyInfer(_)) => { // As the original function this is ripped off of, we don't handle these cases. - panic!("var types encountered in Mismatch::tys") + panic!("var types encountered in MismatchRelation::tys") }, _ => None, }; diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 39e3585a9da47..35b5c69393960 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -32,12 +32,8 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { tcx: tcx, id_mapping: id_mapping, translate_params: translate_params, - needs_translation: |id_mapping, orig_def_id| { - id_mapping.in_old_crate(orig_def_id) - }, - translate_orig: |id_mapping, orig_def_id| { - id_mapping.get_new_id(orig_def_id) - }, + needs_translation: IdMapping::in_old_crate, + translate_orig: IdMapping::get_new_id, } } @@ -49,12 +45,8 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { tcx: tcx, id_mapping: id_mapping, translate_params: translate_params, - needs_translation: |id_mapping, orig_def_id| { - id_mapping.in_new_crate(orig_def_id) - }, - translate_orig: |id_mapping, orig_def_id| { - id_mapping.get_old_id(orig_def_id) - }, + needs_translation: IdMapping::in_new_crate, + translate_orig: IdMapping::get_old_id, } } @@ -243,7 +235,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { } }, TyParam(param) => { - // TODO: we should check `has_self`! + // FIXME: we should check `has_self` if this gets used again! if param.idx != 0 && self.translate_params { // `Self` is special let orig_def_id = index_map[¶m.idx]; if self.needs_translation(orig_def_id) { diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 9f199940bb0c2..695dc6584807e 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -19,7 +19,7 @@ use rustc::ty::Visibility::Public; use semcheck::changes::ChangeType::*; use semcheck::changes::ChangeSet; use semcheck::mapping::{IdMapping, NameMapping}; -use semcheck::mismatch::Mismatch; +use semcheck::mismatch::MismatchRelation; use semcheck::translate::TranslationContext; use semcheck::typeck::{BoundContext, TypeComparisonContext}; @@ -41,7 +41,7 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI // second pass { - let mut mismatch = Mismatch::new(tcx, &mut id_mapping); + let mut mismatch = MismatchRelation::new(tcx, &mut id_mapping); mismatch.process(); } From 3b93bd426087009b168008feba8b2db91875d6d0 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 7 Aug 2017 00:01:53 +0200 Subject: [PATCH 226/553] Implemented nicer change represenatation for trait impls. --- src/semcheck/changes.rs | 39 +++++++++++++++++++++++++++++----- src/semcheck/traverse.rs | 20 ++++++----------- tests/cases/trait_impls/stdout | 12 +++++------ 3 files changed, 46 insertions(+), 25 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 6706bf41ea356..4595ef109227d 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -64,6 +64,25 @@ impl<'a> fmt::Display for ChangeCategory { } } +/// Different ways to refer to a changed item. +pub enum Name { + /// The changed item's name. + Symbol(Symbol), + /// A textutal description of the item, used for trait impls. + ImplDesc(String), +} + +impl<'a> fmt::Display for Name { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Name::Symbol(name) => write!(f, "`{}`", name), + Name::ImplDesc(ref desc) => { + write!(f, "`{}`", desc) + }, + } + } +} + /// A change record of newly introduced or removed paths to an item. /// /// It is important to note that the `Eq` and `Ord` instances are constucted to only regard the @@ -343,7 +362,7 @@ pub struct Change<'tcx> { /// The most severe change category already recorded for the item. max: ChangeCategory, /// The name of the item. - name: Symbol, + name: Name, /// The new definition span of the item. new_span: Span, /// Whether to output changes. Used to distinguish all-private items. @@ -352,7 +371,7 @@ pub struct Change<'tcx> { impl<'tcx> Change<'tcx> { /// Construct a new empty change record for an item. - fn new(name: Symbol, span: Span, output: bool) -> Change<'tcx> { + fn new(name: Name, span: Span, output: bool) -> Change<'tcx> { Change { changes: Vec::new(), max: ChangeCategory::default(), @@ -430,7 +449,7 @@ impl<'tcx> Change<'tcx> { return; } - let msg = format!("{} changes in `{}`", self.max, self.name); + let msg = format!("{} changes in {}", self.max, self.name); let mut builder = session.struct_span_warn(self.new_span, &msg); for change in &self.changes { @@ -526,13 +545,23 @@ impl<'tcx> ChangeSet<'tcx> { old_span: Span, new_span: Span, output: bool) { - let change = Change::new(name, new_span, output); + 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); } + pub fn new_change_impl(&mut self, + def_id: DefId, + desc: String, + span: Span) { + let change = Change::new(Name::ImplDesc(desc), span, true); + + self.spans.insert(span, def_id); + self.changes.insert(def_id, change); + } + /// Add a new change to an already existing entry. pub fn add_change(&mut self, type_: ChangeType<'tcx>, old: DefId, span: Option) { let cat = type_.to_category(); @@ -763,7 +792,7 @@ pub mod tests { -> Change<'a> { let mut interner = Interner::new(); - let mut change = Change::new(interner.intern("test"), s1, output); + let mut change = Change::new(Name::Symbol(interner.intern("test")), s1, output); for (type_, span) in changes.drain(..) { change.insert(type_.inner(), span.map(|s| s.inner())); diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 695dc6584807e..886f21fff675b 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -25,8 +25,6 @@ use semcheck::typeck::{BoundContext, TypeComparisonContext}; use std::collections::{BTreeMap, HashSet, VecDeque}; -use syntax::symbol::Symbol; - /// The main entry point to our analysis passes. /// /// Set up the necessary data structures and run the analysis passes. @@ -780,12 +778,9 @@ fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, if !match_trait_impl(id_mapping, tcx, *old_impl_def_id) { let impl_span = tcx.def_span(*old_impl_def_id); - changes.new_change(*old_impl_def_id, - *old_impl_def_id, - Symbol::intern("impl"), // FIXME: find something more fitting - impl_span, - impl_span, - true); + changes.new_change_impl(*old_impl_def_id, + tcx.item_path_str(*old_impl_def_id), + impl_span); changes.add_change(TraitImplTightened, *old_impl_def_id, None); } } @@ -801,12 +796,9 @@ fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, if !match_trait_impl(id_mapping, tcx, *new_impl_def_id) { let impl_span = tcx.def_span(*new_impl_def_id); - changes.new_change(*new_impl_def_id, - *new_impl_def_id, - Symbol::intern("impl"), // FIXME: find something more fitting - impl_span, - impl_span, - true); + changes.new_change_impl(*new_impl_def_id, + tcx.item_path_str(*new_impl_def_id), + impl_span); changes.add_change(TraitImplLoosened, *new_impl_def_id, None); } } diff --git a/tests/cases/trait_impls/stdout b/tests/cases/trait_impls/stdout index 1c2996a431ac5..b8cf65677c73b 100644 --- a/tests/cases/trait_impls/stdout +++ b/tests/cases/trait_impls/stdout @@ -1,5 +1,5 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 -warning: breaking changes in `impl` +warning: breaking changes in ` as old::Abc>` --> $REPO_PATH/tests/cases/trait_impls/old.rs:9:1 | 9 | impl Abc for Vec { } @@ -7,7 +7,7 @@ warning: breaking changes in `impl` | = warning: trait impl specialized or removed (breaking) -warning: breaking changes in `impl` +warning: breaking changes in `` --> $REPO_PATH/tests/cases/trait_impls/old.rs:11:1 | 11 | / impl Clone for Def { @@ -19,7 +19,7 @@ warning: breaking changes in `impl` | = warning: trait impl specialized or removed (breaking) -warning: technically breaking changes in `impl` +warning: technically breaking changes in ` as new::Abc>` --> $REPO_PATH/tests/cases/trait_impls/new.rs:11:1 | 11 | impl Abc for Box { } @@ -27,7 +27,7 @@ warning: technically breaking changes in `impl` | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in `impl` +warning: technically breaking changes in ` as new::Abc>` --> $REPO_PATH/tests/cases/trait_impls/new.rs:13:1 | 13 | impl Abc for Box { } @@ -35,7 +35,7 @@ warning: technically breaking changes in `impl` | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in `impl` +warning: technically breaking changes in `<() as new::Abc>` --> $REPO_PATH/tests/cases/trait_impls/new.rs:15:1 | 15 | impl Abc for () { } @@ -43,7 +43,7 @@ warning: technically breaking changes in `impl` | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in `impl` +warning: technically breaking changes in ` as new::Abc>` --> $REPO_PATH/tests/cases/trait_impls/new.rs:17:1 | 17 | impl Abc for Cell<(bool, T)> { } From 638e8c74a9f87e41b6ed9c9a08ad1730933465e6 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 7 Aug 2017 13:08:01 +0200 Subject: [PATCH 227/553] Deduplicated trait impl matching. --- src/semcheck/translate.rs | 5 ++++ src/semcheck/traverse.rs | 57 +++++++++++++++------------------------ 2 files changed, 26 insertions(+), 36 deletions(-) diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 35b5c69393960..54a77d06904ab 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -422,6 +422,11 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { 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() + } } #[derive(Clone)] diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 886f21fff675b..2656e6d99161a 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -765,41 +765,32 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let all_impls = tcx.sess.cstore.implementations_of_trait(None); + let to_new = TranslationContext::target_new(tcx, id_mapping, false); + let to_old = TranslationContext::target_old(tcx, id_mapping, false); - // for each trait impl in the old crate, ... - for old_impl_def_id in all_impls.iter().filter(|&did| id_mapping.in_old_crate(*did)) { - let old_trait_def_id = tcx.impl_trait_ref(*old_impl_def_id).unwrap().def_id; - if id_mapping.get_new_id(old_trait_def_id).is_none() { - continue; - } + let all_impls = tcx.sess.cstore.implementations_of_trait(None); - // ... try to match it with a new counterpart - if !match_trait_impl(id_mapping, tcx, *old_impl_def_id) { - let impl_span = tcx.def_span(*old_impl_def_id); + for orig_impl_def_id in all_impls.iter() { + let orig_trait_def_id = tcx.impl_trait_ref(*orig_impl_def_id).unwrap().def_id; - changes.new_change_impl(*old_impl_def_id, - tcx.item_path_str(*old_impl_def_id), - impl_span); - changes.add_change(TraitImplTightened, *old_impl_def_id, None); - } - } + let (forward_trans, err_type) = + if id_mapping.in_old_crate(*orig_impl_def_id) { + (&to_new, TraitImplTightened) + } else if id_mapping.in_new_crate(*orig_impl_def_id) { + (&to_old, TraitImplLoosened) + } else { + continue + }; - // for each trait impl in the new crate, ... - for new_impl_def_id in all_impls.iter().filter(|&did| id_mapping.in_new_crate(*did)) { - let new_trait_def_id = tcx.impl_trait_ref(*new_impl_def_id).unwrap().def_id; - if id_mapping.get_old_id(new_trait_def_id).is_none() { + if !forward_trans.can_translate(orig_trait_def_id) { continue; } - // ... try to match it with an old counterpart - if !match_trait_impl(id_mapping, tcx, *new_impl_def_id) { - let impl_span = tcx.def_span(*new_impl_def_id); - - changes.new_change_impl(*new_impl_def_id, - tcx.item_path_str(*new_impl_def_id), - impl_span); - changes.add_change(TraitImplLoosened, *new_impl_def_id, None); + if !match_trait_impl(tcx, forward_trans, *orig_impl_def_id) { + changes.new_change_impl(*orig_impl_def_id, + tcx.item_path_str(*orig_impl_def_id), + tcx.def_span(*orig_impl_def_id)); + changes.add_change(err_type, *orig_impl_def_id, None); } } } @@ -874,15 +865,9 @@ fn cmp_bounds<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, /// Compare two implementations and indicate whether the target one is compatible with the /// original one. -fn match_trait_impl<'a, 'tcx>(id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, +fn match_trait_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + trans: &TranslationContext<'a, 'tcx, 'tcx>, orig_def_id: DefId) -> bool { - let trans = if id_mapping.in_old_crate(orig_def_id) { - TranslationContext::target_new(tcx, id_mapping, false) - } else { - TranslationContext::target_old(tcx, id_mapping, false) - }; - debug!("matching: {:?}", orig_def_id); tcx.infer_ctxt().enter(|infcx| { From 59f4e161eadb214a0b5a7e83926254fb8a4282d4 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 7 Aug 2017 14:15:56 +0200 Subject: [PATCH 228/553] Updated README and reordered/clarified traversal logic. --- README.md | 13 ++- src/semcheck/traverse.rs | 236 +++++++++++++++++++-------------------- 2 files changed, 119 insertions(+), 130 deletions(-) diff --git a/README.md b/README.md index 09b50a3df9a32..2b8f1e6fcdc42 100644 --- a/README.md +++ b/README.md @@ -69,19 +69,20 @@ implementations are not yet handled, and some type checks behave incorrectly. At the time of writing, the following types of changes are recognized and classified correctly: -* items moving from `pub` to non-`pub` +* 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 -* additions of new and removals of old enum variants -* additions of new and removals of old enum variant- or struct fields +* 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 to and from methods -* addition and removal of (posslibly defaulted) trait items +* additions and removals of a self-parameter on methods +* additions and removals of (posslibly defaulted) trait items * changes to the unsafety of a trait -* type changes of all toplevel items +* type changes of all toplevel items, as well as associated items in inherent impls and + trait definitions Yet, the results presented to the user are merely an approximation of the required versioning policy, especially at such an early stage of development. diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 2656e6d99161a..28f422f6d9092 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -4,10 +4,10 @@ //! 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 find non-public items that are named -//! differently, yet are compatible in their usage. The (currently not implemented) third pass -//! performs the same analysis on trait bounds. The fourth and final pass now uses the -//! information collected in the previous passes to compare the types of all item pairs having -//! been matched. +//! 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 rustc::hir::def::{CtorKind, Def}; use rustc::hir::def_id::DefId; @@ -44,11 +44,6 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI } // third pass - for (old, new) in id_mapping.items() { - diff_bounds(&mut changes, &id_mapping, tcx, old, new); - } - - // fourth pass for (old, new) in id_mapping.items() { diff_types(&mut changes, &id_mapping, tcx, old, new); } @@ -122,7 +117,8 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, tcx.def_span(n_def_id), true); - // FIXME: simplify these conditions ;) + // this seemingly overly complex condition is needed to handle + // `Restricted` visibility correctly. if o_vis == Public && n_vis != Public { changes.add_change(ItemMadePrivate, o_def_id, None); } else if o_vis != Public && n_vis == Public { @@ -568,10 +564,10 @@ fn diff_generics(changes: &mut ChangeSet, (Some(old_region), Some(new_region)) => { id_mapping.add_internal_item(old_region.def_id, new_region.def_id); }, - (Some(_ /* old_region */), None) => { + (Some(_), None) => { found.push(RegionParameterRemoved); }, - (None, Some(_ /* new_region */)) => { + (None, Some(_)) => { found.push(RegionParameterAdded); }, (None, None) => unreachable!(), @@ -615,19 +611,8 @@ fn diff_generics(changes: &mut ChangeSet, } } -// Below functions constitute the third pass of analysis, in which parameter bounds of matching -// items are used to determine matching relationships between items not being exported. - -/// Given two items, compare the bounds on their type and region parameters. -fn diff_bounds<'a, 'tcx>(_changes: &mut ChangeSet, - _id_mapping: &IdMapping, - _tcx: TyCtxt<'a, 'tcx, 'tcx>, - _old: Def, - _new: Def) { -} - -// Below functions constitute the fourth and last pass of analysis, in which the types and/or -// trait bounds of matching items are compared for changes. +// 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<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, @@ -690,6 +675,77 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } } +/// Compare two types and their trait bounds, possibly registering the resulting change. +fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, '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 = Substs::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(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<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, '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 = Substs::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<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, @@ -770,7 +826,7 @@ fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let all_impls = tcx.sess.cstore.implementations_of_trait(None); - for orig_impl_def_id in all_impls.iter() { + for orig_impl_def_id in &all_impls { let orig_trait_def_id = tcx.impl_trait_ref(*orig_impl_def_id).unwrap().def_id; let (forward_trans, err_type) = @@ -795,104 +851,6 @@ fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } } -/// Compare two types and their trait bounds, possibly registering the resulting change. -fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, - id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, '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 = Substs::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(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<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, - id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, '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 = Substs::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); - }) -} - -/// Compare two implementations and indicate whether the target one is compatible with the -/// original one. -fn match_trait_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - trans: &TranslationContext<'a, 'tcx, '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() - }) -} - /// Compare an item pair in two inherent implementations and indicate whether the target one is /// compatible with the original one. fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, @@ -1003,3 +961,33 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, true }) } + +/// Compare two implementations and indicate whether the target one is compatible with the +/// original one. +fn match_trait_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + trans: &TranslationContext<'a, 'tcx, '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() + }) +} From 16a5676d177ff548d4c6b4588c53c6ce6a46e443 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 7 Aug 2017 16:23:45 +0200 Subject: [PATCH 229/553] Added a few testcases to diagnose module span issues. --- src/semcheck/traverse.rs | 2 -- tests/cases/addition/new.rs | 4 ++++ tests/cases/addition/old.rs | 4 ++++ tests/cases/addition/stdout | 8 ++++++++ tests/cases/removal/new.rs | 4 ++++ tests/cases/removal/old.rs | 4 ++++ tests/cases/removal/stdout | 8 ++++++++ 7 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 28f422f6d9092..665f25f2cb06c 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -867,10 +867,8 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, tcx.infer_ctxt().enter(|infcx| { let (compcx, register_errors) = if id_mapping.in_old_crate(orig_impl_def_id) { - // id_mapping.register_current_match(orig_item_def_id, target_item_def_id); (TypeComparisonContext::target_new(&infcx, id_mapping, false), true) } else { - // id_mapping.register_current_match(target_item_def_id, orig_item_def_id); (TypeComparisonContext::target_old(&infcx, id_mapping, false), false) }; diff --git a/tests/cases/addition/new.rs b/tests/cases/addition/new.rs index 5f472077711f4..5c6c42226c1c5 100644 --- a/tests/cases/addition/new.rs +++ b/tests/cases/addition/new.rs @@ -15,3 +15,7 @@ mod c { #[allow(dead_code)] pub struct Def; } + +pub mod d { + +} diff --git a/tests/cases/addition/old.rs b/tests/cases/addition/old.rs index ddc8b73f64ca1..39a077e8f6421 100644 --- a/tests/cases/addition/old.rs +++ b/tests/cases/addition/old.rs @@ -8,3 +8,7 @@ mod b { mod c { } + +mod d { + +} diff --git a/tests/cases/addition/stdout b/tests/cases/addition/stdout index f055ada1b54b9..3a876f5ea12eb 100644 --- a/tests/cases/addition/stdout +++ b/tests/cases/addition/stdout @@ -17,6 +17,14 @@ warning: technically breaking changes in `b` | = note: item made public (technically breaking) +warning: technically breaking changes in `d` + --> $REPO_PATH/tests/cases/addition/new.rs:21:1 + | +21 | } + | ^ + | + = note: item made public (technically breaking) + warning: path changes to `Abc` --> $REPO_PATH/tests/cases/addition/new.rs:1:1 | diff --git a/tests/cases/removal/new.rs b/tests/cases/removal/new.rs index ddc8b73f64ca1..39a077e8f6421 100644 --- a/tests/cases/removal/new.rs +++ b/tests/cases/removal/new.rs @@ -8,3 +8,7 @@ mod b { mod c { } + +mod d { + +} diff --git a/tests/cases/removal/old.rs b/tests/cases/removal/old.rs index 5f472077711f4..5c6c42226c1c5 100644 --- a/tests/cases/removal/old.rs +++ b/tests/cases/removal/old.rs @@ -15,3 +15,7 @@ mod c { #[allow(dead_code)] pub struct Def; } + +pub mod d { + +} diff --git a/tests/cases/removal/stdout b/tests/cases/removal/stdout index cc94b5c867e68..9094364f2ba77 100644 --- a/tests/cases/removal/stdout +++ b/tests/cases/removal/stdout @@ -39,3 +39,11 @@ warning: path changes to `Cde` | = note: removed definition (breaking) +warning: breaking changes in `d` + --> $REPO_PATH/tests/cases/removal/new.rs:14:1 + | +14 | } + | ^ + | + = warning: item made private (breaking) + From 5c3c6387634f2fdb16728b1f7cea044cbef2030c Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 7 Aug 2017 21:58:45 +0200 Subject: [PATCH 230/553] Stepped messages up a bit. --- src/semcheck/changes.rs | 17 +++++++++++++---- src/semcheck/traverse.rs | 10 +++++----- tests/cases/addition_use/stdout | 2 +- tests/cases/bounds/stdout | 4 ++-- tests/cases/consts/stdout | 6 +++--- tests/cases/enums/stdout | 10 +++++----- tests/cases/func/stdout | 12 ++++++------ tests/cases/infer_regress/stdout | 4 ++-- tests/cases/inherent_impls/stdout | 8 ++++---- tests/cases/kind_change/stdout | 2 +- tests/cases/macros/stdout | 8 ++++---- tests/cases/mix/stdout | 6 +++--- tests/cases/regions/stdout | 12 ++++++------ tests/cases/removal/stdout | 18 +++++++++--------- tests/cases/removal_path/stdout | 2 +- tests/cases/removal_use/stdout | 10 +++++----- tests/cases/structs/stdout | 8 ++++---- tests/cases/trait_impls/stdout | 4 ++-- tests/cases/traits/stdout | 26 +++++++++++++------------- tests/cases/ty_alias/stdout | 14 +++++++------- 20 files changed, 96 insertions(+), 87 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 4595ef109227d..9b31bb7c4eb15 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -137,16 +137,21 @@ impl PathChange { /// Report the change in a structured manner. fn report(&self, session: &Session) { - if self.to_category() == Patch { + let cat = self.to_category(); + if cat == Patch { return; } let msg = format!("path changes to `{}`", self.name); - let mut builder = session.struct_span_warn(self.def_span, &msg); + 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.note("removed definition (breaking)"); + builder.warn("removed definition (breaking)"); } else { builder.span_warn(*removed_span, "removed path (breaking)"); } @@ -450,7 +455,11 @@ impl<'tcx> Change<'tcx> { } let msg = format!("{} changes in {}", self.max, self.name); - let mut builder = session.struct_span_warn(self.new_span, &msg); + 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(); diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 665f25f2cb06c..562cdb13df8c9 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -157,9 +157,9 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, // matching items we don't care about because they are either // impossible to encounter at this stage (Mod, AssociatedTy, PrimTy, // TyParam, SelfTy, StructCtor, VariantCtor, AssociatedConst, Local, - // Upvar, Label, Variant, Err), whose analysis is out scope for us - // (GlobalAsm, Macro), or which don't requite further analysis at - // this stage (Const) + // Upvar, Label, Variant, Method, Err), whose analysis is out scope + // for us (GlobalAsm, Macro), or which don't requite further analysis + // at this stage (Const) (Mod(_), Mod(_)) | (AssociatedTy(_), AssociatedTy(_)) | (PrimTy(_), PrimTy(_)) | @@ -175,6 +175,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, (Macro(_, _), Macro(_, _)) | (Variant(_), Variant(_)) | (Const(_), Const(_)) | + (Method(_), Method(_)) | (Err, Err) => {}, // statics are subject to mutability comparison (Static(_, old_mut), Static(_, new_mut)) => { @@ -188,8 +189,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, }, // functions can declare generics and have structural properties // that need to be compared - (Fn(_), Fn(_)) | - (Method(_), Method(_)) => { + (Fn(_), Fn(_)) => { diff_generics(changes, id_mapping, tcx, diff --git a/tests/cases/addition_use/stdout b/tests/cases/addition_use/stdout index dc8b96fbf106f..1a5efb1cdb7ce 100644 --- a/tests/cases/addition_use/stdout +++ b/tests/cases/addition_use/stdout @@ -1,5 +1,5 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 -warning: breaking changes in `Def` +error: breaking changes in `Def` --> $REPO_PATH/tests/cases/addition_use/new.rs:5:1 | 5 | / pub struct Def<'a> { diff --git a/tests/cases/bounds/stdout b/tests/cases/bounds/stdout index 5dbd95a52ab0e..de6b248d39e15 100644 --- a/tests/cases/bounds/stdout +++ b/tests/cases/bounds/stdout @@ -1,5 +1,5 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 -warning: breaking changes in `Abc` +error: breaking changes in `Abc` --> $REPO_PATH/tests/cases/bounds/new.rs:1:1 | 1 | / pub struct Abc { @@ -19,7 +19,7 @@ warning: technically breaking changes in `Def` | = note: removed bound: `A: std::clone::Clone` (technically breaking) -warning: breaking changes in `abc` +error: breaking changes in `abc` --> $REPO_PATH/tests/cases/bounds/new.rs:9:1 | 9 | pub fn abc(_: A) {} diff --git a/tests/cases/consts/stdout b/tests/cases/consts/stdout index ade8d64178667..61c5bd23a788f 100644 --- a/tests/cases/consts/stdout +++ b/tests/cases/consts/stdout @@ -1,5 +1,5 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 -warning: breaking changes in `A` +error: breaking changes in `A` --> $REPO_PATH/tests/cases/consts/new.rs:1:1 | 1 | pub const A: u16 = 0; @@ -7,7 +7,7 @@ warning: breaking changes in `A` | = warning: type error: expected u8, found u16 (breaking) -warning: breaking changes in `B` +error: breaking changes in `B` --> $REPO_PATH/tests/cases/consts/new.rs:3:1 | 3 | pub static B: u16 = 1; @@ -15,7 +15,7 @@ warning: breaking changes in `B` | = warning: type error: expected u8, found u16 (breaking) -warning: breaking changes in `D` +error: breaking changes in `D` --> $REPO_PATH/tests/cases/consts/new.rs:7:1 | 7 | pub static D: bool = true; diff --git a/tests/cases/enums/stdout b/tests/cases/enums/stdout index 6beb03a6ec747..e9a08b0dc56d2 100644 --- a/tests/cases/enums/stdout +++ b/tests/cases/enums/stdout @@ -1,5 +1,5 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 -warning: breaking changes in `Abc` +error: breaking changes in `Abc` --> $REPO_PATH/tests/cases/enums/new.rs:1:1 | 1 | / pub enum Abc { @@ -13,7 +13,7 @@ warning: enum variant added (breaking) 2 | Abc, | ^^^ -warning: breaking changes in `Bcd` +error: breaking changes in `Bcd` --> $REPO_PATH/tests/cases/enums/new.rs:5:1 | 5 | / pub enum Bcd { @@ -27,7 +27,7 @@ warning: enum variant removed (breaking) 6 | Abc, | ^^^ -warning: breaking changes in `Cde` +error: breaking changes in `Cde` --> $REPO_PATH/tests/cases/enums/new.rs:9:1 | 9 | / pub enum Cde { @@ -42,7 +42,7 @@ warning: enum variant added (breaking) 11 | Bcd, | ^^^ -warning: breaking changes in `Def` +error: breaking changes in `Def` --> $REPO_PATH/tests/cases/enums/new.rs:14:1 | 14 | / pub enum Def { @@ -56,7 +56,7 @@ warning: enum variant removed (breaking) 15 | Bcd, | ^^^ -warning: breaking changes in `Efg` +error: breaking changes in `Efg` --> $REPO_PATH/tests/cases/enums/new.rs:18:1 | 18 | / pub enum Efg { diff --git a/tests/cases/func/stdout b/tests/cases/func/stdout index 21c12867c5976..a895ba5e1a3c7 100644 --- a/tests/cases/func/stdout +++ b/tests/cases/func/stdout @@ -1,5 +1,5 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 -warning: breaking changes in `bcd` +error: breaking changes in `bcd` --> $REPO_PATH/tests/cases/func/new.rs:4:1 | 4 | pub fn bcd(_: u8) {} @@ -7,7 +7,7 @@ warning: breaking changes in `bcd` | = warning: type error: incorrect number of function parameters (breaking) -warning: breaking changes in `cde` +error: breaking changes in `cde` --> $REPO_PATH/tests/cases/func/new.rs:6:1 | 6 | / pub fn cde() -> u16 { @@ -17,7 +17,7 @@ warning: breaking changes in `cde` | = warning: type error: expected (), found u16 (breaking) -warning: breaking changes in `def` +error: breaking changes in `def` --> $REPO_PATH/tests/cases/func/new.rs:10:1 | 10 | pub fn def() {} @@ -35,7 +35,7 @@ warning: non-breaking changes in `efg` | = note: defaulted type parameter added (non-breaking) -warning: breaking changes in `fgh` +error: breaking changes in `fgh` --> $REPO_PATH/tests/cases/func/new.rs:16:1 | 16 | / pub fn fgh(a: u8, _: u16) -> u8 { @@ -45,7 +45,7 @@ warning: breaking changes in `fgh` | = warning: type error: expected u8, found u16 (breaking) -warning: breaking changes in `ghi` +error: breaking changes in `ghi` --> $REPO_PATH/tests/cases/func/new.rs:20:1 | 20 | / pub fn ghi(a: u8, _: u8) -> u16 { @@ -65,7 +65,7 @@ warning: non-breaking changes in `hij` | = note: fn item made const (non-breaking) -warning: breaking changes in `ijk` +error: breaking changes in `ijk` --> $REPO_PATH/tests/cases/func/new.rs:28:1 | 28 | / pub fn ijk() -> u8 { diff --git a/tests/cases/infer_regress/stdout b/tests/cases/infer_regress/stdout index b8b6f296231f0..aa3f57e83e156 100644 --- a/tests/cases/infer_regress/stdout +++ b/tests/cases/infer_regress/stdout @@ -1,5 +1,5 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 -warning: breaking changes in `abc` +error: breaking changes in `abc` --> $REPO_PATH/tests/cases/infer_regress/new.rs:1:1 | 1 | pub fn abc(_: A) { } @@ -7,7 +7,7 @@ warning: breaking changes in `abc` | = warning: type error: expected type parameter, found () (breaking) -warning: breaking changes in `Abc` +error: breaking changes in `Abc` --> $REPO_PATH/tests/cases/infer_regress/new.rs:3:1 | 3 | pub struct Abc(A, ()); diff --git a/tests/cases/inherent_impls/stdout b/tests/cases/inherent_impls/stdout index 68e2875a56331..c0f4e77a83f05 100644 --- a/tests/cases/inherent_impls/stdout +++ b/tests/cases/inherent_impls/stdout @@ -1,5 +1,5 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 -warning: breaking changes in `ghi` +error: breaking changes in `ghi` --> $REPO_PATH/tests/cases/inherent_impls/old.rs:14:5 | 14 | / pub fn ghi(&self, a: A) -> A { @@ -9,7 +9,7 @@ warning: breaking changes in `ghi` | = warning: type error: expected type parameter, found u8 (breaking) -warning: breaking changes in `def` +error: breaking changes in `def` --> $REPO_PATH/tests/cases/inherent_impls/old.rs:26:5 | 26 | / pub fn def(&self) -> u8 { @@ -19,7 +19,7 @@ warning: breaking changes in `def` | = warning: removed item in inherent impl (breaking) -warning: breaking changes in `def` +error: breaking changes in `def` --> $REPO_PATH/tests/cases/inherent_impls/old.rs:33:5 | 33 | / pub fn def(&self) -> u8 { @@ -29,7 +29,7 @@ warning: breaking changes in `def` | = warning: type error: expected u8, found u16 (breaking) -warning: breaking changes in `ghi` +error: breaking changes in `ghi` --> $REPO_PATH/tests/cases/inherent_impls/old.rs:37:5 | 37 | pub fn ghi() { } diff --git a/tests/cases/kind_change/stdout b/tests/cases/kind_change/stdout index 0edbc7e33ad96..5190a0a42bd69 100644 --- a/tests/cases/kind_change/stdout +++ b/tests/cases/kind_change/stdout @@ -1,5 +1,5 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 -warning: breaking changes in `Abc` +error: breaking changes in `Abc` --> $REPO_PATH/tests/cases/kind_change/new.rs:1:1 | 1 | / pub enum Abc { diff --git a/tests/cases/macros/stdout b/tests/cases/macros/stdout index 80e4c7aede282..6bfc440e7d334 100644 --- a/tests/cases/macros/stdout +++ b/tests/cases/macros/stdout @@ -1,13 +1,13 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 -warning: path changes to `qux1` +error: path changes to `qux1` --> $REPO_PATH/tests/cases/macros/old.rs:15:5 | 15 | pub macro qux1() { Item } | ^^^^^^^^^^^^^^^^^^^^^ | - = note: removed definition (breaking) + = warning: removed definition (breaking) -warning: path changes to `qux2` +error: path changes to `qux2` --> $REPO_PATH/tests/cases/macros/old.rs:18:1 | 18 | / macro_rules! qux2 { @@ -17,7 +17,7 @@ warning: path changes to `qux2` 22 | | } | |_^ | - = note: removed definition (breaking) + = warning: removed definition (breaking) warning: path changes to `quux1` --> $REPO_PATH/tests/cases/macros/new.rs:15:5 diff --git a/tests/cases/mix/stdout b/tests/cases/mix/stdout index 0d97584e7d951..8282238fbdaee 100644 --- a/tests/cases/mix/stdout +++ b/tests/cases/mix/stdout @@ -1,5 +1,5 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 -warning: breaking changes in `Abc` +error: breaking changes in `Abc` --> $REPO_PATH/tests/cases/mix/new.rs:2:5 | 2 | pub enum Abc {} @@ -7,7 +7,7 @@ warning: breaking changes in `Abc` | = warning: item kind changed (breaking) -warning: breaking changes in `Def` +error: breaking changes in `Def` --> $REPO_PATH/tests/cases/mix/new.rs:3:5 | 3 | pub struct Def; @@ -15,7 +15,7 @@ warning: breaking changes in `Def` | = warning: item kind changed (breaking) -warning: path changes to `Abc` +error: path changes to `Abc` --> $REPO_PATH/tests/cases/mix/new.rs:2:5 | 2 | pub enum Abc {} diff --git a/tests/cases/regions/stdout b/tests/cases/regions/stdout index 0a32f06942292..7f03c3c6252bf 100644 --- a/tests/cases/regions/stdout +++ b/tests/cases/regions/stdout @@ -1,5 +1,5 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 -warning: breaking changes in `D` +error: breaking changes in `D` --> $REPO_PATH/tests/cases/regions/new.rs:7:1 | 7 | pub type D = T::IntoIter; @@ -7,7 +7,7 @@ warning: breaking changes in `D` | = warning: type error: expected std::iter::IntoIterator::Item, found std::iter::IntoIterator::IntoIter (breaking) -warning: breaking changes in `E` +error: breaking changes in `E` --> $REPO_PATH/tests/cases/regions/new.rs:9:1 | 9 | pub type E = T; @@ -15,7 +15,7 @@ warning: breaking changes in `E` | = warning: type error: expected associated type, found type parameter (breaking) -warning: breaking changes in `abc` +error: breaking changes in `abc` --> $REPO_PATH/tests/cases/regions/new.rs:11:1 | 11 | pub fn abc(_: &bool) { } @@ -23,7 +23,7 @@ warning: breaking changes in `abc` | = warning: type error: expected bool, found reference (breaking) -warning: breaking changes in `def` +error: breaking changes in `def` --> $REPO_PATH/tests/cases/regions/new.rs:13:1 | 13 | pub fn def(_: bool) { } @@ -31,7 +31,7 @@ warning: breaking changes in `def` | = warning: type error: expected reference, found bool (breaking) -warning: breaking changes in `efg` +error: breaking changes in `efg` --> $REPO_PATH/tests/cases/regions/new.rs:15:1 | 15 | pub fn efg(_: &str) { } @@ -39,7 +39,7 @@ warning: breaking changes in `efg` | = warning: type error: expected bound lifetime parameterBrAnon(0), found concrete lifetime (breaking) -warning: breaking changes in `fgh` +error: breaking changes in `fgh` --> $REPO_PATH/tests/cases/regions/new.rs:17:1 | 17 | pub fn fgh(_: &'static str) { } diff --git a/tests/cases/removal/stdout b/tests/cases/removal/stdout index 9094364f2ba77..4a01abfa76134 100644 --- a/tests/cases/removal/stdout +++ b/tests/cases/removal/stdout @@ -1,13 +1,13 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 -warning: path changes to `Abc` +error: path changes to `Abc` --> $REPO_PATH/tests/cases/removal/old.rs:1:1 | 1 | pub struct Abc; | ^^^^^^^^^^^^^^^ | - = note: removed definition (breaking) + = warning: removed definition (breaking) -warning: breaking changes in `Bcd` +error: breaking changes in `Bcd` --> $REPO_PATH/tests/cases/removal/new.rs:2:1 | 2 | struct Bcd; @@ -15,15 +15,15 @@ warning: breaking changes in `Bcd` | = warning: item made private (breaking) -warning: path changes to `a` +error: path changes to `a` --> $REPO_PATH/tests/cases/removal/old.rs:7:1 | 7 | } | ^ | - = note: removed definition (breaking) + = warning: removed definition (breaking) -warning: breaking changes in `b` +error: breaking changes in `b` --> $REPO_PATH/tests/cases/removal/new.rs:6:1 | 6 | } @@ -31,15 +31,15 @@ warning: breaking changes in `b` | = warning: item made private (breaking) -warning: path changes to `Cde` +error: path changes to `Cde` --> $REPO_PATH/tests/cases/removal/old.rs:11:5 | 11 | pub struct Cde; | ^^^^^^^^^^^^^^^ | - = note: removed definition (breaking) + = warning: removed definition (breaking) -warning: breaking changes in `d` +error: breaking changes in `d` --> $REPO_PATH/tests/cases/removal/new.rs:14:1 | 14 | } diff --git a/tests/cases/removal_path/stdout b/tests/cases/removal_path/stdout index 6d20e64c5fb52..40751182cd1fe 100644 --- a/tests/cases/removal_path/stdout +++ b/tests/cases/removal_path/stdout @@ -1,5 +1,5 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 -warning: path changes to `Abc` +error: path changes to `Abc` --> $REPO_PATH/tests/cases/removal_path/new.rs:2:5 | 2 | pub struct Abc; diff --git a/tests/cases/removal_use/stdout b/tests/cases/removal_use/stdout index 1b48121097d9b..51f6c7ddecf66 100644 --- a/tests/cases/removal_use/stdout +++ b/tests/cases/removal_use/stdout @@ -1,21 +1,21 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 -warning: path changes to `Abc` +error: path changes to `Abc` --> $REPO_PATH/tests/cases/removal_use/old.rs:1:1 | 1 | pub struct Abc; | ^^^^^^^^^^^^^^^ | - = note: removed definition (breaking) + = warning: removed definition (breaking) -warning: path changes to `Bcd` +error: path changes to `Bcd` --> $REPO_PATH/tests/cases/removal_use/old.rs:3:1 | 3 | pub trait Bcd {} | ^^^^^^^^^^^^^^^^ | - = note: removed definition (breaking) + = warning: removed definition (breaking) -warning: breaking changes in `Def` +error: breaking changes in `Def` --> $REPO_PATH/tests/cases/removal_use/new.rs:1:1 | 1 | / pub struct Def<'a> { diff --git a/tests/cases/structs/stdout b/tests/cases/structs/stdout index 1e187d7327e35..a0864aa096a6c 100644 --- a/tests/cases/structs/stdout +++ b/tests/cases/structs/stdout @@ -14,7 +14,7 @@ note: item made public (technically breaking) 7 | pub field: A, | ^^^^^^^^^^^^ -warning: breaking changes in `Def2` +error: breaking changes in `Def2` --> $REPO_PATH/tests/cases/structs/new.rs:10:1 | 10 | / pub struct Def2 { @@ -25,7 +25,7 @@ warning: breaking changes in `Def2` = note: defaulted type parameter added (non-breaking) = warning: type error: expected u8, found u16 (breaking) -warning: breaking changes in `Efg` +error: breaking changes in `Efg` --> $REPO_PATH/tests/cases/structs/new.rs:14:1 | 14 | / pub struct Efg { @@ -49,7 +49,7 @@ note: item made public (technically breaking) 19 | pub field: u8, | ^^^^^^^^^^^^^ -warning: breaking changes in `Ghi` +error: breaking changes in `Ghi` --> $REPO_PATH/tests/cases/structs/new.rs:22:1 | 22 | / pub struct Ghi { @@ -63,7 +63,7 @@ warning: item made private (breaking) 23 | field: u8, | ^^^^^^^^^ -warning: breaking changes in `Hij` +error: breaking changes in `Hij` --> $REPO_PATH/tests/cases/structs/new.rs:26:1 | 26 | / pub struct Hij { diff --git a/tests/cases/trait_impls/stdout b/tests/cases/trait_impls/stdout index b8cf65677c73b..420d1450bddd8 100644 --- a/tests/cases/trait_impls/stdout +++ b/tests/cases/trait_impls/stdout @@ -1,5 +1,5 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 -warning: breaking changes in ` as old::Abc>` +error: breaking changes in ` as old::Abc>` --> $REPO_PATH/tests/cases/trait_impls/old.rs:9:1 | 9 | impl Abc for Vec { } @@ -7,7 +7,7 @@ warning: breaking changes in ` as old::Abc>` | = warning: trait impl specialized or removed (breaking) -warning: breaking changes in `` +error: breaking changes in `` --> $REPO_PATH/tests/cases/trait_impls/old.rs:11:1 | 11 | / impl Clone for Def { diff --git a/tests/cases/traits/stdout b/tests/cases/traits/stdout index 8ee8b3c459460..bc7e87f34035a 100644 --- a/tests/cases/traits/stdout +++ b/tests/cases/traits/stdout @@ -1,5 +1,5 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 -warning: breaking changes in `Abc` +error: breaking changes in `Abc` --> $REPO_PATH/tests/cases/traits/new.rs:1:1 | 1 | / pub trait Abc { @@ -36,7 +36,7 @@ note: added defaulted item to trait (technically breaking) 10 | | } | |_____^ -warning: breaking changes in `test7` +error: breaking changes in `test7` --> $REPO_PATH/tests/cases/traits/new.rs:11:5 | 11 | fn test7() -> u16; @@ -44,7 +44,7 @@ warning: breaking changes in `test7` | = warning: type error: expected u8, found u16 (breaking) -warning: breaking changes in `test8` +error: breaking changes in `test8` --> $REPO_PATH/tests/cases/traits/new.rs:12:5 | 12 | fn test8(_: &Self) -> u8; @@ -60,7 +60,7 @@ warning: technically breaking changes in `test9` | = note: added self-argument to method (technically breaking) -warning: breaking changes in `Bcd` +error: breaking changes in `Bcd` --> $REPO_PATH/tests/cases/traits/new.rs:16:1 | 16 | pub trait Bcd {} @@ -68,7 +68,7 @@ warning: breaking changes in `Bcd` | = warning: type parameter added (breaking) -warning: breaking changes in `Cde` +error: breaking changes in `Cde` --> $REPO_PATH/tests/cases/traits/new.rs:18:1 | 18 | pub trait Cde {} @@ -76,7 +76,7 @@ warning: breaking changes in `Cde` | = warning: type parameter removed (breaking) -warning: breaking changes in `Def` +error: breaking changes in `Def` --> $REPO_PATH/tests/cases/traits/new.rs:20:1 | 20 | / pub trait Def { @@ -88,7 +88,7 @@ warning: breaking changes in `Def` | = warning: type parameter added (breaking) -warning: breaking changes in `Efg` +error: breaking changes in `Efg` --> $REPO_PATH/tests/cases/traits/new.rs:26:1 | 26 | / pub trait Efg { @@ -98,7 +98,7 @@ warning: breaking changes in `Efg` | = warning: type parameter removed (breaking) -warning: breaking changes in `Ghi` +error: breaking changes in `Ghi` --> $REPO_PATH/tests/cases/traits/new.rs:36:1 | 36 | pub trait Ghi { } @@ -110,7 +110,7 @@ warning: removed item from trait (breaking) 35 | type A; | ^^^^^^^ -warning: breaking changes in `Hij` +error: breaking changes in `Hij` --> $REPO_PATH/tests/cases/traits/new.rs:38:1 | 38 | / pub trait Hij { @@ -124,7 +124,7 @@ warning: added item to trait (breaking) 39 | type A; | ^^^^^^^ -warning: breaking changes in `Klm` +error: breaking changes in `Klm` --> $REPO_PATH/tests/cases/traits/new.rs:42:1 | 42 | pub trait Klm : Clone { } @@ -132,7 +132,7 @@ warning: breaking changes in `Klm` | = warning: added bound: `Self: std::clone::Clone` (breaking) -warning: breaking changes in `Nop` +error: breaking changes in `Nop` --> $REPO_PATH/tests/cases/traits/new.rs:44:1 | 44 | pub trait Nop { } @@ -140,7 +140,7 @@ warning: breaking changes in `Nop` | = warning: removed bound on trait definition: `Self: std::clone::Clone` (breaking) -warning: breaking changes in `Qrs` +error: breaking changes in `Qrs` --> $REPO_PATH/tests/cases/traits/new.rs:46:1 | 46 | pub trait Qrs { } @@ -148,7 +148,7 @@ warning: breaking changes in `Qrs` | = warning: added bound: `A: std::clone::Clone` (breaking) -warning: breaking changes in `Tuv` +error: breaking changes in `Tuv` --> $REPO_PATH/tests/cases/traits/new.rs:48:1 | 48 | pub trait Tuv { } diff --git a/tests/cases/ty_alias/stdout b/tests/cases/ty_alias/stdout index 30562d822b72d..a59bc681c8494 100644 --- a/tests/cases/ty_alias/stdout +++ b/tests/cases/ty_alias/stdout @@ -1,5 +1,5 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 -warning: breaking changes in `A` +error: breaking changes in `A` --> $REPO_PATH/tests/cases/ty_alias/new.rs:1:1 | 1 | pub type A = u16; @@ -7,7 +7,7 @@ warning: breaking changes in `A` | = warning: type error: expected u8, found u16 (breaking) -warning: breaking changes in `B` +error: breaking changes in `B` --> $REPO_PATH/tests/cases/ty_alias/new.rs:2:1 | 2 | pub type B<'a, 'b : 'a, T> = (&'a T, &'b T); @@ -15,7 +15,7 @@ warning: breaking changes in `B` | = warning: region parameter added (breaking) -warning: breaking changes in `C` +error: breaking changes in `C` --> $REPO_PATH/tests/cases/ty_alias/new.rs:3:1 | 3 | pub type C = T; @@ -23,7 +23,7 @@ warning: breaking changes in `C` | = warning: region parameter removed (breaking) -warning: breaking changes in `D` +error: breaking changes in `D` --> $REPO_PATH/tests/cases/ty_alias/new.rs:4:1 | 4 | pub type D<'a, T, U=Box> = (&'a T, U); @@ -32,7 +32,7 @@ warning: breaking changes in `D` = note: defaulted type parameter added (non-breaking) = warning: type error: expected reference, found tuple (breaking) -warning: breaking changes in `E` +error: breaking changes in `E` --> $REPO_PATH/tests/cases/ty_alias/new.rs:5:1 | 5 | pub type E<'a, T, U> = (&'a T, U); @@ -40,7 +40,7 @@ warning: breaking changes in `E` | = warning: type parameter added (breaking) -warning: breaking changes in `F` +error: breaking changes in `F` --> $REPO_PATH/tests/cases/ty_alias/new.rs:6:1 | 6 | pub type F<'a> = &'a u8; @@ -48,7 +48,7 @@ warning: breaking changes in `F` | = warning: defaulted type parameter removed (breaking) -warning: breaking changes in `G` +error: breaking changes in `G` --> $REPO_PATH/tests/cases/ty_alias/new.rs:7:1 | 7 | pub type G<'a> = (&'a u8); From a96ed0fa3fa2840e7d42597348428f78f1b7e6e4 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 7 Aug 2017 22:15:30 +0200 Subject: [PATCH 231/553] Cleaned up tests and error messages. --- src/semcheck/changes.rs | 9 +++++---- src/semcheck/mapping.rs | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 9b31bb7c4eb15..9563f632dc70e 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -797,13 +797,13 @@ pub mod tests { pub type Change_ = (DefId_, DefId_, Span_, Span_, bool, Vec<(ChangeType_, Option)>); /// Construct `Change`s from things that can be generated. - fn build_change<'a>(s1: Span, output: bool, mut changes: Vec<(ChangeType_, Option)>) + fn build_change<'a>(s1: Span, output: bool, changes: Vec<(ChangeType_, Option)>) -> Change<'a> { let mut interner = Interner::new(); let mut change = Change::new(Name::Symbol(interner.intern("test")), s1, output); - for (type_, span) in changes.drain(..) { + for (type_, span) in changes { change.insert(type_.inner(), span.map(|s| s.inner())); } @@ -814,11 +814,11 @@ pub mod tests { pub type PathChange_ = (DefId_, Span_, Vec<(bool, Span_)>); /// Construct `PathChange`s from things that can be generated. - fn build_path_change(s1: Span, mut spans: Vec<(bool, Span)>) -> PathChange { + fn build_path_change(s1: Span, spans: Vec<(bool, Span)>) -> PathChange { let mut interner = Interner::new(); let mut change = PathChange::new(interner.intern("test"), s1); - for (add, span) in spans.drain(..) { + for (add, span) in spans { change.insert(span, add); } @@ -954,6 +954,7 @@ pub mod tests { .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() diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 238df334073cb..ea895a99fc0f2 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -312,12 +312,12 @@ impl NameMapping { } /// Add all items from two vectors of old/new exports. - pub fn add(&mut self, mut old_items: Vec, mut new_items: Vec) { - for item in old_items.drain(..) { + pub fn add(&mut self, old_items: Vec, new_items: Vec) { + for item in old_items { self.insert(item, true); } - for item in new_items.drain(..) { + for item in new_items { self.insert(item, false); } } From fb4119bb4adb64eaa2e4b845b58ea544e45fc00b Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 8 Aug 2017 17:14:02 +0200 Subject: [PATCH 232/553] More tests. Added integration tests on published crates from `cates.io`. --- src/semcheck/traverse.rs | 8 +- tests/dump | 28 - tests/examples.rs | 138 +- tests/full_cases/log-0.3.4-0.3.8 | 178 ++ tests/full_cases/serde-0.7.0-1.0.0 | 4128 ++++++++++++++++++++++++++++ 5 files changed, 4412 insertions(+), 68 deletions(-) delete mode 100644 tests/dump create mode 100644 tests/full_cases/log-0.3.4-0.3.8 create mode 100644 tests/full_cases/serde-0.7.0-1.0.0 diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 562cdb13df8c9..9eb4072089d23 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -253,9 +253,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, continue; } - let o_def_id = o.def.def_id(); - - if old_vis == Public && cstore.visibility(o_def_id) == Public { + if get_vis(cstore, old_vis, o.def.def_id()) == Public { // delay the handling of removals until the id mapping is complete removals.push(o); } @@ -267,9 +265,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, continue; } - let n_def_id = n.def.def_id(); - - if new_vis == Public && cstore.visibility(n_def_id) == Public { + if get_vis(cstore, new_vis, n.def.def_id()) == Public { // delay the handling of additions until the id mapping is complete additions.push(n); } diff --git a/tests/dump b/tests/dump deleted file mode 100644 index 80277b9de29f9..0000000000000 --- a/tests/dump +++ /dev/null @@ -1,28 +0,0 @@ - we can't use the trait system for inherent impls - you have to basically have a (DefId, AssociatedKind, hir::Name) => Vec map - and manually do what the trait system does for trait impls - namely, generate fresh infer vars for the impl you want to match *against*, substitute that - in its type_of (which is its Self) and then eq the type you want to check against that - if it didn't error, the substs containing infer vars which you substituted in type_of are - the params of the impl which you can then substitute in the associated items' signature - sooo example - old: impl Foo { fn foo() {} } - new: impl Foo { fn foo() {} } - (Foo, Method, "foo") => the one foo method in each - or rather - (old::Foo, Method, "foo") => old::...::foo - (new::Foo, Method, "foo") => new::...::foo - checking if old::...::foo is still valid means translating its "owner" (old::Foo), then - pairing it with the fact that it's a Method and its name, to get (new::Foo, Method, "foo") - which means for each in [new::...::foo] (well it's one element but you get the idea) - you generate fresh substs. in this case T => $1 - substitute, so you get new::Foo<$1> - match that against translate(old::Foo), i.e. new::Foo - that will succeed and leave $1 equal to u8 - which means your substs are now T => u8 - oh I should've given it a signature. image it's -> u8 in old and -> T in new - so the signature of the new method, substituted, is still -> u8 - and when you compare them that will succeed - but if the new method were -> Option then for T => u8 it'd be -> Option which is wrong - and you'd notice the mismatch - it's not that hard as long as you keep your code modular diff --git a/tests/examples.rs b/tests/examples.rs index 859e010c5abde..3cc82c9d6a3d9 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -5,25 +5,25 @@ use std::path::Path; use std::process::{Command, Stdio}; macro_rules! test { - ($name:ident, $path:expr) => { + ($name:ident) => { #[test] fn $name() { let mut success = true; let current_dir = env::current_dir().expect("could not determine current dir"); let subst = format!("s#{}#$REPO_PATH#g", current_dir.to_str().unwrap()); - let path = Path::new($path); + let path = Path::new("tests/cases").join(stringify!($name)); let out_file = path.join("stdout"); - let old_rlib = path.join("libold.rlib"); - let new_rlib = path.join("libnew.rlib"); + 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 stdout = File::create(&out_file).expect("could not create `stdout` file"); success &= Command::new("rustc") - .args(&["--crate-type=lib", "-o", old_rlib.to_str().unwrap()]) + .args(&["--crate-type=lib", "-o", &old_rlib]) .arg(path.join("old.rs")) .env("RUST_BACKTRACE", "full") .stdin(Stdio::null()) @@ -34,7 +34,7 @@ macro_rules! test { assert!(success, "couldn't compile old"); success &= Command::new("rustc") - .args(&["--crate-type=lib", "-o", new_rlib.to_str().unwrap()]) + .args(&["--crate-type=lib", "-o", &new_rlib]) .arg(path.join("new.rs")) .env("RUST_BACKTRACE", "full") .stdin(Stdio::null()) @@ -60,8 +60,8 @@ macro_rules! test { success &= Command::new("./target/debug/rust-semverver") .args(&["--crate-type=lib", "-Zverbose", - "--extern", &format!("old={}", old_rlib.to_str().unwrap()), - "--extern", &format!("new={}", new_rlib.to_str().unwrap()), + "--extern", &format!("old={}", old_rlib), + "--extern", &format!("new={}", new_rlib), "tests/helper/test.rs"]) .env("RUST_BACKTRACE", "full") .env("RUST_SEMVER_CRATE_VERSION", "1.0.0") @@ -89,35 +89,105 @@ macro_rules! test { assert!(success, "git"); Command::new("rm") - .args(&[old_rlib.to_str().unwrap(), new_rlib.to_str().unwrap()]) + .args(&[&old_rlib, &new_rlib]) .status() .expect("could not run rm"); } } } -test!(addition, "tests/cases/addition"); -test!(addition_path, "tests/cases/addition_path"); -test!(addition_use, "tests/cases/addition_use"); -test!(bounds, "tests/cases/bounds"); -test!(consts, "tests/cases/consts"); -test!(enums, "tests/cases/enums"); -test!(func, "tests/cases/func"); -test!(infer, "tests/cases/infer"); -test!(infer_regress, "tests/cases/infer_regress"); -test!(inherent_impls, "tests/cases/inherent_impls"); -test!(kind_change, "tests/cases/kind_change"); -test!(macros, "tests/cases/macros"); -test!(max_priv, "tests/cases/max_priv"); -test!(mix, "tests/cases/mix"); -test!(pathologic_paths, "tests/cases/pathologic_paths"); -test!(pub_use, "tests/cases/pub_use"); -test!(regions, "tests/cases/regions"); -test!(removal, "tests/cases/removal"); -test!(removal_path, "tests/cases/removal_path"); -test!(removal_use, "tests/cases/removal_use"); -test!(structs, "tests/cases/structs"); -test!(swap, "tests/cases/swap"); -test!(traits, "tests/cases/traits"); -test!(trait_impls, "tests/cases/trait_impls"); -test!(ty_alias, "tests/cases/ty_alias"); +macro_rules! full_test { + ($name:ident, $old_version:expr, $new_version:expr) => { + #[test] + fn $name() { + let mut success = true; + + let old_version = concat!(stringify!($name), "-", $old_version); + let new_version = concat!(stringify!($name), "-", $new_version); + + let current_dir = env::current_dir().expect("could not determine current dir"); + let subst = format!("s#{}#$REPO_PATH#g", current_dir.to_str().unwrap()); + let out_file = Path::new("tests/full_cases") + .join(concat!(stringify!($name), "-", $old_version, "-", $new_version)); + + if let Some(path) = env::var_os("PATH") { + let mut paths = env::split_paths(&path).collect::>(); + paths.push(current_dir.join("target/debug")); + let new_path = env::join_paths(paths).unwrap(); + env::set_var("PATH", &new_path); + } + + let stdout = File::create(&out_file).expect("could not create `stdout` file"); + let out_file = out_file.to_str().unwrap(); + + let mut sed_child = Command::new("sed") + .arg(&subst) + .stdin(Stdio::piped()) + .stdout(stdout) + .spawn() + .expect("could not run sed"); + + let (err_pipe, out_pipe) = if let Some(ref stdin) = sed_child.stdin { + let fd = stdin.as_raw_fd(); + unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } + } else { + panic!("could not pipe to sed"); + }; + + success &= Command::new("./target/debug/cargo-semver") + .args(&["semver", "-S", &old_version, "-C", &new_version]) + .env("RUST_BACKTRACE", "full") + .stdin(Stdio::null()) + .stdout(out_pipe) + .stderr(err_pipe) + .status() + .expect("could not run cargo-semver") + .success(); + + assert!(success, "cargo-semver"); + + success &= sed_child.wait().expect("could not wait for sed child").success(); + + assert!(success, "sed"); + + eprintln!("path: {}", out_file); + success &= Command::new("git") + .args(&["diff", "--quiet", out_file]) + .status() + .expect("could not run git diff") + .success(); + + assert!(success, "git"); + } + } +} + +test!(addition); +test!(addition_path); +test!(addition_use); +test!(bounds); +test!(consts); +test!(enums); +test!(func); +test!(infer); +test!(infer_regress); +test!(inherent_impls); +test!(kind_change); +test!(macros); +test!(max_priv); +test!(mix); +test!(pathologic_paths); +test!(pub_use); +test!(regions); +test!(removal); +test!(removal_path); +test!(removal_use); +test!(structs); +test!(swap); +test!(traits); +test!(trait_impls); +test!(ty_alias); + +full_test!(log, "0.3.4", "0.3.8"); +full_test!(serde, "0.7.0", "1.0.0"); +// full_test!(serde, "1.0.0", "1.0.8"); diff --git a/tests/full_cases/log-0.3.4-0.3.8 b/tests/full_cases/log-0.3.4-0.3.8 new file mode 100644 index 0000000000000..f5f0905f47e4a --- /dev/null +++ b/tests/full_cases/log-0.3.4-0.3.8 @@ -0,0 +1,178 @@ + Updating registry `https://github.com/rust-lang/crates.io-index` + Fresh log v0.3.8 + Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs + Updating registry `https://github.com/rust-lang/crates.io-index` + Fresh libc v0.2.29 + Fresh log v0.3.4 + Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs +version bump: 0.3.4 -> (technically breaking) -> 0.4.0 +warning: technically breaking changes in `` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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 `` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:410:27 + | +410 | #[derive(Copy, Eq, Debug, Hash)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:517:10 + | +517 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::Eq>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:552:10 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::PartialEq>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:552:14 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::Ord>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:552:25 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::PartialOrd>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:552:30 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::hash::Hash>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:552:42 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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 `` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:591:1 + | +591 | / impl Log for NopLogger { +592 | | fn enabled(&self, _: &LogMetadata) -> bool { false } +593 | | +594 | | fn log(&self, _: &LogRecord) {} +595 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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 `` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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 `` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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 `` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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 `` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:713:1 + | +713 | / pub unsafe fn set_logger_raw(make_logger: M) -> Result<(), SetLoggerError> +714 | | where M: FnOnce(MaxLogLevelFilter) -> *const Log { +715 | | if STATE.compare_and_swap(UNINITIALIZED, INITIALIZING, +716 | | Ordering::SeqCst) != UNINITIALIZED { +... | +722 | | Ok(()) +723 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `shutdown_logger` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:736:1 + | +736 | / pub fn shutdown_logger() -> Result, ShutdownLoggerError> { +737 | | shutdown_logger_raw().map(|l| unsafe { mem::transmute(l) }) +738 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `shutdown_logger_raw` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:797:1 + | +797 | pub struct ShutdownLoggerError(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + diff --git a/tests/full_cases/serde-0.7.0-1.0.0 b/tests/full_cases/serde-0.7.0-1.0.0 new file mode 100644 index 0000000000000..767312db6bb75 --- /dev/null +++ b/tests/full_cases/serde-0.7.0-1.0.0 @@ -0,0 +1,4128 @@ + Updating registry `https://github.com/rust-lang/crates.io-index` + Fresh serde v1.0.0 + Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs + Updating registry `https://github.com/rust-lang/crates.io-index` + Fresh serde v0.7.0 + Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs +version bump: 0.7.0 -> (breaking) -> 1.0.0 +warning: path changes to `forward_to_deserialize_any` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1404:1 + | +1404 | / pub trait SerializeSeq { +1405 | | /// Must match the `Ok` type of our `Serializer`. +1406 | | type Ok; +1407 | | +... | +1417 | | fn end(self) -> Result; +1418 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `SerializeTuple` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1491:1 + | +1491 | / pub trait SerializeTuple { +1492 | | /// Must match the `Ok` type of our `Serializer`. +1493 | | type Ok; +1494 | | +... | +1504 | | fn end(self) -> Result; +1505 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `SerializeTupleStruct` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1526:1 + | +1526 | / pub trait SerializeTupleStruct { +1527 | | /// Must match the `Ok` type of our `Serializer`. +1528 | | type Ok; +1529 | | +... | +1539 | | fn end(self) -> Result; +1540 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `SerializeTupleVariant` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1574:1 + | +1574 | / pub trait SerializeTupleVariant { +1575 | | /// Must match the `Ok` type of our `Serializer`. +1576 | | type Ok; +1577 | | +... | +1587 | | fn end(self) -> Result; +1588 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `SerializeMap` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1629:1 + | +1629 | / pub trait SerializeMap { +1630 | | /// Must match the `Ok` type of our `Serializer`. +1631 | | type Ok; +1632 | | +... | +1687 | | fn end(self) -> Result; +1688 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `SerializeStruct` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1713:1 + | +1713 | / pub trait SerializeStruct { +1714 | | /// Must match the `Ok` type of our `Serializer`. +1715 | | type Ok; +1716 | | +... | +1730 | | fn end(self) -> Result; +1731 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `SerializeStructVariant` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1758:1 + | +1758 | / pub trait SerializeStructVariant { +1759 | | /// Must match the `Ok` type of our `Serializer`. +1760 | | type Ok; +1761 | | +... | +1775 | | fn end(self) -> Result; +1776 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: technically breaking changes in `new::ser::impls::` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:73:1 + | +73 | / impl Serialize for CStr { +74 | | #[inline] +75 | | fn serialize(&self, serializer: S) -> Result +76 | | where +... | +80 | | } +81 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:84:1 + | +84 | / impl Serialize for CString { +85 | | #[inline] +86 | | fn serialize(&self, serializer: S) -> Result +87 | | where +... | +91 | | } +92 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:127:1 + | +127 | / impl Serialize for [T; 0] { +128 | | #[inline] +129 | | fn serialize(&self, serializer: S) -> Result +130 | | where +... | +134 | | } +135 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:182:9 + | +182 | / impl Serialize for $ty +183 | | where +184 | | T: Serialize $(+ $tbound1 $(+ $tbound2)*)*, +185 | | $($typaram: $bound,)* +... | +193 | | } +194 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:219:1 + | +219 | / impl Serialize for ops::Range +220 | | where +221 | | Idx: Serialize, +222 | | { +... | +232 | | } +233 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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::>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:295:9 + | +295 | / impl Serialize for $ty +296 | | where +297 | | K: Serialize $(+ $kbound1 $(+ $kbound2)*)*, +298 | | V: Serialize, +... | +307 | | } +308 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:354:1 + | +354 | / impl Serialize for Cell +355 | | where +356 | | T: Serialize + Copy, +357 | | { +... | +363 | | } +364 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:366:1 + | +366 | / impl Serialize for RefCell +367 | | where +368 | | T: Serialize, +369 | | { +... | +375 | | } +376 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:379:1 + | +379 | / impl Serialize for Mutex +380 | | where +381 | | T: Serialize, +382 | | { +... | +391 | | } +392 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:395:1 + | +395 | / impl Serialize for RwLock +396 | | where +397 | | T: Serialize, +398 | | { +... | +407 | | } +408 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:433:1 + | +433 | / impl Serialize for Duration { +434 | | fn serialize(&self, serializer: S) -> Result +435 | | where +436 | | S: Serializer, +... | +443 | | } +444 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:475:1 + | +475 | / impl Serialize for net::IpAddr { +476 | | fn serialize(&self, serializer: S) -> Result +477 | | where +478 | | S: Serializer, +... | +484 | | } +485 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:574:1 + | +574 | / impl Serialize for OsStr { +575 | | #[cfg(unix)] +576 | | fn serialize(&self, serializer: S) -> Result +577 | | where +... | +592 | | } +593 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::ser::impls::` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:596:1 + | +596 | / impl Serialize for OsString { +597 | | fn serialize(&self, serializer: S) -> Result +598 | | where +599 | | S: Serializer, +... | +602 | | } +603 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: path changes to `Impossible` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impossible.rs:71:1 + | +71 | / pub struct Impossible { +72 | | void: Void, +73 | | ok: PhantomData, +74 | | error: PhantomData, +75 | | } + | |_^ + | +note: added path (technically breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:121:9 + | +121| pub use self::impossible::Impossible; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: path changes to `Error` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/lib.rs:27:41 + | +27 | pub use de::{Deserialize, Deserializer, Error}; + | ^^^^^ + +warning: path changes to `Unexpected` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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 `` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:78:1 + | +78 | / impl ser::Error for Error { +79 | | fn custom(msg: T) -> Self +80 | | where +81 | | T: Display, +... | +84 | | } +85 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::clone::Clone>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:120:10 + | +120 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:120:17 + | +120 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::clone::Clone>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:158:18 + | +158 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:158:25 + | +158 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::clone::Clone>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:215:10 + | +215 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:215:17 + | +215 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::clone::Clone>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:287:10 + | +287 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:287:17 + | +287 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::clone::Clone>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:360:10 + | +360 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:437:1 + | +437 | / pub struct CowStrDeserializer<'a, E> { +438 | | value: Cow<'a, str>, +439 | | marker: PhantomData, +440 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:458:1 + | +458 | / impl<'de, 'a, E> de::Deserializer<'de> for CowStrDeserializer<'a, E> +459 | | where +460 | | E: de::Error, +461 | | { +... | +492 | | } +493 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::clone::Clone>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:514:10 + | +514 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:542:5 + | +542 | / pub fn end(mut self) -> Result<(), E> { +543 | | let mut remaining = 0; +544 | | while self.iter.next().is_some() { +545 | | remaining += 1; +... | +553 | | } +554 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:557:1 + | +557 | / impl<'de, I, T, E> de::Deserializer<'de> for SeqDeserializer +558 | | where +559 | | I: Iterator, +560 | | T: IntoDeserializer<'de, E>, +... | +578 | | } +579 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: path changes to `SeqAccessDeserializer` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:664:1 + | +664 | / pub struct SeqAccessDeserializer { +665 | | seq: A, +666 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:675:1 + | +675 | / impl<'de, A> de::Deserializer<'de> for SeqAccessDeserializer +676 | | where +677 | | A: de::SeqAccess<'de>, +678 | | { +... | +692 | | } +693 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:735:5 + | +735 | / pub fn end(mut self) -> Result<(), E> { +736 | | let mut remaining = 0; +737 | | while self.iter.next().is_some() { +738 | | remaining += 1; +... | +746 | | } +747 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:766:1 + | +766 | / impl<'de, I, E> de::Deserializer<'de> for MapDeserializer<'de, I, E> +767 | | where +768 | | I: Iterator, +769 | | I::Item: private::Pair, +... | +810 | | } +811 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::clone::Clone>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:900:1 + | +900 | / impl<'de, I, E> Clone for MapDeserializer<'de, I, E> +901 | | where +902 | | I: Iterator + Clone, +903 | | I::Item: private::Pair, +... | +914 | | } +915 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:918:1 + | +918 | / impl<'de, I, E> Debug for MapDeserializer<'de, I, E> +919 | | where +920 | | I: Iterator + Debug, +921 | | I::Item: private::Pair, +... | +933 | | } +934 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:940:1 + | +940 | / impl<'de, A, B, E> de::Deserializer<'de> for PairDeserializer +941 | | where +942 | | A: IntoDeserializer<'de, E>, +943 | | B: IntoDeserializer<'de, E>, +... | +988 | | } +989 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: path changes to `MapAccessDeserializer` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:1071:1 + | +1071 | / pub struct MapAccessDeserializer { +1072 | | map: A, +1073 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:1082:1 + | +1082 | / impl<'de, A> de::Deserializer<'de> for MapAccessDeserializer +1083 | | where +1084 | | A: de::MapAccess<'de>, +1085 | | { +... | +1099 | | } +1100 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: path changes to `IgnoredAny` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/ignored_any.rs:107:1 + | +107 | pub struct IgnoredAny; + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: added path (technically breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:132:9 + | +132 | pub use self::ignored_any::IgnoredAny; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: technically breaking changes in `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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 `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/ignored_any.rs:207:1 + | +207 | / impl<'de> Deserialize<'de> for IgnoredAny { +208 | | #[inline] +209 | | fn deserialize(deserializer: D) -> Result +210 | | where +... | +214 | | } +215 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for i8>::deserialize::PrimitiveVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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 `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:271:1 + | +271 | / impl<'a> Visitor<'a> for StrVisitor { +272 | | type Value = &'a str; +273 | | +274 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +290 | | } +291 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for &'a str>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:293:1 + | +293 | / impl<'de: 'a, 'a> Deserialize<'de> for &'a str { +294 | | fn deserialize(deserializer: D) -> Result +295 | | where +296 | | D: Deserializer<'de>, +... | +299 | | } +300 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:306:1 + | +306 | / impl<'a> Visitor<'a> for BytesVisitor { +307 | | type Value = &'a [u8]; +308 | | +309 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +325 | | } +326 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for &'a [u8]>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:328:1 + | +328 | / impl<'de: 'a, 'a> Deserialize<'de> for &'a [u8] { +329 | | fn deserialize(deserializer: D) -> Result +330 | | where +331 | | D: Deserializer<'de>, +... | +334 | | } +335 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:343:1 + | +343 | / impl<'de> Visitor<'de> for CStringVisitor { +344 | | type Value = CString; +345 | | +346 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +390 | | } +391 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::ffi::CString>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:394:1 + | +394 | / impl<'de> Deserialize<'de> for CString { +395 | | fn deserialize(deserializer: D) -> Result +396 | | where +397 | | D: Deserializer<'de>, +... | +400 | | } +401 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:472:1 + | +472 | / impl<'de, T> Visitor<'de> for PhantomDataVisitor { +473 | | type Value = PhantomData; +474 | | +475 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +485 | | } +486 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::marker::PhantomData>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:488:1 + | +488 | / impl<'de, T> Deserialize<'de> for PhantomData { +489 | | fn deserialize(deserializer: D) -> Result, D::Error> +490 | | where +491 | | D: Deserializer<'de>, +... | +495 | | } +496 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::collections::HashSet>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:509:9 + | +509 | / impl<'de, T $(, $typaram)*> Deserialize<'de> for $ty +510 | | where +511 | | T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*, +512 | | $($typaram: $bound1 $(+ $bound2)*,)* +... | +550 | | } +551 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::collections::BTreeSet>::deserialize::SeqVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:522:17 + | +522 | / impl<'de, T $(, $typaram)*> Visitor<'de> for SeqVisitor +523 | | where +524 | | T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*, +525 | | $($typaram: $bound1 $(+ $bound2)*,)* +... | +545 | | } +546 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:615:1 + | +615 | / impl<'de, T> Visitor<'de> for ArrayVisitor<[T; 0]> { +616 | | type Value = [T; 0]; +617 | | +618 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +628 | | } +629 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for [T; 0]>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:632:1 + | +632 | / impl<'de, T> Deserialize<'de> for [T; 0] { +633 | | fn deserialize(deserializer: D) -> Result<[T; 0], D::Error> +634 | | where +635 | | D: Deserializer<'de>, +... | +638 | | } +639 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:644:13 + | +644 | / impl<'de, T> Visitor<'de> for ArrayVisitor<[T; $len]> +645 | | where +646 | | T: Deserialize<'de>, +647 | | { +... | +667 | | } +668 | | } + | |_____________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:735:13 + | +735 | / impl<'de, $($name: Deserialize<'de>),+> Visitor<'de> for $visitor<$($name,)+> { +736 | | type Value = ($($name,)+); +737 | | +738 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +756 | | } +757 | | } + | |_____________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14)>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:759:13 + | +759 | / impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) { +760 | | #[inline] +761 | | fn deserialize(deserializer: D) -> Result<($($name,)+), D::Error> +762 | | where +... | +766 | | } +767 | | } + | |_____________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::collections::HashMap>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:801:9 + | +801 | / impl<'de, K, V $(, $typaram)*> Deserialize<'de> for $ty +802 | | where +803 | | K: Deserialize<'de> $(+ $kbound1 $(+ $kbound2)*)*, +804 | | V: Deserialize<'de>, +... | +844 | | } +845 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::collections::HashMap>::deserialize::MapVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:815:17 + | +815 | / impl<'de, K, V $(, $typaram)*> Visitor<'de> for MapVisitor +816 | | where +817 | | K: Deserialize<'de> $(+ $kbound1 $(+ $kbound2)*)*, +818 | | V: Deserialize<'de>, +... | +839 | | } +840 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::net::IpAddr>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:868:9 + | +868 | / impl<'de> Deserialize<'de> for $ty { +869 | | fn deserialize(deserializer: D) -> Result +870 | | where +871 | | D: Deserializer<'de>, +... | +875 | | } +876 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:952:1 + | +952 | / impl<'de> Deserialize<'de> for OsStringKind { +953 | | fn deserialize(deserializer: D) -> Result +954 | | where +955 | | D: Deserializer<'de>, +... | +1006 | | } +1007 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `<>::deserialize::KindVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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 `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1013:1 + | +1013 | / impl<'de> Visitor<'de> for OsStringVisitor { +1014 | | type Value = OsString; +1015 | | +1016 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1047 | | } +1048 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::ffi::OsString>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1051:1 + | +1051 | / impl<'de> Deserialize<'de> for OsString { +1052 | | fn deserialize(deserializer: D) -> Result +1053 | | where +1054 | | D: Deserializer<'de>, +... | +1057 | | } +1058 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::boxed::Box<[T]>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1076:1 + | +1076 | / impl<'de, T> Deserialize<'de> for Box<[T]> +1077 | | where +1078 | | T: Deserialize<'de>, +1079 | | { +... | +1085 | | } +1086 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::boxed::Box>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1089:1 + | +1089 | / impl<'de> Deserialize<'de> for Box { +1090 | | fn deserialize(deserializer: D) -> Result +1091 | | where +1092 | | D: Deserializer<'de>, +... | +1095 | | } +1096 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::cell::Cell>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1141:1 + | +1141 | / impl<'de, T> Deserialize<'de> for Cell +1142 | | where +1143 | | T: Deserialize<'de> + Copy, +1144 | | { +... | +1150 | | } +1151 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::cell::RefCell>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1153:1 + | +1153 | / impl<'de, T> Deserialize<'de> for RefCell +1154 | | where +1155 | | T: Deserialize<'de>, +1156 | | { +... | +1162 | | } +1163 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::sync::Mutex>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1166:1 + | +1166 | / impl<'de, T> Deserialize<'de> for Mutex +1167 | | where +1168 | | T: Deserialize<'de>, +1169 | | { +... | +1175 | | } +1176 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::sync::RwLock>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1179:1 + | +1179 | / impl<'de, T> Deserialize<'de> for RwLock +1180 | | where +1181 | | T: Deserialize<'de>, +1182 | | { +... | +1188 | | } +1189 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::time::Duration>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1202:1 + | +1202 | / impl<'de> Deserialize<'de> for Duration { +1203 | | fn deserialize(deserializer: D) -> Result +1204 | | where +1205 | | D: Deserializer<'de>, +... | +1324 | | } +1325 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::time::Duration>::deserialize::Field as new::Deserialize<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1216:9 + | +1216 | / impl<'de> Deserialize<'de> for Field { +1217 | | fn deserialize(deserializer: D) -> Result +1218 | | where +1219 | | D: Deserializer<'de>, +... | +1257 | | } +1258 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `< for std::time::Duration>::deserialize::Field as new::Deserialize<'de>>::deserialize::FieldVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1223:17 + | +1223 | / impl<'de> Visitor<'de> for FieldVisitor { +1224 | | type Value = Field; +1225 | | +1226 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1253 | | } +1254 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::time::Duration>::deserialize::DurationVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1262:9 + | +1262 | / impl<'de> Visitor<'de> for DurationVisitor { +1263 | | type Value = Duration; +1264 | | +1265 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1319 | | } +1320 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for std::ops::Range>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1338:1 + | +1338 | / impl<'de, Idx> Deserialize<'de> for ops::Range +1339 | | where +1340 | | Idx: Deserialize<'de>, +1341 | | { +... | +1468 | | } +1469 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::ops::Range>::deserialize::Field as new::Deserialize<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1355:9 + | +1355 | / impl<'de> Deserialize<'de> for Field { +1356 | | fn deserialize(deserializer: D) -> Result +1357 | | where +1358 | | D: Deserializer<'de>, +... | +1396 | | } +1397 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `< for std::ops::Range>::deserialize::Field as new::Deserialize<'de>>::deserialize::FieldVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1362:17 + | +1362 | / impl<'de> Visitor<'de> for FieldVisitor { +1363 | | type Value = Field; +1364 | | +1365 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1392 | | } +1393 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::ops::Range>::deserialize::RangeVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1403:9 + | +1403 | / impl<'de, Idx> Visitor<'de> for RangeVisitor +1404 | | where +1405 | | Idx: Deserialize<'de>, +1406 | | { +... | +1463 | | } +1464 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::result::Result>::deserialize::Field as new::Deserialize<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1513:9 + | +1513 | / impl<'de> Deserialize<'de> for Field { +1514 | | #[inline] +1515 | | fn deserialize(deserializer: D) -> Result +1516 | | where +... | +1572 | | } +1573 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `< for std::result::Result>::deserialize::Field as new::Deserialize<'de>>::deserialize::FieldVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1521:17 + | +1521 | / impl<'de> Visitor<'de> for FieldVisitor { +1522 | | type Value = Field; +1523 | | +1524 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1568 | | } +1569 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::result::Result>::deserialize::ResultVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1577:9 + | +1577 | / impl<'de, T, E> Visitor<'de> for ResultVisitor +1578 | | where +1579 | | T: Deserialize<'de>, +1580 | | E: Deserialize<'de>, +... | +1596 | | } +1597 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: path changes to `export` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/macros.rs:11:1 + | +11 | / macro_rules! __private_serialize { +12 | | () => { +13 | | trait Serialize { +14 | | fn serialize(&self, serializer: S) -> Result +... | +18 | | }; +19 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `__private_deserialize` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/macros.rs:23:1 + | +23 | / macro_rules! __private_deserialize { +24 | | () => { +25 | | trait Deserialize<'de>: Sized { +26 | | fn deserialize(deserializer: D) -> Result +... | +30 | | }; +31 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `__serialize_unimplemented` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/macros.rs:46:1 + | +46 | / macro_rules! __serialize_unimplemented_method { +47 | | ($func:ident $(<$t:ident>)* ($($arg:ty),*) -> $ret:ident) => { +48 | | fn $func $(<$t: ?Sized + $crate::Serialize>)* (self $(, _: $arg)*) -> $crate::export::Result { +49 | | unimplemented!() +50 | | } +51 | | }; +52 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `__serialize_unimplemented_helper` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/macros.rs:56:1 + | +56 | / macro_rules! __serialize_unimplemented_helper { +57 | | (bool) => { +58 | | __serialize_unimplemented_method!(serialize_bool(bool) -> Ok); +59 | | }; +... | +147 | | }; +148 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: technically breaking changes in ` as new::Serializer>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/ser.rs:107:1 + | +107 | / impl Serializer for TaggedSerializer +108 | | where +109 | | S: Serializer, +110 | | { +... | +336 | | } +337 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/ser.rs:344:1 + | +344 | / impl ser::Error for Error { +345 | | fn custom(_: T) -> Self +346 | | where +347 | | T: Display, +... | +350 | | } +351 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/ser.rs:491:5 + | +491 | / impl Serialize for Content { +492 | | fn serialize(&self, serializer: S) -> Result +493 | | where +494 | | S: Serializer, +... | +570 | | } +571 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Serializer>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/ser.rs:583:5 + | +583 | / impl Serializer for ContentSerializer +584 | | where +585 | | E: ser::Error, +586 | | { +... | +803 | | } +804 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:30:5 + | +30 | / impl<'de, E> Deserializer<'de> for MissingFieldDeserializer +31 | | where +32 | | E: Error, +33 | | { +... | +54 | | } +55 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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 `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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 `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:290:5 + | +290 | / impl<'de> Deserialize<'de> for Content { +291 | | fn deserialize(deserializer: D) -> Result +292 | | where +293 | | D: Deserializer<'de>, +... | +298 | | } +299 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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 `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:511:5 + | +511 | / impl<'de> Visitor<'de> for TagOrContentVisitor { +512 | | type Value = TagOrContent; +513 | | +514 | | fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +... | +731 | | } +732 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:775:5 + | +775 | / impl<'de, T> Visitor<'de> for TaggedContentVisitor +776 | | where +777 | | T: Deserialize<'de>, +778 | | { +... | +817 | | } +818 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:845:5 + | +845 | / impl<'de> Visitor<'de> for TagOrContentFieldVisitor { +846 | | type Value = TagOrContentField; +847 | | +848 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +863 | | } +864 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:874:5 + | +874 | / impl<'de, E> Deserializer<'de> for ContentDeserializer +875 | | where +876 | | E: de::Error, +877 | | { +... | +999 | | } +1000 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1125:5 + | +1125 | / impl<'de, E> de::Deserializer<'de> for SeqDeserializer +1126 | | where +1127 | | E: de::Error, +1128 | | { +... | +1154 | | } +1155 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1237:5 + | +1237 | / impl<'de, E> de::Deserializer<'de> for MapDeserializer +1238 | | where +1239 | | E: de::Error, +1240 | | { +... | +1255 | | } +1256 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1266:5 + | +1266 | / impl<'de, 'a, E> Deserializer<'de> for ContentRefDeserializer<'a, E> +1267 | | where +1268 | | E: de::Error, +1269 | | { +... | +1391 | | } +1392 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1517:5 + | +1517 | / impl<'de, 'a, E> de::Deserializer<'de> for SeqRefDeserializer<'a, E> +1518 | | where +1519 | | E: de::Error, +1520 | | { +... | +1546 | | } +1547 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1630:5 + | +1630 | / impl<'de, 'a, E> de::Deserializer<'de> for MapRefDeserializer<'a, E> +1631 | | where +1632 | | E: de::Error, +1633 | | { +... | +1648 | | } +1649 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1691:5 + | +1691 | / impl<'de, 'a> Visitor<'de> for InternallyTaggedUnitVisitor<'a> { +1692 | | type Value = (); +1693 | | +1694 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1703 | | } +1704 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1724:5 + | +1724 | / impl<'de, 'a> Visitor<'de> for UntaggedUnitVisitor<'a> { +1725 | | type Value = (); +1726 | | +1727 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1736 | | } +1737 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1788:1 + | +1788 | / impl<'de, 'a, E> Deserializer<'de> for StrDeserializer<'a, E> +1789 | | where +1790 | | E: Error, +1791 | | { +... | +1805 | | } +1806 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/bytes.rs:1:1 + | +1 | / //! Helper module to enable serializing bytes more efficiently +2 | | +3 | | use std::ops; +4 | | use std::fmt; +... | +215 | | result +216 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: breaking changes in ` as old::Serialize>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/bytes.rs:52:1 + | +52 | / impl<'a> ser::Serialize for Bytes<'a> { +53 | | #[inline] +54 | | fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> +55 | | where S: ser::Serializer +... | +58 | | } +59 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/bytes.rs:139:1 + | +139 | / impl ser::Serialize for ByteBuf { +140 | | fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> +141 | | where S: ser::Serializer +142 | | { +143 | | serializer.serialize_bytes(&self) +144 | | } +145 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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 `` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/bytes.rs:197:1 + | +197 | / impl de::Deserialize for ByteBuf { +198 | | #[inline] +199 | | fn deserialize(deserializer: &mut D) -> Result +200 | | where D: de::Deserializer +... | +203 | | } +204 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `Error` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:18:5 + | +18 | fn end_of_stream() -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: breaking changes in `custom` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:180:13 + | +180 | / fn custom(msg: T) -> Self +181 | | where +182 | | T: Display; + | |___________________________^ + | + = warning: added bound: `T: std::fmt::Display` (breaking) + = note: removed bound: `std::string::String: std::convert::From` (technically breaking) + +error: breaking changes in `invalid_type` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:503:5 + | +503 | / fn deserialize(deserializer: D) -> Result +504 | | where +505 | | D: Deserializer<'de>; + | |_____________________________^ + | + = warning: type error: expected old::Deserializer::Error, found new::Deserializer::Error (breaking) + +error: breaking changes in `Deserializer` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:809:5 + | +809 | / fn deserialize_any(self, visitor: V) -> Result +810 | | where +811 | | V: Visitor<'de>; + | |________________________^ +warning: removed item from trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:180:5 + | +180 | / fn deserialize(&mut self, visitor: V) -> Result +181 | | where V: Visitor; + | |_________________________^ +warning: added item to trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:913:5 + | +913 | / fn deserialize_byte_buf(self, visitor: V) -> Result +914 | | where +915 | | V: Visitor<'de>; + | |________________________^ +warning: added item to trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1002:5 + | +1002 | / fn deserialize_identifier(self, visitor: V) -> Result +1003 | | where +1004 | | V: Visitor<'de>; + | |________________________^ +warning: removed defaulted item from trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:193:5 + | +193 | / fn deserialize_usize(&mut self, visitor: V) -> Result +194 | | where V: Visitor, +195 | | { +196 | | self.deserialize_u64(visitor) +197 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:233:5 + | +233 | / fn deserialize_isize(&mut self, visitor: V) -> Result +234 | | where V: Visitor, +235 | | { +236 | | self.deserialize_i64(visitor) +237 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:343:5 + | +343 | / fn deserialize_fixed_size_array(&mut self, +344 | | _len: usize, +345 | | visitor: V) -> Result +346 | | where V: Visitor, +347 | | { +348 | | self.deserialize(visitor) +349 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:420:5 + | +420 | / fn deserialize_struct_field(&mut self, visitor: V) -> Result +421 | | where V: Visitor, +422 | | { +423 | | self.deserialize(visitor) +424 | | } + | |_____^ + +error: breaking changes in `deserialize_bool` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:814:5 + | +814 | / fn deserialize_bool(self, visitor: V) -> Result +815 | | where +816 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_u8` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:839:5 + | +839 | / fn deserialize_u8(self, visitor: V) -> Result +840 | | where +841 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_u16` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:844:5 + | +844 | / fn deserialize_u16(self, visitor: V) -> Result +845 | | where +846 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_u32` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:849:5 + | +849 | / fn deserialize_u32(self, visitor: V) -> Result +850 | | where +851 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_u64` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:854:5 + | +854 | / fn deserialize_u64(self, visitor: V) -> Result +855 | | where +856 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_i8` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:819:5 + | +819 | / fn deserialize_i8(self, visitor: V) -> Result +820 | | where +821 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_i16` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:824:5 + | +824 | / fn deserialize_i16(self, visitor: V) -> Result +825 | | where +826 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_i32` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:829:5 + | +829 | / fn deserialize_i32(self, visitor: V) -> Result +830 | | where +831 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_i64` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:834:5 + | +834 | / fn deserialize_i64(self, visitor: V) -> Result +835 | | where +836 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_f32` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:859:5 + | +859 | / fn deserialize_f32(self, visitor: V) -> Result +860 | | where +861 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_f64` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:864:5 + | +864 | / fn deserialize_f64(self, visitor: V) -> Result +865 | | where +866 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_char` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:869:5 + | +869 | / fn deserialize_char(self, visitor: V) -> Result +870 | | where +871 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_str` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:880:5 + | +880 | / fn deserialize_str(self, visitor: V) -> Result +881 | | where +882 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_string` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:891:5 + | +891 | / fn deserialize_string(self, visitor: V) -> Result +892 | | where +893 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_unit` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:927:5 + | +927 | / fn deserialize_unit(self, visitor: V) -> Result +928 | | where +929 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_option` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:922:5 + | +922 | / fn deserialize_option(self, visitor: V) -> Result +923 | | where +924 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_seq` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:952:5 + | +952 | / fn deserialize_seq(self, visitor: V) -> Result +953 | | where +954 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_bytes` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:902:5 + | +902 | / fn deserialize_bytes(self, visitor: V) -> Result +903 | | where +904 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_map` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:974:5 + | +974 | / fn deserialize_map(self, visitor: V) -> Result +975 | | where +976 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_unit_struct` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:933:5 + | +933 | / fn deserialize_unit_struct( +934 | | self, +935 | | name: &'static str, +936 | | visitor: V, +937 | | ) -> Result +938 | | where +939 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_newtype_struct` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:943:5 + | +943 | / fn deserialize_newtype_struct( +944 | | self, +945 | | name: &'static str, +946 | | visitor: V, +947 | | ) -> Result +948 | | where +949 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_tuple_struct` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:964:5 + | +964 | / fn deserialize_tuple_struct( +965 | | self, +966 | | name: &'static str, +967 | | len: usize, +... | +970 | | where +971 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_struct` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:980:5 + | +980 | / fn deserialize_struct( +981 | | self, +982 | | name: &'static str, +983 | | fields: &'static [&'static str], +... | +986 | | where +987 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_tuple` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:958:5 + | +958 | / fn deserialize_tuple(self, len: usize, visitor: V) -> Result +959 | | where +960 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_enum` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:991:5 + | +991 | / fn deserialize_enum( +992 | | self, +993 | | name: &'static str, +994 | | variants: &'static [&'static str], +... | +997 | | where +998 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `deserialize_ignored_any` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1010:5 + | +1010 | / fn deserialize_ignored_any(self, visitor: V) -> Result +1011 | | where +1012 | | V: Visitor<'de>; + | |________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `Visitor` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1242:5 + | +1242 | / fn visit_borrowed_str(self, v: &'de str) -> Result +1243 | | where +1244 | | E: Error, +1245 | | { +1246 | | self.visit_str(v) +1247 | | } + | |_____^ +note: added defaulted item to trait (technically breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1301:5 + | +1301 | / fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result +1302 | | where +1303 | | E: Error, +1304 | | { +1305 | | self.visit_bytes(v) +1306 | | } + | |_____^ +note: added defaulted item to trait (technically breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1402:5 + | +1402 | / fn visit_enum(self, data: A) -> Result +1403 | | where +1404 | | A: EnumAccess<'de>, +1405 | | { +1406 | | let _ = data; +1407 | | Err(Error::invalid_type(Unexpected::Enum, &self)) +1408 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:508:5 + | +508 | / fn visit_usize(&mut self, v: usize) -> Result +509 | | where E: Error, +510 | | { +511 | | self.visit_u64(v as u64) +512 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:473:5 + | +473 | / fn visit_isize(&mut self, v: isize) -> Result +474 | | where E: Error, +475 | | { +476 | | self.visit_i64(v as i64) +477 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:592:5 + | +592 | / fn visit_unit_struct(&mut self, _name: &'static str) -> Result +593 | | where E: Error, +594 | | { +595 | | self.visit_unit() +596 | | } + | |_____^ + +error: breaking changes in `visit_bool` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1079:5 + | +1079 | / fn visit_bool(self, v: bool) -> Result +1080 | | where +1081 | | E: Error, +1082 | | { +1083 | | Err(Error::invalid_type(Unexpected::Bool(v), &self)) +1084 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_i8` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1091:5 + | +1091 | / fn visit_i8(self, v: i8) -> Result +1092 | | where +1093 | | E: Error, +1094 | | { +1095 | | self.visit_i64(v as i64) +1096 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_i16` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1103:5 + | +1103 | / fn visit_i16(self, v: i16) -> Result +1104 | | where +1105 | | E: Error, +1106 | | { +1107 | | self.visit_i64(v as i64) +1108 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_i32` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1115:5 + | +1115 | / fn visit_i32(self, v: i32) -> Result +1116 | | where +1117 | | E: Error, +1118 | | { +1119 | | self.visit_i64(v as i64) +1120 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_i64` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1125:5 + | +1125 | / fn visit_i64(self, v: i64) -> Result +1126 | | where +1127 | | E: Error, +1128 | | { +1129 | | Err(Error::invalid_type(Unexpected::Signed(v), &self)) +1130 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_u8` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1137:5 + | +1137 | / fn visit_u8(self, v: u8) -> Result +1138 | | where +1139 | | E: Error, +1140 | | { +1141 | | self.visit_u64(v as u64) +1142 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_u16` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1149:5 + | +1149 | / fn visit_u16(self, v: u16) -> Result +1150 | | where +1151 | | E: Error, +1152 | | { +1153 | | self.visit_u64(v as u64) +1154 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_u32` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1161:5 + | +1161 | / fn visit_u32(self, v: u32) -> Result +1162 | | where +1163 | | E: Error, +1164 | | { +1165 | | self.visit_u64(v as u64) +1166 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_u64` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1171:5 + | +1171 | / fn visit_u64(self, v: u64) -> Result +1172 | | where +1173 | | E: Error, +1174 | | { +1175 | | Err(Error::invalid_type(Unexpected::Unsigned(v), &self)) +1176 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_f32` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1183:5 + | +1183 | / fn visit_f32(self, v: f32) -> Result +1184 | | where +1185 | | E: Error, +1186 | | { +1187 | | self.visit_f64(v as f64) +1188 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_f64` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1193:5 + | +1193 | / fn visit_f64(self, v: f64) -> Result +1194 | | where +1195 | | E: Error, +1196 | | { +1197 | | Err(Error::invalid_type(Unexpected::Float(v), &self)) +1198 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_char` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1207:5 + | +1207 | / fn visit_char(self, v: char) -> Result +1208 | | where +1209 | | E: Error, +1210 | | { +1211 | | self.visit_str(utf8::encode(v).as_str()) +1212 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_str` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1225:5 + | +1225 | / fn visit_str(self, v: &str) -> Result +1226 | | where +1227 | | E: Error, +1228 | | { +1229 | | Err(Error::invalid_type(Unexpected::Str(v), &self)) +1230 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_string` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1266:5 + | +1266 | / fn visit_string(self, v: String) -> Result +1267 | | where +1268 | | E: Error, +1269 | | { +1270 | | self.visit_str(&v) +1271 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_unit` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1356:5 + | +1356 | / fn visit_unit(self) -> Result +1357 | | where +1358 | | E: Error, +1359 | | { +1360 | | Err(Error::invalid_type(Unexpected::Unit, &self)) +1361 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_none` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1335:5 + | +1335 | / fn visit_none(self) -> Result +1336 | | where +1337 | | E: Error, +1338 | | { +1339 | | Err(Error::invalid_type(Unexpected::Option, &self)) +1340 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_some` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1345:5 + | +1345 | / fn visit_some(self, deserializer: D) -> Result +1346 | | where +1347 | | D: Deserializer<'de>, +1348 | | { +1349 | | let _ = deserializer; +1350 | | Err(Error::invalid_type(Unexpected::Option, &self)) +1351 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_newtype_struct` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1369:5 + | +1369 | / fn visit_newtype_struct(self, deserializer: D) -> Result +1370 | | where +1371 | | D: Deserializer<'de>, +1372 | | { +1373 | | let _ = deserializer; +1374 | | Err(Error::invalid_type(Unexpected::NewtypeStruct, &self)) +1375 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_seq` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1380:5 + | +1380 | / fn visit_seq(self, seq: A) -> Result +1381 | | where +1382 | | A: SeqAccess<'de>, +1383 | | { +1384 | | let _ = seq; +1385 | | Err(Error::invalid_type(Unexpected::Seq, &self)) +1386 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_map` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1391:5 + | +1391 | / fn visit_map(self, map: A) -> Result +1392 | | where +1393 | | A: MapAccess<'de>, +1394 | | { +1395 | | let _ = map; +1396 | | Err(Error::invalid_type(Unexpected::Map, &self)) +1397 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_bytes` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1284:5 + | +1284 | / fn visit_bytes(self, v: &[u8]) -> Result +1285 | | where +1286 | | E: Error, +1287 | | { +1288 | | let _ = v; +1289 | | Err(Error::invalid_type(Unexpected::Bytes(v), &self)) +1290 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `visit_byte_buf` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1325:5 + | +1325 | / fn visit_byte_buf(self, v: Vec) -> Result +1326 | | where +1327 | | E: Error, +1328 | | { +1329 | | self.visit_bytes(&v) +1330 | | } + | |_____^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: path changes to `SeqVisitor` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:24:1 + | +24 | struct UnitVisitor; + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: item made private (breaking) + +error: breaking changes in `BoolVisitor` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:52:1 + | +52 | struct BoolVisitor; + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: item made private (breaking) + +error: breaking changes in ` as old::de::Visitor>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:135:1 + | +135 | / impl Visitor for PrimitiveVisitor +136 | | where T: Deserialize + FromPrimitive + str::FromStr +137 | | { +138 | | type Value = T; +... | +160 | | } +161 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::Visitor>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:281:1 + | +281 | / impl< +282 | | T: Deserialize, +283 | | > Visitor for OptionVisitor { +284 | | type Value = Option; +... | +305 | | } +306 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:308:1 + | +308 | / impl Deserialize for Option where T: Deserialize { +309 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> +310 | | where D: Deserializer, +311 | | { +312 | | deserializer.deserialize_option(OptionVisitor { marker: PhantomData }) +313 | | } +314 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `PhantomDataVisitor` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:468:1 + | +468 | / struct PhantomDataVisitor { +469 | | marker: PhantomData, +470 | | } + | |_^ + | + = warning: item made private (breaking) + +error: breaking changes in ` as old::de::Visitor>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:323:1 + | +323 | / impl Visitor for PhantomDataVisitor where T: Deserialize { +324 | | type Value = PhantomData; +325 | | +326 | | #[inline] +... | +331 | | } +332 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:334:1 + | +334 | / impl Deserialize for PhantomData where T: Deserialize { +335 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> +336 | | where D: Deserializer, +337 | | { +... | +340 | | } +341 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: path changes to `VecDequeVisitor` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:356:9 + | +356 | / pub struct $visitor_name { +357 | | marker: PhantomData, +358 | | } + | |_________^ + | + = warning: removed definition (breaking) + +error: breaking changes in ` as old::de::Visitor>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:369:9 + | +369 | / impl Visitor for $visitor_name +370 | | where T: $($constraints +)*, +371 | | { +372 | | type Value = $ty; +... | +394 | | } +395 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:397:9 + | +397 | / impl Deserialize for $ty +398 | | where T: $($constraints +)*, +399 | | { +400 | | fn deserialize(deserializer: &mut D) -> Result<$ty, D::Error> +... | +404 | | } +405 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::Visitor>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:488:1 + | +488 | / impl Visitor for ArrayVisitor0 where T: Deserialize + Default { +489 | | type Value = [T; 0]; +490 | | +491 | | #[inline] +... | +504 | | } +505 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:507:1 + | +507 | / impl Deserialize for [T; 0] +508 | | where T: Deserialize + Default +509 | | { +510 | | fn deserialize(deserializer: &mut D) -> Result<[T; 0], D::Error> +... | +514 | | } +515 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::Visitor>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:533:13 + | +533 | / impl Visitor for $visitor where T: Deserialize { +534 | | type Value = [T; $len]; +535 | | +536 | | #[inline] +... | +550 | | } +551 | | } + | |_____________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:553:13 + | +553 | / impl Deserialize for [T; $len] +554 | | where T: Deserialize, +555 | | { +556 | | fn deserialize(deserializer: &mut D) -> Result<[T; $len], D::Error> +... | +560 | | } +561 | | } + | |_____________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `TupleVisitor9` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:624:17 + | +624 | / pub fn new() -> Self { +625 | | $visitor { marker: PhantomData } +626 | | } + | |_________________^ + | + = warning: removed item in inherent impl (breaking) + +error: breaking changes in ` as old::de::Visitor>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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::` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:695:9 + | +695 | / pub struct $visitor_name { +696 | | marker: PhantomData<$ty>, +697 | | } + | |_________^ + | + = warning: removed definition (breaking) + +error: breaking changes in ` as old::de::Visitor>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:708:9 + | +708 | / impl Visitor for $visitor_name +709 | | where K: $($constraints +)*, +710 | | V: Deserialize, +711 | | { +... | +734 | | } +735 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:737:9 + | +737 | / impl Deserialize for $ty +738 | | where K: $($constraints +)*, +739 | | V: Deserialize, +740 | | { +... | +745 | | } +746 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:875:1 + | +875 | / impl Deserialize for Box { +876 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> +877 | | where D: Deserializer, +878 | | { +... | +881 | | } +882 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:884:1 + | +884 | / impl Deserialize for Arc { +885 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> +886 | | where D: Deserializer, +887 | | { +... | +890 | | } +891 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:893:1 + | +893 | / impl Deserialize for Rc { +894 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> +895 | | where D: Deserializer, +896 | | { +... | +899 | | } +900 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:902:1 + | +902 | / impl<'a, T: ?Sized> Deserialize for Cow<'a, T> where T: ToOwned, T::Owned: Deserialize, { +903 | | #[inline] +904 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> +905 | | where D: Deserializer, +... | +909 | | } +910 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::de::impls::>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:930:1 + | +930 | / impl Deserialize for Result where T: Deserialize, E: Deserialize { +931 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> +932 | | where D: Deserializer { +933 | | enum Field { +... | +1009 | | } +1010 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `>::deserialize::Field as old::Deserialize>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:938:9 + | +938 | / impl Deserialize for Field { +939 | | #[inline] +940 | | fn deserialize(deserializer: &mut D) -> Result +941 | | where D: Deserializer +... | +979 | | } +980 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `<>::deserialize::Field as old::Deserialize>::deserialize::FieldVisitor as old::de::Visitor>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:945:17 + | +945 | / impl ::de::Visitor for FieldVisitor { +946 | | type Value = Field; +947 | | +948 | | fn visit_usize(&mut self, value: usize) -> Result where E: Error { +... | +975 | | } +976 | | } + | |_________________^ + | + = warning: trait impl specialized or removed (breaking) + +error: path changes to `IgnoredAny` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:1016:1 + | +1016 | pub struct IgnoredAny; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: removed definition (breaking) + +error: breaking changes in `` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:1018:1 + | +1018 | / impl Deserialize for IgnoredAny { +1019 | | #[inline] +1020 | | fn deserialize(deserializer: &mut D) -> Result +1021 | | where D: Deserializer, +... | +1113 | | } +1114 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `<::deserialize::IgnoredAnyVisitor as old::de::Visitor>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:93:1 + | +93 | / pub trait ValueDeserializer { +94 | | /// The actual deserializer type. +95 | | type Deserializer: de::Deserializer; +96 | | +97 | | /// Convert this value into a deserializer. +98 | | fn into_deserializer(self) -> Self::Deserializer; +99 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: breaking changes in `UnitDeserializer` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:121:1 + | +121 | / pub struct UnitDeserializer { +122 | | marker: PhantomData, +123 | | } + | |_^ + | +warning: variant with no public fields changed to a struct variant (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:121:1 + | +121 | / pub struct UnitDeserializer { +122 | | marker: PhantomData, +123 | | } + | |_^ + +error: breaking changes in `U8Deserializer` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:159:9 + | +159 | / pub struct $name { +160 | | value: $ty, +161 | | marker: PhantomData +162 | | } + | |_________^ + | +warning: variant with no public fields changed to a struct variant (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:159:9 + | +159 | / pub struct $name { +160 | | value: $ty, +161 | | marker: PhantomData +162 | | } + | |_________^ + +error: breaking changes in `StrDeserializer` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:288:1 + | +288 | / pub struct StrDeserializer<'a, E> { +289 | | value: &'a str, +290 | | marker: PhantomData, +291 | | } + | |_^ + | +warning: variant with no public fields changed to a struct variant (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:288:1 + | +288 | / pub struct StrDeserializer<'a, E> { +289 | | value: &'a str, +290 | | marker: PhantomData, +291 | | } + | |_^ + +error: breaking changes in `StringDeserializer` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:361:1 + | +361 | / pub struct StringDeserializer { +362 | | value: String, +363 | | marker: PhantomData, +364 | | } + | |_^ + | +warning: variant with no public fields changed to a struct variant (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:361:1 + | +361 | / pub struct StringDeserializer { +362 | | value: String, +363 | | marker: PhantomData, +364 | | } + | |_^ + +error: breaking changes in `SeqDeserializer` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:515:1 + | +515 | / pub struct SeqDeserializer { +516 | | iter: iter::Fuse, +517 | | count: usize, +518 | | marker: PhantomData, +519 | | } + | |_^ + | +warning: variant field removed from variant with private fields (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:298:5 + | +298 | len: usize, + | ^^^^^^^^^^ +warning: variant field added to variant with private fields (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:517:5 + | +517 | count: usize, + | ^^^^^^^^^^^^ + +error: breaking changes in `new` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:306:5 + | +306 | / pub fn new(iter: I, len: usize) -> Self { +307 | | SeqDeserializer { +308 | | iter: iter, +309 | | len: len, +310 | | marker: PhantomData, +311 | | } +312 | | } + | |_____^ + | + = warning: removed item in inherent impl (breaking) + +error: breaking changes in ` as old::Deserializer>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:315:1 + | +315 | / impl de::Deserializer for SeqDeserializer +316 | | where I: Iterator, +317 | | T: ValueDeserializer, +318 | | E: de::Error, +... | +326 | | } +327 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: path changes to `SeqVisitorDeserializer` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:403:1 + | +403 | / pub struct SeqVisitorDeserializer { +404 | | visitor: V_, +405 | | marker: PhantomData, +406 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: breaking changes in ` as old::Deserializer>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:421:1 + | +421 | / impl de::Deserializer for SeqVisitorDeserializer +422 | | where V_: de::SeqVisitor, +423 | | E: de::Error, +424 | | { +... | +429 | | } +430 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `MapDeserializer` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:698:1 + | +698 | / pub struct MapDeserializer<'de, I, E> +699 | | where +700 | | I: Iterator, +701 | | I::Item: private::Pair, +... | +707 | | error: PhantomData, +708 | | } + | |_^ + | + = warning: region parameter added (breaking) + = warning: type parameter removed (breaking) + = warning: type parameter removed (breaking) +warning: variant field removed from variant with private fields (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:443:5 + | +443 | len: usize, + | ^^^^^^^^^^ +warning: variant field removed from variant with private fields (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:444:5 + | +444 | marker: PhantomData, + | ^^^^^^^^^^^^^^^^^^^^^^ +warning: variant field added to variant with private fields (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:705:5 + | +705 | count: usize, + | ^^^^^^^^^^^^ +warning: variant field added to variant with private fields (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:707:5 + | +707 | error: PhantomData, + | ^^^^^^^^^^^^^^^^^^^^^ +warning: variant field added to variant with private fields (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:706:5 + | +706 | lifetime: PhantomData<&'de ()>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: breaking changes in `new` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:454:5 + | +454 | / pub fn new(iter: I, len: usize) -> Self { +455 | | MapDeserializer { +456 | | iter: iter, +457 | | value: None, +... | +460 | | } +461 | | } + | |_____^ + | + = warning: removed item in inherent impl (breaking) + +error: breaking changes in ` as old::Deserializer>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:464:1 + | +464 | / impl de::Deserializer for MapDeserializer +465 | | where I: Iterator, +466 | | K: ValueDeserializer, +467 | | V: ValueDeserializer, +... | +476 | | } +477 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: path changes to `MapVisitorDeserializer` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:559:1 + | +559 | / pub struct MapVisitorDeserializer { +560 | | visitor: V_, +561 | | marker: PhantomData, +562 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: breaking changes in ` as old::Deserializer>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:577:1 + | +577 | / impl de::Deserializer for MapVisitorDeserializer +578 | | where V_: de::MapVisitor, +579 | | E: de::Error, +580 | | { +... | +585 | | } +586 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: path changes to `BytesDeserializer` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:601:1 + | +601 | pub struct BytesDeserializer<'a, E> (Option<&'a [u8]>, PhantomData); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: removed definition (breaking) + +error: breaking changes in ` as old::Deserializer>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:632:1 + | +632 | pub struct ByteBufDeserializer(Option>, PhantomData); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: removed definition (breaking) + +error: breaking changes in ` as old::Deserializer>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:634:1 + | +634 | / impl de::Deserializer for ByteBufDeserializer +635 | | where E: de::Error, +636 | | { +637 | | type Error = E; +... | +646 | | } +647 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: path changes to `iter` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:165:13 + | +165 | / fn custom(msg: T) -> Self +166 | | where +167 | | T: Display; + | |___________________________^ + | + = warning: added bound: `T: std::fmt::Display` (breaking) + = note: removed bound: `std::string::String: std::convert::From` (technically breaking) + +error: breaking changes in `serialize` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:236:5 + | +236 | / fn serialize(&self, serializer: S) -> Result +237 | | where +238 | | S: Serializer; + | |______________________^ + | + = warning: type error: expected (), found associated type (breaking) + +error: breaking changes in `Serializer` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:319:5 + | +319 | type Ok; + | ^^^^^^^^ +warning: added item to trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:328:5 + | +328 | type SerializeSeq: SerializeSeq; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: added item to trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:334:5 + | +334 | type SerializeTuple: SerializeTuple; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: added item to trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:340:5 + | +340 | type SerializeTupleStruct: SerializeTupleStruct; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: added item to trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:346:5 + | +346 | type SerializeTupleVariant: SerializeTupleVariant; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: added item to trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:352:5 + | +352 | type SerializeMap: SerializeMap; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: added item to trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:358:5 + | +358 | type SerializeStruct: SerializeStruct; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: added item to trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:364:5 + | +364 | type SerializeStructVariant: SerializeStructVariant; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: added defaulted item to trait (technically breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1243:5 + | +1243 | / fn collect_seq(self, iter: I) -> Result +1244 | | where +1245 | | I: IntoIterator, +1246 | | ::Item: Serialize, +... | +1253 | | serializer.end() +1254 | | } + | |_____^ +note: added defaulted item to trait (technically breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1281:5 + | +1281 | / fn collect_map(self, iter: I) -> Result +1282 | | where +1283 | | K: Serialize, +1284 | | V: Serialize, +... | +1292 | | serializer.end() +1293 | | } + | |_____^ +note: added defaulted item to trait (technically breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1325:5 + | +1325 | / fn collect_str(self, value: &T) -> Result +1326 | | where +1327 | | T: Display, +1328 | | { +... | +1332 | | self.serialize_str(&string) +1333 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:200:5 + | +200 | / fn serialize_seq_elt(&mut self, value: T) -> Result<(), Self::Error> +201 | | where T: Serialize; + | |___________________________^ +warning: removed defaulted item from trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:217:5 + | +217 | / fn serialize_tuple_elt(&mut self, value: T) -> Result<(), Self::Error> +218 | | where T: Serialize +219 | | { +220 | | self.serialize_seq_elt(value) +221 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:227:5 + | +227 | / fn serialize_fixed_size_array(&mut self, visitor: V) -> Result<(), Self::Error> +228 | | where V: SeqVisitor, +229 | | { +230 | | self.serialize_seq(visitor) +231 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:249:5 + | +249 | / fn serialize_tuple_struct_elt(&mut self, value: T) -> Result<(), Self::Error> +250 | | where T: Serialize +251 | | { +252 | | self.serialize_tuple_elt(value) +253 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:273:5 + | +273 | / fn serialize_tuple_variant_elt(&mut self, value: T) -> Result<(), Self::Error> +274 | | where T: Serialize +275 | | { +276 | | self.serialize_tuple_struct_elt(value) +277 | | } + | |_____^ +warning: removed item from trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:287:5 + | +287 | / fn serialize_map_elt(&mut self, key: K, value: V) -> Result<(), Self::Error> +288 | | where K: Serialize, +289 | | V: Serialize; + | |___________________________^ +warning: removed defaulted item from trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:307:5 + | +307 | / fn serialize_struct_elt(&mut self, +308 | | key: &'static str, +309 | | value: V) -> Result<(), Self::Error> +310 | | where V: Serialize, +311 | | { +312 | | self.serialize_map_elt(key, value) +313 | | } + | |_____^ +warning: removed defaulted item from trait (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:333:5 + | +333 | / fn serialize_struct_variant_elt(&mut self, +334 | | key: &'static str, +335 | | value: V) -> Result<(), Self::Error> +336 | | where V: Serialize, +337 | | { +338 | | self.serialize_struct_elt(key, value) +339 | | } + | |_____^ + +error: breaking changes in `serialize_bool` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:386:5 + | +386 | fn serialize_bool(self, v: bool) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_i8` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:412:5 + | +412 | fn serialize_i8(self, v: i8) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_i16` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:438:5 + | +438 | fn serialize_i16(self, v: i16) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_i32` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:464:5 + | +464 | fn serialize_i32(self, v: i32) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_i64` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:486:5 + | +486 | fn serialize_i64(self, v: i64) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_u8` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:512:5 + | +512 | fn serialize_u8(self, v: u8) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_u16` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:538:5 + | +538 | fn serialize_u16(self, v: u16) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_u32` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:564:5 + | +564 | fn serialize_u32(self, v: u32) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_u64` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:586:5 + | +586 | fn serialize_u64(self, v: u64) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_f32` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:612:5 + | +612 | fn serialize_f32(self, v: f32) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_f64` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:634:5 + | +634 | fn serialize_f64(self, v: f64) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_char` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:659:5 + | +659 | fn serialize_char(self, v: char) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_str` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:681:5 + | +681 | fn serialize_str(self, v: &str) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_bytes` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:721:5 + | +721 | fn serialize_bytes(self, v: &[u8]) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_unit` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:811:5 + | +811 | fn serialize_unit(self) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_unit_struct` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:830:5 + | +830 | fn serialize_unit_struct(self, name: &'static str) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_unit_variant` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:857:5 + | +857 | / fn serialize_unit_variant( +858 | | self, +859 | | name: &'static str, +860 | | variant_index: u32, +861 | | variant: &'static str, +862 | | ) -> Result; + | |_______________________________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_newtype_struct` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:883:5 + | +883 | / fn serialize_newtype_struct( +884 | | self, +885 | | name: &'static str, +886 | | value: &T, +887 | | ) -> Result +888 | | where +889 | | T: Serialize; + | |_____________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_newtype_variant` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:916:5 + | +916 | / fn serialize_newtype_variant( +917 | | self, +918 | | name: &'static str, +919 | | variant_index: u32, +... | +923 | | where +924 | | T: Serialize; + | |_____________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_none` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:754:5 + | +754 | fn serialize_none(self) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_some` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:787:5 + | +787 | / fn serialize_some(self, value: &T) -> Result +788 | | where +789 | | T: Serialize; + | |_____________________^ + | + = warning: type error: expected &mut Self, found Self (breaking) + +error: breaking changes in `serialize_seq` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:970:5 + | +970 | fn serialize_seq(self, len: Option) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type parameter removed (breaking) + +error: breaking changes in `serialize_tuple` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1023:5 + | +1023 | fn serialize_tuple(self, len: usize) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type parameter removed (breaking) + +error: breaking changes in `serialize_tuple_struct` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1049:5 + | +1049 | / fn serialize_tuple_struct( +1050 | | self, +1051 | | name: &'static str, +1052 | | len: usize, +1053 | | ) -> Result; + | |_________________________________________________________^ + | + = warning: type parameter removed (breaking) + +error: breaking changes in `serialize_tuple_variant` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1093:5 + | +1093 | / fn serialize_tuple_variant( +1094 | | self, +1095 | | name: &'static str, +1096 | | variant_index: u32, +1097 | | variant: &'static str, +1098 | | len: usize, +1099 | | ) -> Result; + | |__________________________________________________________^ + | + = warning: type parameter removed (breaking) + +error: breaking changes in `serialize_map` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1145:5 + | +1145 | fn serialize_map(self, len: Option) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type parameter removed (breaking) + +error: breaking changes in `serialize_struct` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1175:5 + | +1175 | / fn serialize_struct( +1176 | | self, +1177 | | name: &'static str, +1178 | | len: usize, +1179 | | ) -> Result; + | |____________________________________________________^ + | + = warning: type parameter removed (breaking) + +error: breaking changes in `serialize_struct_variant` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1212:5 + | +1212 | / fn serialize_struct_variant( +1213 | | self, +1214 | | name: &'static str, +1215 | | variant_index: u32, +1216 | | variant: &'static str, +1217 | | len: usize, +1218 | | ) -> Result; + | |___________________________________________________________^ + | + = warning: type parameter removed (breaking) + +error: path changes to `SeqVisitor` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/impls.rs:157:1 + | +157 | / pub struct SeqIteratorVisitor { +158 | | iter: Iter, +159 | | len: Option, +160 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: path changes to `TupleVisitor10` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/impls.rs:557:1 + | +557 | / pub struct MapIteratorVisitor { +558 | | iter: Iter, +559 | | len: Option, +560 | | } + | |_^ + | + = warning: removed definition (breaking) + +error: breaking changes in `old::ser::impls::>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/impls.rs:654:1 + | +654 | / impl Serialize for Rc where T: Serialize, { +655 | | #[inline] +656 | | fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> +657 | | where S: Serializer, +... | +660 | | } +661 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `old::ser::impls::>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/impls.rs:663:1 + | +663 | / impl Serialize for Arc where T: Serialize, { +664 | | #[inline] +665 | | fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> +666 | | where S: Serializer, +... | +669 | | } +670 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + From ce9562b64d32383a87107f1a5addd1a4f8dac12e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 9 Aug 2017 12:07:21 +0200 Subject: [PATCH 233/553] Working around #24 for now. --- tests/examples.rs | 14 +- tests/full_cases/serde-0.7.0-1.0.0 | 11 +- tests/full_cases/serde-1.0.0-1.0.8 | 1313 ++++++++++++++++++++++++++++ 3 files changed, 1327 insertions(+), 11 deletions(-) create mode 100644 tests/full_cases/serde-1.0.0-1.0.8 diff --git a/tests/examples.rs b/tests/examples.rs index 3cc82c9d6a3d9..3a2d883c5d59d 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -97,18 +97,18 @@ macro_rules! test { } macro_rules! full_test { - ($name:ident, $old_version:expr, $new_version:expr) => { + ($name:ident, $crate_name:expr, $old_version:expr, $new_version:expr) => { #[test] fn $name() { let mut success = true; - let old_version = concat!(stringify!($name), "-", $old_version); - let new_version = concat!(stringify!($name), "-", $new_version); + let old_version = concat!($crate_name, "-", $old_version); + let new_version = concat!($crate_name, "-", $new_version); let current_dir = env::current_dir().expect("could not determine current dir"); let subst = format!("s#{}#$REPO_PATH#g", current_dir.to_str().unwrap()); let out_file = Path::new("tests/full_cases") - .join(concat!(stringify!($name), "-", $old_version, "-", $new_version)); + .join(concat!($crate_name, "-", $old_version, "-", $new_version)); if let Some(path) = env::var_os("PATH") { let mut paths = env::split_paths(&path).collect::>(); @@ -188,6 +188,6 @@ test!(traits); test!(trait_impls); test!(ty_alias); -full_test!(log, "0.3.4", "0.3.8"); -full_test!(serde, "0.7.0", "1.0.0"); -// full_test!(serde, "1.0.0", "1.0.8"); +full_test!(log, "log", "0.3.4", "0.3.8"); +// 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/tests/full_cases/serde-0.7.0-1.0.0 b/tests/full_cases/serde-0.7.0-1.0.0 index 767312db6bb75..e063dda9ab74a 100644 --- a/tests/full_cases/serde-0.7.0-1.0.0 +++ b/tests/full_cases/serde-0.7.0-1.0.0 @@ -1,6 +1,9 @@ + Blocking waiting for file lock on the registry index + Blocking waiting for file lock on the registry index Updating registry `https://github.com/rust-lang/crates.io-index` Fresh serde v1.0.0 - Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs + Finished dev [unoptimized + debuginfo] target(s) in 0.1 secs + Blocking waiting for file lock on the registry index Updating registry `https://github.com/rust-lang/crates.io-index` Fresh serde v0.7.0 Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs @@ -2914,7 +2917,7 @@ error: breaking changes in `old::de::impls:: /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:356:9 | 356 | / pub struct $visitor_name { @@ -3268,7 +3271,7 @@ warning: variant with no public fields changed to a struct variant (breaking) 123 | | } | |_^ -error: breaking changes in `U8Deserializer` +error: breaking changes in `F32Deserializer` --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:159:9 | 159 | / pub struct $name { @@ -4076,7 +4079,7 @@ error: path changes to `SeqIteratorVisitor` | = warning: removed definition (breaking) -error: path changes to `TupleVisitor10` +error: path changes to `TupleVisitor8` --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/impls.rs:377:13 | 377 | / pub struct $TupleVisitor<'a, $($T: 'a),+> { diff --git a/tests/full_cases/serde-1.0.0-1.0.8 b/tests/full_cases/serde-1.0.0-1.0.8 new file mode 100644 index 0000000000000..b1b4d775b7a02 --- /dev/null +++ b/tests/full_cases/serde-1.0.0-1.0.8 @@ -0,0 +1,1313 @@ + Updating registry `https://github.com/rust-lang/crates.io-index` + Blocking waiting for file lock on the registry index + Fresh serde v1.0.8 + Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs + Updating registry `https://github.com/rust-lang/crates.io-index` + Blocking waiting for file lock on the registry index + Fresh serde v1.0.0 + Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs +version bump: 1.0.0 -> (breaking) -> 2.0.0 +warning: path changes to `BorrowedStrDeserializer` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/value.rs:361:1 + | +361 | / pub struct BorrowedStrDeserializer<'de, E> { +362 | | value: &'de str, +363 | | marker: PhantomData, +364 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/value.rs:376:1 + | +376 | / impl<'de, E> de::Deserializer<'de> for BorrowedStrDeserializer<'de, E> +377 | | where +378 | | E: de::Error, +379 | | { +... | +407 | | } +408 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::EnumAccess<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/value.rs:585:1 + | +585 | / pub struct BorrowedBytesDeserializer<'de, E> { +586 | | value: &'de [u8], +587 | | marker: PhantomData, +588 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/value.rs:600:1 + | +600 | / impl<'de, E> de::Deserializer<'de> for BorrowedBytesDeserializer<'de, E> +601 | | where +602 | | E: de::Error, +603 | | { +... | +617 | | } +618 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for u8>::deserialize::PrimitiveVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:117:17 + | +117 | / impl<'de> Visitor<'de> for PrimitiveVisitor { +118 | | type Value = $ty; +119 | | +120 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +126 | | )* +127 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::collections::VecDeque>::deserialize::SeqVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:522:17 + | +522 | / impl<'de, T $(, $typaram)*> Visitor<'de> for SeqVisitor +523 | | where +524 | | T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*, +525 | | $($typaram: $bound1 $(+ $bound2)*,)* +... | +545 | | } +546 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::collections::HashMap>::deserialize::MapVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:815:17 + | +815 | / impl<'de, K, V $(, $typaram)*> Visitor<'de> for MapVisitor +816 | | where +817 | | K: Deserialize<'de> $(+ $kbound1 $(+ $kbound2)*)*, +818 | | V: Deserialize<'de>, +... | +839 | | } +840 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:904:1 + | +904 | / impl<'a> Visitor<'a> for PathVisitor { +905 | | type Value = &'a Path; +906 | | +907 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +925 | | } +926 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::de::impls:: for &'a std::path::Path>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:929:1 + | +929 | / impl<'de: 'a, 'a> Deserialize<'de> for &'a Path { +930 | | fn deserialize(deserializer: D) -> Result +931 | | where +932 | | D: Deserializer<'de>, +... | +935 | | } +936 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `<>::deserialize::KindVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:997:9 + | +997 | / impl<'de> Visitor<'de> for KindVisitor { +998 | | type Value = OsStringKind; +999 | | +1000 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1040 | | } +1041 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::time::Duration>::deserialize::Field as new::Deserialize<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:1254:9 + | +1254 | / impl<'de> Deserialize<'de> for Field { +1255 | | fn deserialize(deserializer: D) -> Result +1256 | | where +1257 | | D: Deserializer<'de>, +... | +1295 | | } +1296 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `< for std::time::Duration>::deserialize::Field as new::Deserialize<'de>>::deserialize::FieldVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:1261:17 + | +1261 | / impl<'de> Visitor<'de> for FieldVisitor { +1262 | | type Value = Field; +1263 | | +1264 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1291 | | } +1292 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::time::Duration>::deserialize::DurationVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:1300:9 + | +1300 | / impl<'de> Visitor<'de> for DurationVisitor { +1301 | | type Value = Duration; +1302 | | +1303 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1357 | | } +1358 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::ops::Range>::deserialize::Field as new::Deserialize<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:1393:9 + | +1393 | / impl<'de> Deserialize<'de> for Field { +1394 | | fn deserialize(deserializer: D) -> Result +1395 | | where +1396 | | D: Deserializer<'de>, +... | +1434 | | } +1435 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `< for std::ops::Range>::deserialize::Field as new::Deserialize<'de>>::deserialize::FieldVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:1400:17 + | +1400 | / impl<'de> Visitor<'de> for FieldVisitor { +1401 | | type Value = Field; +1402 | | +1403 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1430 | | } +1431 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::ops::Range>::deserialize::RangeVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:1441:9 + | +1441 | / impl<'de, Idx> Visitor<'de> for RangeVisitor +1442 | | where +1443 | | Idx: Deserialize<'de>, +1444 | | { +... | +1501 | | } +1502 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::result::Result>::deserialize::Field as new::Deserialize<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:1553:9 + | +1553 | / impl<'de> Deserialize<'de> for Field { +1554 | | #[inline] +1555 | | fn deserialize(deserializer: D) -> Result +1556 | | where +... | +1612 | | } +1613 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `< for std::result::Result>::deserialize::Field as new::Deserialize<'de>>::deserialize::FieldVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:1561:17 + | +1561 | / impl<'de> Visitor<'de> for FieldVisitor { +1562 | | type Value = Field; +1563 | | +1564 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1608 | | } +1609 | | } + | |_________________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` for std::result::Result>::deserialize::ResultVisitor as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:1617:9 + | +1617 | / impl<'de, T, E> Visitor<'de> for ResultVisitor +1618 | | where +1619 | | T: Deserialize<'de>, +1620 | | E: Deserialize<'de>, +... | +1636 | | } +1637 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:31:5 + | +31 | / impl<'de, E> Deserializer<'de> for MissingFieldDeserializer +32 | | where +33 | | E: Error, +34 | | { +... | +55 | | } +56 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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 `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:806:9 + | +806 | / pub fn new(name: &'static str) -> Self { +807 | | TaggedContentVisitor { +808 | | tag_name: name, +809 | | value: PhantomData, +810 | | } +811 | | } + | |_________^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in ` as new::de::DeserializeSeed<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:814:5 + | +814 | / impl<'de, T> DeserializeSeed<'de> for TaggedContentVisitor<'de, T> +815 | | where +816 | | T: Deserialize<'de>, +817 | | { +... | +827 | | } +828 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:19:25 + | +19 | TagContentOtherField, TagContentOtherFieldVisitor, + | ^^^^^^^^^^^^^^^^^^^^ + +warning: path changes to `TagContentOtherFieldVisitor` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:19:47 + | +19 | TagContentOtherField, TagContentOtherFieldVisitor, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: technically breaking changes in `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:937:5 + | +937 | / impl<'de> DeserializeSeed<'de> for TagContentOtherFieldVisitor { +938 | | type Value = TagContentOtherField; +939 | | +940 | | fn deserialize(self, deserializer: D) -> Result +... | +945 | | } +946 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:948:5 + | +948 | / impl<'de> Visitor<'de> for TagContentOtherFieldVisitor { +949 | | type Value = TagContentOtherField; +950 | | +951 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +966 | | } +967 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1109:9 + | +1109 | / pub fn new(content: Content<'de>) -> Self { +1110 | | ContentDeserializer { +1111 | | content: content, +1112 | | err: PhantomData, +1113 | | } +1114 | | } + | |_________^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in ` as new::de::EnumAccess<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1126:5 + | +1126 | / impl<'de, E> de::EnumAccess<'de> for EnumDeserializer<'de, E> +1127 | | where +1128 | | E: de::Error, +1129 | | { +... | +1143 | | } +1144 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::VariantAccess<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1154:5 + | +1154 | / impl<'de, E> de::VariantAccess<'de> for VariantDeserializer<'de, E> +1155 | | where +1156 | | E: de::Error, +1157 | | { +... | +1207 | | } +1208 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1230:5 + | +1230 | / impl<'de, E> de::Deserializer<'de> for SeqDeserializer<'de, E> +1231 | | where +1232 | | E: de::Error, +1233 | | { +... | +1259 | | } +1260 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::SeqAccess<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1262:5 + | +1262 | / impl<'de, E> de::SeqAccess<'de> for SeqDeserializer<'de, E> +1263 | | where +1264 | | E: de::Error, +1265 | | { +... | +1283 | | } +1284 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::MapAccess<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1308:5 + | +1308 | / impl<'de, E> de::MapAccess<'de> for MapDeserializer<'de, E> +1309 | | where +1310 | | E: de::Error, +1311 | | { +... | +1339 | | } +1340 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1342:5 + | +1342 | / impl<'de, E> de::Deserializer<'de> for MapDeserializer<'de, E> +1343 | | where +1344 | | E: de::Error, +1345 | | { +... | +1360 | | } +1361 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1503:9 + | +1503 | / pub fn new(content: &'a Content<'de>) -> Self { +1504 | | ContentRefDeserializer { +1505 | | content: content, +1506 | | err: PhantomData, +1507 | | } +1508 | | } + | |_________^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in ` as new::de::EnumAccess<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1520:5 + | +1520 | / impl<'de, 'a, E> de::EnumAccess<'de> for EnumRefDeserializer<'a, 'de, E> +1521 | | where +1522 | | E: de::Error, +1523 | | { +... | +1537 | | } +1538 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::VariantAccess<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1548:5 + | +1548 | / impl<'de, 'a, E> de::VariantAccess<'de> for VariantRefDeserializer<'a, 'de, E> +1549 | | where +1550 | | E: de::Error, +1551 | | { +... | +1601 | | } +1602 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1624:5 + | +1624 | / impl<'de, 'a, E> de::Deserializer<'de> for SeqRefDeserializer<'a, 'de, E> +1625 | | where +1626 | | E: de::Error, +1627 | | { +... | +1653 | | } +1654 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::SeqAccess<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1656:5 + | +1656 | / impl<'de, 'a, E> de::SeqAccess<'de> for SeqRefDeserializer<'a, 'de, E> +1657 | | where +1658 | | E: de::Error, +1659 | | { +... | +1677 | | } +1678 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::MapAccess<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1702:5 + | +1702 | / impl<'de, 'a, E> de::MapAccess<'de> for MapRefDeserializer<'a, 'de, E> +1703 | | where +1704 | | E: de::Error, +1705 | | { +... | +1734 | | } +1735 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1737:5 + | +1737 | / impl<'de, 'a, E> de::Deserializer<'de> for MapRefDeserializer<'a, 'de, E> +1738 | | where +1739 | | E: de::Error, +1740 | | { +... | +1755 | | } +1756 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::IntoDeserializer<'de, E>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1758:5 + | +1758 | / impl<'de, E> de::IntoDeserializer<'de, E> for ContentDeserializer<'de, E> +1759 | | where +1760 | | E: de::Error, +1761 | | { +... | +1766 | | } +1767 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::de::IntoDeserializer<'de, E>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1769:5 + | +1769 | / impl<'de, 'a, E> de::IntoDeserializer<'de, E> for ContentRefDeserializer<'a, 'de, E> +1770 | | where +1771 | | E: de::Error, +1772 | | { +... | +1777 | | } +1778 | | } + | |_____^ + | + = note: trait impl generalized or newly added (technically breaking) + +error: breaking changes in ` for i8>::deserialize::PrimitiveVisitor as old::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:117:17 + | +117 | / impl<'de> Visitor<'de> for PrimitiveVisitor { +118 | | type Value = $ty; +119 | | +120 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +126 | | )* +127 | | } + | |_________________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` for std::collections::BTreeSet>::deserialize::SeqVisitor as old::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:522:17 + | +522 | / impl<'de, T $(, $typaram)*> Visitor<'de> for SeqVisitor +523 | | where +524 | | T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*, +525 | | $($typaram: $bound1 $(+ $bound2)*,)* +... | +545 | | } +546 | | } + | |_________________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` for std::collections::HashMap>::deserialize::MapVisitor as old::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:815:17 + | +815 | / impl<'de, K, V $(, $typaram)*> Visitor<'de> for MapVisitor +816 | | where +817 | | K: Deserialize<'de> $(+ $kbound1 $(+ $kbound2)*)*, +818 | | V: Deserialize<'de>, +... | +839 | | } +840 | | } + | |_________________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `<>::deserialize::KindVisitor as old::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:959:9 + | +959 | / impl<'de> Visitor<'de> for KindVisitor { +960 | | type Value = OsStringKind; +961 | | +962 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1002 | | } +1003 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` for std::time::Duration>::deserialize::Field as old::Deserialize<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1216:9 + | +1216 | / impl<'de> Deserialize<'de> for Field { +1217 | | fn deserialize(deserializer: D) -> Result +1218 | | where +1219 | | D: Deserializer<'de>, +... | +1257 | | } +1258 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `< for std::time::Duration>::deserialize::Field as old::Deserialize<'de>>::deserialize::FieldVisitor as old::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1223:17 + | +1223 | / impl<'de> Visitor<'de> for FieldVisitor { +1224 | | type Value = Field; +1225 | | +1226 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1253 | | } +1254 | | } + | |_________________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` for std::time::Duration>::deserialize::DurationVisitor as old::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1262:9 + | +1262 | / impl<'de> Visitor<'de> for DurationVisitor { +1263 | | type Value = Duration; +1264 | | +1265 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1319 | | } +1320 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` for std::ops::Range>::deserialize::Field as old::Deserialize<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1355:9 + | +1355 | / impl<'de> Deserialize<'de> for Field { +1356 | | fn deserialize(deserializer: D) -> Result +1357 | | where +1358 | | D: Deserializer<'de>, +... | +1396 | | } +1397 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `< for std::ops::Range>::deserialize::Field as old::Deserialize<'de>>::deserialize::FieldVisitor as old::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1362:17 + | +1362 | / impl<'de> Visitor<'de> for FieldVisitor { +1363 | | type Value = Field; +1364 | | +1365 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1392 | | } +1393 | | } + | |_________________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` for std::ops::Range>::deserialize::RangeVisitor as old::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1403:9 + | +1403 | / impl<'de, Idx> Visitor<'de> for RangeVisitor +1404 | | where +1405 | | Idx: Deserialize<'de>, +1406 | | { +... | +1463 | | } +1464 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` for std::result::Result>::deserialize::Field as old::Deserialize<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1513:9 + | +1513 | / impl<'de> Deserialize<'de> for Field { +1514 | | #[inline] +1515 | | fn deserialize(deserializer: D) -> Result +1516 | | where +... | +1572 | | } +1573 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `< for std::result::Result>::deserialize::Field as old::Deserialize<'de>>::deserialize::FieldVisitor as old::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1521:17 + | +1521 | / impl<'de> Visitor<'de> for FieldVisitor { +1522 | | type Value = Field; +1523 | | +1524 | | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +... | +1568 | | } +1569 | | } + | |_________________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` for std::result::Result>::deserialize::ResultVisitor as old::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1577:9 + | +1577 | / impl<'de, T, E> Visitor<'de> for ResultVisitor +1578 | | where +1579 | | T: Deserialize<'de>, +1580 | | E: Deserialize<'de>, +... | +1596 | | } +1597 | | } + | |_________^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:30:5 + | +30 | / impl<'de, E> Deserializer<'de> for MissingFieldDeserializer +31 | | where +32 | | E: Error, +33 | | { +... | +54 | | } +55 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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 `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:254:9 + | +254 | Str(&'de str), + | ^^^^^^^^^^^^^ +warning: enum variant added (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:255:9 + | +255 | ByteBuf(Vec), + | ^^^^^^^^^^^^^^^^ + +error: breaking changes in `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:290:5 + | +290 | / impl<'de> Deserialize<'de> for Content { +291 | | fn deserialize(deserializer: D) -> Result +292 | | where +293 | | D: Deserializer<'de>, +... | +298 | | } +299 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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 `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:498:5 + | +498 | / impl<'de> DeserializeSeed<'de> for TagOrContentVisitor { +499 | | type Value = TagOrContent; +500 | | +501 | | fn deserialize(self, deserializer: D) -> Result +... | +508 | | } +509 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:798:5 + | +798 | / pub struct TaggedContentVisitor<'de, T> { +799 | | tag_name: &'static str, +800 | | value: PhantomData>, +801 | | } + | |_____^ + | + = warning: region parameter added (breaking) +warning: variant field added to variant with private fields (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:800:9 + | +800 | value: PhantomData>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: variant field removed from variant with private fields (breaking) + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:745:9 + | +745 | tag: PhantomData, + | ^^^^^^^^^^^^^^^^^^^ + +error: breaking changes in `new` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:751:9 + | +751 | / pub fn new(name: &'static str) -> Self { +752 | | TaggedContentVisitor { +753 | | tag_name: name, +754 | | tag: PhantomData, +755 | | } +756 | | } + | |_________^ + | + = warning: removed item in inherent impl (breaking) + +error: breaking changes in ` as old::de::DeserializeSeed<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:759:5 + | +759 | / impl<'de, T> DeserializeSeed<'de> for TaggedContentVisitor +760 | | where +761 | | T: Deserialize<'de>, +762 | | { +... | +772 | | } +773 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::Visitor<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:775:5 + | +775 | / impl<'de, T> Visitor<'de> for TaggedContentVisitor +776 | | where +777 | | T: Deserialize<'de>, +778 | | { +... | +817 | | } +818 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `ContentDeserializer` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:970:5 + | +970 | / pub struct ContentDeserializer<'de, E> { +971 | | content: Content<'de>, +972 | | err: PhantomData, +973 | | } + | |_____^ + | + = warning: region parameter added (breaking) + +error: breaking changes in ` as old::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:874:5 + | +874 | / impl<'de, E> Deserializer<'de> for ContentDeserializer +875 | | where +876 | | E: de::Error, +877 | | { +... | +999 | | } +1000 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `new` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1004:9 + | +1004 | / pub fn new(content: Content) -> Self { +1005 | | ContentDeserializer { +1006 | | content: content, +1007 | | err: PhantomData, +1008 | | } +1009 | | } + | |_________^ + | + = warning: removed item in inherent impl (breaking) + +error: breaking changes in ` as old::de::EnumAccess<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1021:5 + | +1021 | / impl<'de, E> de::EnumAccess<'de> for EnumDeserializer +1022 | | where +1023 | | E: de::Error, +1024 | | { +... | +1038 | | } +1039 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::VariantAccess<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1049:5 + | +1049 | / impl<'de, E> de::VariantAccess<'de> for VariantDeserializer +1050 | | where +1051 | | E: de::Error, +1052 | | { +... | +1102 | | } +1103 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1125:5 + | +1125 | / impl<'de, E> de::Deserializer<'de> for SeqDeserializer +1126 | | where +1127 | | E: de::Error, +1128 | | { +... | +1154 | | } +1155 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::SeqAccess<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1157:5 + | +1157 | / impl<'de, E> de::SeqAccess<'de> for SeqDeserializer +1158 | | where +1159 | | E: de::Error, +1160 | | { +... | +1178 | | } +1179 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::MapAccess<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1203:5 + | +1203 | / impl<'de, E> de::MapAccess<'de> for MapDeserializer +1204 | | where +1205 | | E: de::Error, +1206 | | { +... | +1234 | | } +1235 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1237:5 + | +1237 | / impl<'de, E> de::Deserializer<'de> for MapDeserializer +1238 | | where +1239 | | E: de::Error, +1240 | | { +... | +1255 | | } +1256 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `ContentRefDeserializer` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1364:5 + | +1364 | / pub struct ContentRefDeserializer<'a, 'de: 'a, E> { +1365 | | content: &'a Content<'de>, +1366 | | err: PhantomData, +1367 | | } + | |_____^ + | + = warning: region parameter added (breaking) + +error: breaking changes in ` as old::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1396:9 + | +1396 | / pub fn new(content: &'a Content) -> Self { +1397 | | ContentRefDeserializer { +1398 | | content: content, +1399 | | err: PhantomData, +1400 | | } +1401 | | } + | |_________^ + | + = warning: removed item in inherent impl (breaking) + +error: breaking changes in ` as old::de::EnumAccess<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1413:5 + | +1413 | / impl<'de, 'a, E> de::EnumAccess<'de> for EnumRefDeserializer<'a, E> +1414 | | where +1415 | | E: de::Error, +1416 | | { +... | +1430 | | } +1431 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::VariantAccess<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1441:5 + | +1441 | / impl<'de, 'a, E> de::VariantAccess<'de> for VariantRefDeserializer<'a, E> +1442 | | where +1443 | | E: de::Error, +1444 | | { +... | +1494 | | } +1495 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1517:5 + | +1517 | / impl<'de, 'a, E> de::Deserializer<'de> for SeqRefDeserializer<'a, E> +1518 | | where +1519 | | E: de::Error, +1520 | | { +... | +1546 | | } +1547 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::SeqAccess<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1549:5 + | +1549 | / impl<'de, 'a, E> de::SeqAccess<'de> for SeqRefDeserializer<'a, E> +1550 | | where +1551 | | E: de::Error, +1552 | | { +... | +1570 | | } +1571 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::MapAccess<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1595:5 + | +1595 | / impl<'de, 'a, E> de::MapAccess<'de> for MapRefDeserializer<'a, E> +1596 | | where +1597 | | E: de::Error, +1598 | | { +... | +1627 | | } +1628 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::Deserializer<'de>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1630:5 + | +1630 | / impl<'de, 'a, E> de::Deserializer<'de> for MapRefDeserializer<'a, E> +1631 | | where +1632 | | E: de::Error, +1633 | | { +... | +1648 | | } +1649 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::IntoDeserializer<'de, E>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1651:5 + | +1651 | / impl<'de, E> de::IntoDeserializer<'de, E> for ContentDeserializer +1652 | | where +1653 | | E: de::Error, +1654 | | { +... | +1659 | | } +1660 | | } + | |_____^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in ` as old::de::IntoDeserializer<'de, E>>` + --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/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) + From 3a674d69bb139333956c73d3315afbf50c06cead Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 9 Aug 2017 16:10:30 +0200 Subject: [PATCH 234/553] Added more full-crate tests. Also added the best usage of awk since sliced bread. --- .travis.yml | 5 +- tests/examples.rs | 70 --- tests/full.rs | 93 ++++ tests/full_cases/log-0.3.4-0.3.8 | 45 +- tests/full_cases/rand-0.3.10-0.3.16 | 316 ++++++++++++ tests/full_cases/serde-0.7.0-1.0.0 | 717 ++++++++++++++-------------- tests/full_cases/serde-1.0.0-1.0.8 | 206 ++++---- 7 files changed, 885 insertions(+), 567 deletions(-) create mode 100644 tests/full.rs create mode 100644 tests/full_cases/rand-0.3.10-0.3.16 diff --git a/.travis.yml b/.travis.yml index 6256af76b247a..fcc25be38b3d3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,4 +18,7 @@ addons: script: - cargo build --verbose - - cargo test --verbose + - RUST_BACKTRACE=full cargo test --verbose + - pwd + - ls + - ls target/debug diff --git a/tests/examples.rs b/tests/examples.rs index 3a2d883c5d59d..328ab8e3483de 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -96,72 +96,6 @@ macro_rules! test { } } -macro_rules! full_test { - ($name:ident, $crate_name:expr, $old_version:expr, $new_version:expr) => { - #[test] - fn $name() { - let mut success = true; - - let old_version = concat!($crate_name, "-", $old_version); - let new_version = concat!($crate_name, "-", $new_version); - - let current_dir = env::current_dir().expect("could not determine current dir"); - let subst = format!("s#{}#$REPO_PATH#g", current_dir.to_str().unwrap()); - let out_file = Path::new("tests/full_cases") - .join(concat!($crate_name, "-", $old_version, "-", $new_version)); - - if let Some(path) = env::var_os("PATH") { - let mut paths = env::split_paths(&path).collect::>(); - paths.push(current_dir.join("target/debug")); - let new_path = env::join_paths(paths).unwrap(); - env::set_var("PATH", &new_path); - } - - let stdout = File::create(&out_file).expect("could not create `stdout` file"); - let out_file = out_file.to_str().unwrap(); - - let mut sed_child = Command::new("sed") - .arg(&subst) - .stdin(Stdio::piped()) - .stdout(stdout) - .spawn() - .expect("could not run sed"); - - let (err_pipe, out_pipe) = if let Some(ref stdin) = sed_child.stdin { - let fd = stdin.as_raw_fd(); - unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } - } else { - panic!("could not pipe to sed"); - }; - - success &= Command::new("./target/debug/cargo-semver") - .args(&["semver", "-S", &old_version, "-C", &new_version]) - .env("RUST_BACKTRACE", "full") - .stdin(Stdio::null()) - .stdout(out_pipe) - .stderr(err_pipe) - .status() - .expect("could not run cargo-semver") - .success(); - - assert!(success, "cargo-semver"); - - success &= sed_child.wait().expect("could not wait for sed child").success(); - - assert!(success, "sed"); - - eprintln!("path: {}", out_file); - success &= Command::new("git") - .args(&["diff", "--quiet", out_file]) - .status() - .expect("could not run git diff") - .success(); - - assert!(success, "git"); - } - } -} - test!(addition); test!(addition_path); test!(addition_use); @@ -187,7 +121,3 @@ test!(swap); test!(traits); test!(trait_impls); test!(ty_alias); - -full_test!(log, "log", "0.3.4", "0.3.8"); -// 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/tests/full.rs b/tests/full.rs new file mode 100644 index 0000000000000..0084e1c0e6e76 --- /dev/null +++ b/tests/full.rs @@ -0,0 +1,93 @@ +use std::env; +use std::fs::File; +use std::os::unix::io::{AsRawFd, FromRawFd}; +use std::path::Path; +use std::process::{Command, Stdio}; + +macro_rules! full_test { + ($name:ident, $crate_name:expr, $old_version:expr, $new_version:expr) => { + #[test] + fn $name() { + let mut success = true; + + let old_version = concat!($crate_name, "-", $old_version); + let new_version = concat!($crate_name, "-", $new_version); + + let prog = concat!(r#" +# wait for the actual output +/^version bump/ { + doprint = 1; +} + +{ + # skip compilation info + if (!doprint) + next; + + # sanitize paths + gsub(/-->.*"#, $crate_name, r#"/, "--> "#, $crate_name, r#"", $0); + print; +} + "#, $crate_name, $crate_name); + let out_file = Path::new("tests/full_cases") + .join(concat!($crate_name, "-", $old_version, "-", $new_version)); + + if let Some(path) = env::var_os("PATH") { + let mut paths = env::split_paths(&path).collect::>(); + let current_dir = env::current_dir().expect("could not determine current dir"); + paths.push(current_dir.join("target/debug")); + let new_path = env::join_paths(paths).unwrap(); + env::set_var("PATH", &new_path); + } else { + eprintln!("no path!"); + } + + let stdout = File::create(&out_file).expect("could not create `stdout` file"); + let out_file = out_file.to_str().unwrap(); + + let mut awk_child = Command::new("awk") + .arg(&prog) + .stdin(Stdio::piped()) + .stdout(stdout) + .spawn() + .expect("could not run awk"); + + let (err_pipe, out_pipe) = if let Some(ref stdin) = awk_child.stdin { + let fd = stdin.as_raw_fd(); + unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } + } else { + panic!("could not pipe to awk"); + }; + + success &= Command::new("cargo") + .args(&["semver", "-S", &old_version, "-C", &new_version]) + .env("RUST_BACKTRACE", "full") + .stdin(Stdio::null()) + .stdout(out_pipe) + .stderr(err_pipe) + .status() + .expect("could not run cargo semver") + .success(); + + assert!(success, "cargo semver"); + + success &= awk_child.wait().expect("could not wait for awk child").success(); + + assert!(success, "awk"); + + eprintln!("path: {}", out_file); + success &= Command::new("git") + .args(&["diff", "--quiet", out_file]) + .status() + .expect("could not run git diff") + .success(); + + assert!(success, "git"); + } + } +} + +full_test!(log, "log", "0.3.4", "0.3.8"); +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/tests/full_cases/log-0.3.4-0.3.8 b/tests/full_cases/log-0.3.4-0.3.8 index f5f0905f47e4a..a1d1cfd16119f 100644 --- a/tests/full_cases/log-0.3.4-0.3.8 +++ b/tests/full_cases/log-0.3.4-0.3.8 @@ -1,13 +1,6 @@ - Updating registry `https://github.com/rust-lang/crates.io-index` - Fresh log v0.3.8 - Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs - Updating registry `https://github.com/rust-lang/crates.io-index` - Fresh libc v0.2.29 - Fresh log v0.3.4 - Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs version bump: 0.3.4 -> (technically breaking) -> 0.4.0 warning: technically breaking changes in `` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:266:27 + --> log-0.3.8/src/lib.rs:266:27 | 266 | #[derive(Copy, Eq, Debug, Hash)] | ^^^^ @@ -15,7 +8,7 @@ warning: technically breaking changes in `` = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in `` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:410:27 + --> log-0.3.8/src/lib.rs:410:27 | 410 | #[derive(Copy, Eq, Debug, Hash)] | ^^^^ @@ -23,7 +16,7 @@ warning: technically breaking changes in ` as std::fmt::Debug>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:517:10 + --> log-0.3.8/src/lib.rs:517:10 | 517 | #[derive(Debug)] | ^^^^^ @@ -31,7 +24,7 @@ warning: technically breaking changes in ` as std::fmt::Debug = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in ` as std::cmp::Eq>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:552:10 + --> log-0.3.8/src/lib.rs:552:10 | 552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] | ^^ @@ -39,7 +32,7 @@ warning: technically breaking changes in ` as std::cmp::Eq> = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in ` as std::cmp::PartialEq>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:552:14 + --> log-0.3.8/src/lib.rs:552:14 | 552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] | ^^^^^^^^^ @@ -47,7 +40,7 @@ warning: technically breaking changes in ` as std::cmp::Par = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in ` as std::cmp::Ord>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:552:25 + --> log-0.3.8/src/lib.rs:552:25 | 552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] | ^^^ @@ -55,7 +48,7 @@ warning: technically breaking changes in ` as std::cmp::Ord = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in ` as std::cmp::PartialOrd>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:552:30 + --> log-0.3.8/src/lib.rs:552:30 | 552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] | ^^^^^^^^^^ @@ -63,7 +56,7 @@ warning: technically breaking changes in ` as std::cmp::Par = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in ` as std::hash::Hash>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:552:42 + --> log-0.3.8/src/lib.rs:552:42 | 552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] | ^^^^ @@ -71,7 +64,7 @@ warning: technically breaking changes in ` as std::hash::Ha = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in ` as std::fmt::Debug>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:552:48 + --> log-0.3.8/src/lib.rs:552:48 | 552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] | ^^^^^ @@ -79,7 +72,7 @@ warning: technically breaking changes in ` as std::fmt::Deb = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in `` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:591:1 + --> log-0.3.8/src/lib.rs:591:1 | 591 | / impl Log for NopLogger { 592 | | fn enabled(&self, _: &LogMetadata) -> bool { false } @@ -91,7 +84,7 @@ warning: technically breaking changes in `` = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in `` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:604:30 + --> log-0.3.8/src/lib.rs:604:30 | 604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] | ^^ @@ -99,7 +92,7 @@ warning: technically breaking changes in `` = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in `` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:604:34 + --> log-0.3.8/src/lib.rs:604:34 | 604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] | ^^^^^^^^^ @@ -107,7 +100,7 @@ warning: technically breaking changes in `` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:604:45 + --> log-0.3.8/src/lib.rs:604:45 | 604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] | ^^^ @@ -115,7 +108,7 @@ warning: technically breaking changes in `` = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in `` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:604:50 + --> log-0.3.8/src/lib.rs:604:50 | 604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] | ^^^^^^^^^^ @@ -123,7 +116,7 @@ warning: technically breaking changes in `` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:604:62 + --> log-0.3.8/src/lib.rs:604:62 | 604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] | ^^^^ @@ -131,7 +124,7 @@ warning: technically breaking changes in `` = note: trait impl generalized or newly added (technically breaking) warning: path changes to `set_logger_raw` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:713:1 + --> log-0.3.8/src/lib.rs:713:1 | 713 | / pub unsafe fn set_logger_raw(make_logger: M) -> Result<(), SetLoggerError> 714 | | where M: FnOnce(MaxLogLevelFilter) -> *const Log { @@ -145,7 +138,7 @@ warning: path changes to `set_logger_raw` = note: added definition (technically breaking) warning: path changes to `shutdown_logger` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:736:1 + --> log-0.3.8/src/lib.rs:736:1 | 736 | / pub fn shutdown_logger() -> Result, ShutdownLoggerError> { 737 | | shutdown_logger_raw().map(|l| unsafe { mem::transmute(l) }) @@ -155,7 +148,7 @@ warning: path changes to `shutdown_logger` = note: added definition (technically breaking) warning: path changes to `shutdown_logger_raw` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:754:1 + --> 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 @@ -169,7 +162,7 @@ warning: path changes to `shutdown_logger_raw` = note: added definition (technically breaking) warning: path changes to `ShutdownLoggerError` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:797:1 + --> log-0.3.8/src/lib.rs:797:1 | 797 | pub struct ShutdownLoggerError(()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/full_cases/rand-0.3.10-0.3.16 b/tests/full_cases/rand-0.3.10-0.3.16 new file mode 100644 index 0000000000000..ef6f67abc9551 --- /dev/null +++ b/tests/full_cases/rand-0.3.10-0.3.16 @@ -0,0 +1,316 @@ +version bump: 0.3.10 -> (technically breaking) -> 0.4.0 +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/lib.rs:647:10 + | +647 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/lib.rs:667:10 + | +667 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/lib.rs:727:17 + | +727 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/lib.rs:817:10 + | +817 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/lib.rs:835:10 + | +835 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/lib.rs:840:23 + | +840 | #[derive(Copy, Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/lib.rs:903:10 + | +903 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/lib.rs:918:17 + | +918 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/distributions/mod.rs:56:10 + | +56 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/distributions/mod.rs:83:23 + | +83 | #[derive(Copy, Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/distributions/mod.rs:116:10 + | +116 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/distributions/range.rs:49:23 + | +49 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:52:23 + | +52 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:57:23 + | +57 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:78:23 + | +78 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:88:23 + | +88 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:200:23 + | +200 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:205:23 + | +205 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:258:23 + | +258 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:302:23 + | +302 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/normal.rs:36:23 + | +36 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/normal.rs:91:23 + | +91 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/normal.rs:139:23 + | +139 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/exponential.rs:37:23 + | +37 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/exponential.rs:74:23 + | +74 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/isaac.rs:264:1 + | +264 | / impl fmt::Debug for IsaacRng { +265 | | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +266 | | write!(f, "IsaacRng {{}}") +267 | | } +268 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/isaac.rs:513:1 + | +513 | / impl fmt::Debug for Isaac64Rng { +514 | | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +515 | | write!(f, "Isaac64Rng {{}}") +516 | | } +517 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/chacha.rs:29:23 + | +29 | #[derive(Copy, Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/reseeding.rs:24:10 + | +24 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/reseeding.rs:136:23 + | +136 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::rand_impls::` + --> rand_impls.rs:223:9 + | +223 | / impl Rand for [T; $n] where T: Rand { +224 | | #[inline] +225 | | fn rand(_rng: &mut R) -> [T; $n] { +226 | | [_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*] +227 | | } +228 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::rand_impls::` + --> rand_impls.rs:231:9 + | +231 | / impl Rand for [T; $n] { +232 | | fn rand(_rng: &mut R) -> [T; $n] { [] } +233 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/os.rs:50:1 + | +50 | / impl fmt::Debug for OsRng { +51 | | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +52 | | write!(f, "OsRng {{}}") +53 | | } +54 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/read.rs:33:10 + | +33 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `Rng` + --> rand-0.3.16/src/lib.rs:324:1 + | +324 | / pub trait Rng { +325 | | /// Return the next random u32. +326 | | /// +327 | | /// This rarely needs to be called directly, prefer `r.gen()` to +... | +594 | | } +595 | | } + | |_^ + | +note: added defaulted item to trait (technically breaking) + --> rand-0.3.16/src/lib.rs:560:5 + | +560 | / fn choose_mut<'a, T>(&mut self, values: &'a mut [T]) -> Option<&'a mut T> where Self: Sized { +561 | | if values.is_empty() { +562 | | None +563 | | } else { +... | +566 | | } +567 | | } + | |_____^ + diff --git a/tests/full_cases/serde-0.7.0-1.0.0 b/tests/full_cases/serde-0.7.0-1.0.0 index e063dda9ab74a..b293cf2f0caaa 100644 --- a/tests/full_cases/serde-0.7.0-1.0.0 +++ b/tests/full_cases/serde-0.7.0-1.0.0 @@ -1,15 +1,6 @@ - Blocking waiting for file lock on the registry index - Blocking waiting for file lock on the registry index - Updating registry `https://github.com/rust-lang/crates.io-index` - Fresh serde v1.0.0 - Finished dev [unoptimized + debuginfo] target(s) in 0.1 secs - Blocking waiting for file lock on the registry index - Updating registry `https://github.com/rust-lang/crates.io-index` - Fresh serde v0.7.0 - Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs version bump: 0.7.0 -> (breaking) -> 1.0.0 warning: path changes to `forward_to_deserialize_any` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/macros.rs:128:1 + --> serde-1.0.0/src/macros.rs:128:1 | 128 | / macro_rules! forward_to_deserialize_any { 129 | | (<$visitor:ident: Visitor<$lifetime:tt>> $($func:ident)*) => { @@ -23,7 +14,7 @@ warning: path changes to `forward_to_deserialize_any` = note: added definition (technically breaking) warning: path changes to `forward_to_deserialize_any_method` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/macros.rs:140:1 + --> 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),*)) => { @@ -37,7 +28,7 @@ warning: path changes to `forward_to_deserialize_any_method` = note: added definition (technically breaking) warning: path changes to `forward_to_deserialize_any_helper` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/macros.rs:157:1 + --> serde-1.0.0/src/macros.rs:157:1 | 157 | / macro_rules! forward_to_deserialize_any_helper { 158 | | (bool<$l:tt, $v:ident>) => { @@ -51,7 +42,7 @@ warning: path changes to `forward_to_deserialize_any_helper` = note: added definition (technically breaking) warning: path changes to `SerializeSeq` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1404:1 + --> serde-1.0.0/src/ser/mod.rs:1404:1 | 1404 | / pub trait SerializeSeq { 1405 | | /// Must match the `Ok` type of our `Serializer`. @@ -65,7 +56,7 @@ warning: path changes to `SerializeSeq` = note: added definition (technically breaking) warning: path changes to `SerializeTuple` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1491:1 + --> serde-1.0.0/src/ser/mod.rs:1491:1 | 1491 | / pub trait SerializeTuple { 1492 | | /// Must match the `Ok` type of our `Serializer`. @@ -79,7 +70,7 @@ warning: path changes to `SerializeTuple` = note: added definition (technically breaking) warning: path changes to `SerializeTupleStruct` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1526:1 + --> serde-1.0.0/src/ser/mod.rs:1526:1 | 1526 | / pub trait SerializeTupleStruct { 1527 | | /// Must match the `Ok` type of our `Serializer`. @@ -93,7 +84,7 @@ warning: path changes to `SerializeTupleStruct` = note: added definition (technically breaking) warning: path changes to `SerializeTupleVariant` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1574:1 + --> serde-1.0.0/src/ser/mod.rs:1574:1 | 1574 | / pub trait SerializeTupleVariant { 1575 | | /// Must match the `Ok` type of our `Serializer`. @@ -107,7 +98,7 @@ warning: path changes to `SerializeTupleVariant` = note: added definition (technically breaking) warning: path changes to `SerializeMap` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1629:1 + --> serde-1.0.0/src/ser/mod.rs:1629:1 | 1629 | / pub trait SerializeMap { 1630 | | /// Must match the `Ok` type of our `Serializer`. @@ -121,7 +112,7 @@ warning: path changes to `SerializeMap` = note: added definition (technically breaking) warning: path changes to `SerializeStruct` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1713:1 + --> serde-1.0.0/src/ser/mod.rs:1713:1 | 1713 | / pub trait SerializeStruct { 1714 | | /// Must match the `Ok` type of our `Serializer`. @@ -135,7 +126,7 @@ warning: path changes to `SerializeStruct` = note: added definition (technically breaking) warning: path changes to `SerializeStructVariant` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1758:1 + --> serde-1.0.0/src/ser/mod.rs:1758:1 | 1758 | / pub trait SerializeStructVariant { 1759 | | /// Must match the `Ok` type of our `Serializer`. @@ -149,7 +140,7 @@ warning: path changes to `SerializeStructVariant` = note: added definition (technically breaking) warning: technically breaking changes in `new::ser::impls::` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:73:1 + --> serde-1.0.0/src/ser/impls.rs:73:1 | 73 | / impl Serialize for CStr { 74 | | #[inline] @@ -163,7 +154,7 @@ warning: technically breaking changes in `new::ser::impls::` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:84:1 + --> serde-1.0.0/src/ser/impls.rs:84:1 | 84 | / impl Serialize for CString { 85 | | #[inline] @@ -177,7 +168,7 @@ warning: technically breaking changes in `new::ser::impls::` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:127:1 + --> serde-1.0.0/src/ser/impls.rs:127:1 | 127 | / impl Serialize for [T; 0] { 128 | | #[inline] @@ -191,7 +182,7 @@ warning: technically breaking changes in `new::ser::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:182:9 + --> serde-1.0.0/src/ser/impls.rs:182:9 | 182 | / impl Serialize for $ty 183 | | where @@ -205,7 +196,7 @@ warning: technically breaking changes in `new::ser::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:219:1 + --> serde-1.0.0/src/ser/impls.rs:219:1 | 219 | / impl Serialize for ops::Range 220 | | where @@ -219,7 +210,7 @@ warning: technically breaking changes in `new::ser::impls::` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:252:13 + --> serde-1.0.0/src/ser/impls.rs:252:13 | 252 | / impl<$($name),+> Serialize for ($($name,)+) 253 | | where @@ -233,7 +224,7 @@ warning: technically breaking changes in `new::ser::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:295:9 + --> serde-1.0.0/src/ser/impls.rs:295:9 | 295 | / impl Serialize for $ty 296 | | where @@ -247,7 +238,7 @@ warning: technically breaking changes in `new::ser::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:354:1 + --> serde-1.0.0/src/ser/impls.rs:354:1 | 354 | / impl Serialize for Cell 355 | | where @@ -261,7 +252,7 @@ warning: technically breaking changes in `new::ser::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:366:1 + --> serde-1.0.0/src/ser/impls.rs:366:1 | 366 | / impl Serialize for RefCell 367 | | where @@ -275,7 +266,7 @@ warning: technically breaking changes in `new::ser::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:379:1 + --> serde-1.0.0/src/ser/impls.rs:379:1 | 379 | / impl Serialize for Mutex 380 | | where @@ -289,7 +280,7 @@ warning: technically breaking changes in `new::ser::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:395:1 + --> serde-1.0.0/src/ser/impls.rs:395:1 | 395 | / impl Serialize for RwLock 396 | | where @@ -303,7 +294,7 @@ warning: technically breaking changes in `new::ser::impls::` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:433:1 + --> serde-1.0.0/src/ser/impls.rs:433:1 | 433 | / impl Serialize for Duration { 434 | | fn serialize(&self, serializer: S) -> Result @@ -317,7 +308,7 @@ warning: technically breaking changes in `new::ser::impls::` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:475:1 + --> serde-1.0.0/src/ser/impls.rs:475:1 | 475 | / impl Serialize for net::IpAddr { 476 | | fn serialize(&self, serializer: S) -> Result @@ -331,7 +322,7 @@ warning: technically breaking changes in `new::ser::impls::` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:574:1 + --> serde-1.0.0/src/ser/impls.rs:574:1 | 574 | / impl Serialize for OsStr { 575 | | #[cfg(unix)] @@ -345,7 +336,7 @@ warning: technically breaking changes in `new::ser::impls::` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:596:1 + --> serde-1.0.0/src/ser/impls.rs:596:1 | 596 | / impl Serialize for OsString { 597 | | fn serialize(&self, serializer: S) -> Result @@ -359,7 +350,7 @@ warning: technically breaking changes in `new::ser::impls:: /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impossible.rs:71:1 + --> serde-1.0.0/src/ser/impossible.rs:71:1 | 71 | / pub struct Impossible { 72 | | void: Void, @@ -369,13 +360,13 @@ warning: path changes to `Impossible` | |_^ | note: added path (technically breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:121:9 + --> serde-1.0.0/src/ser/mod.rs:121:9 | 121| pub use self::impossible::Impossible; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: path changes to `Error` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:151:9 + --> 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. @@ -387,13 +378,13 @@ error: path changes to `Error` | |_________^ | warning: removed path (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/lib.rs:27:41 + --> serde-0.7.0/src/lib.rs:27:41 | 27 | pub use de::{Deserialize, Deserializer, Error}; | ^^^^^ warning: path changes to `Unexpected` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:307:1 + --> 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. @@ -407,7 +398,7 @@ warning: path changes to `Unexpected` = note: added definition (technically breaking) warning: path changes to `Expected` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:443:1 + --> 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 @@ -419,7 +410,7 @@ warning: path changes to `Expected` = note: added definition (technically breaking) warning: path changes to `DeserializeOwned` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:529:1 + --> serde-1.0.0/src/de/mod.rs:529:1 | 529 | pub trait DeserializeOwned: for<'de> Deserialize<'de> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -427,7 +418,7 @@ warning: path changes to `DeserializeOwned` = note: added definition (technically breaking) warning: path changes to `DeserializeSeed` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:679:1 + --> serde-1.0.0/src/de/mod.rs:679:1 | 679 | / pub trait DeserializeSeed<'de>: Sized { 680 | | /// The type produced by using this seed. @@ -441,7 +432,7 @@ warning: path changes to `DeserializeSeed` = note: added definition (technically breaking) warning: path changes to `SeqAccess` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1417:1 + --> 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 @@ -455,7 +446,7 @@ warning: path changes to `SeqAccess` = note: added definition (technically breaking) warning: path changes to `MapAccess` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1484:1 + --> 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 @@ -469,7 +460,7 @@ warning: path changes to `MapAccess` = note: added definition (technically breaking) warning: path changes to `EnumAccess` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1661:1 + --> 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 @@ -483,7 +474,7 @@ warning: path changes to `EnumAccess` = note: added definition (technically breaking) warning: path changes to `VariantAccess` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1693:1 + --> 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 @@ -497,7 +488,7 @@ warning: path changes to `VariantAccess` = note: added definition (technically breaking) warning: path changes to `IntoDeserializer` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1905:1 + --> 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. @@ -511,7 +502,7 @@ warning: path changes to `IntoDeserializer` = note: added definition (technically breaking) warning: technically breaking changes in `` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:78:1 + --> serde-1.0.0/src/de/value.rs:78:1 | 78 | / impl ser::Error for Error { 79 | | fn custom(msg: T) -> Self @@ -525,7 +516,7 @@ warning: technically breaking changes in ` as std::clone::Clone>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:120:10 + --> serde-1.0.0/src/de/value.rs:120:10 | 120 | #[derive(Clone, Debug)] | ^^^^^ @@ -533,7 +524,7 @@ warning: technically breaking changes in ` a = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in ` as std::fmt::Debug>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:120:17 + --> serde-1.0.0/src/de/value.rs:120:17 | 120 | #[derive(Clone, Debug)] | ^^^^^ @@ -541,7 +532,7 @@ warning: technically breaking changes in ` a = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in ` as std::clone::Clone>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:158:18 + --> serde-1.0.0/src/de/value.rs:158:18 | 158 | #[derive(Clone, Debug)] | ^^^^^ @@ -549,7 +540,7 @@ warning: technically breaking changes in ` as = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in ` as std::fmt::Debug>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:158:25 + --> serde-1.0.0/src/de/value.rs:158:25 | 158 | #[derive(Clone, Debug)] | ^^^^^ @@ -557,7 +548,7 @@ warning: technically breaking changes in ` as = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in ` as std::clone::Clone>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:215:10 + --> serde-1.0.0/src/de/value.rs:215:10 | 215 | #[derive(Clone, Debug)] | ^^^^^ @@ -565,7 +556,7 @@ warning: technically breaking changes in ` as = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in ` as std::fmt::Debug>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:215:17 + --> serde-1.0.0/src/de/value.rs:215:17 | 215 | #[derive(Clone, Debug)] | ^^^^^ @@ -573,7 +564,7 @@ warning: technically breaking changes in ` as = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in ` as std::clone::Clone>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:287:10 + --> serde-1.0.0/src/de/value.rs:287:10 | 287 | #[derive(Clone, Debug)] | ^^^^^ @@ -581,7 +572,7 @@ warning: technically breaking changes in ` as std::fmt::Debug>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:287:17 + --> serde-1.0.0/src/de/value.rs:287:17 | 287 | #[derive(Clone, Debug)] | ^^^^^ @@ -589,7 +580,7 @@ warning: technically breaking changes in ` as std::clone::Clone>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:360:10 + --> serde-1.0.0/src/de/value.rs:360:10 | 360 | #[derive(Clone, Debug)] | ^^^^^ @@ -597,7 +588,7 @@ warning: technically breaking changes in ` = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in ` as std::fmt::Debug>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:360:17 + --> serde-1.0.0/src/de/value.rs:360:17 | 360 | #[derive(Clone, Debug)] | ^^^^^ @@ -605,7 +596,7 @@ warning: technically breaking changes in ` = note: trait impl generalized or newly added (technically breaking) warning: path changes to `CowStrDeserializer` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:437:1 + --> serde-1.0.0/src/de/value.rs:437:1 | 437 | / pub struct CowStrDeserializer<'a, E> { 438 | | value: Cow<'a, str>, @@ -616,7 +607,7 @@ warning: path changes to `CowStrDeserializer` = note: added definition (technically breaking) warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:458:1 + --> serde-1.0.0/src/de/value.rs:458:1 | 458 | / impl<'de, 'a, E> de::Deserializer<'de> for CowStrDeserializer<'a, E> 459 | | where @@ -630,7 +621,7 @@ warning: technically breaking changes in ` as std::clone::Clone>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:514:10 + --> serde-1.0.0/src/de/value.rs:514:10 | 514 | #[derive(Clone, Debug)] | ^^^^^ @@ -638,7 +629,7 @@ warning: technically breaking changes in ` = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in ` as std::fmt::Debug>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:514:17 + --> serde-1.0.0/src/de/value.rs:514:17 | 514 | #[derive(Clone, Debug)] | ^^^^^ @@ -646,7 +637,7 @@ warning: technically breaking changes in ` = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in `new` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:526:5 + --> serde-1.0.0/src/de/value.rs:526:5 | 526 | / pub fn new(iter: I) -> Self { 527 | | SeqDeserializer { @@ -660,7 +651,7 @@ warning: technically breaking changes in `new` = note: added item in inherent impl (technically breaking) warning: technically breaking changes in `end` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:542:5 + --> serde-1.0.0/src/de/value.rs:542:5 | 542 | / pub fn end(mut self) -> Result<(), E> { 543 | | let mut remaining = 0; @@ -674,7 +665,7 @@ warning: technically breaking changes in `end` = note: added item in inherent impl (technically breaking) warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:557:1 + --> serde-1.0.0/src/de/value.rs:557:1 | 557 | / impl<'de, I, T, E> de::Deserializer<'de> for SeqDeserializer 558 | | where @@ -688,7 +679,7 @@ warning: technically breaking changes in ` = note: trait impl generalized or newly added (technically breaking) warning: path changes to `SeqAccessDeserializer` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:664:1 + --> serde-1.0.0/src/de/value.rs:664:1 | 664 | / pub struct SeqAccessDeserializer { 665 | | seq: A, @@ -698,7 +689,7 @@ warning: path changes to `SeqAccessDeserializer` = note: added definition (technically breaking) warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:675:1 + --> serde-1.0.0/src/de/value.rs:675:1 | 675 | / impl<'de, A> de::Deserializer<'de> for SeqAccessDeserializer 676 | | where @@ -712,7 +703,7 @@ warning: technically breaking changes in ` /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:716:5 + --> serde-1.0.0/src/de/value.rs:716:5 | 716 | / pub fn new(iter: I) -> Self { 717 | | MapDeserializer { @@ -726,7 +717,7 @@ warning: technically breaking changes in `new` = note: added item in inherent impl (technically breaking) warning: technically breaking changes in `end` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:735:5 + --> serde-1.0.0/src/de/value.rs:735:5 | 735 | / pub fn end(mut self) -> Result<(), E> { 736 | | let mut remaining = 0; @@ -740,7 +731,7 @@ warning: technically breaking changes in `end` = note: added item in inherent impl (technically breaking) warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:766:1 + --> 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 @@ -754,7 +745,7 @@ warning: technically breaking changes in ` as std::clone::Clone>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:900:1 + --> serde-1.0.0/src/de/value.rs:900:1 | 900 | / impl<'de, I, E> Clone for MapDeserializer<'de, I, E> 901 | | where @@ -768,7 +759,7 @@ warning: technically breaking changes in ` as std::fmt::Debug>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:918:1 + --> serde-1.0.0/src/de/value.rs:918:1 | 918 | / impl<'de, I, E> Debug for MapDeserializer<'de, I, E> 919 | | where @@ -782,7 +773,7 @@ warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:940:1 + --> serde-1.0.0/src/de/value.rs:940:1 | 940 | / impl<'de, A, B, E> de::Deserializer<'de> for PairDeserializer 941 | | where @@ -796,7 +787,7 @@ warning: technically breaking changes in ` /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:1071:1 + --> serde-1.0.0/src/de/value.rs:1071:1 | 1071 | / pub struct MapAccessDeserializer { 1072 | | map: A, @@ -806,7 +797,7 @@ warning: path changes to `MapAccessDeserializer` = note: added definition (technically breaking) warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:1082:1 + --> serde-1.0.0/src/de/value.rs:1082:1 | 1082 | / impl<'de, A> de::Deserializer<'de> for MapAccessDeserializer 1083 | | where @@ -820,19 +811,19 @@ warning: technically breaking changes in ` /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/ignored_any.rs:107:1 + --> serde-1.0.0/src/de/ignored_any.rs:107:1 | 107 | pub struct IgnoredAny; | ^^^^^^^^^^^^^^^^^^^^^^ | note: added path (technically breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:132:9 + --> serde-1.0.0/src/de/mod.rs:132:9 | 132 | pub use self::ignored_any::IgnoredAny; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: technically breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/ignored_any.rs:109:1 + --> serde-1.0.0/src/de/ignored_any.rs:109:1 | 109 | / impl<'de> Visitor<'de> for IgnoredAny { 110 | | type Value = IgnoredAny; @@ -846,7 +837,7 @@ warning: technically breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/ignored_any.rs:207:1 + --> serde-1.0.0/src/de/ignored_any.rs:207:1 | 207 | / impl<'de> Deserialize<'de> for IgnoredAny { 208 | | #[inline] @@ -860,7 +851,7 @@ warning: technically breaking changes in ` for i8>::deserialize::PrimitiveVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:117:17 + --> serde-1.0.0/src/de/impls.rs:117:17 | 117 | / impl<'de> Visitor<'de> for PrimitiveVisitor { 118 | | type Value = $ty; @@ -874,7 +865,7 @@ warning: technically breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:271:1 + --> serde-1.0.0/src/de/impls.rs:271:1 | 271 | / impl<'a> Visitor<'a> for StrVisitor { 272 | | type Value = &'a str; @@ -888,7 +879,7 @@ warning: technically breaking changes in ` for &'a str>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:293:1 + --> serde-1.0.0/src/de/impls.rs:293:1 | 293 | / impl<'de: 'a, 'a> Deserialize<'de> for &'a str { 294 | | fn deserialize(deserializer: D) -> Result @@ -902,7 +893,7 @@ warning: technically breaking changes in `new::de::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:306:1 + --> serde-1.0.0/src/de/impls.rs:306:1 | 306 | / impl<'a> Visitor<'a> for BytesVisitor { 307 | | type Value = &'a [u8]; @@ -916,7 +907,7 @@ warning: technically breaking changes in ` for &'a [u8]>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:328:1 + --> serde-1.0.0/src/de/impls.rs:328:1 | 328 | / impl<'de: 'a, 'a> Deserialize<'de> for &'a [u8] { 329 | | fn deserialize(deserializer: D) -> Result @@ -930,7 +921,7 @@ warning: technically breaking changes in `new::de::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:343:1 + --> serde-1.0.0/src/de/impls.rs:343:1 | 343 | / impl<'de> Visitor<'de> for CStringVisitor { 344 | | type Value = CString; @@ -944,7 +935,7 @@ warning: technically breaking changes in ` for std::ffi::CString>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:394:1 + --> serde-1.0.0/src/de/impls.rs:394:1 | 394 | / impl<'de> Deserialize<'de> for CString { 395 | | fn deserialize(deserializer: D) -> Result @@ -958,7 +949,7 @@ warning: technically breaking changes in `new::de::impls:: as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:472:1 + --> serde-1.0.0/src/de/impls.rs:472:1 | 472 | / impl<'de, T> Visitor<'de> for PhantomDataVisitor { 473 | | type Value = PhantomData; @@ -972,7 +963,7 @@ warning: technically breaking changes in ` = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in `new::de::impls:: for std::marker::PhantomData>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:488:1 + --> serde-1.0.0/src/de/impls.rs:488:1 | 488 | / impl<'de, T> Deserialize<'de> for PhantomData { 489 | | fn deserialize(deserializer: D) -> Result, D::Error> @@ -986,7 +977,7 @@ warning: technically breaking changes in `new::de::impls:: for std::collections::HashSet>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:509:9 + --> serde-1.0.0/src/de/impls.rs:509:9 | 509 | / impl<'de, T $(, $typaram)*> Deserialize<'de> for $ty 510 | | where @@ -1000,7 +991,7 @@ warning: technically breaking changes in `new::de::impls:: for std::collections::BTreeSet>::deserialize::SeqVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:522:17 + --> serde-1.0.0/src/de/impls.rs:522:17 | 522 | / impl<'de, T $(, $typaram)*> Visitor<'de> for SeqVisitor 523 | | where @@ -1014,7 +1005,7 @@ warning: technically breaking changes in ` as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:615:1 + --> 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]; @@ -1028,7 +1019,7 @@ warning: technically breaking changes in ` = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in `new::de::impls:: for [T; 0]>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:632:1 + --> serde-1.0.0/src/de/impls.rs:632:1 | 632 | / impl<'de, T> Deserialize<'de> for [T; 0] { 633 | | fn deserialize(deserializer: D) -> Result<[T; 0], D::Error> @@ -1042,7 +1033,7 @@ warning: technically breaking changes in `new::de::impls:: as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:644:13 + --> serde-1.0.0/src/de/impls.rs:644:13 | 644 | / impl<'de, T> Visitor<'de> for ArrayVisitor<[T; $len]> 645 | | where @@ -1056,7 +1047,7 @@ warning: technically breaking changes in ` = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in ` as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:735:13 + --> 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,)+); @@ -1070,7 +1061,7 @@ warning: technically breaking changes in ` for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14)>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:759:13 + --> serde-1.0.0/src/de/impls.rs:759:13 | 759 | / impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) { 760 | | #[inline] @@ -1084,7 +1075,7 @@ warning: technically breaking changes in `new::de::impls:: for std::collections::HashMap>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:801:9 + --> serde-1.0.0/src/de/impls.rs:801:9 | 801 | / impl<'de, K, V $(, $typaram)*> Deserialize<'de> for $ty 802 | | where @@ -1098,7 +1089,7 @@ warning: technically breaking changes in `new::de::impls:: for std::collections::HashMap>::deserialize::MapVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:815:17 + --> serde-1.0.0/src/de/impls.rs:815:17 | 815 | / impl<'de, K, V $(, $typaram)*> Visitor<'de> for MapVisitor 816 | | where @@ -1112,7 +1103,7 @@ warning: technically breaking changes in ` for std::net::IpAddr>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:868:9 + --> serde-1.0.0/src/de/impls.rs:868:9 | 868 | / impl<'de> Deserialize<'de> for $ty { 869 | | fn deserialize(deserializer: D) -> Result @@ -1126,7 +1117,7 @@ warning: technically breaking changes in `new::de::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:952:1 + --> serde-1.0.0/src/de/impls.rs:952:1 | 952 | / impl<'de> Deserialize<'de> for OsStringKind { 953 | | fn deserialize(deserializer: D) -> Result @@ -1140,7 +1131,7 @@ warning: technically breaking changes in `>::deserialize::KindVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:959:9 + --> serde-1.0.0/src/de/impls.rs:959:9 | 959 | / impl<'de> Visitor<'de> for KindVisitor { 960 | | type Value = OsStringKind; @@ -1154,7 +1145,7 @@ warning: technically breaking changes in `<>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1013:1 + --> serde-1.0.0/src/de/impls.rs:1013:1 | 1013 | / impl<'de> Visitor<'de> for OsStringVisitor { 1014 | | type Value = OsString; @@ -1168,7 +1159,7 @@ warning: technically breaking changes in ` for std::ffi::OsString>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1051:1 + --> serde-1.0.0/src/de/impls.rs:1051:1 | 1051 | / impl<'de> Deserialize<'de> for OsString { 1052 | | fn deserialize(deserializer: D) -> Result @@ -1182,7 +1173,7 @@ warning: technically breaking changes in `new::de::impls:: for std::boxed::Box<[T]>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1076:1 + --> serde-1.0.0/src/de/impls.rs:1076:1 | 1076 | / impl<'de, T> Deserialize<'de> for Box<[T]> 1077 | | where @@ -1196,7 +1187,7 @@ warning: technically breaking changes in `new::de::impls:: for std::boxed::Box>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1089:1 + --> serde-1.0.0/src/de/impls.rs:1089:1 | 1089 | / impl<'de> Deserialize<'de> for Box { 1090 | | fn deserialize(deserializer: D) -> Result @@ -1210,7 +1201,7 @@ warning: technically breaking changes in `new::de::impls:: for std::cell::Cell>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1141:1 + --> serde-1.0.0/src/de/impls.rs:1141:1 | 1141 | / impl<'de, T> Deserialize<'de> for Cell 1142 | | where @@ -1224,7 +1215,7 @@ warning: technically breaking changes in `new::de::impls:: for std::cell::RefCell>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1153:1 + --> serde-1.0.0/src/de/impls.rs:1153:1 | 1153 | / impl<'de, T> Deserialize<'de> for RefCell 1154 | | where @@ -1238,7 +1229,7 @@ warning: technically breaking changes in `new::de::impls:: for std::sync::Mutex>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1166:1 + --> serde-1.0.0/src/de/impls.rs:1166:1 | 1166 | / impl<'de, T> Deserialize<'de> for Mutex 1167 | | where @@ -1252,7 +1243,7 @@ warning: technically breaking changes in `new::de::impls:: for std::sync::RwLock>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1179:1 + --> serde-1.0.0/src/de/impls.rs:1179:1 | 1179 | / impl<'de, T> Deserialize<'de> for RwLock 1180 | | where @@ -1266,7 +1257,7 @@ warning: technically breaking changes in `new::de::impls:: for std::time::Duration>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1202:1 + --> serde-1.0.0/src/de/impls.rs:1202:1 | 1202 | / impl<'de> Deserialize<'de> for Duration { 1203 | | fn deserialize(deserializer: D) -> Result @@ -1280,7 +1271,7 @@ warning: technically breaking changes in `new::de::impls:: for std::time::Duration>::deserialize::Field as new::Deserialize<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1216:9 + --> serde-1.0.0/src/de/impls.rs:1216:9 | 1216 | / impl<'de> Deserialize<'de> for Field { 1217 | | fn deserialize(deserializer: D) -> Result @@ -1294,7 +1285,7 @@ warning: technically breaking changes in ` for std::time::Duration>::deserialize::Field as new::Deserialize<'de>>::deserialize::FieldVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1223:17 + --> serde-1.0.0/src/de/impls.rs:1223:17 | 1223 | / impl<'de> Visitor<'de> for FieldVisitor { 1224 | | type Value = Field; @@ -1308,7 +1299,7 @@ warning: technically breaking changes in `< for std::time::Duration>::deserialize::DurationVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1262:9 + --> serde-1.0.0/src/de/impls.rs:1262:9 | 1262 | / impl<'de> Visitor<'de> for DurationVisitor { 1263 | | type Value = Duration; @@ -1322,7 +1313,7 @@ warning: technically breaking changes in ` for std::ops::Range>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1338:1 + --> serde-1.0.0/src/de/impls.rs:1338:1 | 1338 | / impl<'de, Idx> Deserialize<'de> for ops::Range 1339 | | where @@ -1336,7 +1327,7 @@ warning: technically breaking changes in `new::de::impls:: for std::ops::Range>::deserialize::Field as new::Deserialize<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1355:9 + --> serde-1.0.0/src/de/impls.rs:1355:9 | 1355 | / impl<'de> Deserialize<'de> for Field { 1356 | | fn deserialize(deserializer: D) -> Result @@ -1350,7 +1341,7 @@ warning: technically breaking changes in ` for std::ops::Range>::deserialize::Field as new::Deserialize<'de>>::deserialize::FieldVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1362:17 + --> serde-1.0.0/src/de/impls.rs:1362:17 | 1362 | / impl<'de> Visitor<'de> for FieldVisitor { 1363 | | type Value = Field; @@ -1364,7 +1355,7 @@ warning: technically breaking changes in `< for std::ops::Range>::deserialize::RangeVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1403:9 + --> serde-1.0.0/src/de/impls.rs:1403:9 | 1403 | / impl<'de, Idx> Visitor<'de> for RangeVisitor 1404 | | where @@ -1378,7 +1369,7 @@ warning: technically breaking changes in ` for std::result::Result>::deserialize::Field as new::Deserialize<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1513:9 + --> serde-1.0.0/src/de/impls.rs:1513:9 | 1513 | / impl<'de> Deserialize<'de> for Field { 1514 | | #[inline] @@ -1392,7 +1383,7 @@ warning: technically breaking changes in ` for std::result::Result>::deserialize::Field as new::Deserialize<'de>>::deserialize::FieldVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1521:17 + --> serde-1.0.0/src/de/impls.rs:1521:17 | 1521 | / impl<'de> Visitor<'de> for FieldVisitor { 1522 | | type Value = Field; @@ -1406,7 +1397,7 @@ warning: technically breaking changes in `< for std::result::Result>::deserialize::ResultVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1577:9 + --> serde-1.0.0/src/de/impls.rs:1577:9 | 1577 | / impl<'de, T, E> Visitor<'de> for ResultVisitor 1578 | | where @@ -1420,7 +1411,7 @@ warning: technically breaking changes in ` /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/export.rs:9:1 + --> serde-1.0.0/src/export.rs:9:1 | 9 | / pub use lib::clone::Clone; 10 | | pub use lib::convert::{From, Into}; @@ -1434,7 +1425,7 @@ warning: path changes to `export` = note: added definition (technically breaking) warning: path changes to `private` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/mod.rs:9:1 + --> serde-1.0.0/src/private/mod.rs:9:1 | 9 | / mod macros; 10 | | @@ -1445,7 +1436,7 @@ warning: path changes to `private` = note: added definition (technically breaking) warning: path changes to `__private_serialize` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/macros.rs:11:1 + --> serde-1.0.0/src/private/macros.rs:11:1 | 11 | / macro_rules! __private_serialize { 12 | | () => { @@ -1459,7 +1450,7 @@ warning: path changes to `__private_serialize` = note: added definition (technically breaking) warning: path changes to `__private_deserialize` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/macros.rs:23:1 + --> serde-1.0.0/src/private/macros.rs:23:1 | 23 | / macro_rules! __private_deserialize { 24 | | () => { @@ -1473,7 +1464,7 @@ warning: path changes to `__private_deserialize` = note: added definition (technically breaking) warning: path changes to `__serialize_unimplemented` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/macros.rs:36:1 + --> serde-1.0.0/src/private/macros.rs:36:1 | 36 | / macro_rules! __serialize_unimplemented { 37 | | ($($func:ident)*) => { @@ -1487,7 +1478,7 @@ warning: path changes to `__serialize_unimplemented` = note: added definition (technically breaking) warning: path changes to `__serialize_unimplemented_method` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/macros.rs:46:1 + --> 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) => { @@ -1501,7 +1492,7 @@ warning: path changes to `__serialize_unimplemented_method` = note: added definition (technically breaking) warning: path changes to `__serialize_unimplemented_helper` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/macros.rs:56:1 + --> serde-1.0.0/src/private/macros.rs:56:1 | 56 | / macro_rules! __serialize_unimplemented_helper { 57 | | (bool) => { @@ -1515,7 +1506,7 @@ warning: path changes to `__serialize_unimplemented_helper` = note: added definition (technically breaking) warning: technically breaking changes in ` as new::Serializer>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/ser.rs:107:1 + --> serde-1.0.0/src/private/ser.rs:107:1 | 107 | / impl Serializer for TaggedSerializer 108 | | where @@ -1529,7 +1520,7 @@ warning: technically breaking changes in `` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/ser.rs:344:1 + --> serde-1.0.0/src/private/ser.rs:344:1 | 344 | / impl ser::Error for Error { 345 | | fn custom(_: T) -> Self @@ -1543,7 +1534,7 @@ warning: technically breaking changes in `` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/ser.rs:491:5 + --> serde-1.0.0/src/private/ser.rs:491:5 | 491 | / impl Serialize for Content { 492 | | fn serialize(&self, serializer: S) -> Result @@ -1557,7 +1548,7 @@ warning: technically breaking changes in ` as new::Serializer>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/ser.rs:583:5 + --> serde-1.0.0/src/private/ser.rs:583:5 | 583 | / impl Serializer for ContentSerializer 584 | | where @@ -1571,7 +1562,7 @@ warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:30:5 + --> serde-1.0.0/src/private/de.rs:30:5 | 30 | / impl<'de, E> Deserializer<'de> for MissingFieldDeserializer 31 | | where @@ -1585,7 +1576,7 @@ warning: technically breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:68:5 + --> serde-1.0.0/src/private/de.rs:68:5 | 68 | / impl<'a> Visitor<'a> for CowStrVisitor { 69 | | type Value = Cow<'a, str>; @@ -1599,7 +1590,7 @@ warning: technically breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:137:5 + --> serde-1.0.0/src/private/de.rs:137:5 | 137 | / impl<'a> Visitor<'a> for CowBytesVisitor { 138 | | type Value = Cow<'a, [u8]>; @@ -1613,7 +1604,7 @@ warning: technically breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:290:5 + --> serde-1.0.0/src/private/de.rs:290:5 | 290 | / impl<'de> Deserialize<'de> for Content { 291 | | fn deserialize(deserializer: D) -> Result @@ -1627,7 +1618,7 @@ warning: technically breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:303:5 + --> serde-1.0.0/src/private/de.rs:303:5 | 303 | / impl<'de> Visitor<'de> for ContentVisitor { 304 | | type Value = Content; @@ -1641,7 +1632,7 @@ warning: technically breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:511:5 + --> serde-1.0.0/src/private/de.rs:511:5 | 511 | / impl<'de> Visitor<'de> for TagOrContentVisitor { 512 | | type Value = TagOrContent; @@ -1655,7 +1646,7 @@ warning: technically breaking changes in ` as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:775:5 + --> serde-1.0.0/src/private/de.rs:775:5 | 775 | / impl<'de, T> Visitor<'de> for TaggedContentVisitor 776 | | where @@ -1669,7 +1660,7 @@ warning: technically breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:845:5 + --> serde-1.0.0/src/private/de.rs:845:5 | 845 | / impl<'de> Visitor<'de> for TagOrContentFieldVisitor { 846 | | type Value = TagOrContentField; @@ -1683,7 +1674,7 @@ warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:874:5 + --> serde-1.0.0/src/private/de.rs:874:5 | 874 | / impl<'de, E> Deserializer<'de> for ContentDeserializer 875 | | where @@ -1697,7 +1688,7 @@ warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1125:5 + --> serde-1.0.0/src/private/de.rs:1125:5 | 1125 | / impl<'de, E> de::Deserializer<'de> for SeqDeserializer 1126 | | where @@ -1711,7 +1702,7 @@ warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1237:5 + --> serde-1.0.0/src/private/de.rs:1237:5 | 1237 | / impl<'de, E> de::Deserializer<'de> for MapDeserializer 1238 | | where @@ -1725,7 +1716,7 @@ warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1266:5 + --> serde-1.0.0/src/private/de.rs:1266:5 | 1266 | / impl<'de, 'a, E> Deserializer<'de> for ContentRefDeserializer<'a, E> 1267 | | where @@ -1739,7 +1730,7 @@ warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1517:5 + --> serde-1.0.0/src/private/de.rs:1517:5 | 1517 | / impl<'de, 'a, E> de::Deserializer<'de> for SeqRefDeserializer<'a, E> 1518 | | where @@ -1753,7 +1744,7 @@ warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1630:5 + --> serde-1.0.0/src/private/de.rs:1630:5 | 1630 | / impl<'de, 'a, E> de::Deserializer<'de> for MapRefDeserializer<'a, E> 1631 | | where @@ -1767,7 +1758,7 @@ warning: technically breaking changes in ` as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1691:5 + --> serde-1.0.0/src/private/de.rs:1691:5 | 1691 | / impl<'de, 'a> Visitor<'de> for InternallyTaggedUnitVisitor<'a> { 1692 | | type Value = (); @@ -1781,7 +1772,7 @@ warning: technically breaking changes in ` as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1724:5 + --> serde-1.0.0/src/private/de.rs:1724:5 | 1724 | / impl<'de, 'a> Visitor<'de> for UntaggedUnitVisitor<'a> { 1725 | | type Value = (); @@ -1795,7 +1786,7 @@ warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1788:1 + --> serde-1.0.0/src/private/de.rs:1788:1 | 1788 | / impl<'de, 'a, E> Deserializer<'de> for StrDeserializer<'a, E> 1789 | | where @@ -1809,7 +1800,7 @@ warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1827:1 + --> serde-1.0.0/src/private/de.rs:1827:1 | 1827 | / impl<'de, 'a, E> Deserializer<'de> for BytesDeserializer<'a, E> 1828 | | where @@ -1823,7 +1814,7 @@ warning: technically breaking changes in ` /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/bytes.rs:1:1 + --> serde-0.7.0/src/bytes.rs:1:1 | 1 | / //! Helper module to enable serializing bytes more efficiently 2 | | @@ -1837,7 +1828,7 @@ error: path changes to `bytes` = warning: removed definition (breaking) error: breaking changes in ` as old::Serialize>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/bytes.rs:52:1 + --> serde-0.7.0/src/bytes.rs:52:1 | 52 | / impl<'a> ser::Serialize for Bytes<'a> { 53 | | #[inline] @@ -1851,7 +1842,7 @@ error: breaking changes in ` as old::Serialize>` = warning: trait impl specialized or removed (breaking) error: breaking changes in `` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/bytes.rs:139:1 + --> serde-0.7.0/src/bytes.rs:139:1 | 139 | / impl ser::Serialize for ByteBuf { 140 | | fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> @@ -1865,7 +1856,7 @@ error: breaking changes in `` = warning: trait impl specialized or removed (breaking) error: breaking changes in `` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/bytes.rs:150:1 + --> serde-0.7.0/src/bytes.rs:150:1 | 150 | / impl de::Visitor for ByteBufVisitor { 151 | | type Value = ByteBuf; @@ -1879,7 +1870,7 @@ error: breaking changes in `` = warning: trait impl specialized or removed (breaking) error: breaking changes in `` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/bytes.rs:197:1 + --> serde-0.7.0/src/bytes.rs:197:1 | 197 | / impl de::Deserialize for ByteBuf { 198 | | #[inline] @@ -1893,7 +1884,7 @@ error: breaking changes in `` = warning: trait impl specialized or removed (breaking) error: breaking changes in `Error` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:151:9 + --> 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. @@ -1905,20 +1896,20 @@ error: breaking changes in `Error` | |_________^ | note: added defaulted item to trait (technically breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:266:13 + --> 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) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:18:5 + --> serde-0.7.0/src/de/mod.rs:18:5 | 18 | fn end_of_stream() -> Self; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: breaking changes in `custom` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:180:13 + --> serde-1.0.0/src/de/mod.rs:180:13 | 180 | / fn custom(msg: T) -> Self 181 | | where @@ -1929,7 +1920,7 @@ error: breaking changes in `custom` = note: removed bound: `std::string::String: std::convert::From` (technically breaking) error: breaking changes in `invalid_type` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:197:13 + --> 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)) @@ -1939,7 +1930,7 @@ error: breaking changes in `invalid_type` = warning: type error: incorrect number of function parameters (breaking) error: breaking changes in `invalid_value` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:214:13 + --> 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)) @@ -1949,7 +1940,7 @@ error: breaking changes in `invalid_value` = warning: type error: incorrect number of function parameters (breaking) error: breaking changes in `invalid_length` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:227:13 + --> 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)) @@ -1959,7 +1950,7 @@ error: breaking changes in `invalid_length` = warning: type error: incorrect number of function parameters (breaking) error: breaking changes in `unknown_variant` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:233:13 + --> 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() { @@ -1973,7 +1964,7 @@ error: breaking changes in `unknown_variant` = warning: type error: incorrect number of function parameters (breaking) error: breaking changes in `unknown_field` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:246:13 + --> 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() { @@ -1987,7 +1978,7 @@ error: breaking changes in `unknown_field` = warning: type error: incorrect number of function parameters (breaking) error: path changes to `Type` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:54:1 + --> serde-0.7.0/src/de/mod.rs:54:1 | 54 | / pub enum Type { 55 | | /// Represents a `bool` type. @@ -2001,7 +1992,7 @@ error: path changes to `Type` = warning: removed definition (breaking) error: breaking changes in `Deserialize` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:496:1 + --> 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. @@ -2015,7 +2006,7 @@ error: breaking changes in `Deserialize` = warning: region parameter added (breaking) error: breaking changes in `deserialize` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:503:5 + --> serde-1.0.0/src/de/mod.rs:503:5 | 503 | / fn deserialize(deserializer: D) -> Result 504 | | where @@ -2025,7 +2016,7 @@ error: breaking changes in `deserialize` = warning: type error: expected old::Deserializer::Error, found new::Deserializer::Error (breaking) error: breaking changes in `Deserializer` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:795:1 + --> 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 @@ -2038,34 +2029,34 @@ error: breaking changes in `Deserializer` | = warning: region parameter added (breaking) warning: added item to trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:809:5 + --> serde-1.0.0/src/de/mod.rs:809:5 | 809 | / fn deserialize_any(self, visitor: V) -> Result 810 | | where 811 | | V: Visitor<'de>; | |________________________^ warning: removed item from trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:180:5 + --> serde-0.7.0/src/de/mod.rs:180:5 | 180 | / fn deserialize(&mut self, visitor: V) -> Result 181 | | where V: Visitor; | |_________________________^ warning: added item to trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:913:5 + --> serde-1.0.0/src/de/mod.rs:913:5 | 913 | / fn deserialize_byte_buf(self, visitor: V) -> Result 914 | | where 915 | | V: Visitor<'de>; | |________________________^ warning: added item to trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1002:5 + --> serde-1.0.0/src/de/mod.rs:1002:5 | 1002 | / fn deserialize_identifier(self, visitor: V) -> Result 1003 | | where 1004 | | V: Visitor<'de>; | |________________________^ warning: removed defaulted item from trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:193:5 + --> serde-0.7.0/src/de/mod.rs:193:5 | 193 | / fn deserialize_usize(&mut self, visitor: V) -> Result 194 | | where V: Visitor, @@ -2074,7 +2065,7 @@ warning: removed defaulted item from trait (breaking) 197 | | } | |_____^ warning: removed defaulted item from trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:233:5 + --> serde-0.7.0/src/de/mod.rs:233:5 | 233 | / fn deserialize_isize(&mut self, visitor: V) -> Result 234 | | where V: Visitor, @@ -2083,7 +2074,7 @@ warning: removed defaulted item from trait (breaking) 237 | | } | |_____^ warning: removed defaulted item from trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:343:5 + --> serde-0.7.0/src/de/mod.rs:343:5 | 343 | / fn deserialize_fixed_size_array(&mut self, 344 | | _len: usize, @@ -2094,7 +2085,7 @@ warning: removed defaulted item from trait (breaking) 349 | | } | |_____^ warning: removed defaulted item from trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:420:5 + --> serde-0.7.0/src/de/mod.rs:420:5 | 420 | / fn deserialize_struct_field(&mut self, visitor: V) -> Result 421 | | where V: Visitor, @@ -2104,7 +2095,7 @@ warning: removed defaulted item from trait (breaking) | |_____^ error: breaking changes in `deserialize_bool` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:814:5 + --> serde-1.0.0/src/de/mod.rs:814:5 | 814 | / fn deserialize_bool(self, visitor: V) -> Result 815 | | where @@ -2114,7 +2105,7 @@ error: breaking changes in `deserialize_bool` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_u8` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:839:5 + --> serde-1.0.0/src/de/mod.rs:839:5 | 839 | / fn deserialize_u8(self, visitor: V) -> Result 840 | | where @@ -2124,7 +2115,7 @@ error: breaking changes in `deserialize_u8` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_u16` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:844:5 + --> serde-1.0.0/src/de/mod.rs:844:5 | 844 | / fn deserialize_u16(self, visitor: V) -> Result 845 | | where @@ -2134,7 +2125,7 @@ error: breaking changes in `deserialize_u16` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_u32` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:849:5 + --> serde-1.0.0/src/de/mod.rs:849:5 | 849 | / fn deserialize_u32(self, visitor: V) -> Result 850 | | where @@ -2144,7 +2135,7 @@ error: breaking changes in `deserialize_u32` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_u64` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:854:5 + --> serde-1.0.0/src/de/mod.rs:854:5 | 854 | / fn deserialize_u64(self, visitor: V) -> Result 855 | | where @@ -2154,7 +2145,7 @@ error: breaking changes in `deserialize_u64` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_i8` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:819:5 + --> serde-1.0.0/src/de/mod.rs:819:5 | 819 | / fn deserialize_i8(self, visitor: V) -> Result 820 | | where @@ -2164,7 +2155,7 @@ error: breaking changes in `deserialize_i8` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_i16` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:824:5 + --> serde-1.0.0/src/de/mod.rs:824:5 | 824 | / fn deserialize_i16(self, visitor: V) -> Result 825 | | where @@ -2174,7 +2165,7 @@ error: breaking changes in `deserialize_i16` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_i32` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:829:5 + --> serde-1.0.0/src/de/mod.rs:829:5 | 829 | / fn deserialize_i32(self, visitor: V) -> Result 830 | | where @@ -2184,7 +2175,7 @@ error: breaking changes in `deserialize_i32` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_i64` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:834:5 + --> serde-1.0.0/src/de/mod.rs:834:5 | 834 | / fn deserialize_i64(self, visitor: V) -> Result 835 | | where @@ -2194,7 +2185,7 @@ error: breaking changes in `deserialize_i64` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_f32` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:859:5 + --> serde-1.0.0/src/de/mod.rs:859:5 | 859 | / fn deserialize_f32(self, visitor: V) -> Result 860 | | where @@ -2204,7 +2195,7 @@ error: breaking changes in `deserialize_f32` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_f64` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:864:5 + --> serde-1.0.0/src/de/mod.rs:864:5 | 864 | / fn deserialize_f64(self, visitor: V) -> Result 865 | | where @@ -2214,7 +2205,7 @@ error: breaking changes in `deserialize_f64` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_char` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:869:5 + --> serde-1.0.0/src/de/mod.rs:869:5 | 869 | / fn deserialize_char(self, visitor: V) -> Result 870 | | where @@ -2224,7 +2215,7 @@ error: breaking changes in `deserialize_char` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_str` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:880:5 + --> serde-1.0.0/src/de/mod.rs:880:5 | 880 | / fn deserialize_str(self, visitor: V) -> Result 881 | | where @@ -2234,7 +2225,7 @@ error: breaking changes in `deserialize_str` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_string` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:891:5 + --> serde-1.0.0/src/de/mod.rs:891:5 | 891 | / fn deserialize_string(self, visitor: V) -> Result 892 | | where @@ -2244,7 +2235,7 @@ error: breaking changes in `deserialize_string` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_unit` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:927:5 + --> serde-1.0.0/src/de/mod.rs:927:5 | 927 | / fn deserialize_unit(self, visitor: V) -> Result 928 | | where @@ -2254,7 +2245,7 @@ error: breaking changes in `deserialize_unit` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_option` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:922:5 + --> serde-1.0.0/src/de/mod.rs:922:5 | 922 | / fn deserialize_option(self, visitor: V) -> Result 923 | | where @@ -2264,7 +2255,7 @@ error: breaking changes in `deserialize_option` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_seq` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:952:5 + --> serde-1.0.0/src/de/mod.rs:952:5 | 952 | / fn deserialize_seq(self, visitor: V) -> Result 953 | | where @@ -2274,7 +2265,7 @@ error: breaking changes in `deserialize_seq` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_bytes` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:902:5 + --> serde-1.0.0/src/de/mod.rs:902:5 | 902 | / fn deserialize_bytes(self, visitor: V) -> Result 903 | | where @@ -2284,7 +2275,7 @@ error: breaking changes in `deserialize_bytes` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_map` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:974:5 + --> serde-1.0.0/src/de/mod.rs:974:5 | 974 | / fn deserialize_map(self, visitor: V) -> Result 975 | | where @@ -2294,7 +2285,7 @@ error: breaking changes in `deserialize_map` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_unit_struct` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:933:5 + --> serde-1.0.0/src/de/mod.rs:933:5 | 933 | / fn deserialize_unit_struct( 934 | | self, @@ -2308,7 +2299,7 @@ error: breaking changes in `deserialize_unit_struct` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_newtype_struct` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:943:5 + --> serde-1.0.0/src/de/mod.rs:943:5 | 943 | / fn deserialize_newtype_struct( 944 | | self, @@ -2322,7 +2313,7 @@ error: breaking changes in `deserialize_newtype_struct` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_tuple_struct` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:964:5 + --> serde-1.0.0/src/de/mod.rs:964:5 | 964 | / fn deserialize_tuple_struct( 965 | | self, @@ -2336,7 +2327,7 @@ error: breaking changes in `deserialize_tuple_struct` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_struct` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:980:5 + --> serde-1.0.0/src/de/mod.rs:980:5 | 980 | / fn deserialize_struct( 981 | | self, @@ -2350,7 +2341,7 @@ error: breaking changes in `deserialize_struct` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_tuple` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:958:5 + --> serde-1.0.0/src/de/mod.rs:958:5 | 958 | / fn deserialize_tuple(self, len: usize, visitor: V) -> Result 959 | | where @@ -2360,7 +2351,7 @@ error: breaking changes in `deserialize_tuple` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_enum` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:991:5 + --> serde-1.0.0/src/de/mod.rs:991:5 | 991 | / fn deserialize_enum( 992 | | self, @@ -2374,7 +2365,7 @@ error: breaking changes in `deserialize_enum` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `deserialize_ignored_any` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1010:5 + --> serde-1.0.0/src/de/mod.rs:1010:5 | 1010 | / fn deserialize_ignored_any(self, visitor: V) -> Result 1011 | | where @@ -2384,7 +2375,7 @@ error: breaking changes in `deserialize_ignored_any` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `Visitor` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1048:1 + --> serde-1.0.0/src/de/mod.rs:1048:1 | 1048 | / pub trait Visitor<'de>: Sized { 1049 | | /// The value produced by this visitor. @@ -2397,12 +2388,12 @@ error: breaking changes in `Visitor` | = warning: region parameter added (breaking) warning: added item to trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1074:5 + --> 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) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1242:5 + --> serde-1.0.0/src/de/mod.rs:1242:5 | 1242 | / fn visit_borrowed_str(self, v: &'de str) -> Result 1243 | | where @@ -2412,7 +2403,7 @@ note: added defaulted item to trait (technically breaking) 1247 | | } | |_____^ note: added defaulted item to trait (technically breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1301:5 + --> serde-1.0.0/src/de/mod.rs:1301:5 | 1301 | / fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result 1302 | | where @@ -2422,7 +2413,7 @@ note: added defaulted item to trait (technically breaking) 1306 | | } | |_____^ note: added defaulted item to trait (technically breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1402:5 + --> serde-1.0.0/src/de/mod.rs:1402:5 | 1402 | / fn visit_enum(self, data: A) -> Result 1403 | | where @@ -2433,7 +2424,7 @@ note: added defaulted item to trait (technically breaking) 1408 | | } | |_____^ warning: removed defaulted item from trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:508:5 + --> serde-0.7.0/src/de/mod.rs:508:5 | 508 | / fn visit_usize(&mut self, v: usize) -> Result 509 | | where E: Error, @@ -2442,7 +2433,7 @@ warning: removed defaulted item from trait (breaking) 512 | | } | |_____^ warning: removed defaulted item from trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:473:5 + --> serde-0.7.0/src/de/mod.rs:473:5 | 473 | / fn visit_isize(&mut self, v: isize) -> Result 474 | | where E: Error, @@ -2451,7 +2442,7 @@ warning: removed defaulted item from trait (breaking) 477 | | } | |_____^ warning: removed defaulted item from trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:592:5 + --> serde-0.7.0/src/de/mod.rs:592:5 | 592 | / fn visit_unit_struct(&mut self, _name: &'static str) -> Result 593 | | where E: Error, @@ -2461,7 +2452,7 @@ warning: removed defaulted item from trait (breaking) | |_____^ error: breaking changes in `visit_bool` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1079:5 + --> serde-1.0.0/src/de/mod.rs:1079:5 | 1079 | / fn visit_bool(self, v: bool) -> Result 1080 | | where @@ -2474,7 +2465,7 @@ error: breaking changes in `visit_bool` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_i8` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1091:5 + --> serde-1.0.0/src/de/mod.rs:1091:5 | 1091 | / fn visit_i8(self, v: i8) -> Result 1092 | | where @@ -2487,7 +2478,7 @@ error: breaking changes in `visit_i8` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_i16` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1103:5 + --> serde-1.0.0/src/de/mod.rs:1103:5 | 1103 | / fn visit_i16(self, v: i16) -> Result 1104 | | where @@ -2500,7 +2491,7 @@ error: breaking changes in `visit_i16` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_i32` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1115:5 + --> serde-1.0.0/src/de/mod.rs:1115:5 | 1115 | / fn visit_i32(self, v: i32) -> Result 1116 | | where @@ -2513,7 +2504,7 @@ error: breaking changes in `visit_i32` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_i64` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1125:5 + --> serde-1.0.0/src/de/mod.rs:1125:5 | 1125 | / fn visit_i64(self, v: i64) -> Result 1126 | | where @@ -2526,7 +2517,7 @@ error: breaking changes in `visit_i64` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_u8` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1137:5 + --> serde-1.0.0/src/de/mod.rs:1137:5 | 1137 | / fn visit_u8(self, v: u8) -> Result 1138 | | where @@ -2539,7 +2530,7 @@ error: breaking changes in `visit_u8` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_u16` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1149:5 + --> serde-1.0.0/src/de/mod.rs:1149:5 | 1149 | / fn visit_u16(self, v: u16) -> Result 1150 | | where @@ -2552,7 +2543,7 @@ error: breaking changes in `visit_u16` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_u32` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1161:5 + --> serde-1.0.0/src/de/mod.rs:1161:5 | 1161 | / fn visit_u32(self, v: u32) -> Result 1162 | | where @@ -2565,7 +2556,7 @@ error: breaking changes in `visit_u32` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_u64` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1171:5 + --> serde-1.0.0/src/de/mod.rs:1171:5 | 1171 | / fn visit_u64(self, v: u64) -> Result 1172 | | where @@ -2578,7 +2569,7 @@ error: breaking changes in `visit_u64` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_f32` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1183:5 + --> serde-1.0.0/src/de/mod.rs:1183:5 | 1183 | / fn visit_f32(self, v: f32) -> Result 1184 | | where @@ -2591,7 +2582,7 @@ error: breaking changes in `visit_f32` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_f64` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1193:5 + --> serde-1.0.0/src/de/mod.rs:1193:5 | 1193 | / fn visit_f64(self, v: f64) -> Result 1194 | | where @@ -2604,7 +2595,7 @@ error: breaking changes in `visit_f64` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_char` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1207:5 + --> serde-1.0.0/src/de/mod.rs:1207:5 | 1207 | / fn visit_char(self, v: char) -> Result 1208 | | where @@ -2617,7 +2608,7 @@ error: breaking changes in `visit_char` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_str` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1225:5 + --> serde-1.0.0/src/de/mod.rs:1225:5 | 1225 | / fn visit_str(self, v: &str) -> Result 1226 | | where @@ -2630,7 +2621,7 @@ error: breaking changes in `visit_str` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_string` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1266:5 + --> serde-1.0.0/src/de/mod.rs:1266:5 | 1266 | / fn visit_string(self, v: String) -> Result 1267 | | where @@ -2643,7 +2634,7 @@ error: breaking changes in `visit_string` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_unit` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1356:5 + --> serde-1.0.0/src/de/mod.rs:1356:5 | 1356 | / fn visit_unit(self) -> Result 1357 | | where @@ -2656,7 +2647,7 @@ error: breaking changes in `visit_unit` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_none` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1335:5 + --> serde-1.0.0/src/de/mod.rs:1335:5 | 1335 | / fn visit_none(self) -> Result 1336 | | where @@ -2669,7 +2660,7 @@ error: breaking changes in `visit_none` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_some` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1345:5 + --> serde-1.0.0/src/de/mod.rs:1345:5 | 1345 | / fn visit_some(self, deserializer: D) -> Result 1346 | | where @@ -2683,7 +2674,7 @@ error: breaking changes in `visit_some` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_newtype_struct` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1369:5 + --> serde-1.0.0/src/de/mod.rs:1369:5 | 1369 | / fn visit_newtype_struct(self, deserializer: D) -> Result 1370 | | where @@ -2697,7 +2688,7 @@ error: breaking changes in `visit_newtype_struct` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_seq` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1380:5 + --> serde-1.0.0/src/de/mod.rs:1380:5 | 1380 | / fn visit_seq(self, seq: A) -> Result 1381 | | where @@ -2711,7 +2702,7 @@ error: breaking changes in `visit_seq` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_map` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1391:5 + --> serde-1.0.0/src/de/mod.rs:1391:5 | 1391 | / fn visit_map(self, map: A) -> Result 1392 | | where @@ -2725,7 +2716,7 @@ error: breaking changes in `visit_map` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_bytes` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1284:5 + --> serde-1.0.0/src/de/mod.rs:1284:5 | 1284 | / fn visit_bytes(self, v: &[u8]) -> Result 1285 | | where @@ -2739,7 +2730,7 @@ error: breaking changes in `visit_bytes` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `visit_byte_buf` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/mod.rs:1325:5 + --> serde-1.0.0/src/de/mod.rs:1325:5 | 1325 | / fn visit_byte_buf(self, v: Vec) -> Result 1326 | | where @@ -2752,7 +2743,7 @@ error: breaking changes in `visit_byte_buf` = warning: type error: expected &mut Self, found Self (breaking) error: path changes to `SeqVisitor` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:654:1 + --> 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. @@ -2766,7 +2757,7 @@ error: path changes to `SeqVisitor` = warning: removed definition (breaking) error: path changes to `MapVisitor` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:699:1 + --> 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. @@ -2780,7 +2771,7 @@ error: path changes to `MapVisitor` = warning: removed definition (breaking) error: path changes to `EnumVisitor` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:785:1 + --> serde-0.7.0/src/de/mod.rs:785:1 | 785 | / pub trait EnumVisitor { 786 | | /// The value produced by this visitor. @@ -2794,7 +2785,7 @@ error: path changes to `EnumVisitor` = warning: removed definition (breaking) error: path changes to `VariantVisitor` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/mod.rs:798:1 + --> 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. @@ -2808,7 +2799,7 @@ error: path changes to `VariantVisitor` = warning: removed definition (breaking) error: breaking changes in `impls` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:9:1 + --> serde-1.0.0/src/de/impls.rs:9:1 | 9 | / use lib::*; 10 | | @@ -2822,7 +2813,7 @@ error: breaking changes in `impls` = warning: item made private (breaking) error: breaking changes in `UnitVisitor` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:24:1 + --> serde-1.0.0/src/de/impls.rs:24:1 | 24 | struct UnitVisitor; | ^^^^^^^^^^^^^^^^^^^ @@ -2830,7 +2821,7 @@ error: breaking changes in `UnitVisitor` = warning: item made private (breaking) error: breaking changes in `BoolVisitor` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:52:1 + --> serde-1.0.0/src/de/impls.rs:52:1 | 52 | struct BoolVisitor; | ^^^^^^^^^^^^^^^^^^^ @@ -2838,7 +2829,7 @@ error: breaking changes in `BoolVisitor` = warning: item made private (breaking) error: breaking changes in ` as old::de::Visitor>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:135:1 + --> serde-0.7.0/src/de/impls.rs:135:1 | 135 | / impl Visitor for PrimitiveVisitor 136 | | where T: Deserialize + FromPrimitive + str::FromStr @@ -2852,7 +2843,7 @@ error: breaking changes in ` as old::de::Vis = warning: trait impl specialized or removed (breaking) error: breaking changes in ` as old::de::Visitor>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:281:1 + --> serde-0.7.0/src/de/impls.rs:281:1 | 281 | / impl< 282 | | T: Deserialize, @@ -2866,7 +2857,7 @@ error: breaking changes in ` as old::de::Visito = warning: trait impl specialized or removed (breaking) error: breaking changes in `old::de::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:308:1 + --> serde-0.7.0/src/de/impls.rs:308:1 | 308 | / impl Deserialize for Option where T: Deserialize { 309 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> @@ -2880,7 +2871,7 @@ error: breaking changes in `old::de::impls:: /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:468:1 + --> serde-1.0.0/src/de/impls.rs:468:1 | 468 | / struct PhantomDataVisitor { 469 | | marker: PhantomData, @@ -2890,7 +2881,7 @@ error: breaking changes in `PhantomDataVisitor` = warning: item made private (breaking) error: breaking changes in ` as old::de::Visitor>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:323:1 + --> serde-0.7.0/src/de/impls.rs:323:1 | 323 | / impl Visitor for PhantomDataVisitor where T: Deserialize { 324 | | type Value = PhantomData; @@ -2904,7 +2895,7 @@ error: breaking changes in ` as old::de::V = warning: trait impl specialized or removed (breaking) error: breaking changes in `old::de::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:334:1 + --> serde-0.7.0/src/de/impls.rs:334:1 | 334 | / impl Deserialize for PhantomData where T: Deserialize { 335 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> @@ -2918,7 +2909,7 @@ error: breaking changes in `old::de::impls:: /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:356:9 + --> serde-0.7.0/src/de/impls.rs:356:9 | 356 | / pub struct $visitor_name { 357 | | marker: PhantomData, @@ -2928,7 +2919,7 @@ error: path changes to `BTreeSetVisitor` = warning: removed definition (breaking) error: breaking changes in ` as old::de::Visitor>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:369:9 + --> serde-0.7.0/src/de/impls.rs:369:9 | 369 | / impl Visitor for $visitor_name 370 | | where T: $($constraints +)*, @@ -2942,7 +2933,7 @@ error: breaking changes in ` as old::de::Vi = warning: trait impl specialized or removed (breaking) error: breaking changes in `old::de::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:397:9 + --> serde-0.7.0/src/de/impls.rs:397:9 | 397 | / impl Deserialize for $ty 398 | | where T: $($constraints +)*, @@ -2956,7 +2947,7 @@ error: breaking changes in `old::de::impls:: as old::de::Visitor>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:488:1 + --> serde-0.7.0/src/de/impls.rs:488:1 | 488 | / impl Visitor for ArrayVisitor0 where T: Deserialize + Default { 489 | | type Value = [T; 0]; @@ -2970,7 +2961,7 @@ error: breaking changes in ` as old::de::Visito = warning: trait impl specialized or removed (breaking) error: breaking changes in `old::de::impls::` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:507:1 + --> serde-0.7.0/src/de/impls.rs:507:1 | 507 | / impl Deserialize for [T; 0] 508 | | where T: Deserialize + Default @@ -2984,7 +2975,7 @@ error: breaking changes in `old::de::impls::` = warning: trait impl specialized or removed (breaking) error: breaking changes in ` as old::de::Visitor>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:533:13 + --> serde-0.7.0/src/de/impls.rs:533:13 | 533 | / impl Visitor for $visitor where T: Deserialize { 534 | | type Value = [T; $len]; @@ -2998,7 +2989,7 @@ error: breaking changes in ` as old::de::Visit = warning: trait impl specialized or removed (breaking) error: breaking changes in `old::de::impls::` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:553:13 + --> serde-0.7.0/src/de/impls.rs:553:13 | 553 | / impl Deserialize for [T; $len] 554 | | where T: Deserialize, @@ -3011,8 +3002,8 @@ error: breaking changes in `old::de::impls::` | = warning: trait impl specialized or removed (breaking) -error: breaking changes in `TupleVisitor9` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:725:13 +error: breaking changes in `TupleVisitor1` + --> serde-1.0.0/src/de/impls.rs:725:13 | 725 | / struct $visitor<$($name,)+> { 726 | | marker: PhantomData<($($name,)+)>, @@ -3022,7 +3013,7 @@ error: breaking changes in `TupleVisitor9` = warning: item made private (breaking) error: breaking changes in `new` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:624:17 + --> serde-0.7.0/src/de/impls.rs:624:17 | 624 | / pub fn new() -> Self { 625 | | $visitor { marker: PhantomData } @@ -3032,7 +3023,7 @@ error: breaking changes in `new` = warning: removed item in inherent impl (breaking) error: breaking changes in ` as old::de::Visitor>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:630:13 + --> serde-0.7.0/src/de/impls.rs:630:13 | 630 | / impl< 631 | | $($name: Deserialize,)+ @@ -3046,7 +3037,7 @@ error: breaking changes in `` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:653:13 + --> serde-0.7.0/src/de/impls.rs:653:13 | 653 | / impl< 654 | | $($name: Deserialize),+ @@ -3059,8 +3050,8 @@ error: breaking changes in `old::de::impls:: /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:695:9 +error: path changes to `BTreeMapVisitor` + --> serde-0.7.0/src/de/impls.rs:695:9 | 695 | / pub struct $visitor_name { 696 | | marker: PhantomData<$ty>, @@ -3070,7 +3061,7 @@ error: path changes to `HashMapVisitor` = warning: removed definition (breaking) error: breaking changes in ` as old::de::Visitor>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:708:9 + --> serde-0.7.0/src/de/impls.rs:708:9 | 708 | / impl Visitor for $visitor_name 709 | | where K: $($constraints +)*, @@ -3084,7 +3075,7 @@ error: breaking changes in ` as old::de::V = warning: trait impl specialized or removed (breaking) error: breaking changes in `old::de::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:737:9 + --> serde-0.7.0/src/de/impls.rs:737:9 | 737 | / impl Deserialize for $ty 738 | | where K: $($constraints +)*, @@ -3098,7 +3089,7 @@ error: breaking changes in `old::de::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:875:1 + --> serde-0.7.0/src/de/impls.rs:875:1 | 875 | / impl Deserialize for Box { 876 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> @@ -3112,7 +3103,7 @@ error: breaking changes in `old::de::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:884:1 + --> serde-0.7.0/src/de/impls.rs:884:1 | 884 | / impl Deserialize for Arc { 885 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> @@ -3126,7 +3117,7 @@ error: breaking changes in `old::de::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:893:1 + --> serde-0.7.0/src/de/impls.rs:893:1 | 893 | / impl Deserialize for Rc { 894 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> @@ -3140,7 +3131,7 @@ error: breaking changes in `old::de::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:902:1 + --> 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] @@ -3154,7 +3145,7 @@ error: breaking changes in `old::de::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:930:1 + --> serde-0.7.0/src/de/impls.rs:930:1 | 930 | / impl Deserialize for Result where T: Deserialize, E: Deserialize { 931 | | fn deserialize(deserializer: &mut D) -> Result, D::Error> @@ -3168,7 +3159,7 @@ error: breaking changes in `old::de::impls::>::deserialize::Field as old::Deserialize>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:938:9 + --> serde-0.7.0/src/de/impls.rs:938:9 | 938 | / impl Deserialize for Field { 939 | | #[inline] @@ -3182,7 +3173,7 @@ error: breaking changes in `>::deserialize::Field as old::Deserialize>::deserialize::FieldVisitor as old::de::Visitor>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:945:17 + --> serde-0.7.0/src/de/impls.rs:945:17 | 945 | / impl ::de::Visitor for FieldVisitor { 946 | | type Value = Field; @@ -3196,7 +3187,7 @@ error: breaking changes in `< /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:1016:1 + --> serde-0.7.0/src/de/impls.rs:1016:1 | 1016 | pub struct IgnoredAny; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -3204,7 +3195,7 @@ error: path changes to `IgnoredAny` = warning: removed definition (breaking) error: breaking changes in `` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:1018:1 + --> serde-0.7.0/src/de/impls.rs:1018:1 | 1018 | / impl Deserialize for IgnoredAny { 1019 | | #[inline] @@ -3218,7 +3209,7 @@ error: breaking changes in `` = warning: trait impl specialized or removed (breaking) error: breaking changes in `<::deserialize::IgnoredAnyVisitor as old::de::Visitor>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/impls.rs:1025:9 + --> serde-0.7.0/src/de/impls.rs:1025:9 | 1025 | / impl Visitor for IgnoredAnyVisitor { 1026 | | type Value = IgnoredAny; @@ -3232,7 +3223,7 @@ error: breaking changes in `<::d = warning: trait impl specialized or removed (breaking) error: breaking changes in `Error` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:50:1 + --> serde-1.0.0/src/de/value.rs:50:1 | 50 | / pub struct Error { 51 | | err: ErrorImpl, @@ -3242,7 +3233,7 @@ error: breaking changes in `Error` = warning: item kind changed (breaking) error: path changes to `ValueDeserializer` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:93:1 + --> serde-0.7.0/src/de/value.rs:93:1 | 93 | / pub trait ValueDeserializer { 94 | | /// The actual deserializer type. @@ -3256,7 +3247,7 @@ error: path changes to `ValueDeserializer` = warning: removed definition (breaking) error: breaking changes in `UnitDeserializer` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:121:1 + --> serde-1.0.0/src/de/value.rs:121:1 | 121 | / pub struct UnitDeserializer { 122 | | marker: PhantomData, @@ -3264,7 +3255,7 @@ error: breaking changes in `UnitDeserializer` | |_^ | warning: variant with no public fields changed to a struct variant (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:121:1 + --> serde-1.0.0/src/de/value.rs:121:1 | 121 | / pub struct UnitDeserializer { 122 | | marker: PhantomData, @@ -3272,7 +3263,7 @@ warning: variant with no public fields changed to a struct variant (breaking) | |_^ error: breaking changes in `F32Deserializer` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:159:9 + --> serde-1.0.0/src/de/value.rs:159:9 | 159 | / pub struct $name { 160 | | value: $ty, @@ -3281,7 +3272,7 @@ error: breaking changes in `F32Deserializer` | |_________^ | warning: variant with no public fields changed to a struct variant (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:159:9 + --> serde-1.0.0/src/de/value.rs:159:9 | 159 | / pub struct $name { 160 | | value: $ty, @@ -3290,7 +3281,7 @@ warning: variant with no public fields changed to a struct variant (breaking) | |_________^ error: breaking changes in `StrDeserializer` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:288:1 + --> serde-1.0.0/src/de/value.rs:288:1 | 288 | / pub struct StrDeserializer<'a, E> { 289 | | value: &'a str, @@ -3299,7 +3290,7 @@ error: breaking changes in `StrDeserializer` | |_^ | warning: variant with no public fields changed to a struct variant (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:288:1 + --> serde-1.0.0/src/de/value.rs:288:1 | 288 | / pub struct StrDeserializer<'a, E> { 289 | | value: &'a str, @@ -3308,7 +3299,7 @@ warning: variant with no public fields changed to a struct variant (breaking) | |_^ error: breaking changes in `StringDeserializer` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:361:1 + --> serde-1.0.0/src/de/value.rs:361:1 | 361 | / pub struct StringDeserializer { 362 | | value: String, @@ -3317,7 +3308,7 @@ error: breaking changes in `StringDeserializer` | |_^ | warning: variant with no public fields changed to a struct variant (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:361:1 + --> serde-1.0.0/src/de/value.rs:361:1 | 361 | / pub struct StringDeserializer { 362 | | value: String, @@ -3326,7 +3317,7 @@ warning: variant with no public fields changed to a struct variant (breaking) | |_^ error: breaking changes in `SeqDeserializer` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:515:1 + --> serde-1.0.0/src/de/value.rs:515:1 | 515 | / pub struct SeqDeserializer { 516 | | iter: iter::Fuse, @@ -3336,18 +3327,18 @@ error: breaking changes in `SeqDeserializer` | |_^ | warning: variant field removed from variant with private fields (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:298:5 + --> serde-0.7.0/src/de/value.rs:298:5 | 298 | len: usize, | ^^^^^^^^^^ warning: variant field added to variant with private fields (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:517:5 + --> serde-1.0.0/src/de/value.rs:517:5 | 517 | count: usize, | ^^^^^^^^^^^^ error: breaking changes in `new` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:306:5 + --> serde-0.7.0/src/de/value.rs:306:5 | 306 | / pub fn new(iter: I, len: usize) -> Self { 307 | | SeqDeserializer { @@ -3361,7 +3352,7 @@ error: breaking changes in `new` = warning: removed item in inherent impl (breaking) error: breaking changes in ` as old::Deserializer>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:315:1 + --> serde-0.7.0/src/de/value.rs:315:1 | 315 | / impl de::Deserializer for SeqDeserializer 316 | | where I: Iterator, @@ -3375,7 +3366,7 @@ error: breaking changes in ` as old::Deser = warning: trait impl specialized or removed (breaking) error: path changes to `SeqVisitorDeserializer` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:403:1 + --> serde-0.7.0/src/de/value.rs:403:1 | 403 | / pub struct SeqVisitorDeserializer { 404 | | visitor: V_, @@ -3386,7 +3377,7 @@ error: path changes to `SeqVisitorDeserializer` = warning: removed definition (breaking) error: breaking changes in ` as old::Deserializer>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:421:1 + --> serde-0.7.0/src/de/value.rs:421:1 | 421 | / impl de::Deserializer for SeqVisitorDeserializer 422 | | where V_: de::SeqVisitor, @@ -3400,7 +3391,7 @@ error: breaking changes in ` as ol = warning: trait impl specialized or removed (breaking) error: breaking changes in `MapDeserializer` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:698:1 + --> serde-1.0.0/src/de/value.rs:698:1 | 698 | / pub struct MapDeserializer<'de, I, E> 699 | | where @@ -3415,33 +3406,33 @@ error: breaking changes in `MapDeserializer` = warning: type parameter removed (breaking) = warning: type parameter removed (breaking) warning: variant field removed from variant with private fields (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:443:5 + --> serde-0.7.0/src/de/value.rs:443:5 | 443 | len: usize, | ^^^^^^^^^^ warning: variant field removed from variant with private fields (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:444:5 + --> serde-0.7.0/src/de/value.rs:444:5 | 444 | marker: PhantomData, | ^^^^^^^^^^^^^^^^^^^^^^ warning: variant field added to variant with private fields (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:705:5 + --> serde-1.0.0/src/de/value.rs:705:5 | 705 | count: usize, | ^^^^^^^^^^^^ warning: variant field added to variant with private fields (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:707:5 + --> serde-1.0.0/src/de/value.rs:707:5 | 707 | error: PhantomData, | ^^^^^^^^^^^^^^^^^^^^^ warning: variant field added to variant with private fields (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/value.rs:706:5 + --> serde-1.0.0/src/de/value.rs:706:5 | 706 | lifetime: PhantomData<&'de ()>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: breaking changes in `new` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:454:5 + --> serde-0.7.0/src/de/value.rs:454:5 | 454 | / pub fn new(iter: I, len: usize) -> Self { 455 | | MapDeserializer { @@ -3455,7 +3446,7 @@ error: breaking changes in `new` = warning: removed item in inherent impl (breaking) error: breaking changes in ` as old::Deserializer>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:464:1 + --> serde-0.7.0/src/de/value.rs:464:1 | 464 | / impl de::Deserializer for MapDeserializer 465 | | where I: Iterator, @@ -3469,7 +3460,7 @@ error: breaking changes in ` as old: = warning: trait impl specialized or removed (breaking) error: path changes to `MapVisitorDeserializer` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:559:1 + --> serde-0.7.0/src/de/value.rs:559:1 | 559 | / pub struct MapVisitorDeserializer { 560 | | visitor: V_, @@ -3480,7 +3471,7 @@ error: path changes to `MapVisitorDeserializer` = warning: removed definition (breaking) error: breaking changes in ` as old::Deserializer>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:577:1 + --> serde-0.7.0/src/de/value.rs:577:1 | 577 | / impl de::Deserializer for MapVisitorDeserializer 578 | | where V_: de::MapVisitor, @@ -3494,7 +3485,7 @@ error: breaking changes in ` as ol = warning: trait impl specialized or removed (breaking) error: path changes to `BytesDeserializer` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:601:1 + --> serde-0.7.0/src/de/value.rs:601:1 | 601 | pub struct BytesDeserializer<'a, E> (Option<&'a [u8]>, PhantomData); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3502,7 +3493,7 @@ error: path changes to `BytesDeserializer` = warning: removed definition (breaking) error: breaking changes in ` as old::Deserializer>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:603:1 + --> 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 @@ -3516,7 +3507,7 @@ error: breaking changes in ` as old::De = warning: trait impl specialized or removed (breaking) error: path changes to `ByteBufDeserializer` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:632:1 + --> serde-0.7.0/src/de/value.rs:632:1 | 632 | pub struct ByteBufDeserializer(Option>, PhantomData); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3524,7 +3515,7 @@ error: path changes to `ByteBufDeserializer` = warning: removed definition (breaking) error: breaking changes in ` as old::Deserializer>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/de/value.rs:634:1 + --> serde-0.7.0/src/de/value.rs:634:1 | 634 | / impl de::Deserializer for ByteBufDeserializer 635 | | where E: de::Error, @@ -3538,7 +3529,7 @@ error: breaking changes in ` as old::Dese = warning: trait impl specialized or removed (breaking) error: path changes to `iter` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/iter.rs:1:1 + --> serde-0.7.0/src/iter.rs:1:1 | 1 | / //! Module that contains helper iterators. 2 | | @@ -3552,7 +3543,7 @@ error: path changes to `iter` = warning: removed definition (breaking) error: breaking changes in `Error` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:130:9 + --> 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 @@ -3564,7 +3555,7 @@ error: breaking changes in `Error` | |_________^ | warning: removed defaulted item from trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:16:5 + --> serde-0.7.0/src/ser/mod.rs:16:5 | 16 | / fn invalid_value(msg: &str) -> Self { 17 | | Error::custom(format!("invalid value: {}", msg)) @@ -3572,7 +3563,7 @@ warning: removed defaulted item from trait (breaking) | |_____^ error: breaking changes in `custom` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:165:13 + --> serde-1.0.0/src/ser/mod.rs:165:13 | 165 | / fn custom(msg: T) -> Self 166 | | where @@ -3583,7 +3574,7 @@ error: breaking changes in `custom` = note: removed bound: `std::string::String: std::convert::From` (technically breaking) error: breaking changes in `serialize` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:236:5 + --> serde-1.0.0/src/ser/mod.rs:236:5 | 236 | / fn serialize(&self, serializer: S) -> Result 237 | | where @@ -3593,7 +3584,7 @@ error: breaking changes in `serialize` = warning: type error: expected (), found associated type (breaking) error: breaking changes in `Serializer` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:310:1 + --> 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 @@ -3605,47 +3596,47 @@ error: breaking changes in `Serializer` | |_^ | warning: added item to trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:319:5 + --> serde-1.0.0/src/ser/mod.rs:319:5 | 319 | type Ok; | ^^^^^^^^ warning: added item to trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:328:5 + --> serde-1.0.0/src/ser/mod.rs:328:5 | 328 | type SerializeSeq: SerializeSeq; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: added item to trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:334:5 + --> serde-1.0.0/src/ser/mod.rs:334:5 | 334 | type SerializeTuple: SerializeTuple; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: added item to trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:340:5 + --> serde-1.0.0/src/ser/mod.rs:340:5 | 340 | type SerializeTupleStruct: SerializeTupleStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: added item to trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:346:5 + --> serde-1.0.0/src/ser/mod.rs:346:5 | 346 | type SerializeTupleVariant: SerializeTupleVariant; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: added item to trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:352:5 + --> serde-1.0.0/src/ser/mod.rs:352:5 | 352 | type SerializeMap: SerializeMap; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: added item to trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:358:5 + --> serde-1.0.0/src/ser/mod.rs:358:5 | 358 | type SerializeStruct: SerializeStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: added item to trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:364:5 + --> serde-1.0.0/src/ser/mod.rs:364:5 | 364 | type SerializeStructVariant: SerializeStructVariant; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: added defaulted item to trait (technically breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1243:5 + --> serde-1.0.0/src/ser/mod.rs:1243:5 | 1243 | / fn collect_seq(self, iter: I) -> Result 1244 | | where @@ -3656,7 +3647,7 @@ note: added defaulted item to trait (technically breaking) 1254 | | } | |_____^ note: added defaulted item to trait (technically breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1281:5 + --> serde-1.0.0/src/ser/mod.rs:1281:5 | 1281 | / fn collect_map(self, iter: I) -> Result 1282 | | where @@ -3667,7 +3658,7 @@ note: added defaulted item to trait (technically breaking) 1293 | | } | |_____^ note: added defaulted item to trait (technically breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1325:5 + --> serde-1.0.0/src/ser/mod.rs:1325:5 | 1325 | / fn collect_str(self, value: &T) -> Result 1326 | | where @@ -3678,27 +3669,27 @@ note: added defaulted item to trait (technically breaking) 1333 | | } | |_____^ warning: removed defaulted item from trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:43:5 + --> 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) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:75:5 + --> 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) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:200:5 + --> serde-0.7.0/src/ser/mod.rs:200:5 | 200 | / fn serialize_seq_elt(&mut self, value: T) -> Result<(), Self::Error> 201 | | where T: Serialize; | |___________________________^ warning: removed defaulted item from trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:217:5 + --> serde-0.7.0/src/ser/mod.rs:217:5 | 217 | / fn serialize_tuple_elt(&mut self, value: T) -> Result<(), Self::Error> 218 | | where T: Serialize @@ -3707,7 +3698,7 @@ warning: removed defaulted item from trait (breaking) 221 | | } | |_____^ warning: removed defaulted item from trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:227:5 + --> serde-0.7.0/src/ser/mod.rs:227:5 | 227 | / fn serialize_fixed_size_array(&mut self, visitor: V) -> Result<(), Self::Error> 228 | | where V: SeqVisitor, @@ -3716,7 +3707,7 @@ warning: removed defaulted item from trait (breaking) 231 | | } | |_____^ warning: removed defaulted item from trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:249:5 + --> serde-0.7.0/src/ser/mod.rs:249:5 | 249 | / fn serialize_tuple_struct_elt(&mut self, value: T) -> Result<(), Self::Error> 250 | | where T: Serialize @@ -3725,7 +3716,7 @@ warning: removed defaulted item from trait (breaking) 253 | | } | |_____^ warning: removed defaulted item from trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:273:5 + --> serde-0.7.0/src/ser/mod.rs:273:5 | 273 | / fn serialize_tuple_variant_elt(&mut self, value: T) -> Result<(), Self::Error> 274 | | where T: Serialize @@ -3734,14 +3725,14 @@ warning: removed defaulted item from trait (breaking) 277 | | } | |_____^ warning: removed item from trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:287:5 + --> serde-0.7.0/src/ser/mod.rs:287:5 | 287 | / fn serialize_map_elt(&mut self, key: K, value: V) -> Result<(), Self::Error> 288 | | where K: Serialize, 289 | | V: Serialize; | |___________________________^ warning: removed defaulted item from trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:307:5 + --> serde-0.7.0/src/ser/mod.rs:307:5 | 307 | / fn serialize_struct_elt(&mut self, 308 | | key: &'static str, @@ -3752,7 +3743,7 @@ warning: removed defaulted item from trait (breaking) 313 | | } | |_____^ warning: removed defaulted item from trait (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:333:5 + --> serde-0.7.0/src/ser/mod.rs:333:5 | 333 | / fn serialize_struct_variant_elt(&mut self, 334 | | key: &'static str, @@ -3764,7 +3755,7 @@ warning: removed defaulted item from trait (breaking) | |_____^ error: breaking changes in `serialize_bool` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:386:5 + --> serde-1.0.0/src/ser/mod.rs:386:5 | 386 | fn serialize_bool(self, v: bool) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3772,7 +3763,7 @@ error: breaking changes in `serialize_bool` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_i8` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:412:5 + --> serde-1.0.0/src/ser/mod.rs:412:5 | 412 | fn serialize_i8(self, v: i8) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3780,7 +3771,7 @@ error: breaking changes in `serialize_i8` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_i16` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:438:5 + --> serde-1.0.0/src/ser/mod.rs:438:5 | 438 | fn serialize_i16(self, v: i16) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3788,7 +3779,7 @@ error: breaking changes in `serialize_i16` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_i32` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:464:5 + --> serde-1.0.0/src/ser/mod.rs:464:5 | 464 | fn serialize_i32(self, v: i32) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3796,7 +3787,7 @@ error: breaking changes in `serialize_i32` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_i64` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:486:5 + --> serde-1.0.0/src/ser/mod.rs:486:5 | 486 | fn serialize_i64(self, v: i64) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3804,7 +3795,7 @@ error: breaking changes in `serialize_i64` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_u8` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:512:5 + --> serde-1.0.0/src/ser/mod.rs:512:5 | 512 | fn serialize_u8(self, v: u8) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3812,7 +3803,7 @@ error: breaking changes in `serialize_u8` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_u16` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:538:5 + --> serde-1.0.0/src/ser/mod.rs:538:5 | 538 | fn serialize_u16(self, v: u16) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3820,7 +3811,7 @@ error: breaking changes in `serialize_u16` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_u32` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:564:5 + --> serde-1.0.0/src/ser/mod.rs:564:5 | 564 | fn serialize_u32(self, v: u32) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3828,7 +3819,7 @@ error: breaking changes in `serialize_u32` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_u64` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:586:5 + --> serde-1.0.0/src/ser/mod.rs:586:5 | 586 | fn serialize_u64(self, v: u64) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3836,7 +3827,7 @@ error: breaking changes in `serialize_u64` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_f32` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:612:5 + --> serde-1.0.0/src/ser/mod.rs:612:5 | 612 | fn serialize_f32(self, v: f32) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3844,7 +3835,7 @@ error: breaking changes in `serialize_f32` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_f64` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:634:5 + --> serde-1.0.0/src/ser/mod.rs:634:5 | 634 | fn serialize_f64(self, v: f64) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3852,7 +3843,7 @@ error: breaking changes in `serialize_f64` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_char` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:659:5 + --> serde-1.0.0/src/ser/mod.rs:659:5 | 659 | fn serialize_char(self, v: char) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3860,7 +3851,7 @@ error: breaking changes in `serialize_char` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_str` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:681:5 + --> serde-1.0.0/src/ser/mod.rs:681:5 | 681 | fn serialize_str(self, v: &str) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3868,7 +3859,7 @@ error: breaking changes in `serialize_str` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_bytes` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:721:5 + --> serde-1.0.0/src/ser/mod.rs:721:5 | 721 | fn serialize_bytes(self, v: &[u8]) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3876,7 +3867,7 @@ error: breaking changes in `serialize_bytes` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_unit` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:811:5 + --> serde-1.0.0/src/ser/mod.rs:811:5 | 811 | fn serialize_unit(self) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3884,7 +3875,7 @@ error: breaking changes in `serialize_unit` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_unit_struct` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:830:5 + --> serde-1.0.0/src/ser/mod.rs:830:5 | 830 | fn serialize_unit_struct(self, name: &'static str) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3892,7 +3883,7 @@ error: breaking changes in `serialize_unit_struct` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_unit_variant` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:857:5 + --> serde-1.0.0/src/ser/mod.rs:857:5 | 857 | / fn serialize_unit_variant( 858 | | self, @@ -3905,7 +3896,7 @@ error: breaking changes in `serialize_unit_variant` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_newtype_struct` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:883:5 + --> serde-1.0.0/src/ser/mod.rs:883:5 | 883 | / fn serialize_newtype_struct( 884 | | self, @@ -3919,7 +3910,7 @@ error: breaking changes in `serialize_newtype_struct` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_newtype_variant` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:916:5 + --> serde-1.0.0/src/ser/mod.rs:916:5 | 916 | / fn serialize_newtype_variant( 917 | | self, @@ -3933,7 +3924,7 @@ error: breaking changes in `serialize_newtype_variant` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_none` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:754:5 + --> serde-1.0.0/src/ser/mod.rs:754:5 | 754 | fn serialize_none(self) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3941,7 +3932,7 @@ error: breaking changes in `serialize_none` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_some` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:787:5 + --> serde-1.0.0/src/ser/mod.rs:787:5 | 787 | / fn serialize_some(self, value: &T) -> Result 788 | | where @@ -3951,7 +3942,7 @@ error: breaking changes in `serialize_some` = warning: type error: expected &mut Self, found Self (breaking) error: breaking changes in `serialize_seq` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:970:5 + --> serde-1.0.0/src/ser/mod.rs:970:5 | 970 | fn serialize_seq(self, len: Option) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3959,7 +3950,7 @@ error: breaking changes in `serialize_seq` = warning: type parameter removed (breaking) error: breaking changes in `serialize_tuple` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1023:5 + --> serde-1.0.0/src/ser/mod.rs:1023:5 | 1023 | fn serialize_tuple(self, len: usize) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3967,7 +3958,7 @@ error: breaking changes in `serialize_tuple` = warning: type parameter removed (breaking) error: breaking changes in `serialize_tuple_struct` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1049:5 + --> serde-1.0.0/src/ser/mod.rs:1049:5 | 1049 | / fn serialize_tuple_struct( 1050 | | self, @@ -3979,7 +3970,7 @@ error: breaking changes in `serialize_tuple_struct` = warning: type parameter removed (breaking) error: breaking changes in `serialize_tuple_variant` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1093:5 + --> serde-1.0.0/src/ser/mod.rs:1093:5 | 1093 | / fn serialize_tuple_variant( 1094 | | self, @@ -3993,7 +3984,7 @@ error: breaking changes in `serialize_tuple_variant` = warning: type parameter removed (breaking) error: breaking changes in `serialize_map` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1145:5 + --> serde-1.0.0/src/ser/mod.rs:1145:5 | 1145 | fn serialize_map(self, len: Option) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -4001,7 +3992,7 @@ error: breaking changes in `serialize_map` = warning: type parameter removed (breaking) error: breaking changes in `serialize_struct` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1175:5 + --> serde-1.0.0/src/ser/mod.rs:1175:5 | 1175 | / fn serialize_struct( 1176 | | self, @@ -4013,7 +4004,7 @@ error: breaking changes in `serialize_struct` = warning: type parameter removed (breaking) error: breaking changes in `serialize_struct_variant` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/mod.rs:1212:5 + --> serde-1.0.0/src/ser/mod.rs:1212:5 | 1212 | / fn serialize_struct_variant( 1213 | | self, @@ -4027,7 +4018,7 @@ error: breaking changes in `serialize_struct_variant` = warning: type parameter removed (breaking) error: path changes to `SeqVisitor` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:344:1 + --> serde-0.7.0/src/ser/mod.rs:344:1 | 344 | / pub trait SeqVisitor { 345 | | /// Serializes a sequence item in the serializer. @@ -4041,7 +4032,7 @@ error: path changes to `SeqVisitor` = warning: removed definition (breaking) error: path changes to `MapVisitor` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/mod.rs:361:1 + --> serde-0.7.0/src/ser/mod.rs:361:1 | 361 | / pub trait MapVisitor { 362 | | /// Serializes a map item in the serializer. @@ -4055,7 +4046,7 @@ error: path changes to `MapVisitor` = warning: removed definition (breaking) error: breaking changes in `impls` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/ser/impls.rs:9:1 + --> serde-1.0.0/src/ser/impls.rs:9:1 | 9 | / use lib::*; 10 | | @@ -4069,7 +4060,7 @@ error: breaking changes in `impls` = warning: item made private (breaking) error: path changes to `SeqIteratorVisitor` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/impls.rs:157:1 + --> serde-0.7.0/src/ser/impls.rs:157:1 | 157 | / pub struct SeqIteratorVisitor { 158 | | iter: Iter, @@ -4080,7 +4071,7 @@ error: path changes to `SeqIteratorVisitor` = warning: removed definition (breaking) error: path changes to `TupleVisitor8` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/impls.rs:377:13 + --> serde-0.7.0/src/ser/impls.rs:377:13 | 377 | / pub struct $TupleVisitor<'a, $($T: 'a),+> { 378 | | tuple: &'a ($($T,)+), @@ -4091,7 +4082,7 @@ error: path changes to `TupleVisitor8` = warning: removed definition (breaking) error: path changes to `MapIteratorVisitor` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/impls.rs:557:1 + --> serde-0.7.0/src/ser/impls.rs:557:1 | 557 | / pub struct MapIteratorVisitor { 558 | | iter: Iter, @@ -4102,7 +4093,7 @@ error: path changes to `MapIteratorVisitor` = warning: removed definition (breaking) error: breaking changes in `old::ser::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/impls.rs:654:1 + --> serde-0.7.0/src/ser/impls.rs:654:1 | 654 | / impl Serialize for Rc where T: Serialize, { 655 | | #[inline] @@ -4116,7 +4107,7 @@ error: breaking changes in `old::ser::impls::>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.0/src/ser/impls.rs:663:1 + --> serde-0.7.0/src/ser/impls.rs:663:1 | 663 | / impl Serialize for Arc where T: Serialize, { 664 | | #[inline] diff --git a/tests/full_cases/serde-1.0.0-1.0.8 b/tests/full_cases/serde-1.0.0-1.0.8 index b1b4d775b7a02..1be5f84fcf5d6 100644 --- a/tests/full_cases/serde-1.0.0-1.0.8 +++ b/tests/full_cases/serde-1.0.0-1.0.8 @@ -1,14 +1,6 @@ - Updating registry `https://github.com/rust-lang/crates.io-index` - Blocking waiting for file lock on the registry index - Fresh serde v1.0.8 - Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs - Updating registry `https://github.com/rust-lang/crates.io-index` - Blocking waiting for file lock on the registry index - Fresh serde v1.0.0 - Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs version bump: 1.0.0 -> (breaking) -> 2.0.0 warning: path changes to `BorrowedStrDeserializer` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/value.rs:361:1 + --> serde-1.0.8/src/de/value.rs:361:1 | 361 | / pub struct BorrowedStrDeserializer<'de, E> { 362 | | value: &'de str, @@ -19,7 +11,7 @@ warning: path changes to `BorrowedStrDeserializer` = note: added definition (technically breaking) warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/value.rs:376:1 + --> serde-1.0.8/src/de/value.rs:376:1 | 376 | / impl<'de, E> de::Deserializer<'de> for BorrowedStrDeserializer<'de, E> 377 | | where @@ -33,7 +25,7 @@ warning: technically breaking changes in ` as new::de::EnumAccess<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/value.rs:410:1 + --> serde-1.0.8/src/de/value.rs:410:1 | 410 | / impl<'de, E> de::EnumAccess<'de> for BorrowedStrDeserializer<'de, E> 411 | | where @@ -47,7 +39,7 @@ warning: technically breaking changes in ` /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/value.rs:585:1 + --> serde-1.0.8/src/de/value.rs:585:1 | 585 | / pub struct BorrowedBytesDeserializer<'de, E> { 586 | | value: &'de [u8], @@ -58,7 +50,7 @@ warning: path changes to `BorrowedBytesDeserializer` = note: added definition (technically breaking) warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/value.rs:600:1 + --> serde-1.0.8/src/de/value.rs:600:1 | 600 | / impl<'de, E> de::Deserializer<'de> for BorrowedBytesDeserializer<'de, E> 601 | | where @@ -72,7 +64,7 @@ warning: technically breaking changes in ` for u8>::deserialize::PrimitiveVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:117:17 + --> serde-1.0.8/src/de/impls.rs:117:17 | 117 | / impl<'de> Visitor<'de> for PrimitiveVisitor { 118 | | type Value = $ty; @@ -86,7 +78,7 @@ warning: technically breaking changes in ` for std::collections::VecDeque>::deserialize::SeqVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:522:17 + --> serde-1.0.8/src/de/impls.rs:522:17 | 522 | / impl<'de, T $(, $typaram)*> Visitor<'de> for SeqVisitor 523 | | where @@ -100,7 +92,7 @@ warning: technically breaking changes in ` for std::collections::HashMap>::deserialize::MapVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:815:17 + --> serde-1.0.8/src/de/impls.rs:815:17 | 815 | / impl<'de, K, V $(, $typaram)*> Visitor<'de> for MapVisitor 816 | | where @@ -114,7 +106,7 @@ warning: technically breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:904:1 + --> serde-1.0.8/src/de/impls.rs:904:1 | 904 | / impl<'a> Visitor<'a> for PathVisitor { 905 | | type Value = &'a Path; @@ -128,7 +120,7 @@ warning: technically breaking changes in ` for &'a std::path::Path>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:929:1 + --> serde-1.0.8/src/de/impls.rs:929:1 | 929 | / impl<'de: 'a, 'a> Deserialize<'de> for &'a Path { 930 | | fn deserialize(deserializer: D) -> Result @@ -142,7 +134,7 @@ warning: technically breaking changes in `new::de::impls::>::deserialize::KindVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:997:9 + --> serde-1.0.8/src/de/impls.rs:997:9 | 997 | / impl<'de> Visitor<'de> for KindVisitor { 998 | | type Value = OsStringKind; @@ -156,7 +148,7 @@ warning: technically breaking changes in `< for std::time::Duration>::deserialize::Field as new::Deserialize<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:1254:9 + --> serde-1.0.8/src/de/impls.rs:1254:9 | 1254 | / impl<'de> Deserialize<'de> for Field { 1255 | | fn deserialize(deserializer: D) -> Result @@ -170,7 +162,7 @@ warning: technically breaking changes in ` for std::time::Duration>::deserialize::Field as new::Deserialize<'de>>::deserialize::FieldVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:1261:17 + --> serde-1.0.8/src/de/impls.rs:1261:17 | 1261 | / impl<'de> Visitor<'de> for FieldVisitor { 1262 | | type Value = Field; @@ -184,7 +176,7 @@ warning: technically breaking changes in `< for std::time::Duration>::deserialize::DurationVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:1300:9 + --> serde-1.0.8/src/de/impls.rs:1300:9 | 1300 | / impl<'de> Visitor<'de> for DurationVisitor { 1301 | | type Value = Duration; @@ -198,7 +190,7 @@ warning: technically breaking changes in ` for std::ops::Range>::deserialize::Field as new::Deserialize<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:1393:9 + --> serde-1.0.8/src/de/impls.rs:1393:9 | 1393 | / impl<'de> Deserialize<'de> for Field { 1394 | | fn deserialize(deserializer: D) -> Result @@ -212,7 +204,7 @@ warning: technically breaking changes in ` for std::ops::Range>::deserialize::Field as new::Deserialize<'de>>::deserialize::FieldVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:1400:17 + --> serde-1.0.8/src/de/impls.rs:1400:17 | 1400 | / impl<'de> Visitor<'de> for FieldVisitor { 1401 | | type Value = Field; @@ -226,7 +218,7 @@ warning: technically breaking changes in `< for std::ops::Range>::deserialize::RangeVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:1441:9 + --> serde-1.0.8/src/de/impls.rs:1441:9 | 1441 | / impl<'de, Idx> Visitor<'de> for RangeVisitor 1442 | | where @@ -240,7 +232,7 @@ warning: technically breaking changes in ` for std::result::Result>::deserialize::Field as new::Deserialize<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:1553:9 + --> serde-1.0.8/src/de/impls.rs:1553:9 | 1553 | / impl<'de> Deserialize<'de> for Field { 1554 | | #[inline] @@ -254,7 +246,7 @@ warning: technically breaking changes in ` for std::result::Result>::deserialize::Field as new::Deserialize<'de>>::deserialize::FieldVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:1561:17 + --> serde-1.0.8/src/de/impls.rs:1561:17 | 1561 | / impl<'de> Visitor<'de> for FieldVisitor { 1562 | | type Value = Field; @@ -268,7 +260,7 @@ warning: technically breaking changes in `< for std::result::Result>::deserialize::ResultVisitor as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/de/impls.rs:1617:9 + --> serde-1.0.8/src/de/impls.rs:1617:9 | 1617 | / impl<'de, T, E> Visitor<'de> for ResultVisitor 1618 | | where @@ -282,7 +274,7 @@ warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:31:5 + --> serde-1.0.8/src/private/de.rs:31:5 | 31 | / impl<'de, E> Deserializer<'de> for MissingFieldDeserializer 32 | | where @@ -296,7 +288,7 @@ warning: technically breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:69:5 + --> serde-1.0.8/src/private/de.rs:69:5 | 69 | / impl<'a> Visitor<'a> for CowStrVisitor { 70 | | type Value = Cow<'a, str>; @@ -310,7 +302,7 @@ warning: technically breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:138:5 + --> serde-1.0.8/src/private/de.rs:138:5 | 138 | / impl<'a> Visitor<'a> for CowBytesVisitor { 139 | | type Value = Cow<'a, [u8]>; @@ -324,7 +316,7 @@ warning: technically breaking changes in ` /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:806:9 + --> serde-1.0.8/src/private/de.rs:806:9 | 806 | / pub fn new(name: &'static str) -> Self { 807 | | TaggedContentVisitor { @@ -337,7 +329,7 @@ warning: technically breaking changes in `new` = note: added item in inherent impl (technically breaking) warning: technically breaking changes in ` as new::de::DeserializeSeed<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:814:5 + --> serde-1.0.8/src/private/de.rs:814:5 | 814 | / impl<'de, T> DeserializeSeed<'de> for TaggedContentVisitor<'de, T> 815 | | where @@ -351,7 +343,7 @@ warning: technically breaking changes in ` as new::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:830:5 + --> serde-1.0.8/src/private/de.rs:830:5 | 830 | / impl<'de, T> Visitor<'de> for TaggedContentVisitor<'de, T> 831 | | where @@ -365,7 +357,7 @@ warning: technically breaking changes in ` /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:925:5 + --> serde-1.0.8/src/private/de.rs:925:5 | 925 | / pub enum TagContentOtherField { 926 | | Tag, @@ -375,13 +367,13 @@ warning: path changes to `TagContentOtherField` | |_____^ | note: added path (technically breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:19:25 + --> serde-1.0.8/src/private/de.rs:19:25 | 19 | TagContentOtherField, TagContentOtherFieldVisitor, | ^^^^^^^^^^^^^^^^^^^^ warning: path changes to `TagContentOtherFieldVisitor` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:932:5 + --> serde-1.0.8/src/private/de.rs:932:5 | 932 | / pub struct TagContentOtherFieldVisitor { 933 | | pub tag: &'static str, @@ -390,13 +382,13 @@ warning: path changes to `TagContentOtherFieldVisitor` | |_____^ | note: added path (technically breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:19:47 + --> serde-1.0.8/src/private/de.rs:19:47 | 19 | TagContentOtherField, TagContentOtherFieldVisitor, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: technically breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:937:5 + --> serde-1.0.8/src/private/de.rs:937:5 | 937 | / impl<'de> DeserializeSeed<'de> for TagContentOtherFieldVisitor { 938 | | type Value = TagContentOtherField; @@ -410,7 +402,7 @@ warning: technically breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:948:5 + --> serde-1.0.8/src/private/de.rs:948:5 | 948 | / impl<'de> Visitor<'de> for TagContentOtherFieldVisitor { 949 | | type Value = TagContentOtherField; @@ -424,7 +416,7 @@ warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:977:5 + --> serde-1.0.8/src/private/de.rs:977:5 | 977 | / impl<'de, E> Deserializer<'de> for ContentDeserializer<'de, E> 978 | | where @@ -438,7 +430,7 @@ warning: technically breaking changes in ` /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1109:9 + --> serde-1.0.8/src/private/de.rs:1109:9 | 1109 | / pub fn new(content: Content<'de>) -> Self { 1110 | | ContentDeserializer { @@ -451,7 +443,7 @@ warning: technically breaking changes in `new` = note: added item in inherent impl (technically breaking) warning: technically breaking changes in ` as new::de::EnumAccess<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1126:5 + --> serde-1.0.8/src/private/de.rs:1126:5 | 1126 | / impl<'de, E> de::EnumAccess<'de> for EnumDeserializer<'de, E> 1127 | | where @@ -465,7 +457,7 @@ warning: technically breaking changes in ` as new::de::VariantAccess<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1154:5 + --> serde-1.0.8/src/private/de.rs:1154:5 | 1154 | / impl<'de, E> de::VariantAccess<'de> for VariantDeserializer<'de, E> 1155 | | where @@ -479,7 +471,7 @@ warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1230:5 + --> serde-1.0.8/src/private/de.rs:1230:5 | 1230 | / impl<'de, E> de::Deserializer<'de> for SeqDeserializer<'de, E> 1231 | | where @@ -493,7 +485,7 @@ warning: technically breaking changes in ` as new::de::SeqAccess<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1262:5 + --> serde-1.0.8/src/private/de.rs:1262:5 | 1262 | / impl<'de, E> de::SeqAccess<'de> for SeqDeserializer<'de, E> 1263 | | where @@ -507,7 +499,7 @@ warning: technically breaking changes in ` as new::de::MapAccess<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1308:5 + --> serde-1.0.8/src/private/de.rs:1308:5 | 1308 | / impl<'de, E> de::MapAccess<'de> for MapDeserializer<'de, E> 1309 | | where @@ -521,7 +513,7 @@ warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1342:5 + --> serde-1.0.8/src/private/de.rs:1342:5 | 1342 | / impl<'de, E> de::Deserializer<'de> for MapDeserializer<'de, E> 1343 | | where @@ -535,7 +527,7 @@ warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1371:5 + --> serde-1.0.8/src/private/de.rs:1371:5 | 1371 | / impl<'de, 'a, E> Deserializer<'de> for ContentRefDeserializer<'a, 'de, E> 1372 | | where @@ -549,7 +541,7 @@ warning: technically breaking changes in ` /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1503:9 + --> serde-1.0.8/src/private/de.rs:1503:9 | 1503 | / pub fn new(content: &'a Content<'de>) -> Self { 1504 | | ContentRefDeserializer { @@ -562,7 +554,7 @@ warning: technically breaking changes in `new` = note: added item in inherent impl (technically breaking) warning: technically breaking changes in ` as new::de::EnumAccess<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1520:5 + --> 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 @@ -576,7 +568,7 @@ warning: technically breaking changes in ` as new::de::VariantAccess<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1548:5 + --> 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 @@ -590,7 +582,7 @@ warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1624:5 + --> 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 @@ -604,7 +596,7 @@ warning: technically breaking changes in ` as new::de::SeqAccess<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1656:5 + --> 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 @@ -618,7 +610,7 @@ warning: technically breaking changes in ` as new::de::MapAccess<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1702:5 + --> 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 @@ -632,7 +624,7 @@ warning: technically breaking changes in ` as new::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1737:5 + --> 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 @@ -646,7 +638,7 @@ warning: technically breaking changes in ` as new::de::IntoDeserializer<'de, E>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1758:5 + --> serde-1.0.8/src/private/de.rs:1758:5 | 1758 | / impl<'de, E> de::IntoDeserializer<'de, E> for ContentDeserializer<'de, E> 1759 | | where @@ -660,7 +652,7 @@ warning: technically breaking changes in ` as new::de::IntoDeserializer<'de, E>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1769:5 + --> 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 @@ -674,7 +666,7 @@ warning: technically breaking changes in ` for i8>::deserialize::PrimitiveVisitor as old::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:117:17 + --> serde-1.0.0/src/de/impls.rs:117:17 | 117 | / impl<'de> Visitor<'de> for PrimitiveVisitor { 118 | | type Value = $ty; @@ -688,7 +680,7 @@ error: breaking changes in ` for i8> = warning: trait impl specialized or removed (breaking) error: breaking changes in ` for std::collections::BTreeSet>::deserialize::SeqVisitor as old::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:522:17 + --> serde-1.0.0/src/de/impls.rs:522:17 | 522 | / impl<'de, T $(, $typaram)*> Visitor<'de> for SeqVisitor 523 | | where @@ -702,7 +694,7 @@ error: breaking changes in ` for std = warning: trait impl specialized or removed (breaking) error: breaking changes in ` for std::collections::HashMap>::deserialize::MapVisitor as old::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:815:17 + --> serde-1.0.0/src/de/impls.rs:815:17 | 815 | / impl<'de, K, V $(, $typaram)*> Visitor<'de> for MapVisitor 816 | | where @@ -716,7 +708,7 @@ error: breaking changes in ` for std = warning: trait impl specialized or removed (breaking) error: breaking changes in `<>::deserialize::KindVisitor as old::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:959:9 + --> serde-1.0.0/src/de/impls.rs:959:9 | 959 | / impl<'de> Visitor<'de> for KindVisitor { 960 | | type Value = OsStringKind; @@ -730,7 +722,7 @@ error: breaking changes in `< for std::time::Duration>::deserialize::Field as old::Deserialize<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1216:9 + --> serde-1.0.0/src/de/impls.rs:1216:9 | 1216 | / impl<'de> Deserialize<'de> for Field { 1217 | | fn deserialize(deserializer: D) -> Result @@ -744,7 +736,7 @@ error: breaking changes in ` for std = warning: trait impl specialized or removed (breaking) error: breaking changes in `< for std::time::Duration>::deserialize::Field as old::Deserialize<'de>>::deserialize::FieldVisitor as old::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1223:17 + --> serde-1.0.0/src/de/impls.rs:1223:17 | 1223 | / impl<'de> Visitor<'de> for FieldVisitor { 1224 | | type Value = Field; @@ -758,7 +750,7 @@ error: breaking changes in `< for st = warning: trait impl specialized or removed (breaking) error: breaking changes in ` for std::time::Duration>::deserialize::DurationVisitor as old::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1262:9 + --> serde-1.0.0/src/de/impls.rs:1262:9 | 1262 | / impl<'de> Visitor<'de> for DurationVisitor { 1263 | | type Value = Duration; @@ -772,7 +764,7 @@ error: breaking changes in ` for std = warning: trait impl specialized or removed (breaking) error: breaking changes in ` for std::ops::Range>::deserialize::Field as old::Deserialize<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1355:9 + --> serde-1.0.0/src/de/impls.rs:1355:9 | 1355 | / impl<'de> Deserialize<'de> for Field { 1356 | | fn deserialize(deserializer: D) -> Result @@ -786,7 +778,7 @@ error: breaking changes in ` for std = warning: trait impl specialized or removed (breaking) error: breaking changes in `< for std::ops::Range>::deserialize::Field as old::Deserialize<'de>>::deserialize::FieldVisitor as old::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1362:17 + --> serde-1.0.0/src/de/impls.rs:1362:17 | 1362 | / impl<'de> Visitor<'de> for FieldVisitor { 1363 | | type Value = Field; @@ -800,7 +792,7 @@ error: breaking changes in `< for st = warning: trait impl specialized or removed (breaking) error: breaking changes in ` for std::ops::Range>::deserialize::RangeVisitor as old::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1403:9 + --> serde-1.0.0/src/de/impls.rs:1403:9 | 1403 | / impl<'de, Idx> Visitor<'de> for RangeVisitor 1404 | | where @@ -814,7 +806,7 @@ error: breaking changes in ` for std = warning: trait impl specialized or removed (breaking) error: breaking changes in ` for std::result::Result>::deserialize::Field as old::Deserialize<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1513:9 + --> serde-1.0.0/src/de/impls.rs:1513:9 | 1513 | / impl<'de> Deserialize<'de> for Field { 1514 | | #[inline] @@ -828,7 +820,7 @@ error: breaking changes in ` for std = warning: trait impl specialized or removed (breaking) error: breaking changes in `< for std::result::Result>::deserialize::Field as old::Deserialize<'de>>::deserialize::FieldVisitor as old::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1521:17 + --> serde-1.0.0/src/de/impls.rs:1521:17 | 1521 | / impl<'de> Visitor<'de> for FieldVisitor { 1522 | | type Value = Field; @@ -842,7 +834,7 @@ error: breaking changes in `< for st = warning: trait impl specialized or removed (breaking) error: breaking changes in ` for std::result::Result>::deserialize::ResultVisitor as old::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/de/impls.rs:1577:9 + --> serde-1.0.0/src/de/impls.rs:1577:9 | 1577 | / impl<'de, T, E> Visitor<'de> for ResultVisitor 1578 | | where @@ -856,7 +848,7 @@ error: breaking changes in ` for std = warning: trait impl specialized or removed (breaking) error: breaking changes in ` as old::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:30:5 + --> serde-1.0.0/src/private/de.rs:30:5 | 30 | / impl<'de, E> Deserializer<'de> for MissingFieldDeserializer 31 | | where @@ -870,7 +862,7 @@ error: breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:68:5 + --> serde-1.0.0/src/private/de.rs:68:5 | 68 | / impl<'a> Visitor<'a> for CowStrVisitor { 69 | | type Value = Cow<'a, str>; @@ -884,7 +876,7 @@ error: breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:137:5 + --> serde-1.0.0/src/private/de.rs:137:5 | 137 | / impl<'a> Visitor<'a> for CowBytesVisitor { 138 | | type Value = Cow<'a, [u8]>; @@ -898,7 +890,7 @@ error: breaking changes in ` /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:236:5 + --> serde-1.0.8/src/private/de.rs:236:5 | 236 | / pub enum Content<'de> { 237 | | Bool(bool), @@ -911,18 +903,18 @@ error: breaking changes in `Content` | = warning: region parameter added (breaking) warning: enum variant added (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:254:9 + --> serde-1.0.8/src/private/de.rs:254:9 | 254 | Str(&'de str), | ^^^^^^^^^^^^^ warning: enum variant added (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:255:9 + --> serde-1.0.8/src/private/de.rs:255:9 | 255 | ByteBuf(Vec), | ^^^^^^^^^^^^^^^^ error: breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:290:5 + --> serde-1.0.0/src/private/de.rs:290:5 | 290 | / impl<'de> Deserialize<'de> for Content { 291 | | fn deserialize(deserializer: D) -> Result @@ -936,7 +928,7 @@ error: breaking changes in `> = warning: trait impl specialized or removed (breaking) error: breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:303:5 + --> serde-1.0.0/src/private/de.rs:303:5 | 303 | / impl<'de> Visitor<'de> for ContentVisitor { 304 | | type Value = Content; @@ -950,7 +942,7 @@ error: breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:498:5 + --> serde-1.0.0/src/private/de.rs:498:5 | 498 | / impl<'de> DeserializeSeed<'de> for TagOrContentVisitor { 499 | | type Value = TagOrContent; @@ -964,7 +956,7 @@ error: breaking changes in `>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:511:5 + --> serde-1.0.0/src/private/de.rs:511:5 | 511 | / impl<'de> Visitor<'de> for TagOrContentVisitor { 512 | | type Value = TagOrContent; @@ -978,7 +970,7 @@ error: breaking changes in ` /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:798:5 + --> serde-1.0.8/src/private/de.rs:798:5 | 798 | / pub struct TaggedContentVisitor<'de, T> { 799 | | tag_name: &'static str, @@ -988,18 +980,18 @@ error: breaking changes in `TaggedContentVisitor` | = warning: region parameter added (breaking) warning: variant field added to variant with private fields (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:800:9 + --> serde-1.0.8/src/private/de.rs:800:9 | 800 | value: PhantomData>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: variant field removed from variant with private fields (breaking) - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:745:9 + --> serde-1.0.0/src/private/de.rs:745:9 | 745 | tag: PhantomData, | ^^^^^^^^^^^^^^^^^^^ error: breaking changes in `new` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:751:9 + --> serde-1.0.0/src/private/de.rs:751:9 | 751 | / pub fn new(name: &'static str) -> Self { 752 | | TaggedContentVisitor { @@ -1012,7 +1004,7 @@ error: breaking changes in `new` = warning: removed item in inherent impl (breaking) error: breaking changes in ` as old::de::DeserializeSeed<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:759:5 + --> serde-1.0.0/src/private/de.rs:759:5 | 759 | / impl<'de, T> DeserializeSeed<'de> for TaggedContentVisitor 760 | | where @@ -1026,7 +1018,7 @@ error: breaking changes in ` as old::d = warning: trait impl specialized or removed (breaking) error: breaking changes in ` as old::de::Visitor<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:775:5 + --> serde-1.0.0/src/private/de.rs:775:5 | 775 | / impl<'de, T> Visitor<'de> for TaggedContentVisitor 776 | | where @@ -1040,7 +1032,7 @@ error: breaking changes in ` as old::d = warning: trait impl specialized or removed (breaking) error: breaking changes in `ContentDeserializer` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:970:5 + --> serde-1.0.8/src/private/de.rs:970:5 | 970 | / pub struct ContentDeserializer<'de, E> { 971 | | content: Content<'de>, @@ -1051,7 +1043,7 @@ error: breaking changes in `ContentDeserializer` = warning: region parameter added (breaking) error: breaking changes in ` as old::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:874:5 + --> serde-1.0.0/src/private/de.rs:874:5 | 874 | / impl<'de, E> Deserializer<'de> for ContentDeserializer 875 | | where @@ -1065,7 +1057,7 @@ error: breaking changes in ` as old::De = warning: trait impl specialized or removed (breaking) error: breaking changes in `new` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1004:9 + --> serde-1.0.0/src/private/de.rs:1004:9 | 1004 | / pub fn new(content: Content) -> Self { 1005 | | ContentDeserializer { @@ -1078,7 +1070,7 @@ error: breaking changes in `new` = warning: removed item in inherent impl (breaking) error: breaking changes in ` as old::de::EnumAccess<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1021:5 + --> serde-1.0.0/src/private/de.rs:1021:5 | 1021 | / impl<'de, E> de::EnumAccess<'de> for EnumDeserializer 1022 | | where @@ -1092,7 +1084,7 @@ error: breaking changes in ` as o = warning: trait impl specialized or removed (breaking) error: breaking changes in ` as old::de::VariantAccess<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1049:5 + --> serde-1.0.0/src/private/de.rs:1049:5 | 1049 | / impl<'de, E> de::VariantAccess<'de> for VariantDeserializer 1050 | | where @@ -1106,7 +1098,7 @@ error: breaking changes in ` a = warning: trait impl specialized or removed (breaking) error: breaking changes in ` as old::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1125:5 + --> serde-1.0.0/src/private/de.rs:1125:5 | 1125 | / impl<'de, E> de::Deserializer<'de> for SeqDeserializer 1126 | | where @@ -1120,7 +1112,7 @@ error: breaking changes in ` as ol = warning: trait impl specialized or removed (breaking) error: breaking changes in ` as old::de::SeqAccess<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1157:5 + --> serde-1.0.0/src/private/de.rs:1157:5 | 1157 | / impl<'de, E> de::SeqAccess<'de> for SeqDeserializer 1158 | | where @@ -1134,7 +1126,7 @@ error: breaking changes in ` as ol = warning: trait impl specialized or removed (breaking) error: breaking changes in ` as old::de::MapAccess<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1203:5 + --> serde-1.0.0/src/private/de.rs:1203:5 | 1203 | / impl<'de, E> de::MapAccess<'de> for MapDeserializer 1204 | | where @@ -1148,7 +1140,7 @@ error: breaking changes in ` as ol = warning: trait impl specialized or removed (breaking) error: breaking changes in ` as old::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1237:5 + --> serde-1.0.0/src/private/de.rs:1237:5 | 1237 | / impl<'de, E> de::Deserializer<'de> for MapDeserializer 1238 | | where @@ -1162,7 +1154,7 @@ error: breaking changes in ` as ol = warning: trait impl specialized or removed (breaking) error: breaking changes in `ContentRefDeserializer` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.8/src/private/de.rs:1364:5 + --> serde-1.0.8/src/private/de.rs:1364:5 | 1364 | / pub struct ContentRefDeserializer<'a, 'de: 'a, E> { 1365 | | content: &'a Content<'de>, @@ -1173,7 +1165,7 @@ error: breaking changes in `ContentRefDeserializer` = warning: region parameter added (breaking) error: breaking changes in ` as old::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1266:5 + --> serde-1.0.0/src/private/de.rs:1266:5 | 1266 | / impl<'de, 'a, E> Deserializer<'de> for ContentRefDeserializer<'a, E> 1267 | | where @@ -1187,7 +1179,7 @@ error: breaking changes in ` as = warning: trait impl specialized or removed (breaking) error: breaking changes in `new` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1396:9 + --> serde-1.0.0/src/private/de.rs:1396:9 | 1396 | / pub fn new(content: &'a Content) -> Self { 1397 | | ContentRefDeserializer { @@ -1200,7 +1192,7 @@ error: breaking changes in `new` = warning: removed item in inherent impl (breaking) error: breaking changes in ` as old::de::EnumAccess<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1413:5 + --> serde-1.0.0/src/private/de.rs:1413:5 | 1413 | / impl<'de, 'a, E> de::EnumAccess<'de> for EnumRefDeserializer<'a, E> 1414 | | where @@ -1214,7 +1206,7 @@ error: breaking changes in ` as old::de::VariantAccess<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1441:5 + --> serde-1.0.0/src/private/de.rs:1441:5 | 1441 | / impl<'de, 'a, E> de::VariantAccess<'de> for VariantRefDeserializer<'a, E> 1442 | | where @@ -1228,7 +1220,7 @@ error: breaking changes in ` as old::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1517:5 + --> serde-1.0.0/src/private/de.rs:1517:5 | 1517 | / impl<'de, 'a, E> de::Deserializer<'de> for SeqRefDeserializer<'a, E> 1518 | | where @@ -1242,7 +1234,7 @@ error: breaking changes in ` as old::de::SeqAccess<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1549:5 + --> serde-1.0.0/src/private/de.rs:1549:5 | 1549 | / impl<'de, 'a, E> de::SeqAccess<'de> for SeqRefDeserializer<'a, E> 1550 | | where @@ -1256,7 +1248,7 @@ error: breaking changes in ` as old::de::MapAccess<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1595:5 + --> serde-1.0.0/src/private/de.rs:1595:5 | 1595 | / impl<'de, 'a, E> de::MapAccess<'de> for MapRefDeserializer<'a, E> 1596 | | where @@ -1270,7 +1262,7 @@ error: breaking changes in ` as old::Deserializer<'de>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1630:5 + --> serde-1.0.0/src/private/de.rs:1630:5 | 1630 | / impl<'de, 'a, E> de::Deserializer<'de> for MapRefDeserializer<'a, E> 1631 | | where @@ -1284,7 +1276,7 @@ error: breaking changes in ` as old::de::IntoDeserializer<'de, E>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1651:5 + --> serde-1.0.0/src/private/de.rs:1651:5 | 1651 | / impl<'de, E> de::IntoDeserializer<'de, E> for ContentDeserializer 1652 | | where @@ -1298,7 +1290,7 @@ error: breaking changes in ` as old::de = warning: trait impl specialized or removed (breaking) error: breaking changes in ` as old::de::IntoDeserializer<'de, E>>` - --> /home/twk/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.0/src/private/de.rs:1662:5 + --> 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 From ba3d2cc0888fff0f97e8d34286c48e3de570ef96 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 9 Aug 2017 20:21:56 +0200 Subject: [PATCH 235/553] Cleaned up registry handling. --- .travis.yml | 4 +- src/bin/cargo_semver.rs | 18 +- tests/full.rs | 4 +- tests/full_cases/log-0.3.4-0.3.8 | 171 --------------- tests/full_cases/rand-0.3.10-0.3.16 | 316 ---------------------------- 5 files changed, 15 insertions(+), 498 deletions(-) diff --git a/.travis.yml b/.travis.yml index fcc25be38b3d3..924fa6cb922d9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,5 @@ addons: script: - cargo build --verbose + - cargo update - RUST_BACKTRACE=full cargo test --verbose - - pwd - - ls - - ls target/debug diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 5ffe63caba99d..2201213f9425a 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -3,6 +3,7 @@ extern crate cargo; extern crate crates_io; +extern crate env_logger; extern crate getopts; use crates_io::{Crate, Registry}; @@ -10,7 +11,6 @@ use crates_io::{Crate, Registry}; use cargo::exit_with_error; use cargo::core::{Package, PackageId, Source, SourceId, Workspace}; use cargo::ops::{compile, CompileMode, CompileOptions}; -use cargo::sources::registry::RegistrySource; use cargo::util::{human, CargoError, CargoResult, CliError}; use cargo::util::config::Config; use cargo::util::important_paths::find_root_manifest_for_wd; @@ -51,18 +51,18 @@ struct NameAndVersion<'a> { struct SourceInfo<'a> { /// The source id to be used. id: SourceId, - /// The registry to be used. - registry: RegistrySource<'a>, + /// The source to be used. + source: Box, } impl<'a> SourceInfo<'a> { /// Construct a new source info for `crates.io`. fn new(config: &'a Config) -> CargoResult> { let source_id = SourceId::crates_io(config)?; - let registry = RegistrySource::remote(&source_id, config); + let source = source_id.load(config); Ok(SourceInfo { id: source_id, - registry: registry, + source: source, }) } } @@ -98,7 +98,7 @@ impl<'a> WorkInfo<'a> { // TODO: fall back to locally cached package instance, or better yet, search for it // first. let package_id = PackageId::new(info.name, info.version, &source.id)?; - let package = source.registry.download(&package_id)?; + let package = source.source.download(&package_id)?; let workspace = Workspace::ephemeral(package.clone(), config, None, false)?; Ok(WorkInfo { @@ -237,6 +237,12 @@ fn main() { exit_with_error(CliError::new(e, 1), &mut config.shell()); } + ::std::env::set_var("RUST_LOG", "debug"); + + if env_logger::init().is_err() { + eprintln!("ERROR: could not initialize logger"); + } + let args: Vec = std::env::args().skip(1).collect(); let mut opts = Options::new(); diff --git a/tests/full.rs b/tests/full.rs index 0084e1c0e6e76..74097d6b96e0e 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -63,8 +63,8 @@ macro_rules! full_test { .args(&["semver", "-S", &old_version, "-C", &new_version]) .env("RUST_BACKTRACE", "full") .stdin(Stdio::null()) - .stdout(out_pipe) - .stderr(err_pipe) + // .stdout(out_pipe) + // .stderr(err_pipe) .status() .expect("could not run cargo semver") .success(); diff --git a/tests/full_cases/log-0.3.4-0.3.8 b/tests/full_cases/log-0.3.4-0.3.8 index a1d1cfd16119f..e69de29bb2d1d 100644 --- a/tests/full_cases/log-0.3.4-0.3.8 +++ b/tests/full_cases/log-0.3.4-0.3.8 @@ -1,171 +0,0 @@ -version bump: 0.3.4 -> (technically breaking) -> 0.4.0 -warning: technically breaking changes in `` - --> log-0.3.8/src/lib.rs:266:27 - | -266 | #[derive(Copy, Eq, Debug, Hash)] - | ^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> log-0.3.8/src/lib.rs:410:27 - | -410 | #[derive(Copy, Eq, Debug, Hash)] - | ^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in ` as std::fmt::Debug>` - --> log-0.3.8/src/lib.rs:517:10 - | -517 | #[derive(Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in ` as std::cmp::Eq>` - --> log-0.3.8/src/lib.rs:552:10 - | -552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] - | ^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in ` as std::cmp::PartialEq>` - --> log-0.3.8/src/lib.rs:552:14 - | -552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] - | ^^^^^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in ` as std::cmp::Ord>` - --> log-0.3.8/src/lib.rs:552:25 - | -552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] - | ^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in ` as std::cmp::PartialOrd>` - --> log-0.3.8/src/lib.rs:552:30 - | -552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] - | ^^^^^^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in ` as std::hash::Hash>` - --> log-0.3.8/src/lib.rs:552:42 - | -552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] - | ^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in ` as std::fmt::Debug>` - --> log-0.3.8/src/lib.rs:552:48 - | -552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> log-0.3.8/src/lib.rs:591:1 - | -591 | / impl Log for NopLogger { -592 | | fn enabled(&self, _: &LogMetadata) -> bool { false } -593 | | -594 | | fn log(&self, _: &LogRecord) {} -595 | | } - | |_^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> log-0.3.8/src/lib.rs:604:30 - | -604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] - | ^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> log-0.3.8/src/lib.rs:604:34 - | -604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] - | ^^^^^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> log-0.3.8/src/lib.rs:604:45 - | -604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] - | ^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> log-0.3.8/src/lib.rs:604:50 - | -604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] - | ^^^^^^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> log-0.3.8/src/lib.rs:604:62 - | -604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] - | ^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: path changes to `set_logger_raw` - --> log-0.3.8/src/lib.rs:713:1 - | -713 | / pub unsafe fn set_logger_raw(make_logger: M) -> Result<(), SetLoggerError> -714 | | where M: FnOnce(MaxLogLevelFilter) -> *const Log { -715 | | if STATE.compare_and_swap(UNINITIALIZED, INITIALIZING, -716 | | Ordering::SeqCst) != UNINITIALIZED { -... | -722 | | Ok(()) -723 | | } - | |_^ - | - = note: added definition (technically breaking) - -warning: path changes to `shutdown_logger` - --> log-0.3.8/src/lib.rs:736:1 - | -736 | / pub fn shutdown_logger() -> Result, ShutdownLoggerError> { -737 | | shutdown_logger_raw().map(|l| unsafe { mem::transmute(l) }) -738 | | } - | |_^ - | - = note: added definition (technically breaking) - -warning: path changes to `shutdown_logger_raw` - --> log-0.3.8/src/lib.rs:754:1 - | -754 | / pub fn shutdown_logger_raw() -> Result<*const Log, ShutdownLoggerError> { -755 | | // Set the global log level to stop other thread from logging -756 | | MAX_LOG_LEVEL_FILTER.store(0, Ordering::SeqCst); -757 | | -... | -772 | | } -773 | | } - | |_^ - | - = note: added definition (technically breaking) - -warning: path changes to `ShutdownLoggerError` - --> log-0.3.8/src/lib.rs:797:1 - | -797 | pub struct ShutdownLoggerError(()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: added definition (technically breaking) - diff --git a/tests/full_cases/rand-0.3.10-0.3.16 b/tests/full_cases/rand-0.3.10-0.3.16 index ef6f67abc9551..e69de29bb2d1d 100644 --- a/tests/full_cases/rand-0.3.10-0.3.16 +++ b/tests/full_cases/rand-0.3.10-0.3.16 @@ -1,316 +0,0 @@ -version bump: 0.3.10 -> (technically breaking) -> 0.4.0 -warning: technically breaking changes in ` as std::fmt::Debug>` - --> rand-0.3.16/src/lib.rs:647:10 - | -647 | #[derive(Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in ` as std::fmt::Debug>` - --> rand-0.3.16/src/lib.rs:667:10 - | -667 | #[derive(Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/lib.rs:727:17 - | -727 | #[derive(Clone, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in ` as std::fmt::Debug>` - --> rand-0.3.16/src/lib.rs:817:10 - | -817 | #[derive(Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in ` as std::fmt::Debug>` - --> rand-0.3.16/src/lib.rs:835:10 - | -835 | #[derive(Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/lib.rs:840:23 - | -840 | #[derive(Copy, Clone, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/lib.rs:903:10 - | -903 | #[derive(Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/lib.rs:918:17 - | -918 | #[derive(Clone, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in ` as std::fmt::Debug>` - --> rand-0.3.16/src/distributions/mod.rs:56:10 - | -56 | #[derive(Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in ` as std::fmt::Debug>` - --> rand-0.3.16/src/distributions/mod.rs:83:23 - | -83 | #[derive(Copy, Clone, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in ` as std::fmt::Debug>` - --> rand-0.3.16/src/distributions/mod.rs:116:10 - | -116 | #[derive(Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in ` as std::fmt::Debug>` - --> rand-0.3.16/src/distributions/range.rs:49:23 - | -49 | #[derive(Clone, Copy, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/distributions/gamma.rs:52:23 - | -52 | #[derive(Clone, Copy, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/distributions/gamma.rs:57:23 - | -57 | #[derive(Clone, Copy, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/distributions/gamma.rs:78:23 - | -78 | #[derive(Clone, Copy, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/distributions/gamma.rs:88:23 - | -88 | #[derive(Clone, Copy, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/distributions/gamma.rs:200:23 - | -200 | #[derive(Clone, Copy, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/distributions/gamma.rs:205:23 - | -205 | #[derive(Clone, Copy, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/distributions/gamma.rs:258:23 - | -258 | #[derive(Clone, Copy, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/distributions/gamma.rs:302:23 - | -302 | #[derive(Clone, Copy, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/distributions/normal.rs:36:23 - | -36 | #[derive(Clone, Copy, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/distributions/normal.rs:91:23 - | -91 | #[derive(Clone, Copy, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/distributions/normal.rs:139:23 - | -139 | #[derive(Clone, Copy, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/distributions/exponential.rs:37:23 - | -37 | #[derive(Clone, Copy, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/distributions/exponential.rs:74:23 - | -74 | #[derive(Clone, Copy, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/isaac.rs:264:1 - | -264 | / impl fmt::Debug for IsaacRng { -265 | | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -266 | | write!(f, "IsaacRng {{}}") -267 | | } -268 | | } - | |_^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/isaac.rs:513:1 - | -513 | / impl fmt::Debug for Isaac64Rng { -514 | | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -515 | | write!(f, "Isaac64Rng {{}}") -516 | | } -517 | | } - | |_^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/chacha.rs:29:23 - | -29 | #[derive(Copy, Clone, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in ` as std::fmt::Debug>` - --> rand-0.3.16/src/reseeding.rs:24:10 - | -24 | #[derive(Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/reseeding.rs:136:23 - | -136 | #[derive(Clone, Copy, Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `new::rand_impls::` - --> rand_impls.rs:223:9 - | -223 | / impl Rand for [T; $n] where T: Rand { -224 | | #[inline] -225 | | fn rand(_rng: &mut R) -> [T; $n] { -226 | | [_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*] -227 | | } -228 | | } - | |_________^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `new::rand_impls::` - --> rand_impls.rs:231:9 - | -231 | / impl Rand for [T; $n] { -232 | | fn rand(_rng: &mut R) -> [T; $n] { [] } -233 | | } - | |_________^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `` - --> rand-0.3.16/src/os.rs:50:1 - | -50 | / impl fmt::Debug for OsRng { -51 | | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -52 | | write!(f, "OsRng {{}}") -53 | | } -54 | | } - | |_^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in ` as std::fmt::Debug>` - --> rand-0.3.16/src/read.rs:33:10 - | -33 | #[derive(Debug)] - | ^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `Rng` - --> rand-0.3.16/src/lib.rs:324:1 - | -324 | / pub trait Rng { -325 | | /// Return the next random u32. -326 | | /// -327 | | /// This rarely needs to be called directly, prefer `r.gen()` to -... | -594 | | } -595 | | } - | |_^ - | -note: added defaulted item to trait (technically breaking) - --> rand-0.3.16/src/lib.rs:560:5 - | -560 | / fn choose_mut<'a, T>(&mut self, values: &'a mut [T]) -> Option<&'a mut T> where Self: Sized { -561 | | if values.is_empty() { -562 | | None -563 | | } else { -... | -566 | | } -567 | | } - | |_____^ - From 3b5d1b00f96414cf7893469c0703172ea7c7373a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 10 Aug 2017 12:14:09 +0200 Subject: [PATCH 236/553] Switched to newer cargo version. --- Cargo.toml | 4 ++-- src/bin/cargo_semver.rs | 39 ++++++++++++++++++++++++--------------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 71b81324313f3..10673d3bd86ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,8 +15,8 @@ name = "rust-semverver" path = "src/bin/rust_semverver.rs" [dependencies] -cargo = "^0.18.0" -crates-io = "^0.7.0" +cargo = "^0.20.0" +crates-io = "^0.9.0" env_logger = "^0.4.0" log = "^0.3.0" semver = "^0.7.0" diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 2201213f9425a..260c645633a73 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -5,13 +5,15 @@ extern crate cargo; extern crate crates_io; extern crate env_logger; extern crate getopts; +#[macro_use] +extern crate log; use crates_io::{Crate, Registry}; use cargo::exit_with_error; use cargo::core::{Package, PackageId, Source, SourceId, Workspace}; use cargo::ops::{compile, CompileMode, CompileOptions}; -use cargo::util::{human, CargoError, CargoResult, CliError}; +use cargo::util::{CargoError, CargoResult, CliError}; use cargo::util::config::Config; use cargo::util::important_paths::find_root_manifest_for_wd; @@ -30,12 +32,12 @@ fn exact_search(query: &str) -> CargoResult { registry .search(query, 1) .map_err(|e| - human(format!("failed to retrieve search results from the registry: {}", e))) + format!("failed to retrieve search results from the registry: {}", e).into()) .and_then(|(mut crates, _)| { crates .drain(..) .find(|krate| krate.name == query) - .ok_or_else(|| human(format!("failed to find a matching crate `{}`", query))) + .ok_or_else(|| format!("failed to find a matching crate `{}`", query).into()) }) } @@ -60,6 +62,10 @@ impl<'a> SourceInfo<'a> { fn new(config: &'a Config) -> CargoResult> { let source_id = SourceId::crates_io(config)?; let source = source_id.load(config); + + debug!("source id: {:?}", source_id); + // TODO: debug!("source: {:?}", source); + Ok(SourceInfo { id: source_id, source: source, @@ -98,8 +104,11 @@ impl<'a> WorkInfo<'a> { // TODO: fall back to locally cached package instance, or better yet, search for it // first. let package_id = PackageId::new(info.name, info.version, &source.id)?; + debug!("package_id: {:?}", package_id); let package = source.source.download(&package_id)?; + // TODO: debug!("package: {:?}", package); let workspace = Workspace::ephemeral(package.clone(), config, None, false)?; + // TODO: debug!("workspace: {:?}", workspace); Ok(WorkInfo { package: package, @@ -116,7 +125,7 @@ impl<'a> WorkInfo<'a> { let rlib = compilation.libraries[self.package.package_id()] .iter() .find(|t| t.0.name() == name) - .ok_or_else(|| human("lost a build artifact"))?; + .ok_or_else(|| "lost a build artifact".to_owned())?; Ok((rlib.1.clone(), compilation.deps_output)) } @@ -134,16 +143,16 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { let name = if let Some(n) = split.next() { n } else { - return Err(human("spec has to be of form `name-version`".to_owned())); + return Err("spec has to be of form `name-version`".to_owned().into()); }; let version = if let Some(v) = split.next() { v } else { - return Err(human("spec has to be of form `name-version`".to_owned())); + return Err("spec has to be of form `name-version`".to_owned().into()); }; if split.next().is_some() { - return Err(human("spec has to be of form `name-version`".to_owned())); + return Err("spec has to be of form `name-version`".to_owned().into()); } Ok((name, version)) @@ -203,17 +212,17 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { .stdin(Stdio::piped()) .env("RUST_SEMVER_CRATE_VERSION", stable_version) .spawn() - .map_err(|e| human(format!("could not spawn rustc: {}", e)))?; + .map_err(|e| format!("could not spawn rustc: {}", e))?; if let Some(ref mut stdin) = child.stdin { stdin.write_fmt(format_args!("extern crate new; extern crate old;"))?; } else { - return Err(human("could not pipe to rustc (wtf?)")); + return Err("could not pipe to rustc (wtf?)".to_owned().into()); } child .wait() - .map_err(|e| human(format!("failed to wait for rustc: {}", e)))?; + .map_err(|e| format!("failed to wait for rustc: {}", e))?; Ok(()) } @@ -233,11 +242,11 @@ fn version() { /// /// Parse CLI arguments, handle their semantics, and provide for proper error handling. fn main() { - fn err(config: &Config, e: Box) -> ! { + fn err(config: &Config, e: CargoError) -> ! { exit_with_error(CliError::new(e, 1), &mut config.shell()); } - ::std::env::set_var("RUST_LOG", "debug"); + std::env::set_var("RUST_LOG", "debug"); if env_logger::init().is_err() { eprintln!("ERROR: could not initialize logger"); @@ -262,7 +271,7 @@ fn main() { let matches = match opts.parse(&args) { Ok(m) => m, - Err(f) => err(&config, human(f.to_string())), + Err(f) => err(&config, f.to_string().into()), }; if matches.opt_present("h") { @@ -279,14 +288,14 @@ fn main() { matches.opt_count("s") > 1 || matches.opt_count("S") > 1 { let msg = "at most one of `-s,--stable-path` and `-S,--stable-pkg` allowed".to_owned(); - err(&config, human(msg)); + err(&config, msg.to_owned().into()); } 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".to_owned(); - err(&config, human(msg)); + err(&config, msg.to_owned().into()); } if let Err(e) = do_main(&config, &matches) { From 501e785e1f6e89a3814cc199e2ac92aa8da1301f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 10 Aug 2017 12:35:28 +0200 Subject: [PATCH 237/553] Cleanup after the latest debugging session. --- src/bin/cargo_semver.rs | 34 ++- tests/full.rs | 6 +- tests/full_cases/log-0.3.4-0.3.8 | 171 +++++++++++++++ tests/full_cases/rand-0.3.10-0.3.16 | 316 ++++++++++++++++++++++++++++ tests/full_cases/serde-0.7.0-1.0.0 | 38 ++-- tests/full_cases/serde-1.0.0-1.0.8 | 8 +- 6 files changed, 526 insertions(+), 47 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 260c645633a73..8343df398443a 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -5,8 +5,6 @@ extern crate cargo; extern crate crates_io; extern crate env_logger; extern crate getopts; -#[macro_use] -extern crate log; use crates_io::{Crate, Registry}; @@ -63,9 +61,6 @@ impl<'a> SourceInfo<'a> { let source_id = SourceId::crates_io(config)?; let source = source_id.load(config); - debug!("source id: {:?}", source_id); - // TODO: debug!("source: {:?}", source); - Ok(SourceInfo { id: source_id, source: source, @@ -104,11 +99,8 @@ impl<'a> WorkInfo<'a> { // TODO: fall back to locally cached package instance, or better yet, search for it // first. let package_id = PackageId::new(info.name, info.version, &source.id)?; - debug!("package_id: {:?}", package_id); let package = source.source.download(&package_id)?; - // TODO: debug!("package: {:?}", package); let workspace = Workspace::ephemeral(package.clone(), config, None, false)?; - // TODO: debug!("workspace: {:?}", workspace); Ok(WorkInfo { package: package, @@ -125,7 +117,7 @@ impl<'a> WorkInfo<'a> { let rlib = compilation.libraries[self.package.package_id()] .iter() .find(|t| t.0.name() == name) - .ok_or_else(|| "lost a build artifact".to_owned())?; + .ok_or_else(|| "lost a build artifact")?; Ok((rlib.1.clone(), compilation.deps_output)) } @@ -143,16 +135,16 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { let name = if let Some(n) = split.next() { n } else { - return Err("spec has to be of form `name-version`".to_owned().into()); + return Err("spec has to be of form `name-version`".into()); }; let version = if let Some(v) = split.next() { v } else { - return Err("spec has to be of form `name-version`".to_owned().into()); + return Err("spec has to be of form `name-version`".into()); }; if split.next().is_some() { - return Err("spec has to be of form `name-version`".to_owned().into()); + return Err("spec has to be of form `name-version`".into()); } Ok((name, version)) @@ -217,7 +209,7 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { if let Some(ref mut stdin) = child.stdin { stdin.write_fmt(format_args!("extern crate new; extern crate old;"))?; } else { - return Err("could not pipe to rustc (wtf?)".to_owned().into()); + return Err("could not pipe to rustc (wtf?)".into()); } child @@ -246,8 +238,6 @@ fn main() { exit_with_error(CliError::new(e, 1), &mut config.shell()); } - std::env::set_var("RUST_LOG", "debug"); - if env_logger::init().is_err() { eprintln!("ERROR: could not initialize logger"); } @@ -261,8 +251,10 @@ fn main() { opts.optflag("d", "debug", "print command to debug and exit"); 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", "SPEC"); - opts.optopt("C", "current-pkg", "use a name-version string as current/new crate", "SPEC"); + opts.optopt("S", "stable-pkg", "use a name-version string as stable/old crate", + "SPEC"); + opts.optopt("C", "current-pkg", "use a name-version string as current/new crate", + "SPEC"); let config = match Config::default() { Ok(cfg) => cfg, @@ -287,15 +279,15 @@ fn main() { 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".to_owned(); - err(&config, msg.to_owned().into()); + let msg = "at most one of `-s,--stable-path` and `-S,--stable-pkg` allowed"; + err(&config, msg.into()); } 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".to_owned(); - err(&config, msg.to_owned().into()); + let msg = "at most one of `-c,--current-path` and `-C,--current-pkg` allowed"; + err(&config, msg.into()); } if let Err(e) = do_main(&config, &matches) { diff --git a/tests/full.rs b/tests/full.rs index 74097d6b96e0e..c90d30711d78b 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -63,8 +63,8 @@ macro_rules! full_test { .args(&["semver", "-S", &old_version, "-C", &new_version]) .env("RUST_BACKTRACE", "full") .stdin(Stdio::null()) - // .stdout(out_pipe) - // .stderr(err_pipe) + .stdout(out_pipe) + .stderr(err_pipe) .status() .expect("could not run cargo semver") .success(); @@ -77,7 +77,7 @@ macro_rules! full_test { eprintln!("path: {}", out_file); success &= Command::new("git") - .args(&["diff", "--quiet", out_file]) + .args(&["diff", /*"--quiet",*/ out_file]) .status() .expect("could not run git diff") .success(); diff --git a/tests/full_cases/log-0.3.4-0.3.8 b/tests/full_cases/log-0.3.4-0.3.8 index e69de29bb2d1d..a1d1cfd16119f 100644 --- a/tests/full_cases/log-0.3.4-0.3.8 +++ b/tests/full_cases/log-0.3.4-0.3.8 @@ -0,0 +1,171 @@ +version bump: 0.3.4 -> (technically breaking) -> 0.4.0 +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:266:27 + | +266 | #[derive(Copy, Eq, Debug, Hash)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:410:27 + | +410 | #[derive(Copy, Eq, Debug, Hash)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> log-0.3.8/src/lib.rs:517:10 + | +517 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::Eq>` + --> log-0.3.8/src/lib.rs:552:10 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::PartialEq>` + --> log-0.3.8/src/lib.rs:552:14 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::Ord>` + --> log-0.3.8/src/lib.rs:552:25 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::PartialOrd>` + --> log-0.3.8/src/lib.rs:552:30 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::hash::Hash>` + --> log-0.3.8/src/lib.rs:552:42 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> log-0.3.8/src/lib.rs:552:48 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:591:1 + | +591 | / impl Log for NopLogger { +592 | | fn enabled(&self, _: &LogMetadata) -> bool { false } +593 | | +594 | | fn log(&self, _: &LogRecord) {} +595 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:30 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:34 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:45 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:50 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:62 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: path changes to `set_logger_raw` + --> log-0.3.8/src/lib.rs:713:1 + | +713 | / pub unsafe fn set_logger_raw(make_logger: M) -> Result<(), SetLoggerError> +714 | | where M: FnOnce(MaxLogLevelFilter) -> *const Log { +715 | | if STATE.compare_and_swap(UNINITIALIZED, INITIALIZING, +716 | | Ordering::SeqCst) != UNINITIALIZED { +... | +722 | | Ok(()) +723 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `shutdown_logger` + --> log-0.3.8/src/lib.rs:736:1 + | +736 | / pub fn shutdown_logger() -> Result, ShutdownLoggerError> { +737 | | shutdown_logger_raw().map(|l| unsafe { mem::transmute(l) }) +738 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `shutdown_logger_raw` + --> log-0.3.8/src/lib.rs:754:1 + | +754 | / pub fn shutdown_logger_raw() -> Result<*const Log, ShutdownLoggerError> { +755 | | // Set the global log level to stop other thread from logging +756 | | MAX_LOG_LEVEL_FILTER.store(0, Ordering::SeqCst); +757 | | +... | +772 | | } +773 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `ShutdownLoggerError` + --> log-0.3.8/src/lib.rs:797:1 + | +797 | pub struct ShutdownLoggerError(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + diff --git a/tests/full_cases/rand-0.3.10-0.3.16 b/tests/full_cases/rand-0.3.10-0.3.16 index e69de29bb2d1d..7c0633c785842 100644 --- a/tests/full_cases/rand-0.3.10-0.3.16 +++ b/tests/full_cases/rand-0.3.10-0.3.16 @@ -0,0 +1,316 @@ +version bump: 0.3.10 -> (technically breaking) -> 0.4.0 +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/lib.rs:647:10 + | +647 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/lib.rs:667:10 + | +667 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/lib.rs:727:17 + | +727 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/lib.rs:817:10 + | +817 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/lib.rs:835:10 + | +835 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/lib.rs:840:23 + | +840 | #[derive(Copy, Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/lib.rs:903:10 + | +903 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/lib.rs:918:17 + | +918 | #[derive(Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/distributions/mod.rs:56:10 + | +56 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/distributions/mod.rs:83:23 + | +83 | #[derive(Copy, Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/distributions/mod.rs:116:10 + | +116 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/distributions/range.rs:49:23 + | +49 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:52:23 + | +52 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:57:23 + | +57 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:78:23 + | +78 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:88:23 + | +88 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:200:23 + | +200 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:205:23 + | +205 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:258:23 + | +258 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/gamma.rs:302:23 + | +302 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/normal.rs:36:23 + | +36 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/normal.rs:91:23 + | +91 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/normal.rs:139:23 + | +139 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/exponential.rs:37:23 + | +37 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/distributions/exponential.rs:74:23 + | +74 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/isaac.rs:264:1 + | +264 | / impl fmt::Debug for IsaacRng { +265 | | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +266 | | write!(f, "IsaacRng {{}}") +267 | | } +268 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/isaac.rs:513:1 + | +513 | / impl fmt::Debug for Isaac64Rng { +514 | | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +515 | | write!(f, "Isaac64Rng {{}}") +516 | | } +517 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/chacha.rs:29:23 + | +29 | #[derive(Copy, Clone, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/reseeding.rs:24:10 + | +24 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/reseeding.rs:136:23 + | +136 | #[derive(Clone, Copy, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::rand_impls::` + --> rand_impls.rs:223:9 + | +223 | / impl Rand for [T; $n] where T: Rand { +224 | | #[inline] +225 | | fn rand(_rng: &mut R) -> [T; $n] { +226 | | [_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*] +227 | | } +228 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `new::rand_impls::` + --> rand_impls.rs:231:9 + | +231 | / impl Rand for [T; $n] { +232 | | fn rand(_rng: &mut R) -> [T; $n] { [] } +233 | | } + | |_________^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> rand-0.3.16/src/os.rs:50:1 + | +50 | / impl fmt::Debug for OsRng { +51 | | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +52 | | write!(f, "OsRng {{}}") +53 | | } +54 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> rand-0.3.16/src/read.rs:33:10 + | +33 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `Rng` + --> rand-0.3.16/src/lib.rs:324:1 + | +324 | / pub trait Rng { +325 | | /// Return the next random u32. +326 | | /// +327 | | /// This rarely needs to be called directly, prefer `r.gen()` to +... | +594 | | } +595 | | } + | |_^ + | +note: added defaulted item to trait (technically breaking) + --> rand-0.3.16/src/lib.rs:560:5 + | +560 | / fn choose_mut<'a, T>(&mut self, values: &'a mut [T]) -> Option<&'a mut T> where Self: Sized { +561 | | if values.is_empty() { +562 | | None +563 | | } else { +... | +566 | | } +567 | | } + | |_____^ + diff --git a/tests/full_cases/serde-0.7.0-1.0.0 b/tests/full_cases/serde-0.7.0-1.0.0 index b293cf2f0caaa..5ed8205391387 100644 --- a/tests/full_cases/serde-0.7.0-1.0.0 +++ b/tests/full_cases/serde-0.7.0-1.0.0 @@ -209,7 +209,7 @@ warning: technically breaking changes in `new::ser::impls::` +warning: technically breaking changes in `new::ser::impls::` --> serde-1.0.0/src/ser/impls.rs:252:13 | 252 | / impl<$($name),+> Serialize for ($($name,)+) @@ -531,7 +531,7 @@ warning: technically breaking changes in ` a | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in ` as std::clone::Clone>` +warning: technically breaking changes in ` as std::clone::Clone>` --> serde-1.0.0/src/de/value.rs:158:18 | 158 | #[derive(Clone, Debug)] @@ -539,7 +539,7 @@ warning: technically breaking changes in ` as | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in ` as std::fmt::Debug>` +warning: technically breaking changes in ` as std::fmt::Debug>` --> serde-1.0.0/src/de/value.rs:158:25 | 158 | #[derive(Clone, Debug)] @@ -850,7 +850,7 @@ warning: technically breaking changes in ` for i8>::deserialize::PrimitiveVisitor as new::de::Visitor<'de>>` +warning: technically breaking changes in ` for f32>::deserialize::PrimitiveVisitor as new::de::Visitor<'de>>` --> serde-1.0.0/src/de/impls.rs:117:17 | 117 | / impl<'de> Visitor<'de> for PrimitiveVisitor { @@ -990,7 +990,7 @@ warning: technically breaking changes in `new::de::impls:: for std::collections::BTreeSet>::deserialize::SeqVisitor as new::de::Visitor<'de>>` +warning: technically breaking changes in ` for std::collections::VecDeque>::deserialize::SeqVisitor as new::de::Visitor<'de>>` --> serde-1.0.0/src/de/impls.rs:522:17 | 522 | / impl<'de, T $(, $typaram)*> Visitor<'de> for SeqVisitor @@ -1032,7 +1032,7 @@ warning: technically breaking changes in `new::de::impls:: as new::de::Visitor<'de>>` +warning: technically breaking changes in ` as new::de::Visitor<'de>>` --> serde-1.0.0/src/de/impls.rs:644:13 | 644 | / impl<'de, T> Visitor<'de> for ArrayVisitor<[T; $len]> @@ -1060,7 +1060,7 @@ warning: technically breaking changes in ` for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14)>` +warning: technically breaking changes in `new::de::impls:: for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)>` --> serde-1.0.0/src/de/impls.rs:759:13 | 759 | / impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) { @@ -2908,7 +2908,7 @@ error: breaking changes in `old::de::impls:: serde-0.7.0/src/de/impls.rs:356:9 | 356 | / pub struct $visitor_name { @@ -2918,7 +2918,7 @@ error: path changes to `BTreeSetVisitor` | = warning: removed definition (breaking) -error: breaking changes in ` as old::de::Visitor>` +error: breaking changes in ` as old::de::Visitor>` --> serde-0.7.0/src/de/impls.rs:369:9 | 369 | / impl Visitor for $visitor_name @@ -2974,7 +2974,7 @@ error: breaking changes in `old::de::impls::` | = warning: trait impl specialized or removed (breaking) -error: breaking changes in ` as old::de::Visitor>` +error: breaking changes in ` as old::de::Visitor>` --> serde-0.7.0/src/de/impls.rs:533:13 | 533 | / impl Visitor for $visitor where T: Deserialize { @@ -2988,7 +2988,7 @@ error: breaking changes in ` as old::de::Visit | = warning: trait impl specialized or removed (breaking) -error: breaking changes in `old::de::impls::` +error: breaking changes in `old::de::impls::` --> serde-0.7.0/src/de/impls.rs:553:13 | 553 | / impl Deserialize for [T; $len] @@ -3002,7 +3002,7 @@ error: breaking changes in `old::de::impls::` | = warning: trait impl specialized or removed (breaking) -error: breaking changes in `TupleVisitor1` +error: breaking changes in `TupleVisitor10` --> serde-1.0.0/src/de/impls.rs:725:13 | 725 | / struct $visitor<$($name,)+> { @@ -3022,7 +3022,7 @@ error: breaking changes in `new` | = warning: removed item in inherent impl (breaking) -error: breaking changes in ` as old::de::Visitor>` +error: breaking changes in ` as old::de::Visitor>` --> serde-0.7.0/src/de/impls.rs:630:13 | 630 | / impl< @@ -3036,7 +3036,7 @@ error: breaking changes in `` +error: breaking changes in `old::de::impls::` --> serde-0.7.0/src/de/impls.rs:653:13 | 653 | / impl< @@ -3050,7 +3050,7 @@ error: breaking changes in `old::de::impls:: serde-0.7.0/src/de/impls.rs:695:9 | 695 | / pub struct $visitor_name { @@ -3060,7 +3060,7 @@ error: path changes to `BTreeMapVisitor` | = warning: removed definition (breaking) -error: breaking changes in ` as old::de::Visitor>` +error: breaking changes in ` as old::de::Visitor>` --> serde-0.7.0/src/de/impls.rs:708:9 | 708 | / impl Visitor for $visitor_name @@ -3074,7 +3074,7 @@ error: breaking changes in ` as old::de::V | = warning: trait impl specialized or removed (breaking) -error: breaking changes in `old::de::impls::>` +error: breaking changes in `old::de::impls::>` --> serde-0.7.0/src/de/impls.rs:737:9 | 737 | / impl Deserialize for $ty @@ -3262,7 +3262,7 @@ warning: variant with no public fields changed to a struct variant (breaking) 123 | | } | |_^ -error: breaking changes in `F32Deserializer` +error: breaking changes in `I8Deserializer` --> serde-1.0.0/src/de/value.rs:159:9 | 159 | / pub struct $name { @@ -4070,7 +4070,7 @@ error: path changes to `SeqIteratorVisitor` | = warning: removed definition (breaking) -error: path changes to `TupleVisitor8` +error: path changes to `TupleVisitor2` --> serde-0.7.0/src/ser/impls.rs:377:13 | 377 | / pub struct $TupleVisitor<'a, $($T: 'a),+> { diff --git a/tests/full_cases/serde-1.0.0-1.0.8 b/tests/full_cases/serde-1.0.0-1.0.8 index 1be5f84fcf5d6..b8971ff445623 100644 --- a/tests/full_cases/serde-1.0.0-1.0.8 +++ b/tests/full_cases/serde-1.0.0-1.0.8 @@ -63,7 +63,7 @@ warning: technically breaking changes in ` for u8>::deserialize::PrimitiveVisitor as new::de::Visitor<'de>>` +warning: technically breaking changes in ` for i8>::deserialize::PrimitiveVisitor as new::de::Visitor<'de>>` --> serde-1.0.8/src/de/impls.rs:117:17 | 117 | / impl<'de> Visitor<'de> for PrimitiveVisitor { @@ -91,7 +91,7 @@ warning: technically breaking changes in ` for std::collections::HashMap>::deserialize::MapVisitor as new::de::Visitor<'de>>` +warning: technically breaking changes in ` for std::collections::BTreeMap>::deserialize::MapVisitor as new::de::Visitor<'de>>` --> serde-1.0.8/src/de/impls.rs:815:17 | 815 | / impl<'de, K, V $(, $typaram)*> Visitor<'de> for MapVisitor @@ -665,7 +665,7 @@ warning: technically breaking changes in ` for i8>::deserialize::PrimitiveVisitor as old::de::Visitor<'de>>` +error: breaking changes in ` for f32>::deserialize::PrimitiveVisitor as old::de::Visitor<'de>>` --> serde-1.0.0/src/de/impls.rs:117:17 | 117 | / impl<'de> Visitor<'de> for PrimitiveVisitor { @@ -679,7 +679,7 @@ error: breaking changes in ` for i8> | = warning: trait impl specialized or removed (breaking) -error: breaking changes in ` for std::collections::BTreeSet>::deserialize::SeqVisitor as old::de::Visitor<'de>>` +error: breaking changes in ` for std::collections::VecDeque>::deserialize::SeqVisitor as old::de::Visitor<'de>>` --> serde-1.0.0/src/de/impls.rs:522:17 | 522 | / impl<'de, T $(, $typaram)*> Visitor<'de> for SeqVisitor From 60881e94968dd3549c83827bd9884109c9163198 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 10 Aug 2017 17:04:24 +0200 Subject: [PATCH 238/553] Final cleanup in tests for now. --- tests/examples.rs | 3 ++- tests/full.rs | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/examples.rs b/tests/examples.rs index 328ab8e3483de..b75bdc7f56c0c 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -81,7 +81,8 @@ macro_rules! test { eprintln!("path: {}", out_file.to_str().unwrap()); success &= Command::new("git") - .args(&["diff", "--quiet", out_file.to_str().unwrap()]) + .args(&["diff", out_file.to_str().unwrap()]) + .env("PAGER", "") .status() .expect("could not run git diff") .success(); diff --git a/tests/full.rs b/tests/full.rs index c90d30711d78b..df529685e181a 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -77,7 +77,8 @@ macro_rules! full_test { eprintln!("path: {}", out_file); success &= Command::new("git") - .args(&["diff", /*"--quiet",*/ out_file]) + .args(&["diff", out_file]) + .env("PAGER", "") .status() .expect("could not run git diff") .success(); @@ -88,6 +89,6 @@ macro_rules! full_test { } full_test!(log, "log", "0.3.4", "0.3.8"); -full_test!(rand, "rand", "0.3.10", "0.3.16"); +// 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"); From 03d63edb13fc0c83b0cf4943c55778d871a76264 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 10 Aug 2017 19:27:36 +0200 Subject: [PATCH 239/553] Debugging session for #26. --- src/bin/cargo_semver.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 8343df398443a..b749f8a5fa1bb 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -5,6 +5,8 @@ extern crate cargo; extern crate crates_io; extern crate env_logger; extern crate getopts; +#[macro_use] +extern crate log; use crates_io::{Crate, Registry}; @@ -61,6 +63,8 @@ impl<'a> SourceInfo<'a> { let source_id = SourceId::crates_io(config)?; let source = source_id.load(config); + debug!("source id loaded: {:?}", source_id); + Ok(SourceInfo { id: source_id, source: source, @@ -99,6 +103,7 @@ impl<'a> WorkInfo<'a> { // TODO: fall back to locally cached package instance, or better yet, search for it // first. let package_id = PackageId::new(info.name, info.version, &source.id)?; + debug!("(remote) package id: {:?}", package_id); let package = source.source.download(&package_id)?; let workspace = Workspace::ephemeral(package.clone(), config, None, false)?; @@ -130,7 +135,7 @@ impl<'a> WorkInfo<'a> { /// and/or defaults, and dispatch the actual analysis. // TODO: possibly reduce the complexity by finding where some info can be taken from directly fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { - fn parse_arg(opt: &str) -> CargoResult<(&str, &str)> { + fn parse_arg(opt: &str) -> CargoResult { let mut split = opt.split('-'); let name = if let Some(n) = split.next() { n @@ -147,16 +152,13 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { return Err("spec has to be of form `name-version`".into()); } - Ok((name, version)) + Ok(NameAndVersion { name: name, version: version }) } let mut source = SourceInfo::new(config)?; let current = if let Some(opt) = matches.opt_str("C") { - let (name, version) = parse_arg(&opt)?; - - let info = NameAndVersion { name: name, version: version }; - WorkInfo::remote(config, &mut source, info)? + WorkInfo::remote(config, &mut source, parse_arg(&opt)?)? } else { WorkInfo::local(config, matches.opt_str("c").map(PathBuf::from))? }; @@ -164,12 +166,12 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { let name = current.package.name().to_owned(); let (stable, stable_version) = if let Some(opt) = matches.opt_str("S") { - let (name, version) = parse_arg(&opt)?; + let info = parse_arg(&opt)?; + let version = info.version.to_owned(); - let info = NameAndVersion { name: name, version: version }; let work_info = WorkInfo::remote(config, &mut source, info)?; - (work_info, version.to_owned()) + (work_info, version) } else if let Some(path) = matches.opt_str("s") { let work_info = WorkInfo::local(config, Some(PathBuf::from(path)))?; let version = format!("{}", work_info.package.version()); From c42e855e0fbbc71ae4b053be13756694a54b0a74 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 12 Aug 2017 20:54:33 +0200 Subject: [PATCH 240/553] Adjusted to newest nightly fixes to module spans. Fixes #3. --- tests/cases/addition/stdout | 21 +++++++++++++-------- tests/cases/addition_path/stdout | 8 +++++--- tests/cases/pathologic_paths/stdout | 8 ++++---- tests/cases/removal/stdout | 24 +++++++++++++++--------- 4 files changed, 37 insertions(+), 24 deletions(-) diff --git a/tests/cases/addition/stdout b/tests/cases/addition/stdout index 3a876f5ea12eb..5371868cfbd7c 100644 --- a/tests/cases/addition/stdout +++ b/tests/cases/addition/stdout @@ -8,9 +8,10 @@ warning: technically breaking changes in `Bcd` = note: item made public (technically breaking) warning: technically breaking changes in `b` - --> $REPO_PATH/tests/cases/addition/new.rs:10:5 + --> $REPO_PATH/tests/cases/addition/new.rs:9:1 | -10 | / #[allow(dead_code)] +9 | / pub mod b { +10 | | #[allow(dead_code)] 11 | | pub struct Cde; 12 | | } | |_^ @@ -18,10 +19,12 @@ warning: technically breaking changes in `b` = note: item made public (technically breaking) warning: technically breaking changes in `d` - --> $REPO_PATH/tests/cases/addition/new.rs:21:1 + --> $REPO_PATH/tests/cases/addition/new.rs:19:1 | -21 | } - | ^ +19 | / pub mod d { +20 | | +21 | | } + | |_^ | = note: item made public (technically breaking) @@ -34,10 +37,12 @@ warning: path changes to `Abc` = note: added definition (technically breaking) warning: path changes to `a` - --> $REPO_PATH/tests/cases/addition/new.rs:7:1 + --> $REPO_PATH/tests/cases/addition/new.rs:5:1 | -7 | } - | ^ +5 | / pub mod a { +6 | | +7 | | } + | |_^ | = note: added definition (technically breaking) diff --git a/tests/cases/addition_path/stdout b/tests/cases/addition_path/stdout index d10d3201cba1b..ae6d98c7cf3b4 100644 --- a/tests/cases/addition_path/stdout +++ b/tests/cases/addition_path/stdout @@ -22,10 +22,12 @@ note: added path (technically breaking) | ^^^^^^^^^^^^ warning: path changes to `d` - --> $REPO_PATH/tests/cases/addition_path/new.rs:17:1 + --> $REPO_PATH/tests/cases/addition_path/new.rs:15:1 | -17 | } - | ^ +15 | / pub mod d { +16 | | +17 | | } + | |_^ | = note: added definition (technically breaking) diff --git a/tests/cases/pathologic_paths/stdout b/tests/cases/pathologic_paths/stdout index 3caab879b7026..2e4d2db681784 100644 --- a/tests/cases/pathologic_paths/stdout +++ b/tests/cases/pathologic_paths/stdout @@ -1,17 +1,17 @@ version bump: 1.0.0 -> (technically breaking) -> 1.1.0 warning: path changes to `a` - --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:5:21 + --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:5:9 | 5 | pub mod a { blow!($($rest)*); } - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: added definition (technically breaking) warning: path changes to `b` - --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:6:21 + --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:6:9 | 6 | pub mod b { pub use super::a::*; } - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: added definition (technically breaking) diff --git a/tests/cases/removal/stdout b/tests/cases/removal/stdout index 4a01abfa76134..fd17ca8100065 100644 --- a/tests/cases/removal/stdout +++ b/tests/cases/removal/stdout @@ -16,18 +16,22 @@ error: breaking changes in `Bcd` = warning: item made private (breaking) error: path changes to `a` - --> $REPO_PATH/tests/cases/removal/old.rs:7:1 + --> $REPO_PATH/tests/cases/removal/old.rs:5:1 | -7 | } - | ^ +5 | / pub mod a { +6 | | +7 | | } + | |_^ | = warning: removed definition (breaking) error: breaking changes in `b` - --> $REPO_PATH/tests/cases/removal/new.rs:6:1 + --> $REPO_PATH/tests/cases/removal/new.rs:4:1 | -6 | } - | ^ +4 | / mod b { +5 | | +6 | | } + | |_^ | = warning: item made private (breaking) @@ -40,10 +44,12 @@ error: path changes to `Cde` = warning: removed definition (breaking) error: breaking changes in `d` - --> $REPO_PATH/tests/cases/removal/new.rs:14:1 + --> $REPO_PATH/tests/cases/removal/new.rs:12:1 | -14 | } - | ^ +12 | / mod d { +13 | | +14 | | } + | |_^ | = warning: item made private (breaking) From 3fdee13b02be9101fb3c2faef66051f10d2cf498 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 20 Aug 2017 15:21:59 +0200 Subject: [PATCH 241/553] More info material --- GSOC.md | 34 ++++++++++++++++++++++++++++++++++ README.md | 18 +++++++++++++----- 2 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 GSOC.md diff --git a/GSOC.md b/GSOC.md new file mode 100644 index 0000000000000..cef9a6a266e54 --- /dev/null +++ b/GSOC.md @@ -0,0 +1,34 @@ +# Notes on work done during GSoC 2017 +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 functioanlity 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. + +## 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/README.md b/README.md index 2b8f1e6fcdc42..19133882abc6b 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,9 @@ on `crates.io`. ## 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, crate. Then, a custom compiler driver is run on the -resulting crate and all necessary analysis is performed in that context. +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 will be provided soon. @@ -19,8 +20,10 @@ The tool is implemented as a cargo plugin. As of now, it can be obtained from th repository and compiled from source, provided you have a recent Rust nightly installed: ```sh +# using rustup is recommended $ rustup update nightly $ rustup default nightly + $ git clone https://github.com/ibabushkin/rust-semverver $ cd rust-semverver $ cargo install @@ -59,12 +62,15 @@ Options: use a name-version string as current/new crate ``` +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. + ## 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. According to the RFC, -most changes are already recognized correctly, even though trait- and inherent -implementations are not yet handled, and some type checks behave incorrectly. +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: @@ -83,6 +89,8 @@ correctly: * 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 Yet, the results presented to the user are merely an approximation of the required versioning policy, especially at such an early stage of development. From 2d0ed0001fd6971b791c97a4fda905ca028381c4 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 20 Aug 2017 20:12:23 +0200 Subject: [PATCH 242/553] More notes for the GSoC submission. --- GSOC.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/GSOC.md b/GSOC.md index cef9a6a266e54..fff0cb6b26ae9 100644 --- a/GSOC.md +++ b/GSOC.md @@ -13,6 +13,28 @@ See [this issue](https://github.com/ibabushkin/rust-semverver/issues/24) for a v 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](404). + +## Progress made +TODO: summarize your findings and what you learned here. + ## List of references * [this repository](https://github.com/ibabushkin/rust-semverver) contains the main body of code written. From e92cb6351ed61c2b5d90b5055710aa92c3f8ec2a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 20 Aug 2017 21:15:43 +0200 Subject: [PATCH 243/553] More notes for project submission. --- GSOC.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/GSOC.md b/GSOC.md index fff0cb6b26ae9..6f54ee1ab83ac 100644 --- a/GSOC.md +++ b/GSOC.md @@ -6,7 +6,7 @@ and which eventually led to the current working state of the project. ## Completion status All core functioanlity 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 +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 @@ -33,7 +33,12 @@ usability and code quality. An overview of the functionality, and it's implementation can be found [here](404). ## Progress made -TODO: summarize your findings and what you learned here. +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 From 67560aca77dac6d69cbbd7cc101c1f65b855ddfa Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 22 Aug 2017 21:04:51 +0200 Subject: [PATCH 244/553] Added more detailed implementation overview notes. --- GSOC.md | 5 ++- IMPLEMENTATION_NOTES.md | 95 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 IMPLEMENTATION_NOTES.md diff --git a/GSOC.md b/GSOC.md index 6f54ee1ab83ac..6f1520dfecbb3 100644 --- a/GSOC.md +++ b/GSOC.md @@ -5,7 +5,7 @@ gathering references to the work that has been done during the Google Summer of and which eventually led to the current working state of the project. ## Completion status -All core functioanlity has been implemented. There are still some bugs present, whose +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. @@ -30,7 +30,8 @@ the course of the program. Other possible enhancements are listed in the issue t 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](404). +An overview of the functionality, and it's implementation can be found +[here](https://github.com/ibabushkin/rust-semverver/blob/master/IMPLEMENTATION_NOTES.md). ## Progress made The project provided a very through and challenging walkthrough to the internal working of diff --git a/IMPLEMENTATION_NOTES.md b/IMPLEMENTATION_NOTES.md new file mode 100644 index 0000000000000..6ddabed7c0cab --- /dev/null +++ b/IMPLEMENTATION_NOTES.md @@ -0,0 +1,95 @@ +# 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. + +## 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 +TODO + +### Bounds checks implementation +TODO + +## 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 `quickecheck`, others are exercised as plain examples. + +Most of the functionality, however, especially the analysis implementation, is testes +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. From 61671ef6d6675cb6f19517b7f7e584a393385d9c Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 22 Aug 2017 21:54:49 +0200 Subject: [PATCH 245/553] More implementation notes. --- IMPLEMENTATION_NOTES.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/IMPLEMENTATION_NOTES.md b/IMPLEMENTATION_NOTES.md index 6ddabed7c0cab..b93a933b95e83 100644 --- a/IMPLEMENTATION_NOTES.md +++ b/IMPLEMENTATION_NOTES.md @@ -75,11 +75,35 @@ source spans, ultimately leading to deterministic output. The implementation is the `changes` submodule. ### Type checks implementation -TODO +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 TODO +### Inherent impl matching + ## 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 From 59ba1bf4a29a13c83d900612ff3c1c3c2acd4d7a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 23 Aug 2017 19:29:38 +0200 Subject: [PATCH 246/553] Added even more implementation notes. --- IMPLEMENTATION_NOTES.md | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/IMPLEMENTATION_NOTES.md b/IMPLEMENTATION_NOTES.md index b93a933b95e83..4076623eb1083 100644 --- a/IMPLEMENTATION_NOTES.md +++ b/IMPLEMENTATION_NOTES.md @@ -100,15 +100,32 @@ recognize all changes to trait bounds, this analysis step has to be performed in directions, to catch both loosening and tightening of bounds. ### Trait impl matching -TODO +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 `quickecheck`, others are exercised as plain examples. +tested using `quickcheck`, others are exercised as plain examples. Most of the functionality, however, especially the analysis implementation, is testes using an evergrowing integration test suite, which records the analysis results for mockup From 44197f6abfaa55b92ee1d44c54ea42a434959907 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 23 Aug 2017 19:44:06 +0200 Subject: [PATCH 247/553] Typos and small doc additions. --- IMPLEMENTATION_NOTES.md | 8 +++++--- README.md | 6 +++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/IMPLEMENTATION_NOTES.md b/IMPLEMENTATION_NOTES.md index 4076623eb1083..1515525734a6b 100644 --- a/IMPLEMENTATION_NOTES.md +++ b/IMPLEMENTATION_NOTES.md @@ -10,13 +10,15 @@ The toplevel directory of the repository is structured according to cargo's conv * 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. +* a cargo manifest and lockfile, various documentation material you are currently reading, + etc. is also placed at the top level. ## 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 +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 @@ -78,7 +80,7 @@ the `changes` submodule. 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 +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 @@ -127,7 +129,7 @@ regards to change categorization and storage, according to the usual convention, 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 testes +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 diff --git a/README.md b/README.md index 19133882abc6b..fe4f679578342 100644 --- a/README.md +++ b/README.md @@ -7,13 +7,17 @@ of Code 2017. The goal is to provide an automated command akin to `cargo clippy` analyzes the current crate's source code for changes compared to the most recent version on `crates.io`. +Details on the work done during GSoC 2017 can be found +[here](https://github.com/ibabushkin/rust-semverver/blob/master/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 will be provided soon. +More information on the inner workings of the tool can be found +[here](https://github.com/ibabushkin/rust-semverver/blob/master/IMPLEMENTATION_NOTES.md). ## Installation The tool is implemented as a cargo plugin. As of now, it can be obtained from this git From 054d4fe8f93fea6fb3d3c3e652fa8a299ff97f07 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 23 Aug 2017 19:49:07 +0200 Subject: [PATCH 248/553] Moved docs to a dedicated directory. --- README.md | 4 ++-- GSOC.md => doc/GSoC.md | 2 +- IMPLEMENTATION_NOTES.md => doc/impl_notes.md | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) rename GSOC.md => doc/GSoC.md (99%) rename IMPLEMENTATION_NOTES.md => doc/impl_notes.md (98%) diff --git a/README.md b/README.md index fe4f679578342..1cbacce88e8e4 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ analyzes the current crate's source code for changes compared to the most recent on `crates.io`. Details on the work done during GSoC 2017 can be found -[here](https://github.com/ibabushkin/rust-semverver/blob/master/GSOC.md). +[here](https://github.com/ibabushkin/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 @@ -17,7 +17,7 @@ said dummy and all necessary analysis is performed in that context, where type i and other resources are available. More information on the inner workings of the tool can be found -[here](https://github.com/ibabushkin/rust-semverver/blob/master/IMPLEMENTATION_NOTES.md). +[here](https://github.com/ibabushkin/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 diff --git a/GSOC.md b/doc/GSoC.md similarity index 99% rename from GSOC.md rename to doc/GSoC.md index 6f1520dfecbb3..c5a4fa2259f4f 100644 --- a/GSOC.md +++ b/doc/GSoC.md @@ -31,7 +31,7 @@ On a different front, the cargo plugin could need some technical improvements to 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/IMPLEMENTATION_NOTES.md). +[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 diff --git a/IMPLEMENTATION_NOTES.md b/doc/impl_notes.md similarity index 98% rename from IMPLEMENTATION_NOTES.md rename to doc/impl_notes.md index 1515525734a6b..0c7a47a1ec04f 100644 --- a/IMPLEMENTATION_NOTES.md +++ b/doc/impl_notes.md @@ -10,8 +10,9 @@ The toplevel directory of the repository is structured according to cargo's conv * 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. -* a cargo manifest and lockfile, various documentation material you are currently reading, - etc. is also placed at the top level. +* `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` From 3d983849413ce1398d70ea454a1abfdbffe80f7f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 23 Aug 2017 22:56:26 +0200 Subject: [PATCH 249/553] Comment overhaul. --- src/semcheck/changes.rs | 82 +++++++++++++++++++++++---------------- src/semcheck/mapping.rs | 8 ++-- src/semcheck/mismatch.rs | 12 +++--- src/semcheck/mod.rs | 2 +- src/semcheck/translate.rs | 18 ++++++--- src/semcheck/traverse.rs | 8 ++-- src/semcheck/typeck.rs | 4 +- 7 files changed, 79 insertions(+), 55 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 9563f632dc70e..ea05683a45151 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -6,7 +6,8 @@ //! 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 that we still group changes by the item they refer to, even if it's path changes. +//! 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::session::Session; @@ -28,16 +29,16 @@ use syntax_pos::Span; /// 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. +/// 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)] pub enum ChangeCategory { - /// Patch change - no change to the public API of a crate. + /// A patch-level change - no change to the public API of a crate. Patch, - /// A backwards-compatible change. + /// A non-breaking, backwards-compatible change. NonBreaking, - /// A breaking change that is very unlikely to cause breakage. + /// A breaking change that only causes breakage in well-known exotic cases. TechnicallyBreaking, /// A breaking, backwards-incompatible change. Breaking, @@ -65,6 +66,8 @@ impl<'a> fmt::Display for ChangeCategory { } /// 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(Symbol), @@ -85,15 +88,15 @@ impl<'a> fmt::Display for Name { /// A change record of newly introduced or removed paths to an item. /// -/// It is important to note that the `Eq` and `Ord` instances are constucted to only regard the -/// span of the associated item definition. All other spans are only present for later display of -/// the change record. +/// 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. + /// 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: Symbol, /// The definition span of the item. def_span: Span, - /// The set of spans of newly added exports of the item. + /// The set of spans of added exports of the item. additions: BTreeSet, /// The set of spans of removed exports of the item. removals: BTreeSet, @@ -135,7 +138,7 @@ impl PathChange { &self.def_span } - /// Report the change in a structured manner. + /// 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 { @@ -194,7 +197,7 @@ impl Ord for PathChange { pub enum ChangeType<'tcx> { /// An item has been made public. ItemMadePublic, - /// An item has been made private + /// An item has been made private. ItemMadePrivate, /// An item has changed it's kind. KindDifference, @@ -204,45 +207,57 @@ pub enum ChangeType<'tcx> { RegionParameterAdded, /// A region parameter has been removed from an item. RegionParameterRemoved, - /// A type parameter has been added to an item. + /// A possibly defaulted type parameter has been added to an item. TypeParameterAdded { defaulted: bool }, - /// A type parameter has been removed from an item. + /// 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 field hasb been added to a variant. + /// 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 }, - /// A field has been removed from a variant. + /// A possibly public field has been removed from a variant or struct. + /// + /// This also records whether all fields are public were public before the change. VariantFieldRemoved { public: bool, total_public: bool }, - /// A variant has changed it's style. + /// 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 }, /// A function has changed it's constness. FnConstChanged { now_const: bool }, - /// A method has changed whether it can be invoked as a method call. + /// A method either gained or lost a `self` parameter. MethodSelfChanged { now_self: bool }, - /// A trait's definition added an item. + /// A trait's definition added a possibly defaulted item. TraitItemAdded { defaulted: bool }, - /// A trait's definition removed an item. + /// A trait's definition removed a possibly defaulted item. TraitItemRemoved { defaulted: bool }, /// A trait's definition changed it's unsafety. TraitUnsafetyChanged { now_unsafe: bool }, - /// A field in a struct or enum has changed it's type. + /// An item's type has changed. TypeChanged { error: TypeError<'tcx> }, - /// An item's bounds have been tightened. + /// An item's (trait) bounds have been tightened. BoundsTightened { pred: Predicate<'tcx> }, - /// An item's bounds have been loosened. + /// 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 types. + /// A trait impl has been specialized or removed for some type(s). TraitImplTightened, - /// A trait impl has been generalized or newly added for some types. + /// 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 is any change we don't yet explicitly handle. + /// An unknown change we don't yet explicitly handle. Unknown, } @@ -251,6 +266,7 @@ 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 | @@ -358,9 +374,8 @@ impl<'a> fmt::Display for ChangeType<'a> { /// A change record of an item present in both crate versions. /// -/// It is important to note that the `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. +/// 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)>, @@ -448,7 +463,7 @@ impl<'tcx> Change<'tcx> { &self.new_span } - /// Report the change in a structured manner. + /// Report the change in a structured manner, using rustc's error reporting capabilities. fn report(&self, session: &Session) { if self.max == Patch || !self.output { return; @@ -504,9 +519,9 @@ impl<'tcx> Ord for Change<'tcx> { /// The total set of changes recorded for two crate versions. #[derive(Default)] pub struct ChangeSet<'tcx> { - /// The currently recorded path changes. + /// The set of currently recorded path changes. path_changes: HashMap, - /// The currently recorded regular changes. + /// The set of currently recorded regular changes. changes: HashMap>, /// The mapping of spans to changes, for ordering purposes. spans: BTreeMap, @@ -546,7 +561,7 @@ impl<'tcx> ChangeSet<'tcx> { self.path_changes.get_mut(&old).unwrap().insert(span, add); } - /// Add a new change entry for the given items. + /// Add a new change entry for the given item pair. pub fn new_change(&mut self, old_def_id: DefId, new_def_id: DefId, @@ -561,6 +576,7 @@ impl<'tcx> ChangeSet<'tcx> { 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, diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index ea895a99fc0f2..a7a62e20c1092 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -22,7 +22,7 @@ pub struct InherentEntry { pub name: Name, } -/// A set of pairs of impl- and item `DefId` for inherent associated items. +/// 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. @@ -48,9 +48,9 @@ pub struct IdMapping { child_mapping: HashMap>, /// New `DefId`s mapped to their old counterparts. reverse_mapping: HashMap, - /// Map of type parameters' `DefId`s and their definitions. + /// Type parameters' `DefId`s mapped to their definitions. type_params: HashMap, - /// Map of items from inherent impls' descriptors to the impls they are declared in. + /// Map from inherent impls' descriptors to the impls they are declared in. inherent_items: HashMap, } @@ -259,7 +259,7 @@ impl IdMapping { /// 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. +/// Both old and new exports can be missing. Allows for reuse of the `HashMap`s used for storage. #[derive(Default)] pub struct NameMapping { /// The exports in the type namespace. diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 4f6bd42d190fe..3f74c20c35524 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -1,8 +1,8 @@ //! 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 yet with other items are -//! essentially just 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. +//! 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 rustc::hir::def_id::DefId; use rustc::ty; @@ -23,7 +23,7 @@ use std::collections::{HashMap, VecDeque}; pub struct MismatchRelation<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { /// The type context used. tcx: TyCtxt<'a, 'gcx, 'tcx>, - /// The queue to append found item pairings. + /// The queue of found item pairings to be processed. item_queue: VecDeque<(DefId, DefId)>, /// The id mapping to use. id_mapping: &'a mut IdMapping, @@ -40,7 +40,7 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> MismatchRelation<'a, 'gcx, 'tcx> { } } - /// Process the next pair of `DefId`s in the queue and return them. + /// Process the next pair of `DefId`s in the queue. pub fn process(&mut self) { use rustc::hir::def::Def::*; @@ -56,7 +56,7 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> MismatchRelation<'a, 'gcx, 'tcx> { } } - /// Ensure that the pair of given `Substs` is suitable for being related. + /// Ensure that the pair of given `Substs` is suitable to be related. fn check_substs(&self, a_substs: &'tcx Substs<'tcx>, b_substs: &'tcx Substs<'tcx>) -> bool { for (a, b) in a_substs.iter().zip(b_substs) { if a.as_type().is_some() != b.as_type().is_some() { diff --git a/src/semcheck/mod.rs b/src/semcheck/mod.rs index 15653b884f3f5..55d2699c71fca 100644 --- a/src/semcheck/mod.rs +++ b/src/semcheck/mod.rs @@ -1,5 +1,5 @@ //! This module holds all logic and data structures needed to perform semver analysis on two -//! modules which are usually crate roots (or just regular modules in a testing scenario). +//! modules which are (usually) just crate roots. pub mod changes; diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 54a77d06904ab..4426bfcc9a61f 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -1,3 +1,6 @@ +//! The translation machinery used to lift items into the context of the other crate for +//! comparison and inference. + use rustc::hir::def_id::DefId; use rustc::ty::{ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt}; use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder}; @@ -83,7 +86,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { }) } - /// Translate a `DefId` of any item and it's substs. + /// Translate the `DefId` and substs of an item. fn translate_orig_substs(&self, index_map: &HashMap, orig_def_id: DefId, @@ -294,7 +297,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { self.translate(&self.construct_index_map(orig_def_id), &orig) } - /// Translate a predicate. + /// Translate a predicate using a type parameter index map. fn translate_predicate(&self, index_map: &HashMap, predicate: Predicate<'tcx>) -> Option> { @@ -373,7 +376,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { }) } - /// Translate a slice of predicates. + /// Translate a slice of predicates in the context of an item. fn translate_predicates(&self, orig_def_id: DefId, orig_preds: &[Predicate<'tcx>]) -> Option>> { @@ -391,7 +394,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { Some(target_preds) } - /// Translate a `ParamEnv`. + /// Translate a `ParamEnv` in the context of an item. pub fn translate_param_env(&self, orig_def_id: DefId, param_env: ParamEnv<'tcx>) -> Option> { @@ -402,7 +405,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { }) } - /// Translate a `TraitRef`. + /// 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> { @@ -429,12 +432,17 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { } } +/// 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, 'gcx: 'a+'tcx, 'tcx: 'a> { + /// The inference context used. infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, } impl<'a, 'gcx, 'tcx> InferenceCleanupFolder<'a, 'gcx, 'tcx> { + /// Construct a new folder. pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self { InferenceCleanupFolder { infcx: infcx, diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 9eb4072089d23..a52465da9d372 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -3,7 +3,7 @@ //! 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 find non-public items that are named +//! 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 @@ -27,7 +27,7 @@ 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. +/// Set up the necessary data structures and run the analysis passes and call the actual passes. pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefId) -> ChangeSet<'tcx> { @@ -58,7 +58,7 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI // 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 their structure. +/// 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 @@ -239,7 +239,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, output); }, // a non-matching item pair - register the change and abort further - // analysis + // analysis of it _ => { changes.add_change(KindDifference, o_def_id, None); }, diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs index 32cd31295fbd5..f65775bc6eeba 100644 --- a/src/semcheck/typeck.rs +++ b/src/semcheck/typeck.rs @@ -172,7 +172,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { }) } - /// Check for type mismatches for a pair of items. + /// Check for type mismatches in a pair of items. pub fn check_type_error<'b, 'tcx2>(&self, lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, target_def_id: DefId, @@ -212,7 +212,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { } } - /// Check for trait bound mismatches for a pair of items. + /// Check for trait bound mismatches in a pair of items. pub fn check_bounds_error<'b, 'tcx2>(&self, lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, orig_param_env: ParamEnv<'tcx>, From 818f4c9ae995f171f18aa572ee08393d790ae0c7 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 24 Aug 2017 13:17:46 +0200 Subject: [PATCH 250/553] Implemented type parameter variance comparison. --- src/semcheck/changes.rs | 21 ++++++++++++++++++ src/semcheck/traverse.rs | 38 +++++++++++++++++++++++++++++++- tests/cases/infer_regress/stdout | 1 + 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index ea05683a45151..ec067bcab0df5 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -203,6 +203,15 @@ pub enum ChangeType<'tcx> { 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. @@ -271,6 +280,8 @@ impl<'tcx> ChangeType<'tcx> { ItemMadePrivate | KindDifference | StaticMutabilityChanged { now_mut: false } | + VarianceTightened | + VarianceChanged { .. } | RegionParameterAdded | RegionParameterRemoved | TypeParameterAdded { defaulted: false } | @@ -298,6 +309,7 @@ impl<'tcx> ChangeType<'tcx> { AssociatedItemAdded | ItemMadePublic => TechnicallyBreaking, StaticMutabilityChanged { now_mut: true } | + VarianceLoosened | TypeParameterAdded { defaulted: true } | FnConstChanged { now_const: true } => NonBreaking, } @@ -312,6 +324,12 @@ impl<'a> fmt::Display for ChangeType<'a> { 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", @@ -438,6 +456,9 @@ impl<'tcx> Change<'tcx> { TraitItemAdded { .. } | TraitItemRemoved { .. } | ItemMadePublic | + VarianceLoosened | + VarianceTightened | + VarianceChanged { .. } | TypeParameterAdded { .. } | TraitUnsafetyChanged { .. } | FnConstChanged { now_const: true } | diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index a52465da9d372..ac149b365616e 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -16,6 +16,7 @@ use rustc::ty::subst::{Subst, Substs}; use rustc::ty::Visibility; use rustc::ty::Visibility::Public; +use semcheck::changes::ChangeType; use semcheck::changes::ChangeType::*; use semcheck::changes::ChangeSet; use semcheck::mapping::{IdMapping, NameMapping}; @@ -548,16 +549,43 @@ fn diff_generics(changes: &mut ChangeSet, is_fn: bool, old: DefId, new: DefId) { + use rustc::ty::Variance; + use rustc::ty::Variance::*; use std::cmp::max; + fn diff_variance<'tcx>(old_var: Variance, new_var: Variance) -> Option> { + match (old_var, new_var) { + (Covariant, Covariant) | + (Invariant, Invariant) | + (Contravariant, Contravariant) | + (Bivariant, Bivariant) => None, + (Invariant, _) | (_, Bivariant) => Some(VarianceLoosened), + (_, Invariant) | (Bivariant, _) => Some(VarianceTightened), + (Covariant, Contravariant) => Some(VarianceChanged { now_contravariant: true }), + (Contravariant, Covariant) => Some(VarianceChanged { now_contravariant: false }), + } + } + let mut found = Vec::new(); let old_gen = tcx.generics_of(old); let new_gen = tcx.generics_of(new); - for i in 0..max(old_gen.regions.len(), new_gen.regions.len()) { + let old_var = tcx.variances_of(old); + let new_var = tcx.variances_of(new); + + let old_regions_len = old_gen.regions.len(); + let new_regions_len = new_gen.regions.len(); + + for i in 0..max(old_regions_len, new_regions_len) { match (old_gen.regions.get(i), new_gen.regions.get(i)) { (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)) { + diff_variance(*old_var, *new_var) + .map(|t| found.push(t)); + } + id_mapping.add_internal_item(old_region.def_id, new_region.def_id); }, (Some(_), None) => { @@ -573,6 +601,14 @@ fn diff_generics(changes: &mut ChangeSet, for i in 0..max(old_gen.types.len(), new_gen.types.len()) { match (old_gen.types.get(i), new_gen.types.get(i)) { (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(i + old_regions_len), new_var.get(i + new_regions_len)) + { + diff_variance(*old_var, *new_var) + .map(|t| found.push(t)); + } + if old_type.has_default && !new_type.has_default { found.push(TypeParameterRemoved { defaulted: true }); found.push(TypeParameterAdded { defaulted: false }); diff --git a/tests/cases/infer_regress/stdout b/tests/cases/infer_regress/stdout index aa3f57e83e156..b0d9fbf0ef1f5 100644 --- a/tests/cases/infer_regress/stdout +++ b/tests/cases/infer_regress/stdout @@ -5,6 +5,7 @@ error: breaking changes in `abc` 1 | pub fn abc(_: A) { } | ^^^^^^^^^^^^^^^^^^^^^^^ | + = note: variance loosened (non-breaking) = warning: type error: expected type parameter, found () (breaking) error: breaking changes in `Abc` From c05cb942cbdc8d61d33b33abdce49ca82db0193d Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 24 Aug 2017 13:21:00 +0200 Subject: [PATCH 251/553] Updated README. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1cbacce88e8e4..649562b5069fd 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,7 @@ correctly: * 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 From 155a88e7c88efd02469396323c8c537579e2241b Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 25 Aug 2017 00:14:44 +0200 Subject: [PATCH 252/553] Moved docs a bit. --- README.md | 2 +- doc/{GSoC.md => gsoc.md} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename doc/{GSoC.md => gsoc.md} (100%) diff --git a/README.md b/README.md index 649562b5069fd..e20e783d4481c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ analyzes the current crate's source code for changes compared to the most recent on `crates.io`. Details on the work done during GSoC 2017 can be found -[here](https://github.com/ibabushkin/rust-semverver/blob/master/doc/GSoC.md). +[here](https://github.com/ibabushkin/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 diff --git a/doc/GSoC.md b/doc/gsoc.md similarity index 100% rename from doc/GSoC.md rename to doc/gsoc.md From dcffff5161fa4ebb624a0c532a225107bb1589d3 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 29 Aug 2017 19:20:57 +0200 Subject: [PATCH 253/553] Added name to docs. --- doc/gsoc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gsoc.md b/doc/gsoc.md index c5a4fa2259f4f..0f6ae3e59b09c 100644 --- a/doc/gsoc.md +++ b/doc/gsoc.md @@ -1,4 +1,4 @@ -# Notes on work done during GSoC 2017 +# 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 From 54cb2cf9fda50a53d0a2c34036c1a498dea44d31 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 29 Aug 2017 20:06:38 +0200 Subject: [PATCH 254/553] Fixed old tests. --- tests/examples.rs | 2 +- tests/full.rs | 2 +- tests/helper/test.rs | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/examples.rs b/tests/examples.rs index b75bdc7f56c0c..2ac9fde110660 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -81,7 +81,7 @@ macro_rules! test { eprintln!("path: {}", out_file.to_str().unwrap()); success &= Command::new("git") - .args(&["diff", out_file.to_str().unwrap()]) + .args(&["diff", "--exit-code", out_file.to_str().unwrap()]) .env("PAGER", "") .status() .expect("could not run git diff") diff --git a/tests/full.rs b/tests/full.rs index df529685e181a..808c55f17d407 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -77,7 +77,7 @@ macro_rules! full_test { eprintln!("path: {}", out_file); success &= Command::new("git") - .args(&["diff", out_file]) + .args(&["diff", "--exit-code", out_file]) .env("PAGER", "") .status() .expect("could not run git diff") diff --git a/tests/helper/test.rs b/tests/helper/test.rs index 88c8d225801c7..c7485a8a40348 100644 --- a/tests/helper/test.rs +++ b/tests/helper/test.rs @@ -1,2 +1,4 @@ +#[allow(unused_extern_crates)] extern crate old; +#[allow(unused_extern_crates)] extern crate new; From 4835764592414d881af35b66049ab493a8037735 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 31 Aug 2017 23:51:41 +0200 Subject: [PATCH 255/553] Fixed issue #28. Trait objects weren't translated correctly in some edge cases. Combined with an ordering bug in the filtering logic, this led to crashes when sentinel values were passed to the analysis mechanisms. --- src/semcheck/translate.rs | 33 ++++++++++++++++++++++----------- tests/examples.rs | 1 + 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 4426bfcc9a61f..b5ef029541997 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -174,21 +174,31 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { TyDynamic(preds, region) => { // hacky error catching mechanism use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; - let mut success = true; + use std::cell::Cell; + + let success = Cell::new(true); let err_pred = AutoTrait(DefId::local(CRATE_DEF_INDEX)); - let target_preds = self.tcx.mk_existential_predicates(preds.iter().map(|p| { + let res: Vec<_> = preds.iter().map(|p| { + debug!("pred: {:?}", p); match *p.skip_binder() { - Trait(ExistentialTraitRef { def_id: did, substs }) => { + Trait(existential_trait_ref) => { + let trait_ref = Binder(existential_trait_ref) + .with_self_ty(self.tcx, self.tcx.types.err); + let did = trait_ref.skip_binder().def_id; + let substs = trait_ref.skip_binder().substs; + if let Some((target_def_id, target_substs)) = self.translate_orig_substs(index_map, did, substs) { - Trait(ExistentialTraitRef { + let target_trait_ref = TraitRef { def_id: target_def_id, - substs: target_substs - }) - } else { - success = false; + substs: target_substs, + }; + Trait(ExistentialTraitRef::erase_self_ty(self.tcx, + target_trait_ref)) + } else { + success.set(false); err_pred } }, @@ -202,7 +212,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { ty: ty, }) } else { - success = false; + success.set(false); err_pred } }, @@ -210,9 +220,10 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { AutoTrait(self.translate_orig(did)) }, } - })); + }).collect(); - if success { + if success.get() { + let target_preds = self.tcx.mk_existential_predicates(res.iter()); self.tcx.mk_dynamic(Binder(target_preds), region) } else { ty diff --git a/tests/examples.rs b/tests/examples.rs index 2ac9fde110660..1705fc1341fc4 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -121,4 +121,5 @@ test!(structs); test!(swap); test!(traits); test!(trait_impls); +test!(trait_objects); test!(ty_alias); From 8617604550dcca4794b19977f739c0fe76abaa3f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 1 Sep 2017 00:26:45 +0200 Subject: [PATCH 256/553] Cleanup. Generalized last bugfix to projections. Removed unused imports and fixed projections in a similar, but much more ugly manner. This will have to be cleanly solved in rustc. --- src/bin/rust_semverver.rs | 2 -- src/lib.rs | 2 -- src/semcheck/translate.rs | 11 +++++++++-- tests/cases/trait_objects/new.rs | 13 +++++++++++++ tests/cases/trait_objects/old.rs | 13 +++++++++++++ tests/cases/trait_objects/stdout | 1 + 6 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 tests/cases/trait_objects/new.rs create mode 100644 tests/cases/trait_objects/old.rs create mode 100644 tests/cases/trait_objects/stdout diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index a00e3f1a59225..19417e42d9aa0 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -6,8 +6,6 @@ extern crate getopts; extern crate rustc; extern crate rustc_driver; extern crate rustc_errors; -extern crate rustc_metadata; -extern crate semver; extern crate semverver; extern crate syntax; diff --git a/src/lib.rs b/src/lib.rs index 6e4f63f5a7d57..dc82cad64bb9e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,8 +10,6 @@ extern crate log; extern crate quickcheck; extern crate rustc; -extern crate rustc_data_structures; -extern crate rustc_errors; extern crate semver; extern crate syntax; extern crate syntax_pos; diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index b5ef029541997..f2e573a9eaaea 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -202,13 +202,20 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { err_pred } }, - Projection(ExistentialProjection { item_def_id, substs, ty }) => { + Projection(existential_projection) => { + let projection_pred = Binder(existential_projection) + .with_self_ty(self.tcx, self.tcx.types.err); + let item_def_id = + projection_pred.skip_binder().projection_ty.item_def_id; + let substs = projection_pred.skip_binder().projection_ty.substs; + 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, - substs: target_substs, + // TODO: should be it's own method in rustc + substs: self.tcx.intern_substs(&target_substs[1..]), ty: ty, }) } else { diff --git a/tests/cases/trait_objects/new.rs b/tests/cases/trait_objects/new.rs new file mode 100644 index 0000000000000..2491fd9c96194 --- /dev/null +++ b/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(_: &Abc) { } + +pub trait A { } + +pub type Something = A<()>; diff --git a/tests/cases/trait_objects/old.rs b/tests/cases/trait_objects/old.rs new file mode 100644 index 0000000000000..2491fd9c96194 --- /dev/null +++ b/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(_: &Abc) { } + +pub trait A { } + +pub type Something = A<()>; diff --git a/tests/cases/trait_objects/stdout b/tests/cases/trait_objects/stdout new file mode 100644 index 0000000000000..f8c2af4c949b7 --- /dev/null +++ b/tests/cases/trait_objects/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (patch) -> 1.0.1 From 4b4ce95adae5f653f7c1f3dd18a4a5502f8b34ee Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 1 Sep 2017 19:26:20 +0200 Subject: [PATCH 257/553] Avoid some warnings in production runs. --- src/bin/cargo_semver.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index b749f8a5fa1bb..c30a12d89fe48 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -209,7 +209,10 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { .map_err(|e| format!("could not spawn rustc: {}", e))?; if let Some(ref mut stdin) = child.stdin { - stdin.write_fmt(format_args!("extern crate new; extern crate old;"))?; + stdin.write_fmt(format_args!("#[allow(unused_extern_crate)] \ + extern crate new; \ + #[allow(unused_extern_crate)] \ + extern crate old;"))?; } else { return Err("could not pipe to rustc (wtf?)".into()); } From b1015639bb088cf9321e00530ca3d67e92d2bac9 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Thu, 7 Sep 2017 16:40:35 +0200 Subject: [PATCH 258/553] Readme: Condense install section, default usage --- README.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e20e783d4481c..2812ac886bb27 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # rust-semverver + [![Build Status](https://travis-ci.org/ibabushkin/rust-semverver.svg?branch=master)](https://travis-ci.org/ibabushkin/rust-semverver) This repository is hosting a proof-of-concept implementation of an automatic tool checking @@ -11,6 +12,7 @@ Details on the work done during GSoC 2017 can be found [here](https://github.com/ibabushkin/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 @@ -20,8 +22,22 @@ More information on the inner workings of the tool can be found [here](https://github.com/ibabushkin/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, provided you have a recent Rust nightly installed: +repository and compiled from source. + +If you are already using Rust nightly and have successfully installed tools like +`cargo add` and `cargo clippy`, just do: + +```sh +$ cargo install --git https://github.com/ibabushkin/rust-semverver +``` + +
+ + + Manual installation and more details + ```sh # using rustup is recommended @@ -44,7 +60,14 @@ PATH=/path/to/repo/target/debug:$PATH cargo semver If you have built using `cargo build --release` instead, change the path to point to the `release` subdirectory of the `target` directory. +
+ ## Usage + +By default, running `cargo semver` in directory with a Cargo project will try to compare +the local version the one last published on crates.io, and display warning or errors for +all breaking changes found. + Invoking `cargo semver -h` gives you the latest help message, which outlines how to use the cargo plugin: @@ -70,6 +93,7 @@ This means that you can compare any two crates' specified versions, as long as t available on crates.io or present on your filesystem. ## 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 From c311a8502db547d0411ea572001f90031518c1e0 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 8 Sep 2017 01:06:56 +0200 Subject: [PATCH 259/553] Fixed build. --- src/semcheck/typeck.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs index f65775bc6eeba..9a68fd0566a95 100644 --- a/src/semcheck/typeck.rs +++ b/src/semcheck/typeck.rs @@ -181,7 +181,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { target: Ty<'tcx>) -> Option> { use rustc::infer::InferOk; use rustc::middle::free_region::FreeRegionMap; - use rustc::middle::region::RegionMaps; + use rustc::middle::region::ScopeTree; use rustc::ty::Lift; let error = @@ -191,12 +191,12 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { .map(|InferOk { obligations: o, .. }| { assert_eq!(o, vec![]); }); if let Err(err) = error { - let region_maps = RegionMaps::new(); + let scope_tree = ScopeTree::default(); let mut free_regions = FreeRegionMap::new(); free_regions.relate_free_regions_from_predicates(target_param_env.caller_bounds); self.infcx.resolve_regions_and_report_errors(target_def_id, - ®ion_maps, + &scope_tree, &free_regions); let err = From 8f1998a2a7bafe4f0e81fd5b5766f68a16bd818d Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 8 Sep 2017 01:40:49 +0200 Subject: [PATCH 260/553] Fixed wording in README. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2812ac886bb27..f8897964c5e4d 100644 --- a/README.md +++ b/README.md @@ -65,8 +65,8 @@ If you have built using `cargo build --release` instead, change the path to poin ## 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 warning or errors for -all breaking changes found. +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: From 72854c541f8cfad9ddf419d3f472ea8c8d3f9dc4 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 8 Sep 2017 11:16:08 +0200 Subject: [PATCH 261/553] Fixed a typo. --- src/bin/cargo_semver.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index c30a12d89fe48..a9037de8fe24b 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -209,9 +209,9 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { .map_err(|e| format!("could not spawn rustc: {}", e))?; if let Some(ref mut stdin) = child.stdin { - stdin.write_fmt(format_args!("#[allow(unused_extern_crate)] \ + stdin.write_fmt(format_args!("#[allow(unused_extern_crates)] \ extern crate new; \ - #[allow(unused_extern_crate)] \ + #[allow(unused_extern_crates)] \ extern crate old;"))?; } else { return Err("could not pipe to rustc (wtf?)".into()); From e5534bd3ddf8b14f28746b5459b6f5fa6f31f366 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 21 Sep 2017 20:07:48 +0200 Subject: [PATCH 262/553] Fixed build on newest nightly. --- src/bin/rust_semverver.rs | 10 ++++--- src/semcheck/mapping.rs | 10 +++++++ src/semcheck/translate.rs | 8 ++++++ src/semcheck/traverse.rs | 59 ++++++++++++++++++++------------------- tests/cases/macros/stdout | 8 +++--- 5 files changed, 59 insertions(+), 36 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 19417e42d9aa0..5bbf135a23945 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -12,6 +12,7 @@ extern crate syntax; use semverver::semcheck::run_analysis; use rustc::hir::def_id::*; +use rustc::middle::cstore::CrateStore; use rustc::session::{config, Session}; use rustc::session::config::{Input, ErrorOutputType}; @@ -28,13 +29,13 @@ use syntax::ast; /// find their root modules and then proceed to walk their module trees. fn callback(state: &driver::CompileState, version: &str) { let tcx = state.tcx.unwrap(); - let cstore = &tcx.sess.cstore; + // let cstore = &tcx.sess.cstore; - let cnums = cstore + let cnums = tcx .crates() .iter() .fold((None, None), |(o, n), crate_num| { - let name = cstore.crate_name(*crate_num); + let name = tcx.crate_name(*crate_num); if name == "old" { (Some(*crate_num), n) } else if name == "new" { @@ -108,12 +109,13 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { fn late_callback(&mut self, matches: &getopts::Matches, sess: &Session, + cstore: &CrateStore, input: &Input, odir: &Option, ofile: &Option) -> Compilation { self.default - .late_callback(matches, sess, input, odir, ofile) + .late_callback(matches, sess, cstore, input, odir, ofile) } fn build_controller(&mut self, diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index a7a62e20c1092..71589acd75d0e 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -251,10 +251,20 @@ impl IdMapping { 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 + } } /// A mapping from names to pairs of old and new exports. diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index f2e573a9eaaea..ac708819e3dfd 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -391,6 +391,14 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { } })) }, + Predicate::ConstEvaluatable(orig_did, orig_substs) => { + if let Some((target_def_id, target_substs)) = + self.translate_orig_substs(index_map, orig_did, orig_substs) { + Predicate::ConstEvaluatable(target_def_id, target_substs) + } else { + return None; + } + }, }) } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index ac149b365616e..cbbe3823f1c48 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -75,15 +75,14 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, use std::rc::Rc; // Get the visibility of the inner item, given the outer item's visibility. - fn get_vis(cstore: &Rc, outer_vis: Visibility, def_id: DefId) -> Visibility { + fn get_vis(tcx: TyCtxt, outer_vis: Visibility, def_id: DefId) -> Visibility { if outer_vis == Public { - cstore.visibility(def_id) + tcx.visibility(def_id) } else { outer_vis } } - let cstore = &tcx.sess.cstore; let mut visited = HashSet::new(); let mut children = NameMapping::default(); let mut mod_queue = VecDeque::new(); @@ -98,8 +97,8 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, // 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(cstore.item_children(old_def_id, tcx.sess), - cstore.item_children(new_def_id, tcx.sess)); + 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 { @@ -107,8 +106,8 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, (Some(o), Some(n)) => { if let (Mod(o_def_id), Mod(n_def_id)) = (o.def, n.def) { if visited.insert((o_def_id, n_def_id)) { - let o_vis = get_vis(cstore, old_vis, o_def_id); - let n_vis = get_vis(cstore, new_vis, n_def_id); + let o_vis = get_vis(tcx, old_vis , o_def_id); + let n_vis = get_vis(tcx, new_vis , n_def_id); if o_vis != n_vis { changes.new_change(o_def_id, @@ -137,8 +136,8 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, let o_def_id = o.def.def_id(); let n_def_id = n.def.def_id(); - let o_vis = get_vis(cstore, old_vis, o_def_id); - let n_vis = get_vis(cstore, new_vis, n_def_id); + let o_vis = get_vis(tcx, old_vis, o_def_id); + let n_vis = get_vis(tcx, new_vis, n_def_id); let output = o_vis == Public || n_vis == Public; changes.new_change(o_def_id, @@ -254,7 +253,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, continue; } - if get_vis(cstore, old_vis, o.def.def_id()) == Public { + if get_vis(tcx, old_vis , o.def.def_id()) == Public { // delay the handling of removals until the id mapping is complete removals.push(o); } @@ -266,7 +265,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, continue; } - if get_vis(cstore, new_vis, n.def.def_id()) == Public { + if get_vis(tcx, new_vis , n.def.def_id()) == Public { // delay the handling of additions until the id mapping is complete additions.push(n); } @@ -856,29 +855,33 @@ fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let to_new = TranslationContext::target_new(tcx, id_mapping, false); let to_old = TranslationContext::target_old(tcx, id_mapping, false); - let all_impls = tcx.sess.cstore.implementations_of_trait(None); + 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; - for orig_impl_def_id in &all_impls { - let orig_trait_def_id = tcx.impl_trait_ref(*orig_impl_def_id).unwrap().def_id; + if !to_new.can_translate(old_trait_def_id) { + continue; + } - let (forward_trans, err_type) = - if id_mapping.in_old_crate(*orig_impl_def_id) { - (&to_new, TraitImplTightened) - } else if id_mapping.in_new_crate(*orig_impl_def_id) { - (&to_old, TraitImplLoosened) - } else { - continue - }; + if !match_trait_impl(tcx, &to_new, *old_impl_def_id) { + changes.new_change_impl(*old_impl_def_id, + tcx.item_path_str(*old_impl_def_id), + tcx.def_span(*old_impl_def_id)); + changes.add_change(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 !forward_trans.can_translate(orig_trait_def_id) { + if !to_old.can_translate(new_trait_def_id) { continue; } - if !match_trait_impl(tcx, forward_trans, *orig_impl_def_id) { - changes.new_change_impl(*orig_impl_def_id, - tcx.item_path_str(*orig_impl_def_id), - tcx.def_span(*orig_impl_def_id)); - changes.add_change(err_type, *orig_impl_def_id, None); + if !match_trait_impl(tcx, &to_old, *new_impl_def_id) { + changes.new_change_impl(*new_impl_def_id, + tcx.item_path_str(*new_impl_def_id), + tcx.def_span(*new_impl_def_id)); + changes.add_change(TraitImplLoosened, *new_impl_def_id, None); } } } diff --git a/tests/cases/macros/stdout b/tests/cases/macros/stdout index 6bfc440e7d334..3dd74b0d20d23 100644 --- a/tests/cases/macros/stdout +++ b/tests/cases/macros/stdout @@ -1,9 +1,9 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: path changes to `qux1` - --> $REPO_PATH/tests/cases/macros/old.rs:15:5 + --> $REPO_PATH/tests/cases/macros/old.rs:15:1 | 15 | pub macro qux1() { Item } - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: removed definition (breaking) @@ -20,10 +20,10 @@ error: path changes to `qux2` = warning: removed definition (breaking) warning: path changes to `quux1` - --> $REPO_PATH/tests/cases/macros/new.rs:15:5 + --> $REPO_PATH/tests/cases/macros/new.rs:15:1 | 15 | pub macro quux1() { Item } - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: added definition (technically breaking) From 2f170c1e37600f89696296e8afa324cd5f6ac5b1 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 21 Sep 2017 20:13:07 +0200 Subject: [PATCH 263/553] Cleaned up warnings. --- src/semcheck/changes.rs | 6 +----- src/semcheck/traverse.rs | 3 --- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index ec067bcab0df5..fd72f32aa4e8f 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -713,11 +713,7 @@ pub mod tests { fn arbitrary(g: &mut G) -> Span_ { let a: u32 = Arbitrary::arbitrary(g); let b: u32 = Arbitrary::arbitrary(g); - Span_(Span { - lo: BytePos(min(a, b)), - hi: BytePos(max(a, b)), - ctxt: SyntaxContext::empty(), - }) + Span_(Span::new(BytePos(min(a, b)), BytePos(max(a, b)), SyntaxContext::empty())) } } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index cbbe3823f1c48..80c74825b91a0 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -69,11 +69,8 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefId) { - use rustc::middle::cstore::CrateStore; use rustc::hir::def::Def::*; - use std::rc::Rc; - // Get the visibility of the inner item, given the outer item's visibility. fn get_vis(tcx: TyCtxt, outer_vis: Visibility, def_id: DefId) -> Visibility { if outer_vis == Public { From d9ca25a77310bc6fe2efb3c676eb9dae82a2de74 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 22 Sep 2017 21:46:17 +0200 Subject: [PATCH 264/553] Made full tests more robust. --- src/semcheck/traverse.rs | 2 +- tests/full.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 80c74825b91a0..b580117b139bc 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -963,7 +963,7 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, (tcx.mk_fn_ptr(orig_sig), tcx.mk_fn_ptr(target_sig)) }, _ => { - unreachable!(); + unreachable!() }, }; diff --git a/tests/full.rs b/tests/full.rs index 808c55f17d407..5192eddf854b6 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -35,7 +35,7 @@ macro_rules! full_test { if let Some(path) = env::var_os("PATH") { let mut paths = env::split_paths(&path).collect::>(); let current_dir = env::current_dir().expect("could not determine current dir"); - paths.push(current_dir.join("target/debug")); + paths.insert(0, current_dir.join("target/debug")); let new_path = env::join_paths(paths).unwrap(); env::set_var("PATH", &new_path); } else { @@ -75,7 +75,6 @@ macro_rules! full_test { assert!(success, "awk"); - eprintln!("path: {}", out_file); success &= Command::new("git") .args(&["diff", "--exit-code", out_file]) .env("PAGER", "") From a39731b636b648e93fa032d1d9ceeebc662bad53 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 3 Oct 2017 22:28:45 +0200 Subject: [PATCH 265/553] Added more debug logging. --- src/bin/rust_semverver.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 5bbf135a23945..377151adbc1c4 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -3,6 +3,8 @@ extern crate env_logger; extern crate getopts; +#[macro_use] +extern crate log; extern crate rustc; extern crate rustc_driver; extern crate rustc_errors; @@ -90,6 +92,7 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { descriptions: &rustc_errors::registry::Registry, output: ErrorOutputType) -> Compilation { + debug!("running rust-semverver early_callback"); self.default .early_callback(matches, sopts, cfg, descriptions, output) } @@ -102,6 +105,7 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { ofile: &Option, descriptions: &rustc_errors::registry::Registry) -> Option<(Input, Option)> { + debug!("running rust-semverver no_input"); self.default .no_input(matches, sopts, cfg, odir, ofile, descriptions) } @@ -114,6 +118,7 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { odir: &Option, ofile: &Option) -> Compilation { + debug!("running rust-semverver late_callback"); self.default .late_callback(matches, sess, cstore, input, odir, ofile) } @@ -128,6 +133,7 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { let version = self.version.clone(); controller.after_analysis.callback = box move |state| { + debug!("running rust-semverver after_analysis callback"); callback(state, &version); old_callback(state); }; @@ -146,6 +152,8 @@ fn main() { eprintln!("ERROR: could not initialize logger"); } + debug!("running rust-semverver compiler driver"); + let home = option_env!("RUSTUP_HOME"); let toolchain = option_env!("RUSTUP_TOOLCHAIN"); let sys_root = if let (Some(home), Some(toolchain)) = (home, toolchain) { From 3fc38eece3672c4c34ba2ac38117815b5e820285 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 3 Oct 2017 22:28:59 +0200 Subject: [PATCH 266/553] Fixed tests to work with new nightlies. --- src/semcheck/changes.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index fd72f32aa4e8f..e6ae901ffece2 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -701,11 +701,11 @@ pub mod tests { /// A wrapper for `Span` that can be randomly generated. #[derive(Clone, Debug)] - pub struct Span_(Span); + pub struct Span_(u32, u32); impl Span_ { pub fn inner(self) -> Span { - self.0 + Span::new(BytePos(self.0), BytePos(self.1), SyntaxContext::empty()) } } @@ -713,7 +713,7 @@ pub mod tests { fn arbitrary(g: &mut G) -> Span_ { let a: u32 = Arbitrary::arbitrary(g); let b: u32 = Arbitrary::arbitrary(g); - Span_(Span::new(BytePos(min(a, b)), BytePos(max(a, b)), SyntaxContext::empty())) + Span_(min(a, b), max(a, b)) } } From 32cb8fa4e8cad95face2bbaa1f4e0677a74dc91c Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 4 Oct 2017 20:17:38 +0200 Subject: [PATCH 267/553] Added more debugging output. --- src/bin/cargo_semver.rs | 3 +++ src/bin/rust_semverver.rs | 3 ++- src/semcheck/mismatch.rs | 5 +++++ src/semcheck/traverse.rs | 5 +++++ tests/full.rs | 3 +-- 5 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index a9037de8fe24b..9dbee87d8e3e3 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -135,6 +135,7 @@ impl<'a> WorkInfo<'a> { /// and/or defaults, and dispatch the actual analysis. // TODO: possibly reduce the complexity by finding where some info can be taken from directly fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { + debug!("running cargo-semver"); fn parse_arg(opt: &str) -> CargoResult { let mut split = opt.split('-'); let name = if let Some(n) = split.next() { @@ -196,6 +197,8 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { return Ok(()); } + debug!("running rust-semverver on compiled crates"); + let mut child = Command::new("rust-semverver") .arg("--crate-type=lib") .args(&["--extern", &*format!("old={}", stable_rlib.display())]) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 377151adbc1c4..7bccf77cc3619 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -31,7 +31,6 @@ use syntax::ast; /// find their root modules and then proceed to walk their module trees. fn callback(state: &driver::CompileState, version: &str) { let tcx = state.tcx.unwrap(); - // let cstore = &tcx.sess.cstore; let cnums = tcx .crates() @@ -61,6 +60,7 @@ fn callback(state: &driver::CompileState, version: &str) { return; }; + debug!("running semver analysis"); let changes = run_analysis(tcx, old_def_id, new_def_id); changes.output(tcx.sess, version); @@ -135,6 +135,7 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { controller.after_analysis.callback = box move |state| { debug!("running rust-semverver after_analysis callback"); callback(state, &version); + debug!("running other after_analysis callback"); old_callback(state); }; controller.after_analysis.stop = Compilation::Stop; diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 3f74c20c35524..52882a20ac785 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -45,6 +45,8 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> MismatchRelation<'a, 'gcx, 'tcx> { use rustc::hir::def::Def::*; while let Some((old_def_id, new_def_id)) = self.item_queue.pop_front() { + debug!("processing mismatch item pair, remaining: {}", self.item_queue.len()); + debug!("old: {:?}, new: {:?}", old_def_id, new_def_id); match self.tcx.describe_def(old_def_id) { Some(Trait(_)) | Some(Macro(_, _)) => continue, _ => (), @@ -52,6 +54,7 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> MismatchRelation<'a, 'gcx, 'tcx> { 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); } } @@ -90,12 +93,14 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, } fn relate>(&mut self, a: &T, b: &T) -> RelateResult<'tcx, T> { + debug!("relate: mismatch relation: a: {:?}, b: {:?}", a, b); Relate::relate(self, a, b) } fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { use rustc::ty::TypeVariants::*; + debug!("tys: mismatch relation: a: {:?}, b: {:?}", a, b); let matching = match (&a.sty, &b.sty) { (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs)) => { if self.check_substs(a_substs, b_substs) { diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index b580117b139bc..84c3cb380df07 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -36,20 +36,25 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI 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); diff --git a/tests/full.rs b/tests/full.rs index 5192eddf854b6..0810d17ee7f64 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -27,8 +27,7 @@ macro_rules! full_test { # sanitize paths gsub(/-->.*"#, $crate_name, r#"/, "--> "#, $crate_name, r#"", $0); print; -} - "#, $crate_name, $crate_name); +}"#, $crate_name, $crate_name); let out_file = Path::new("tests/full_cases") .join(concat!($crate_name, "-", $old_version, "-", $new_version)); From c7a06876ab782fa51f505ceffdd3795d7688327d Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 4 Oct 2017 20:18:58 +0200 Subject: [PATCH 268/553] Fixed #30. A stack overflow was caused by circular references in analyzed item types, since mismatch computation didn't keep track of item pairs *currently being matched*. This is now fixed using two sets of old and new types. --- src/semcheck/mismatch.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 52882a20ac785..1023ed9ca9fb3 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -13,7 +13,7 @@ use rustc::ty::subst::Substs; use semcheck::mapping::IdMapping; -use std::collections::{HashMap, VecDeque}; +use std::collections::{HashMap, HashSet, VecDeque}; /// A relation searching for items appearing at the same spot in a type. /// @@ -27,6 +27,10 @@ pub struct MismatchRelation<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { item_queue: VecDeque<(DefId, DefId)>, /// The id mapping to use. id_mapping: &'a mut IdMapping, + /// Type cache holding all old types currently being processed to avoid loops. + current_old_types: HashSet>, + /// Type cache holding all new types currently being processed to avoid loops. + current_new_types: HashSet>, } impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> MismatchRelation<'a, 'gcx, 'tcx> { @@ -37,6 +41,8 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> MismatchRelation<'a, 'gcx, 'tcx> { tcx: tcx, item_queue: id_mapping.toplevel_queue(), id_mapping: id_mapping, + current_old_types: Default::default(), + current_new_types: Default::default(), } } @@ -100,6 +106,13 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { use rustc::ty::TypeVariants::*; + if self.current_old_types.contains(a) || self.current_new_types.contains(b) { + return Ok(self.tcx.types.err); + } + + self.current_old_types.insert(a); + self.current_new_types.insert(b); + debug!("tys: mismatch relation: a: {:?}, b: {:?}", a, b); let matching = match (&a.sty, &b.sty) { (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs)) => { @@ -193,6 +206,9 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, _ => None, }; + self.current_old_types.remove(a); + self.current_new_types.remove(b); + if let Some((old_def_id, new_def_id)) = matching { if !self.id_mapping.contains_old_id(old_def_id) && self.id_mapping.in_old_crate(old_def_id) { From bb743629ec119e1082ab43d564a1cb074e2d5aed Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 4 Oct 2017 20:27:32 +0200 Subject: [PATCH 269/553] Added libc test case. --- tests/full.rs | 1 + tests/full_cases/libc-0.2.28-0.2.31 | 867 ++++++++++++++++++++++++++++ 2 files changed, 868 insertions(+) create mode 100644 tests/full_cases/libc-0.2.28-0.2.31 diff --git a/tests/full.rs b/tests/full.rs index 0810d17ee7f64..4830aafdf5ea8 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -87,6 +87,7 @@ macro_rules! full_test { } full_test!(log, "log", "0.3.4", "0.3.8"); +full_test!(libc, "libc", "0.2.28", "0.2.31"); // 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/tests/full_cases/libc-0.2.28-0.2.31 b/tests/full_cases/libc-0.2.28-0.2.31 new file mode 100644 index 0000000000000..95b5ee9bfff83 --- /dev/null +++ b/tests/full_cases/libc-0.2.28-0.2.31 @@ -0,0 +1,867 @@ +version bump: 0.2.28 -> (breaking) -> 1.0.0 +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: 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) + From 970709169015abc3ff22b2ab54a0f73d63aa8a4e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 4 Oct 2017 20:34:06 +0200 Subject: [PATCH 270/553] Add circular reference test case. --- tests/cases/circular/new.rs | 5 +++++ tests/cases/circular/old.rs | 5 +++++ tests/cases/circular/stdout | 1 + tests/examples.rs | 1 + 4 files changed, 12 insertions(+) create mode 100644 tests/cases/circular/new.rs create mode 100644 tests/cases/circular/old.rs create mode 100644 tests/cases/circular/stdout diff --git a/tests/cases/circular/new.rs b/tests/cases/circular/new.rs new file mode 100644 index 0000000000000..1e7ad70739f6c --- /dev/null +++ b/tests/cases/circular/new.rs @@ -0,0 +1,5 @@ +use std::rc::Rc; + +struct Abc { + member: Option>, +} diff --git a/tests/cases/circular/old.rs b/tests/cases/circular/old.rs new file mode 100644 index 0000000000000..1e7ad70739f6c --- /dev/null +++ b/tests/cases/circular/old.rs @@ -0,0 +1,5 @@ +use std::rc::Rc; + +struct Abc { + member: Option>, +} diff --git a/tests/cases/circular/stdout b/tests/cases/circular/stdout new file mode 100644 index 0000000000000..f8c2af4c949b7 --- /dev/null +++ b/tests/cases/circular/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/tests/examples.rs b/tests/examples.rs index 1705fc1341fc4..c10fce1faf84e 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -101,6 +101,7 @@ test!(addition); test!(addition_path); test!(addition_use); test!(bounds); +test!(circular); test!(consts); test!(enums); test!(func); From 4cd76f139dc622184b051f756c7b266cec99ecf8 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 5 Oct 2017 12:43:55 +0200 Subject: [PATCH 271/553] Added a test case for function local items. --- tests/cases/func_local_items/new.rs | 6 ++++++ tests/cases/func_local_items/old.rs | 6 ++++++ tests/cases/func_local_items/stdout | 1 + tests/examples.rs | 1 + 4 files changed, 14 insertions(+) create mode 100644 tests/cases/func_local_items/new.rs create mode 100644 tests/cases/func_local_items/old.rs create mode 100644 tests/cases/func_local_items/stdout diff --git a/tests/cases/func_local_items/new.rs b/tests/cases/func_local_items/new.rs new file mode 100644 index 0000000000000..8f8963a3adc46 --- /dev/null +++ b/tests/cases/func_local_items/new.rs @@ -0,0 +1,6 @@ +pub fn abc() { + #[allow(dead_code)] + struct Something(); + + () +} diff --git a/tests/cases/func_local_items/old.rs b/tests/cases/func_local_items/old.rs new file mode 100644 index 0000000000000..5d42ef3f7a157 --- /dev/null +++ b/tests/cases/func_local_items/old.rs @@ -0,0 +1,6 @@ +pub fn abc() { + #[allow(dead_code)] + struct SomethingElse(); + + () +} diff --git a/tests/cases/func_local_items/stdout b/tests/cases/func_local_items/stdout new file mode 100644 index 0000000000000..f8c2af4c949b7 --- /dev/null +++ b/tests/cases/func_local_items/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/tests/examples.rs b/tests/examples.rs index c10fce1faf84e..3c68199087b81 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -105,6 +105,7 @@ test!(circular); test!(consts); test!(enums); test!(func); +test!(func_local_items); test!(infer); test!(infer_regress); test!(inherent_impls); From cebffbcdeb7e931154f8711bc1f0c62a8b09629a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 5 Oct 2017 13:17:50 +0200 Subject: [PATCH 272/553] Fixed #34. We crawl all trait implementations in the `old` and `new` crates and thus check private implementations inside functions and methods as well. This has now been fixed in the obvious manner. --- src/semcheck/traverse.rs | 19 +++++++++++++++++-- tests/cases/issue_34/new.rs | 11 +++++++++++ tests/cases/issue_34/old.rs | 11 +++++++++++ tests/cases/issue_34/stdout | 1 + tests/examples.rs | 1 + 5 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 tests/cases/issue_34/new.rs create mode 100644 tests/cases/issue_34/old.rs create mode 100644 tests/cases/issue_34/stdout diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 84c3cb380df07..625a9c5a3b00e 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -854,13 +854,21 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>) { + use rustc::hir::def::Def; 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) { + let old_impl_parent_def = + tcx.parent_def_id(*old_impl_def_id).and_then(|did| tcx.describe_def(did)); + let old_impl_parent_is_fn = match old_impl_parent_def { + Some(Def::Fn(_)) | Some(Def::Method(_)) => true, + _ => false, + }; + + if !to_new.can_translate(old_trait_def_id) || old_impl_parent_is_fn { continue; } @@ -875,7 +883,14 @@ fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, 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) { + let new_impl_parent_def = + tcx.parent_def_id(*new_impl_def_id).and_then(|did| tcx.describe_def(did)); + let new_impl_parent_is_fn = match new_impl_parent_def { + Some(Def::Fn(_)) | Some(Def::Method(_)) => true, + _ => false, + }; + + if !to_old.can_translate(new_trait_def_id) || new_impl_parent_is_fn { continue; } diff --git a/tests/cases/issue_34/new.rs b/tests/cases/issue_34/new.rs new file mode 100644 index 0000000000000..33434b195e990 --- /dev/null +++ b/tests/cases/issue_34/new.rs @@ -0,0 +1,11 @@ +use std::marker::PhantomData; + +pub fn missing_field<'de, V, E>() -> Result { + #[allow(dead_code)] + struct MissingFieldDeserializer(PhantomData); + + impl Deserializer for MissingFieldDeserializer {} + unimplemented!() +} + +pub trait Deserializer {} diff --git a/tests/cases/issue_34/old.rs b/tests/cases/issue_34/old.rs new file mode 100644 index 0000000000000..33434b195e990 --- /dev/null +++ b/tests/cases/issue_34/old.rs @@ -0,0 +1,11 @@ +use std::marker::PhantomData; + +pub fn missing_field<'de, V, E>() -> Result { + #[allow(dead_code)] + struct MissingFieldDeserializer(PhantomData); + + impl Deserializer for MissingFieldDeserializer {} + unimplemented!() +} + +pub trait Deserializer {} diff --git a/tests/cases/issue_34/stdout b/tests/cases/issue_34/stdout new file mode 100644 index 0000000000000..f8c2af4c949b7 --- /dev/null +++ b/tests/cases/issue_34/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/tests/examples.rs b/tests/examples.rs index 3c68199087b81..e2d7672055c06 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -109,6 +109,7 @@ test!(func_local_items); test!(infer); test!(infer_regress); test!(inherent_impls); +test!(issue_34); test!(kind_change); test!(macros); test!(max_priv); From f0a5bcda13b38868fb67117be6dfd676e068b5c0 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 5 Oct 2017 13:19:34 +0200 Subject: [PATCH 273/553] Silenced warnings for the test case. --- tests/cases/circular/new.rs | 1 + tests/cases/circular/old.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/cases/circular/new.rs b/tests/cases/circular/new.rs index 1e7ad70739f6c..db2735f7f52bb 100644 --- a/tests/cases/circular/new.rs +++ b/tests/cases/circular/new.rs @@ -1,5 +1,6 @@ use std::rc::Rc; +#[allow(dead_code)] struct Abc { member: Option>, } diff --git a/tests/cases/circular/old.rs b/tests/cases/circular/old.rs index 1e7ad70739f6c..db2735f7f52bb 100644 --- a/tests/cases/circular/old.rs +++ b/tests/cases/circular/old.rs @@ -1,5 +1,6 @@ use std::rc::Rc; +#[allow(dead_code)] struct Abc { member: Option>, } From 11add487e07e984909afec1386ca187dbf73499e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 30 Oct 2017 00:07:22 +0100 Subject: [PATCH 274/553] Added handling for . --- src/semcheck/mapping.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 71589acd75d0e..fed4204da489e 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -293,6 +293,7 @@ impl NameMapping { Variant(_) | Trait(_) | TyAlias(_) | + TyForeign(_) | AssociatedTy(_) | PrimTy(_) | TyParam(_) | From 98c5496957aa9a5bf97aad2008fd15c32fc17bcd Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 8 Nov 2017 11:45:30 +0100 Subject: [PATCH 275/553] Fixed tests for newest nightly. --- src/semcheck/changes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index e6ae901ffece2..403dd3b84a1c1 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -735,7 +735,7 @@ pub mod tests { let b: u32 = Arbitrary::arbitrary(g); DefId_(DefId { krate: CrateNum::new(a as usize), - index: DefIndex::new(b as usize), + index: DefIndex::from_u32(b), }) } } From 8c89839fc7d34d3506f4c28b3238fff675b6bc91 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 12 Nov 2017 00:56:16 +0100 Subject: [PATCH 276/553] Updated README to fix #38. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f8897964c5e4d..a606f483c092e 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ If you are already using Rust nightly and have successfully installed tools like `cargo add` and `cargo clippy`, just do: ```sh -$ cargo install --git https://github.com/ibabushkin/rust-semverver +$ cargo +nightly install --git https://github.com/ibabushkin/rust-semverver ```
From be45e6f03b499f6eab399f0dc44777c04148d1b4 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 23 Nov 2017 22:31:35 +0100 Subject: [PATCH 277/553] Fixed build with the newest nightly. --- src/semcheck/translate.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index ac708819e3dfd..9f3a77e804016 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -378,8 +378,11 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { Predicate::WellFormed(ty) => Predicate::WellFormed(self.translate(index_map, &ty)), Predicate::ObjectSafe(did) => Predicate::ObjectSafe(self.translate_orig(did)), - Predicate::ClosureKind(did, kind) => - Predicate::ClosureKind(self.translate_orig(did), kind), + Predicate::ClosureKind(did, substs, kind) => + Predicate::ClosureKind( + self.translate_orig(did), + self.translate(index_map, &substs), + kind), Predicate::Subtype(subtype_predicate) => { Predicate::Subtype(subtype_predicate.map_bound(|s_pred| { let l = self.translate(index_map, &s_pred.a); From 1ce77e24ca82608028b7a9f061709720b57afe3a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 2 Dec 2017 23:37:10 +0100 Subject: [PATCH 278/553] Updated test output. --- tests/cases/addition_path/stdout | 2 +- tests/cases/removal_path/stdout | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cases/addition_path/stdout b/tests/cases/addition_path/stdout index ae6d98c7cf3b4..e8d8730a5baed 100644 --- a/tests/cases/addition_path/stdout +++ b/tests/cases/addition_path/stdout @@ -9,7 +9,7 @@ note: added path (technically breaking) --> $REPO_PATH/tests/cases/addition_path/new.rs:6:13 | 6 | pub use a::*; - | ^^^^^ + | ^^^^ note: added path (technically breaking) --> $REPO_PATH/tests/cases/addition_path/new.rs:10:13 | diff --git a/tests/cases/removal_path/stdout b/tests/cases/removal_path/stdout index 40751182cd1fe..c913b1e79ef86 100644 --- a/tests/cases/removal_path/stdout +++ b/tests/cases/removal_path/stdout @@ -9,7 +9,7 @@ warning: removed path (breaking) --> $REPO_PATH/tests/cases/removal_path/old.rs:6:13 | 6 | pub use a::*; - | ^^^^^ + | ^^^^ warning: removed path (breaking) --> $REPO_PATH/tests/cases/removal_path/old.rs:10:13 | From 9050d1dbb4704c7fc909d218f706926f438e922a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 3 Dec 2017 00:30:09 +0100 Subject: [PATCH 279/553] More test output updates. --- tests/full_cases/libc-0.2.28-0.2.31 | 128 ++++++++++++++-------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/tests/full_cases/libc-0.2.28-0.2.31 b/tests/full_cases/libc-0.2.28-0.2.31 index 95b5ee9bfff83..7f729fb62773a 100644 --- a/tests/full_cases/libc-0.2.28-0.2.31 +++ b/tests/full_cases/libc-0.2.28-0.2.31 @@ -9,7 +9,7 @@ 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 @@ -21,7 +21,7 @@ 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 @@ -33,7 +33,7 @@ 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 @@ -45,7 +45,7 @@ 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 @@ -57,7 +57,7 @@ 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 @@ -69,7 +69,7 @@ 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 @@ -81,7 +81,7 @@ 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 @@ -93,7 +93,7 @@ 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 @@ -105,7 +105,7 @@ 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 @@ -117,7 +117,7 @@ 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 @@ -129,7 +129,7 @@ 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 @@ -141,7 +141,7 @@ 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 @@ -153,7 +153,7 @@ 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 @@ -165,7 +165,7 @@ 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 @@ -177,7 +177,7 @@ 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 @@ -189,7 +189,7 @@ 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 @@ -201,7 +201,7 @@ 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 @@ -213,7 +213,7 @@ 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 @@ -225,7 +225,7 @@ 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 @@ -237,7 +237,7 @@ 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 @@ -249,7 +249,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 @@ -261,7 +261,7 @@ 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 @@ -273,7 +273,7 @@ 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 @@ -285,7 +285,7 @@ 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 @@ -297,7 +297,7 @@ 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 @@ -309,7 +309,7 @@ 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 @@ -321,7 +321,7 @@ 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 @@ -333,7 +333,7 @@ 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 @@ -345,7 +345,7 @@ 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 @@ -357,7 +357,7 @@ 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 @@ -369,7 +369,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/notbsd/linux/mod.rs:691:1 @@ -381,7 +381,7 @@ 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 @@ -393,7 +393,7 @@ 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 @@ -405,7 +405,7 @@ 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 @@ -417,7 +417,7 @@ 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 @@ -429,7 +429,7 @@ 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 @@ -441,7 +441,7 @@ 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 @@ -453,7 +453,7 @@ 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 @@ -465,7 +465,7 @@ 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 @@ -477,7 +477,7 @@ 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 @@ -489,7 +489,7 @@ 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 @@ -501,7 +501,7 @@ 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 @@ -513,7 +513,7 @@ 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 @@ -525,7 +525,7 @@ 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 @@ -537,7 +537,7 @@ 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 @@ -549,7 +549,7 @@ 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 @@ -561,7 +561,7 @@ 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 @@ -573,7 +573,7 @@ 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 @@ -585,7 +585,7 @@ 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 @@ -597,7 +597,7 @@ 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 @@ -609,7 +609,7 @@ 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 @@ -621,7 +621,7 @@ 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 @@ -633,7 +633,7 @@ 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 @@ -645,7 +645,7 @@ 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 @@ -657,7 +657,7 @@ 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 @@ -669,7 +669,7 @@ 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 @@ -681,7 +681,7 @@ 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 @@ -693,7 +693,7 @@ 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 @@ -706,7 +706,7 @@ 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 @@ -721,7 +721,7 @@ 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 @@ -737,7 +737,7 @@ 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 @@ -753,7 +753,7 @@ 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 @@ -768,7 +768,7 @@ note: added path (technically breaking) --> libc-0.2.31/src/lib.rs:284:17 | 284 | pub use unix::*; - | ^^^^^^^^ + | ^^^^^^^ error: path changes to `forkpty` --> libc-0.2.28/src/unix/notbsd/mod.rs:1035:5 @@ -783,7 +783,7 @@ 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 From 7eb3f5296e5d79e71c4b6658ebc321ce817f8304 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 10 Dec 2017 22:28:20 +0100 Subject: [PATCH 280/553] Fixed type error post-processing with new rust nightlies. --- src/semcheck/typeck.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs index 9a68fd0566a95..2b4d268b686ea 100644 --- a/src/semcheck/typeck.rs +++ b/src/semcheck/typeck.rs @@ -180,7 +180,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { orig: Ty<'tcx>, target: Ty<'tcx>) -> Option> { use rustc::infer::InferOk; - use rustc::middle::free_region::FreeRegionMap; + use rustc::infer::outlives::env::OutlivesEnvironment; use rustc::middle::region::ScopeTree; use rustc::ty::Lift; @@ -192,12 +192,22 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { if let Err(err) = error { let scope_tree = ScopeTree::default(); - let mut free_regions = FreeRegionMap::new(); + let mut 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); + // } - free_regions.relate_free_regions_from_predicates(target_param_env.caller_bounds); self.infcx.resolve_regions_and_report_errors(target_def_id, &scope_tree, - &free_regions); + &outlives_env); let err = self.infcx From 931119f2d8aa9759df704ca5069804d307470de2 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 10 Dec 2017 22:32:23 +0100 Subject: [PATCH 281/553] Fixed a clippy warning. --- src/bin/cargo_semver.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 9dbee87d8e3e3..c2eda36c72d4c 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -97,7 +97,7 @@ impl<'a> WorkInfo<'a> { /// Construct a package/workspace pair by fetching the package of a specified name and /// version. - fn remote(config: &'a Config, source: &mut SourceInfo<'a>, info: NameAndVersion) + fn remote(config: &'a Config, source: &mut SourceInfo<'a>, info: &NameAndVersion) -> CargoResult> { // TODO: fall back to locally cached package instance, or better yet, search for it @@ -159,7 +159,7 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { let mut source = SourceInfo::new(config)?; let current = if let Some(opt) = matches.opt_str("C") { - WorkInfo::remote(config, &mut source, parse_arg(&opt)?)? + WorkInfo::remote(config, &mut source, &parse_arg(&opt)?)? } else { WorkInfo::local(config, matches.opt_str("c").map(PathBuf::from))? }; @@ -170,7 +170,7 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { let info = parse_arg(&opt)?; let version = info.version.to_owned(); - let work_info = WorkInfo::remote(config, &mut source, info)?; + let work_info = WorkInfo::remote(config, &mut source, &info)?; (work_info, version) } else if let Some(path) = matches.opt_str("s") { @@ -180,7 +180,7 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { } else { let stable_crate = exact_search(&name)?; let info = NameAndVersion { name: &name, version: &stable_crate.max_version }; - let work_info = WorkInfo::remote(config, &mut source, info)?; + let work_info = WorkInfo::remote(config, &mut source, &info)?; (work_info, stable_crate.max_version.clone()) }; From ec8fd92c6bcdcd681c5e5c74ddebf34b609539e8 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 14 Dec 2017 21:20:46 +0100 Subject: [PATCH 282/553] Fixed visibility issues with imports on new nightlies. --- src/semcheck/traverse.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 625a9c5a3b00e..c6813352c55ef 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -9,7 +9,7 @@ //! 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 rustc::hir::def::{CtorKind, Def}; +use rustc::hir::def::{CtorKind, Def, Export}; use rustc::hir::def_id::DefId; use rustc::ty::{AssociatedItem, Ty, TyCtxt}; use rustc::ty::subst::{Subst, Substs}; @@ -77,9 +77,9 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, use rustc::hir::def::Def::*; // Get the visibility of the inner item, given the outer item's visibility. - fn get_vis(tcx: TyCtxt, outer_vis: Visibility, def_id: DefId) -> Visibility { + fn get_vis(outer_vis: Visibility, def: Export) -> Visibility { if outer_vis == Public { - tcx.visibility(def_id) + def.vis } else { outer_vis } @@ -108,8 +108,8 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, (Some(o), Some(n)) => { if let (Mod(o_def_id), Mod(n_def_id)) = (o.def, n.def) { if visited.insert((o_def_id, n_def_id)) { - let o_vis = get_vis(tcx, old_vis , o_def_id); - let n_vis = get_vis(tcx, new_vis , 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, @@ -138,8 +138,8 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, let o_def_id = o.def.def_id(); let n_def_id = n.def.def_id(); - let o_vis = get_vis(tcx, old_vis, o_def_id); - let n_vis = get_vis(tcx, new_vis, n_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, @@ -255,7 +255,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, continue; } - if get_vis(tcx, old_vis , o.def.def_id()) == Public { + if get_vis(old_vis, o) == Public { // delay the handling of removals until the id mapping is complete removals.push(o); } @@ -267,7 +267,8 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, continue; } - if get_vis(tcx, new_vis , n.def.def_id()) == Public { + 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); } From 2376c78709ebaadac54c76bc379413d89b218da4 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 15 Dec 2017 19:59:08 +0100 Subject: [PATCH 283/553] Fixed build with newest nightly. --- src/semcheck/mapping.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index fed4204da489e..5eb0bdc98c17c 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -294,6 +294,7 @@ impl NameMapping { Trait(_) | TyAlias(_) | TyForeign(_) | + TraitAlias(_) | AssociatedTy(_) | PrimTy(_) | TyParam(_) | From be4203955bd0c962671433f296fd488e124e0233 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 15 Dec 2017 20:27:49 +0100 Subject: [PATCH 284/553] Added a note for trait aliases (when they are implemented). --- src/semcheck/mapping.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 5eb0bdc98c17c..608ed18b030d9 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -294,7 +294,7 @@ impl NameMapping { Trait(_) | TyAlias(_) | TyForeign(_) | - TraitAlias(_) | + TraitAlias(_) | // TODO: will need some handling later on. AssociatedTy(_) | PrimTy(_) | TyParam(_) | From bbcc1005c0720e561631cf9163167abef90a284e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 14 Jan 2018 23:55:26 +0100 Subject: [PATCH 285/553] Fixed build with newest rust nightly. --- src/semcheck/changes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 403dd3b84a1c1..463f5d906ed83 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -735,7 +735,7 @@ pub mod tests { let b: u32 = Arbitrary::arbitrary(g); DefId_(DefId { krate: CrateNum::new(a as usize), - index: DefIndex::from_u32(b), + index: DefIndex::from_raw_u32(b), }) } } From e365ae26d92d136eab11f08016384b31ddcc6ff7 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 23 Jan 2018 13:12:09 +0100 Subject: [PATCH 286/553] Fixed build with the newest nightly. --- src/bin/rust_semverver.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 7bccf77cc3619..f5ba56fbd4d17 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -8,6 +8,7 @@ extern crate log; extern crate rustc; extern crate rustc_driver; extern crate rustc_errors; +extern crate rustc_trans_utils; extern crate semverver; extern crate syntax; @@ -20,6 +21,8 @@ use rustc::session::config::{Input, ErrorOutputType}; use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; +use rustc_trans_utils::trans_crate::TransCrate; + use std::path::PathBuf; use std::process::Command; @@ -111,6 +114,7 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { } fn late_callback(&mut self, + trans_crate: &TransCrate, matches: &getopts::Matches, sess: &Session, cstore: &CrateStore, @@ -120,7 +124,7 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { -> Compilation { debug!("running rust-semverver late_callback"); self.default - .late_callback(matches, sess, cstore, input, odir, ofile) + .late_callback(trans_crate, matches, sess, cstore, input, odir, ofile) } fn build_controller(&mut self, From 28b1dc031d9736407233ac0a65c8280f85cdbbb8 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 26 Jan 2018 20:27:51 +0100 Subject: [PATCH 287/553] Added disambiguation metadata to compilations. This avoids errors from cargo regarding symbol resolution problems which were discussed in #32. This commit should fix the issue. --- src/bin/cargo_semver.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index c2eda36c72d4c..2fa8bd38de1f7 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -19,6 +19,7 @@ use cargo::util::important_paths::find_root_manifest_for_wd; use getopts::{Matches, Options}; +use std::env; use std::io::Write; use std::path::PathBuf; use std::process::{Stdio, Command}; @@ -114,11 +115,21 @@ impl<'a> WorkInfo<'a> { } /// Obtain the paths to the produced rlib and the dependency output directory. - fn rlib_and_dep_output(&self, config: &'a Config, name: &str) + fn rlib_and_dep_output(&self, config: &'a Config, name: &str, current: bool) -> CargoResult<(PathBuf, PathBuf)> { let opts = CompileOptions::default(config, CompileMode::Build); + + if current { + env::set_var("RUSTFLAGS", "-C metadata=new"); + } else { + env::set_var("RUSTFLAGS", "-C metadata=old"); + } + let compilation = compile(&self.workspace, &opts)?; + + env::remove_var("RUSTFLAGS"); + let rlib = compilation.libraries[self.package.package_id()] .iter() .find(|t| t.0.name() == name) @@ -185,8 +196,8 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { (work_info, stable_crate.max_version.clone()) }; - let (current_rlib, current_deps_output) = current.rlib_and_dep_output(config, &name)?; - let (stable_rlib, stable_deps_output) = stable.rlib_and_dep_output(config, &name)?; + let (current_rlib, current_deps_output) = current.rlib_and_dep_output(config, &name, true)?; + let (stable_rlib, stable_deps_output) = stable.rlib_and_dep_output(config, &name, false)?; if matches.opt_present("d") { println!("--extern old={} -L{} --extern new={} -L{}", From 33d41a9ef0771a02907a94f4ac36cadaf8a610b5 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 29 Jan 2018 15:36:13 +0100 Subject: [PATCH 288/553] Updated README after the move to the nursery. --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a606f483c092e..65846efc521a8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # rust-semverver -[![Build Status](https://travis-ci.org/ibabushkin/rust-semverver.svg?branch=master)](https://travis-ci.org/ibabushkin/rust-semverver) +[![Build +Status](https://travis-ci.org/rust-lang-nursery/rust-semverver.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rust-semverver) This repository is hosting a proof-of-concept implementation of an automatic tool checking rust library crates for semantic versioning adherence, developed during the Google Summer @@ -9,7 +10,7 @@ analyzes the current crate's source code for changes compared to the most recent on `crates.io`. Details on the work done during GSoC 2017 can be found -[here](https://github.com/ibabushkin/rust-semverver/blob/master/doc/gsoc.md). +[here](https://github.com/rust-lang-nursery/rust-semverver/blob/master/doc/gsoc.md). ## Background @@ -19,7 +20,7 @@ said dummy and all necessary analysis is performed in that context, where type i and other resources are available. More information on the inner workings of the tool can be found -[here](https://github.com/ibabushkin/rust-semverver/blob/master/doc/impl_notes.md). +[here](https://github.com/rust-lang-nursery/rust-semverver/blob/master/doc/impl_notes.md). ## Installation @@ -30,7 +31,7 @@ If you are already using Rust nightly and have successfully installed tools like `cargo add` and `cargo clippy`, just do: ```sh -$ cargo +nightly install --git https://github.com/ibabushkin/rust-semverver +$ cargo +nightly install --git https://github.com/rust-lang-nursery/rust-semverver ```
@@ -44,7 +45,7 @@ $ cargo +nightly install --git https://github.com/ibabushkin/rust-semverver $ rustup update nightly $ rustup default nightly -$ git clone https://github.com/ibabushkin/rust-semverver +$ git clone https://github.com/rust-lang-nursery/rust-semverver $ cd rust-semverver $ cargo install ``` From e99550934b6a3b40b2043d8c997085bb3b2c3daa Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Tue, 30 Jan 2018 19:00:02 +0100 Subject: [PATCH 289/553] Bump dependencies --- Cargo.toml | 12 ++++++------ src/bin/cargo_semver.rs | 4 ++-- src/bin/rust_semverver.rs | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 10673d3bd86ce..020e5e4981f47 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,11 +15,11 @@ name = "rust-semverver" path = "src/bin/rust_semverver.rs" [dependencies] -cargo = "^0.20.0" -crates-io = "^0.9.0" -env_logger = "^0.4.0" -log = "^0.3.0" -semver = "^0.7.0" +cargo = "0.24" +crates-io = "0.13" +env_logger = "0.5" +log = "0.4" +semver = "0.9" [dev-dependencies] -quickcheck = "^0.4.1" +quickcheck = "0.6" diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 2fa8bd38de1f7..0143247c535d3 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -62,7 +62,7 @@ impl<'a> SourceInfo<'a> { /// Construct a new source info for `crates.io`. fn new(config: &'a Config) -> CargoResult> { let source_id = SourceId::crates_io(config)?; - let source = source_id.load(config); + let source = source_id.load(config)?; debug!("source id loaded: {:?}", source_id); @@ -257,7 +257,7 @@ fn main() { exit_with_error(CliError::new(e, 1), &mut config.shell()); } - if env_logger::init().is_err() { + if env_logger::try_init().is_err() { eprintln!("ERROR: could not initialize logger"); } diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index f5ba56fbd4d17..10c599ba7d1bd 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -153,7 +153,7 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { /// Find the sysroot before passing our args to the compiler driver, after registering our custom /// compiler driver. fn main() { - if env_logger::init().is_err() { + if env_logger::try_init().is_err() { eprintln!("ERROR: could not initialize logger"); } From 8278d281ccfd938054cc6c35fce98d91d7fa0284 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 31 Jan 2018 18:20:22 +0100 Subject: [PATCH 290/553] Replaced `name-version` arg format with `name:version` , akin to pkgids. This is necessary because of crate names containing dashes, as pointed out in #45. --- src/bin/cargo_semver.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 0143247c535d3..f72fc7eb537fb 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -148,20 +148,20 @@ impl<'a> WorkInfo<'a> { fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { debug!("running cargo-semver"); fn parse_arg(opt: &str) -> CargoResult { - let mut split = opt.split('-'); + let mut split = opt.split(':'); let name = if let Some(n) = split.next() { n } else { - return Err("spec has to be of form `name-version`".into()); + return Err("spec has to be of form `name:version`".into()); }; let version = if let Some(v) = split.next() { v } else { - return Err("spec has to be of form `name-version`".into()); + return Err("spec has to be of form `name:version`".into()); }; if split.next().is_some() { - return Err("spec has to be of form `name-version`".into()); + return Err("spec has to be of form `name:version`".into()); } Ok(NameAndVersion { name: name, version: version }) @@ -270,10 +270,10 @@ fn main() { opts.optflag("d", "debug", "print command to debug and exit"); 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", - "SPEC"); - opts.optopt("C", "current-pkg", "use a name-version string as current/new crate", - "SPEC"); + 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"); let config = match Config::default() { Ok(cfg) => cfg, From a42bf7e2ddc7faaf4171d136d1a62fd7aa6d74cb Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 31 Jan 2018 18:36:33 +0100 Subject: [PATCH 291/553] Updated manifest for publishing. --- Cargo.toml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 020e5e4981f47..a68d1a49cb748 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,20 @@ [package] name = "semverver" description = "Automatic verification of SemVer adhrence in rust library crates" -repository = "https://github.com/ibabushkin/rust-semverver" +repository = "https://github.com/rust-lang-nursery/rust-semverver" + +readme = "README.md" +keywords = ["semver", "plugin"] +categories = ["development-tools", "development-tools::cargo-plugins"] + version = "0.1.0" + authors = ["Inokentiy Babushkin "] license = "BSD3" +[badges] +travis-ci = { repository = "rust-lang-nursery/rust-semverver" } + [[bin]] name = "cargo-semver" path = "src/bin/cargo_semver.rs" From 815262c602896798c8050216c288ae78b762b44f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 31 Jan 2018 18:44:53 +0100 Subject: [PATCH 292/553] Fixed tests and readme after invocation syntax change. --- README.md | 8 ++++---- tests/full.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 65846efc521a8..e07d482b8fc73 100644 --- a/README.md +++ b/README.md @@ -84,10 +84,10 @@ Options: use local path as stable/old crate -c, --current-path PATH use local path as current/new crate - -S, --stable-pkg SPEC - use a name-version string as stable/old crate - -C, --current-pkg SPEC - use a name-version string 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 ``` This means that you can compare any two crates' specified versions, as long as they are diff --git a/tests/full.rs b/tests/full.rs index 4830aafdf5ea8..012d3a7c33802 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -10,8 +10,8 @@ macro_rules! full_test { fn $name() { let mut success = true; - let old_version = concat!($crate_name, "-", $old_version); - let new_version = concat!($crate_name, "-", $new_version); + let old_version = concat!($crate_name, ":", $old_version); + let new_version = concat!($crate_name, ":", $new_version); let prog = concat!(r#" # wait for the actual output From 0dd42fbe72a893781549bd318a7c1af509edafb3 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 31 Jan 2018 19:05:45 +0100 Subject: [PATCH 293/553] Fixed license in manifest. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index a68d1a49cb748..4d75d711768bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ categories = ["development-tools", "development-tools::cargo-plugins"] version = "0.1.0" authors = ["Inokentiy Babushkin "] -license = "BSD3" +license-file = "LICENSE" [badges] travis-ci = { repository = "rust-lang-nursery/rust-semverver" } From 90c0398af010ed39e68303513eae9d28fa276568 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 31 Jan 2018 19:24:41 +0100 Subject: [PATCH 294/553] Added some info on crates.io presence. --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e07d482b8fc73..ab5251132095e 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![Build Status](https://travis-ci.org/rust-lang-nursery/rust-semverver.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rust-semverver) +[![Current Version](https://meritbadge.herokuapp.com/semverver)](https://crates.io/crates/semverver) This repository is hosting a proof-of-concept implementation of an automatic tool checking rust library crates for semantic versioning adherence, developed during the Google Summer @@ -55,7 +56,7 @@ directory your project resides in. If you prefer not to install to `~/.cargo/bin invoke it like so after building with a regular `cargo build`: ```sh -PATH=/path/to/repo/target/debug:$PATH cargo semver +$ PATH=/path/to/repo/target/debug:$PATH cargo semver ``` If you have built using `cargo build --release` instead, change the path to point to the @@ -63,6 +64,12 @@ If you have built using `cargo build --release` instead, change the path to poin
+You can also install the (possibly more stable) version of the tool from crates.io: + +```sh +$ cargo install +nightly semverver +``` + ## Usage By default, running `cargo semver` in directory with a Cargo project will try to compare From ac5928d81e158af9de050b9613ee527fa325f166 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 3 Feb 2018 21:17:47 +0100 Subject: [PATCH 295/553] Checking if the current travis script can be cleaned up. --- .travis.yml | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 924fa6cb922d9..9bb2b10281334 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,22 +1,21 @@ language: rust -rust: - - nightly +rust: nightly os: - linux + - osx -addons: - apt: - sources: - - kalakris-cmake - packages: - - cmake - - libcurl4-openssl-dev - - libelf-dev - - libdw-dev +# addons: +# apt: +# sources: +# - kalakris-cmake +# packages: +# - cmake +# - libcurl4-openssl-dev +# - libelf-dev +# - libdw-dev script: - cargo build --verbose - - cargo update - RUST_BACKTRACE=full cargo test --verbose From d667db380f62d02ba12ead49b09f9393d64e9570 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 3 Feb 2018 21:40:07 +0100 Subject: [PATCH 296/553] Added a travis build for mac. --- .travis.yml | 30 ++++++++++++++++--------- tests/full_cases/libc-0.2.28-0.2.31.osx | 0 2 files changed, 19 insertions(+), 11 deletions(-) create mode 100644 tests/full_cases/libc-0.2.28-0.2.31.osx diff --git a/.travis.yml b/.travis.yml index 9bb2b10281334..e4a069f6a3310 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,16 +6,24 @@ os: - linux - osx -# addons: -# apt: -# sources: -# - kalakris-cmake -# packages: -# - cmake -# - libcurl4-openssl-dev -# - libelf-dev -# - libdw-dev +env: + global: + - RUST_BACKTRACE=full script: - - cargo build --verbose - - RUST_BACKTRACE=full cargo test --verbose + - | + set -e + if [ "$TRAVIS_OS_NAME" == "osx" ]; then + # test output for a different libc is expected to be different + mv tests/full_cases/libc-0.2.28-0.2.31.osx tests/full_cases/libc-0.2.28-0.2.31 + fi + + cargo build + cargo test --verbose + + # install + mkdir -p ~/rust/cargo/bin + cp target/debug/{cargo-semver, rust-semverver} ~/rust/cargo/bin + + # become semververver + PATH=~/. diff --git a/tests/full_cases/libc-0.2.28-0.2.31.osx b/tests/full_cases/libc-0.2.28-0.2.31.osx new file mode 100644 index 0000000000000..e69de29bb2d1d From 9a2903b9a6617e1d85b37fe34ddc8a989bc9cfa9 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 3 Feb 2018 22:39:41 +0100 Subject: [PATCH 297/553] Added meta-semverver to travis config. --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e4a069f6a3310..6971627aba1d7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,8 @@ script: # install mkdir -p ~/rust/cargo/bin - cp target/debug/{cargo-semver, rust-semverver} ~/rust/cargo/bin + cp target/debug/cargo-semver ~/rust/cargo/bin + cp target/debug/rust-semverver ~/rust/cargo/bin # become semververver - PATH=~/. + PATH=~/rust/cargo/bin:$PATH cargo semver From ac044af9f8a2a8059ac1a73c46f120ad45ccafe3 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 3 Feb 2018 23:16:59 +0100 Subject: [PATCH 298/553] Polished travis meta semverver a bit. --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6971627aba1d7..fb8bcd8ac7b56 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,4 +27,5 @@ script: cp target/debug/rust-semverver ~/rust/cargo/bin # become semververver - PATH=~/rust/cargo/bin:$PATH cargo semver + eval "current_version=$(grep -e '^version = .*$' Cargo.toml | cut -d ' ' -f 3)" + PATH=~/rust/cargo/bin:$PATH cargo semver | head -n 1 | grep "$current_version" From cce78b85e2dddef1adc65b9c2384f17eb2e106d7 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 3 Feb 2018 23:33:34 +0100 Subject: [PATCH 299/553] Added a note on CI setup to the README. --- .travis.yml | 2 +- README.md | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fb8bcd8ac7b56..ac9a372b5fdf4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,4 +28,4 @@ script: # become semververver eval "current_version=$(grep -e '^version = .*$' Cargo.toml | cut -d ' ' -f 3)" - PATH=~/rust/cargo/bin:$PATH cargo semver | head -n 1 | grep "$current_version" + PATH=~/rust/cargo/bin:$PATH cargo semver | head -n 1 | grep "\-> $current_version" diff --git a/README.md b/README.md index ab5251132095e..d54d2b491af9a 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,26 @@ Options: 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" +``` + +Make sure you do the above with access to a nightly toolchain. Check your CI provider's +documentation on how to do that. + ## Functionality The guideline used to implement semver compatibility is the [API evolution From 33cb8889bf6e0d76c7c538427ad365309a9956e3 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 3 Feb 2018 23:34:55 +0100 Subject: [PATCH 300/553] Removed mac build for now. --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ac9a372b5fdf4..293e5f7e32160 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,8 @@ rust: nightly os: - linux - - osx +# coming soon: +# - osx env: global: From dd8e435e95b0adab1595715ea31ab0f0e52375cd Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 4 Feb 2018 23:01:56 +0100 Subject: [PATCH 301/553] Made the cargo-semver invocation more verbose. --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 293e5f7e32160..edea35a9f6d7f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,4 +29,5 @@ script: # become semververver eval "current_version=$(grep -e '^version = .*$' Cargo.toml | cut -d ' ' -f 3)" - PATH=~/rust/cargo/bin:$PATH cargo semver | head -n 1 | grep "\-> $current_version" + PATH=~/rust/cargo/bin:$PATH cargo semver | tee semver_out + head -n 1 semver_out | grep "\-> $current_version" From 892e843d4ba00c3896a822033622d3497f54f243 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 4 Feb 2018 23:20:32 +0100 Subject: [PATCH 302/553] Version bump to please meta semverver. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4d75d711768bc..ce126ffb3eab8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.0" +version = "0.1.1" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From b5e35e7bbef0ab628eaf221e8a6010d78b4d6259 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 5 Feb 2018 21:14:13 +0100 Subject: [PATCH 303/553] More obvious erroring in builds failing because of semverver. --- .travis.yml | 1 + README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index edea35a9f6d7f..911555af2939f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,3 +31,4 @@ script: eval "current_version=$(grep -e '^version = .*$' Cargo.toml | cut -d ' ' -f 3)" PATH=~/rust/cargo/bin:$PATH cargo semver | tee semver_out head -n 1 semver_out | grep "\-> $current_version" + (head -n 1 semver_out | grep "\-> $current_version") || (echo "versioning mismatch" && return 1) diff --git a/README.md b/README.md index d54d2b491af9a..9e2570c8d2148 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ 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" +(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 From 77a8386cc51ad3f9cab8c3563004dc8246d8041a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 5 Feb 2018 21:32:57 +0100 Subject: [PATCH 304/553] Removed a stray line from the travis build. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 911555af2939f..2b72343603188 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,5 +30,4 @@ script: # become semververver eval "current_version=$(grep -e '^version = .*$' Cargo.toml | cut -d ' ' -f 3)" PATH=~/rust/cargo/bin:$PATH cargo semver | tee semver_out - head -n 1 semver_out | grep "\-> $current_version" (head -n 1 semver_out | grep "\-> $current_version") || (echo "versioning mismatch" && return 1) From 9191fb2d4d785c78fe911035a3d43a9ce2bac757 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 7 Feb 2018 22:31:04 +0100 Subject: [PATCH 305/553] Added basic structure for explanations. This is the first step in implementing #36. --- src/bin/rust_semverver.rs | 3 ++- src/semcheck/changes.rs | 19 +++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 10c599ba7d1bd..bfbc356cdb72f 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -66,7 +66,8 @@ fn callback(state: &driver::CompileState, version: &str) { debug!("running semver analysis"); let changes = run_analysis(tcx, old_def_id, new_def_id); - changes.output(tcx.sess, version); + // TODO: arm the verbosity switch + changes.output(tcx.sess, version, false); } /// A wrapper to control compilation. diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 463f5d906ed83..0397c816c2408 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -314,6 +314,12 @@ impl<'tcx> ChangeType<'tcx> { FnConstChanged { now_const: true } => NonBreaking, } } + + /// Get a detailed explanation of a change, and why it is categorized as-is. + fn explanation(&self) -> &'static str { + // TODO: meaningful explanations + "test" + } } impl<'a> fmt::Display for ChangeType<'a> { @@ -485,7 +491,7 @@ impl<'tcx> Change<'tcx> { } /// Report the change in a structured manner, using rustc's error reporting capabilities. - fn report(&self, session: &Session) { + fn report(&self, session: &Session, verbose: bool) { if self.max == Patch || !self.output { return; } @@ -499,7 +505,12 @@ impl<'tcx> Change<'tcx> { for change in &self.changes { let cat = change.0.to_category(); - let sub_msg = format!("{} ({})", change.0, cat); + 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); @@ -661,7 +672,7 @@ impl<'tcx> ChangeSet<'tcx> { } /// Format the contents of a change set for user output. - pub fn output(&self, session: &Session, version: &str) { + pub fn output(&self, session: &Session, version: &str, verbose: bool) { if let Ok(mut new_version) = Version::parse(version) { match self.max { Patch => new_version.increment_patch(), @@ -680,7 +691,7 @@ impl<'tcx> ChangeSet<'tcx> { } if let Some(change) = self.changes.get(key) { - change.report(session); + change.report(session, verbose); } } } From 35c85d45674722cef184bb8e9bc6460c61686715 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 7 Feb 2018 22:43:21 +0100 Subject: [PATCH 306/553] Implemented less strict version requirements for pre-1.0.0 versions. Closes #46. --- src/semcheck/changes.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 0397c816c2408..ba1fa269284a9 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -674,10 +674,14 @@ impl<'tcx> ChangeSet<'tcx> { /// Format the contents of a change set for user output. pub fn output(&self, session: &Session, version: &str, verbose: bool) { if let Ok(mut new_version) = Version::parse(version) { - match self.max { - Patch => new_version.increment_patch(), - NonBreaking | TechnicallyBreaking => new_version.increment_minor(), - Breaking => new_version.increment_major(), + 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(), + } } println!("version bump: {} -> ({}) -> {}", version, self.max, new_version); From 7b51f7b3825ad1adbaa76d0f37b4b274a8da35e8 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 7 Feb 2018 23:12:47 +0100 Subject: [PATCH 307/553] Version bump and test fixes. --- Cargo.toml | 2 +- tests/full_cases/libc-0.2.28-0.2.31 | 2 +- tests/full_cases/log-0.3.4-0.3.8 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ce126ffb3eab8..e1146020531eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.1" +version = "0.1.2" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" diff --git a/tests/full_cases/libc-0.2.28-0.2.31 b/tests/full_cases/libc-0.2.28-0.2.31 index 7f729fb62773a..ec59f2f4e3de6 100644 --- a/tests/full_cases/libc-0.2.28-0.2.31 +++ b/tests/full_cases/libc-0.2.28-0.2.31 @@ -1,4 +1,4 @@ -version bump: 0.2.28 -> (breaking) -> 1.0.0 +version bump: 0.2.28 -> (breaking) -> 0.2.29 warning: path changes to `INADDR_LOOPBACK` --> libc-0.2.31/src/unix/mod.rs:227:1 | diff --git a/tests/full_cases/log-0.3.4-0.3.8 b/tests/full_cases/log-0.3.4-0.3.8 index a1d1cfd16119f..b7ce494eadc75 100644 --- a/tests/full_cases/log-0.3.4-0.3.8 +++ b/tests/full_cases/log-0.3.4-0.3.8 @@ -1,4 +1,4 @@ -version bump: 0.3.4 -> (technically breaking) -> 0.4.0 +version bump: 0.3.4 -> (technically breaking) -> 0.3.5 warning: technically breaking changes in `` --> log-0.3.8/src/lib.rs:266:27 | From f4c7589a5ccd8facded9f4bbfea7dc143fbccf21 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 9 Feb 2018 21:39:27 +0100 Subject: [PATCH 308/553] Avoid weirding out cargo with PATHs in test suite. Fixes #47. --- tests/full.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/full.rs b/tests/full.rs index 012d3a7c33802..20f981dfd9c85 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -58,8 +58,8 @@ macro_rules! full_test { panic!("could not pipe to awk"); }; - success &= Command::new("cargo") - .args(&["semver", "-S", &old_version, "-C", &new_version]) + success &= Command::new("./target/debug/cargo-semver") + .args(&["-S", &old_version, "-C", &new_version]) .env("RUST_BACKTRACE", "full") .stdin(Stdio::null()) .stdout(out_pipe) From 663b882812649b897590365f8a085f8a3af6548c Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 13 Feb 2018 14:22:48 +0100 Subject: [PATCH 309/553] Some drafts for error explanations. --- src/semcheck/changes.rs | 107 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 1 deletion(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index ba1fa269284a9..e85b680addeb6 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -318,7 +318,112 @@ impl<'tcx> ChangeType<'tcx> { /// Get a detailed explanation of a change, and why it is categorized as-is. fn explanation(&self) -> &'static str { // TODO: meaningful explanations - "test" + match *self { + ItemMadePublic => +"Items being added 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.", + ItemMadePrivate => +"Items being removed from a module's public interface are a breaking change.", + KindDifference => +"Items changing their \"kind\" of item between versions are a breaking change.", + StaticMutabilityChanged { now_mut: true } => +"Static items newly made mutable don't break any user code, which is guaranteed +to use them in a read-only fashion.", + StaticMutabilityChanged { now_mut: false } => +"Static items newly made immutable can break user code that tries to mutate them.", + VarianceLoosened => +"The variance of a type or region parameter in an item loosens iff .", + VarianceTightened => +"The variance of a type or region parameter in an item tightens iff .", + VarianceChanged { .. } => +"Switching the variance of a type or region parameter is breaking. ", + RegionParameterAdded => +"Adding a new region parameter is a breaking change. .", + RegionParameterRemoved => +"Removing a region parameter is a breaking change. .", + 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 difference arises.", + TypeParameterAdded { defaulted: false } => +"Adding a new non-defaulted type parameter is a breaking change, because old +references to the item become invalid, if 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 it +is rendered invalid.", + VariantFieldAdded { public: _, total_public: _ } => +"Adding a field from a variant: .", + VariantFieldRemoved { public: _, total_public: _ } => +"Removing a field from a variant: .", + VariantStyleChanged { .. } => +"Changing the style of a variant is a breaking change, since every old reference +to it is rendered invalid.", + FnConstChanged { now_const: true } => +"Making a function const is a non-breaking change, because a const-function can +appear everywhere a regular function is expected.", + FnConstChanged { now_const: false } => +"Making a const function non-const is a breaking change, because some situations +require a const function, and don't accept a regular one.", + 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.", + 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.", + TraitItemAdded { defaulted: false } => +"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 lieftime 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 associated item is a breaking change in some specific situations, +.", + AssociatedItemRemoved => +"Removing an associated item is a breaking change, as all old references to it +become invalid.", + Unknown => "No explanation for unknown changes.", + } } } From 29096e093ee1759346a5a2e905ca0a51ac59e303 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 13 Feb 2018 16:29:39 +0100 Subject: [PATCH 310/553] Fixed some of the error descriptions. --- src/semcheck/changes.rs | 121 ++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 55 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index e85b680addeb6..63880184c60bb 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -320,18 +320,22 @@ impl<'tcx> ChangeType<'tcx> { // TODO: meaningful explanations match *self { ItemMadePublic => -"Items being added to a module's public interface is generally a non-breaking +"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.", +they can cause nameclashes. Thus, the change is classified as \"technically +breaking\".", ItemMadePrivate => -"Items being removed from a module's public interface are a breaking change.", +"Removing an item from a module's public interface is a breaking change.", KindDifference => -"Items changing their \"kind\" of item between versions are a breaking change.", +"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 } => -"Static items newly made mutable don't break any user code, which is guaranteed -to use them in a read-only fashion.", +"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 } => -"Static items newly made immutable can break user code that tries to mutate them.", +"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 iff .", VarianceTightened => @@ -343,85 +347,92 @@ to use them in a read-only fashion.", RegionParameterRemoved => "Removing a region parameter is a breaking change. .", 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 difference arises.", +"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, if the type parameter can't be inferred.", +"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.", +"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.", +"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 it -is rendered invalid.", +"Removing an enum variant is a braking change, because every old reference +to the removed variant is rendered invalid.", VariantFieldAdded { public: _, total_public: _ } => "Adding a field from a variant: .", VariantFieldRemoved { public: _, total_public: _ } => "Removing a field from a variant: .", VariantStyleChanged { .. } => -"Changing the style of a variant is a breaking change, since every old reference -to it is rendered invalid.", +"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 everywhere a regular function is expected.", +"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 some situations -require a const function, and don't accept a regular one.", +"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.", +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.", +"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.", +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 { defaulted: false } => "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.", +"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.", +"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.", +"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.", +"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 lieftime or type parameter in a non-trait definition -is a non-breaking change, because all old references to the item would remain -valid.", +"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.", +"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.", +"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 associated item is a breaking change in some specific situations, -.", +"Adding a new associated item is a breaking change in some specific +situations, .", AssociatedItemRemoved => -"Removing an associated item is a breaking change, as all old references to it -become invalid.", +"Removing an associated item is a breaking change, as all old +references to it become invalid.", Unknown => "No explanation for unknown changes.", } } From a27de78f681829a321dbf81accf5e0e168c7b847 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 13 Feb 2018 17:00:02 +0100 Subject: [PATCH 311/553] Added an ugly envvar hack for verbosity. --- src/bin/rust_semverver.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index bfbc356cdb72f..1e120c0a7d5cb 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -32,7 +32,7 @@ use syntax::ast; /// /// To compare the two well-typed crates, first find the aptly named crates `new` and `old`, /// find their root modules and then proceed to walk their module trees. -fn callback(state: &driver::CompileState, version: &str) { +fn callback(state: &driver::CompileState, version: &str, verbose: bool) { let tcx = state.tcx.unwrap(); let cnums = tcx @@ -66,8 +66,7 @@ fn callback(state: &driver::CompileState, version: &str) { debug!("running semver analysis"); let changes = run_analysis(tcx, old_def_id, new_def_id); - // TODO: arm the verbosity switch - changes.output(tcx.sess, version, false); + changes.output(tcx.sess, version, verbose); } /// A wrapper to control compilation. @@ -137,9 +136,13 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { std::mem::replace(&mut controller.after_analysis.callback, box |_| {}); let version = self.version.clone(); + let verbose = std::env::var("RUST_SEMVER_VERBOSE") + .ok() + .map_or(false, |s| s == "true"); + controller.after_analysis.callback = box move |state| { debug!("running rust-semverver after_analysis callback"); - callback(state, &version); + callback(state, &version, verbose); debug!("running other after_analysis callback"); old_callback(state); }; From b55420e3d1e39af5d521d7de889bbb5b32ad9c7e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 3 Mar 2018 20:35:51 +0100 Subject: [PATCH 312/553] Implemented UnpackedKind handling in order to fix build with newest nightly. --- src/semcheck/mismatch.rs | 7 +++++-- src/semcheck/translate.rs | 9 +++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 1023ed9ca9fb3..7240d77665f08 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -67,9 +67,12 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> MismatchRelation<'a, 'gcx, 'tcx> { /// Ensure that the pair of given `Substs` is suitable to be related. fn check_substs(&self, a_substs: &'tcx Substs<'tcx>, b_substs: &'tcx Substs<'tcx>) -> bool { + use rustc::ty::subst::UnpackedKind::*; + for (a, b) in a_substs.iter().zip(b_substs) { - if a.as_type().is_some() != b.as_type().is_some() { - return false; + match (a.unpack(), b.unpack()) { + (Lifetime(_), Type(_)) | (Type(_), Lifetime(_)) => return false, + _ => (), } } diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 9f3a77e804016..0185ccbbe7e4f 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -95,6 +95,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { orig_def_id, orig_substs); use rustc::ty::ReEarlyBound; + use rustc::ty::subst::UnpackedKind; use std::cell::Cell; let target_def_id = (self.translate_orig)(self.id_mapping, orig_def_id); @@ -105,9 +106,9 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { let target_substs = Substs::for_item(self.tcx, target_def_id, |def, _| { if !success.get() { self.tcx.mk_region(ReEarlyBound(def.to_early_bound_region_data())) - } else if let Some(region) = orig_substs + } else if let Some(UnpackedKind::Lifetime(region)) = orig_substs .get(def.index as usize) - .and_then(|k| k.as_region()) + .map(|k| k.unpack()) { self.translate_region(region) } else { @@ -118,9 +119,9 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { }, |def, _| { if !success.get() { self.tcx.mk_param_from_def(def) - } else if let Some(type_) = orig_substs + } else if let Some(UnpackedKind::Type(type_)) = orig_substs .get(def.index as usize) - .and_then(|k| k.as_type()) + .map(|k| k.unpack()) { self.translate(index_map, &type_) } else if self.id_mapping.is_non_mapped_defaulted_type_param(&def.def_id) { From c60c4c3c8d1ec9ee1a1c38fbe03f7c8ebd6ee6b3 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 3 Mar 2018 22:50:03 +0100 Subject: [PATCH 313/553] Added support for universe indices to fix build with newest nightly. --- src/semcheck/translate.rs | 3 ++- src/semcheck/typeck.rs | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 0185ccbbe7e4f..bc99848c1f4a2 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -2,7 +2,7 @@ //! comparison and inference. use rustc::hir::def_id::DefId; -use rustc::ty::{ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt}; +use rustc::ty::{ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt, UniverseIndex}; use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder}; use rustc::infer::InferCtxt; use rustc::ty::subst::Substs; @@ -432,6 +432,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { .map(|target_preds| ParamEnv { caller_bounds: self.tcx.intern_predicates(&target_preds), reveal: param_env.reveal, + universe: UniverseIndex::ROOT, }) } diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs index 2b4d268b686ea..a6dc135ec07d7 100644 --- a/src/semcheck/typeck.rs +++ b/src/semcheck/typeck.rs @@ -6,7 +6,7 @@ use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; use rustc::traits::{FulfillmentContext, FulfillmentError, Obligation, ObligationCause}; -use rustc::ty::{ParamEnv, Predicate, TraitRef, Ty, TyCtxt}; +use rustc::ty::{ParamEnv, Predicate, TraitRef, Ty, TyCtxt, UniverseIndex}; use rustc::ty::error::TypeError; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::Substs; @@ -150,11 +150,11 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { Substs::for_item(self.infcx.tcx, target_def_id, |def, _| { self.infcx.region_var_for_def(DUMMY_SP, def) - }, |def, substs| { + }, |def, _| { if def.index == 0 && has_self { // `Self` is special self.infcx.tcx.mk_param_from_def(def) } else { - self.infcx.type_var_for_def(DUMMY_SP, def, substs) + self.infcx.type_var_for_def(UniverseIndex::ROOT, DUMMY_SP, def) } }) } From 45302526bd2eb8820debc6552e1ae0ea9f573d8d Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 3 Mar 2018 23:16:01 +0100 Subject: [PATCH 314/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e1146020531eb..5612c6ead3f07 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.2" +version = "0.1.3" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From 3145c133dbb3678e40aa10b05abb5cfa46914895 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 10 Mar 2018 16:19:21 +0100 Subject: [PATCH 315/553] Fixes for next nightly and a small improvement in laziness. --- src/semcheck/translate.rs | 6 +++--- src/semcheck/typeck.rs | 11 +++++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index bc99848c1f4a2..dda5ef9686453 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -320,7 +320,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { fn translate_predicate(&self, index_map: &HashMap, predicate: Predicate<'tcx>) -> Option> { - use rustc::ty::{Binder, EquatePredicate, OutlivesPredicate, ProjectionPredicate, + use rustc::ty::{Binder, /*EquatePredicate,*/ OutlivesPredicate, ProjectionPredicate, ProjectionTy, SubtypePredicate, TraitPredicate, TraitRef}; Some(match predicate { @@ -339,13 +339,13 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { return None; })) }, - Predicate::Equate(equate_predicate) => { + /*Predicate::Equate(equate_predicate) => { Predicate::Equate(equate_predicate.map_bound(|e_pred| { let l = self.translate(index_map, &e_pred.0); let r = self.translate(index_map, &e_pred.1); EquatePredicate(l, r) })) - }, + },*/ Predicate::RegionOutlives(region_outlives_predicate) => { Predicate::RegionOutlives(region_outlives_predicate.map_bound(|r_pred| { let l = self.translate_region(r_pred.0); diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs index a6dc135ec07d7..466251889243a 100644 --- a/src/semcheck/typeck.rs +++ b/src/semcheck/typeck.rs @@ -5,7 +5,9 @@ use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; -use rustc::traits::{FulfillmentContext, FulfillmentError, Obligation, ObligationCause}; +use rustc::traits::{auto_trait, + FulfillmentContext, FulfillmentError, + Obligation, ObligationCause}; use rustc::ty::{ParamEnv, Predicate, TraitRef, Ty, TyCtxt, UniverseIndex}; use rustc::ty::error::TypeError; use rustc::ty::fold::TypeFoldable; @@ -267,9 +269,6 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { let orig_param_env = self .forward_trans .translate_param_env(orig_def_id, tcx.param_env(orig_def_id)); - let target_param_env = self - .backward_trans - .translate_param_env(target_def_id, tcx.param_env(target_def_id)); let orig_param_env = if let Some(env) = orig_param_env { env @@ -289,6 +288,10 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { } } + 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 { From 8424fbd4d2de616c6facff2a9a3fa9dc24d76d71 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 16 Mar 2018 14:25:16 +0100 Subject: [PATCH 316/553] Fixed some leftovers from the previous cherry-pick. --- src/semcheck/mismatch.rs | 2 +- src/semcheck/typeck.rs | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 7240d77665f08..2079400bb9fc8 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -187,7 +187,7 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, _ => None, } }, - (&TyTuple(as_, _), &TyTuple(bs, _)) => { + (&TyTuple(as_), &TyTuple(bs)) => { let _ = as_.iter().zip(bs).map(|(a, b)| self.relate(a, b)); None }, diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs index 466251889243a..4de9aa553b6b4 100644 --- a/src/semcheck/typeck.rs +++ b/src/semcheck/typeck.rs @@ -5,9 +5,7 @@ use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; -use rustc::traits::{auto_trait, - FulfillmentContext, FulfillmentError, - Obligation, ObligationCause}; +use rustc::traits::{FulfillmentContext, FulfillmentError, Obligation, ObligationCause}; use rustc::ty::{ParamEnv, Predicate, TraitRef, Ty, TyCtxt, UniverseIndex}; use rustc::ty::error::TypeError; use rustc::ty::fold::TypeFoldable; From 54775d6f49db976e18550c43bdec7f25f0e81925 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 16 Mar 2018 16:11:52 +0100 Subject: [PATCH 317/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 5612c6ead3f07..501e4e3fc552b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.3" +version = "0.1.4" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From a95a64bb77b892cd61f10624df4ee49d28ab88ae Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 16 Mar 2018 16:24:50 +0100 Subject: [PATCH 318/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 501e4e3fc552b..ff500f8d6cb07 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.4" +version = "0.1.5" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From 474863a6c4f0fce2fd12cf9ea4ed4f1c2890b8b7 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 19 Mar 2018 18:17:20 +0100 Subject: [PATCH 319/553] Stopped type checking private fields. --- src/semcheck/traverse.rs | 6 +++--- tests/cases/infer_regress/new.rs | 2 +- tests/cases/infer_regress/old.rs | 2 +- tests/cases/infer_regress/stdout | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index c6813352c55ef..d59d24b038953 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -406,9 +406,9 @@ fn diff_adts(changes: &mut ChangeSet, for items2 in fields.values() { match *items2 { (Some(o), Some(n)) => { - id_mapping.add_subitem(old_def_id, o.did, n.did); - - if o.vis != Public && n.vis == Public { + 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(ItemMadePublic, old_def_id, Some(tcx.def_span(n.did))); diff --git a/tests/cases/infer_regress/new.rs b/tests/cases/infer_regress/new.rs index 188823ab39b6e..86aafa21b9875 100644 --- a/tests/cases/infer_regress/new.rs +++ b/tests/cases/infer_regress/new.rs @@ -1,3 +1,3 @@ pub fn abc
(_: A) { } -pub struct Abc(A, ()); +pub struct Abc(pub A, pub ()); diff --git a/tests/cases/infer_regress/old.rs b/tests/cases/infer_regress/old.rs index cad3da0abdbd2..e6def43b4d539 100644 --- a/tests/cases/infer_regress/old.rs +++ b/tests/cases/infer_regress/old.rs @@ -2,4 +2,4 @@ pub fn abc(a: A) -> A { a } -pub struct Abc(A, A); +pub struct Abc(pub A, pub A); diff --git a/tests/cases/infer_regress/stdout b/tests/cases/infer_regress/stdout index b0d9fbf0ef1f5..a15a5c5691b28 100644 --- a/tests/cases/infer_regress/stdout +++ b/tests/cases/infer_regress/stdout @@ -11,8 +11,8 @@ error: breaking changes in `abc` error: breaking changes in `Abc` --> $REPO_PATH/tests/cases/infer_regress/new.rs:3:1 | -3 | pub struct Abc(A, ()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +3 | pub struct Abc(pub A, pub ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: type error: expected type parameter, found () (breaking) From d7b4c0b800ab60b5fcf0edb495ef345c621cc005 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 22 Mar 2018 15:19:22 +0100 Subject: [PATCH 320/553] Improved debugging experience for full tests. --- src/semcheck/traverse.rs | 7 +++++++ tests/full.rs | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index d59d24b038953..9a8e30db7fd1a 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -784,6 +784,8 @@ fn cmp_bounds<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, '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); @@ -855,6 +857,8 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>) { + debug!("diffing trait impls"); + use rustc::hir::def::Def; let to_new = TranslationContext::target_new(tcx, id_mapping, false); let to_old = TranslationContext::target_old(tcx, id_mapping, false); @@ -915,6 +919,9 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, target_item: AssociatedItem) -> bool { use rustc::ty::AssociatedKind; + 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; diff --git a/tests/full.rs b/tests/full.rs index 20f981dfd9c85..5dc291cce5587 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -20,6 +20,10 @@ macro_rules! full_test { } { + # check the environ for filtering + if (ENVIRON["RUST_LOG"] == "debug") + doprint = 1; + # skip compilation info if (!doprint) next; From 0c5106804d4b6268b01aea71191387e2eec2aa17 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 22 Mar 2018 19:58:54 +0100 Subject: [PATCH 321/553] Fixed Issue #50. Caused by the translation of substs in a context where said substs were already translated, due to the bottom-up nature of our translation mechanism. This should be adressed in the future in other cases as well. --- src/semcheck/translate.rs | 13 +++++++++++-- tests/cases/issue_50/new.rs | 16 ++++++++++++++++ tests/cases/issue_50/old.rs | 16 ++++++++++++++++ tests/cases/issue_50/stdout | 1 + tests/examples.rs | 1 + tests/full.rs | 1 + 6 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 tests/cases/issue_50/new.rs create mode 100644 tests/cases/issue_50/old.rs create mode 100644 tests/cases/issue_50/stdout diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index dda5ef9686453..f8ca7319f3154 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -151,13 +151,23 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { orig.fold_with(&mut BottomUpFolder { tcx: self.tcx, fldop: |ty| { match ty.sty { TyAdt(&AdtDef { ref did, .. }, substs) if self.needs_translation(*did) => { - if let Some((target_def_id, target_substs)) = + /* if let Some((target_def_id, target_substs)) = self.translate_orig_substs(index_map, *did, substs) { let target_adt = self.tcx.adt_def(target_def_id); self.tcx.mk_adt(target_adt, target_substs) } else { ty + } */ + + // we fold bottom-up, so the code above is invalid, as it assumes the + // substs (that have been folded already) are yet untranslated + // TODO: fix other places as well? + 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 } }, TyRef(region, type_and_mut) => { @@ -181,7 +191,6 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { let err_pred = AutoTrait(DefId::local(CRATE_DEF_INDEX)); let res: Vec<_> = preds.iter().map(|p| { - debug!("pred: {:?}", p); match *p.skip_binder() { Trait(existential_trait_ref) => { let trait_ref = Binder(existential_trait_ref) diff --git a/tests/cases/issue_50/new.rs b/tests/cases/issue_50/new.rs new file mode 100644 index 0000000000000..1c5995ed73f6a --- /dev/null +++ b/tests/cases/issue_50/new.rs @@ -0,0 +1,16 @@ +pub trait TypedArrayElement { + type Element; +} + +pub struct CreateWith<'a, T: 'a>(&'a T); + +pub fn create(_: CreateWith) { } + +/* #[allow(dead_code)] +pub struct TypedArray { + computed: T::Element, +} + +impl TypedArray { + pub unsafe fn create(_: CreateWith) { } +} */ diff --git a/tests/cases/issue_50/old.rs b/tests/cases/issue_50/old.rs new file mode 100644 index 0000000000000..1c5995ed73f6a --- /dev/null +++ b/tests/cases/issue_50/old.rs @@ -0,0 +1,16 @@ +pub trait TypedArrayElement { + type Element; +} + +pub struct CreateWith<'a, T: 'a>(&'a T); + +pub fn create(_: CreateWith) { } + +/* #[allow(dead_code)] +pub struct TypedArray { + computed: T::Element, +} + +impl TypedArray { + pub unsafe fn create(_: CreateWith) { } +} */ diff --git a/tests/cases/issue_50/stdout b/tests/cases/issue_50/stdout new file mode 100644 index 0000000000000..f8c2af4c949b7 --- /dev/null +++ b/tests/cases/issue_50/stdout @@ -0,0 +1 @@ +version bump: 1.0.0 -> (patch) -> 1.0.1 diff --git a/tests/examples.rs b/tests/examples.rs index e2d7672055c06..11587fe0c280a 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -110,6 +110,7 @@ test!(infer); test!(infer_regress); test!(inherent_impls); test!(issue_34); +test!(issue_50); test!(kind_change); test!(macros); test!(max_priv); diff --git a/tests/full.rs b/tests/full.rs index 5dc291cce5587..723933bf10c91 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -92,6 +92,7 @@ macro_rules! full_test { full_test!(log, "log", "0.3.4", "0.3.8"); full_test!(libc, "libc", "0.2.28", "0.2.31"); +// 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"); From e901c68170e75b35dbb31e381a882efd327b3a43 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 22 Mar 2018 20:14:09 +0100 Subject: [PATCH 322/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ff500f8d6cb07..549b34e0be8b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.5" +version = "0.1.6" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From 0d532c4c42ad0030ee3d6f064eeda4e496988e74 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 26 Mar 2018 12:47:46 +0200 Subject: [PATCH 323/553] Updated test output to go with newest nightly. --- tests/cases/addition_use/stdout | 2 ++ tests/cases/bounds/stdout | 2 ++ tests/cases/consts/stdout | 2 ++ tests/cases/enums/stdout | 2 ++ tests/cases/func/stdout | 2 ++ tests/cases/infer_regress/stdout | 2 ++ tests/cases/inherent_impls/stdout | 2 ++ tests/cases/kind_change/stdout | 2 ++ tests/cases/macros/stdout | 2 ++ tests/cases/mix/stdout | 2 ++ tests/cases/regions/stdout | 2 ++ tests/cases/removal/stdout | 2 ++ tests/cases/removal_path/stdout | 2 ++ tests/cases/removal_use/stdout | 2 ++ tests/cases/structs/stdout | 2 ++ tests/cases/trait_impls/stdout | 2 ++ tests/cases/traits/stdout | 2 ++ tests/cases/ty_alias/stdout | 2 ++ tests/full_cases/libc-0.2.28-0.2.31 | 2 ++ 19 files changed, 38 insertions(+) diff --git a/tests/cases/addition_use/stdout b/tests/cases/addition_use/stdout index 1a5efb1cdb7ce..297904f044b77 100644 --- a/tests/cases/addition_use/stdout +++ b/tests/cases/addition_use/stdout @@ -27,3 +27,5 @@ warning: path changes to `Bcd` | = note: added definition (technically breaking) +error: aborting due to previous error + diff --git a/tests/cases/bounds/stdout b/tests/cases/bounds/stdout index de6b248d39e15..7bf7db721bb5a 100644 --- a/tests/cases/bounds/stdout +++ b/tests/cases/bounds/stdout @@ -35,3 +35,5 @@ warning: technically breaking changes in `def` | = note: removed bound: `A: std::clone::Clone` (technically breaking) +error: aborting due to 2 previous errors + diff --git a/tests/cases/consts/stdout b/tests/cases/consts/stdout index 61c5bd23a788f..c6473bc5168e8 100644 --- a/tests/cases/consts/stdout +++ b/tests/cases/consts/stdout @@ -31,3 +31,5 @@ warning: non-breaking changes in `E` | = note: static item made mutable (non-breaking) +error: aborting due to 3 previous errors + diff --git a/tests/cases/enums/stdout b/tests/cases/enums/stdout index e9a08b0dc56d2..87d10b98338d1 100644 --- a/tests/cases/enums/stdout +++ b/tests/cases/enums/stdout @@ -104,3 +104,5 @@ warning: variant field added to variant with private fields (breaking) 25 | Ghi { g: u8 }, | ^^^^^ +error: aborting due to 5 previous errors + diff --git a/tests/cases/func/stdout b/tests/cases/func/stdout index a895ba5e1a3c7..282e8f15e85af 100644 --- a/tests/cases/func/stdout +++ b/tests/cases/func/stdout @@ -75,3 +75,5 @@ error: breaking changes in `ijk` | = warning: fn item made non-const (breaking) +error: aborting due to 6 previous errors + diff --git a/tests/cases/infer_regress/stdout b/tests/cases/infer_regress/stdout index a15a5c5691b28..eab24a7480d36 100644 --- a/tests/cases/infer_regress/stdout +++ b/tests/cases/infer_regress/stdout @@ -16,3 +16,5 @@ error: breaking changes in `Abc` | = warning: type error: expected type parameter, found () (breaking) +error: aborting due to 2 previous errors + diff --git a/tests/cases/inherent_impls/stdout b/tests/cases/inherent_impls/stdout index c0f4e77a83f05..2f1ef38d71c40 100644 --- a/tests/cases/inherent_impls/stdout +++ b/tests/cases/inherent_impls/stdout @@ -55,3 +55,5 @@ warning: technically breaking changes in `def` | = note: added item in inherent impl (technically breaking) +error: aborting due to 4 previous errors + diff --git a/tests/cases/kind_change/stdout b/tests/cases/kind_change/stdout index 5190a0a42bd69..f744fe3ccf44e 100644 --- a/tests/cases/kind_change/stdout +++ b/tests/cases/kind_change/stdout @@ -9,3 +9,5 @@ error: breaking changes in `Abc` | = warning: item kind changed (breaking) +error: aborting due to previous error + diff --git a/tests/cases/macros/stdout b/tests/cases/macros/stdout index 3dd74b0d20d23..da768f9909b37 100644 --- a/tests/cases/macros/stdout +++ b/tests/cases/macros/stdout @@ -39,3 +39,5 @@ warning: path changes to `quux2` | = note: added definition (technically breaking) +error: aborting due to 2 previous errors + diff --git a/tests/cases/mix/stdout b/tests/cases/mix/stdout index 8282238fbdaee..9ba0b514a8cfd 100644 --- a/tests/cases/mix/stdout +++ b/tests/cases/mix/stdout @@ -44,3 +44,5 @@ note: added path (technically breaking) 10| pub use self::a::Def; | ^^^^^^^^^^^^ +error: aborting due to 3 previous errors + diff --git a/tests/cases/regions/stdout b/tests/cases/regions/stdout index 7f03c3c6252bf..d128cea097596 100644 --- a/tests/cases/regions/stdout +++ b/tests/cases/regions/stdout @@ -47,3 +47,5 @@ error: breaking changes in `fgh` | = warning: type error: expected bound lifetime parameterBrAnon(0), found concrete lifetime (breaking) +error: aborting due to 6 previous errors + diff --git a/tests/cases/removal/stdout b/tests/cases/removal/stdout index fd17ca8100065..25c647e52be0f 100644 --- a/tests/cases/removal/stdout +++ b/tests/cases/removal/stdout @@ -53,3 +53,5 @@ error: breaking changes in `d` | = warning: item made private (breaking) +error: aborting due to 6 previous errors + diff --git a/tests/cases/removal_path/stdout b/tests/cases/removal_path/stdout index c913b1e79ef86..e404c4c92ac01 100644 --- a/tests/cases/removal_path/stdout +++ b/tests/cases/removal_path/stdout @@ -21,3 +21,5 @@ warning: removed path (breaking) 13| pub use self::a::Abc; | ^^^^^^^^^^^^ +error: aborting due to previous error + diff --git a/tests/cases/removal_use/stdout b/tests/cases/removal_use/stdout index 51f6c7ddecf66..5d72bb3749f03 100644 --- a/tests/cases/removal_use/stdout +++ b/tests/cases/removal_use/stdout @@ -27,3 +27,5 @@ error: breaking changes in `Def` = warning: type error: expected struct `old::Abc`, found () (breaking) = warning: type error: expected trait old::Bcd, found () (breaking) +error: aborting due to 3 previous errors + diff --git a/tests/cases/structs/stdout b/tests/cases/structs/stdout index a0864aa096a6c..32025a98d4273 100644 --- a/tests/cases/structs/stdout +++ b/tests/cases/structs/stdout @@ -79,3 +79,5 @@ warning: variant with no public fields changed to a struct variant (breaking) 28 | | } | |_^ +error: aborting due to 4 previous errors + diff --git a/tests/cases/trait_impls/stdout b/tests/cases/trait_impls/stdout index 420d1450bddd8..5169b41301c16 100644 --- a/tests/cases/trait_impls/stdout +++ b/tests/cases/trait_impls/stdout @@ -51,3 +51,5 @@ warning: technically breaking changes in ` as new::Ab | = note: trait impl generalized or newly added (technically breaking) +error: aborting due to 2 previous errors + diff --git a/tests/cases/traits/stdout b/tests/cases/traits/stdout index bc7e87f34035a..a3f2a4e292452 100644 --- a/tests/cases/traits/stdout +++ b/tests/cases/traits/stdout @@ -156,3 +156,5 @@ error: breaking changes in `Tuv` | = warning: removed bound on trait definition: `A: std::clone::Clone` (breaking) +error: aborting due to 13 previous errors + diff --git a/tests/cases/ty_alias/stdout b/tests/cases/ty_alias/stdout index a59bc681c8494..0c28d4835061d 100644 --- a/tests/cases/ty_alias/stdout +++ b/tests/cases/ty_alias/stdout @@ -56,3 +56,5 @@ error: breaking changes in `G` | = warning: type parameter removed (breaking) +error: aborting due to 7 previous errors + diff --git a/tests/full_cases/libc-0.2.28-0.2.31 b/tests/full_cases/libc-0.2.28-0.2.31 index ec59f2f4e3de6..499486a0ed232 100644 --- a/tests/full_cases/libc-0.2.28-0.2.31 +++ b/tests/full_cases/libc-0.2.28-0.2.31 @@ -865,3 +865,5 @@ error: breaking changes in `PTRACE_O_SUSPEND_SECCOMP` | = warning: type error: expected u32, found i32 (breaking) +error: aborting due to 11 previous errors + From 41b5fcffca0e74eca06105e622eff09e058a6383 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 28 Mar 2018 20:13:14 +0200 Subject: [PATCH 324/553] Added private trait mapping facility. --- src/semcheck/mapping.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 608ed18b030d9..2e97e1bc2385e 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -42,6 +42,8 @@ pub struct IdMapping { non_mapped_items: HashSet, /// Trait items' old `DefId` mapped to old and new `Def`, and the enclosing trait's `DefId`. trait_item_mapping: HashMap, + /// The set of private traits in both crates. + private_traits: HashSet, /// Other items' old `DefId` mapped to new `DefId`. internal_mapping: HashMap, /// Children mapping, allowing us to enumerate descendants in `AdtDef`s. @@ -63,6 +65,7 @@ impl IdMapping { 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(), @@ -100,6 +103,11 @@ impl IdMapping { 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), @@ -202,6 +210,11 @@ impl IdMapping { 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) || From 9995570f1844d1272a8d23a3deebcc79319783e0 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 28 Mar 2018 20:26:05 +0200 Subject: [PATCH 325/553] Added private trait recognition. --- src/semcheck/traverse.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 9a8e30db7fd1a..f1933919bd41e 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -227,6 +227,16 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, // 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, @@ -483,6 +493,8 @@ fn diff_traits(changes: &mut ChangeSet, output: bool) { use rustc::hir::Unsafety::Unsafe; + 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; @@ -555,6 +567,8 @@ fn diff_generics(changes: &mut ChangeSet, use rustc::ty::Variance::*; use std::cmp::max; + debug!("diff_generics: old: {:?}, new: {:?}", old, new); + fn diff_variance<'tcx>(old_var: Variance, new_var: Variance) -> Option> { match (old_var, new_var) { (Covariant, Covariant) | From a78b9f41b14574be371219892f3d330b4d437012 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 30 Mar 2018 12:53:29 +0200 Subject: [PATCH 326/553] Fixed build with newest nightly. --- src/lib.rs | 1 - src/semcheck/translate.rs | 3 +-- src/semcheck/typeck.rs | 7 ++++--- tests/cases/regions/new.rs | 2 +- tests/cases/regions/old.rs | 4 ++-- tests/cases/regions/stdout | 4 ++-- 6 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index dc82cad64bb9e..711be90a44cb7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,3 @@ -#![feature(conservative_impl_trait)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index f8ca7319f3154..9db17d7d6d41d 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -2,7 +2,7 @@ //! comparison and inference. use rustc::hir::def_id::DefId; -use rustc::ty::{ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt, UniverseIndex}; +use rustc::ty::{ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt}; use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder}; use rustc::infer::InferCtxt; use rustc::ty::subst::Substs; @@ -441,7 +441,6 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { .map(|target_preds| ParamEnv { caller_bounds: self.tcx.intern_predicates(&target_preds), reveal: param_env.reveal, - universe: UniverseIndex::ROOT, }) } diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs index 4de9aa553b6b4..273b9e7da75d5 100644 --- a/src/semcheck/typeck.rs +++ b/src/semcheck/typeck.rs @@ -5,8 +5,9 @@ use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; -use rustc::traits::{FulfillmentContext, FulfillmentError, Obligation, ObligationCause}; -use rustc::ty::{ParamEnv, Predicate, TraitRef, Ty, TyCtxt, UniverseIndex}; +use rustc::traits::{FulfillmentContext, FulfillmentError, + Obligation, ObligationCause, TraitEngine}; +use rustc::ty::{ParamEnv, Predicate, TraitRef, Ty, TyCtxt}; use rustc::ty::error::TypeError; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::Substs; @@ -154,7 +155,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { if def.index == 0 && has_self { // `Self` is special self.infcx.tcx.mk_param_from_def(def) } else { - self.infcx.type_var_for_def(UniverseIndex::ROOT, DUMMY_SP, def) + self.infcx.type_var_for_def(DUMMY_SP, def) } }) } diff --git a/tests/cases/regions/new.rs b/tests/cases/regions/new.rs index b99ca05947923..c124198b04dd7 100644 --- a/tests/cases/regions/new.rs +++ b/tests/cases/regions/new.rs @@ -4,7 +4,7 @@ pub type B = for<'a> fn(&'a bool); pub type C<'a, 'b> = (&'b u8, &'a u16); -pub type D = T::IntoIter; +pub type D = ::IntoIter; pub type E = T; diff --git a/tests/cases/regions/old.rs b/tests/cases/regions/old.rs index 494ba7e6cc273..cd69b7b2ebe83 100644 --- a/tests/cases/regions/old.rs +++ b/tests/cases/regions/old.rs @@ -4,9 +4,9 @@ pub type B = fn(&bool); pub type C<'a, 'b> = (&'a u8, &'b u16); -pub type D = T::Item; +pub type D = ::Item; -pub type E = T::Item; +pub type E = ::Item; pub fn abc(_: bool) { } diff --git a/tests/cases/regions/stdout b/tests/cases/regions/stdout index d128cea097596..04f464969575d 100644 --- a/tests/cases/regions/stdout +++ b/tests/cases/regions/stdout @@ -2,8 +2,8 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: breaking changes in `D` --> $REPO_PATH/tests/cases/regions/new.rs:7:1 | -7 | pub type D = T::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +7 | pub type D = ::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: type error: expected std::iter::IntoIterator::Item, found std::iter::IntoIterator::IntoIter (breaking) From b7e5394930bb0978b14e80e34c85cd2244bd21ff Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 30 Mar 2018 14:39:12 +0200 Subject: [PATCH 327/553] Version bump and dependency updates. --- Cargo.toml | 12 +++++------ src/bin/cargo_semver.rs | 44 ++++++++++++++++++++++++++++++----------- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 549b34e0be8b5..7cbec1384c90d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.6" +version = "0.1.7" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" @@ -24,11 +24,11 @@ name = "rust-semverver" path = "src/bin/rust_semverver.rs" [dependencies] -cargo = "0.24" -crates-io = "0.13" -env_logger = "0.5" -log = "0.4" -semver = "0.9" +cargo = "^0.25" +crates-io = "^0.14" +env_logger = "^0.5" +log = "^0.4" +semver = "^0.9" [dev-dependencies] quickcheck = "0.6" diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index f72fc7eb537fb..681d8e4da680a 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -20,10 +20,28 @@ use cargo::util::important_paths::find_root_manifest_for_wd; use getopts::{Matches, Options}; use std::env; +use std::error; +use std::fmt; use std::io::Write; use std::path::PathBuf; use std::process::{Stdio, Command}; +/// Very simple error representation. +#[derive(Debug)] +struct Error(String); + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "{}", self.0) + } +} + +impl error::Error for Error { + fn description(&self) -> &str { + &self.0 + } +} + /// Given a crate name, try to locate the corresponding crate on `crates.io`. /// /// If no crate with the exact name is present, error out. @@ -33,12 +51,14 @@ fn exact_search(query: &str) -> CargoResult { registry .search(query, 1) .map_err(|e| - format!("failed to retrieve search results from the registry: {}", e).into()) + Error(format!("failed to retrieve search results from the registry: {}", e)) + .into()) .and_then(|(mut crates, _)| { crates .drain(..) .find(|krate| krate.name == query) - .ok_or_else(|| format!("failed to find a matching crate `{}`", query).into()) + .ok_or_else(|| Error(format!("failed to find a matching crate `{}`", query)) + .into()) }) } @@ -133,7 +153,7 @@ impl<'a> WorkInfo<'a> { let rlib = compilation.libraries[self.package.package_id()] .iter() .find(|t| t.0.name() == name) - .ok_or_else(|| "lost a build artifact")?; + .ok_or_else(|| Error("lost a build artifact".to_owned()))?; Ok((rlib.1.clone(), compilation.deps_output)) } @@ -152,16 +172,16 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { let name = if let Some(n) = split.next() { n } else { - return Err("spec has to be of form `name:version`".into()); + return Err(Error("spec has to be of form `name:version`".to_owned()).into()); }; let version = if let Some(v) = split.next() { v } else { - return Err("spec has to be of form `name:version`".into()); + return Err(Error("spec has to be of form `name:version`".to_owned()).into()); }; if split.next().is_some() { - return Err("spec has to be of form `name:version`".into()); + return Err(Error("spec has to be of form `name:version`".to_owned()).into()); } Ok(NameAndVersion { name: name, version: version }) @@ -220,7 +240,7 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { .stdin(Stdio::piped()) .env("RUST_SEMVER_CRATE_VERSION", stable_version) .spawn() - .map_err(|e| format!("could not spawn rustc: {}", e))?; + .map_err(|e| Error(format!("could not spawn rustc: {}", e)))?; if let Some(ref mut stdin) = child.stdin { stdin.write_fmt(format_args!("#[allow(unused_extern_crates)] \ @@ -228,12 +248,12 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { #[allow(unused_extern_crates)] \ extern crate old;"))?; } else { - return Err("could not pipe to rustc (wtf?)".into()); + return Err(Error("could not pipe to rustc (wtf?)".to_owned()).into()); } child .wait() - .map_err(|e| format!("failed to wait for rustc: {}", e))?; + .map_err(|e| Error(format!("failed to wait for rustc: {}", e)))?; Ok(()) } @@ -282,7 +302,7 @@ fn main() { let matches = match opts.parse(&args) { Ok(m) => m, - Err(f) => err(&config, f.to_string().into()), + Err(f) => err(&config, f.to_owned().into()), }; if matches.opt_present("h") { @@ -299,14 +319,14 @@ fn main() { matches.opt_count("s") > 1 || matches.opt_count("S") > 1 { let msg = "at most one of `-s,--stable-path` and `-S,--stable-pkg` allowed"; - err(&config, msg.into()); + err(&config, Error(msg.to_owned()).into()); } 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"; - err(&config, msg.into()); + err(&config, Error(msg.to_owned()).into()); } if let Err(e) = do_main(&config, &matches) { From acfb0b7feeb4a255e832e941fc8e99ce57d00f6a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 30 Mar 2018 16:45:49 +0200 Subject: [PATCH 328/553] Implemented sealed trait handling. Closes #51. --- src/semcheck/changes.rs | 29 ++++++++++++++++---------- src/semcheck/traverse.rs | 35 ++++++++++++++++++++++++++++++-- tests/cases/sealed_traits/new.rs | 7 +++++++ tests/cases/sealed_traits/old.rs | 5 +++++ tests/cases/sealed_traits/stdout | 15 ++++++++++++++ tests/examples.rs | 1 + 6 files changed, 79 insertions(+), 13 deletions(-) create mode 100644 tests/cases/sealed_traits/new.rs create mode 100644 tests/cases/sealed_traits/old.rs create mode 100644 tests/cases/sealed_traits/stdout diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 63880184c60bb..2a1f28ab8af14 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -243,7 +243,7 @@ pub enum ChangeType<'tcx> { /// 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 }, + 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. @@ -294,7 +294,7 @@ impl<'tcx> ChangeType<'tcx> { TypeChanged { .. } | FnConstChanged { now_const: false } | MethodSelfChanged { now_self: false } | - TraitItemAdded { defaulted: false } | + TraitItemAdded { defaulted: false, sealed_trait: false } | TraitItemRemoved { .. } | TraitUnsafetyChanged { .. } | BoundsTightened { .. } | @@ -303,7 +303,7 @@ impl<'tcx> ChangeType<'tcx> { AssociatedItemRemoved | Unknown => Breaking, MethodSelfChanged { now_self: true } | - TraitItemAdded { defaulted: true } | + TraitItemAdded { .. } | // either defaulted or sealed BoundsLoosened { trait_def: false, .. } | TraitImplLoosened | AssociatedItemAdded | @@ -388,12 +388,16 @@ 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 } => + 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 { defaulted: false } => + 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 { .. } => @@ -488,8 +492,11 @@ impl<'a> fmt::Display for ChangeType<'a> { 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 } => "added item to trait", + 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", @@ -888,7 +895,7 @@ pub mod tests { VariantStyleChanged { now_struct: bool, total_private: bool }, FnConstChanged { now_const: bool }, MethodSelfChanged { now_self: bool }, - TraitItemAdded { defaulted: bool }, + TraitItemAdded { defaulted: bool, sealed_trait: bool }, TraitItemRemoved { defaulted: bool }, TraitUnsafetyChanged { now_unsafe: bool }, Unknown, @@ -918,8 +925,8 @@ pub mod tests { FnConstChanged { now_const }, ChangeType_::MethodSelfChanged { now_self } => MethodSelfChanged { now_self }, - ChangeType_::TraitItemAdded { defaulted } => - TraitItemAdded { defaulted }, + ChangeType_::TraitItemAdded { defaulted, sealed_trait } => + TraitItemAdded { defaulted, sealed_trait }, ChangeType_::TraitItemRemoved { defaulted } => TraitItemRemoved { defaulted }, ChangeType_::TraitUnsafetyChanged { now_unsafe } => @@ -950,7 +957,7 @@ pub mod tests { VariantStyleChanged { now_struct: b1, total_private: b2 }, FnConstChanged { now_const: b1 }, MethodSelfChanged { now_self: b1 }, - TraitItemAdded { defaulted: b1 }, + TraitItemAdded { defaulted: b1, sealed_trait: b2 }, TraitItemRemoved { defaulted: b1 }, TraitUnsafetyChanged { now_unsafe: b1 }, Unknown]).unwrap().clone() diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index f1933919bd41e..d3fe648b383f7 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -88,6 +88,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, 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. @@ -243,12 +244,13 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, false, o_def_id, n_def_id); - diff_traits(changes, + traits.push((o_def_id, n_def_id, output)); + /* diff_traits(changes, id_mapping, tcx, o_def_id, n_def_id, - output); + output); */ }, // a non-matching item pair - register the change and abort further // analysis of it @@ -314,6 +316,10 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, 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. @@ -492,6 +498,8 @@ fn diff_traits(changes: &mut ChangeSet, new: DefId, output: bool) { use rustc::hir::Unsafety::Unsafe; + use rustc::ty::subst::UnpackedKind::Type; + use rustc::ty::{ParamTy, Predicate, TyS, TypeVariants::*}; debug!("diff_traits: old: {:?}, new: {:?}, output: {:?}", old, new, output); @@ -506,6 +514,28 @@ fn diff_traits(changes: &mut ChangeSet, 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 { + match *bound { + Predicate::Trait(pred) => { + 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 { sty: TyParam(ParamTy { idx: 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() { @@ -547,6 +577,7 @@ fn diff_traits(changes: &mut ChangeSet, (None, Some((_, new_item))) => { let change_type = 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); diff --git a/tests/cases/sealed_traits/new.rs b/tests/cases/sealed_traits/new.rs new file mode 100644 index 0000000000000..0b12d071f7d50 --- /dev/null +++ b/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/tests/cases/sealed_traits/old.rs b/tests/cases/sealed_traits/old.rs new file mode 100644 index 0000000000000..7df0fde4e799d --- /dev/null +++ b/tests/cases/sealed_traits/old.rs @@ -0,0 +1,5 @@ +pub trait PublicTrait : private::PrivateTrait { } + +mod private { + pub trait PrivateTrait { } +} diff --git a/tests/cases/sealed_traits/stdout b/tests/cases/sealed_traits/stdout new file mode 100644 index 0000000000000..87b33459f55a5 --- /dev/null +++ b/tests/cases/sealed_traits/stdout @@ -0,0 +1,15 @@ +version bump: 1.0.0 -> (technically breaking) -> 1.1.0 +warning: technically breaking changes in `PublicTrait` + --> $REPO_PATH/tests/cases/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) + --> $REPO_PATH/tests/cases/sealed_traits/new.rs:2:5 + | +2 | fn abc(&self) -> bool; + | ^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/examples.rs b/tests/examples.rs index 11587fe0c280a..804cfc747dead 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -121,6 +121,7 @@ test!(regions); test!(removal); test!(removal_path); test!(removal_use); +test!(sealed_traits); test!(structs); test!(swap); test!(traits); From 54c529dd744844a05f6b95096d945e7eda22f06c Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 30 Mar 2018 16:55:13 +0200 Subject: [PATCH 329/553] Version bump. --- Cargo.toml | 2 +- README.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 7cbec1384c90d..52b70f82746e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.7" +version = "0.1.8" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" diff --git a/README.md b/README.md index 9e2570c8d2148..ecd80180b76d6 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,7 @@ correctly: * 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 From b6bf991980dc3c7ab196adaa01c3f5a5d3b491c4 Mon Sep 17 00:00:00 2001 From: Andrew Shu Date: Sun, 8 Apr 2018 21:58:28 -0700 Subject: [PATCH 330/553] Fix install command typo in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ecd80180b76d6..f50b7749937c3 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ If you have built using `cargo build --release` instead, change the path to poin You can also install the (possibly more stable) version of the tool from crates.io: ```sh -$ cargo install +nightly semverver +$ cargo +nightly install semverver ``` ## Usage From d446eaf802bf56d051010692cc1403009696cbb4 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 9 Apr 2018 21:37:42 +0200 Subject: [PATCH 331/553] Added an appveyor configuration. --- appveyor.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000000000..8d1d2144e80c4 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,24 @@ +environment: + matrix: + - TARGET: x86_64-pc-windows-msvc + OTHER_TARGET: i686-pc-windows-msvc + +install: + - set PATH=C:\Program Files\Git\mingw64\bin;%PATH% + - curl -sSf -o rustup-init.exe https://win.rustup.rs/ + - rustup-init.exe -y --default-host %TARGET% --default-toolchain nightly + - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin;C:\Users\appveyor\.rustup\toolchains\nightly-%TARGET%\bin + - if defined MSYS2_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS2_BITS%\bin + - rustc -V + - cargo -V + +build: false + +test_script: + - set RUST_BACKTRACE=full + - cargo build + - cargo test --verbose + +notifications: + - provider: Email + on_build_success: false From 873b53f0c8dd0ff3691cd0cd83ebdda5e3e7c411 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 10 Apr 2018 13:15:39 +0200 Subject: [PATCH 332/553] Skip full tests on windows. --- tests/full.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/full.rs b/tests/full.rs index 723933bf10c91..ed1bdde3b3f2f 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -1,11 +1,13 @@ use std::env; use std::fs::File; +#[cfg(not(windows))] use std::os::unix::io::{AsRawFd, FromRawFd}; use std::path::Path; use std::process::{Command, Stdio}; macro_rules! full_test { ($name:ident, $crate_name:expr, $old_version:expr, $new_version:expr) => { + #[cfg(not(windows))] #[test] fn $name() { let mut success = true; From 9d83cae89cae7337bf476b50068c74e2df9e7900 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 10 Apr 2018 13:45:12 +0200 Subject: [PATCH 333/553] Restructured test hierarchy a bit. --- tests/examples.rs | 244 +++++++++++++++++++++++----------------------- tests/full.rs | 189 +++++++++++++++++------------------ 2 files changed, 218 insertions(+), 215 deletions(-) diff --git a/tests/examples.rs b/tests/examples.rs index 804cfc747dead..4434674b5b6d2 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -1,130 +1,132 @@ -use std::env; -use std::fs::File; -use std::os::unix::io::{AsRawFd, FromRawFd}; -use std::path::Path; -use std::process::{Command, Stdio}; - -macro_rules! test { - ($name:ident) => { - #[test] - fn $name() { - let mut success = true; - - let current_dir = env::current_dir().expect("could not determine current dir"); - let subst = format!("s#{}#$REPO_PATH#g", current_dir.to_str().unwrap()); - let path = Path::new("tests/cases").join(stringify!($name)); - - let out_file = path.join("stdout"); - - 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 stdout = File::create(&out_file).expect("could not create `stdout` file"); - - success &= Command::new("rustc") - .args(&["--crate-type=lib", "-o", &old_rlib]) - .arg(path.join("old.rs")) - .env("RUST_BACKTRACE", "full") - .stdin(Stdio::null()) +mod features { + use std::env; + use std::fs::File; + use std::os::unix::io::{AsRawFd, FromRawFd}; + use std::path::Path; + use std::process::{Command, Stdio}; + + macro_rules! test { + ($name:ident) => { + #[test] + fn $name() { + let mut success = true; + + let current_dir = env::current_dir().expect("could not determine current dir"); + let subst = format!("s#{}#$REPO_PATH#g", current_dir.to_str().unwrap()); + let path = Path::new("tests/cases").join(stringify!($name)); + + let out_file = path.join("stdout"); + + 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 stdout = File::create(&out_file).expect("could not create `stdout` file"); + + success &= Command::new("rustc") + .args(&["--crate-type=lib", "-o", &old_rlib]) + .arg(path.join("old.rs")) + .env("RUST_BACKTRACE", "full") + .stdin(Stdio::null()) + .status() + .expect("could not run rustc") + .success(); + + assert!(success, "couldn't compile old"); + + success &= Command::new("rustc") + .args(&["--crate-type=lib", "-o", &new_rlib]) + .arg(path.join("new.rs")) + .env("RUST_BACKTRACE", "full") + .stdin(Stdio::null()) + .status() + .expect("could not run rustc") + .success(); + + assert!(success, "couldn't compile new"); + + let mut sed_child = Command::new("sed") + .arg(&subst) + .stdin(Stdio::piped()) + .stdout(stdout) + .spawn() + .expect("could not run sed"); + + let (err_pipe, out_pipe) = if let Some(ref stdin) = sed_child.stdin { + let fd = stdin.as_raw_fd(); + unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } + } else { + panic!("could not pipe to sed"); + }; + + success &= Command::new("./target/debug/rust-semverver") + .args(&["--crate-type=lib", "-Zverbose", + "--extern", &format!("old={}", old_rlib), + "--extern", &format!("new={}", new_rlib), + "tests/helper/test.rs"]) + .env("RUST_BACKTRACE", "full") + .env("RUST_SEMVER_CRATE_VERSION", "1.0.0") + .stdin(Stdio::null()) + .stdout(out_pipe) + .stderr(err_pipe) + .status() + .expect("could not run rust-semverver") + .success(); + + assert!(success, "rust-semverver"); + + success &= sed_child.wait().expect("could not wait for sed child").success(); + } + + assert!(success, "sed"); + + eprintln!("path: {}", out_file.to_str().unwrap()); + success &= Command::new("git") + .args(&["diff", "--exit-code", out_file.to_str().unwrap()]) + .env("PAGER", "") .status() - .expect("could not run rustc") + .expect("could not run git diff") .success(); - assert!(success, "couldn't compile old"); + assert!(success, "git"); - success &= Command::new("rustc") - .args(&["--crate-type=lib", "-o", &new_rlib]) - .arg(path.join("new.rs")) - .env("RUST_BACKTRACE", "full") - .stdin(Stdio::null()) + Command::new("rm") + .args(&[&old_rlib, &new_rlib]) .status() - .expect("could not run rustc") - .success(); - - assert!(success, "couldn't compile new"); - - let mut sed_child = Command::new("sed") - .arg(&subst) - .stdin(Stdio::piped()) - .stdout(stdout) - .spawn() - .expect("could not run sed"); - - let (err_pipe, out_pipe) = if let Some(ref stdin) = sed_child.stdin { - let fd = stdin.as_raw_fd(); - unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } - } else { - panic!("could not pipe to sed"); - }; - - success &= Command::new("./target/debug/rust-semverver") - .args(&["--crate-type=lib", "-Zverbose", - "--extern", &format!("old={}", old_rlib), - "--extern", &format!("new={}", new_rlib), - "tests/helper/test.rs"]) - .env("RUST_BACKTRACE", "full") - .env("RUST_SEMVER_CRATE_VERSION", "1.0.0") - .stdin(Stdio::null()) - .stdout(out_pipe) - .stderr(err_pipe) - .status() - .expect("could not run rust-semverver") - .success(); - - assert!(success, "rust-semverver"); - - success &= sed_child.wait().expect("could not wait for sed child").success(); + .expect("could not run rm"); } - - assert!(success, "sed"); - - eprintln!("path: {}", out_file.to_str().unwrap()); - success &= Command::new("git") - .args(&["diff", "--exit-code", out_file.to_str().unwrap()]) - .env("PAGER", "") - .status() - .expect("could not run git diff") - .success(); - - assert!(success, "git"); - - Command::new("rm") - .args(&[&old_rlib, &new_rlib]) - .status() - .expect("could not run rm"); } } -} -test!(addition); -test!(addition_path); -test!(addition_use); -test!(bounds); -test!(circular); -test!(consts); -test!(enums); -test!(func); -test!(func_local_items); -test!(infer); -test!(infer_regress); -test!(inherent_impls); -test!(issue_34); -test!(issue_50); -test!(kind_change); -test!(macros); -test!(max_priv); -test!(mix); -test!(pathologic_paths); -test!(pub_use); -test!(regions); -test!(removal); -test!(removal_path); -test!(removal_use); -test!(sealed_traits); -test!(structs); -test!(swap); -test!(traits); -test!(trait_impls); -test!(trait_objects); -test!(ty_alias); + test!(addition); + test!(addition_path); + test!(addition_use); + test!(bounds); + test!(circular); + test!(consts); + test!(enums); + test!(func); + test!(func_local_items); + test!(infer); + test!(infer_regress); + test!(inherent_impls); + test!(issue_34); + test!(issue_50); + test!(kind_change); + test!(macros); + test!(max_priv); + test!(mix); + test!(pathologic_paths); + test!(pub_use); + test!(regions); + test!(removal); + test!(removal_path); + test!(removal_use); + test!(sealed_traits); + test!(structs); + test!(swap); + test!(traits); + test!(trait_impls); + test!(trait_objects); + test!(ty_alias); +} diff --git a/tests/full.rs b/tests/full.rs index ed1bdde3b3f2f..3b2218d38ef5b 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -1,100 +1,101 @@ -use std::env; -use std::fs::File; -#[cfg(not(windows))] -use std::os::unix::io::{AsRawFd, FromRawFd}; -use std::path::Path; -use std::process::{Command, Stdio}; - -macro_rules! full_test { - ($name:ident, $crate_name:expr, $old_version:expr, $new_version:expr) => { - #[cfg(not(windows))] - #[test] - fn $name() { - let mut success = true; - - let old_version = concat!($crate_name, ":", $old_version); - let new_version = concat!($crate_name, ":", $new_version); - - let prog = concat!(r#" -# wait for the actual output -/^version bump/ { - doprint = 1; -} - -{ - # check the environ for filtering - if (ENVIRON["RUST_LOG"] == "debug") +#[cfg(not(target_os = "windows"))] +mod full { + use std::env; + use std::fs::File; + use std::os::unix::io::{AsRawFd, FromRawFd}; + use std::path::Path; + use std::process::{Command, Stdio}; + + macro_rules! full_test { + ($name:ident, $crate_name:expr, $old_version:expr, $new_version:expr) => { + #[test] + fn $name() { + let mut success = true; + + let old_version = concat!($crate_name, ":", $old_version); + let new_version = concat!($crate_name, ":", $new_version); + + let prog = concat!(r#" + # wait for the actual output + /^version bump/ { doprint = 1; + } - # skip compilation info - if (!doprint) - next; - - # sanitize paths - gsub(/-->.*"#, $crate_name, r#"/, "--> "#, $crate_name, r#"", $0); - print; -}"#, $crate_name, $crate_name); - let out_file = Path::new("tests/full_cases") - .join(concat!($crate_name, "-", $old_version, "-", $new_version)); - - if let Some(path) = env::var_os("PATH") { - let mut paths = env::split_paths(&path).collect::>(); - let current_dir = env::current_dir().expect("could not determine current dir"); - paths.insert(0, current_dir.join("target/debug")); - let new_path = env::join_paths(paths).unwrap(); - env::set_var("PATH", &new_path); - } else { - eprintln!("no path!"); + { + # check the environ for filtering + if (ENVIRON["RUST_LOG"] == "debug") + doprint = 1; + + # skip compilation info + if (!doprint) + next; + + # sanitize paths + gsub(/-->.*"#, $crate_name, r#"/, "--> "#, $crate_name, r#"", $0); + print; + }"#, $crate_name, $crate_name); + let out_file = Path::new("tests/full_cases") + .join(concat!($crate_name, "-", $old_version, "-", $new_version)); + + if let Some(path) = env::var_os("PATH") { + let mut paths = env::split_paths(&path).collect::>(); + let current_dir = env::current_dir().expect("could not determine current dir"); + paths.insert(0, current_dir.join("target/debug")); + let new_path = env::join_paths(paths).unwrap(); + env::set_var("PATH", &new_path); + } else { + eprintln!("no path!"); + } + + let stdout = File::create(&out_file).expect("could not create `stdout` file"); + let out_file = out_file.to_str().unwrap(); + + let mut awk_child = Command::new("awk") + .arg(&prog) + .stdin(Stdio::piped()) + .stdout(stdout) + .spawn() + .expect("could not run awk"); + + let (err_pipe, out_pipe) = if let Some(ref stdin) = awk_child.stdin { + let fd = stdin.as_raw_fd(); + unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } + } else { + panic!("could not pipe to awk"); + }; + + success &= Command::new("./target/debug/cargo-semver") + .args(&["-S", &old_version, "-C", &new_version]) + .env("RUST_BACKTRACE", "full") + .stdin(Stdio::null()) + .stdout(out_pipe) + .stderr(err_pipe) + .status() + .expect("could not run cargo semver") + .success(); + + assert!(success, "cargo semver"); + + success &= awk_child.wait().expect("could not wait for awk child").success(); + + assert!(success, "awk"); + + success &= Command::new("git") + .args(&["diff", "--exit-code", out_file]) + .env("PAGER", "") + .status() + .expect("could not run git diff") + .success(); + + assert!(success, "git"); } - - let stdout = File::create(&out_file).expect("could not create `stdout` file"); - let out_file = out_file.to_str().unwrap(); - - let mut awk_child = Command::new("awk") - .arg(&prog) - .stdin(Stdio::piped()) - .stdout(stdout) - .spawn() - .expect("could not run awk"); - - let (err_pipe, out_pipe) = if let Some(ref stdin) = awk_child.stdin { - let fd = stdin.as_raw_fd(); - unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } - } else { - panic!("could not pipe to awk"); - }; - - success &= Command::new("./target/debug/cargo-semver") - .args(&["-S", &old_version, "-C", &new_version]) - .env("RUST_BACKTRACE", "full") - .stdin(Stdio::null()) - .stdout(out_pipe) - .stderr(err_pipe) - .status() - .expect("could not run cargo semver") - .success(); - - assert!(success, "cargo semver"); - - success &= awk_child.wait().expect("could not wait for awk child").success(); - - assert!(success, "awk"); - - success &= Command::new("git") - .args(&["diff", "--exit-code", out_file]) - .env("PAGER", "") - .status() - .expect("could not run git diff") - .success(); - - assert!(success, "git"); } } -} -full_test!(log, "log", "0.3.4", "0.3.8"); -full_test!(libc, "libc", "0.2.28", "0.2.31"); -// 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"); + full_test!(log, "log", "0.3.4", "0.3.8"); + full_test!(libc, "libc", "0.2.28", "0.2.31"); + // 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"); +} From 449125821b627797aa3b2992de9139c733e940e0 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 10 Apr 2018 16:52:30 +0200 Subject: [PATCH 334/553] Disabled all example tests on windows for now. --- appveyor.yml | 2 +- tests/examples.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 8d1d2144e80c4..cff738be149d7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,7 +17,7 @@ build: false test_script: - set RUST_BACKTRACE=full - cargo build - - cargo test --verbose +# - cargo test --verbose notifications: - provider: Email diff --git a/tests/examples.rs b/tests/examples.rs index 4434674b5b6d2..3293d042b25b7 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -1,3 +1,4 @@ +#[cfg(not(target_os = "windows"))] mod features { use std::env; use std::fs::File; From 2eb587d2a93cb2dd53b9b7ce5fc73c0d8053305c Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 11 Apr 2018 11:23:32 +0200 Subject: [PATCH 335/553] Added AppVeyor badge to README and Cargo.toml. --- Cargo.toml | 1 + README.md | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 52b70f82746e1..1607ae89f098c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ license-file = "LICENSE" [badges] travis-ci = { repository = "rust-lang-nursery/rust-semverver" } +appveyor = { repository = "rust-lang-nursery/rust-semverver" } [[bin]] name = "cargo-semver" diff --git a/README.md b/README.md index f50b7749937c3..97587b4ecfd7e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # rust-semverver -[![Build -Status](https://travis-ci.org/rust-lang-nursery/rust-semverver.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rust-semverver) +[![Travis Build Status](https://travis-ci.org/rust-lang-nursery/rust-semverver.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/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) This repository is hosting a proof-of-concept implementation of an automatic tool checking From f59f47886187dc05fedad65847476c5f8a2c1cbb Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 11 Apr 2018 18:15:21 +0200 Subject: [PATCH 336/553] Updated README. --- README.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 97587b4ecfd7e..7d06c0f6c70fc 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,16 @@ repository and compiled from source. If you are already using Rust nightly and have successfully installed tools like `cargo add` and `cargo clippy`, just do: +```sh +$ cargo +nightly install semverver +``` + +You'd also need `cmake` for some dependencies, and a few common libraries (if I 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 $ cargo +nightly install --git https://github.com/rust-lang-nursery/rust-semverver ``` @@ -64,12 +74,6 @@ If you have built using `cargo build --release` instead, change the path to poin
-You can also install the (possibly more stable) version of the tool from crates.io: - -```sh -$ cargo +nightly install semverver -``` - ## Usage By default, running `cargo semver` in directory with a Cargo project will try to compare From 64780e88b33f11f132a8b87a75bf83fe4f1432c1 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 18 Apr 2018 21:51:45 +0200 Subject: [PATCH 337/553] Better long error descriptions. --- src/semcheck/changes.rs | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 2a1f28ab8af14..aa2ec5db34d76 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -288,7 +288,7 @@ impl<'tcx> ChangeType<'tcx> { TypeParameterRemoved { .. } | VariantAdded | VariantRemoved | - VariantFieldAdded { .. } | + VariantFieldAdded { .. } | // TODO: this (and the two below) appear wrong VariantFieldRemoved { .. } | VariantStyleChanged { .. } | TypeChanged { .. } | @@ -317,7 +317,6 @@ impl<'tcx> ChangeType<'tcx> { /// Get a detailed explanation of a change, and why it is categorized as-is. fn explanation(&self) -> &'static str { - // TODO: meaningful explanations match *self { ItemMadePublic => "Adding an item to a module's public interface is generally a non-breaking @@ -341,11 +340,16 @@ user code that tries to mutate them will break.", VarianceTightened => "The variance of a type or region parameter in an item tightens iff .", VarianceChanged { .. } => -"Switching the variance of a type or region parameter is breaking. ", +"Switching the variance of a type or region parameter is breaking, if it goes +from covariant to contravariant, or vice-versa.", RegionParameterAdded => -"Adding a new region parameter is a breaking change. .", +"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. .", +"Removing a region parameter is a breaking change, because it can break +explicit type annotations, 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 @@ -365,9 +369,12 @@ on said enum can become non-exhaustive.", "Removing an enum variant is a braking change, because every old reference to the removed variant is rendered invalid.", VariantFieldAdded { public: _, total_public: _ } => -"Adding a field from a variant: .", +"Adding a field to an enum variant is breaking, as matches on the variant are +invalidated. In case of structs, this only holds for public fields, or the +first private field being added.", VariantFieldRemoved { public: _, total_public: _ } => -"Removing a field from a variant: .", +"Removing a field from an enum variant 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 @@ -432,10 +439,12 @@ 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 associated item is a breaking change in some specific -situations, .", +"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 associated item is a breaking change, as all old +"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.", } From ffa3f92ed57be25601b83b2dd670e8fcf921bbd5 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 18 Apr 2018 22:02:24 +0200 Subject: [PATCH 338/553] Identified some places where issues might arise. --- src/semcheck/translate.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 9db17d7d6d41d..8b6cfa71df725 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -151,18 +151,8 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { orig.fold_with(&mut BottomUpFolder { tcx: self.tcx, fldop: |ty| { match ty.sty { TyAdt(&AdtDef { ref did, .. }, substs) if self.needs_translation(*did) => { - /* if let Some((target_def_id, target_substs)) = - self.translate_orig_substs(index_map, *did, substs) - { - let target_adt = self.tcx.adt_def(target_def_id); - self.tcx.mk_adt(target_adt, target_substs) - } else { - ty - } */ - // we fold bottom-up, so the code above is invalid, as it assumes the // substs (that have been folded already) are yet untranslated - // TODO: fix other places as well? 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) @@ -174,6 +164,8 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { self.tcx.mk_ref(self.translate_region(region), type_and_mut) }, TyFnDef(did, substs) => { + // TODO: this might be buggy as *technically* the substs are + // already translated (see TyAdt for a possible fix) if let Some((target_def_id, target_substs)) = self.translate_orig_substs(index_map, did, substs) { @@ -198,6 +190,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { 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) { @@ -219,6 +212,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { 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) { From 597b9517e70ca22b1b96b2afb34a7ce6718d8881 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 19 Apr 2018 09:05:18 +0200 Subject: [PATCH 339/553] Properly implemented verbose error messages. --- src/bin/cargo_semver.rs | 6 ++++-- src/bin/rust_semverver.rs | 16 +++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 681d8e4da680a..de477651a0ac2 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -165,7 +165,7 @@ impl<'a> WorkInfo<'a> { /// Obtain the two versions of the crate to be analyzed as specified by command line arguments /// and/or defaults, and dispatch the actual analysis. // TODO: possibly reduce the complexity by finding where some info can be taken from directly -fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { +fn do_main(config: &Config, matches: &Matches, explain: bool) -> CargoResult<()> { debug!("running cargo-semver"); fn parse_arg(opt: &str) -> CargoResult { let mut split = opt.split(':'); @@ -239,6 +239,7 @@ fn do_main(config: &Config, matches: &Matches) -> CargoResult<()> { .arg("-") .stdin(Stdio::piped()) .env("RUST_SEMVER_CRATE_VERSION", stable_version) + .env("RUST_SEMVER_VERBOSE", format!("{}", explain)) .spawn() .map_err(|e| Error(format!("could not spawn rustc: {}", e)))?; @@ -287,6 +288,7 @@ fn main() { 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("d", "debug", "print command to debug and exit"); 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"); @@ -329,7 +331,7 @@ fn main() { err(&config, Error(msg.to_owned()).into()); } - if let Err(e) = do_main(&config, &matches) { + if let Err(e) = do_main(&config, &matches, matches.opt_present("e")) { err(&config, e); } } diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 1e120c0a7d5cb..6dc3fc6ea4100 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -75,14 +75,17 @@ struct SemVerVerCompilerCalls { default: RustcDefaultCalls, /// The version of the old crate. version: String, + /// The output mode. + verbose: bool, } impl SemVerVerCompilerCalls { /// Construct a new compilation wrapper, given a version string. - pub fn new(version: String) -> SemVerVerCompilerCalls { + pub fn new(version: String, verbose: bool) -> SemVerVerCompilerCalls { SemVerVerCompilerCalls { default: RustcDefaultCalls, - version: version, + version, + verbose, } } } @@ -135,10 +138,7 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { let old_callback = std::mem::replace(&mut controller.after_analysis.callback, box |_| {}); let version = self.version.clone(); - - let verbose = std::env::var("RUST_SEMVER_VERBOSE") - .ok() - .map_or(false, |s| s == "true"); + let verbose = self.verbose; controller.after_analysis.callback = box move |state| { debug!("running rust-semverver after_analysis callback"); @@ -197,7 +197,9 @@ fn main() { "no_version".to_owned() }; - let mut cc = SemVerVerCompilerCalls::new(version); + let verbose = std::env::var("RUST_SEMVER_VERBOSE") == Ok("true".to_string()); + + let mut cc = SemVerVerCompilerCalls::new(version, verbose); rustc_driver::run_compiler(&args, &mut cc, None, None) }); From 67978815ecb44a69e17f01e13f79d01d709dabb9 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 19 Apr 2018 09:08:17 +0200 Subject: [PATCH 340/553] Updated README. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7d06c0f6c70fc..9967a6f87a62a 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,7 @@ usage: cargo semver [options] [-- cargo options] Options: -h, --help print this message and exit -V, --version print version information and exit + -e, --explain print detailed error explanations -d, --debug print command to debug and exit -s, --stable-path PATH use local path as stable/old crate From 6bdc37434c2d8eb1a433f23b81fa991c8ac6eec7 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 19 Apr 2018 10:21:25 +0200 Subject: [PATCH 341/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 1607ae89f098c..7bebfb8ff4994 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.8" +version = "0.1.9" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From db38db14bdf9ca80c9218a9d597f965c0446135c Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 28 Apr 2018 01:19:39 +0200 Subject: [PATCH 342/553] Fixed build with newest nightly. --- src/semcheck/mismatch.rs | 7 ++++--- src/semcheck/translate.rs | 26 ++++++++++++++++---------- src/semcheck/typeck.rs | 2 +- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 2079400bb9fc8..d208ef8789126 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -180,8 +180,9 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, let _ = self.relate(&a_r, &b_r)?; match (a_obj.principal(), b_obj.principal()) { - (Some(a), Some(b)) if self.check_substs(a.0.substs, b.0.substs) => { - let _ = self.relate(&a.0.substs, &b.0.substs)?; + (Some(a), Some(b)) if self.check_substs(a.skip_binder().substs, + b.skip_binder().substs) => { + let _ = self.relate(&a.skip_binder().substs, &b.skip_binder().substs)?; Some((a.skip_binder().def_id, b.skip_binder().def_id)) }, _ => None, @@ -232,6 +233,6 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, fn binders>(&mut self, a: &ty::Binder, b: &ty::Binder) -> RelateResult<'tcx, ty::Binder> { - Ok(ty::Binder(self.relate(a.skip_binder(), b.skip_binder())?)) + Ok(ty::Binder::bind(self.relate(a.skip_binder(), b.skip_binder())?)) } } diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 8b6cfa71df725..20492cfa18adc 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -185,7 +185,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { let res: Vec<_> = preds.iter().map(|p| { match *p.skip_binder() { Trait(existential_trait_ref) => { - let trait_ref = Binder(existential_trait_ref) + let trait_ref = Binder::bind(existential_trait_ref) .with_self_ty(self.tcx, self.tcx.types.err); let did = trait_ref.skip_binder().def_id; let substs = trait_ref.skip_binder().substs; @@ -206,7 +206,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { } }, Projection(existential_projection) => { - let projection_pred = Binder(existential_projection) + let projection_pred = Binder::bind(existential_projection) .with_self_ty(self.tcx, self.tcx.types.err); let item_def_id = projection_pred.skip_binder().projection_ty.item_def_id; @@ -235,7 +235,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { if success.get() { let target_preds = self.tcx.mk_existential_predicates(res.iter()); - self.tcx.mk_dynamic(Binder(target_preds), region) + self.tcx.mk_dynamic(Binder::bind(target_preds), region) } else { ty } @@ -328,10 +328,10 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { Some(match predicate { Predicate::Trait(trait_predicate) => { - Predicate::Trait(Binder(if let Some((target_def_id, target_substs)) = + Predicate::Trait(Binder::bind(if let Some((target_def_id, target_substs)) = self.translate_orig_substs(index_map, - trait_predicate.0.trait_ref.def_id, - trait_predicate.0.trait_ref.substs) { + trait_predicate.skip_binder().trait_ref.def_id, + trait_predicate.skip_binder().trait_ref.substs) { TraitPredicate { trait_ref: TraitRef { def_id: target_def_id, @@ -364,16 +364,22 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { })) }, Predicate::Projection(projection_predicate) => { - Predicate::Projection(Binder(if let Some((target_def_id, target_substs)) = + Predicate::Projection(Binder::bind(if let Some((target_def_id, target_substs)) = self.translate_orig_substs(index_map, - projection_predicate.0.projection_ty.item_def_id, - projection_predicate.0.projection_ty.substs) { + 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.0.ty), + ty: self.translate(index_map, &projection_predicate.skip_binder().ty), } } else { return None; diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs index 273b9e7da75d5..0ff95c3e9652d 100644 --- a/src/semcheck/typeck.rs +++ b/src/semcheck/typeck.rs @@ -64,7 +64,7 @@ impl<'a, 'gcx, 'tcx> BoundContext<'a, 'gcx, 'tcx> { pub fn register_trait_ref(&mut self, checked_trait_ref: TraitRef<'tcx>) { use rustc::ty::{Binder, Predicate, TraitPredicate}; - let predicate = Predicate::Trait(Binder(TraitPredicate { + let predicate = Predicate::Trait(Binder::bind(TraitPredicate { trait_ref: checked_trait_ref, })); let obligation = From 821fd1076060651c4a2978e331ff46c7936bd08c Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 28 Apr 2018 01:30:49 +0200 Subject: [PATCH 343/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 7bebfb8ff4994..b6ba5ca781765 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.9" +version = "0.1.10" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From 840faf881c8947c86786f4b521811b94c3857560 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 11 May 2018 23:02:17 +0200 Subject: [PATCH 344/553] Fixed build with newest nightly. --- src/semcheck/mismatch.rs | 4 ++-- src/semcheck/translate.rs | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index d208ef8789126..5cdcd2c06a569 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -157,9 +157,9 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, let _ = self.relate(&a_mt, &b_mt)?; None }, - (&TyRef(a_r, a_mt), &TyRef(b_r, b_mt)) => { + (&TyRef(a_r, a_ty, _), &TyRef(b_r, b_ty, _)) => { let _ = self.relate(&a_r, &b_r)?; - let _ = self.relate(&a_mt, &b_mt)?; + let _ = self.relate(&a_ty, &b_ty)?; None }, (&TyFnDef(a_def_id, a_substs), &TyFnDef(b_def_id, b_substs)) => { diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 20492cfa18adc..77a119e870529 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -146,6 +146,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { fn translate>(&self, index_map: &HashMap, orig: &T) -> T { use rustc::ty::{AdtDef, Binder, ExistentialProjection, ExistentialTraitRef}; use rustc::ty::ExistentialPredicate::*; + use rustc::ty::TypeAndMut; use rustc::ty::TypeVariants::*; orig.fold_with(&mut BottomUpFolder { tcx: self.tcx, fldop: |ty| { @@ -160,8 +161,9 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { ty } }, - TyRef(region, type_and_mut) => { - self.tcx.mk_ref(self.translate_region(region), type_and_mut) + TyRef(region, ty, mutbl) => { + let ty_and_mut = TypeAndMut { ty, mutbl }; + self.tcx.mk_ref(self.translate_region(region), ty_and_mut) }, TyFnDef(did, substs) => { // TODO: this might be buggy as *technically* the substs are @@ -493,12 +495,14 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceCleanupFolder<'a, 'gcx, fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + use rustc::ty::TypeAndMut; use rustc::ty::TypeVariants::{TyError, TyInfer, TyRef}; let t1 = ty.super_fold_with(self); match t1.sty { - TyRef(region, tm) if region.needs_infer() => { - self.infcx.tcx.mk_ref(self.infcx.tcx.types.re_erased, tm) + TyRef(region, ty, mutbl) if region.needs_infer() => { + let ty_and_mut = TypeAndMut { ty, mutbl }; + self.infcx.tcx.mk_ref(self.infcx.tcx.types.re_erased, ty_and_mut) }, TyInfer(_) => self.infcx.tcx.mk_ty(TyError), _ => t1, From f3b2512706a7b3d85808d82be764135c5f65ad10 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 11 May 2018 23:48:30 +0200 Subject: [PATCH 345/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b6ba5ca781765..c67aeaf167593 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.10" +version = "0.1.11" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From 9fa40f1fb29fde2ff29f7797b5ea8a4a48ab6dda Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 12 May 2018 00:42:27 +0200 Subject: [PATCH 346/553] Updated README. --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9967a6f87a62a..9942154edcddd 100644 --- a/README.md +++ b/README.md @@ -26,22 +26,26 @@ More information on the inner workings of the tool can be found ## Installation The tool is implemented as a cargo plugin. As of now, it can be obtained from this git -repository and compiled from source. +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 $ cargo +nightly install semverver ``` You'd also need `cmake` for some dependencies, and a few common libraries (if I you hit build failures because of missing system-wide dependencies, please open an issue, so they -can be added here. +can be added here). You can also install the newest version of the tool from git: ```sh +$ rustup update nightly $ cargo +nightly install --git https://github.com/rust-lang-nursery/rust-semverver ``` From 811b4d74997df7f29f48da767c9d89a834db6261 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 2 Jun 2018 14:12:52 +0200 Subject: [PATCH 347/553] Fixed build with newest nightly. --- src/bin/cargo_semver.rs | 11 +++-- src/bin/rust_semverver.rs | 6 +-- src/semcheck/mapping.rs | 22 ++++++---- src/semcheck/translate.rs | 88 ++++++++++++++++++++++++--------------- src/semcheck/traverse.rs | 56 +++++++++++++++++-------- src/semcheck/typeck.rs | 28 ++++++++----- 6 files changed, 136 insertions(+), 75 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index de477651a0ac2..b51726ce94f64 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -105,14 +105,17 @@ impl<'a> WorkInfo<'a> { /// Construct a package/workspace pair for the local directory. fn local(config: &'a Config, explicit_path: Option) -> CargoResult> { let manifest_path = if let Some(path) = explicit_path { - find_root_manifest_for_wd(None, &path)? + find_root_manifest_for_wd(&path)? } else { - find_root_manifest_for_wd(None, config.cwd())? + find_root_manifest_for_wd(config.cwd())? }; + let workspace = Workspace::new(&manifest_path, config)?; + let package = workspace.load(&manifest_path)?; + Ok(WorkInfo { - package: Package::for_path(&manifest_path, config)?, - workspace: Workspace::new(&manifest_path, config)?, + package, + workspace, }) } diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 6dc3fc6ea4100..c21ffa2c830d1 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -8,7 +8,7 @@ extern crate log; extern crate rustc; extern crate rustc_driver; extern crate rustc_errors; -extern crate rustc_trans_utils; +extern crate rustc_codegen_utils; extern crate semverver; extern crate syntax; @@ -21,7 +21,7 @@ use rustc::session::config::{Input, ErrorOutputType}; use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; -use rustc_trans_utils::trans_crate::TransCrate; +use rustc_codegen_utils::codegen_backend::CodegenBackend; use std::path::PathBuf; use std::process::Command; @@ -117,7 +117,7 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { } fn late_callback(&mut self, - trans_crate: &TransCrate, + trans_crate: &CodegenBackend, matches: &getopts::Matches, sess: &Session, cstore: &CrateStore, diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 2e97e1bc2385e..1c404364aae50 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -5,7 +5,7 @@ use rustc::hir::def::{Def, Export}; use rustc::hir::def_id::{CrateNum, DefId}; -use rustc::ty::{AssociatedKind, TypeParameterDef}; +use rustc::ty::{AssociatedKind, GenericParamDef, GenericParamDefKind}; use std::collections::{BTreeSet, HashMap, HashSet, VecDeque}; @@ -51,7 +51,7 @@ pub struct IdMapping { /// New `DefId`s mapped to their old counterparts. reverse_mapping: HashMap, /// Type parameters' `DefId`s mapped to their definitions. - type_params: HashMap, + type_params: HashMap, /// Map from inherent impls' descriptors to the impls they are declared in. inherent_items: HashMap, } @@ -133,19 +133,27 @@ impl IdMapping { } /// Record that a `DefId` represents a type parameter. - pub fn add_type_param(&mut self, param: TypeParameterDef) { - self.type_params.insert(param.def_id, param); + pub fn add_type_param(&mut self, param: &GenericParamDef) { + match param.kind { + GenericParamDefKind::Lifetime => unreachable!(), + GenericParamDefKind::Type { .. } => (), + }; + + 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) -> TypeParameterDef { - self.type_params[did] + 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| def.has_default) + 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. diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 77a119e870529..1d8c41e4d0938 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -2,8 +2,9 @@ //! comparison and inference. use rustc::hir::def_id::DefId; -use rustc::ty::{ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt}; +use rustc::ty::{GenericParamDefKind, ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt}; use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder}; +use rustc::ty::subst::Kind; use rustc::infer::InferCtxt; use rustc::ty::subst::Substs; @@ -58,15 +59,25 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { let mut index_map = HashMap::new(); let orig_generics = self.tcx.generics_of(orig_def_id); - for type_ in &orig_generics.types { - index_map.insert(type_.index, type_.def_id); + for param in &orig_generics.params { + match param.kind { + GenericParamDefKind::Type { .. } => { + index_map.insert(param.index, param.def_id); + }, + _ => (), + }; } if let Some(did) = orig_generics.parent { let parent_generics = self.tcx.generics_of(did); - for type_ in &parent_generics.types { - index_map.insert(type_.index, type_.def_id); + for param in &parent_generics.params { + match param.kind { + GenericParamDefKind::Type { .. } => { + index_map.insert(param.index, param.def_id); + }, + _ => (), + }; } } @@ -104,33 +115,39 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { let success = Cell::new(true); let target_substs = Substs::for_item(self.tcx, target_def_id, |def, _| { - if !success.get() { - self.tcx.mk_region(ReEarlyBound(def.to_early_bound_region_data())) - } else if let Some(UnpackedKind::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())) - } - - }, |def, _| { - if !success.get() { - self.tcx.mk_param_from_def(def) - } else if let Some(UnpackedKind::Type(type_)) = orig_substs - .get(def.index as usize) - .map(|k| k.unpack()) - { - self.translate(index_map, &type_) - } else if self.id_mapping.is_non_mapped_defaulted_type_param(&def.def_id) { - 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) + match def.kind { + GenericParamDefKind::Lifetime => { + Kind::from(if !success.get() { + self.tcx.mk_region(ReEarlyBound(def.to_early_bound_region_data())) + } else if let Some(UnpackedKind::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(UnpackedKind::Type(type_)) = orig_substs + .get(def.index as usize) + .map(|k| k.unpack()) + { + self.translate(index_map, &Kind::from(type_)) + } else if self.id_mapping + .is_non_mapped_defaulted_type_param(&def.def_id) { + Kind::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) + } + }, } }); @@ -266,11 +283,16 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { if param.idx != 0 && self.translate_params { // `Self` is special let orig_def_id = index_map[¶m.idx]; if self.needs_translation(orig_def_id) { + use rustc::ty::subst::UnpackedKind; + 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); - self.tcx.mk_param_from_def(&type_param) + match self.tcx.mk_param_from_def(&type_param).unpack() { + UnpackedKind::Type(param_t) => param_t, + _ => unreachable!(), + } } else { ty } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index d3fe648b383f7..2db789108e4ee 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -11,7 +11,7 @@ use rustc::hir::def::{CtorKind, Def, Export}; use rustc::hir::def_id::DefId; -use rustc::ty::{AssociatedItem, Ty, TyCtxt}; +use rustc::ty::{AssociatedItem, GenericParamDefKind, Ty, TyCtxt}; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::Visibility; use rustc::ty::Visibility::Public; @@ -391,11 +391,11 @@ fn diff_adts(changes: &mut ChangeSet, match *items { (Some(old), Some(new)) => { for field in &old.fields { - fields.entry(field.name).or_insert((None, None)).0 = Some(field); + fields.entry(field.ident.name).or_insert((None, None)).0 = Some(field); } for field in &new.fields { - fields.entry(field.name).or_insert((None, None)).1 = Some(field); + fields.entry(field.ident.name).or_insert((None, None)).1 = Some(field); } let mut total_private = true; @@ -621,11 +621,11 @@ fn diff_generics(changes: &mut ChangeSet, let old_var = tcx.variances_of(old); let new_var = tcx.variances_of(new); - let old_regions_len = old_gen.regions.len(); - let new_regions_len = new_gen.regions.len(); + let old_count = old_gen.own_counts(); + let new_count = new_gen.own_counts(); - for i in 0..max(old_regions_len, new_regions_len) { - match (old_gen.regions.get(i), new_gen.regions.get(i)) { + for i in 0..max(old_count.lifetimes, new_count.lifetimes) { + match (old_gen.params.get(i), new_gen.params.get(i)) { (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)) { @@ -645,21 +645,31 @@ fn diff_generics(changes: &mut ChangeSet, } } - for i in 0..max(old_gen.types.len(), new_gen.types.len()) { - match (old_gen.types.get(i), new_gen.types.get(i)) { + for i in 0..max(old_count.types, new_count.types) { + match (old_gen.params.get(old_count.lifetimes + i), + new_gen.params.get(new_count.lifetimes + i)) { (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(i + old_regions_len), new_var.get(i + new_regions_len)) + (old_var.get(old_count.lifetimes + i), new_var.get(new_count.lifetimes + i)) { diff_variance(*old_var, *new_var) .map(|t| found.push(t)); } - if old_type.has_default && !new_type.has_default { + 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(TypeParameterRemoved { defaulted: true }); found.push(TypeParameterAdded { defaulted: false }); - } else if !old_type.has_default && new_type.has_default { + } else if !old_default && new_default { found.push(TypeParameterRemoved { defaulted: false }); found.push(TypeParameterAdded { defaulted: true }); } @@ -668,17 +678,27 @@ fn diff_generics(changes: &mut ChangeSet, 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); + id_mapping.add_type_param(old_type); + id_mapping.add_type_param(new_type); }, (Some(old_type), None) => { - found.push(TypeParameterRemoved { defaulted: old_type.has_default }); - id_mapping.add_type_param(*old_type); + let old_default = match old_type.kind { + GenericParamDefKind::Type { has_default, .. } => has_default, + _ => unreachable!(), + }; + + found.push(TypeParameterRemoved { defaulted: old_default }); + id_mapping.add_type_param(old_type); id_mapping.add_non_mapped(old_type.def_id); }, (None, Some(new_type)) => { - found.push(TypeParameterAdded { defaulted: new_type.has_default || is_fn }); - id_mapping.add_type_param(*new_type); + let new_default = match new_type.kind { + GenericParamDefKind::Type { has_default, .. } => has_default, + _ => unreachable!(), + }; + + found.push(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!(), diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs index 0ff95c3e9652d..d66bb99970e15 100644 --- a/src/semcheck/typeck.rs +++ b/src/semcheck/typeck.rs @@ -7,10 +7,10 @@ use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; use rustc::traits::{FulfillmentContext, FulfillmentError, Obligation, ObligationCause, TraitEngine}; -use rustc::ty::{ParamEnv, Predicate, TraitRef, Ty, TyCtxt}; +use rustc::ty::{GenericParamDefKind, ParamEnv, Predicate, TraitRef, Ty, TyCtxt}; use rustc::ty::error::TypeError; use rustc::ty::fold::TypeFoldable; -use rustc::ty::subst::Substs; +use rustc::ty::subst::{Kind, Substs}; use semcheck::changes::ChangeSet; use semcheck::mapping::IdMapping; @@ -150,12 +150,10 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { let has_self = self.infcx.tcx.generics_of(target_def_id).has_self; Substs::for_item(self.infcx.tcx, target_def_id, |def, _| { - self.infcx.region_var_for_def(DUMMY_SP, def) - }, |def, _| { if def.index == 0 && has_self { // `Self` is special self.infcx.tcx.mk_param_from_def(def) } else { - self.infcx.type_var_for_def(DUMMY_SP, def) + self.infcx.var_for_def(DUMMY_SP, def) } }) } @@ -165,11 +163,21 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { use rustc::ty::ReEarlyBound; Substs::for_item(self.infcx.tcx, target_def_id, |def, _| { - self.infcx.tcx.mk_region(ReEarlyBound(def.to_early_bound_region_data())) - }, |def, _| if self.id_mapping.is_non_mapped_defaulted_type_param(&def.def_id) { - self.infcx.tcx.type_of(def.def_id) - } else { - self.infcx.tcx.mk_param_from_def(def) + match def.kind { + GenericParamDefKind::Lifetime => { + Kind::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) { + Kind::from(self.infcx.tcx.type_of(def.def_id)) + } else { + self.infcx.tcx.mk_param_from_def(def) + } + }, + } }) } From 815b7f8388cf0e84a57468edf2010458ae567e4e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 2 Jun 2018 14:44:05 +0200 Subject: [PATCH 348/553] Updated dependencies --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c67aeaf167593..4cfa04fd7aeab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,8 +25,8 @@ name = "rust-semverver" path = "src/bin/rust_semverver.rs" [dependencies] -cargo = "^0.25" -crates-io = "^0.14" +cargo = "^0.27" +crates-io = "^0.16" env_logger = "^0.5" log = "^0.4" semver = "^0.9" From 708dfdd0d66e8b8f509be37e2d7c8961927a8597 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 2 Jun 2018 14:44:20 +0200 Subject: [PATCH 349/553] Fixed bugs fresh out of the oven. --- src/semcheck/traverse.rs | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 2db789108e4ee..7b2cf30946e0d 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -11,7 +11,7 @@ use rustc::hir::def::{CtorKind, Def, Export}; use rustc::hir::def_id::DefId; -use rustc::ty::{AssociatedItem, GenericParamDefKind, Ty, TyCtxt}; +use rustc::ty::{AssociatedItem, Generics, GenericParamDef, GenericParamDefKind, Ty, TyCtxt}; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::Visibility; use rustc::ty::Visibility::Public; @@ -624,8 +624,18 @@ fn diff_generics(changes: &mut ChangeSet, let old_count = old_gen.own_counts(); let new_count = new_gen.own_counts(); + // 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, + } + } + for i in 0..max(old_count.lifetimes, new_count.lifetimes) { - match (old_gen.params.get(i), new_gen.params.get(i)) { + match (get_region_from_params(old_gen, i), get_region_from_params(new_gen, i)) { (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)) { @@ -645,9 +655,19 @@ fn diff_generics(changes: &mut ChangeSet, } } + // 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, + } + } + for i in 0..max(old_count.types, new_count.types) { - match (old_gen.params.get(old_count.lifetimes + i), - new_gen.params.get(new_count.lifetimes + i)) { + match (get_type_from_params(old_gen, old_count.lifetimes + i), + get_type_from_params(new_gen, new_count.lifetimes + i)) { (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)) = From 8dbc10730dfde4a8ed4ecbee61ae86f86ff53967 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 2 Jun 2018 14:57:35 +0200 Subject: [PATCH 350/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4cfa04fd7aeab..71cafe76c19ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.11" +version = "0.1.12" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From 40b7b062f9476b88a616d538ffb845405250caec Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 10 Jun 2018 13:02:53 +0200 Subject: [PATCH 351/553] Fixed build with newest nightly. --- src/bin/rust_semverver.rs | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index c21ffa2c830d1..4ffb2635d2b23 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -72,7 +72,7 @@ fn callback(state: &driver::CompileState, version: &str, verbose: bool) { /// A wrapper to control compilation. struct SemVerVerCompilerCalls { /// The wrapped compilation handle. - default: RustcDefaultCalls, + default: Box, /// The version of the old crate. version: String, /// The output mode. @@ -81,12 +81,20 @@ struct SemVerVerCompilerCalls { impl SemVerVerCompilerCalls { /// Construct a new compilation wrapper, given a version string. - pub fn new(version: String, verbose: bool) -> SemVerVerCompilerCalls { - SemVerVerCompilerCalls { - default: RustcDefaultCalls, + pub fn new(version: String, verbose: bool) -> Box { + Box::new(SemVerVerCompilerCalls { + default: Box::new(RustcDefaultCalls), version, verbose, - } + }) + } + + pub fn get_default(&self) -> Box { + self.default.clone() + } + + pub fn get_version(&self) -> &String { + &self.version } } @@ -130,15 +138,16 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { .late_callback(trans_crate, matches, sess, cstore, input, odir, ofile) } - fn build_controller(&mut self, + fn build_controller(self: Box, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> { - let mut controller = self.default.build_controller(sess, matches); + let default = self.get_default(); + let version = self.get_version().clone(); + let SemVerVerCompilerCalls { verbose, .. } = *self; + let mut controller = CompilerCalls::build_controller(default, sess, matches); let old_callback = std::mem::replace(&mut controller.after_analysis.callback, box |_| {}); - let version = self.version.clone(); - let verbose = self.verbose; controller.after_analysis.callback = box move |state| { debug!("running rust-semverver after_analysis callback"); @@ -199,8 +208,8 @@ fn main() { let verbose = std::env::var("RUST_SEMVER_VERBOSE") == Ok("true".to_string()); - let mut cc = SemVerVerCompilerCalls::new(version, verbose); - rustc_driver::run_compiler(&args, &mut cc, None, None) + let cc = SemVerVerCompilerCalls::new(version, verbose); + rustc_driver::run_compiler(&args, cc, None, None) }); std::process::exit(result as i32); From 98729952c2b5b51954901dd1b133629324218705 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 10 Jun 2018 13:14:43 +0200 Subject: [PATCH 352/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 71cafe76c19ad..2acc59315f427 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.12" +version = "0.1.13" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From c0dadaef43ac23e7cf2ba5fde8e722259fcb4b5e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 19 Jun 2018 23:19:12 +0200 Subject: [PATCH 353/553] Fixed build with newest nightly. --- src/semcheck/mapping.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 1c404364aae50..982f8ae3ccf01 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -313,6 +313,7 @@ impl NameMapping { Enum(_) | Variant(_) | Trait(_) | + Existential(_) | TyAlias(_) | TyForeign(_) | TraitAlias(_) | // TODO: will need some handling later on. From f43e7e9c4cbd0c39e7ce34864bdcffa70981d425 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 19 Jun 2018 23:45:53 +0200 Subject: [PATCH 354/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 2acc59315f427..fbbe669ec77ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.13" +version = "0.1.14" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From 8c44359d5f37a27da390e34ec11dd338207f5fe6 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 30 Jun 2018 13:08:15 +0200 Subject: [PATCH 355/553] Fixed build with newest nightly. --- src/semcheck/traverse.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 7b2cf30946e0d..ed26a465ce8d3 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -469,7 +469,7 @@ fn diff_adts(changes: &mut ChangeSet, let item = tcx.associated_item(*item_def_id); id_mapping.add_inherent_item(old_def_id, item.kind, - item.name, + item.ident.name, *impl_def_id, *item_def_id); } @@ -480,7 +480,7 @@ fn diff_adts(changes: &mut ChangeSet, let item = tcx.associated_item(*item_def_id); id_mapping.add_inherent_item(new_def_id, item.kind, - item.name, + item.ident.name, *impl_def_id, *item_def_id); } @@ -540,13 +540,13 @@ fn diff_traits(changes: &mut ChangeSet, for old_def_id in tcx.associated_item_def_ids(old).iter() { let item = tcx.associated_item(*old_def_id); - items.entry(item.name).or_insert((None, None)).0 = + items.entry(item.ident.name).or_insert((None, None)).0 = 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.name).or_insert((None, None)).1 = + items.entry(item.ident.name).or_insert((None, None)).1 = tcx.describe_def(*new_def_id).map(|d| (d, item)); } From 39a017628cdddc7afffa5c4c9826248c376b26b4 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 30 Jun 2018 13:17:21 +0200 Subject: [PATCH 356/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index fbbe669ec77ad..4d8bd742ec484 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.14" +version = "0.1.15" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From b720b3a6e77f7dd339e894d804a1808ef8281304 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 23 Jul 2018 00:15:22 +0200 Subject: [PATCH 357/553] Fixed build with newest nightly. --- src/semcheck/mapping.rs | 1 + src/semcheck/translate.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 982f8ae3ccf01..7eb049cab0837 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -318,6 +318,7 @@ impl NameMapping { TyForeign(_) | TraitAlias(_) | // TODO: will need some handling later on. AssociatedTy(_) | + AssociatedExistential(_) | PrimTy(_) | TyParam(_) | SelfTy(_, _) => Some(&mut self.type_map), diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 1d8c41e4d0938..7c6d50af9adb5 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -302,7 +302,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { }, _ => ty, } - }}) + }, reg_op: |region| self.translate_region(region) }) } /// Translate a region. From 6fcccb4d2532feb9dd3305c4f406ae5bb17f6b42 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 23 Jul 2018 00:15:52 +0200 Subject: [PATCH 358/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4d8bd742ec484..c19ff4046faf4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.15" +version = "0.1.16" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From 1738b59ae142b7f2be3f2316728aa7232bf6a05e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 12 Aug 2018 23:05:24 +0200 Subject: [PATCH 359/553] Fixed build with newest nightly. --- src/bin/rust_semverver.rs | 5 +++-- src/semcheck/mapping.rs | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 4ffb2635d2b23..ace27b10fcb8b 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -9,13 +9,14 @@ extern crate rustc; extern crate rustc_driver; extern crate rustc_errors; extern crate rustc_codegen_utils; +extern crate rustc_metadata; extern crate semverver; extern crate syntax; use semverver::semcheck::run_analysis; use rustc::hir::def_id::*; -use rustc::middle::cstore::CrateStore; +use rustc_metadata::cstore::CStore; use rustc::session::{config, Session}; use rustc::session::config::{Input, ErrorOutputType}; @@ -128,7 +129,7 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { trans_crate: &CodegenBackend, matches: &getopts::Matches, sess: &Session, - cstore: &CrateStore, + cstore: &CStore, input: &Input, odir: &Option, ofile: &Option) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 7eb049cab0837..2fe6bd1cb2f0c 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -333,6 +333,8 @@ impl NameMapping { Upvar(_, _, _) | Label(_) => Some(&mut self.value_map), Macro(_, _) => Some(&mut self.macro_map), + ToolMod | + NonMacroAttr /*(_)*/ | GlobalAsm(_) | Err => None, }; From a5a05d3f3f5560f86f2e70e6b7075bb625c88970 Mon Sep 17 00:00:00 2001 From: jeb Date: Wed, 22 Aug 2018 16:52:17 -0600 Subject: [PATCH 360/553] Fixed build with nightly. --- src/semcheck/mapping.rs | 7 +++---- src/semcheck/traverse.rs | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 2fe6bd1cb2f0c..8224b41881437 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -321,7 +321,8 @@ impl NameMapping { AssociatedExistential(_) | PrimTy(_) | TyParam(_) | - SelfTy(_, _) => Some(&mut self.type_map), + SelfTy(_, _) | + ToolMod => Some(&mut self.type_map), Fn(_) | Const(_) | Static(_, _) | @@ -333,9 +334,7 @@ impl NameMapping { Upvar(_, _, _) | Label(_) => Some(&mut self.value_map), Macro(_, _) => Some(&mut self.macro_map), - ToolMod | - NonMacroAttr /*(_)*/ | - GlobalAsm(_) | + NonMacroAttr(_) | Err => None, }; diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index ed26a465ce8d3..a1af382f55fd1 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -174,7 +174,6 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, (Local(_), Local(_)) | (Upvar(_, _, _), Upvar(_, _, _)) | (Label(_), Label(_)) | - (GlobalAsm(_), GlobalAsm(_)) | (Macro(_, _), Macro(_, _)) | (Variant(_), Variant(_)) | (Const(_), Const(_)) | From 7381d71a47ceb2fa3330cbf03297115e1c23b5ef Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Sat, 15 Sep 2018 20:22:12 +0100 Subject: [PATCH 361/553] Fix compilation errors. --- src/lib.rs | 1 - src/semcheck/mapping.rs | 3 ++- src/semcheck/mismatch.rs | 26 +++++++++++++------------- src/semcheck/translate.rs | 26 +++++++++++++------------- src/semcheck/traverse.rs | 4 ++-- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 711be90a44cb7..1216d0c0fcf74 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,6 @@ extern crate log; #[cfg(test)] -#[macro_use] extern crate quickcheck; extern crate rustc; diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 8224b41881437..719d447de974b 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -315,7 +315,7 @@ impl NameMapping { Trait(_) | Existential(_) | TyAlias(_) | - TyForeign(_) | + ForeignTy(_) | TraitAlias(_) | // TODO: will need some handling later on. AssociatedTy(_) | AssociatedExistential(_) | @@ -327,6 +327,7 @@ impl NameMapping { Const(_) | Static(_, _) | StructCtor(_, _) | + SelfCtor(_) | VariantCtor(_, _) | Method(_) | AssociatedConst(_) | diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 5cdcd2c06a569..cc3c689db49f6 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -107,7 +107,7 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, } fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { - use rustc::ty::TypeVariants::*; + use rustc::ty::TyKind; if self.current_old_types.contains(a) || self.current_new_types.contains(b) { return Ok(self.tcx.types.err); @@ -118,7 +118,7 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, debug!("tys: mismatch relation: a: {:?}, b: {:?}", a, b); let matching = match (&a.sty, &b.sty) { - (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs)) => { + (&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); @@ -148,21 +148,21 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, None } }, - (&TyArray(a_t, _), &TyArray(b_t, _)) | - (&TySlice(a_t), &TySlice(b_t)) => { + (&TyKind::Array(a_t, _), &TyKind::Array(b_t, _)) | + (&TyKind::Slice(a_t), &TyKind::Slice(b_t)) => { let _ = self.relate(&a_t, &b_t)?; None }, - (&TyRawPtr(a_mt), &TyRawPtr(b_mt)) => { + (&TyKind::RawPtr(a_mt), &TyKind::RawPtr(b_mt)) => { let _ = self.relate(&a_mt, &b_mt)?; None }, - (&TyRef(a_r, a_ty, _), &TyRef(b_r, b_ty, _)) => { + (&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 }, - (&TyFnDef(a_def_id, a_substs), &TyFnDef(b_def_id, b_substs)) => { + (&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); @@ -172,11 +172,11 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, Some((a_def_id, b_def_id)) }, - (&TyFnPtr(a_fty), &TyFnPtr(b_fty)) => { + (&TyKind::FnPtr(a_fty), &TyKind::FnPtr(b_fty)) => { let _ = self.relate(&a_fty, &b_fty)?; None }, - (&TyDynamic(a_obj, a_r), &TyDynamic(b_obj, b_r)) => { + (&TyKind::Dynamic(a_obj, a_r), &TyKind::Dynamic(b_obj, b_r)) => { let _ = self.relate(&a_r, &b_r)?; match (a_obj.principal(), b_obj.principal()) { @@ -188,22 +188,22 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, _ => None, } }, - (&TyTuple(as_), &TyTuple(bs)) => { + (&TyKind::Tuple(as_), &TyKind::Tuple(bs)) => { let _ = as_.iter().zip(bs).map(|(a, b)| self.relate(a, b)); None }, - (&TyProjection(a_data), &TyProjection(b_data)) => { + (&TyKind::Projection(a_data), &TyKind::Projection(b_data)) => { let _ = self.relate(&a_data, &b_data)?; Some((a_data.item_def_id, b_data.item_def_id)) }, - (&TyAnon(a_def_id, a_substs), &TyAnon(b_def_id, b_substs)) => { + (&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)?; } Some((a_def_id, b_def_id)) }, - (&TyInfer(_), _) | (_, &TyInfer(_)) => { + (&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") }, diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 7c6d50af9adb5..abe477d515de9 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -164,11 +164,11 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { use rustc::ty::{AdtDef, Binder, ExistentialProjection, ExistentialTraitRef}; use rustc::ty::ExistentialPredicate::*; use rustc::ty::TypeAndMut; - use rustc::ty::TypeVariants::*; + use rustc::ty::TyKind; orig.fold_with(&mut BottomUpFolder { tcx: self.tcx, fldop: |ty| { match ty.sty { - TyAdt(&AdtDef { ref did, .. }, substs) if self.needs_translation(*did) => { + 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) { @@ -178,13 +178,13 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { ty } }, - TyRef(region, ty, mutbl) => { + TyKind::Ref(region, ty, mutbl) => { let ty_and_mut = TypeAndMut { ty, mutbl }; self.tcx.mk_ref(self.translate_region(region), ty_and_mut) }, - TyFnDef(did, substs) => { + TyKind::FnDef(did, substs) => { // TODO: this might be buggy as *technically* the substs are - // already translated (see TyAdt for a possible fix) + // 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) { @@ -193,7 +193,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { ty } }, - TyDynamic(preds, region) => { + TyKind::Dynamic(preds, region) => { // hacky error catching mechanism use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use std::cell::Cell; @@ -259,7 +259,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { ty } }, - TyProjection(proj) => { + TyKind::Projection(proj) => { if let Some((target_def_id, target_substs)) = self.translate_orig_substs(index_map, proj.item_def_id, @@ -269,16 +269,16 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { ty } }, - TyAnon(did, substs) => { + TyKind::Opaque(did, substs) => { if let Some((target_def_id, target_substs)) = self.translate_orig_substs(index_map, did, substs) { - self.tcx.mk_anon(target_def_id, target_substs) + self.tcx.mk_opaque(target_def_id, target_substs) } else { ty } }, - TyParam(param) => { + TyKind::Param(param) => { // FIXME: we should check `has_self` if this gets used again! if param.idx != 0 && self.translate_params { // `Self` is special let orig_def_id = index_map[¶m.idx]; @@ -518,15 +518,15 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceCleanupFolder<'a, 'gcx, fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { use rustc::ty::TypeAndMut; - use rustc::ty::TypeVariants::{TyError, TyInfer, TyRef}; + use rustc::ty::TyKind; let t1 = ty.super_fold_with(self); match t1.sty { - TyRef(region, ty, mutbl) if region.needs_infer() => { + TyKind::Ref(region, ty, mutbl) if region.needs_infer() => { let ty_and_mut = TypeAndMut { ty, mutbl }; self.infcx.tcx.mk_ref(self.infcx.tcx.types.re_erased, ty_and_mut) }, - TyInfer(_) => self.infcx.tcx.mk_ty(TyError), + TyKind::Infer(_) => self.infcx.tcx.mk_ty(TyKind::Error), _ => t1, } } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index a1af382f55fd1..cf8dc253292c5 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -498,7 +498,7 @@ fn diff_traits(changes: &mut ChangeSet, output: bool) { use rustc::hir::Unsafety::Unsafe; use rustc::ty::subst::UnpackedKind::Type; - use rustc::ty::{ParamTy, Predicate, TyS, TypeVariants::*}; + use rustc::ty::{ParamTy, Predicate, TyS, TyKind}; debug!("diff_traits: old: {:?}, new: {:?}, output: {:?}", old, new, output); @@ -525,7 +525,7 @@ fn diff_traits(changes: &mut ChangeSet, if id_mapping.is_private_trait(&trait_ref.def_id) && trait_ref.substs.len() == 1 { - if let Type(&TyS { sty: TyParam(ParamTy { idx: 0, ..}), ..}) = + if let Type(&TyS { sty: TyKind::Param(ParamTy { idx: 0, ..}), ..}) = trait_ref.substs[0].unpack() { old_sealed = true; } From eb5facce74bc4d2ae48cdbb07b6bc33c8a12ce9a Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Sun, 16 Sep 2018 00:17:19 +0100 Subject: [PATCH 362/553] Now it works again :) Fixes #64. --- src/bin/cargo_semver.rs | 6 +- src/bin/rust_semverver.rs | 61 ++++----- tests/full_cases/libc-0.2.28-0.2.31 | 190 ++++++++++++++-------------- 3 files changed, 130 insertions(+), 127 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index b51726ce94f64..2247457c58d53 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -247,10 +247,12 @@ fn do_main(config: &Config, matches: &Matches, explain: bool) -> CargoResult<()> .map_err(|e| Error(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 new; \ + extern crate old; \ #[allow(unused_extern_crates)] \ - extern crate old;"))?; + extern crate new;"))?; } else { return Err(Error("could not pipe to rustc (wtf?)".to_owned()).into()); } diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index ace27b10fcb8b..2198189d68b71 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -19,6 +19,7 @@ use rustc::hir::def_id::*; use rustc_metadata::cstore::CStore; use rustc::session::{config, Session}; use rustc::session::config::{Input, ErrorOutputType}; +use rustc::middle::cstore::ExternCrate; use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; @@ -28,46 +29,46 @@ use std::path::PathBuf; use std::process::Command; use syntax::ast; +use syntax::source_map::Pos; /// After the typechecker has finished it's work, perform our checks. -/// -/// To compare the two well-typed crates, first find the aptly named crates `new` and `old`, -/// find their root modules and then proceed to walk their module trees. fn callback(state: &driver::CompileState, version: &str, verbose: bool) { let tcx = state.tcx.unwrap(); - let cnums = 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() - .fold((None, None), |(o, n), crate_num| { - let name = tcx.crate_name(*crate_num); - if name == "old" { - (Some(*crate_num), n) - } else if name == "new" { - (o, Some(*crate_num)) - } else { - (o, n) + .flat_map(|crate_num| { + let def_id = DefId { + krate: *crate_num, + index: CRATE_DEF_INDEX, + }; + + match *tcx.extern_crate(def_id) { + Some(ExternCrate { span, direct: true, ..}) if span.data().lo.to_usize() > 0 => + Some((span.data().lo.to_usize(), def_id)), + _ => None, } - }); - - let (old_def_id, new_def_id) = if let (Some(c0), Some(c1)) = cnums { - (DefId { - krate: c0, - index: CRATE_DEF_INDEX, - }, - DefId { - krate: c1, - index: CRATE_DEF_INDEX, - }) - } else { - tcx.sess.err("could not find crate `old` and/or `new`"); - return; - }; + }) + .collect(); + + crates.sort_by_key(|&(span_lo, _)| span_lo); - debug!("running semver analysis"); - let changes = run_analysis(tcx, old_def_id, new_def_id); + match crates.as_slice() { + &[(_, old_def_id), (_, new_def_id)] => { + debug!("running semver analysis"); + let changes = run_analysis(tcx, old_def_id, new_def_id); - changes.output(tcx.sess, version, verbose); + changes.output(tcx.sess, version, verbose); + } + _ => { + tcx.sess.err("could not find crate old and new crates"); + } + } } /// A wrapper to control compilation. diff --git a/tests/full_cases/libc-0.2.28-0.2.31 b/tests/full_cases/libc-0.2.28-0.2.31 index 499486a0ed232..04597882ddd88 100644 --- a/tests/full_cases/libc-0.2.28-0.2.31 +++ b/tests/full_cases/libc-0.2.28-0.2.31 @@ -1,4 +1,99 @@ 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 | @@ -770,100 +865,5 @@ note: added path (technically breaking) 284 | pub use unix::*; | ^^^^^^^ -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) - error: aborting due to 11 previous errors From 6abeba7a3743701663298482a7a473d7459fb8a1 Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Sun, 16 Sep 2018 02:12:51 +0100 Subject: [PATCH 363/553] Updated dependencies. --- Cargo.toml | 13 +++++++------ src/bin/cargo_semver.rs | 5 +++-- src/lib.rs | 1 + src/semcheck/changes.rs | 1 + 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c19ff4046faf4..077c11a5abf0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,11 +25,12 @@ name = "rust-semverver" path = "src/bin/rust_semverver.rs" [dependencies] -cargo = "^0.27" -crates-io = "^0.16" -env_logger = "^0.5" -log = "^0.4" -semver = "^0.9" +cargo = "0.29" +crates-io = "0.17" +env_logger = "0.5" +log = "0.4" +semver = "0.9" +rand = "0.5" [dev-dependencies] -quickcheck = "0.6" +quickcheck = "0.7" diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 2247457c58d53..eb40ab39f5213 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -12,7 +12,8 @@ use crates_io::{Crate, Registry}; use cargo::exit_with_error; use cargo::core::{Package, PackageId, Source, SourceId, Workspace}; -use cargo::ops::{compile, CompileMode, CompileOptions}; +use cargo::core::compiler::CompileMode; +use cargo::ops::{compile, CompileOptions}; use cargo::util::{CargoError, CargoResult, CliError}; use cargo::util::config::Config; use cargo::util::important_paths::find_root_manifest_for_wd; @@ -141,7 +142,7 @@ impl<'a> WorkInfo<'a> { fn rlib_and_dep_output(&self, config: &'a Config, name: &str, current: bool) -> CargoResult<(PathBuf, PathBuf)> { - let opts = CompileOptions::default(config, CompileMode::Build); + let opts = CompileOptions::new(config, CompileMode::Build).unwrap(); if current { env::set_var("RUSTFLAGS", "-C metadata=new"); diff --git a/src/lib.rs b/src/lib.rs index 1216d0c0fcf74..e0f9bff1bef76 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ extern crate log; #[cfg(test)] extern crate quickcheck; +extern crate rand; extern crate rustc; extern crate semver; extern crate syntax; diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index aa2ec5db34d76..cdf0b14198fa5 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -948,6 +948,7 @@ pub mod tests { impl Arbitrary for ChangeType_ { fn arbitrary(g: &mut G) -> ChangeType_ { use self::ChangeType_::*; + use ::rand::Rng; let b1 = Arbitrary::arbitrary(g); let b2 = Arbitrary::arbitrary(g); From 25f2068d7c603aaf89f9604ec1a09e915b5fe6d5 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 17 Sep 2018 01:55:58 +0200 Subject: [PATCH 364/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 077c11a5abf0e..e5004a23ac165 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.16" +version = "0.1.17" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From 3fe9b6b5c9d2e5be591983458ee9a810c01b9c37 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 17 Sep 2018 01:57:18 +0200 Subject: [PATCH 365/553] Second version bump (we got out of sync for some reason). --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e5004a23ac165..bcefc24e1b7f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.17" +version = "0.1.18" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From 8ce555f55c5fd9e9d73144a5c55e3289720c53a6 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 27 Sep 2018 13:48:11 +0200 Subject: [PATCH 366/553] Fixed build with newest nightly. --- src/semcheck/typeck.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs index d66bb99970e15..6f5ec81a23da7 100644 --- a/src/semcheck/typeck.rs +++ b/src/semcheck/typeck.rs @@ -188,7 +188,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { target_param_env: ParamEnv<'tcx>, orig: Ty<'tcx>, target: Ty<'tcx>) -> Option> { - use rustc::infer::InferOk; + use rustc::infer::{InferOk, SuppressRegionErrors}; use rustc::infer::outlives::env::OutlivesEnvironment; use rustc::middle::region::ScopeTree; use rustc::ty::Lift; @@ -216,7 +216,8 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { self.infcx.resolve_regions_and_report_errors(target_def_id, &scope_tree, - &outlives_env); + &outlives_env, + SuppressRegionErrors::default()); let err = self.infcx From 9988a47a492a82d78d7a63796ff74d829deeeb26 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 27 Sep 2018 14:51:55 +0200 Subject: [PATCH 367/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index bcefc24e1b7f9..ff8f9f87a4cf0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.18" +version = "0.1.19" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From 5c784c03eddce15a19e3ae6191cbff4a3781b06d Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 5 Oct 2018 14:08:38 +0200 Subject: [PATCH 368/553] Fixed build with newest nightly. --- src/semcheck/traverse.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index cf8dc253292c5..0e8ac789e3dd7 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -322,7 +322,7 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, } /// Given two fn items, perform structural checks. -fn diff_fn(changes: &mut ChangeSet, tcx: TyCtxt, old: Def, new: Def) { +fn diff_fn<'a, 'tcx>(changes: &mut ChangeSet, tcx: TyCtxt<'a, 'tcx, 'tcx>, old: Def, new: Def) { let old_def_id = old.def_id(); let new_def_id = new.def_id(); @@ -335,7 +335,10 @@ fn diff_fn(changes: &mut ChangeSet, tcx: TyCtxt, old: Def, new: Def) { } /// Given two method items, perform structural checks. -fn diff_method(changes: &mut ChangeSet, tcx: TyCtxt, old: AssociatedItem, new: AssociatedItem) { +fn diff_method<'a, 'tcx>(changes: &mut ChangeSet, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + old: AssociatedItem, + new: AssociatedItem) { if old.method_has_self_argument != new.method_has_self_argument { changes.add_change(MethodSelfChanged { now_self: new.method_has_self_argument }, old.def_id, @@ -490,12 +493,12 @@ fn diff_adts(changes: &mut ChangeSet, /// /// This establishes the needed correspondence between non-toplevel items found in the trait /// definition. -fn diff_traits(changes: &mut ChangeSet, - id_mapping: &mut IdMapping, - tcx: TyCtxt, - old: DefId, - new: DefId, - output: bool) { +fn diff_traits<'a, 'tcx>(changes: &mut ChangeSet, + id_mapping: &mut IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + old: DefId, + new: DefId, + output: bool) { use rustc::hir::Unsafety::Unsafe; use rustc::ty::subst::UnpackedKind::Type; use rustc::ty::{ParamTy, Predicate, TyS, TyKind}; From a1f8b3a5bb3db94a407cd8775b697331799563b9 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 5 Oct 2018 14:27:37 +0200 Subject: [PATCH 369/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ff8f9f87a4cf0..091db103b2b4c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.19" +version = "0.1.20" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From 912189a26548789b52709f32475b38752939dc42 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 21 Oct 2018 00:17:17 +0200 Subject: [PATCH 370/553] Fixed build with newest nightly. --- src/semcheck/mismatch.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index cc3c689db49f6..b1415597241f8 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -178,14 +178,14 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, }, (&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(); - match (a_obj.principal(), b_obj.principal()) { - (Some(a), Some(b)) if self.check_substs(a.skip_binder().substs, - b.skip_binder().substs) => { - let _ = self.relate(&a.skip_binder().substs, &b.skip_binder().substs)?; - Some((a.skip_binder().def_id, b.skip_binder().def_id)) - }, - _ => None, + if self.check_substs(a.skip_binder().substs, b.skip_binder().substs) { + let _ = self.relate(&a.skip_binder().substs, &b.skip_binder().substs)?; + Some((a.skip_binder().def_id, b.skip_binder().def_id)) + } else { + None } }, (&TyKind::Tuple(as_), &TyKind::Tuple(bs)) => { From db5821081573764f35161a7fda77323d374ba3d3 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 21 Oct 2018 00:17:45 +0200 Subject: [PATCH 371/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 091db103b2b4c..fe57cbea46fc4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.20" +version = "0.1.21" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From 45eac833b0fe5ad711892e97596892418ed34d64 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 22 Oct 2018 00:28:12 +0200 Subject: [PATCH 372/553] Fixed build with newest nightly. --- src/semcheck/changes.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index cdf0b14198fa5..b596bbfe51409 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -981,7 +981,7 @@ pub mod tests { fn build_change<'a>(s1: Span, output: bool, changes: Vec<(ChangeType_, Option)>) -> Change<'a> { - let mut interner = Interner::new(); + let mut interner = Interner::default(); let mut change = Change::new(Name::Symbol(interner.intern("test")), s1, output); for (type_, span) in changes { @@ -996,7 +996,7 @@ pub mod tests { /// Construct `PathChange`s from things that can be generated. fn build_path_change(s1: Span, spans: Vec<(bool, Span)>) -> PathChange { - let mut interner = Interner::new(); + let mut interner = Interner::default(); let mut change = PathChange::new(interner.intern("test"), s1); for (add, span) in spans { @@ -1062,7 +1062,7 @@ pub mod tests { fn max_pchange(changes: Vec) -> bool { let mut set = ChangeSet::default(); - let mut interner = Interner::new(); + let mut interner = Interner::default(); let name = interner.intern("test"); let max = changes @@ -1093,7 +1093,7 @@ pub mod tests { fn max_change(changes: Vec) -> bool { let mut set = ChangeSet::default(); - let mut interner = Interner::new(); + let mut interner = Interner::default(); let name = interner.intern("test"); let max = changes @@ -1126,7 +1126,7 @@ pub mod tests { fn max_pchange_or_change(pchanges: Vec, changes: Vec) -> bool { let mut set = ChangeSet::default(); - let mut interner = Interner::new(); + let mut interner = Interner::default(); let name = interner.intern("test"); let max = pchanges From bd2cd2713b359ae95651bc23d137b76481165760 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 22 Oct 2018 00:30:24 +0200 Subject: [PATCH 373/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index fe57cbea46fc4..008edb508c8a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.21" +version = "0.1.22" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From 0c5c73e43adbf908172a5a9311324f1ee7220718 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 21 Nov 2018 14:17:28 +0100 Subject: [PATCH 374/553] Temporarily silence full tests --- tests/full.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/full.rs b/tests/full.rs index 3b2218d38ef5b..89ff7b676bb2e 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -92,8 +92,8 @@ mod full { } } - full_test!(log, "log", "0.3.4", "0.3.8"); - full_test!(libc, "libc", "0.2.28", "0.2.31"); + // full_test!(log, "log", "0.3.4", "0.3.8"); + // full_test!(libc, "libc", "0.2.28", "0.2.31"); // 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"); From 65d0d60f0f7f8c9ea4bc767081457cbcca1554f9 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 21 Nov 2018 14:18:49 +0100 Subject: [PATCH 375/553] Remove already-stable feature --- tests/cases/macros/new.rs | 2 +- tests/cases/macros/old.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cases/macros/new.rs b/tests/cases/macros/new.rs index bcc4bb969f8de..58c04fcf36594 100644 --- a/tests/cases/macros/new.rs +++ b/tests/cases/macros/new.rs @@ -1,4 +1,4 @@ -#![feature(decl_macro, use_extern_macros)] +#![feature(decl_macro)] pub struct Item; pub macro foo() { Item } diff --git a/tests/cases/macros/old.rs b/tests/cases/macros/old.rs index b1fc107f5c978..fd850798fd152 100644 --- a/tests/cases/macros/old.rs +++ b/tests/cases/macros/old.rs @@ -1,4 +1,4 @@ -#![feature(decl_macro, use_extern_macros)] +#![feature(decl_macro)] pub struct Item; pub macro foo() { Item } From 0515656fe665fc91665e52d070fe9cb94936aac7 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 21 Nov 2018 14:20:44 +0100 Subject: [PATCH 376/553] Allow type_alias_bounds in regions tests --- tests/cases/regions/new.rs | 2 ++ tests/cases/regions/old.rs | 2 ++ tests/cases/regions/stdout | 32 ++++++++++++++++---------------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/tests/cases/regions/new.rs b/tests/cases/regions/new.rs index c124198b04dd7..a87db392d40d4 100644 --- a/tests/cases/regions/new.rs +++ b/tests/cases/regions/new.rs @@ -1,3 +1,5 @@ +#![allow(type_alias_bounds)] + pub type A = fn(&bool); pub type B = for<'a> fn(&'a bool); diff --git a/tests/cases/regions/old.rs b/tests/cases/regions/old.rs index cd69b7b2ebe83..07d02bff24dd2 100644 --- a/tests/cases/regions/old.rs +++ b/tests/cases/regions/old.rs @@ -1,3 +1,5 @@ +#![allow(type_alias_bounds)] + pub type A = for<'a> fn(&'a bool); pub type B = fn(&bool); diff --git a/tests/cases/regions/stdout b/tests/cases/regions/stdout index 04f464969575d..d012a2110e871 100644 --- a/tests/cases/regions/stdout +++ b/tests/cases/regions/stdout @@ -1,48 +1,48 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: breaking changes in `D` - --> $REPO_PATH/tests/cases/regions/new.rs:7:1 + --> $REPO_PATH/tests/cases/regions/new.rs:9:1 | -7 | pub type D = ::IntoIter; +9 | pub type D = ::IntoIter; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: type error: expected std::iter::IntoIterator::Item, found std::iter::IntoIterator::IntoIter (breaking) error: breaking changes in `E` - --> $REPO_PATH/tests/cases/regions/new.rs:9:1 - | -9 | pub type E = T; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: type error: expected associated type, found type parameter (breaking) + --> $REPO_PATH/tests/cases/regions/new.rs:11:1 + | +11 | pub type E = T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected associated type, found type parameter (breaking) error: breaking changes in `abc` - --> $REPO_PATH/tests/cases/regions/new.rs:11:1 + --> $REPO_PATH/tests/cases/regions/new.rs:13:1 | -11 | pub fn abc(_: &bool) { } +13 | pub fn abc(_: &bool) { } | ^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: type error: expected bool, found reference (breaking) error: breaking changes in `def` - --> $REPO_PATH/tests/cases/regions/new.rs:13:1 + --> $REPO_PATH/tests/cases/regions/new.rs:15:1 | -13 | pub fn def(_: bool) { } +15 | pub fn def(_: bool) { } | ^^^^^^^^^^^^^^^^^^^^^^^ | = warning: type error: expected reference, found bool (breaking) error: breaking changes in `efg` - --> $REPO_PATH/tests/cases/regions/new.rs:15:1 + --> $REPO_PATH/tests/cases/regions/new.rs:17:1 | -15 | pub fn efg(_: &str) { } +17 | pub fn efg(_: &str) { } | ^^^^^^^^^^^^^^^^^^^^^^^ | = warning: type error: expected bound lifetime parameterBrAnon(0), found concrete lifetime (breaking) error: breaking changes in `fgh` - --> $REPO_PATH/tests/cases/regions/new.rs:17:1 + --> $REPO_PATH/tests/cases/regions/new.rs:19:1 | -17 | pub fn fgh(_: &'static str) { } +19 | pub fn fgh(_: &'static str) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: type error: expected bound lifetime parameterBrAnon(0), found concrete lifetime (breaking) From 046de6f434d59e41fb8ceeaa4e55a72c8c15c5d2 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 21 Nov 2018 14:20:59 +0100 Subject: [PATCH 377/553] Allow type_alias_bounds in ty_alias tests --- tests/cases/ty_alias/new.rs | 2 ++ tests/cases/ty_alias/old.rs | 2 ++ tests/cases/ty_alias/stdout | 28 ++++++++++++++-------------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/tests/cases/ty_alias/new.rs b/tests/cases/ty_alias/new.rs index cf912a36fa4ff..bd9a08714ebd5 100644 --- a/tests/cases/ty_alias/new.rs +++ b/tests/cases/ty_alias/new.rs @@ -1,3 +1,5 @@ +#![allow(type_alias_bounds)] + pub type A = u16; pub type B<'a, 'b : 'a, T> = (&'a T, &'b T); pub type C = T; diff --git a/tests/cases/ty_alias/old.rs b/tests/cases/ty_alias/old.rs index 833da24169297..432730d792b22 100644 --- a/tests/cases/ty_alias/old.rs +++ b/tests/cases/ty_alias/old.rs @@ -1,3 +1,5 @@ +#![allow(type_alias_bounds)] + pub type A = u8; pub type B<'a, T> = &'a T; pub type C<'a, T> = &'a T; diff --git a/tests/cases/ty_alias/stdout b/tests/cases/ty_alias/stdout index 0c28d4835061d..1eef78d287335 100644 --- a/tests/cases/ty_alias/stdout +++ b/tests/cases/ty_alias/stdout @@ -1,57 +1,57 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: breaking changes in `A` - --> $REPO_PATH/tests/cases/ty_alias/new.rs:1:1 + --> $REPO_PATH/tests/cases/ty_alias/new.rs:3:1 | -1 | pub type A = u16; +3 | pub type A = u16; | ^^^^^^^^^^^^^^^^^ | = warning: type error: expected u8, found u16 (breaking) error: breaking changes in `B` - --> $REPO_PATH/tests/cases/ty_alias/new.rs:2:1 + --> $REPO_PATH/tests/cases/ty_alias/new.rs:4:1 | -2 | pub type B<'a, 'b : 'a, T> = (&'a T, &'b T); +4 | pub type B<'a, 'b : 'a, T> = (&'a T, &'b T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: region parameter added (breaking) error: breaking changes in `C` - --> $REPO_PATH/tests/cases/ty_alias/new.rs:3:1 + --> $REPO_PATH/tests/cases/ty_alias/new.rs:5:1 | -3 | pub type C = T; +5 | pub type C = T; | ^^^^^^^^^^^^^^^^^^ | = warning: region parameter removed (breaking) error: breaking changes in `D` - --> $REPO_PATH/tests/cases/ty_alias/new.rs:4:1 + --> $REPO_PATH/tests/cases/ty_alias/new.rs:6:1 | -4 | pub type D<'a, T, U=Box> = (&'a T, U); +6 | pub type D<'a, T, U=Box> = (&'a T, U); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: defaulted type parameter added (non-breaking) = warning: type error: expected reference, found tuple (breaking) error: breaking changes in `E` - --> $REPO_PATH/tests/cases/ty_alias/new.rs:5:1 + --> $REPO_PATH/tests/cases/ty_alias/new.rs:7:1 | -5 | pub type E<'a, T, U> = (&'a T, U); +7 | pub type E<'a, T, U> = (&'a T, U); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: type parameter added (breaking) error: breaking changes in `F` - --> $REPO_PATH/tests/cases/ty_alias/new.rs:6:1 + --> $REPO_PATH/tests/cases/ty_alias/new.rs:8:1 | -6 | pub type F<'a> = &'a u8; +8 | pub type F<'a> = &'a u8; | ^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: defaulted type parameter removed (breaking) error: breaking changes in `G` - --> $REPO_PATH/tests/cases/ty_alias/new.rs:7:1 + --> $REPO_PATH/tests/cases/ty_alias/new.rs:9:1 | -7 | pub type G<'a> = (&'a u8); +9 | pub type G<'a> = (&'a u8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: type parameter removed (breaking) From 4e9912534167dd1f4efa3a2ef5045efacd0e96e0 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 21 Nov 2018 14:25:46 +0100 Subject: [PATCH 378/553] Refactor example testing code. --- tests/examples.rs | 239 ++++++++++++++++++++++++---------------------- 1 file changed, 124 insertions(+), 115 deletions(-) diff --git a/tests/examples.rs b/tests/examples.rs index 3293d042b25b7..0fcfe0b47b9e4 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -6,128 +6,137 @@ mod features { use std::path::Path; use std::process::{Command, Stdio}; + fn test_example(path: &Path) { + let mut success = true; + + let current_dir = env::current_dir().expect("could not determine current dir"); + let subst = format!("s#{}#$REPO_PATH#g", current_dir.to_str().unwrap()); + + let out_file = path.join("stdout"); + + 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 stdout = File::create(&out_file).expect("could not create `stdout` file"); + + success &= Command::new("rustc") + .args(&["--crate-type=lib", "-o", &old_rlib]) + .arg(path.join("old.rs")) + .env("RUST_BACKTRACE", "full") + .stdin(Stdio::null()) + .status() + .expect("could not run rustc") + .success(); + + assert!(success, "couldn't compile old"); + + success &= Command::new("rustc") + .args(&["--crate-type=lib", "-o", &new_rlib]) + .arg(path.join("new.rs")) + .env("RUST_BACKTRACE", "full") + .stdin(Stdio::null()) + .status() + .expect("could not run rustc") + .success(); + + assert!(success, "couldn't compile new"); + + let mut sed_child = Command::new("sed") + .arg(&subst) + .stdin(Stdio::piped()) + .stdout(stdout) + .spawn() + .expect("could not run sed"); + + let (err_pipe, out_pipe) = if let Some(ref stdin) = sed_child.stdin { + let fd = stdin.as_raw_fd(); + unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } + } else { + panic!("could not pipe to sed"); + }; + + success &= Command::new("./target/debug/rust-semverver") + .args(&["--crate-type=lib", "-Zverbose", + "--extern", &format!("old={}", old_rlib), + "--extern", &format!("new={}", new_rlib), + "tests/helper/test.rs"]) + .env("RUST_BACKTRACE", "full") + .env("RUST_SEMVER_CRATE_VERSION", "1.0.0") + .stdin(Stdio::null()) + .stdout(out_pipe) + .stderr(err_pipe) + .status() + .expect("could not run rust-semverver") + .success(); + + assert!(success, "rust-semverver"); + + success &= sed_child.wait().expect("could not wait for sed child").success(); + } + + assert!(success, "sed"); + + eprintln!("path: {}", out_file.to_str().unwrap()); + success &= Command::new("git") + .args(&["diff", "--exit-code", out_file.to_str().unwrap()]) + .env("PAGER", "") + .status() + .expect("could not run git diff") + .success(); + + assert!(success, "git"); + + Command::new("rm") + .args(&[&old_rlib, &new_rlib]) + .status() + .expect("could not run rm"); + } + macro_rules! test { ($name:ident) => { #[test] fn $name() { - let mut success = true; - - let current_dir = env::current_dir().expect("could not determine current dir"); - let subst = format!("s#{}#$REPO_PATH#g", current_dir.to_str().unwrap()); let path = Path::new("tests/cases").join(stringify!($name)); - - let out_file = path.join("stdout"); - - 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 stdout = File::create(&out_file).expect("could not create `stdout` file"); - - success &= Command::new("rustc") - .args(&["--crate-type=lib", "-o", &old_rlib]) - .arg(path.join("old.rs")) - .env("RUST_BACKTRACE", "full") - .stdin(Stdio::null()) - .status() - .expect("could not run rustc") - .success(); - - assert!(success, "couldn't compile old"); - - success &= Command::new("rustc") - .args(&["--crate-type=lib", "-o", &new_rlib]) - .arg(path.join("new.rs")) - .env("RUST_BACKTRACE", "full") - .stdin(Stdio::null()) - .status() - .expect("could not run rustc") - .success(); - - assert!(success, "couldn't compile new"); - - let mut sed_child = Command::new("sed") - .arg(&subst) - .stdin(Stdio::piped()) - .stdout(stdout) - .spawn() - .expect("could not run sed"); - - let (err_pipe, out_pipe) = if let Some(ref stdin) = sed_child.stdin { - let fd = stdin.as_raw_fd(); - unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } - } else { - panic!("could not pipe to sed"); - }; - - success &= Command::new("./target/debug/rust-semverver") - .args(&["--crate-type=lib", "-Zverbose", - "--extern", &format!("old={}", old_rlib), - "--extern", &format!("new={}", new_rlib), - "tests/helper/test.rs"]) - .env("RUST_BACKTRACE", "full") - .env("RUST_SEMVER_CRATE_VERSION", "1.0.0") - .stdin(Stdio::null()) - .stdout(out_pipe) - .stderr(err_pipe) - .status() - .expect("could not run rust-semverver") - .success(); - - assert!(success, "rust-semverver"); - - success &= sed_child.wait().expect("could not wait for sed child").success(); - } - - assert!(success, "sed"); - - eprintln!("path: {}", out_file.to_str().unwrap()); - success &= Command::new("git") - .args(&["diff", "--exit-code", out_file.to_str().unwrap()]) - .env("PAGER", "") - .status() - .expect("could not run git diff") - .success(); - - assert!(success, "git"); - - Command::new("rm") - .args(&[&old_rlib, &new_rlib]) - .status() - .expect("could not run rm"); + test_example(&path); } + }; + ($($name:ident),*) => { + $(test!($name);)* } } - test!(addition); - test!(addition_path); - test!(addition_use); - test!(bounds); - test!(circular); - test!(consts); - test!(enums); - test!(func); - test!(func_local_items); - test!(infer); - test!(infer_regress); - test!(inherent_impls); - test!(issue_34); - test!(issue_50); - test!(kind_change); - test!(macros); - test!(max_priv); - test!(mix); - test!(pathologic_paths); - test!(pub_use); - test!(regions); - test!(removal); - test!(removal_path); - test!(removal_use); - test!(sealed_traits); - test!(structs); - test!(swap); - test!(traits); - test!(trait_impls); - test!(trait_objects); - test!(ty_alias); + test! { + addition, + addition_path, + addition_use, + bounds, + circular, + consts, + enums, + func, + func_local_items, + infer, + infer_regress, + inherent_impls, + issue_34, + issue_50, + kind_change, + macros, + max_priv, + mix, + pathologic_paths, + pub_use, + regions, + removal, + removal_path, + removal_use, + sealed_traits, + structs, + swap, + traits, + trait_impls, + trait_objects, + ty_alias + } } From f44186342a3e3d1e3d4f6acfb248595e878b0ee1 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 21 Nov 2018 15:03:54 +0100 Subject: [PATCH 379/553] Refactor full tests and add OSX support --- tests/full.rs | 140 +- tests/full_cases/libc-0.2.28-0.2.31.osx | 2371 +++++++++++++++++++++++ 2 files changed, 2449 insertions(+), 62 deletions(-) diff --git a/tests/full.rs b/tests/full.rs index 89ff7b676bb2e..43982257e7238 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -3,25 +3,19 @@ mod full { use std::env; use std::fs::File; use std::os::unix::io::{AsRawFd, FromRawFd}; - use std::path::Path; + use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; - macro_rules! full_test { - ($name:ident, $crate_name:expr, $old_version:expr, $new_version:expr) => { - #[test] - fn $name() { - let mut success = true; - - let old_version = concat!($crate_name, ":", $old_version); - let new_version = concat!($crate_name, ":", $new_version); + fn test_full(crate_name: &str, old_version: &str, new_version: &str) { + let mut success = true; - let prog = concat!(r#" + let prog = format!(r#" # wait for the actual output - /^version bump/ { + /^version bump/ {{ doprint = 1; - } + }} - { + {{ # check the environ for filtering if (ENVIRON["RUST_LOG"] == "debug") doprint = 1; @@ -31,69 +25,91 @@ mod full { next; # sanitize paths - gsub(/-->.*"#, $crate_name, r#"/, "--> "#, $crate_name, r#"", $0); + gsub(/-->.*{crate_name}/, "--> {crate_name}", $0); print; - }"#, $crate_name, $crate_name); - let out_file = Path::new("tests/full_cases") - .join(concat!($crate_name, "-", $old_version, "-", $new_version)); - - if let Some(path) = env::var_os("PATH") { - let mut paths = env::split_paths(&path).collect::>(); - let current_dir = env::current_dir().expect("could not determine current dir"); - paths.insert(0, current_dir.join("target/debug")); - let new_path = env::join_paths(paths).unwrap(); - env::set_var("PATH", &new_path); - } else { - eprintln!("no path!"); - } - - let stdout = File::create(&out_file).expect("could not create `stdout` file"); - let out_file = out_file.to_str().unwrap(); - - let mut awk_child = Command::new("awk") - .arg(&prog) - .stdin(Stdio::piped()) - .stdout(stdout) - .spawn() - .expect("could not run awk"); - - let (err_pipe, out_pipe) = if let Some(ref stdin) = awk_child.stdin { - let fd = stdin.as_raw_fd(); - unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } - } else { - panic!("could not pipe to awk"); - }; - - success &= Command::new("./target/debug/cargo-semver") - .args(&["-S", &old_version, "-C", &new_version]) - .env("RUST_BACKTRACE", "full") - .stdin(Stdio::null()) - .stdout(out_pipe) - .stderr(err_pipe) - .status() - .expect("could not run cargo semver") - .success(); + }}{crate_name}{crate_name}"#, crate_name = crate_name); + + eprintln!("prog:\n{}",prog); + + let base_out_file = Path::new("tests/full_cases") + .join(format!("{}-{}-{}", crate_name, old_version, new_version)); + + let out_file = if cfg!(target_os = "macos") { + let p: PathBuf = format!("{}.osx", base_out_file.display()).into(); + if p.exists() { p } else { base_out_file } + } else { + base_out_file + }; + assert!(out_file.exists()); + + if let Some(path) = env::var_os("PATH") { + let mut paths = env::split_paths(&path).collect::>(); + let current_dir = env::current_dir().expect("could not determine current dir"); + paths.insert(0, current_dir.join("target/debug")); + let new_path = env::join_paths(paths).unwrap(); + env::set_var("PATH", &new_path); + } else { + eprintln!("no path!"); + } + + let stdout = File::create(&out_file).expect("could not create `stdout` file"); + let out_file = out_file.to_str().unwrap(); + + let mut awk_child = Command::new("awk") + .arg(&prog) + .stdin(Stdio::piped()) + .stdout(stdout) + .spawn() + .expect("could not run awk"); - assert!(success, "cargo semver"); + let (err_pipe, out_pipe) = if let Some(ref stdin) = awk_child.stdin { + let fd = stdin.as_raw_fd(); + unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } + } else { + panic!("could not pipe to awk"); + }; - success &= awk_child.wait().expect("could not wait for awk child").success(); + let old_version = format!("{}:{}", crate_name, old_version); + let new_version = format!("{}:{}", crate_name, new_version); - assert!(success, "awk"); + success &= Command::new("./target/debug/cargo-semver") + .args(&["-S", &old_version, "-C", &new_version]) + .env("RUST_BACKTRACE", "full") + .stdin(Stdio::null()) + .stdout(out_pipe) + .stderr(err_pipe) + .status() + .expect("could not run cargo semver") + .success(); - success &= Command::new("git") - .args(&["diff", "--exit-code", out_file]) + assert!(success, "cargo semver"); + + success &= awk_child.wait().expect("could not wait for awk child").success(); + + assert!(success, "awk"); + + success &= Command::new("git") + .args(&["diff", "--exit-code", out_file]) .env("PAGER", "") .status() .expect("could not run git diff") .success(); - assert!(success, "git"); + assert!(success, "git"); + + } + + macro_rules! full_test { + ($name:ident, $crate_name:expr, $old_version:expr, $new_version:expr) => { + #[test] + fn $name() { + test_full($crate_name, $old_version, $new_version); } } } - // full_test!(log, "log", "0.3.4", "0.3.8"); - // full_test!(libc, "libc", "0.2.28", "0.2.31"); + full_test!(log, "log", "0.3.4", "0.3.8"); + full_test!(libc, "libc", "0.2.28", "0.2.31"); // 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"); diff --git a/tests/full_cases/libc-0.2.28-0.2.31.osx b/tests/full_cases/libc-0.2.28-0.2.31.osx index e69de29bb2d1d..6956991669aa3 100644 --- a/tests/full_cases/libc-0.2.28-0.2.31.osx +++ b/tests/full_cases/libc-0.2.28-0.2.31.osx @@ -0,0 +1,2371 @@ +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 + From cb2eeb1ac9d9f06185d8ef13732595be7d26a664 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 21 Nov 2018 15:19:44 +0100 Subject: [PATCH 380/553] Travis should test OSX --- .travis.yml | 46 ++++++++++++++++++---------------------------- ci/run.sh | 16 ++++++++++++++++ 2 files changed, 34 insertions(+), 28 deletions(-) create mode 100755 ci/run.sh diff --git a/.travis.yml b/.travis.yml index 2b72343603188..d5990e1c88bcf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,33 +1,23 @@ language: rust - rust: nightly +sudo: false -os: - - linux -# coming soon: -# - osx - -env: - global: - - RUST_BACKTRACE=full - -script: - - | - set -e - if [ "$TRAVIS_OS_NAME" == "osx" ]; then - # test output for a different libc is expected to be different - mv tests/full_cases/libc-0.2.28-0.2.31.osx tests/full_cases/libc-0.2.28-0.2.31 - fi - - cargo build - cargo test --verbose +matrix: + fast_finish: true + include: + # Targets + - name: "linux" + os: linux + env: RUST_BACKTRACE=full + - name: "osx" + os: osx + osx_image: xcode10 + env: RUST_BACKTRACE=full - # install - mkdir -p ~/rust/cargo/bin - cp target/debug/cargo-semver ~/rust/cargo/bin - cp target/debug/rust-semverver ~/rust/cargo/bin + # Tools: + - name: "Shellcheck" + script: + - shellcheck --version + - shellcheck ci/*.sh - # become semververver - eval "current_version=$(grep -e '^version = .*$' Cargo.toml | cut -d ' ' -f 3)" - PATH=~/rust/cargo/bin:$PATH cargo semver | tee semver_out - (head -n 1 semver_out | grep "\-> $current_version") || (echo "versioning mismatch" && return 1) +script: sh ci/run.sh diff --git a/ci/run.sh b/ci/run.sh new file mode 100755 index 0000000000000..3671aaef99bb4 --- /dev/null +++ b/ci/run.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh + +set -ex + +cargo build +cargo test --verbose + +# install +mkdir -p ~/rust/cargo/bin +cp target/debug/cargo-semver ~/rust/cargo/bin +cp target/debug/rust-semverver ~/rust/cargo/bin + +# become semververver +eval "current_version=$(grep -e '^version = .*$' Cargo.toml | cut -d ' ' -f 3)" +PATH=~/rust/cargo/bin:$PATH cargo semver | tee semver_out +(head -n 1 semver_out | grep "\-> $current_version") || (echo "versioning mismatch" && return 1) From 01a41861719e8a7828857d4c0539160e3aab536d Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 21 Nov 2018 15:22:20 +0100 Subject: [PATCH 381/553] Fix shellcheck issues --- ci/run.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/run.sh b/ci/run.sh index 3671aaef99bb4..d518981e02ce4 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -11,6 +11,6 @@ cp target/debug/cargo-semver ~/rust/cargo/bin cp target/debug/rust-semverver ~/rust/cargo/bin # become semververver -eval "current_version=$(grep -e '^version = .*$' Cargo.toml | cut -d ' ' -f 3)" +current_version=$(grep -e '^version = .*$' Cargo.toml | cut -d ' ' -f 3) PATH=~/rust/cargo/bin:$PATH cargo semver | tee semver_out -(head -n 1 semver_out | grep "\-> $current_version") || (echo "versioning mismatch" && return 1) +(head -n 1 semver_out | grep "\\-> $current_version") || (echo "versioning mismatch" && return 1) From ce92b8a95eaea4e475c6de378d80e488928c4c77 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 21 Nov 2018 15:22:39 +0100 Subject: [PATCH 382/553] Apply rustfmt --- src/bin/cargo_semver.rs | 116 ++++-- src/bin/rust_semverver.rs | 78 ++-- src/semcheck/changes.rs | 672 ++++++++++++++++++++------------- src/semcheck/mapping.rs | 76 ++-- src/semcheck/mismatch.rs | 89 +++-- src/semcheck/translate.rs | 503 +++++++++++++------------ src/semcheck/traverse.rs | 760 +++++++++++++++++++++----------------- src/semcheck/typeck.rs | 227 ++++++------ tests/debug.rs | 4 +- tests/examples.rs | 18 +- tests/full.rs | 31 +- 11 files changed, 1465 insertions(+), 1109 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index eb40ab39f5213..947db16928972 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -10,13 +10,13 @@ extern crate log; use crates_io::{Crate, Registry}; -use cargo::exit_with_error; -use cargo::core::{Package, PackageId, Source, SourceId, Workspace}; use cargo::core::compiler::CompileMode; +use cargo::core::{Package, PackageId, Source, SourceId, Workspace}; +use cargo::exit_with_error; use cargo::ops::{compile, CompileOptions}; -use cargo::util::{CargoError, CargoResult, CliError}; use cargo::util::config::Config; use cargo::util::important_paths::find_root_manifest_for_wd; +use cargo::util::{CargoError, CargoResult, CliError}; use getopts::{Matches, Options}; @@ -25,7 +25,7 @@ use std::error; use std::fmt; use std::io::Write; use std::path::PathBuf; -use std::process::{Stdio, Command}; +use std::process::{Command, Stdio}; /// Very simple error representation. #[derive(Debug)] @@ -51,15 +51,18 @@ fn exact_search(query: &str) -> CargoResult { registry .search(query, 1) - .map_err(|e| - Error(format!("failed to retrieve search results from the registry: {}", e)) - .into()) + .map_err(|e| { + Error(format!( + "failed to retrieve search results from the registry: {}", + e + )) + .into() + }) .and_then(|(mut crates, _)| { crates .drain(..) .find(|krate| krate.name == query) - .ok_or_else(|| Error(format!("failed to find a matching crate `{}`", query)) - .into()) + .ok_or_else(|| Error(format!("failed to find a matching crate `{}`", query)).into()) }) } @@ -114,17 +117,16 @@ impl<'a> WorkInfo<'a> { let workspace = Workspace::new(&manifest_path, config)?; let package = workspace.load(&manifest_path)?; - Ok(WorkInfo { - package, - workspace, - }) + Ok(WorkInfo { package, workspace }) } /// Construct a package/workspace pair by fetching the package of a specified name and /// version. - fn remote(config: &'a Config, source: &mut SourceInfo<'a>, info: &NameAndVersion) - -> CargoResult> - { + fn remote( + config: &'a Config, + source: &mut SourceInfo<'a>, + info: &NameAndVersion, + ) -> CargoResult> { // TODO: fall back to locally cached package instance, or better yet, search for it // first. let package_id = PackageId::new(info.name, info.version, &source.id)?; @@ -139,9 +141,12 @@ impl<'a> WorkInfo<'a> { } /// Obtain the paths to the produced rlib and the dependency output directory. - fn rlib_and_dep_output(&self, config: &'a Config, name: &str, current: bool) - -> CargoResult<(PathBuf, PathBuf)> - { + fn rlib_and_dep_output( + &self, + config: &'a Config, + name: &str, + current: bool, + ) -> CargoResult<(PathBuf, PathBuf)> { let opts = CompileOptions::new(config, CompileMode::Build).unwrap(); if current { @@ -161,7 +166,6 @@ impl<'a> WorkInfo<'a> { Ok((rlib.1.clone(), compilation.deps_output)) } - } /// Perform the heavy lifting. @@ -188,7 +192,10 @@ fn do_main(config: &Config, matches: &Matches, explain: bool) -> CargoResult<()> return Err(Error("spec has to be of form `name:version`".to_owned()).into()); } - Ok(NameAndVersion { name: name, version: version }) + Ok(NameAndVersion { + name: name, + version: version, + }) } let mut source = SourceInfo::new(config)?; @@ -214,7 +221,10 @@ fn do_main(config: &Config, matches: &Matches, explain: bool) -> CargoResult<()> (work_info, version) } else { let stable_crate = exact_search(&name)?; - let info = NameAndVersion { name: &name, version: &stable_crate.max_version }; + let info = NameAndVersion { + name: &name, + version: &stable_crate.max_version, + }; let work_info = WorkInfo::remote(config, &mut source, &info)?; (work_info, stable_crate.max_version.clone()) @@ -224,11 +234,13 @@ fn do_main(config: &Config, matches: &Matches, explain: bool) -> CargoResult<()> let (stable_rlib, stable_deps_output) = stable.rlib_and_dep_output(config, &name, false)?; 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()); + println!( + "--extern old={} -L{} --extern new={} -L{}", + stable_rlib.display(), + stable_deps_output.display(), + current_rlib.display(), + current_deps_output.display() + ); return Ok(()); } @@ -250,10 +262,12 @@ fn do_main(config: &Config, matches: &Matches, explain: bool) -> CargoResult<()> 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;"))?; + stdin.write_fmt(format_args!( + "#[allow(unused_extern_crates)] \ + extern crate old; \ + #[allow(unused_extern_crates)] \ + extern crate new;" + ))?; } else { return Err(Error("could not pipe to rustc (wtf?)".to_owned()).into()); } @@ -296,12 +310,30 @@ fn main() { opts.optflag("V", "version", "print version information and exit"); opts.optflag("e", "explain", "print detailed error explanations"); opts.optflag("d", "debug", "print command to debug and exit"); - 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.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", + ); let config = match Config::default() { Ok(cfg) => cfg, @@ -323,15 +355,17 @@ fn main() { return; } - if (matches.opt_present("s") && matches.opt_present("S")) || - matches.opt_count("s") > 1 || matches.opt_count("S") > 1 + 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"; err(&config, Error(msg.to_owned()).into()); } - if (matches.opt_present("c") && matches.opt_present("C")) || - matches.opt_count("c") > 1 || matches.opt_count("C") > 1 + 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"; err(&config, Error(msg.to_owned()).into()); diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 2198189d68b71..8ee7aa93698bd 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -6,9 +6,9 @@ extern crate getopts; #[macro_use] extern crate log; extern crate rustc; +extern crate rustc_codegen_utils; extern crate rustc_driver; extern crate rustc_errors; -extern crate rustc_codegen_utils; extern crate rustc_metadata; extern crate semverver; extern crate syntax; @@ -16,12 +16,12 @@ extern crate syntax; use semverver::semcheck::run_analysis; use rustc::hir::def_id::*; -use rustc_metadata::cstore::CStore; -use rustc::session::{config, Session}; -use rustc::session::config::{Input, ErrorOutputType}; use rustc::middle::cstore::ExternCrate; +use rustc::session::config::{ErrorOutputType, Input}; +use rustc::session::{config, Session}; +use rustc_metadata::cstore::CStore; -use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; +use rustc_driver::{driver, Compilation, CompilerCalls, RustcDefaultCalls}; use rustc_codegen_utils::codegen_backend::CodegenBackend; @@ -49,8 +49,9 @@ fn callback(state: &driver::CompileState, version: &str, verbose: bool) { }; match *tcx.extern_crate(def_id) { - Some(ExternCrate { span, direct: true, ..}) if span.data().lo.to_usize() > 0 => - Some((span.data().lo.to_usize(), def_id)), + Some(ExternCrate { + span, direct: true, .. + }) if span.data().lo.to_usize() > 0 => Some((span.data().lo.to_usize(), def_id)), _ => None, } }) @@ -101,55 +102,58 @@ impl SemVerVerCompilerCalls { } impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { - fn early_callback(&mut self, - matches: &getopts::Matches, - sopts: &config::Options, - cfg: &ast::CrateConfig, - descriptions: &rustc_errors::registry::Registry, - output: ErrorOutputType) - -> Compilation { + fn early_callback( + &mut self, + matches: &getopts::Matches, + sopts: &config::Options, + cfg: &ast::CrateConfig, + descriptions: &rustc_errors::registry::Registry, + output: ErrorOutputType, + ) -> Compilation { debug!("running rust-semverver early_callback"); self.default .early_callback(matches, sopts, cfg, descriptions, output) } - fn no_input(&mut self, - matches: &getopts::Matches, - sopts: &config::Options, - cfg: &ast::CrateConfig, - odir: &Option, - ofile: &Option, - descriptions: &rustc_errors::registry::Registry) - -> Option<(Input, Option)> { + fn no_input( + &mut self, + matches: &getopts::Matches, + sopts: &config::Options, + cfg: &ast::CrateConfig, + odir: &Option, + ofile: &Option, + descriptions: &rustc_errors::registry::Registry, + ) -> Option<(Input, Option)> { debug!("running rust-semverver no_input"); self.default .no_input(matches, sopts, cfg, odir, ofile, descriptions) } - fn late_callback(&mut self, - trans_crate: &CodegenBackend, - matches: &getopts::Matches, - sess: &Session, - cstore: &CStore, - input: &Input, - odir: &Option, - ofile: &Option) - -> Compilation { + fn late_callback( + &mut self, + trans_crate: &CodegenBackend, + matches: &getopts::Matches, + sess: &Session, + cstore: &CStore, + input: &Input, + odir: &Option, + ofile: &Option, + ) -> Compilation { debug!("running rust-semverver late_callback"); self.default .late_callback(trans_crate, matches, sess, cstore, input, odir, ofile) } - fn build_controller(self: Box, - sess: &Session, - matches: &getopts::Matches) - -> driver::CompileController<'a> { + fn build_controller( + self: Box, + sess: &Session, + matches: &getopts::Matches, + ) -> driver::CompileController<'a> { let default = self.get_default(); let version = self.get_version().clone(); let SemVerVerCompilerCalls { verbose, .. } = *self; let mut controller = CompilerCalls::build_controller(default, sess, matches); - let old_callback = - std::mem::replace(&mut controller.after_analysis.callback, box |_| {}); + let old_callback = std::mem::replace(&mut controller.after_analysis.callback, box |_| {}); controller.after_analysis.callback = box move |state| { debug!("running rust-semverver after_analysis callback"); diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index b596bbfe51409..bbc80dd1e3323 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -11,13 +11,13 @@ use rustc::hir::def_id::DefId; use rustc::session::Session; -use rustc::ty::Predicate; use rustc::ty::error::TypeError; +use rustc::ty::Predicate; use semver::Version; -use std::collections::{BTreeSet, BTreeMap, HashMap}; use std::cmp::Ordering; +use std::collections::{BTreeMap, BTreeSet, HashMap}; use std::fmt; use syntax::symbol::Symbol; @@ -79,9 +79,7 @@ impl<'a> fmt::Display for Name { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Name::Symbol(name) => write!(f, "`{}`", name), - Name::ImplDesc(ref desc) => { - write!(f, "`{}`", desc) - }, + Name::ImplDesc(ref desc) => write!(f, "`{}`", desc), } } } @@ -237,7 +235,10 @@ pub enum ChangeType<'tcx> { /// 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 }, + VariantStyleChanged { + now_struct: bool, + total_private: bool, + }, /// A function has changed it's constness. FnConstChanged { now_const: bool }, /// A method either gained or lost a `self` parameter. @@ -257,7 +258,10 @@ pub enum ChangeType<'tcx> { /// 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 }, + 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). @@ -318,134 +322,185 @@ impl<'tcx> ChangeType<'tcx> { /// 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 + 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, +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 iff .", - VarianceTightened => -"The variance of a type or region parameter in an item tightens iff .", - VarianceChanged { .. } => -"Switching the variance of a type or region parameter is breaking, if it goes -from covariant to contravariant, or vice-versa.", - RegionParameterAdded => -"Adding a new region parameter is a breaking change, because it can break +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 iff ." + } + VarianceTightened => { + "The variance of a type or region parameter in an item tightens iff ." + } + VarianceChanged { .. } => { + "Switching the variance of a type or region parameter is breaking, if it goes +from covariant to contravariant, or vice-versa." + } + 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 +before." + } + RegionParameterRemoved => { + "Removing a region parameter is a breaking change, because it can break explicit type annotations, well as prevent region inference working as -before.", - TypeParameterAdded { defaulted: true } => -"Adding a new defaulted type parameter is a non-breaking change, because +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 +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, +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 { public: _, total_public: _ } => -"Adding a field to an enum variant is breaking, as matches on the variant are +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 { + public: _, + total_public: _, + } => { + "Adding a field to an enum variant is breaking, as matches on the variant are invalidated. In case of structs, this only holds for public fields, or the -first private field being added.", - VariantFieldRemoved { public: _, total_public: _ } => -"Removing a field from an enum variant 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 +first private field being added." + } + VariantFieldRemoved { + public: _, + total_public: _, + } => { + "Removing a field from an enum variant 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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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.", +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.", } } @@ -461,10 +516,12 @@ impl<'a> fmt::Display for ChangeType<'a> { 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", + 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", @@ -473,38 +530,65 @@ impl<'a> fmt::Display for ChangeType<'a> { TypeParameterRemoved { defaulted: false } => "type parameter removed", VariantAdded => "enum variant added", VariantRemoved => "enum variant removed", - VariantFieldAdded { public: true, total_public: true } => - "public variant field added to variant with no private fields", - VariantFieldAdded { public: true, total_public: false } => - "public variant field added to variant with private fields", - VariantFieldAdded { public: false, total_public: true } => - "variant field added to variant with no private fields", - VariantFieldAdded { public: false, total_public: false } => - "variant field added to variant with private fields", - VariantFieldRemoved { public: true, total_public: true } => - "public variant field removed from variant with no private fields", - VariantFieldRemoved { public: true, total_public: false } => - "public variant field removed from variant with private fields", - VariantFieldRemoved { public: false, total_public: true } => - "variant field removed from variant with no private fields", - VariantFieldRemoved { public: false, total_public: false } => - "variant field removed from variant with private fields", - VariantStyleChanged { now_struct: true, total_private: true } => - "variant with no public fields changed to a struct variant", - VariantStyleChanged { now_struct: true, total_private: false } => - "variant changed to a struct variant", - VariantStyleChanged { now_struct: false, total_private: true } => - "variant with no public fields changed to a tuple variant", - VariantStyleChanged { now_struct: false, total_private: false } => - "variant changed to a tuple variant", + VariantFieldAdded { + public: true, + total_public: true, + } => "public variant field added to variant with no private fields", + VariantFieldAdded { + public: true, + total_public: false, + } => "public variant field added to variant with private fields", + VariantFieldAdded { + public: false, + total_public: true, + } => "variant field added to variant with no private fields", + VariantFieldAdded { + public: false, + total_public: false, + } => "variant field added to variant with private fields", + VariantFieldRemoved { + public: true, + total_public: true, + } => "public variant field removed from variant with no private fields", + VariantFieldRemoved { + public: true, + total_public: false, + } => "public variant field removed from variant with private fields", + VariantFieldRemoved { + public: false, + total_public: true, + } => "variant field removed from variant with no private fields", + VariantFieldRemoved { + public: false, + total_public: false, + } => "variant field removed from variant with private fields", + VariantStyleChanged { + now_struct: true, + total_private: true, + } => "variant with no public fields changed to a struct variant", + VariantStyleChanged { + now_struct: true, + total_private: false, + } => "variant changed to a struct variant", + VariantStyleChanged { + now_struct: false, + total_private: true, + } => "variant with no public fields changed to a tuple variant", + VariantStyleChanged { + now_struct: false, + total_private: false, + } => "variant changed to a tuple variant", 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 { + 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", @@ -512,12 +596,16 @@ impl<'a> fmt::Display for ChangeType<'a> { 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 } => + BoundsLoosened { + ref pred, + trait_def, + } => { if trait_def { - return write!(f, "removed bound on trait definition: `{}`", pred) + return write!(f, "removed bound on trait definition: `{}`", pred); } else { - return write!(f, "removed bound: `{}`", pred) - }, + 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", @@ -542,7 +630,7 @@ pub struct Change<'tcx> { /// The new definition span of the item. new_span: Span, /// Whether to output changes. Used to distinguish all-private items. - output: bool + output: bool, } impl<'tcx> Change<'tcx> { @@ -575,37 +663,37 @@ impl<'tcx> Change<'tcx> { 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 => (), + 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 => (), } } @@ -647,9 +735,10 @@ impl<'tcx> Change<'tcx> { if cat == Breaking { builder.span_warn(span, &sub_msg); } else { - builder.span_note(span, &sub_msg,); + builder.span_note(span, &sub_msg); } - } else if cat == Breaking { // change.1 == None from here on. + } else if cat == Breaking { + // change.1 == None from here on. builder.warn(&sub_msg); } else { builder.note(&sub_msg); @@ -696,9 +785,7 @@ pub struct ChangeSet<'tcx> { 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.spans.entry(def_span).or_insert_with(|| old); self.path_changes .entry(old) .or_insert_with(|| PathChange::new(name, def_span)); @@ -726,13 +813,15 @@ impl<'tcx> ChangeSet<'tcx> { } /// 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) { + 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); @@ -741,10 +830,7 @@ impl<'tcx> ChangeSet<'tcx> { } /// Add a new change entry for the given trait impl. - pub fn new_change_impl(&mut self, - def_id: DefId, - desc: String, - span: Span) { + 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); @@ -770,17 +856,15 @@ impl<'tcx> ChangeSet<'tcx> { /// Set up reporting for the changes associated with a given `DefId`. pub fn set_output(&mut self, old: DefId) { let max = &mut self.max; - self.changes - .get_mut(&old) - .map(|change| { - let cat = change.to_category(); + self.changes.get_mut(&old).map(|change| { + let cat = change.to_category(); - if cat > *max { - *max = cat; - } + if cat > *max { + *max = cat; + } - change.output = true - }); + change.output = true + }); } /// Check whether an item with the given id has undergone breaking changes. @@ -816,7 +900,10 @@ impl<'tcx> ChangeSet<'tcx> { } } - println!("version bump: {} -> ({}) -> {}", version, self.max, new_version); + println!( + "version bump: {} -> ({}) -> {}", + version, self.max, new_version + ); } else { println!("max change: {}, could not parse {}", self.max, version); } @@ -835,16 +922,16 @@ impl<'tcx> ChangeSet<'tcx> { #[cfg(test)] pub mod tests { - use quickcheck::*; pub use super::*; + use quickcheck::*; use rustc::hir::def_id::DefId; use std::cmp::{max, min}; - use syntax_pos::BytePos; use syntax_pos::hygiene::SyntaxContext; use syntax_pos::symbol::Interner; + use syntax_pos::BytePos; /// A wrapper for `Span` that can be randomly generated. #[derive(Clone, Debug)] @@ -876,7 +963,7 @@ pub mod tests { impl Arbitrary for DefId_ { fn arbitrary(g: &mut G) -> DefId_ { - use rustc::hir::def_id::{DefId, CrateNum, DefIndex}; + use rustc::hir::def_id::{CrateNum, DefId, DefIndex}; let a: u32 = Arbitrary::arbitrary(g); let b: u32 = Arbitrary::arbitrary(g); @@ -895,18 +982,42 @@ pub mod tests { KindDifference, RegionParameterAdded, RegionParameterRemoved, - TypeParameterAdded { defaulted: bool }, - TypeParameterRemoved { defaulted: bool }, + TypeParameterAdded { + defaulted: bool, + }, + TypeParameterRemoved { + defaulted: bool, + }, VariantAdded, VariantRemoved, - VariantFieldAdded { public: bool, total_public: bool }, - VariantFieldRemoved { public: bool, total_public: bool }, - VariantStyleChanged { now_struct: bool, total_private: bool }, - FnConstChanged { now_const: bool }, - MethodSelfChanged { now_self: bool }, - TraitItemAdded { defaulted: bool, sealed_trait: bool }, - TraitItemRemoved { defaulted: bool }, - TraitUnsafetyChanged { now_unsafe: bool }, + VariantFieldAdded { + public: bool, + total_public: bool, + }, + VariantFieldRemoved { + public: bool, + total_public: bool, + }, + VariantStyleChanged { + now_struct: bool, + total_private: bool, + }, + FnConstChanged { + now_const: bool, + }, + MethodSelfChanged { + now_self: bool, + }, + TraitItemAdded { + defaulted: bool, + sealed_trait: bool, + }, + TraitItemRemoved { + defaulted: bool, + }, + TraitUnsafetyChanged { + now_unsafe: bool, + }, Unknown, } @@ -918,28 +1029,46 @@ pub mod tests { ChangeType_::KindDifference => KindDifference, ChangeType_::RegionParameterAdded => RegionParameterAdded, ChangeType_::RegionParameterRemoved => RegionParameterRemoved, - ChangeType_::TypeParameterAdded { defaulted } => - TypeParameterAdded { defaulted }, - ChangeType_::TypeParameterRemoved { defaulted } => - TypeParameterRemoved { defaulted }, + ChangeType_::TypeParameterAdded { defaulted } => TypeParameterAdded { defaulted }, + ChangeType_::TypeParameterRemoved { defaulted } => { + TypeParameterRemoved { defaulted } + } ChangeType_::VariantAdded => VariantAdded, ChangeType_::VariantRemoved => VariantRemoved, - ChangeType_::VariantFieldAdded { public, total_public } => - VariantFieldAdded { public, total_public }, - ChangeType_::VariantFieldRemoved { public, total_public } => - VariantFieldRemoved { public, total_public }, - ChangeType_::VariantStyleChanged { now_struct, total_private } => - VariantStyleChanged { now_struct, total_private }, - 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_::VariantFieldAdded { + public, + total_public, + } => VariantFieldAdded { + public, + total_public, + }, + ChangeType_::VariantFieldRemoved { + public, + total_public, + } => VariantFieldRemoved { + public, + total_public, + }, + ChangeType_::VariantStyleChanged { + now_struct, + total_private, + } => VariantStyleChanged { + now_struct, + total_private, + }, + 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, } } @@ -948,39 +1077,64 @@ pub mod tests { impl Arbitrary for ChangeType_ { fn arbitrary(g: &mut G) -> ChangeType_ { use self::ChangeType_::*; - use ::rand::Rng; + use rand::Rng; let b1 = Arbitrary::arbitrary(g); let b2 = Arbitrary::arbitrary(g); - g.choose(&[ItemMadePublic, - ItemMadePrivate, - KindDifference, - RegionParameterAdded, - RegionParameterRemoved, - TypeParameterAdded { defaulted: b1 }, - TypeParameterRemoved { defaulted: b1 }, - VariantAdded, - VariantRemoved, - VariantFieldAdded { public: b1, total_public: b2 }, - VariantFieldRemoved { public: b1, total_public: b2 }, - VariantStyleChanged { now_struct: b1, total_private: b2 }, - FnConstChanged { now_const: b1 }, - MethodSelfChanged { now_self: b1 }, - TraitItemAdded { defaulted: b1, sealed_trait: b2 }, - TraitItemRemoved { defaulted: b1 }, - TraitUnsafetyChanged { now_unsafe: b1 }, - Unknown]).unwrap().clone() + g.choose(&[ + ItemMadePublic, + ItemMadePrivate, + KindDifference, + RegionParameterAdded, + RegionParameterRemoved, + TypeParameterAdded { defaulted: b1 }, + TypeParameterRemoved { defaulted: b1 }, + VariantAdded, + VariantRemoved, + VariantFieldAdded { + public: b1, + total_public: b2, + }, + VariantFieldRemoved { + public: b1, + total_public: b2, + }, + VariantStyleChanged { + now_struct: b1, + total_private: b2, + }, + FnConstChanged { now_const: b1 }, + MethodSelfChanged { now_self: b1 }, + TraitItemAdded { + defaulted: b1, + sealed_trait: b2, + }, + TraitItemRemoved { defaulted: b1 }, + TraitUnsafetyChanged { now_unsafe: b1 }, + Unknown, + ]) + .unwrap() + .clone() } } /// A wrapper type used to construct `Change`s. - pub type Change_ = (DefId_, DefId_, Span_, Span_, bool, Vec<(ChangeType_, Option)>); + pub type Change_ = ( + DefId_, + DefId_, + Span_, + Span_, + bool, + Vec<(ChangeType_, Option)>, + ); /// Construct `Change`s from things that can be generated. - fn build_change<'a>(s1: Span, output: bool, changes: Vec<(ChangeType_, Option)>) - -> Change<'a> - { + fn build_change<'a>( + s1: Span, + output: bool, + changes: Vec<(ChangeType_, Option)>, + ) -> Change<'a> { let mut interner = Interner::default(); let mut change = Change::new(Name::Symbol(interner.intern("test")), s1, output); diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 719d447de974b..d566ebe0b0f9e 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -99,7 +99,8 @@ impl IdMapping { assert!(self.in_old_crate(old_def_id)); - self.trait_item_mapping.insert(old_def_id, (old, new, old_trait)); + self.trait_item_mapping + .insert(old_def_id, (old, new, old_trait)); self.reverse_mapping.insert(new.def_id(), old_def_id); } @@ -110,11 +111,13 @@ impl IdMapping { /// 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.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)); @@ -149,20 +152,25 @@ impl IdMapping { /// 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!(), - }) + 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: AssociatedKind, - name: Name, - impl_def_id: DefId, - item_def_id: DefId) { + pub fn add_inherent_item( + &mut self, + parent_def_id: DefId, + kind: AssociatedKind, + name: Name, + impl_def_id: DefId, + item_def_id: DefId, + ) { self.inherent_items .entry(InherentEntry { parent_def_id: parent_def_id, @@ -174,11 +182,8 @@ impl IdMapping { } /// 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) + 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. @@ -205,9 +210,7 @@ impl IdMapping { assert!(!self.in_old_crate(new)); if self.in_new_crate(new) { - self.reverse_mapping - .get(&new) - .cloned() + self.reverse_mapping.get(&new).cloned() } else { Some(new) } @@ -225,9 +228,9 @@ impl IdMapping { /// 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) + 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. @@ -252,18 +255,19 @@ impl IdMapping { } /// Iterate over the item pairs of all children of a given item. - pub fn children_of<'a>(&'a self, parent: DefId) - -> Option + 'a> - { + pub fn children_of<'a>( + &'a self, + parent: DefId, + ) -> Option + 'a> { self.child_mapping .get(&parent) .map(|m| m.iter().map(move |old| (*old, self.internal_mapping[old]))) } /// Iterate over all items in inherent impls. - pub fn inherent_impls<'a>(&'a self) - -> impl Iterator - { + pub fn inherent_impls<'a>( + &'a self, + ) -> impl Iterator { self.inherent_items.iter() } @@ -360,9 +364,7 @@ impl NameMapping { } /// Drain the item pairs being stored. - pub fn drain<'a>(&'a mut self) - -> impl Iterator, Option)> + 'a - { + pub fn drain<'a>(&'a mut self) -> impl Iterator, Option)> + 'a { self.type_map .drain() .chain(self.value_map.drain()) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index b1415597241f8..842134173e494 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -6,10 +6,10 @@ use rustc::hir::def_id::DefId; use rustc::ty; -use rustc::ty::{Ty, TyCtxt}; -use rustc::ty::Visibility::Public; use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc::ty::subst::Substs; +use rustc::ty::Visibility::Public; +use rustc::ty::{Ty, TyCtxt}; use semcheck::mapping::IdMapping; @@ -35,8 +35,7 @@ pub struct MismatchRelation<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> MismatchRelation<'a, 'gcx, 'tcx> { /// Construct a new mismtach type relation. - pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a mut IdMapping) -> Self - { + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a mut IdMapping) -> Self { MismatchRelation { tcx: tcx, item_queue: id_mapping.toplevel_queue(), @@ -51,7 +50,10 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> MismatchRelation<'a, 'gcx, 'tcx> { use rustc::hir::def::Def::*; while let Some((old_def_id, new_def_id)) = self.item_queue.pop_front() { - debug!("processing mismatch item pair, remaining: {}", self.item_queue.len()); + debug!( + "processing mismatch item pair, remaining: {}", + self.item_queue.len() + ); debug!("old: {:?}, new: {:?}", old_def_id, new_def_id); match self.tcx.describe_def(old_def_id) { Some(Trait(_)) | Some(Macro(_, _)) => continue, @@ -93,11 +95,12 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, true } - fn relate_with_variance>(&mut self, - _: ty::Variance, - a: &T, - b: &T) - -> RelateResult<'tcx, T> { + fn relate_with_variance>( + &mut self, + _: ty::Variance, + a: &T, + b: &T, + ) -> RelateResult<'tcx, T> { self.relate(a, b) } @@ -124,19 +127,16 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, 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(); + 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)) { + 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)?; @@ -147,21 +147,21 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, } else { None } - }, - (&TyKind::Array(a_t, _), &TyKind::Array(b_t, _)) | - (&TyKind::Slice(a_t), &TyKind::Slice(b_t)) => { + } + (&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); @@ -171,11 +171,11 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, } Some((a_def_id, b_def_id)) - }, + } (&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(); @@ -187,26 +187,26 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, } 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)?; Some((a_data.item_def_id, b_data.item_def_id)) - }, + } (&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)?; } Some((a_def_id, b_def_id)) - }, + } (&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, }; @@ -214,8 +214,9 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, self.current_new_types.remove(b); if let Some((old_def_id, new_def_id)) = matching { - if !self.id_mapping.contains_old_id(old_def_id) && - self.id_mapping.in_old_crate(old_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_def_id, new_def_id)); } @@ -224,15 +225,21 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, Ok(self.tcx.types.err) } - fn regions(&mut self, a: ty::Region<'tcx>, _: ty::Region<'tcx>) - -> RelateResult<'tcx, ty::Region<'tcx>> - { + fn regions( + &mut self, + a: ty::Region<'tcx>, + _: ty::Region<'tcx>, + ) -> RelateResult<'tcx, ty::Region<'tcx>> { Ok(a) } - fn binders>(&mut self, a: &ty::Binder, b: &ty::Binder) - -> RelateResult<'tcx, ty::Binder> - { - Ok(ty::Binder::bind(self.relate(a.skip_binder(), b.skip_binder())?)) + fn binders>( + &mut self, + a: &ty::Binder, + b: &ty::Binder, + ) -> RelateResult<'tcx, ty::Binder> { + Ok(ty::Binder::bind( + self.relate(a.skip_binder(), b.skip_binder())?, + )) } } diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index abe477d515de9..f2d73e02acf59 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -2,11 +2,11 @@ //! comparison and inference. use rustc::hir::def_id::DefId; -use rustc::ty::{GenericParamDefKind, ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt}; +use rustc::infer::InferCtxt; use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder}; use rustc::ty::subst::Kind; -use rustc::infer::InferCtxt; use rustc::ty::subst::Substs; +use rustc::ty::{GenericParamDefKind, ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt}; use semcheck::mapping::{IdMapping, InherentEntry}; @@ -28,10 +28,11 @@ pub struct TranslationContext<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { /// Construct a translation context translating to the new crate's `DefId`s. - pub fn target_new(tcx: TyCtxt<'a, 'gcx, 'tcx>, - id_mapping: &'a IdMapping, - translate_params: bool) -> TranslationContext<'a, 'gcx, 'tcx> - { + pub fn target_new( + tcx: TyCtxt<'a, 'gcx, 'tcx>, + id_mapping: &'a IdMapping, + translate_params: bool, + ) -> TranslationContext<'a, 'gcx, 'tcx> { TranslationContext { tcx: tcx, id_mapping: id_mapping, @@ -42,9 +43,11 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { } /// Construct a translation context translating to the old crate's `DefId`s. - pub fn target_old(tcx: TyCtxt<'a, 'gcx, 'tcx>, - id_mapping: &'a IdMapping, - translate_params: bool) -> TranslationContext<'a, 'gcx, 'tcx> { + pub fn target_old( + tcx: TyCtxt<'a, 'gcx, 'tcx>, + id_mapping: &'a IdMapping, + translate_params: bool, + ) -> TranslationContext<'a, 'gcx, 'tcx> { TranslationContext { tcx: tcx, id_mapping: id_mapping, @@ -63,7 +66,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { match param.kind { GenericParamDefKind::Type { .. } => { index_map.insert(param.index, param.def_id); - }, + } _ => (), }; } @@ -75,7 +78,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { match param.kind { GenericParamDefKind::Type { .. } => { index_map.insert(param.index, param.def_id); - }, + } _ => (), }; } @@ -98,15 +101,19 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { } /// Translate the `DefId` and substs of an item. - fn translate_orig_substs(&self, - index_map: &HashMap, - orig_def_id: DefId, - orig_substs: &Substs<'tcx>) -> Option<(DefId, &'tcx Substs<'tcx>)> { - debug!("translating w/ substs: did: {:?}, substs: {:?}", - orig_def_id, orig_substs); + fn translate_orig_substs( + &self, + index_map: &HashMap, + orig_def_id: DefId, + orig_substs: &Substs<'tcx>, + ) -> Option<(DefId, &'tcx Substs<'tcx>)> { + debug!( + "translating w/ substs: did: {:?}, substs: {:?}", + orig_def_id, orig_substs + ); - use rustc::ty::ReEarlyBound; use rustc::ty::subst::UnpackedKind; + use rustc::ty::ReEarlyBound; use std::cell::Cell; let target_def_id = (self.translate_orig)(self.id_mapping, orig_def_id); @@ -114,42 +121,40 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { if let Some(target_def_id) = target_def_id { let success = Cell::new(true); - let target_substs = Substs::for_item(self.tcx, target_def_id, |def, _| { - match def.kind { - GenericParamDefKind::Lifetime => { - Kind::from(if !success.get() { - self.tcx.mk_region(ReEarlyBound(def.to_early_bound_region_data())) - } else if let Some(UnpackedKind::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())) - }) - }, + let target_substs = + Substs::for_item(self.tcx, target_def_id, |def, _| match def.kind { + GenericParamDefKind::Lifetime => Kind::from(if !success.get() { + self.tcx + .mk_region(ReEarlyBound(def.to_early_bound_region_data())) + } else if let Some(UnpackedKind::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(UnpackedKind::Type(type_)) = orig_substs - .get(def.index as usize) - .map(|k| k.unpack()) + } else if let Some(UnpackedKind::Type(type_)) = + orig_substs.get(def.index as usize).map(|k| k.unpack()) { self.translate(index_map, &Kind::from(type_)) - } else if self.id_mapping - .is_non_mapped_defaulted_type_param(&def.def_id) { + } else if self + .id_mapping + .is_non_mapped_defaulted_type_param(&def.def_id) + { Kind::from(self.tcx.type_of(def.def_id)) - } else if self.tcx - .generics_of(target_def_id).has_self && def.index == 0 { + } 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) } - }, - } - }); + } + }); if success.get() { return Some((target_def_id, target_substs)); @@ -161,155 +166,165 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { /// Fold a structure, translating all `DefId`s reachable by the folder. fn translate>(&self, index_map: &HashMap, orig: &T) -> T { - use rustc::ty::{AdtDef, Binder, ExistentialProjection, ExistentialTraitRef}; use rustc::ty::ExistentialPredicate::*; - use rustc::ty::TypeAndMut; use rustc::ty::TyKind; + use rustc::ty::TypeAndMut; + use rustc::ty::{AdtDef, Binder, ExistentialProjection, ExistentialTraitRef}; - orig.fold_with(&mut BottomUpFolder { tcx: self.tcx, fldop: |ty| { - match ty.sty { - 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) + orig.fold_with(&mut BottomUpFolder { + tcx: self.tcx, + fldop: |ty| { + match ty.sty { + TyKind::Adt(&AdtDef { ref did, .. }, substs) + if self.needs_translation(*did) => { - self.tcx.mk_fn_def(target_def_id, target_substs) - } else { - ty + // 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::Dynamic(preds, region) => { - // hacky error catching mechanism - use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; - 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.types.err); - 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.types.err); - 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: ty, - }) - } else { - success.set(false); - err_pred - } - }, - AutoTrait(did) => { - AutoTrait(self.translate_orig(did)) - }, + 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 } - }).collect(); + } + TyKind::Dynamic(preds, region) => { + // hacky error catching mechanism + use rustc::hir::def_id::{DefId, 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.types.err); + 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.types.err); + 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: 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 + 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::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::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.idx != 0 && self.translate_params { // `Self` is special - let orig_def_id = index_map[¶m.idx]; - if self.needs_translation(orig_def_id) { - use rustc::ty::subst::UnpackedKind; - - 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() { - UnpackedKind::Type(param_t) => param_t, - _ => unreachable!(), + TyKind::Param(param) => { + // FIXME: we should check `has_self` if this gets used again! + if param.idx != 0 && self.translate_params { + // `Self` is special + let orig_def_id = index_map[¶m.idx]; + if self.needs_translation(orig_def_id) { + use rustc::ty::subst::UnpackedKind; + + 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() { + UnpackedKind::Type(param_t) => param_t, + _ => unreachable!(), + } + } else { + ty } } else { ty } - } else { - ty } - }, - _ => ty, - } - }, reg_op: |region| self.translate_region(region) }) + _ => ty, + } + }, + reg_op: |region| self.translate_region(region), + }) } /// Translate a region. fn translate_region(&self, region: Region<'tcx>) -> Region<'tcx> { - use rustc::ty::{EarlyBoundRegion, FreeRegion}; use rustc::ty::BoundRegion::BrNamed; use rustc::ty::RegionKind::*; + use rustc::ty::{EarlyBoundRegion, FreeRegion}; if !self.translate_params { return region; @@ -324,16 +339,17 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { }; 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, - }, - }) - }, + } + 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, }) } @@ -344,28 +360,33 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { } /// Translate a predicate using a type parameter index map. - fn translate_predicate(&self, index_map: &HashMap, predicate: Predicate<'tcx>) - -> Option> - { - use rustc::ty::{Binder, /*EquatePredicate,*/ OutlivesPredicate, ProjectionPredicate, - ProjectionTy, SubtypePredicate, TraitPredicate, TraitRef}; + fn translate_predicate( + &self, + index_map: &HashMap, + predicate: Predicate<'tcx>, + ) -> Option> { + use rustc::ty::{ + Binder, /*EquatePredicate,*/ OutlivesPredicate, ProjectionPredicate, ProjectionTy, + SubtypePredicate, TraitPredicate, TraitRef, + }; Some(match predicate { - Predicate::Trait(trait_predicate) => { - Predicate::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) { + Predicate::Trait(trait_predicate) => Predicate::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; - })) - }, + }, + )), /*Predicate::Equate(equate_predicate) => { Predicate::Equate(equate_predicate.map_bound(|e_pred| { let l = self.translate(index_map, &e_pred.0); @@ -379,25 +400,20 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { let r = self.translate_region(r_pred.1); OutlivesPredicate(l, r) })) - }, + } Predicate::TypeOutlives(type_outlives_predicate) => { Predicate::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) })) - }, - Predicate::Projection(projection_predicate) => { - Predicate::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) { + } + Predicate::Projection(projection_predicate) => Predicate::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, @@ -407,16 +423,15 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { } } else { return None; - })) - }, - Predicate::WellFormed(ty) => - Predicate::WellFormed(self.translate(index_map, &ty)), + }, + )), + Predicate::WellFormed(ty) => Predicate::WellFormed(self.translate(index_map, &ty)), Predicate::ObjectSafe(did) => Predicate::ObjectSafe(self.translate_orig(did)), - Predicate::ClosureKind(did, substs, kind) => - Predicate::ClosureKind( - self.translate_orig(did), - self.translate(index_map, &substs), - kind), + Predicate::ClosureKind(did, substs, kind) => Predicate::ClosureKind( + self.translate_orig(did), + self.translate(index_map, &substs), + kind, + ), Predicate::Subtype(subtype_predicate) => { Predicate::Subtype(subtype_predicate.map_bound(|s_pred| { let l = self.translate(index_map, &s_pred.a); @@ -427,22 +442,25 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { b: r, } })) - }, + } Predicate::ConstEvaluatable(orig_did, orig_substs) => { if let Some((target_def_id, target_substs)) = - self.translate_orig_substs(index_map, orig_did, orig_substs) { + self.translate_orig_substs(index_map, orig_did, orig_substs) + { Predicate::ConstEvaluatable(target_def_id, target_substs) } else { return None; } - }, + } }) } /// Translate a slice of predicates in the context of an item. - fn translate_predicates(&self, orig_def_id: DefId, orig_preds: &[Predicate<'tcx>]) - -> Option>> - { + fn translate_predicates( + &self, + orig_def_id: DefId, + orig_preds: &[Predicate<'tcx>], + ) -> Option>> { let index_map = self.construct_index_map(orig_def_id); let mut target_preds = Vec::with_capacity(orig_preds.len()); @@ -458,9 +476,11 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { } /// Translate a `ParamEnv` in the context of an item. - pub fn translate_param_env(&self, orig_def_id: DefId, param_env: ParamEnv<'tcx>) - -> Option> - { + pub fn translate_param_env( + &self, + orig_def_id: DefId, + param_env: ParamEnv<'tcx>, + ) -> Option> { self.translate_predicates(orig_def_id, param_env.caller_bounds) .map(|target_preds| ParamEnv { caller_bounds: self.tcx.intern_predicates(&target_preds), @@ -469,9 +489,11 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { } /// 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> - { + 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), @@ -481,12 +503,13 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { /// Translate an `InherentEntry`. pub fn translate_inherent_entry(&self, orig_entry: &InherentEntry) -> Option { - (self.translate_orig)(self.id_mapping, orig_entry.parent_def_id) - .map(|parent_def_id| InherentEntry { + (self.translate_orig)(self.id_mapping, orig_entry.parent_def_id).map(|parent_def_id| { + InherentEntry { parent_def_id: parent_def_id, kind: orig_entry.kind, name: orig_entry.name, - }) + } + }) } /// Check whether a given `DefId` can be translated. @@ -499,7 +522,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { /// /// Used to lift type errors and predicates to wrap them in an error type. #[derive(Clone)] -pub struct InferenceCleanupFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { +pub struct InferenceCleanupFolder<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { /// The inference context used. infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, } @@ -507,25 +530,27 @@ pub struct InferenceCleanupFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> InferenceCleanupFolder<'a, 'gcx, 'tcx> { /// Construct a new folder. pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self { - InferenceCleanupFolder { - infcx: infcx, - } + InferenceCleanupFolder { infcx: infcx } } } impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceCleanupFolder<'a, 'gcx, 'tcx> { - fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx } + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { + self.infcx.tcx + } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - use rustc::ty::TypeAndMut; use rustc::ty::TyKind; + use rustc::ty::TypeAndMut; let t1 = ty.super_fold_with(self); match t1.sty { TyKind::Ref(region, ty, mutbl) if region.needs_infer() => { let ty_and_mut = TypeAndMut { ty, mutbl }; - self.infcx.tcx.mk_ref(self.infcx.tcx.types.re_erased, ty_and_mut) - }, + self.infcx + .tcx + .mk_ref(self.infcx.tcx.types.re_erased, ty_and_mut) + } TyKind::Infer(_) => self.infcx.tcx.mk_ty(TyKind::Error), _ => t1, } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 0e8ac789e3dd7..2564403de310b 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -11,14 +11,14 @@ use rustc::hir::def::{CtorKind, Def, Export}; use rustc::hir::def_id::DefId; -use rustc::ty::{AssociatedItem, Generics, GenericParamDef, GenericParamDefKind, Ty, TyCtxt}; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::Visibility; use rustc::ty::Visibility::Public; +use rustc::ty::{AssociatedItem, GenericParamDef, GenericParamDefKind, Generics, Ty, TyCtxt}; +use semcheck::changes::ChangeSet; use semcheck::changes::ChangeType; use semcheck::changes::ChangeType::*; -use semcheck::changes::ChangeSet; use semcheck::mapping::{IdMapping, NameMapping}; use semcheck::mismatch::MismatchRelation; use semcheck::translate::TranslationContext; @@ -29,9 +29,11 @@ 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<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefId) - -> ChangeSet<'tcx> -{ +pub fn run_analysis<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + old: DefId, + new: DefId, +) -> ChangeSet<'tcx> { let mut changes = Default::default(); let mut id_mapping = IdMapping::new(old.krate, new.krate); @@ -69,11 +71,13 @@ pub fn run_analysis<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, old: DefId, new: DefI /// 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. -fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, - id_mapping: &mut IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - old: DefId, - new: DefId) { +fn diff_structure<'a, 'tcx>( + changes: &mut ChangeSet, + id_mapping: &mut IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + old: DefId, + new: DefId, +) { use rustc::hir::def::Def::*; // Get the visibility of the inner item, given the outer item's visibility. @@ -100,8 +104,10 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, // 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()); + 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 { @@ -113,12 +119,14 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, 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); + 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. @@ -143,12 +151,14 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, 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); + 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(ItemMadePrivate, o_def_id, None); @@ -163,66 +173,47 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, // Upvar, Label, Variant, Method, Err), whose analysis is out scope // for us (GlobalAsm, Macro), or which don't requite further analysis // at this stage (Const) - (Mod(_), Mod(_)) | - (AssociatedTy(_), AssociatedTy(_)) | - (PrimTy(_), PrimTy(_)) | - (TyParam(_), TyParam(_)) | - (SelfTy(_, _), SelfTy(_, _)) | - (StructCtor(_, _), StructCtor(_, _)) | - (VariantCtor(_, _), VariantCtor(_, _)) | - (AssociatedConst(_), AssociatedConst(_)) | - (Local(_), Local(_)) | - (Upvar(_, _, _), Upvar(_, _, _)) | - (Label(_), Label(_)) | - (Macro(_, _), Macro(_, _)) | - (Variant(_), Variant(_)) | - (Const(_), Const(_)) | - (Method(_), Method(_)) | - (Err, Err) => {}, + (Mod(_), Mod(_)) + | (AssociatedTy(_), AssociatedTy(_)) + | (PrimTy(_), PrimTy(_)) + | (TyParam(_), TyParam(_)) + | (SelfTy(_, _), SelfTy(_, _)) + | (StructCtor(_, _), StructCtor(_, _)) + | (VariantCtor(_, _), VariantCtor(_, _)) + | (AssociatedConst(_), AssociatedConst(_)) + | (Local(_), Local(_)) + | (Upvar(_, _, _), Upvar(_, _, _)) + | (Label(_), Label(_)) + | (Macro(_, _), Macro(_, _)) + | (Variant(_), Variant(_)) + | (Const(_), Const(_)) + | (Method(_), Method(_)) + | (Err, Err) => {} // statics are subject to mutability comparison (Static(_, old_mut), Static(_, new_mut)) => { if old_mut != new_mut { - let change_type = StaticMutabilityChanged { - now_mut: new_mut, - }; + let change_type = 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_generics(changes, id_mapping, tcx, true, o_def_id, n_def_id); diff_fn(changes, tcx, o.def, n.def); - }, + } // type aliases can declare generics, too (TyAlias(_), TyAlias(_)) => { - diff_generics(changes, - id_mapping, - tcx, - false, - o_def_id, - n_def_id); - }, + 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); + (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.def, n.def); - }, + } // 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 @@ -237,25 +228,20 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet, id_mapping.add_private_trait(n_def_id); } - diff_generics(changes, - id_mapping, - tcx, - false, - o_def_id, - 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)); /* diff_traits(changes, - id_mapping, - tcx, - o_def_id, - n_def_id, - output); */ - }, + id_mapping, + tcx, + o_def_id, + n_def_id, + output); */ + } // a non-matching item pair - register the change and abort further // analysis of it _ => { changes.add_change(KindDifference, o_def_id, None); - }, + } } } } @@ -330,19 +316,31 @@ fn diff_fn<'a, 'tcx>(changes: &mut ChangeSet, tcx: TyCtxt<'a, 'tcx, 'tcx>, old: let new_const = tcx.is_const_fn(new_def_id); if old_const != new_const { - changes.add_change(FnConstChanged { now_const: new_const }, old_def_id, None); + changes.add_change( + FnConstChanged { + now_const: new_const, + }, + old_def_id, + None, + ); } } /// Given two method items, perform structural checks. -fn diff_method<'a, 'tcx>(changes: &mut ChangeSet, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - old: AssociatedItem, - new: AssociatedItem) { +fn diff_method<'a, 'tcx>( + changes: &mut ChangeSet, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + old: AssociatedItem, + new: AssociatedItem, +) { if old.method_has_self_argument != new.method_has_self_argument { - changes.add_change(MethodSelfChanged { now_self: new.method_has_self_argument }, - old.def_id, - None); + changes.add_change( + MethodSelfChanged { + now_self: new.method_has_self_argument, + }, + old.def_id, + None, + ); } let old_pub = old.vis == Public; @@ -354,27 +352,28 @@ fn diff_method<'a, 'tcx>(changes: &mut ChangeSet, changes.add_change(ItemMadePublic, old.def_id, None); } - diff_fn(changes, tcx, Def::Method(old.def_id), Def::Method(new.def_id)); + diff_fn( + changes, + tcx, + Def::Method(old.def_id), + Def::Method(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: Def, - new: Def) { +fn diff_adts(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, old: Def, new: Def) { use rustc::hir::def::Def::*; let old_def_id = old.def_id(); let new_def_id = new.def_id(); let (old_def, new_def) = match (old, new) { - (Struct(_), Struct(_)) | - (Union(_), Union(_)) | - (Enum(_), Enum(_)) => (tcx.adt_def(old_def_id), tcx.adt_def(new_def_id)), + (Struct(_), Struct(_)) | (Union(_), Union(_)) | (Enum(_), Enum(_)) => { + (tcx.adt_def(old_def_id), tcx.adt_def(new_def_id)) + } _ => return, }; @@ -427,41 +426,45 @@ fn diff_adts(changes: &mut ChangeSet, 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(ItemMadePublic, - old_def_id, - Some(tcx.def_span(n.did))); + changes.add_change( + ItemMadePublic, + old_def_id, + Some(tcx.def_span(n.did)), + ); } else if o.vis == Public && n.vis != Public { - changes.add_change(ItemMadePrivate, - old_def_id, - Some(tcx.def_span(n.did))); + changes.add_change( + ItemMadePrivate, + old_def_id, + Some(tcx.def_span(n.did)), + ); } - }, + } (Some(o), None) => { let c = VariantFieldRemoved { public: o.vis == Public, - total_public: total_public + total_public: total_public, }; changes.add_change(c, old_def_id, Some(tcx.def_span(o.did))); - }, + } (None, Some(n)) => { let c = VariantFieldAdded { public: n.vis == Public, - total_public: total_public + total_public: total_public, }; changes.add_change(c, old_def_id, Some(tcx.def_span(n.did))); - }, + } (None, None) => unreachable!(), } } fields.clear(); - }, + } (Some(old), None) => { changes.add_change(VariantRemoved, old_def_id, Some(tcx.def_span(old.did))); - }, + } (None, Some(new)) => { changes.add_change(VariantAdded, old_def_id, Some(tcx.def_span(new.did))); - }, + } (None, None) => unreachable!(), } } @@ -469,22 +472,26 @@ fn diff_adts(changes: &mut ChangeSet, 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); + 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); + id_mapping.add_inherent_item( + new_def_id, + item.kind, + item.ident.name, + *impl_def_id, + *item_def_id, + ); } } } @@ -493,17 +500,22 @@ fn diff_adts(changes: &mut ChangeSet, /// /// This establishes the needed correspondence between non-toplevel items found in the trait /// definition. -fn diff_traits<'a, 'tcx>(changes: &mut ChangeSet, - id_mapping: &mut IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - old: DefId, - new: DefId, - output: bool) { +fn diff_traits<'a, 'tcx>( + changes: &mut ChangeSet, + id_mapping: &mut IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + old: DefId, + new: DefId, + output: bool, +) { use rustc::hir::Unsafety::Unsafe; use rustc::ty::subst::UnpackedKind::Type; - use rustc::ty::{ParamTy, Predicate, TyS, TyKind}; + use rustc::ty::{ParamTy, Predicate, TyKind, TyS}; - debug!("diff_traits: old: {:?}, new: {:?}, output: {:?}", old, new, output); + 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; @@ -526,14 +538,16 @@ fn diff_traits<'a, 'tcx>(changes: &mut ChangeSet, 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 { sty: TyKind::Param(ParamTy { idx: 0, ..}), ..}) = - trait_ref.substs[0].unpack() { + if id_mapping.is_private_trait(&trait_ref.def_id) && trait_ref.substs.len() == 1 { + if let Type(&TyS { + sty: TyKind::Param(ParamTy { idx: 0, .. }), + .. + }) = trait_ref.substs[0].unpack() + { old_sealed = true; } } - }, + } _ => (), } } @@ -559,23 +573,25 @@ fn diff_traits<'a, 'tcx>(changes: &mut ChangeSet, let new_def_id = new_def.def_id(); id_mapping.add_trait_item(old_def, new_def, old); - changes.new_change(old_def_id, - new_def_id, - *name, - tcx.def_span(old_def_id), - tcx.def_span(new_def_id), - output); + 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 = 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 = TraitItemAdded { defaulted: new_item.defaultness.has_value(), @@ -583,19 +599,21 @@ fn diff_traits<'a, 'tcx>(changes: &mut ChangeSet, }; 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) { +fn diff_generics( + changes: &mut ChangeSet, + id_mapping: &mut IdMapping, + tcx: TyCtxt, + is_fn: bool, + old: DefId, + new: DefId, +) { use rustc::ty::Variance; use rustc::ty::Variance::*; use std::cmp::max; @@ -604,14 +622,18 @@ fn diff_generics(changes: &mut ChangeSet, fn diff_variance<'tcx>(old_var: Variance, new_var: Variance) -> Option> { match (old_var, new_var) { - (Covariant, Covariant) | - (Invariant, Invariant) | - (Contravariant, Contravariant) | - (Bivariant, Bivariant) => None, + (Covariant, Covariant) + | (Invariant, Invariant) + | (Contravariant, Contravariant) + | (Bivariant, Bivariant) => None, (Invariant, _) | (_, Bivariant) => Some(VarianceLoosened), (_, Invariant) | (Bivariant, _) => Some(VarianceTightened), - (Covariant, Contravariant) => Some(VarianceChanged { now_contravariant: true }), - (Contravariant, Covariant) => Some(VarianceChanged { now_contravariant: false }), + (Covariant, Contravariant) => Some(VarianceChanged { + now_contravariant: true, + }), + (Contravariant, Covariant) => Some(VarianceChanged { + now_contravariant: false, + }), } } @@ -637,22 +659,24 @@ fn diff_generics(changes: &mut ChangeSet, } for i in 0..max(old_count.lifetimes, new_count.lifetimes) { - match (get_region_from_params(old_gen, i), get_region_from_params(new_gen, i)) { + match ( + get_region_from_params(old_gen, i), + get_region_from_params(new_gen, i), + ) { (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)) { - diff_variance(*old_var, *new_var) - .map(|t| found.push(t)); + diff_variance(*old_var, *new_var).map(|t| found.push(t)); } id_mapping.add_internal_item(old_region.def_id, new_region.def_id); - }, + } (Some(_), None) => { found.push(RegionParameterRemoved); - }, + } (None, Some(_)) => { found.push(RegionParameterAdded); - }, + } (None, None) => unreachable!(), } } @@ -668,15 +692,17 @@ fn diff_generics(changes: &mut ChangeSet, } for i in 0..max(old_count.types, new_count.types) { - match (get_type_from_params(old_gen, old_count.lifetimes + i), - get_type_from_params(new_gen, new_count.lifetimes + i)) { + match ( + get_type_from_params(old_gen, old_count.lifetimes + i), + get_type_from_params(new_gen, new_count.lifetimes + i), + ) { (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)) - { - diff_variance(*old_var, *new_var) - .map(|t| found.push(t)); + if let (Some(old_var), Some(new_var)) = ( + old_var.get(old_count.lifetimes + i), + new_var.get(new_count.lifetimes + i), + ) { + diff_variance(*old_var, *new_var).map(|t| found.push(t)); } let old_default = match old_type.kind { @@ -696,33 +722,39 @@ fn diff_generics(changes: &mut ChangeSet, found.push(TypeParameterAdded { defaulted: true }); } - debug!("in item {:?} / {:?}:\n type param pair: {:?}, {:?}", - old, new, old_type, new_type); + 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(TypeParameterRemoved { defaulted: old_default }); + found.push(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(TypeParameterAdded { defaulted: new_default || is_fn }); + found.push(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!(), } } @@ -736,47 +768,55 @@ fn diff_generics(changes: &mut ChangeSet, // of matching items are compared for changes. /// Given two items, compare their types. -fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, - id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - old: Def, - new: Def) { +fn diff_types<'a, 'tcx>( + changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + old: Def, + new: Def, +) { use rustc::hir::def::Def::*; 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)) { + 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 TyAlias(_) | Const(_) | 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)); - }, + 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 Fn(_) | Method(_) => { 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)); - }, + 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 Struct(_) | Enum(_) | Union(_) => { if let Some(children) = id_mapping.children_of(old_def_id) { @@ -787,25 +827,29 @@ fn diff_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, 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 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<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, - id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, '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); +fn cmp_types<'a, 'tcx>( + changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, '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); @@ -822,8 +866,10 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, }; let target = target.subst(infcx.tcx, target_substs); - let target_param_env = - infcx.tcx.param_env(target_def_id).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) @@ -831,23 +877,30 @@ fn cmp_types<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, changes.add_change(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); + 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<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, - id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - orig_def_id: DefId, - target_def_id: DefId) { - info!("comparing bounds of {:?} / {:?}", orig_def_id, target_def_id); +fn cmp_bounds<'a, 'tcx>( + changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, '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); @@ -855,12 +908,14 @@ fn cmp_bounds<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, let orig_substs = Substs::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); + compcx.check_bounds_bidirectional( + changes, + tcx, + orig_def_id, + target_def_id, + orig_substs, + target_substs, + ); }) } @@ -868,9 +923,11 @@ fn cmp_bounds<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, // their trait bounds and compared for changes, if applicable. /// Compare the inherent implementations of all matching items. -fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, - id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>) { +fn diff_inherent_impls<'a, 'tcx>( + changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, +) { debug!("diffing inherent impls"); let to_new = TranslationContext::target_new(tcx, id_mapping, false); @@ -878,14 +935,13 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, 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, AssociatedItemRemoved) - } else if id_mapping.in_new_crate(orig_item.parent_def_id) { - (&to_old, AssociatedItemAdded) - } else { - unreachable!() - }; + let (forward_trans, err_type) = if id_mapping.in_old_crate(orig_item.parent_def_id) { + (&to_new, AssociatedItemRemoved) + } else if id_mapping.in_new_crate(orig_item.parent_def_id) { + (&to_old, AssociatedItemAdded) + } else { + unreachable!() + }; // determine item visibility let parent_output = changes.get_output(orig_item.parent_def_id); @@ -895,12 +951,14 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, 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); + 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 @@ -914,23 +972,26 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, }; // 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); + 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); + } - 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) - }); + 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 { @@ -941,20 +1002,26 @@ fn diff_inherent_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } /// Compare the implementations of all matching traits. -fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, - id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>) { +fn diff_trait_impls<'a, 'tcx>( + changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, +) { debug!("diffing trait impls"); use rustc::hir::def::Def; 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() { + 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; - let old_impl_parent_def = - tcx.parent_def_id(*old_impl_def_id).and_then(|did| tcx.describe_def(did)); + let old_impl_parent_def = tcx + .parent_def_id(*old_impl_def_id) + .and_then(|did| tcx.describe_def(did)); let old_impl_parent_is_fn = match old_impl_parent_def { Some(Def::Fn(_)) | Some(Def::Method(_)) => true, _ => false, @@ -965,18 +1032,24 @@ fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } if !match_trait_impl(tcx, &to_new, *old_impl_def_id) { - changes.new_change_impl(*old_impl_def_id, - tcx.item_path_str(*old_impl_def_id), - tcx.def_span(*old_impl_def_id)); + changes.new_change_impl( + *old_impl_def_id, + tcx.item_path_str(*old_impl_def_id), + tcx.def_span(*old_impl_def_id), + ); changes.add_change(TraitImplTightened, *old_impl_def_id, None); } } - for new_impl_def_id in tcx.all_trait_implementations(id_mapping.get_new_crate()).iter() { + 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; - let new_impl_parent_def = - tcx.parent_def_id(*new_impl_def_id).and_then(|did| tcx.describe_def(did)); + let new_impl_parent_def = tcx + .parent_def_id(*new_impl_def_id) + .and_then(|did| tcx.describe_def(did)); let new_impl_parent_is_fn = match new_impl_parent_def { Some(Def::Fn(_)) | Some(Def::Method(_)) => true, _ => false, @@ -987,9 +1060,11 @@ fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, } if !match_trait_impl(tcx, &to_old, *new_impl_def_id) { - changes.new_change_impl(*new_impl_def_id, - tcx.item_path_str(*new_impl_def_id), - tcx.def_span(*new_impl_def_id)); + changes.new_change_impl( + *new_impl_def_id, + tcx.item_path_str(*new_impl_def_id), + tcx.def_span(*new_impl_def_id), + ); changes.add_change(TraitImplLoosened, *new_impl_def_id, None); } } @@ -997,26 +1072,36 @@ fn diff_trait_impls<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, /// Compare an item pair in two inherent implementations and indicate whether the target one is /// compatible with the original one. -fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, - id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - orig_impl_def_id: DefId, - target_impl_def_id: DefId, - orig_item: AssociatedItem, - target_item: AssociatedItem) -> bool { +fn match_inherent_impl<'a, 'tcx>( + changes: &mut ChangeSet<'tcx>, + id_mapping: &IdMapping, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + orig_impl_def_id: DefId, + target_impl_def_id: DefId, + orig_item: AssociatedItem, + target_item: AssociatedItem, +) -> bool { use rustc::ty::AssociatedKind; - debug!("match_inherent_impl: orig_impl/item: {:?}/{:?}, target_impl/item: {:?}/{:?}", - orig_impl_def_id, orig_item, target_impl_def_id, target_item); + 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) + ( + TypeComparisonContext::target_new(&infcx, id_mapping, false), + true, + ) } else { - (TypeComparisonContext::target_old(&infcx, id_mapping, false), false) + ( + TypeComparisonContext::target_old(&infcx, id_mapping, false), + false, + ) }; let orig_substs = Substs::identity_for_item(infcx.tcx, target_item_def_id); @@ -1025,15 +1110,20 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, .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_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); + 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. @@ -1045,13 +1135,11 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, .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); + 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 + return false; } } else { // The bounds could not have been translated - no impl match. @@ -1067,40 +1155,40 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, // prepare the item type for comparison, as we do for toplevel items' types let (orig, target) = match (orig_item.kind, target_item.kind) { - (AssociatedKind::Const, AssociatedKind::Const) | - (AssociatedKind::Type, AssociatedKind::Type) => { - (infcx.tcx.type_of(orig_item_def_id), infcx.tcx.type_of(target_item_def_id)) - }, + (AssociatedKind::Const, AssociatedKind::Const) + | (AssociatedKind::Type, AssociatedKind::Type) => ( + infcx.tcx.type_of(orig_item_def_id), + infcx.tcx.type_of(target_item_def_id), + ), (AssociatedKind::Method, AssociatedKind::Method) => { 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!() - }, + } + _ => unreachable!(), }; - let orig = compcx.forward_trans.translate_item_type(orig_item_def_id, orig); + 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); + let error = + compcx.check_type_error(tcx, target_item_def_id, target_param_env, orig, target); if let Some(err) = error { changes.add_change(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); + compcx.check_bounds_bidirectional( + changes, + tcx, + orig_item_def_id, + target_item_def_id, + orig_substs, + target_substs, + ); } true @@ -1109,27 +1197,29 @@ fn match_inherent_impl<'a, 'tcx>(changes: &mut ChangeSet<'tcx>, /// Compare two implementations and indicate whether the target one is compatible with the /// original one. -fn match_trait_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - trans: &TranslationContext<'a, 'tcx, 'tcx>, - orig_def_id: DefId) -> bool { +fn match_trait_impl<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + trans: &TranslationContext<'a, 'tcx, '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; - }; + 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(); + 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)); + 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)); diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs index 6f5ec81a23da7..7b97d9e41f1a3 100644 --- a/src/semcheck/typeck.rs +++ b/src/semcheck/typeck.rs @@ -5,12 +5,13 @@ use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; -use rustc::traits::{FulfillmentContext, FulfillmentError, - Obligation, ObligationCause, TraitEngine}; -use rustc::ty::{GenericParamDefKind, ParamEnv, Predicate, TraitRef, Ty, TyCtxt}; +use rustc::traits::{ + FulfillmentContext, FulfillmentError, Obligation, ObligationCause, TraitEngine, +}; use rustc::ty::error::TypeError; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::{Kind, Substs}; +use rustc::ty::{GenericParamDefKind, ParamEnv, Predicate, TraitRef, Ty, TyCtxt}; use semcheck::changes::ChangeSet; use semcheck::mapping::IdMapping; @@ -42,21 +43,23 @@ impl<'a, 'gcx, 'tcx> BoundContext<'a, 'gcx, 'tcx> { 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 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); + 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); + self.fulfill_cx + .register_predicate_obligation(self.infcx, obligation); } } @@ -67,9 +70,9 @@ impl<'a, 'gcx, 'tcx> BoundContext<'a, 'gcx, 'tcx> { let predicate = Predicate::Trait(Binder::bind(TraitPredicate { trait_ref: checked_trait_ref, })); - let obligation = - Obligation::new(ObligationCause::dummy(), self.given_param_env, predicate); - self.fulfill_cx.register_predicate_obligation(self.infcx, obligation); + 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. @@ -101,37 +104,47 @@ pub struct TypeComparisonContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { /// Construct a new context where the original item is old. - pub fn target_new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - id_mapping: &'a IdMapping, - checking_trait_def: bool) -> Self { + pub fn target_new( + infcx: &'a InferCtxt<'a, 'gcx, '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) + 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, 'gcx, 'tcx>, - id_mapping: &'a IdMapping, - checking_trait_def: bool) -> Self { + pub fn target_old( + infcx: &'a InferCtxt<'a, 'gcx, '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) + 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, 'gcx, 'tcx>, - id_mapping: &'a IdMapping, - forward_trans: TranslationContext<'a, 'gcx, 'tcx>, - backward_trans: TranslationContext<'a, 'gcx, 'tcx>, - checking_trait_def: bool) -> Self { + fn from_trans( + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + id_mapping: &'a IdMapping, + forward_trans: TranslationContext<'a, 'gcx, 'tcx>, + backward_trans: TranslationContext<'a, 'gcx, 'tcx>, + checking_trait_def: bool, + ) -> Self { TypeComparisonContext { infcx: infcx, id_mapping: id_mapping, @@ -150,7 +163,8 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { let has_self = self.infcx.tcx.generics_of(target_def_id).has_self; Substs::for_item(self.infcx.tcx, target_def_id, |def, _| { - if def.index == 0 && has_self { // `Self` is special + 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) @@ -162,42 +176,46 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { pub fn compute_target_default_substs(&self, target_def_id: DefId) -> &Substs<'tcx> { use rustc::ty::ReEarlyBound; - Substs::for_item(self.infcx.tcx, target_def_id, |def, _| { - match def.kind { - GenericParamDefKind::Lifetime => { - Kind::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) { - Kind::from(self.infcx.tcx.type_of(def.def_id)) - } else { - self.infcx.tcx.mk_param_from_def(def) - } - }, + Substs::for_item(self.infcx.tcx, target_def_id, |def, _| match def.kind { + GenericParamDefKind::Lifetime => Kind::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) + { + Kind::from(self.infcx.tcx.type_of(def.def_id)) + } else { + self.infcx.tcx.mk_param_from_def(def) + } } }) } /// Check for type mismatches in a pair of items. - pub fn check_type_error<'b, 'tcx2>(&self, - lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, - target_def_id: DefId, - target_param_env: ParamEnv<'tcx>, - orig: Ty<'tcx>, - target: Ty<'tcx>) -> Option> { - use rustc::infer::{InferOk, SuppressRegionErrors}; + pub fn check_type_error<'b, 'tcx2>( + &self, + lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, + target_def_id: DefId, + target_param_env: ParamEnv<'tcx>, + orig: Ty<'tcx>, + target: Ty<'tcx>, + ) -> Option> { use rustc::infer::outlives::env::OutlivesEnvironment; + use rustc::infer::{InferOk, SuppressRegionErrors}; use rustc::middle::region::ScopeTree; use rustc::ty::Lift; - let error = - self.infcx - .at(&ObligationCause::dummy(), target_param_env) - .eq(orig, target) - .map(|InferOk { obligations: o, .. }| { assert_eq!(o, vec![]); }); + 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 scope_tree = ScopeTree::default(); @@ -214,17 +232,19 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { // self.relate_regions(r_b, r_a); // } - self.infcx.resolve_regions_and_report_errors(target_def_id, - &scope_tree, - &outlives_env, - SuppressRegionErrors::default()); + self.infcx.resolve_regions_and_report_errors( + target_def_id, + &scope_tree, + &outlives_env, + SuppressRegionErrors::default(), + ); - let err = - self.infcx - .resolve_type_vars_if_possible(&err) - .fold_with(&mut self.folder.clone()) - .lift_to_tcx(lift_tcx) - .unwrap(); + let err = self + .infcx + .resolve_type_vars_if_possible(&err) + .fold_with(&mut self.folder.clone()) + .lift_to_tcx(lift_tcx) + .unwrap(); Some(err) } else { @@ -233,43 +253,46 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { } /// Check for trait bound mismatches in a pair of items. - pub fn check_bounds_error<'b, 'tcx2>(&self, - lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, - orig_param_env: ParamEnv<'tcx>, - target_def_id: DefId, - target_substs: &Substs<'tcx>) - -> Option>> - { + pub fn check_bounds_error<'b, 'tcx2>( + &self, + lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, + orig_param_env: ParamEnv<'tcx>, + target_def_id: DefId, + target_substs: &Substs<'tcx>, + ) -> Option>> { use rustc::ty::Lift; - debug!("check_bounds_error: orig env: {:?}, target did: {:?}, target substs: {:?}", - orig_param_env, - target_def_id, - target_substs); + 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 + bound_cx.get_errors().map(|errors| { + errors .iter() - .map(|err| - self.infcx - .resolve_type_vars_if_possible(&err.obligation.predicate) - .fold_with(&mut self.folder.clone()) - .lift_to_tcx(lift_tcx) - .unwrap()) - .collect()) + .map(|err| { + self.infcx + .resolve_type_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<'b, 'tcx2>(&self, - changes: &mut ChangeSet<'tcx2>, - lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, - orig_def_id: DefId, - target_def_id: DefId, - orig_substs: &Substs<'tcx>, - target_substs: &Substs<'tcx>) { + pub fn check_bounds_bidirectional<'b, 'tcx2>( + &self, + changes: &mut ChangeSet<'tcx2>, + lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, + orig_def_id: DefId, + target_def_id: DefId, + orig_substs: &Substs<'tcx>, + target_substs: &Substs<'tcx>, + ) { use semcheck::changes::ChangeType::{BoundsLoosened, BoundsTightened}; let tcx = self.infcx.tcx; @@ -288,9 +311,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { self.check_bounds_error(lift_tcx, orig_param_env, target_def_id, target_substs) { for err in errors { - let err_type = BoundsTightened { - pred: err, - }; + let err_type = BoundsTightened { pred: err }; changes.add_change(err_type, orig_def_id, None); } diff --git a/tests/debug.rs b/tests/debug.rs index fb07bc57480db..686352f81ec85 100644 --- a/tests/debug.rs +++ b/tests/debug.rs @@ -10,7 +10,9 @@ fn debug() { let mut dump = File::create(Path::new("tests/debug.sh")).expect("could not create dump file"); - let metadata = dump.metadata().expect("could not access dump file metadata"); + 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); diff --git a/tests/examples.rs b/tests/examples.rs index 0fcfe0b47b9e4..ac39a691f75ab 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -57,10 +57,15 @@ mod features { }; success &= Command::new("./target/debug/rust-semverver") - .args(&["--crate-type=lib", "-Zverbose", - "--extern", &format!("old={}", old_rlib), - "--extern", &format!("new={}", new_rlib), - "tests/helper/test.rs"]) + .args(&[ + "--crate-type=lib", + "-Zverbose", + "--extern", + &format!("old={}", old_rlib), + "--extern", + &format!("new={}", new_rlib), + "tests/helper/test.rs", + ]) .env("RUST_BACKTRACE", "full") .env("RUST_SEMVER_CRATE_VERSION", "1.0.0") .stdin(Stdio::null()) @@ -72,7 +77,10 @@ mod features { assert!(success, "rust-semverver"); - success &= sed_child.wait().expect("could not wait for sed child").success(); + success &= sed_child + .wait() + .expect("could not wait for sed child") + .success(); } assert!(success, "sed"); diff --git a/tests/full.rs b/tests/full.rs index 43982257e7238..8c17651f0dd0a 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -9,7 +9,8 @@ mod full { fn test_full(crate_name: &str, old_version: &str, new_version: &str) { let mut success = true; - let prog = format!(r#" + let prog = format!( + r#" # wait for the actual output /^version bump/ {{ doprint = 1; @@ -27,16 +28,22 @@ mod full { # sanitize paths gsub(/-->.*{crate_name}/, "--> {crate_name}", $0); print; - }}{crate_name}{crate_name}"#, crate_name = crate_name); + }}{crate_name}{crate_name}"#, + crate_name = crate_name + ); - eprintln!("prog:\n{}",prog); + eprintln!("prog:\n{}", prog); let base_out_file = Path::new("tests/full_cases") .join(format!("{}-{}-{}", crate_name, old_version, new_version)); let out_file = if cfg!(target_os = "macos") { let p: PathBuf = format!("{}.osx", base_out_file.display()).into(); - if p.exists() { p } else { base_out_file } + if p.exists() { + p + } else { + base_out_file + } } else { base_out_file }; @@ -84,19 +91,21 @@ mod full { assert!(success, "cargo semver"); - success &= awk_child.wait().expect("could not wait for awk child").success(); + success &= awk_child + .wait() + .expect("could not wait for awk child") + .success(); assert!(success, "awk"); success &= Command::new("git") .args(&["diff", "--exit-code", out_file]) - .env("PAGER", "") - .status() - .expect("could not run git diff") - .success(); + .env("PAGER", "") + .status() + .expect("could not run git diff") + .success(); assert!(success, "git"); - } macro_rules! full_test { @@ -105,7 +114,7 @@ mod full { fn $name() { test_full($crate_name, $old_version, $new_version); } - } + }; } full_test!(log, "log", "0.3.4", "0.3.8"); From 74784adee0d2f82093a68a9b2e28744cb179af29 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 21 Nov 2018 15:24:12 +0100 Subject: [PATCH 383/553] Test rustfmt on CI --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index d5990e1c88bcf..e966975df7c94 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,9 @@ matrix: env: RUST_BACKTRACE=full # Tools: + - name: "rustfmt" + install: rustup component add rustfmt-preview + script: cargo fmt --all -- --check - name: "Shellcheck" script: - shellcheck --version From ae122052967288c4e7fa088ad1abb7be369c07e2 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 21 Nov 2018 15:45:52 +0100 Subject: [PATCH 384/553] Update outdated dependencies --- Cargo.toml | 8 ++++---- src/semcheck/changes.rs | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 008edb508c8a7..739eb66fb8c37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,12 +25,12 @@ name = "rust-semverver" path = "src/bin/rust_semverver.rs" [dependencies] -cargo = "0.29" -crates-io = "0.17" -env_logger = "0.5" +cargo = "0.31" +crates-io = "0.19" +env_logger = "0.6" log = "0.4" semver = "0.9" -rand = "0.5" +rand = "0.6" [dev-dependencies] quickcheck = "0.7" diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index bbc80dd1e3323..d087a79006f07 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -1077,12 +1077,12 @@ pub mod tests { impl Arbitrary for ChangeType_ { fn arbitrary(g: &mut G) -> ChangeType_ { use self::ChangeType_::*; - use rand::Rng; + use rand::seq::SliceRandom; let b1 = Arbitrary::arbitrary(g); let b2 = Arbitrary::arbitrary(g); - g.choose(&[ + [ ItemMadePublic, ItemMadePrivate, KindDifference, @@ -1113,7 +1113,8 @@ pub mod tests { TraitItemRemoved { defaulted: b1 }, TraitUnsafetyChanged { now_unsafe: b1 }, Unknown, - ]) + ] + .choose(g) .unwrap() .clone() } From b2337c35e0753510793e8f6c87528d30adc22ca5 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 21 Nov 2018 16:41:18 +0100 Subject: [PATCH 385/553] Fix clippy issues --- .travis.yml | 5 + src/bin/cargo_semver.rs | 50 ++++----- src/bin/rust_semverver.rs | 53 +++++----- src/semcheck/changes.rs | 69 ++++++------ src/semcheck/mapping.rs | 46 ++++---- src/semcheck/mismatch.rs | 29 ++--- src/semcheck/translate.rs | 63 +++++------ src/semcheck/traverse.rs | 215 +++++++++++++++++++++----------------- src/semcheck/typeck.rs | 43 ++++---- 9 files changed, 290 insertions(+), 283 deletions(-) diff --git a/.travis.yml b/.travis.yml index e966975df7c94..a32c9efb1e7db 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,11 @@ matrix: - name: "rustfmt" install: rustup component add rustfmt-preview script: cargo fmt --all -- --check + - name: "clippy" + script: | + if rustup component add clippy-preview; then + cargo clippy --all -- -D clippy::pedantic + fi - name: "Shellcheck" script: - shellcheck --version diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 947db16928972..dde9f8293ea4a 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -8,24 +8,23 @@ extern crate getopts; #[macro_use] extern crate log; +use cargo::{ + core::{compiler::CompileMode, Package, PackageId, Source, SourceId, Workspace}, + exit_with_error, + ops::{compile, CompileOptions}, + util::{ + config::Config, important_paths::find_root_manifest_for_wd, CargoError, CargoResult, + CliError, + }, +}; use crates_io::{Crate, Registry}; - -use cargo::core::compiler::CompileMode; -use cargo::core::{Package, PackageId, Source, SourceId, Workspace}; -use cargo::exit_with_error; -use cargo::ops::{compile, CompileOptions}; -use cargo::util::config::Config; -use cargo::util::important_paths::find_root_manifest_for_wd; -use cargo::util::{CargoError, CargoResult, CliError}; - use getopts::{Matches, Options}; - -use std::env; -use std::error; -use std::fmt; -use std::io::Write; -use std::path::PathBuf; -use std::process::{Command, Stdio}; +use std::{ + env, error, fmt, + io::Write, + path::PathBuf, + process::{Command, Stdio}, +}; /// Very simple error representation. #[derive(Debug)] @@ -90,9 +89,9 @@ impl<'a> SourceInfo<'a> { debug!("source id loaded: {:?}", source_id); - Ok(SourceInfo { + Ok(Self { id: source_id, - source: source, + source, }) } } @@ -117,7 +116,7 @@ impl<'a> WorkInfo<'a> { let workspace = Workspace::new(&manifest_path, config)?; let package = workspace.load(&manifest_path)?; - Ok(WorkInfo { package, workspace }) + Ok(Self { package, workspace }) } /// Construct a package/workspace pair by fetching the package of a specified name and @@ -134,10 +133,7 @@ impl<'a> WorkInfo<'a> { let package = source.source.download(&package_id)?; let workspace = Workspace::ephemeral(package.clone(), config, None, false)?; - Ok(WorkInfo { - package: package, - workspace: workspace, - }) + Ok(Self { package, workspace }) } /// Obtain the paths to the produced rlib and the dependency output directory. @@ -174,7 +170,6 @@ impl<'a> WorkInfo<'a> { /// and/or defaults, and dispatch the actual analysis. // TODO: possibly reduce the complexity by finding where some info can be taken from directly fn do_main(config: &Config, matches: &Matches, explain: bool) -> CargoResult<()> { - debug!("running cargo-semver"); fn parse_arg(opt: &str) -> CargoResult { let mut split = opt.split(':'); let name = if let Some(n) = split.next() { @@ -192,12 +187,11 @@ fn do_main(config: &Config, matches: &Matches, explain: bool) -> CargoResult<()> return Err(Error("spec has to be of form `name:version`".to_owned()).into()); } - Ok(NameAndVersion { - name: name, - version: version, - }) + Ok(NameAndVersion { name, version }) } + debug!("running cargo-semver"); + let mut source = SourceInfo::new(config)?; let current = if let Some(opt) = matches.opt_str("C") { diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 8ee7aa93698bd..f40c56c48d26a 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -13,23 +13,20 @@ extern crate rustc_metadata; extern crate semverver; extern crate syntax; -use semverver::semcheck::run_analysis; - -use rustc::hir::def_id::*; -use rustc::middle::cstore::ExternCrate; -use rustc::session::config::{ErrorOutputType, Input}; -use rustc::session::{config, Session}; -use rustc_metadata::cstore::CStore; - -use rustc_driver::{driver, Compilation, CompilerCalls, RustcDefaultCalls}; - +use rustc::{ + hir::def_id::*, + middle::cstore::ExternCrate, + session::{ + config::{self, ErrorOutputType, Input}, + Session, + }, +}; use rustc_codegen_utils::codegen_backend::CodegenBackend; - -use std::path::PathBuf; -use std::process::Command; - -use syntax::ast; -use syntax::source_map::Pos; +use rustc_driver::{driver, Compilation, CompilerCalls, RustcDefaultCalls}; +use rustc_metadata::cstore::CStore; +use semverver::semcheck::run_analysis; +use std::{path::PathBuf, process::Command}; +use syntax::{ast, source_map::Pos}; /// After the typechecker has finished it's work, perform our checks. fn callback(state: &driver::CompileState, version: &str, verbose: bool) { @@ -59,16 +56,13 @@ fn callback(state: &driver::CompileState, version: &str, verbose: bool) { crates.sort_by_key(|&(span_lo, _)| span_lo); - match crates.as_slice() { - &[(_, old_def_id), (_, new_def_id)] => { - debug!("running semver analysis"); - let changes = run_analysis(tcx, old_def_id, new_def_id); + 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); - changes.output(tcx.sess, version, verbose); - } - _ => { - tcx.sess.err("could not find crate old and new crates"); - } + changes.output(tcx.sess, version, verbose); + } else { + tcx.sess.err("could not find crate old and new crates"); } } @@ -84,8 +78,8 @@ struct SemVerVerCompilerCalls { impl SemVerVerCompilerCalls { /// Construct a new compilation wrapper, given a version string. - pub fn new(version: String, verbose: bool) -> Box { - Box::new(SemVerVerCompilerCalls { + pub fn new(version: String, verbose: bool) -> Box { + Box::new(Self { default: Box::new(RustcDefaultCalls), version, verbose, @@ -145,13 +139,13 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { } fn build_controller( - self: Box, + self: Box, sess: &Session, matches: &getopts::Matches, ) -> driver::CompileController<'a> { let default = self.get_default(); let version = self.get_version().clone(); - let SemVerVerCompilerCalls { verbose, .. } = *self; + let Self { verbose, .. } = *self; let mut controller = CompilerCalls::build_controller(default, sess, matches); let old_callback = std::mem::replace(&mut controller.after_analysis.callback, box |_| {}); @@ -218,5 +212,6 @@ fn main() { rustc_driver::run_compiler(&args, cc, None, None) }); + #[cfg_attr(feature = "cargo-clippy", allow(clippy::cast_possible_truncation))] std::process::exit(result as i32); } diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index d087a79006f07..3ed44bd5c0a47 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -9,19 +9,18 @@ //! 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::session::Session; -use rustc::ty::error::TypeError; -use rustc::ty::Predicate; - +use rustc::{ + hir::def_id::DefId, + session::Session, + ty::{error::TypeError, Predicate}, +}; use semver::Version; - -use std::cmp::Ordering; -use std::collections::{BTreeMap, BTreeSet, HashMap}; -use std::fmt; - +use std::{ + cmp::Ordering, + collections::{BTreeMap, BTreeSet, HashMap}, + fmt, +}; use syntax::symbol::Symbol; - use syntax_pos::Span; /// The categories we use when analyzing changes between crate versions. @@ -47,7 +46,7 @@ pub enum ChangeCategory { pub use self::ChangeCategory::*; impl<'a> Default for ChangeCategory { - fn default() -> ChangeCategory { + fn default() -> Self { Patch } } @@ -102,10 +101,10 @@ pub struct PathChange { impl PathChange { /// Construct a new empty path change record for an item. - fn new(name: Symbol, def_span: Span) -> PathChange { - PathChange { - name: name, - def_span: def_span, + fn new(name: Symbol, def_span: Span) -> Self { + Self { + name, + def_span, additions: BTreeSet::new(), removals: BTreeSet::new(), } @@ -124,10 +123,10 @@ impl PathChange { pub fn to_category(&self) -> ChangeCategory { if !self.removals.is_empty() { Breaking - } else if !self.additions.is_empty() { - TechnicallyBreaking - } else { + } else if self.additions.is_empty() { Patch + } else { + TechnicallyBreaking } } @@ -171,7 +170,7 @@ impl PathChange { } impl PartialEq for PathChange { - fn eq(&self, other: &PathChange) -> bool { + fn eq(&self, other: &Self) -> bool { self.span() == other.span() } } @@ -179,13 +178,13 @@ impl PartialEq for PathChange { impl Eq for PathChange {} impl PartialOrd for PathChange { - fn partial_cmp(&self, other: &PathChange) -> Option { + fn partial_cmp(&self, other: &Self) -> Option { self.span().partial_cmp(other.span()) } } impl Ord for PathChange { - fn cmp(&self, other: &PathChange) -> Ordering { + fn cmp(&self, other: &Self) -> Ordering { self.span().cmp(other.span()) } } @@ -387,18 +386,12 @@ on said enum can become non-exhaustive." "Removing an enum variant is a braking change, because every old reference to the removed variant is rendered invalid." } - VariantFieldAdded { - public: _, - total_public: _, - } => { + VariantFieldAdded { .. } => { "Adding a field to an enum variant is breaking, as matches on the variant are invalidated. In case of structs, this only holds for public fields, or the first private field being added." } - VariantFieldRemoved { - public: _, - total_public: _, - } => { + VariantFieldRemoved { .. } => { "Removing a field from an enum variant is breaking, as matches on the variant are invalidated. In case of structs, this only holds for public fields." } @@ -639,9 +632,9 @@ impl<'tcx> Change<'tcx> { Change { changes: Vec::new(), max: ChangeCategory::default(), - name: name, + name, new_span: span, - output: output, + output, } } @@ -856,15 +849,15 @@ impl<'tcx> ChangeSet<'tcx> { /// Set up reporting for the changes associated with a given `DefId`. pub fn set_output(&mut self, old: DefId) { let max = &mut self.max; - self.changes.get_mut(&old).map(|change| { + if let Some(change) = self.changes.get_mut(&old) { let cat = change.to_category(); if cat > *max { *max = cat; } - change.output = true - }); + change.output = true; + } } /// Check whether an item with the given id has undergone breaking changes. @@ -874,8 +867,7 @@ impl<'tcx> ChangeSet<'tcx> { // we only care about items that were present in both versions. self.changes .get(&old) - .map(|change| change.to_category() == Breaking) - .unwrap_or(false) + .map_or(false, |change| change.to_category() == Breaking) } /// Check whether a trait item contains breaking changes preventing further analysis of it's @@ -883,8 +875,7 @@ impl<'tcx> ChangeSet<'tcx> { pub fn trait_item_breaking(&self, old: DefId) -> bool { self.changes .get(&old) - .map(|change| change.trait_item_breaking()) - .unwrap_or(false) + .map_or(false, |change| change.trait_item_breaking()) } /// Format the contents of a change set for user output. diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index d566ebe0b0f9e..285ea82968371 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -3,12 +3,14 @@ //! 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::{Def, Export}; -use rustc::hir::def_id::{CrateNum, DefId}; -use rustc::ty::{AssociatedKind, GenericParamDef, GenericParamDefKind}; - +use rustc::{ + hir::{ + def::{Def, Export}, + def_id::{CrateNum, DefId}, + }, + ty::{AssociatedKind, GenericParamDef, GenericParamDefKind}, +}; use std::collections::{BTreeSet, HashMap, HashSet, VecDeque}; - use syntax::ast::Name; /// A description of an item found in an inherent impl. @@ -30,6 +32,7 @@ pub type InherentImplSet = BTreeSet<(DefId, DefId)>; /// 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::stutter))] pub struct IdMapping { /// The old crate. old_crate: CrateNum, @@ -58,10 +61,10 @@ pub struct IdMapping { impl IdMapping { /// Construct a new mapping with the given crate information. - pub fn new(old_crate: CrateNum, new_crate: CrateNum) -> IdMapping { - IdMapping { - old_crate: old_crate, - new_crate: new_crate, + 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(), @@ -151,11 +154,11 @@ impl IdMapping { } /// 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) + 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) + .get(&def_id) .map_or(false, |def| match def.kind { GenericParamDefKind::Type { has_default, .. } => has_default, _ => unreachable!(), @@ -173,9 +176,9 @@ impl IdMapping { ) { self.inherent_items .entry(InherentEntry { - parent_def_id: parent_def_id, - kind: kind, - name: name, + parent_def_id, + kind, + name, }) .or_insert_with(Default::default) .insert((impl_def_id, item_def_id)); @@ -217,13 +220,13 @@ impl IdMapping { } /// Return the `DefId` of the trait a given item belongs to. - pub fn get_trait_def(&self, item_def_id: &DefId) -> Option { - self.trait_item_mapping.get(item_def_id).map(|t| t.2) + pub fn get_trait_def(&self, item_def_id: DefId) -> Option { + self.trait_item_mapping.get(&item_def_id).map(|t| t.2) } /// Check whether the given `DefId` is a private trait. - pub fn is_private_trait(&self, trait_def_id: &DefId) -> bool { - self.private_traits.contains(trait_def_id) + 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. @@ -265,9 +268,7 @@ impl IdMapping { } /// Iterate over all items in inherent impls. - pub fn inherent_impls<'a>( - &'a self, - ) -> impl Iterator { + pub fn inherent_impls(&self) -> impl Iterator { self.inherent_items.iter() } @@ -296,6 +297,7 @@ impl IdMapping { /// /// 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::stutter))] pub struct NameMapping { /// The exports in the type namespace. type_map: HashMap, Option)>, diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 842134173e494..d3f0481fe081e 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -4,15 +4,17 @@ //! 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 rustc::hir::def_id::DefId; -use rustc::ty; -use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; -use rustc::ty::subst::Substs; -use rustc::ty::Visibility::Public; -use rustc::ty::{Ty, TyCtxt}; - +use rustc::{ + hir::def_id::DefId, + ty::{ + self, + relate::{Relate, RelateResult, TypeRelation}, + subst::Substs, + Ty, TyCtxt, + Visibility::Public, + }, +}; use semcheck::mapping::IdMapping; - use std::collections::{HashMap, HashSet, VecDeque}; /// A relation searching for items appearing at the same spot in a type. @@ -20,6 +22,7 @@ use std::collections::{HashMap, HashSet, VecDeque}; /// 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::stutter))] pub struct MismatchRelation<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { /// The type context used. tcx: TyCtxt<'a, 'gcx, 'tcx>, @@ -36,12 +39,12 @@ pub struct MismatchRelation<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> MismatchRelation<'a, 'gcx, 'tcx> { /// Construct a new mismtach type relation. pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a mut IdMapping) -> Self { - MismatchRelation { - tcx: tcx, + Self { + tcx, item_queue: id_mapping.toplevel_queue(), - id_mapping: id_mapping, - current_old_types: Default::default(), - current_new_types: Default::default(), + id_mapping, + current_old_types: HashSet::default(), + current_new_types: HashSet::default(), } } diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index f2d73e02acf59..21771c3e04c4f 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -1,15 +1,16 @@ //! The translation machinery used to lift items into the context of the other crate for //! comparison and inference. -use rustc::hir::def_id::DefId; -use rustc::infer::InferCtxt; -use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder}; -use rustc::ty::subst::Kind; -use rustc::ty::subst::Substs; -use rustc::ty::{GenericParamDefKind, ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt}; - +use rustc::{ + hir::def_id::DefId, + infer::InferCtxt, + ty::{ + fold::{BottomUpFolder, TypeFoldable, TypeFolder}, + subst::{Kind, Substs}, + GenericParamDefKind, ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt, + }, +}; use semcheck::mapping::{IdMapping, InherentEntry}; - use std::collections::HashMap; /// The context in which `DefId` translation happens. @@ -34,9 +35,9 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { translate_params: bool, ) -> TranslationContext<'a, 'gcx, 'tcx> { TranslationContext { - tcx: tcx, - id_mapping: id_mapping, - translate_params: translate_params, + tcx, + id_mapping, + translate_params, needs_translation: IdMapping::in_old_crate, translate_orig: IdMapping::get_new_id, } @@ -49,9 +50,9 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { translate_params: bool, ) -> TranslationContext<'a, 'gcx, 'tcx> { TranslationContext { - tcx: tcx, - id_mapping: id_mapping, - translate_params: translate_params, + tcx, + id_mapping, + translate_params, needs_translation: IdMapping::in_new_crate, translate_orig: IdMapping::get_old_id, } @@ -63,24 +64,18 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { let orig_generics = self.tcx.generics_of(orig_def_id); for param in &orig_generics.params { - match param.kind { - GenericParamDefKind::Type { .. } => { - index_map.insert(param.index, param.def_id); - } - _ => (), - }; + 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 { - match param.kind { - GenericParamDefKind::Type { .. } => { - index_map.insert(param.index, param.def_id); - } - _ => (), - }; + if let GenericParamDefKind::Type { .. } = param.kind { + index_map.insert(param.index, param.def_id); + } } } @@ -107,15 +102,15 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { orig_def_id: DefId, orig_substs: &Substs<'tcx>, ) -> Option<(DefId, &'tcx Substs<'tcx>)> { + use rustc::ty::subst::UnpackedKind; + use rustc::ty::ReEarlyBound; + use std::cell::Cell; + debug!( "translating w/ substs: did: {:?}, substs: {:?}", orig_def_id, orig_substs ); - use rustc::ty::subst::UnpackedKind; - use rustc::ty::ReEarlyBound; - use std::cell::Cell; - let target_def_id = (self.translate_orig)(self.id_mapping, orig_def_id); if let Some(target_def_id) = target_def_id { @@ -144,7 +139,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { self.translate(index_map, &Kind::from(type_)) } else if self .id_mapping - .is_non_mapped_defaulted_type_param(&def.def_id) + .is_non_mapped_defaulted_type_param(def.def_id) { Kind::from(self.tcx.type_of(def.def_id)) } else if self.tcx.generics_of(target_def_id).has_self && def.index == 0 { @@ -253,7 +248,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { item_def_id: target_def_id, // TODO: should be it's own method in rustc substs: self.tcx.intern_substs(&target_substs[1..]), - ty: ty, + ty, }) } else { success.set(false); @@ -505,7 +500,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { pub fn translate_inherent_entry(&self, orig_entry: &InherentEntry) -> Option { (self.translate_orig)(self.id_mapping, orig_entry.parent_def_id).map(|parent_def_id| { InherentEntry { - parent_def_id: parent_def_id, + parent_def_id, kind: orig_entry.kind, name: orig_entry.name, } @@ -530,7 +525,7 @@ pub struct InferenceCleanupFolder<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> InferenceCleanupFolder<'a, 'gcx, 'tcx> { /// Construct a new folder. pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self { - InferenceCleanupFolder { infcx: infcx } + InferenceCleanupFolder { infcx } } } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 2564403de310b..2e5c734916e81 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -9,21 +9,24 @@ //! 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 rustc::hir::def::{CtorKind, Def, Export}; -use rustc::hir::def_id::DefId; -use rustc::ty::subst::{Subst, Substs}; -use rustc::ty::Visibility; -use rustc::ty::Visibility::Public; -use rustc::ty::{AssociatedItem, GenericParamDef, GenericParamDefKind, Generics, Ty, TyCtxt}; - -use semcheck::changes::ChangeSet; -use semcheck::changes::ChangeType; -use semcheck::changes::ChangeType::*; -use semcheck::mapping::{IdMapping, NameMapping}; -use semcheck::mismatch::MismatchRelation; -use semcheck::translate::TranslationContext; -use semcheck::typeck::{BoundContext, TypeComparisonContext}; - +use rustc::{ + hir::{ + def::{CtorKind, Def, Export}, + def_id::DefId, + }, + ty::{ + subst::{Subst, Substs}, + AssociatedItem, GenericParamDef, GenericParamDefKind, Generics, Ty, TyCtxt, Visibility, + Visibility::Public, + }, +}; +use semcheck::{ + changes::{ChangeSet, ChangeType}, + mapping::{IdMapping, NameMapping}, + mismatch::MismatchRelation, + translate::TranslationContext, + typeck::{BoundContext, TypeComparisonContext}, +}; use std::collections::{BTreeMap, HashSet, VecDeque}; /// The main entry point to our analysis passes. @@ -34,7 +37,7 @@ pub fn run_analysis<'a, 'tcx>( old: DefId, new: DefId, ) -> ChangeSet<'tcx> { - let mut changes = Default::default(); + let mut changes = ChangeSet::default(); let mut id_mapping = IdMapping::new(old.krate, new.krate); // first pass @@ -71,6 +74,7 @@ pub fn run_analysis<'a, 'tcx>( /// 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::cyclomatic_complexity))] fn diff_structure<'a, 'tcx>( changes: &mut ChangeSet, id_mapping: &mut IdMapping, @@ -131,9 +135,9 @@ fn diff_structure<'a, 'tcx>( // this seemingly overly complex condition is needed to handle // `Restricted` visibility correctly. if o_vis == Public && n_vis != Public { - changes.add_change(ItemMadePrivate, o_def_id, None); + changes.add_change(ChangeType::ItemMadePrivate, o_def_id, None); } else if o_vis != Public && n_vis == Public { - changes.add_change(ItemMadePublic, o_def_id, None); + changes.add_change(ChangeType::ItemMadePublic, o_def_id, None); } } @@ -161,9 +165,9 @@ fn diff_structure<'a, 'tcx>( ); if o_vis == Public && n_vis != Public { - changes.add_change(ItemMadePrivate, o_def_id, None); + changes.add_change(ChangeType::ItemMadePrivate, o_def_id, None); } else if o_vis != Public && n_vis == Public { - changes.add_change(ItemMadePublic, o_def_id, None); + changes.add_change(ChangeType::ItemMadePublic, o_def_id, None); } match (o.def, n.def) { @@ -192,7 +196,8 @@ fn diff_structure<'a, 'tcx>( // statics are subject to mutability comparison (Static(_, old_mut), Static(_, new_mut)) => { if old_mut != new_mut { - let change_type = StaticMutabilityChanged { now_mut: new_mut }; + let change_type = + ChangeType::StaticMutabilityChanged { now_mut: new_mut }; changes.add_change(change_type, o_def_id, None); } @@ -240,7 +245,7 @@ fn diff_structure<'a, 'tcx>( // a non-matching item pair - register the change and abort further // analysis of it _ => { - changes.add_change(KindDifference, o_def_id, None); + changes.add_change(ChangeType::KindDifference, o_def_id, None); } } } @@ -317,7 +322,7 @@ fn diff_fn<'a, 'tcx>(changes: &mut ChangeSet, tcx: TyCtxt<'a, 'tcx, 'tcx>, old: if old_const != new_const { changes.add_change( - FnConstChanged { + ChangeType::FnConstChanged { now_const: new_const, }, old_def_id, @@ -335,7 +340,7 @@ fn diff_method<'a, 'tcx>( ) { if old.method_has_self_argument != new.method_has_self_argument { changes.add_change( - MethodSelfChanged { + ChangeType::MethodSelfChanged { now_self: new.method_has_self_argument, }, old.def_id, @@ -347,9 +352,9 @@ fn diff_method<'a, 'tcx>( let new_pub = new.vis == Public; if old_pub && !new_pub { - changes.add_change(ItemMadePrivate, old.def_id, None); + changes.add_change(ChangeType::ItemMadePrivate, old.def_id, None); } else if !old_pub && new_pub { - changes.add_change(ItemMadePublic, old.def_id, None); + changes.add_change(ChangeType::ItemMadePublic, old.def_id, None); } diff_fn( @@ -411,9 +416,9 @@ fn diff_adts(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, o } if old.ctor_kind != new.ctor_kind { - let c = VariantStyleChanged { + let c = ChangeType::VariantStyleChanged { now_struct: new.ctor_kind == CtorKind::Fictive, - total_private: total_private, + total_private, }; changes.add_change(c, old_def_id, Some(tcx.def_span(new.did))); @@ -427,29 +432,29 @@ fn diff_adts(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, o id_mapping.add_subitem(old_def_id, o.did, n.did); } else if o.vis != Public && n.vis == Public { changes.add_change( - ItemMadePublic, + ChangeType::ItemMadePublic, old_def_id, Some(tcx.def_span(n.did)), ); } else if o.vis == Public && n.vis != Public { changes.add_change( - ItemMadePrivate, + ChangeType::ItemMadePrivate, old_def_id, Some(tcx.def_span(n.did)), ); } } (Some(o), None) => { - let c = VariantFieldRemoved { + let c = ChangeType::VariantFieldRemoved { public: o.vis == Public, - total_public: total_public, + total_public, }; changes.add_change(c, old_def_id, Some(tcx.def_span(o.did))); } (None, Some(n)) => { - let c = VariantFieldAdded { + let c = ChangeType::VariantFieldAdded { public: n.vis == Public, - total_public: total_public, + total_public, }; changes.add_change(c, old_def_id, Some(tcx.def_span(n.did))); } @@ -460,10 +465,18 @@ fn diff_adts(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, o fields.clear(); } (Some(old), None) => { - changes.add_change(VariantRemoved, old_def_id, Some(tcx.def_span(old.did))); + changes.add_change( + ChangeType::VariantRemoved, + old_def_id, + Some(tcx.def_span(old.did)), + ); } (None, Some(new)) => { - changes.add_change(VariantAdded, old_def_id, Some(tcx.def_span(new.did))); + changes.add_change( + ChangeType::VariantAdded, + old_def_id, + Some(tcx.def_span(new.did)), + ); } (None, None) => unreachable!(), } @@ -521,7 +534,7 @@ fn diff_traits<'a, 'tcx>( let new_unsafety = tcx.trait_def(new).unsafety; if old_unsafety != new_unsafety { - let change_type = TraitUnsafetyChanged { + let change_type = ChangeType::TraitUnsafetyChanged { now_unsafe: new_unsafety == Unsafe, }; @@ -532,23 +545,20 @@ fn diff_traits<'a, 'tcx>( let old_param_env = tcx.param_env(old); for bound in old_param_env.caller_bounds { - match *bound { - Predicate::Trait(pred) => { - 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 { - sty: TyKind::Param(ParamTy { idx: 0, .. }), - .. - }) = trait_ref.substs[0].unpack() - { - old_sealed = true; - } + if let Predicate::Trait(pred) = *bound { + 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 { + sty: TyKind::Param(ParamTy { idx: 0, .. }), + .. + }) = trait_ref.substs[0].unpack() + { + old_sealed = true; } } - _ => (), } } @@ -586,14 +596,14 @@ fn diff_traits<'a, 'tcx>( diff_method(changes, tcx, old_item, new_item); } (Some((_, old_item)), None) => { - let change_type = TraitItemRemoved { + 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 = TraitItemAdded { + let change_type = ChangeType::TraitItemAdded { defaulted: new_item.defaultness.has_value(), sealed_trait: old_sealed, }; @@ -618,25 +628,45 @@ fn diff_generics( use rustc::ty::Variance::*; use std::cmp::max; - debug!("diff_generics: old: {:?}, new: {:?}", old, new); - fn diff_variance<'tcx>(old_var: Variance, new_var: Variance) -> Option> { match (old_var, new_var) { (Covariant, Covariant) | (Invariant, Invariant) | (Contravariant, Contravariant) | (Bivariant, Bivariant) => None, - (Invariant, _) | (_, Bivariant) => Some(VarianceLoosened), - (_, Invariant) | (Bivariant, _) => Some(VarianceTightened), - (Covariant, Contravariant) => Some(VarianceChanged { + (Invariant, _) | (_, Bivariant) => Some(ChangeType::VarianceLoosened), + (_, Invariant) | (Bivariant, _) => Some(ChangeType::VarianceTightened), + (Covariant, Contravariant) => Some(ChangeType::VarianceChanged { now_contravariant: true, }), - (Contravariant, Covariant) => Some(VarianceChanged { + (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); @@ -648,16 +678,6 @@ fn diff_generics( let old_count = old_gen.own_counts(); let new_count = new_gen.own_counts(); - // 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, - } - } - for i in 0..max(old_count.lifetimes, new_count.lifetimes) { match ( get_region_from_params(old_gen, i), @@ -666,31 +686,23 @@ fn diff_generics( (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)) { - diff_variance(*old_var, *new_var).map(|t| found.push(t)); + 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(RegionParameterRemoved); + found.push(ChangeType::RegionParameterRemoved); } (None, Some(_)) => { - found.push(RegionParameterAdded); + found.push(ChangeType::RegionParameterAdded); } (None, None) => unreachable!(), } } - // 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, - } - } - for i in 0..max(old_count.types, new_count.types) { match ( get_type_from_params(old_gen, old_count.lifetimes + i), @@ -702,7 +714,9 @@ fn diff_generics( old_var.get(old_count.lifetimes + i), new_var.get(new_count.lifetimes + i), ) { - diff_variance(*old_var, *new_var).map(|t| found.push(t)); + if let Some(t) = diff_variance(*old_var, *new_var) { + found.push(t) + }; } let old_default = match old_type.kind { @@ -715,11 +729,11 @@ fn diff_generics( }; if old_default && !new_default { - found.push(TypeParameterRemoved { defaulted: true }); - found.push(TypeParameterAdded { defaulted: false }); + found.push(ChangeType::TypeParameterRemoved { defaulted: true }); + found.push(ChangeType::TypeParameterAdded { defaulted: false }); } else if !old_default && new_default { - found.push(TypeParameterRemoved { defaulted: false }); - found.push(TypeParameterAdded { defaulted: true }); + found.push(ChangeType::TypeParameterRemoved { defaulted: false }); + found.push(ChangeType::TypeParameterAdded { defaulted: true }); } debug!( @@ -737,7 +751,7 @@ fn diff_generics( _ => unreachable!(), }; - found.push(TypeParameterRemoved { + found.push(ChangeType::TypeParameterRemoved { defaulted: old_default, }); id_mapping.add_type_param(old_type); @@ -749,7 +763,7 @@ fn diff_generics( _ => unreachable!(), }; - found.push(TypeParameterAdded { + found.push(ChangeType::TypeParameterAdded { defaulted: new_default || is_fn, }); id_mapping.add_type_param(new_type); @@ -783,7 +797,7 @@ fn diff_types<'a, 'tcx>( // bail out of analysis of already broken items if changes.item_breaking(old_def_id) || id_mapping - .get_trait_def(&old_def_id) + .get_trait_def(old_def_id) .map_or(false, |did| changes.trait_item_breaking(did)) { return; @@ -874,7 +888,7 @@ fn cmp_types<'a, 'tcx>( if let Some(err) = compcx.check_type_error(tcx, target_def_id, target_param_env, orig, target) { - changes.add_change(TypeChanged { error: err }, orig_def_id, None); + 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( @@ -936,9 +950,9 @@ fn diff_inherent_impls<'a, 'tcx>( 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, AssociatedItemRemoved) + (&to_new, ChangeType::AssociatedItemRemoved) } else if id_mapping.in_new_crate(orig_item.parent_def_id) { - (&to_old, AssociatedItemAdded) + (&to_old, ChangeType::AssociatedItemAdded) } else { unreachable!() }; @@ -1007,9 +1021,10 @@ fn diff_trait_impls<'a, 'tcx>( id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, ) { + use rustc::hir::def::Def; + debug!("diffing trait impls"); - use rustc::hir::def::Def; let to_new = TranslationContext::target_new(tcx, id_mapping, false); let to_old = TranslationContext::target_old(tcx, id_mapping, false); @@ -1037,7 +1052,7 @@ fn diff_trait_impls<'a, 'tcx>( tcx.item_path_str(*old_impl_def_id), tcx.def_span(*old_impl_def_id), ); - changes.add_change(TraitImplTightened, *old_impl_def_id, None); + changes.add_change(ChangeType::TraitImplTightened, *old_impl_def_id, None); } } @@ -1065,7 +1080,7 @@ fn diff_trait_impls<'a, 'tcx>( tcx.item_path_str(*new_impl_def_id), tcx.def_span(*new_impl_def_id), ); - changes.add_change(TraitImplLoosened, *new_impl_def_id, None); + changes.add_change(ChangeType::TraitImplLoosened, *new_impl_def_id, None); } } } @@ -1178,7 +1193,11 @@ fn match_inherent_impl<'a, 'tcx>( compcx.check_type_error(tcx, target_item_def_id, target_param_env, orig, target); if let Some(err) = error { - changes.add_change(TypeChanged { error: err }, orig_item_def_id, None); + 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( diff --git a/src/semcheck/typeck.rs b/src/semcheck/typeck.rs index 7b97d9e41f1a3..4278d2737ca71 100644 --- a/src/semcheck/typeck.rs +++ b/src/semcheck/typeck.rs @@ -3,19 +3,22 @@ //! Multiple context structures are provided that modularize the needed functionality to allow //! for code reuse across analysis steps. -use rustc::hir::def_id::DefId; -use rustc::infer::InferCtxt; -use rustc::traits::{ - FulfillmentContext, FulfillmentError, Obligation, ObligationCause, TraitEngine, +use rustc::{ + hir::def_id::DefId, + infer::InferCtxt, + traits::{FulfillmentContext, FulfillmentError, Obligation, ObligationCause, TraitEngine}, + ty::{ + error::TypeError, + fold::TypeFoldable, + subst::{Kind, Substs}, + GenericParamDefKind, ParamEnv, Predicate, TraitRef, Ty, TyCtxt, + }, +}; +use semcheck::{ + changes::ChangeSet, + mapping::IdMapping, + translate::{InferenceCleanupFolder, TranslationContext}, }; -use rustc::ty::error::TypeError; -use rustc::ty::fold::TypeFoldable; -use rustc::ty::subst::{Kind, Substs}; -use rustc::ty::{GenericParamDefKind, ParamEnv, Predicate, TraitRef, Ty, TyCtxt}; - -use semcheck::changes::ChangeSet; -use semcheck::mapping::IdMapping; -use semcheck::translate::{InferenceCleanupFolder, TranslationContext}; /// The context in which bounds analysis happens. pub struct BoundContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { @@ -31,9 +34,9 @@ impl<'a, 'gcx, 'tcx> BoundContext<'a, 'gcx, 'tcx> { /// Construct a new bound context. pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, given_param_env: ParamEnv<'tcx>) -> Self { BoundContext { - infcx: infcx, + infcx, fulfill_cx: FulfillmentContext::new(), - given_param_env: given_param_env, + given_param_env, } } @@ -146,12 +149,12 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { checking_trait_def: bool, ) -> Self { TypeComparisonContext { - infcx: infcx, - id_mapping: id_mapping, + infcx, + id_mapping, folder: InferenceCleanupFolder::new(infcx), - forward_trans: forward_trans, - backward_trans: backward_trans, - checking_trait_def: checking_trait_def, + forward_trans, + backward_trans, + checking_trait_def, } } @@ -185,7 +188,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { GenericParamDefKind::Type { .. } => { if self .id_mapping - .is_non_mapped_defaulted_type_param(&def.def_id) + .is_non_mapped_defaulted_type_param(def.def_id) { Kind::from(self.infcx.tcx.type_of(def.def_id)) } else { From 193969c2a802d03d7b11b299d7f7d94e5f9466dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Wed, 21 Nov 2018 16:29:56 +0000 Subject: [PATCH 386/553] Update rand requirement from 0.5 to 0.6 Updates the requirements on [rand](https://github.com/rust-random/rand) to permit the latest version. - [Release notes](https://github.com/rust-random/rand/releases) - [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-random/rand/commits) Signed-off-by: dependabot[bot] --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 008edb508c8a7..b5f503e0d41a0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ crates-io = "0.17" env_logger = "0.5" log = "0.4" semver = "0.9" -rand = "0.5" +rand = "0.6" [dev-dependencies] quickcheck = "0.7" From ffbfd781c186236d83fd02890b886d80bed81656 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 21 Nov 2018 17:44:40 +0100 Subject: [PATCH 387/553] Fix exit of ci/run.sh script --- ci/run.sh | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/ci/run.sh b/ci/run.sh index d518981e02ce4..1762db7bac138 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -2,6 +2,10 @@ set -ex +export RUST_TEST_THREADS=1 +export RUST_BACKTRACE=full +#export RUST_TEST_NOCAPTURE=1 + cargo build cargo test --verbose @@ -11,6 +15,17 @@ cp target/debug/cargo-semver ~/rust/cargo/bin cp target/debug/rust-semverver ~/rust/cargo/bin # become semververver -current_version=$(grep -e '^version = .*$' Cargo.toml | cut -d ' ' -f 3) PATH=~/rust/cargo/bin:$PATH cargo semver | tee semver_out -(head -n 1 semver_out | grep "\\-> $current_version") || (echo "versioning mismatch" && return 1) +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 From 09308fd877bb439a54c2d32c56f2133eb9981534 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 21 Nov 2018 17:59:56 +0100 Subject: [PATCH 388/553] Test windows on CI --- .travis.yml | 2 + ci/run.sh | 2 +- src/bin/rust_semverver.rs | 20 +- tests/debug.rs | 26 +-- tests/examples.rs | 129 +++++++------ tests/full.rs | 41 +++-- ...0.2.28-0.2.31 => libc-0.2.28-0.2.31.linux} | 0 .../libc-0.2.28-0.2.31.windows_msvc | 1 + ...{log-0.3.4-0.3.8 => log-0.3.4-0.3.8.linux} | 0 tests/full_cases/log-0.3.4-0.3.8.osx | 171 ++++++++++++++++++ tests/full_cases/log-0.3.4-0.3.8.windows_msvc | 171 ++++++++++++++++++ 11 files changed, 476 insertions(+), 87 deletions(-) rename tests/full_cases/{libc-0.2.28-0.2.31 => libc-0.2.28-0.2.31.linux} (100%) create mode 100644 tests/full_cases/libc-0.2.28-0.2.31.windows_msvc rename tests/full_cases/{log-0.3.4-0.3.8 => log-0.3.4-0.3.8.linux} (100%) create mode 100644 tests/full_cases/log-0.3.4-0.3.8.osx create mode 100644 tests/full_cases/log-0.3.4-0.3.8.windows_msvc diff --git a/.travis.yml b/.travis.yml index a32c9efb1e7db..146f85b6de2b7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,8 @@ matrix: os: osx osx_image: xcode10 env: RUST_BACKTRACE=full + - name: "windows" + os: windows # Tools: - name: "rustfmt" diff --git a/ci/run.sh b/ci/run.sh index 1762db7bac138..48f97d1dac286 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -7,7 +7,7 @@ export RUST_BACKTRACE=full #export RUST_TEST_NOCAPTURE=1 cargo build -cargo test --verbose +cargo test --verbose -- --nocapture # install mkdir -p ~/rust/cargo/bin diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index f40c56c48d26a..86f0aa10a9c44 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -25,7 +25,10 @@ use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_driver::{driver, Compilation, CompilerCalls, RustcDefaultCalls}; use rustc_metadata::cstore::CStore; use semverver::semcheck::run_analysis; -use std::{path::PathBuf, process::Command}; +use std::{ + path::{Path, PathBuf}, + process::Command, +}; use syntax::{ast, source_map::Pos}; /// After the typechecker has finished it's work, perform our checks. @@ -174,8 +177,8 @@ fn main() { let home = option_env!("RUSTUP_HOME"); let toolchain = option_env!("RUSTUP_TOOLCHAIN"); - let sys_root = if let (Some(home), Some(toolchain)) = (home, toolchain) { - format!("{}/toolchains/{}", home, toolchain) + let sys_root: PathBuf = if let (Some(home), Some(toolchain)) = (home, toolchain) { + Path::new(home).join("toolchains").join(toolchain) } else { option_env!("SYSROOT") .map(|s| s.to_owned()) @@ -188,15 +191,22 @@ fn main() { .map(|s| s.trim().to_owned()) }) .expect("need to specify SYSROOT env var during compilation, or use rustup") + .into() }; - let result = rustc_driver::run(|| { + assert!( + sys_root.exists(), + "sysroot \"{}\" does not exist", + sys_root.display() + ); + + let result = rustc_driver::run(move || { let args: Vec = if std::env::args().any(|s| s == "--sysroot") { std::env::args().collect() } else { std::env::args() .chain(Some("--sysroot".to_owned())) - .chain(Some(sys_root)) + .chain(Some(sys_root.to_str().unwrap().to_owned())) .collect() }; diff --git a/tests/debug.rs b/tests/debug.rs index 686352f81ec85..97e040f2d8858 100644 --- a/tests/debug.rs +++ b/tests/debug.rs @@ -1,8 +1,4 @@ -use std::env; -use std::fs::File; -use std::io::Write; -use std::os::unix::fs::PermissionsExt; -use std::path::Path; +use std::{env, fs::File, io::Write, path::Path}; #[test] fn debug() { @@ -10,14 +6,18 @@ fn debug() { let mut dump = File::create(Path::new("tests/debug.sh")).expect("could not create dump file"); - 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#"#!/bin/sh + #[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 diff --git a/tests/examples.rs b/tests/examples.rs index ac39a691f75ab..7c6ed6c8b9954 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -1,24 +1,22 @@ -#[cfg(not(target_os = "windows"))] mod features { - use std::env; - use std::fs::File; - use std::os::unix::io::{AsRawFd, FromRawFd}; - use std::path::Path; - use std::process::{Command, Stdio}; + use std::{ + env, fs, io, + path::Path, + process::{Command, Stdio}, + }; fn test_example(path: &Path) { let mut success = true; - let current_dir = env::current_dir().expect("could not determine current dir"); - let subst = format!("s#{}#$REPO_PATH#g", current_dir.to_str().unwrap()); - let out_file = path.join("stdout"); - 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 stdout = File::create(&out_file).expect("could not create `stdout` file"); + let stdout = fs::File::create(&out_file).expect("could not create `stdout` file"); + let stderr = stdout + .try_clone() + .expect("could not create `stderr` file by cloning `stdout`"); success &= Command::new("rustc") .args(&["--crate-type=lib", "-o", &old_rlib]) @@ -42,52 +40,79 @@ mod features { assert!(success, "couldn't compile new"); - let mut sed_child = Command::new("sed") - .arg(&subst) - .stdin(Stdio::piped()) - .stdout(stdout) - .spawn() - .expect("could not run sed"); - - let (err_pipe, out_pipe) = if let Some(ref stdin) = sed_child.stdin { - let fd = stdin.as_raw_fd(); - unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } - } else { - panic!("could not pipe to sed"); - }; - - success &= Command::new("./target/debug/rust-semverver") - .args(&[ - "--crate-type=lib", - "-Zverbose", - "--extern", - &format!("old={}", old_rlib), - "--extern", - &format!("new={}", new_rlib), - "tests/helper/test.rs", - ]) - .env("RUST_BACKTRACE", "full") - .env("RUST_SEMVER_CRATE_VERSION", "1.0.0") - .stdin(Stdio::null()) - .stdout(out_pipe) - .stderr(err_pipe) - .status() - .expect("could not run rust-semverver") - .success(); + success &= Command::new( + Path::new(".") + .join("target") + .join("debug") + .join("rust-semverver") + .to_str() + .unwrap(), + ) + .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::from(stdout)) + .stderr(Stdio::from(stderr)) + .status() + .expect("could not run rust-semverver") + .success(); assert!(success, "rust-semverver"); - success &= sed_child - .wait() - .expect("could not wait for sed child") - .success(); + { + // replace root path with with $REPO_PATH + use self::io::{Read, Write}; + let current_dir = env::current_dir().expect("could not determine current dir"); + let mut contents = { + let mut f = fs::File::open(&out_file).expect("file not found"); + let mut contents = String::new(); + f.read_to_string(&mut contents) + .expect("something went wrong reading the file"); + contents + }; + + contents = contents.replace(current_dir.to_str().unwrap(), "$REPO_PATH"); + + if cfg!(target_os = "windows") { + let mut lines = Vec::new(); + + for line in contents.lines() { + if line.contains("$REPO_PATH") { + lines.push(line.replace('\\', "/")); + } else { + lines.push(line.to_owned()); + } + } + lines.push(String::new()); + contents = lines.join("\r\n"); + } + + let mut file = fs::File::create(&out_file).expect("cannot create file"); + file.write_all(contents.as_bytes()) + .expect("cannot write to file"); + } } - assert!(success, "sed"); - - eprintln!("path: {}", out_file.to_str().unwrap()); success &= Command::new("git") - .args(&["diff", "--exit-code", out_file.to_str().unwrap()]) + .args(&[ + "diff", + "--ignore-space-at-eol", + "--exit-code", + out_file.to_str().unwrap(), + ]) .env("PAGER", "") .status() .expect("could not run git diff") @@ -105,7 +130,7 @@ mod features { ($name:ident) => { #[test] fn $name() { - let path = Path::new("tests/cases").join(stringify!($name)); + let path = Path::new("tests").join("cases").join(stringify!($name)); test_example(&path); } }; diff --git a/tests/full.rs b/tests/full.rs index 8c17651f0dd0a..61841fb19a644 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -1,8 +1,6 @@ -#[cfg(not(target_os = "windows"))] mod full { use std::env; use std::fs::File; - use std::os::unix::io::{AsRawFd, FromRawFd}; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; @@ -32,21 +30,22 @@ mod full { crate_name = crate_name ); - eprintln!("prog:\n{}", prog); - - let base_out_file = Path::new("tests/full_cases") + let out_file = Path::new("tests/full_cases") .join(format!("{}-{}-{}", crate_name, old_version, new_version)); - let out_file = if cfg!(target_os = "macos") { - let p: PathBuf = format!("{}.osx", base_out_file.display()).into(); - if p.exists() { - p - } else { - base_out_file - } + // 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 { - base_out_file + eprintln!("full tests are not available in this target"); + return; }; + + let out_file: PathBuf = format!("{}.{}", out_file.display(), file_ext).into(); assert!(out_file.exists()); if let Some(path) = env::var_os("PATH") { @@ -70,8 +69,18 @@ mod full { .expect("could not run awk"); let (err_pipe, out_pipe) = if let Some(ref stdin) = awk_child.stdin { - let fd = stdin.as_raw_fd(); - unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } + #[cfg(unix)] + { + use std::os::unix::io::{AsRawFd, FromRawFd}; + let fd = stdin.as_raw_fd(); + unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } + } + #[cfg(windows)] + { + use std::os::windows::io::{AsRawHandle, FromRawHandle}; + let fd = stdin.as_raw_handle(); + unsafe { (Stdio::from_raw_handle(fd), Stdio::from_raw_handle(fd)) } + } } else { panic!("could not pipe to awk"); }; @@ -99,7 +108,7 @@ mod full { assert!(success, "awk"); success &= Command::new("git") - .args(&["diff", "--exit-code", out_file]) + .args(&["diff", "--ignore-space-at-eol", "--exit-code", out_file]) .env("PAGER", "") .status() .expect("could not run git diff") diff --git a/tests/full_cases/libc-0.2.28-0.2.31 b/tests/full_cases/libc-0.2.28-0.2.31.linux similarity index 100% rename from tests/full_cases/libc-0.2.28-0.2.31 rename to tests/full_cases/libc-0.2.28-0.2.31.linux diff --git a/tests/full_cases/libc-0.2.28-0.2.31.windows_msvc b/tests/full_cases/libc-0.2.28-0.2.31.windows_msvc new file mode 100644 index 0000000000000..d4b8e6342fa42 --- /dev/null +++ b/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/tests/full_cases/log-0.3.4-0.3.8 b/tests/full_cases/log-0.3.4-0.3.8.linux similarity index 100% rename from tests/full_cases/log-0.3.4-0.3.8 rename to tests/full_cases/log-0.3.4-0.3.8.linux diff --git a/tests/full_cases/log-0.3.4-0.3.8.osx b/tests/full_cases/log-0.3.4-0.3.8.osx new file mode 100644 index 0000000000000..b7ce494eadc75 --- /dev/null +++ b/tests/full_cases/log-0.3.4-0.3.8.osx @@ -0,0 +1,171 @@ +version bump: 0.3.4 -> (technically breaking) -> 0.3.5 +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:266:27 + | +266 | #[derive(Copy, Eq, Debug, Hash)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:410:27 + | +410 | #[derive(Copy, Eq, Debug, Hash)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> log-0.3.8/src/lib.rs:517:10 + | +517 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::Eq>` + --> log-0.3.8/src/lib.rs:552:10 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::PartialEq>` + --> log-0.3.8/src/lib.rs:552:14 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::Ord>` + --> log-0.3.8/src/lib.rs:552:25 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::PartialOrd>` + --> log-0.3.8/src/lib.rs:552:30 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::hash::Hash>` + --> log-0.3.8/src/lib.rs:552:42 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> log-0.3.8/src/lib.rs:552:48 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:591:1 + | +591 | / impl Log for NopLogger { +592 | | fn enabled(&self, _: &LogMetadata) -> bool { false } +593 | | +594 | | fn log(&self, _: &LogRecord) {} +595 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:30 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:34 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:45 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:50 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8/src/lib.rs:604:62 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: path changes to `set_logger_raw` + --> log-0.3.8/src/lib.rs:713:1 + | +713 | / pub unsafe fn set_logger_raw(make_logger: M) -> Result<(), SetLoggerError> +714 | | where M: FnOnce(MaxLogLevelFilter) -> *const Log { +715 | | if STATE.compare_and_swap(UNINITIALIZED, INITIALIZING, +716 | | Ordering::SeqCst) != UNINITIALIZED { +... | +722 | | Ok(()) +723 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `shutdown_logger` + --> log-0.3.8/src/lib.rs:736:1 + | +736 | / pub fn shutdown_logger() -> Result, ShutdownLoggerError> { +737 | | shutdown_logger_raw().map(|l| unsafe { mem::transmute(l) }) +738 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `shutdown_logger_raw` + --> log-0.3.8/src/lib.rs:754:1 + | +754 | / pub fn shutdown_logger_raw() -> Result<*const Log, ShutdownLoggerError> { +755 | | // Set the global log level to stop other thread from logging +756 | | MAX_LOG_LEVEL_FILTER.store(0, Ordering::SeqCst); +757 | | +... | +772 | | } +773 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `ShutdownLoggerError` + --> log-0.3.8/src/lib.rs:797:1 + | +797 | pub struct ShutdownLoggerError(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + diff --git a/tests/full_cases/log-0.3.4-0.3.8.windows_msvc b/tests/full_cases/log-0.3.4-0.3.8.windows_msvc new file mode 100644 index 0000000000000..86b0f543b587f --- /dev/null +++ b/tests/full_cases/log-0.3.4-0.3.8.windows_msvc @@ -0,0 +1,171 @@ +version bump: 0.3.4 -> (technically breaking) -> 0.3.5 +warning: technically breaking changes in `` + --> log-0.3.8\src\lib.rs:266:27 + | +266 | #[derive(Copy, Eq, Debug, Hash)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8\src\lib.rs:410:27 + | +410 | #[derive(Copy, Eq, Debug, Hash)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> log-0.3.8\src\lib.rs:517:10 + | +517 | #[derive(Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::Eq>` + --> log-0.3.8\src\lib.rs:552:10 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::PartialEq>` + --> log-0.3.8\src\lib.rs:552:14 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::Ord>` + --> log-0.3.8\src\lib.rs:552:25 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::cmp::PartialOrd>` + --> log-0.3.8\src\lib.rs:552:30 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::hash::Hash>` + --> log-0.3.8\src\lib.rs:552:42 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as std::fmt::Debug>` + --> log-0.3.8\src\lib.rs:552:48 + | +552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + | ^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8\src\lib.rs:591:1 + | +591 | / impl Log for NopLogger { +592 | | fn enabled(&self, _: &LogMetadata) -> bool { false } +593 | | +594 | | fn log(&self, _: &LogRecord) {} +595 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8\src\lib.rs:604:30 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8\src\lib.rs:604:34 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8\src\lib.rs:604:45 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8\src\lib.rs:604:50 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `` + --> log-0.3.8\src\lib.rs:604:62 + | +604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + | ^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: path changes to `set_logger_raw` + --> log-0.3.8\src\lib.rs:713:1 + | +713 | / pub unsafe fn set_logger_raw(make_logger: M) -> Result<(), SetLoggerError> +714 | | where M: FnOnce(MaxLogLevelFilter) -> *const Log { +715 | | if STATE.compare_and_swap(UNINITIALIZED, INITIALIZING, +716 | | Ordering::SeqCst) != UNINITIALIZED { +... | +722 | | Ok(()) +723 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `shutdown_logger` + --> log-0.3.8\src\lib.rs:736:1 + | +736 | / pub fn shutdown_logger() -> Result, ShutdownLoggerError> { +737 | | shutdown_logger_raw().map(|l| unsafe { mem::transmute(l) }) +738 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `shutdown_logger_raw` + --> log-0.3.8\src\lib.rs:754:1 + | +754 | / pub fn shutdown_logger_raw() -> Result<*const Log, ShutdownLoggerError> { +755 | | // Set the global log level to stop other thread from logging +756 | | MAX_LOG_LEVEL_FILTER.store(0, Ordering::SeqCst); +757 | | +... | +772 | | } +773 | | } + | |_^ + | + = note: added definition (technically breaking) + +warning: path changes to `ShutdownLoggerError` + --> log-0.3.8\src\lib.rs:797:1 + | +797 | pub struct ShutdownLoggerError(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: added definition (technically breaking) + From d7ad44075f86028e4af11915e9fa2070f1fcd583 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Mon, 26 Nov 2018 15:09:46 +0100 Subject: [PATCH 389/553] Run Windows tests on appveyor as well --- appveyor.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index cff738be149d7..11e21d4cade1e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,10 +14,7 @@ install: build: false -test_script: - - set RUST_BACKTRACE=full - - cargo build -# - cargo test --verbose +test_script: C:\msys64\usr\bin\sh ci\run.sh notifications: - provider: Email From 9c406275317524c743659ebb31a6f63d63438fa2 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Mon, 26 Nov 2018 17:09:09 +0100 Subject: [PATCH 390/553] Add support for --target --- ci/run.sh | 12 ++++++++++ src/bin/cargo_semver.rs | 12 ++++++++-- tests/examples.rs | 51 ++++++++++++++++++++++++++--------------- tests/full.rs | 23 +++++++++++-------- 4 files changed, 68 insertions(+), 30 deletions(-) diff --git a/ci/run.sh b/ci/run.sh index 48f97d1dac286..fc50ec136174b 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -9,6 +9,18 @@ export RUST_BACKTRACE=full cargo build cargo test --verbose -- --nocapture +case "${TRAVIS_OS_NAME}" 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 diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index dde9f8293ea4a..d1868b84db8c3 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -240,12 +240,19 @@ fn do_main(config: &Config, matches: &Matches, explain: bool) -> CargoResult<()> debug!("running rust-semverver on compiled crates"); - let mut child = Command::new("rust-semverver") + 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())]) + .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()) .env("RUST_SEMVER_CRATE_VERSION", stable_version) @@ -328,6 +335,7 @@ fn main() { "use a `name:version` string as current/new crate", "NAME:VERSION", ); + opts.optopt("T", "target", "Build for the target triple", ""); let config = match Config::default() { Ok(cfg) => cfg, diff --git a/tests/examples.rs b/tests/examples.rs index 7c6ed6c8b9954..33e6164ea5ab6 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -18,37 +18,44 @@ mod features { .try_clone() .expect("could not create `stderr` file by cloning `stdout`"); - success &= Command::new("rustc") - .args(&["--crate-type=lib", "-o", &old_rlib]) + 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()) - .status() - .expect("could not run rustc") - .success(); + .stdin(Stdio::null()); + + if let Ok(target_args) = &target_args { + cmd.args(target_args); + } + success &= cmd.status().expect("could not run rustc").success(); assert!(success, "couldn't compile old"); - success &= Command::new("rustc") - .args(&["--crate-type=lib", "-o", &new_rlib]) + 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()) - .status() - .expect("could not run rustc") - .success(); + .stdin(Stdio::null()); + + if let Ok(target_args) = &target_args { + cmd.args(target_args); + } + + success &= cmd.status().expect("could not run rustc").success(); assert!(success, "couldn't compile new"); - success &= Command::new( + let mut cmd = Command::new( Path::new(".") .join("target") .join("debug") .join("rust-semverver") .to_str() .unwrap(), - ) - .args(&[ + ); + cmd.args(&[ "--crate-type=lib", "-Zverbose", "--extern", @@ -65,10 +72,16 @@ mod features { .env("RUST_SEMVER_CRATE_VERSION", "1.0.0") .stdin(Stdio::null()) .stdout(Stdio::from(stdout)) - .stderr(Stdio::from(stderr)) - .status() - .expect("could not run rust-semverver") - .success(); + .stderr(Stdio::from(stderr)); + + if let Ok(target_args) = &target_args { + cmd.args(target_args); + } + + success &= cmd + .status() + .expect("could not run rust-semverver") + .success(); assert!(success, "rust-semverver"); diff --git a/tests/full.rs b/tests/full.rs index 61841fb19a644..de7a45d880834 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -88,15 +88,20 @@ mod full { let old_version = format!("{}:{}", crate_name, old_version); let new_version = format!("{}:{}", crate_name, new_version); - success &= Command::new("./target/debug/cargo-semver") - .args(&["-S", &old_version, "-C", &new_version]) - .env("RUST_BACKTRACE", "full") - .stdin(Stdio::null()) - .stdout(out_pipe) - .stderr(err_pipe) - .status() - .expect("could not run cargo semver") - .success(); + success &= { + let mut cmd = Command::new("./target/debug/cargo-semver"); + cmd.args(&["-S", &old_version, "-C", &new_version]) + .env("RUST_BACKTRACE", "full") + .stdin(Stdio::null()) + .stdout(out_pipe) + .stderr(err_pipe); + + if let Ok(target) = std::env::var("TEST_TARGET") { + cmd.args(&["--target", &target]); + } + + cmd.status().expect("could not run cargo semver").success() + }; assert!(success, "cargo semver"); From fa51b614e13432e4ff0ca66b3ed514335520441b Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 21 Nov 2018 14:05:43 +0100 Subject: [PATCH 391/553] Implement --api-guidelines flag to not diagnose non-technical breaking changes --- src/bin/cargo_semver.rs | 17 +++++++++++++++- src/bin/rust_semverver.rs | 20 +++++++++++++------ src/semcheck/changes.rs | 20 ++++++++++++++++--- tests/cases/addition/stdout_api_guidelines | 1 + .../cases/addition_path/stdout_api_guidelines | 1 + .../cases/addition_use/stdout_api_guidelines | 15 ++++++++++++++ tests/examples.rs | 14 ++++++++++--- 7 files changed, 75 insertions(+), 13 deletions(-) create mode 100644 tests/cases/addition/stdout_api_guidelines create mode 100644 tests/cases/addition_path/stdout_api_guidelines create mode 100644 tests/cases/addition_use/stdout_api_guidelines diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index d1868b84db8c3..13514f80903be 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -252,11 +252,21 @@ fn do_main(config: &Config, matches: &Matches, explain: bool) -> CargoResult<()> child.args(&["--target", &target]); } - let mut child = child + let child = child .arg("-") .stdin(Stdio::piped()) .env("RUST_SEMVER_CRATE_VERSION", stable_version) .env("RUST_SEMVER_VERBOSE", format!("{}", explain)) + .env( + "RUST_SEMVER_API_GUIDELINES", + if matches.opt_present("a") { + "true" + } else { + "false" + }, + ); + + let mut child = child .spawn() .map_err(|e| Error(format!("could not spawn rustc: {}", e)))?; @@ -311,6 +321,11 @@ fn main() { opts.optflag("V", "version", "print version information and exit"); opts.optflag("e", "explain", "print detailed error explanations"); 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( "s", "stable-path", diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 86f0aa10a9c44..2e7569ed207ab 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -32,7 +32,7 @@ use std::{ use syntax::{ast, source_map::Pos}; /// After the typechecker has finished it's work, perform our checks. -fn callback(state: &driver::CompileState, version: &str, verbose: bool) { +fn callback(state: &driver::CompileState, version: &str, verbose: bool, api_guidelines: bool) { let tcx = state.tcx.unwrap(); // To select the old and new crates we look at the position of the declaration in the @@ -62,8 +62,7 @@ fn callback(state: &driver::CompileState, version: &str, verbose: bool) { 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); - - changes.output(tcx.sess, version, verbose); + changes.output(tcx.sess, version, verbose, api_guidelines); } else { tcx.sess.err("could not find crate old and new crates"); } @@ -77,15 +76,18 @@ struct SemVerVerCompilerCalls { version: String, /// The output mode. verbose: bool, + /// Output only changes that are breaking according to the API guidelines. + api_guidelines: bool, } impl SemVerVerCompilerCalls { /// Construct a new compilation wrapper, given a version string. - pub fn new(version: String, verbose: bool) -> Box { + pub fn new(version: String, verbose: bool, api_guidelines: bool) -> Box { Box::new(Self { default: Box::new(RustcDefaultCalls), version, verbose, + api_guidelines, }) } @@ -96,6 +98,10 @@ impl SemVerVerCompilerCalls { pub fn get_version(&self) -> &String { &self.version } + + pub fn get_api_guidelines(&self) -> bool { + self.api_guidelines + } } impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { @@ -148,13 +154,14 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { ) -> driver::CompileController<'a> { let default = self.get_default(); let version = self.get_version().clone(); + let api_guidelines = self.get_api_guidelines(); let Self { verbose, .. } = *self; let mut controller = CompilerCalls::build_controller(default, sess, matches); let old_callback = std::mem::replace(&mut controller.after_analysis.callback, box |_| {}); controller.after_analysis.callback = box move |state| { debug!("running rust-semverver after_analysis callback"); - callback(state, &version, verbose); + callback(state, &version, verbose, api_guidelines); debug!("running other after_analysis callback"); old_callback(state); }; @@ -217,8 +224,9 @@ fn main() { }; let verbose = std::env::var("RUST_SEMVER_VERBOSE") == Ok("true".to_string()); + let api_guidelines = std::env::var("RUST_SEMVER_API_GUIDELINES") == Ok("true".to_string()); - let cc = SemVerVerCompilerCalls::new(version, verbose); + let cc = SemVerVerCompilerCalls::new(version, verbose, api_guidelines); rustc_driver::run_compiler(&args, cc, None, None) }); diff --git a/src/semcheck/changes.rs b/src/semcheck/changes.rs index 3ed44bd5c0a47..59f5afc36bdc6 100644 --- a/src/semcheck/changes.rs +++ b/src/semcheck/changes.rs @@ -879,7 +879,7 @@ impl<'tcx> ChangeSet<'tcx> { } /// Format the contents of a change set for user output. - pub fn output(&self, session: &Session, version: &str, verbose: bool) { + pub fn output(&self, session: &Session, version: &str, verbose: bool, api_guidelines: bool) { if let Ok(mut new_version) = Version::parse(version) { if new_version.major == 0 { new_version.increment_patch(); @@ -901,11 +901,25 @@ impl<'tcx> ChangeSet<'tcx> { for key in self.spans.values() { if let Some(change) = self.path_changes.get(key) { - change.report(session); + if api_guidelines { + match change.to_category() { + Patch | Breaking => change.report(session), + _ => (), + } + } else { + change.report(session); + } } if let Some(change) = self.changes.get(key) { - change.report(session, verbose); + if api_guidelines { + match change.to_category() { + Patch | Breaking => change.report(session, verbose), + _ => (), + } + } else { + change.report(session, verbose); + } } } } diff --git a/tests/cases/addition/stdout_api_guidelines b/tests/cases/addition/stdout_api_guidelines new file mode 100644 index 0000000000000..045662d9257f7 --- /dev/null +++ b/tests/cases/addition/stdout_api_guidelines @@ -0,0 +1 @@ +version bump: 1.0.0 -> (technically breaking) -> 1.1.0 diff --git a/tests/cases/addition_path/stdout_api_guidelines b/tests/cases/addition_path/stdout_api_guidelines new file mode 100644 index 0000000000000..045662d9257f7 --- /dev/null +++ b/tests/cases/addition_path/stdout_api_guidelines @@ -0,0 +1 @@ +version bump: 1.0.0 -> (technically breaking) -> 1.1.0 diff --git a/tests/cases/addition_use/stdout_api_guidelines b/tests/cases/addition_use/stdout_api_guidelines new file mode 100644 index 0000000000000..744aefb460742 --- /dev/null +++ b/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` + --> $REPO_PATH/tests/cases/addition_use/new.rs:5:1 + | +5 | / pub struct Def<'a> { +6 | | pub field1: Abc, +7 | | pub field2: &'a Bcd, +8 | | } + | |_^ + | + = warning: type error: expected (), found struct `new::Abc` (breaking) + = warning: type error: expected (), found trait new::Bcd (breaking) + +error: aborting due to previous error + diff --git a/tests/examples.rs b/tests/examples.rs index 33e6164ea5ab6..d4a72fdb2908b 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -5,10 +5,9 @@ mod features { process::{Command, Stdio}, }; - fn test_example(path: &Path) { + fn test_example(path: &Path, out_file: &Path) { let mut success = true; - let out_file = path.join("stdout"); let old_rlib = path.join("libold.rlib").to_str().unwrap().to_owned(); let new_rlib = path.join("libnew.rlib").to_str().unwrap().to_owned(); @@ -78,6 +77,10 @@ mod features { cmd.args(target_args); } + if out_file.to_str().unwrap().contains("stdout_api_guidelines") { + cmd.env("RUST_SEMVER_API_GUIDELINES", "true"); + } + success &= cmd .status() .expect("could not run rust-semverver") @@ -144,7 +147,12 @@ mod features { #[test] fn $name() { let path = Path::new("tests").join("cases").join(stringify!($name)); - test_example(&path); + test_example(&path, &path.join("stdout")); + + if path.join("stdout_api_guidelines").exists() { + eprintln!("api-guidelines"); + test_example(&path, &path.join("stdout_api_guidelines")); + } } }; ($($name:ident),*) => { From b3f8a7dfe9cfb698035a07a19e9f0f25bc49120a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 8 Dec 2018 18:45:52 +0100 Subject: [PATCH 392/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 739eb66fb8c37..936407d29f42a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["semver", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] -version = "0.1.22" +version = "0.1.23" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" From f8fab65861a1f62f2c806beb957967ffa1b4e5f9 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 20 Dec 2018 00:52:55 +0900 Subject: [PATCH 393/553] Fix build in nightly cc https://github.com/rust-lang/rust/pull/56481. --- src/semcheck/mismatch.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index d3f0481fe081e..335d2f19827f1 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -8,7 +8,7 @@ use rustc::{ hir::def_id::DefId, ty::{ self, - relate::{Relate, RelateResult, TypeRelation}, + relate::{Relate, RelateResult, TraitObjectMode, TypeRelation}, subst::Substs, Ty, TyCtxt, Visibility::Public, @@ -94,6 +94,10 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, "Mismatch" } + fn trait_object_mode(&self) -> TraitObjectMode { + TraitObjectMode::NoSquash + } + fn a_is_expected(&self) -> bool { true } From 8b46690ba22f4dc1804fe209f50dba89bd276127 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 2 Jan 2019 14:25:37 +0100 Subject: [PATCH 394/553] Update cargo and crates-io dependencies --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 936407d29f42a..32ae7f1dbd1e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,8 +25,8 @@ name = "rust-semverver" path = "src/bin/rust_semverver.rs" [dependencies] -cargo = "0.31" -crates-io = "0.19" +cargo = "0.32" +crates-io = "0.20" env_logger = "0.6" log = "0.4" semver = "0.9" From e8ef0177353d9d19348d1628b0de335d8d1db377 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 2 Jan 2019 14:38:01 +0100 Subject: [PATCH 395/553] Update paths from rust-lang-nursery to rust-dev-tools --- Cargo.toml | 6 +++--- README.md | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 936407d29f42a..7e3b51ae63b74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "semverver" description = "Automatic verification of SemVer adhrence in rust library crates" -repository = "https://github.com/rust-lang-nursery/rust-semverver" +repository = "https://github.com/rust-dev-tools/rust-semverver" readme = "README.md" keywords = ["semver", "plugin"] @@ -13,8 +13,8 @@ authors = ["Inokentiy Babushkin "] license-file = "LICENSE" [badges] -travis-ci = { repository = "rust-lang-nursery/rust-semverver" } -appveyor = { repository = "rust-lang-nursery/rust-semverver" } +travis-ci = { repository = "rust-dev-tools/rust-semverver" } +appveyor = { repository = "rust-dev-tools/rust-semverver" } [[bin]] name = "cargo-semver" diff --git a/README.md b/README.md index 9942154edcddd..9334ef5dae429 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # rust-semverver -[![Travis Build Status](https://travis-ci.org/rust-lang-nursery/rust-semverver.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/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) @@ -11,7 +11,7 @@ analyzes the current crate's source code for changes compared to the most recent on `crates.io`. Details on the work done during GSoC 2017 can be found -[here](https://github.com/rust-lang-nursery/rust-semverver/blob/master/doc/gsoc.md). +[here](https://github.com/rust-dev-tools/rust-semverver/blob/master/doc/gsoc.md). ## Background @@ -21,7 +21,7 @@ said dummy and all necessary analysis is performed in that context, where type i and other resources are available. More information on the inner workings of the tool can be found -[here](https://github.com/rust-lang-nursery/rust-semverver/blob/master/doc/impl_notes.md). +[here](https://github.com/rust-dev-tools/rust-semverver/blob/master/doc/impl_notes.md). ## Installation @@ -46,7 +46,7 @@ You can also install the newest version of the tool from git: ```sh $ rustup update nightly -$ cargo +nightly install --git https://github.com/rust-lang-nursery/rust-semverver +$ cargo +nightly install --git https://github.com/rust-dev-tools/rust-semverver ```
@@ -60,7 +60,7 @@ $ cargo +nightly install --git https://github.com/rust-lang-nursery/rust-semverv $ rustup update nightly $ rustup default nightly -$ git clone https://github.com/rust-lang-nursery/rust-semverver +$ git clone https://github.com/rust-dev-tools/rust-semverver $ cd rust-semverver $ cargo install ``` From 29baebceafb7174aa2f4af81f7326e696012f4f5 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Thu, 3 Jan 2019 14:00:05 +0100 Subject: [PATCH 396/553] Update cargo to 0.34 --- Cargo.toml | 3 ++- src/bin/cargo_semver.rs | 52 ++++++++++++++++++++++++++------------- src/semcheck/translate.rs | 2 +- src/semcheck/traverse.rs | 4 +-- 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 981b6f758e73b..428c2af5c2971 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,8 @@ name = "rust-semverver" path = "src/bin/rust_semverver.rs" [dependencies] -cargo = "0.32" +cargo = { git = "https://github.com/gnzlbg/cargo", branch = "revert_6193" } +failure = "0.1" crates-io = "0.20" env_logger = "0.6" log = "0.4" diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 13514f80903be..fed56f0ccc2ca 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -4,18 +4,19 @@ extern crate cargo; extern crate crates_io; extern crate env_logger; +extern crate failure; extern crate getopts; #[macro_use] extern crate log; use cargo::{ - core::{compiler::CompileMode, Package, PackageId, Source, SourceId, Workspace}, + core::{ + compiler::CompileMode, Package, PackageId, PackageSet, Source, SourceId, SourceMap, + Workspace, + }, exit_with_error, ops::{compile, CompileOptions}, - util::{ - config::Config, important_paths::find_root_manifest_for_wd, CargoError, CargoResult, - CliError, - }, + util::{config::Config, important_paths::find_root_manifest_for_wd, CargoResult, CliError}, }; use crates_io::{Crate, Registry}; use getopts::{Matches, Options}; @@ -123,17 +124,36 @@ impl<'a> WorkInfo<'a> { /// version. fn remote( config: &'a Config, - source: &mut SourceInfo<'a>, + source: SourceInfo<'a>, info: &NameAndVersion, ) -> CargoResult> { // TODO: fall back to locally cached package instance, or better yet, search for it // first. - let package_id = PackageId::new(info.name, info.version, &source.id)?; - debug!("(remote) package id: {:?}", package_id); - let package = source.source.download(&package_id)?; + let package_ids = [PackageId::new(info.name, info.version, source.id)?]; + debug!("(remote) package id: {:?}", package_ids[0]); + let sources = { + let mut s = SourceMap::new(); + s.insert(source.source); + s + }; + + let package_set = PackageSet::new(&package_ids, sources, config)?; + let mut downloads = package_set.enable_download()?; + let package = if let Some(package) = downloads.start(package_ids[0])? { + package + } else { + downloads.wait()?; + downloads + .start(package_ids[0])? + .expect("started download did not finish after wait") + }; + let workspace = Workspace::ephemeral(package.clone(), config, None, false)?; - Ok(Self { package, workspace }) + Ok(Self { + package: package.clone(), + workspace, + }) } /// Obtain the paths to the produced rlib and the dependency output directory. @@ -155,7 +175,7 @@ impl<'a> WorkInfo<'a> { env::remove_var("RUSTFLAGS"); - let rlib = compilation.libraries[self.package.package_id()] + let rlib = compilation.libraries[&self.package.package_id()] .iter() .find(|t| t.0.name() == name) .ok_or_else(|| Error("lost a build artifact".to_owned()))?; @@ -192,10 +212,8 @@ fn do_main(config: &Config, matches: &Matches, explain: bool) -> CargoResult<()> debug!("running cargo-semver"); - let mut source = SourceInfo::new(config)?; - let current = if let Some(opt) = matches.opt_str("C") { - WorkInfo::remote(config, &mut source, &parse_arg(&opt)?)? + WorkInfo::remote(config, SourceInfo::new(config)?, &parse_arg(&opt)?)? } else { WorkInfo::local(config, matches.opt_str("c").map(PathBuf::from))? }; @@ -206,7 +224,7 @@ fn do_main(config: &Config, matches: &Matches, explain: bool) -> CargoResult<()> let info = parse_arg(&opt)?; let version = info.version.to_owned(); - let work_info = WorkInfo::remote(config, &mut source, &info)?; + let work_info = WorkInfo::remote(config, SourceInfo::new(config)?, &info)?; (work_info, version) } else if let Some(path) = matches.opt_str("s") { @@ -219,7 +237,7 @@ fn do_main(config: &Config, matches: &Matches, explain: bool) -> CargoResult<()> name: &name, version: &stable_crate.max_version, }; - let work_info = WorkInfo::remote(config, &mut source, &info)?; + let work_info = WorkInfo::remote(config, SourceInfo::new(config)?, &info)?; (work_info, stable_crate.max_version.clone()) }; @@ -305,7 +323,7 @@ fn version() { /// /// Parse CLI arguments, handle their semantics, and provide for proper error handling. fn main() { - fn err(config: &Config, e: CargoError) -> ! { + fn err(config: &Config, e: failure::Error) -> ! { exit_with_error(CliError::new(e, 1), &mut config.shell()); } diff --git a/src/semcheck/translate.rs b/src/semcheck/translate.rs index 21771c3e04c4f..16f7597d73cf3 100644 --- a/src/semcheck/translate.rs +++ b/src/semcheck/translate.rs @@ -479,7 +479,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { self.translate_predicates(orig_def_id, param_env.caller_bounds) .map(|target_preds| ParamEnv { caller_bounds: self.tcx.intern_predicates(&target_preds), - reveal: param_env.reveal, + ..param_env }) } diff --git a/src/semcheck/traverse.rs b/src/semcheck/traverse.rs index 2e5c734916e81..d0287c12abcbd 100644 --- a/src/semcheck/traverse.rs +++ b/src/semcheck/traverse.rs @@ -386,11 +386,11 @@ fn diff_adts(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, o let mut fields = BTreeMap::new(); for variant in &old_def.variants { - variants.entry(variant.name).or_insert((None, None)).0 = Some(variant); + variants.entry(variant.ident.name).or_insert((None, None)).0 = Some(variant); } for variant in &new_def.variants { - variants.entry(variant.name).or_insert((None, None)).1 = Some(variant); + variants.entry(variant.ident.name).or_insert((None, None)).1 = Some(variant); } for items in variants.values() { From b8dc61ad6a72df58c76c75b3162f7eeff3bc97b0 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Thu, 3 Jan 2019 14:11:55 +0100 Subject: [PATCH 397/553] Fix clippy issues --- src/semcheck/mapping.rs | 4 ++-- src/semcheck/mismatch.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/semcheck/mapping.rs b/src/semcheck/mapping.rs index 285ea82968371..b141987ccb71f 100644 --- a/src/semcheck/mapping.rs +++ b/src/semcheck/mapping.rs @@ -32,7 +32,7 @@ pub type InherentImplSet = BTreeSet<(DefId, DefId)>; /// 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::stutter))] +#[cfg_attr(feature = "cargo-clippy", allow(clippy::module_name_repetitions))] pub struct IdMapping { /// The old crate. old_crate: CrateNum, @@ -297,7 +297,7 @@ impl IdMapping { /// /// 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::stutter))] +#[cfg_attr(feature = "cargo-clippy", allow(clippy::module_name_repetitions))] pub struct NameMapping { /// The exports in the type namespace. type_map: HashMap, Option)>, diff --git a/src/semcheck/mismatch.rs b/src/semcheck/mismatch.rs index 335d2f19827f1..64f9c4dac4898 100644 --- a/src/semcheck/mismatch.rs +++ b/src/semcheck/mismatch.rs @@ -22,7 +22,7 @@ use std::collections::{HashMap, HashSet, VecDeque}; /// 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::stutter))] +#[cfg_attr(feature = "cargo-clippy", allow(clippy::module_name_repetitions))] pub struct MismatchRelation<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { /// The type context used. tcx: TyCtxt<'a, 'gcx, 'tcx>, From 4888c7d4f5d02a5b990b6db2429acbd2c6f36935 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Thu, 3 Jan 2019 16:17:39 +0100 Subject: [PATCH 398/553] Use patched cargo version until a better solution is available --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 428c2af5c2971..4217246b653fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ name = "rust-semverver" path = "src/bin/rust_semverver.rs" [dependencies] -cargo = { git = "https://github.com/gnzlbg/cargo", branch = "revert_6193" } +cargo-semverver = "0.34" failure = "0.1" crates-io = "0.20" env_logger = "0.6" From 5c20a314f41963940746f3aba24ab71e15b54e6b Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Thu, 3 Jan 2019 17:09:25 +0100 Subject: [PATCH 399/553] Use PackageSet::get_one --- src/bin/cargo_semver.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index fed56f0ccc2ca..42c5c56b98dbb 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -138,16 +138,7 @@ impl<'a> WorkInfo<'a> { }; let package_set = PackageSet::new(&package_ids, sources, config)?; - let mut downloads = package_set.enable_download()?; - let package = if let Some(package) = downloads.start(package_ids[0])? { - package - } else { - downloads.wait()?; - downloads - .start(package_ids[0])? - .expect("started download did not finish after wait") - }; - + let package = package_set.get_one(package_ids[0])?; let workspace = Workspace::ephemeral(package.clone(), config, None, false)?; Ok(Self { From 085967bbce75f91cce2ccd1923c3025be7cac9e7 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Thu, 3 Jan 2019 16:16:38 +0100 Subject: [PATCH 400/553] Update rust-semverver driver Instead of having a custom `CompilerCalls` impl, the analysis pass is just injected into the default compiler. --- src/bin/rust_semverver.rs | 324 ++++++++++++++------------------------ 1 file changed, 119 insertions(+), 205 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 2e7569ed207ab..d82f1c61e5796 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -1,5 +1,6 @@ #![feature(box_syntax)] #![feature(rustc_private)] +#![feature(try_from)] extern crate env_logger; extern crate getopts; @@ -13,162 +14,19 @@ extern crate rustc_metadata; extern crate semverver; extern crate syntax; -use rustc::{ - hir::def_id::*, - middle::cstore::ExternCrate, - session::{ - config::{self, ErrorOutputType, Input}, - Session, - }, -}; -use rustc_codegen_utils::codegen_backend::CodegenBackend; -use rustc_driver::{driver, Compilation, CompilerCalls, RustcDefaultCalls}; -use rustc_metadata::cstore::CStore; +use rustc::{hir::def_id::*, middle::cstore::ExternCrate}; +use rustc_driver::{driver::CompileController, Compilation}; use semverver::semcheck::run_analysis; +use std::convert::TryInto; use std::{ - path::{Path, PathBuf}, - process::Command, + path::Path, + process::{exit, Command}, }; -use syntax::{ast, source_map::Pos}; - -/// After the typechecker has finished it's work, perform our checks. -fn callback(state: &driver::CompileState, version: &str, verbose: bool, api_guidelines: bool) { - let tcx = state.tcx.unwrap(); - - // 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 = DefId { - krate: *crate_num, - index: CRATE_DEF_INDEX, - }; - - match *tcx.extern_crate(def_id) { - Some(ExternCrate { - span, direct: true, .. - }) if span.data().lo.to_usize() > 0 => Some((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); - changes.output(tcx.sess, version, verbose, api_guidelines); - } else { - tcx.sess.err("could not find crate old and new crates"); - } -} +use syntax::source_map::Pos; -/// A wrapper to control compilation. -struct SemVerVerCompilerCalls { - /// The wrapped compilation handle. - default: Box, - /// The version of the old crate. - version: String, - /// The output mode. - verbose: bool, - /// Output only changes that are breaking according to the API guidelines. - api_guidelines: bool, -} - -impl SemVerVerCompilerCalls { - /// Construct a new compilation wrapper, given a version string. - pub fn new(version: String, verbose: bool, api_guidelines: bool) -> Box { - Box::new(Self { - default: Box::new(RustcDefaultCalls), - version, - verbose, - api_guidelines, - }) - } - - pub fn get_default(&self) -> Box { - self.default.clone() - } - - pub fn get_version(&self) -> &String { - &self.version - } - - pub fn get_api_guidelines(&self) -> bool { - self.api_guidelines - } -} - -impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { - fn early_callback( - &mut self, - matches: &getopts::Matches, - sopts: &config::Options, - cfg: &ast::CrateConfig, - descriptions: &rustc_errors::registry::Registry, - output: ErrorOutputType, - ) -> Compilation { - debug!("running rust-semverver early_callback"); - self.default - .early_callback(matches, sopts, cfg, descriptions, output) - } - - fn no_input( - &mut self, - matches: &getopts::Matches, - sopts: &config::Options, - cfg: &ast::CrateConfig, - odir: &Option, - ofile: &Option, - descriptions: &rustc_errors::registry::Registry, - ) -> Option<(Input, Option)> { - debug!("running rust-semverver no_input"); - self.default - .no_input(matches, sopts, cfg, odir, ofile, descriptions) - } - - fn late_callback( - &mut self, - trans_crate: &CodegenBackend, - matches: &getopts::Matches, - sess: &Session, - cstore: &CStore, - input: &Input, - odir: &Option, - ofile: &Option, - ) -> Compilation { - debug!("running rust-semverver late_callback"); - self.default - .late_callback(trans_crate, matches, sess, cstore, input, odir, ofile) - } - - fn build_controller( - self: Box, - sess: &Session, - matches: &getopts::Matches, - ) -> driver::CompileController<'a> { - let default = self.get_default(); - let version = self.get_version().clone(); - let api_guidelines = self.get_api_guidelines(); - let Self { verbose, .. } = *self; - let mut controller = CompilerCalls::build_controller(default, sess, matches); - let old_callback = std::mem::replace(&mut controller.after_analysis.callback, box |_| {}); - - controller.after_analysis.callback = box move |state| { - debug!("running rust-semverver after_analysis callback"); - callback(state, &version, verbose, api_guidelines); - debug!("running other after_analysis callback"); - old_callback(state); - }; - controller.after_analysis.stop = Compilation::Stop; - - controller - } +/// Display semverver version. +fn show_version() { + println!(env!("CARGO_PKG_VERSION")); } /// Main routine. @@ -176,60 +34,116 @@ impl<'a> CompilerCalls<'a> for SemVerVerCompilerCalls { /// Find the sysroot before passing our args to the compiler driver, after registering our custom /// compiler driver. fn main() { - if env_logger::try_init().is_err() { - eprintln!("ERROR: could not initialize logger"); - } + rustc_driver::init_rustc_env_logger(); debug!("running rust-semverver compiler driver"); + exit( + rustc_driver::run(move || { + use std::env; + + if std::env::args().any(|a| a == "--version" || a == "-V") { + show_version(); + exit(0); + } + + let sys_root = option_env!("SYSROOT") + .map(String::from) + .or_else(|| std::env::var("SYSROOT").ok()) + .or_else(|| { + let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); + let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); + home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain))) + }) + .or_else(|| { + Command::new("rustc") + .arg("--print") + .arg("sysroot") + .output() + .ok() + .and_then(|out| String::from_utf8(out.stdout).ok()) + .map(|s| s.trim().to_owned()) + }) + .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); + + // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. + // We're invoking the compiler programmatically, so we ignore this/ + let mut orig_args: Vec = env::args().collect(); + if orig_args.len() <= 1 { + std::process::exit(1); + } + + if Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref()) { + // we still want to be able to invoke it normally though + orig_args.remove(1); + } + + // this conditional check for the --sysroot flag is there so users can call + // `clippy_driver` directly + // without having to pass --sysroot or anything + let args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { + orig_args.clone() + } else { + orig_args + .clone() + .into_iter() + .chain(Some("--sysroot".to_owned())) + .chain(Some(sys_root)) + .collect() + }; + + let verbose = std::env::var("RUST_SEMVER_VERBOSE") == Ok("true".to_string()); + let api_guidelines = std::env::var("RUST_SEMVER_API_GUIDELINES") == Ok("true".to_string()); + let version = if let Ok(ver) = std::env::var("RUST_SEMVER_CRATE_VERSION") { + ver + } else { + "no_version".to_owned() + }; - let home = option_env!("RUSTUP_HOME"); - let toolchain = option_env!("RUSTUP_TOOLCHAIN"); - let sys_root: PathBuf = if let (Some(home), Some(toolchain)) = (home, toolchain) { - Path::new(home).join("toolchains").join(toolchain) - } else { - option_env!("SYSROOT") - .map(|s| s.to_owned()) - .or_else(|| { - Command::new("rustc") - .args(&["--print", "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 compilation, or use rustup") - .into() - }; - - assert!( - sys_root.exists(), - "sysroot \"{}\" does not exist", - sys_root.display() - ); - - let result = rustc_driver::run(move || { - let args: Vec = if std::env::args().any(|s| s == "--sysroot") { - std::env::args().collect() - } else { - std::env::args() - .chain(Some("--sysroot".to_owned())) - .chain(Some(sys_root.to_str().unwrap().to_owned())) - .collect() - }; - - let version = if let Ok(ver) = std::env::var("RUST_SEMVER_CRATE_VERSION") { - ver - } else { - "no_version".to_owned() - }; - - let verbose = std::env::var("RUST_SEMVER_VERBOSE") == Ok("true".to_string()); - let api_guidelines = std::env::var("RUST_SEMVER_API_GUIDELINES") == Ok("true".to_string()); - - let cc = SemVerVerCompilerCalls::new(version, verbose, api_guidelines); - rustc_driver::run_compiler(&args, cc, None, None) - }); - - #[cfg_attr(feature = "cargo-clippy", allow(clippy::cast_possible_truncation))] - std::process::exit(result as i32); + let mut controller = CompileController::basic(); + + controller.after_analysis.callback = Box::new(move |state| { + debug!("running rust-semverver after_analysis..."); + let tcx = state.tcx.unwrap(); + + // 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 = DefId { + krate: *crate_num, + index: CRATE_DEF_INDEX, + }; + + match *tcx.extern_crate(def_id) { + Some(ExternCrate { + span, direct: true, .. + }) if span.data().lo.to_usize() > 0 => Some((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); + changes.output(tcx.sess, &version, verbose, api_guidelines); + } else { + tcx.sess.err("could not find crate old and new crates"); + } + + debug!("running rust-semverver after_analysis finished!"); + }); + controller.after_analysis.stop = Compilation::Stop; + + let args = args; + rustc_driver::run_compiler(&args, Box::new(controller), None, None) + }).try_into() + .expect("exit code too large"), + ) } From 05f7dc6138590225512a3bbb09c0a1f6358acde9 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Fri, 4 Jan 2019 11:23:52 +0100 Subject: [PATCH 401/553] Port to the 2018 edition and cargo-semver cleanups --- Cargo.toml | 4 +- src/bin/cargo_semver.rs | 558 ++++++++++++++++---------------- src/bin/rust_semverver.rs | 8 +- src/{semcheck => }/changes.rs | 1 + src/lib.rs | 18 +- src/{semcheck => }/mapping.rs | 0 src/{semcheck => }/mismatch.rs | 3 +- src/semcheck/mod.rs | 12 - src/{semcheck => }/translate.rs | 3 +- src/{semcheck => }/traverse.rs | 15 +- src/{semcheck => }/typeck.rs | 15 +- tests/full.rs | 10 +- 12 files changed, 319 insertions(+), 328 deletions(-) rename src/{semcheck => }/changes.rs (99%) rename src/{semcheck => }/mapping.rs (100%) rename src/{semcheck => }/mismatch.rs (99%) delete mode 100644 src/semcheck/mod.rs rename src/{semcheck => }/translate.rs (99%) rename src/{semcheck => }/traverse.rs (99%) rename src/{semcheck => }/typeck.rs (98%) diff --git a/Cargo.toml b/Cargo.toml index 4217246b653fe..43ef5ae6eb288 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,15 +2,13 @@ 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.23" - authors = ["Inokentiy Babushkin "] license-file = "LICENSE" +edition = "2018" [badges] travis-ci = { repository = "rust-dev-tools/rust-semverver" } diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 42c5c56b98dbb..5ec67d0f23870 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -1,235 +1,105 @@ -#![feature(box_syntax)] #![feature(rustc_private)] +#![feature(uniform_paths)] -extern crate cargo; -extern crate crates_io; -extern crate env_logger; -extern crate failure; extern crate getopts; -#[macro_use] -extern crate log; - -use cargo::{ - core::{ - compiler::CompileMode, Package, PackageId, PackageSet, Source, SourceId, SourceMap, - Workspace, - }, - exit_with_error, - ops::{compile, CompileOptions}, - util::{config::Config, important_paths::find_root_manifest_for_wd, CargoResult, CliError}, -}; -use crates_io::{Crate, Registry}; -use getopts::{Matches, Options}; + +use log::debug; use std::{ - env, error, fmt, io::Write, - path::PathBuf, + env, + path::{Path, PathBuf}, process::{Command, Stdio}, }; +use cargo::core::{Package, PackageId, PackageSet, Source, SourceId, SourceMap, Workspace}; -/// Very simple error representation. -#[derive(Debug)] -struct Error(String); - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "{}", self.0) - } -} - -impl error::Error for Error { - fn description(&self) -> &str { - &self.0 - } -} +pub type Result = cargo::util::CargoResult; -/// Given a crate name, try to locate the corresponding crate on `crates.io`. +/// Main entry point. /// -/// If no crate with the exact name is present, error out. -fn exact_search(query: &str) -> CargoResult { - let mut registry = Registry::new("https://crates.io".to_owned(), None); - - registry - .search(query, 1) - .map_err(|e| { - Error(format!( - "failed to retrieve search results from the registry: {}", - e - )) - .into() - }) - .and_then(|(mut crates, _)| { - crates - .drain(..) - .find(|krate| krate.name == query) - .ok_or_else(|| Error(format!("failed to find a matching crate `{}`", query)).into()) - }) -} - -/// A specification of package name and version. -struct NameAndVersion<'a> { - /// The package's name. - name: &'a str, - /// The package's version, as a semver-string. - version: &'a str, -} - -/// A specification of a package source to fetch remote packages from. -struct SourceInfo<'a> { - /// The source id to be used. - id: SourceId, - /// The source to be used. - source: Box, -} - -impl<'a> SourceInfo<'a> { - /// Construct a new source info for `crates.io`. - fn new(config: &'a Config) -> CargoResult> { - let source_id = SourceId::crates_io(config)?; - let source = source_id.load(config)?; - - debug!("source id loaded: {:?}", source_id); - - Ok(Self { - id: source_id, - source, - }) +/// 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"); } -} -/// A specification of a package and it's workspace. -struct WorkInfo<'a> { - /// The package to be compiled. - package: Package, - /// The package's workspace. - workspace: Workspace<'a>, -} + let config = match cargo::Config::default() { + Ok(cfg) => cfg, + Err(e) => panic!("can't obtain cargo config: {:?}", e), + }; -impl<'a> WorkInfo<'a> { - /// Construct a package/workspace pair for the local directory. - fn local(config: &'a Config, explicit_path: Option) -> CargoResult> { - let manifest_path = if let Some(path) = explicit_path { - find_root_manifest_for_wd(&path)? - } else { - find_root_manifest_for_wd(config.cwd())? - }; + let opts = cli::options(); - let workspace = Workspace::new(&manifest_path, config)?; - let package = workspace.load(&manifest_path)?; + let matches = match cli::parse_args(&opts) { + Ok(m) => m, + Err(f) => cli::exit_with_error(&config, f.to_owned().into()), + }; - Ok(Self { package, workspace }) + if matches.opt_present("h") { + cli::print_help(&opts); + return; } - /// Construct a package/workspace pair by fetching the package of a specified name and - /// version. - fn remote( - config: &'a Config, - source: SourceInfo<'a>, - info: &NameAndVersion, - ) -> CargoResult> { - // TODO: fall back to locally cached package instance, or better yet, search for it - // first. - let package_ids = [PackageId::new(info.name, info.version, source.id)?]; - debug!("(remote) package id: {:?}", package_ids[0]); - let sources = { - let mut s = SourceMap::new(); - s.insert(source.source); - s - }; - - let package_set = PackageSet::new(&package_ids, sources, config)?; - let package = package_set.get_one(package_ids[0])?; - let workspace = Workspace::ephemeral(package.clone(), config, None, false)?; - - Ok(Self { - package: package.clone(), - workspace, - }) + if matches.opt_present("V") { + cli::print_version(); + return; } - /// Obtain the paths to the produced rlib and the dependency output directory. - fn rlib_and_dep_output( - &self, - config: &'a Config, - name: &str, - current: bool, - ) -> CargoResult<(PathBuf, PathBuf)> { - let opts = CompileOptions::new(config, CompileMode::Build).unwrap(); - - if current { - env::set_var("RUSTFLAGS", "-C metadata=new"); - } else { - env::set_var("RUSTFLAGS", "-C metadata=old"); - } - - let compilation = compile(&self.workspace, &opts)?; - - env::remove_var("RUSTFLAGS"); - - let rlib = compilation.libraries[&self.package.package_id()] - .iter() - .find(|t| t.0.name() == name) - .ok_or_else(|| Error("lost a build artifact".to_owned()))?; + if let Err(e) = cli::validate_args(&matches) { + cli::exit_with_error(&config, e); + } - Ok((rlib.1.clone(), compilation.deps_output)) + if let Err(e) = run(&config, &matches, matches.opt_present("e")) { + cli::exit_with_error(&config, e); } } -/// Perform the heavy lifting. -/// -/// Obtain the two versions of the crate to be analyzed as specified by command line arguments -/// and/or defaults, and dispatch the actual analysis. +/// 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 do_main(config: &Config, matches: &Matches, explain: bool) -> CargoResult<()> { - fn parse_arg(opt: &str) -> CargoResult { - let mut split = opt.split(':'); - let name = if let Some(n) = split.next() { - n - } else { - return Err(Error("spec has to be of form `name:version`".to_owned()).into()); - }; - let version = if let Some(v) = split.next() { - v - } else { - return Err(Error("spec has to be of form `name:version`".to_owned()).into()); - }; - - if split.next().is_some() { - return Err(Error("spec has to be of form `name:version`".to_owned()).into()); - } - - Ok(NameAndVersion { name, version }) - } - +fn run(config: &cargo::Config, matches: &getopts::Matches, explain: bool) -> Result<()> { + use cargo::util::important_paths::find_root_manifest_for_wd; debug!("running cargo-semver"); - let current = if let Some(opt) = matches.opt_str("C") { - WorkInfo::remote(config, SourceInfo::new(config)?, &parse_arg(&opt)?)? + // 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, + SourceInfo::new(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 { - WorkInfo::local(config, matches.opt_str("c").map(PathBuf::from))? + // 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(); - let (stable, stable_version) = if let Some(opt) = matches.opt_str("S") { - let info = parse_arg(&opt)?; + // 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, SourceInfo::new(config)?, &info)?; - (work_info, version) } else if let Some(path) = matches.opt_str("s") { - let work_info = WorkInfo::local(config, Some(PathBuf::from(path)))?; + // -s "local_path": + let work_info = WorkInfo::local(config, &PathBuf::from(path))?; let version = format!("{}", work_info.package.version()); (work_info, version) } else { - let stable_crate = exact_search(&name)?; - let info = NameAndVersion { + // 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, SourceInfo::new(config)?, &info)?; - (work_info, stable_crate.max_version.clone()) }; @@ -277,7 +147,7 @@ fn do_main(config: &Config, matches: &Matches, explain: bool) -> CargoResult<()> let mut child = child .spawn() - .map_err(|e| Error(format!("could not spawn rustc: {}", e)))?; + .map_err(|e| failure::err_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 @@ -289,115 +159,247 @@ fn do_main(config: &Config, matches: &Matches, explain: bool) -> CargoResult<()> extern crate new;" ))?; } else { - return Err(Error("could not pipe to rustc (wtf?)".to_owned()).into()); + return Err(failure::err_msg("could not pipe to rustc (wtf?)".to_owned()).into()); } child .wait() - .map_err(|e| Error(format!("failed to wait for rustc: {}", e)))?; + .map_err(|e| failure::err_msg(format!("failed to wait for rustc: {}", e)))?; Ok(()) } -/// Print a help message. -fn help(opts: &Options) { - let brief = "usage: cargo semver [options] [-- cargo options]"; - print!("{}", opts.usage(brief)); -} +/// CLI utils +mod cli { + extern crate getopts; + use cargo::util::CliError; + + /// 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("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( + "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.optopt("T", "target", "Build for the target triple", ""); + opts + } -/// Print a version message. -fn version() { - println!("{}", env!("CARGO_PKG_VERSION")); -} + /// Parse CLI arguments + pub fn parse_args(opts: &getopts::Options) -> Result { + let args: Vec = std::env::args().skip(1).collect(); + opts.parse(&args) + } -/// Main entry point. -/// -/// Parse CLI arguments, handle their semantics, and provide for proper error handling. -fn main() { - fn err(config: &Config, e: failure::Error) -> ! { - exit_with_error(CliError::new(e, 1), &mut config.shell()); + /// Validate CLI arguments + pub fn validate_args(matches: &getopts::Matches) -> Result<(), failure::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(failure::err_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(failure::err_msg(msg.to_owned())); + } + + Ok(()) } - if env_logger::try_init().is_err() { - eprintln!("ERROR: could not initialize logger"); + /// Print a help message + pub fn print_help(opts: &getopts::Options) { + let brief = "usage: cargo semver [options] [-- cargo options]"; + print!("{}", opts.usage(brief)); } - let args: Vec = std::env::args().skip(1).collect(); - - let mut opts = 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("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( - "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.optopt("T", "target", "Build for the target triple", ""); - - let config = match Config::default() { - Ok(cfg) => cfg, - Err(e) => panic!("can't obtain config: {:?}", e), - }; + /// Print a version message. + pub fn print_version() { + println!("{}", env!("CARGO_PKG_VERSION")); + } - let matches = match opts.parse(&args) { - Ok(m) => m, - Err(f) => err(&config, f.to_owned().into()), - }; + /// Exit with error `e`. + pub fn exit_with_error(config: &cargo::Config, e: failure::Error) -> ! { + cargo::exit_with_error(CliError::new(e, 1), &mut config.shell()); + } +} - if matches.opt_present("h") { - help(&opts); - return; +/// A package's name and version. +pub struct PackageNameAndVersion<'a> { + /// The crate's name. + pub name: &'a str, + /// The package's version, as a semver-string. + pub version: &'a str, +} + +impl<'a> PackageNameAndVersion<'a> { + /// Parses the string "name:version" into `Self` + pub fn parse(s: &'a str) -> Result { + let err = || { + failure::err_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 }) + } } +} - if matches.opt_present("V") { - version(); - return; +/// A specification of a package source to fetch remote packages from. +pub struct SourceInfo<'a> { + /// The source id to be used. + id: SourceId, + /// The source to be used. + source: Box, +} + +impl<'a> SourceInfo<'a> { + /// Construct a new source info for `crates.io`. + pub fn new(config: &'a cargo::Config) -> Result> { + let source_id = SourceId::crates_io(config)?; + let source = source_id.load(config)?; + + debug!("source id loaded: {:?}", source_id); + + Ok(Self { + id: source_id, + source, + }) } +} + +/// 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>, +} - 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"; - err(&config, Error(msg.to_owned()).into()); +impl<'a> WorkInfo<'a> { + /// Construct a package/workspace pair for the `manifest_path` + pub fn local(config: &'a cargo::Config, manifest_path: &Path) -> Result> { + let workspace = Workspace::new(&manifest_path, config)?; + let package = workspace.load(&manifest_path)?; + Ok(Self { package, workspace }) } - 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"; - err(&config, Error(msg.to_owned()).into()); + /// Construct a package/workspace pair by fetching the package of a + /// specified `PackageNameAndVersion` from the `source`. + pub fn remote( + config: &'a cargo::Config, + source: SourceInfo<'a>, + &PackageNameAndVersion { name, version }: &PackageNameAndVersion, + ) -> Result> { + // TODO: fall back to locally cached package instance, or better yet, search for it + // first. + let package_ids = [PackageId::new(name, version, source.id)?]; + debug!("(remote) package id: {:?}", package_ids[0]); + let sources = { + let mut s = SourceMap::new(); + s.insert(source.source); + s + }; + + let package_set = PackageSet::new(&package_ids, sources, config)?; + let package = package_set.get_one(package_ids[0])?; + let workspace = Workspace::ephemeral(package.clone(), config, None, false)?; + + Ok(Self { + package: package.clone(), + workspace, + }) } - if let Err(e) = do_main(&config, &matches, matches.opt_present("e")) { - err(&config, e); + /// 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, + ) -> Result<(PathBuf, PathBuf)> { + let opts = + cargo::ops::CompileOptions::new(config, cargo::core::compiler::CompileMode::Build) + .unwrap(); + + env::set_var("RUSTFLAGS", format!("-C metadata={}", if current { "new" } else { "old" })); + let compilation = cargo::ops::compile(&self.workspace, &opts)?; + env::remove_var("RUSTFLAGS"); + + // TODO: use cargo metadata to fetch the rlib path here: + let rlib = compilation.libraries[&self.package.package_id()] + .iter() + .find(|t| t.0.name() == name) + .ok_or_else(|| failure::err_msg("lost a build artifact".to_owned()))?; + + Ok((rlib.1.clone(), compilation.deps_output)) } } + +/// Given a `crate_name`, try to locate the corresponding crate on `crates.io`. +/// +/// If no crate with the exact name is present, error out. +pub fn find_on_crates_io(crate_name: &str) -> Result { + let mut registry = crates_io::Registry::new("https://crates.io".to_owned(), None); + + registry + .search(crate_name, 1) + .map_err(|e| { + failure::err_msg(format!( + "failed to retrieve search results from the registry: {}", + e + )) + .into() + }) + .and_then(|(mut crates, _)| { + crates + .drain(..) + .find(|krate| krate.name == crate_name) + .ok_or_else(|| { + failure::err_msg(format!("failed to find a matching crate `{}`", crate_name)) + .into() + }) + }) +} diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index d82f1c61e5796..22a4c076690ce 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -1,22 +1,18 @@ -#![feature(box_syntax)] #![feature(rustc_private)] #![feature(try_from)] -extern crate env_logger; extern crate getopts; -#[macro_use] -extern crate log; extern crate rustc; extern crate rustc_codegen_utils; extern crate rustc_driver; extern crate rustc_errors; extern crate rustc_metadata; -extern crate semverver; extern crate syntax; +use log::debug; use rustc::{hir::def_id::*, middle::cstore::ExternCrate}; use rustc_driver::{driver::CompileController, Compilation}; -use semverver::semcheck::run_analysis; +use semverver::run_analysis; use std::convert::TryInto; use std::{ path::Path, diff --git a/src/semcheck/changes.rs b/src/changes.rs similarity index 99% rename from src/semcheck/changes.rs rename to src/changes.rs index 59f5afc36bdc6..92e8395471d4a 100644 --- a/src/semcheck/changes.rs +++ b/src/changes.rs @@ -928,6 +928,7 @@ impl<'tcx> ChangeSet<'tcx> { #[cfg(test)] pub mod tests { pub use super::*; + extern crate quickcheck; use quickcheck::*; use rustc::hir::def_id::DefId; diff --git a/src/lib.rs b/src/lib.rs index e0f9bff1bef76..c5647ce11b1e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,16 +1,16 @@ #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] +#![feature(uniform_paths)] -#[macro_use] -extern crate log; - -#[cfg(test)] -extern crate quickcheck; - -extern crate rand; extern crate rustc; -extern crate semver; extern crate syntax; extern crate syntax_pos; -pub mod semcheck; +mod changes; +mod mapping; +mod mismatch; +mod translate; +mod traverse; +mod typeck; + +pub use self::traverse::run_analysis; diff --git a/src/semcheck/mapping.rs b/src/mapping.rs similarity index 100% rename from src/semcheck/mapping.rs rename to src/mapping.rs diff --git a/src/semcheck/mismatch.rs b/src/mismatch.rs similarity index 99% rename from src/semcheck/mismatch.rs rename to src/mismatch.rs index 64f9c4dac4898..10d940027ce60 100644 --- a/src/semcheck/mismatch.rs +++ b/src/mismatch.rs @@ -4,6 +4,8 @@ //! 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_id::DefId, ty::{ @@ -14,7 +16,6 @@ use rustc::{ Visibility::Public, }, }; -use semcheck::mapping::IdMapping; use std::collections::{HashMap, HashSet, VecDeque}; /// A relation searching for items appearing at the same spot in a type. diff --git a/src/semcheck/mod.rs b/src/semcheck/mod.rs deleted file mode 100644 index 55d2699c71fca..0000000000000 --- a/src/semcheck/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -//! This module holds all logic and data structures needed to perform semver analysis on two -//! modules which are (usually) just crate roots. - -pub mod changes; - -mod mapping; -mod mismatch; -mod translate; -mod traverse; -mod typeck; - -pub use self::traverse::run_analysis; diff --git a/src/semcheck/translate.rs b/src/translate.rs similarity index 99% rename from src/semcheck/translate.rs rename to src/translate.rs index 16f7597d73cf3..9c71518f6ca0c 100644 --- a/src/semcheck/translate.rs +++ b/src/translate.rs @@ -1,6 +1,8 @@ //! 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, infer::InferCtxt, @@ -10,7 +12,6 @@ use rustc::{ GenericParamDefKind, ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt, }, }; -use semcheck::mapping::{IdMapping, InherentEntry}; use std::collections::HashMap; /// The context in which `DefId` translation happens. diff --git a/src/semcheck/traverse.rs b/src/traverse.rs similarity index 99% rename from src/semcheck/traverse.rs rename to src/traverse.rs index d0287c12abcbd..b49cbd962409c 100644 --- a/src/semcheck/traverse.rs +++ b/src/traverse.rs @@ -9,6 +9,14 @@ //! 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, Def, Export}, @@ -20,13 +28,6 @@ use rustc::{ Visibility::Public, }, }; -use semcheck::{ - changes::{ChangeSet, ChangeType}, - mapping::{IdMapping, NameMapping}, - mismatch::MismatchRelation, - translate::TranslationContext, - typeck::{BoundContext, TypeComparisonContext}, -}; use std::collections::{BTreeMap, HashSet, VecDeque}; /// The main entry point to our analysis passes. diff --git a/src/semcheck/typeck.rs b/src/typeck.rs similarity index 98% rename from src/semcheck/typeck.rs rename to src/typeck.rs index 4278d2737ca71..3be8b44b9097b 100644 --- a/src/semcheck/typeck.rs +++ b/src/typeck.rs @@ -3,6 +3,12 @@ //! 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, infer::InferCtxt, @@ -14,11 +20,6 @@ use rustc::{ GenericParamDefKind, ParamEnv, Predicate, TraitRef, Ty, TyCtxt, }, }; -use semcheck::{ - changes::ChangeSet, - mapping::IdMapping, - translate::{InferenceCleanupFolder, TranslationContext}, -}; /// The context in which bounds analysis happens. pub struct BoundContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { @@ -222,7 +223,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { if let Err(err) = error { let scope_tree = ScopeTree::default(); - let mut outlives_env = OutlivesEnvironment::new(target_param_env); + 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 @@ -296,7 +297,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { orig_substs: &Substs<'tcx>, target_substs: &Substs<'tcx>, ) { - use semcheck::changes::ChangeType::{BoundsLoosened, BoundsTightened}; + use crate::changes::ChangeType::{BoundsLoosened, BoundsTightened}; let tcx = self.infcx.tcx; diff --git a/tests/full.rs b/tests/full.rs index de7a45d880834..0df8d3dbe5381 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -1,8 +1,10 @@ mod full { - use std::env; - use std::fs::File; - use std::path::{Path, PathBuf}; - use std::process::{Command, Stdio}; + use std::{ + env, + fs::File, + path::{Path, PathBuf}, + process::{Command, Stdio}, + }; fn test_full(crate_name: &str, old_version: &str, new_version: &str) { let mut success = true; From 2d1df7dde4a917b7eb82f5ade6758457411e7bab Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 7 Jan 2019 11:43:10 +0100 Subject: [PATCH 402/553] Implemented cargo build plan based compilation artifact discovery. --- Cargo.toml | 7 +++-- src/bin/cargo_semver.rs | 70 ++++++++++++++++++++++++++++++++--------- 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 43ef5ae6eb288..1007f28bc56e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,13 +23,14 @@ name = "rust-semverver" path = "src/bin/rust_semverver.rs" [dependencies] -cargo-semverver = "0.34" -failure = "0.1" +cargo = "0.32" crates-io = "0.20" env_logger = "0.6" +failure = "0.1" log = "0.4" -semver = "0.9" rand = "0.6" +semver = "0.9" +serde_json = "1.0.34" [dev-dependencies] quickcheck = "0.7" diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 5ec67d0f23870..3e8ff5d76d6dd 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -1,16 +1,21 @@ #![feature(rustc_private)] #![feature(uniform_paths)] +#![feature(set_stdio)] extern crate getopts; +extern crate serde_json; +use cargo::core::{Package, PackageId, PackageSet, Source, SourceId, SourceMap, Workspace}; use log::debug; +use serde_json::Value; use std::{ - io::Write, env, + io::BufReader, + io::Write, + fs::File, path::{Path, PathBuf}, process::{Command, Stdio}, }; -use cargo::core::{Package, PackageId, PackageSet, Source, SourceId, SourceMap, Workspace}; pub type Result = cargo::util::CargoResult; @@ -106,6 +111,9 @@ fn run(config: &cargo::Config, matches: &getopts::Matches, explain: bool) -> Res let (current_rlib, current_deps_output) = current.rlib_and_dep_output(config, &name, true)?; let (stable_rlib, stable_deps_output) = stable.rlib_and_dep_output(config, &name, false)?; + println!("current_rlib: {:?}", current_rlib); + println!("stable_rlib: {:?}", stable_rlib); + if matches.opt_present("d") { println!( "--extern old={} -L{} --extern new={} -L{}", @@ -335,7 +343,7 @@ impl<'a> WorkInfo<'a> { ) -> Result> { // TODO: fall back to locally cached package instance, or better yet, search for it // first. - let package_ids = [PackageId::new(name, version, source.id)?]; + let package_ids = [PackageId::new(name, version, &source.id)?]; debug!("(remote) package id: {:?}", package_ids[0]); let sources = { let mut s = SourceMap::new(); @@ -344,7 +352,7 @@ impl<'a> WorkInfo<'a> { }; let package_set = PackageSet::new(&package_ids, sources, config)?; - let package = package_set.get_one(package_ids[0])?; + let package = package_set.get_one(&package_ids[0])?; let workspace = Workspace::ephemeral(package.clone(), config, None, false)?; Ok(Self { @@ -360,21 +368,55 @@ impl<'a> WorkInfo<'a> { name: &str, current: bool, ) -> Result<(PathBuf, PathBuf)> { - let opts = - cargo::ops::CompileOptions::new(config, cargo::core::compiler::CompileMode::Build) - .unwrap(); + 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; + // TODO: this is where we could insert feature flag builds (or using the CLI mechanisms) + + env::set_var("RUSTFLAGS", + format!("-C metadata={}", if current { "new" } else { "old" })); + + let mut outdir = env::temp_dir(); + outdir.push(&format!("cargo_semver_{}_{}", name, current)); + + // 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; - env::set_var("RUSTFLAGS", format!("-C metadata={}", if current { "new" } else { "old" })); let compilation = cargo::ops::compile(&self.workspace, &opts)?; env::remove_var("RUSTFLAGS"); - // TODO: use cargo metadata to fetch the rlib path here: - let rlib = compilation.libraries[&self.package.package_id()] - .iter() - .find(|t| t.0.name() == name) - .ok_or_else(|| failure::err_msg("lost a build artifact".to_owned()))?; + let build_plan: Value = + serde_json::from_reader(BufReader::new(File::open(&outdir)?))?; + + // FIXME: yuck drilling + if let Value::Object(m) = build_plan { + if let Some(Value::Array(v)) = m.get("invocations") { + for s in v { + if let Value::Object(m2) = s { + if let Some(Value::String(s2)) = m2.get("package_name") { + if s2 != name { continue; } + } + + if let Some(Value::Array(v2)) = m2.get("outputs") { + if let Some(Value::String(s)) = v2.get(0) { + return Ok((PathBuf::from(s), compilation.deps_output)); + } + } + } + } + } + } - Ok((rlib.1.clone(), compilation.deps_output)) + Err(failure::err_msg("lost build artifact".to_owned())) } } From beb3aa8c513f3666edf4feff98596fc10eab3be6 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 7 Jan 2019 12:42:32 +0100 Subject: [PATCH 403/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 1007f28bc56e7..3d3cf7e1207c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.23" +version = "0.1.24" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From ebb488f0cc456b39fe77566574864a14e629d2a4 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 7 Jan 2019 13:28:43 +0100 Subject: [PATCH 404/553] Switched to a slightly less disgusting JSON parsing approach. --- Cargo.toml | 2 ++ src/bin/cargo_semver.rs | 37 +++++++++++++++++++------------------ 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3d3cf7e1207c8..c53ebed9aca4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,8 @@ failure = "0.1" log = "0.4" rand = "0.6" semver = "0.9" +serde = "1.0.84" +serde_derive = "1.0.84" serde_json = "1.0.34" [dev-dependencies] diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 3e8ff5d76d6dd..338ecad525837 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -3,11 +3,13 @@ #![feature(set_stdio)] extern crate getopts; +extern crate serde; +#[macro_use] +extern crate serde_derive; extern crate serde_json; use cargo::core::{Package, PackageId, PackageSet, Source, SourceId, SourceMap, Workspace}; use log::debug; -use serde_json::Value; use std::{ env, io::BufReader, @@ -19,6 +21,17 @@ use std::{ pub type Result = cargo::util::CargoResult; +#[derive(Debug, Deserialize)] +struct Invocation { + package_name: String, + outputs: Vec, +} + +#[derive(Debug, Deserialize)] +struct BuildPlan { + invocations: Vec, +} + /// Main entry point. /// /// Parse CLI arguments, handle their semantics, and provide for proper error handling. @@ -394,25 +407,13 @@ impl<'a> WorkInfo<'a> { let compilation = cargo::ops::compile(&self.workspace, &opts)?; env::remove_var("RUSTFLAGS"); - let build_plan: Value = + let build_plan: BuildPlan = serde_json::from_reader(BufReader::new(File::open(&outdir)?))?; - // FIXME: yuck drilling - if let Value::Object(m) = build_plan { - if let Some(Value::Array(v)) = m.get("invocations") { - for s in v { - if let Value::Object(m2) = s { - if let Some(Value::String(s2)) = m2.get("package_name") { - if s2 != name { continue; } - } - - if let Some(Value::Array(v2)) = m2.get("outputs") { - if let Some(Value::String(s)) = v2.get(0) { - return Ok((PathBuf::from(s), compilation.deps_output)); - } - } - } - } + // TODO: handle multiple outputs gracefully + for i in &build_plan.invocations { + if i.package_name == name { + return Ok((i.outputs[0].clone(), compilation.deps_output)); } } From cc03ed7e0919a40bcd13acf8c39ab86468248d77 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 7 Jan 2019 19:18:07 +0100 Subject: [PATCH 405/553] Build with newest nightly. --- src/mismatch.rs | 16 ++++++++-------- tests/cases/regions/stdout | 18 +----------------- 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/src/mismatch.rs b/src/mismatch.rs index 10d940027ce60..9d9376f08980a 100644 --- a/src/mismatch.rs +++ b/src/mismatch.rs @@ -10,7 +10,7 @@ use rustc::{ hir::def_id::DefId, ty::{ self, - relate::{Relate, RelateResult, TraitObjectMode, TypeRelation}, + relate::{Relate, RelateResult, TypeRelation}, subst::Substs, Ty, TyCtxt, Visibility::Public, @@ -95,10 +95,6 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, "Mismatch" } - fn trait_object_mode(&self) -> TraitObjectMode { - TraitObjectMode::NoSquash - } - fn a_is_expected(&self) -> bool { true } @@ -189,9 +185,13 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, let a = a_obj.principal(); let b = b_obj.principal(); - if self.check_substs(a.skip_binder().substs, b.skip_binder().substs) { - let _ = self.relate(&a.skip_binder().substs, &b.skip_binder().substs)?; - Some((a.skip_binder().def_id, b.skip_binder().def_id)) + 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)?; + Some((a.skip_binder().def_id, b.skip_binder().def_id)) + } else { + None + } } else { None } diff --git a/tests/cases/regions/stdout b/tests/cases/regions/stdout index d012a2110e871..4abe1dd636ec7 100644 --- a/tests/cases/regions/stdout +++ b/tests/cases/regions/stdout @@ -31,21 +31,5 @@ error: breaking changes in `def` | = warning: type error: expected reference, found bool (breaking) -error: breaking changes in `efg` - --> $REPO_PATH/tests/cases/regions/new.rs:17:1 - | -17 | pub fn efg(_: &str) { } - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: type error: expected bound lifetime parameterBrAnon(0), found concrete lifetime (breaking) - -error: breaking changes in `fgh` - --> $REPO_PATH/tests/cases/regions/new.rs:19:1 - | -19 | pub fn fgh(_: &'static str) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: type error: expected bound lifetime parameterBrAnon(0), found concrete lifetime (breaking) - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors From b8d1c38fa2cdea83d975505d5bcca0841011e2e6 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 7 Jan 2019 19:38:51 +0100 Subject: [PATCH 406/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c53ebed9aca4f..4b2da0b1b78c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.24" +version = "0.1.25" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From 44e1c14d25995ac3b348e5841a580904e2a54277 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 30 Jan 2019 16:35:38 +0100 Subject: [PATCH 407/553] Fix build --- src/mismatch.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/mismatch.rs b/src/mismatch.rs index 10d940027ce60..25d53580afc9a 100644 --- a/src/mismatch.rs +++ b/src/mismatch.rs @@ -10,7 +10,7 @@ use rustc::{ hir::def_id::DefId, ty::{ self, - relate::{Relate, RelateResult, TraitObjectMode, TypeRelation}, + relate::{Relate, RelateResult, TypeRelation}, subst::Substs, Ty, TyCtxt, Visibility::Public, @@ -95,10 +95,6 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, "Mismatch" } - fn trait_object_mode(&self) -> TraitObjectMode { - TraitObjectMode::NoSquash - } - fn a_is_expected(&self) -> bool { true } From abed1d7a052d658ab9b93204786e735d80f06c6b Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 13 Feb 2019 15:49:00 +0100 Subject: [PATCH 408/553] Fix compilation --- src/bin/cargo_semver.rs | 3 +-- src/lib.rs | 1 - src/mapping.rs | 1 + 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 338ecad525837..52ace312cff40 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -1,5 +1,4 @@ #![feature(rustc_private)] -#![feature(uniform_paths)] #![feature(set_stdio)] extern crate getopts; @@ -232,7 +231,7 @@ mod cli { "use a `name:version` string as current/new crate", "NAME:VERSION", ); - opts.optopt("T", "target", "Build for the target triple", ""); + opts.optopt("", "target", "Build for the target triple", ""); opts } diff --git a/src/lib.rs b/src/lib.rs index c5647ce11b1e6..2ceb224f740cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,5 @@ #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] -#![feature(uniform_paths)] extern crate rustc; extern crate syntax; diff --git a/src/mapping.rs b/src/mapping.rs index b141987ccb71f..98db3a495934a 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -331,6 +331,7 @@ impl NameMapping { ToolMod => Some(&mut self.type_map), Fn(_) | Const(_) | + ConstParam(_) | Static(_, _) | StructCtor(_, _) | SelfCtor(_) | From fc08da9e25cc448e05885972177ad6a734e5b349 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Feb 2019 11:50:18 +0100 Subject: [PATCH 409/553] Fix exit code of rust-semverver in tests --- src/bin/rust_semverver.rs | 1 - tests/cases/regions/stdout | 18 ++++++- tests/examples.rs | 105 ++++++++++++++++++------------------- 3 files changed, 69 insertions(+), 55 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 22a4c076690ce..8a342adb8cb72 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -1,5 +1,4 @@ #![feature(rustc_private)] -#![feature(try_from)] extern crate getopts; extern crate rustc; diff --git a/tests/cases/regions/stdout b/tests/cases/regions/stdout index 4abe1dd636ec7..d012a2110e871 100644 --- a/tests/cases/regions/stdout +++ b/tests/cases/regions/stdout @@ -31,5 +31,21 @@ error: breaking changes in `def` | = warning: type error: expected reference, found bool (breaking) -error: aborting due to 4 previous errors +error: breaking changes in `efg` + --> $REPO_PATH/tests/cases/regions/new.rs:17:1 + | +17 | pub fn efg(_: &str) { } + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected bound lifetime parameterBrAnon(0), found concrete lifetime (breaking) + +error: breaking changes in `fgh` + --> $REPO_PATH/tests/cases/regions/new.rs:19:1 + | +19 | pub fn fgh(_: &'static str) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: type error: expected bound lifetime parameterBrAnon(0), found concrete lifetime (breaking) + +error: aborting due to 6 previous errors diff --git a/tests/examples.rs b/tests/examples.rs index d4a72fdb2908b..9dc94e8aaeed8 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -5,9 +5,7 @@ mod features { process::{Command, Stdio}, }; - fn test_example(path: &Path, out_file: &Path) { - let mut success = true; - + fn test_example(path: &Path, out_file: &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(); @@ -29,8 +27,8 @@ mod features { cmd.args(target_args); } - success &= cmd.status().expect("could not run rustc").success(); - assert!(success, "couldn't compile old"); + 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]) @@ -42,9 +40,8 @@ mod features { cmd.args(target_args); } - success &= cmd.status().expect("could not run rustc").success(); - - assert!(success, "couldn't compile new"); + 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(".") @@ -81,12 +78,11 @@ mod features { cmd.env("RUST_SEMVER_API_GUIDELINES", "true"); } - success &= cmd - .status() - .expect("could not run rust-semverver") - .success(); - - assert!(success, "rust-semverver"); + let rustsemverver_result = cmd.status().expect("could not run rust-semverver").success(); + assert_eq!( + rustsemverver_result, expected_result, + "rust-semverver returned an unexpected result" + ); { // replace root path with with $REPO_PATH @@ -122,7 +118,7 @@ mod features { } } - success &= Command::new("git") + let git_result = Command::new("git") .args(&[ "diff", "--ignore-space-at-eol", @@ -134,7 +130,7 @@ mod features { .expect("could not run git diff") .success(); - assert!(success, "git"); + assert!(git_result, "git reports a diff"); Command::new("rm") .args(&[&old_rlib, &new_rlib]) @@ -143,54 +139,57 @@ mod features { } macro_rules! test { - ($name:ident) => { + ($name:ident => $result:literal) => { #[test] fn $name() { let path = Path::new("tests").join("cases").join(stringify!($name)); - test_example(&path, &path.join("stdout")); + test_example(&path, &path.join("stdout"), $result); if path.join("stdout_api_guidelines").exists() { eprintln!("api-guidelines"); - test_example(&path, &path.join("stdout_api_guidelines")); + test_example(&path, &path.join("stdout_api_guidelines"), $result); } } }; - ($($name:ident),*) => { - $(test!($name);)* - } + ($($name:ident => $result:literal),*) => { + $(test!($name => $result);)* + }; + ($($name:ident => $result:literal,)*) => { + $(test!($name => $result);)* + }; } test! { - addition, - addition_path, - addition_use, - bounds, - circular, - consts, - enums, - func, - func_local_items, - infer, - infer_regress, - inherent_impls, - issue_34, - issue_50, - kind_change, - macros, - max_priv, - mix, - pathologic_paths, - pub_use, - regions, - removal, - removal_path, - removal_use, - sealed_traits, - structs, - swap, - traits, - trait_impls, - trait_objects, - ty_alias + 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, } } From 5a8c55198a3f242dafc958e4aae82af0960b97b7 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Feb 2019 13:13:25 +0100 Subject: [PATCH 410/553] Correctly propagate rustc-semverver error in cargo-semver --- src/bin/cargo_semver.rs | 8 ++++-- tests/examples.rs | 4 +-- tests/full.rs | 34 ++++++++++++++--------- tests/full_cases/libc-0.2.28-0.2.31.linux | 2 ++ tests/full_cases/libc-0.2.28-0.2.31.osx | 2 ++ 5 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 52ace312cff40..e86a14fdedea6 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -182,11 +182,15 @@ fn run(config: &cargo::Config, matches: &getopts::Matches, explain: bool) -> Res return Err(failure::err_msg("could not pipe to rustc (wtf?)".to_owned()).into()); } - child + let exit_status = child .wait() .map_err(|e| failure::err_msg(format!("failed to wait for rustc: {}", e)))?; - Ok(()) + if exit_status.success() { + Ok(()) + } else { + Err(failure::err_msg("rustc-semverver errored".to_owned())) + } } /// CLI utils diff --git a/tests/examples.rs b/tests/examples.rs index 9dc94e8aaeed8..36a90351c3067 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -81,7 +81,7 @@ mod features { let rustsemverver_result = cmd.status().expect("could not run rust-semverver").success(); assert_eq!( rustsemverver_result, expected_result, - "rust-semverver returned an unexpected result" + "rust-semverver returned an unexpected exit status" ); { @@ -130,7 +130,7 @@ mod features { .expect("could not run git diff") .success(); - assert!(git_result, "git reports a diff"); + assert!(git_result, "git reports unexpected diff"); Command::new("rm") .args(&[&old_rlib, &new_rlib]) diff --git a/tests/full.rs b/tests/full.rs index 0df8d3dbe5381..a02ed25952225 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -6,9 +6,12 @@ mod full { process::{Command, Stdio}, }; - fn test_full(crate_name: &str, old_version: &str, new_version: &str) { - let mut success = true; - + fn test_full( + crate_name: &str, + old_version: &str, + new_version: &str, + expected_result: bool + ) { let prog = format!( r#" # wait for the actual output @@ -90,7 +93,7 @@ mod full { let old_version = format!("{}:{}", crate_name, old_version); let new_version = format!("{}:{}", crate_name, new_version); - success &= { + let cargo_semver_result = { let mut cmd = Command::new("./target/debug/cargo-semver"); cmd.args(&["-S", &old_version, "-C", &new_version]) .env("RUST_BACKTRACE", "full") @@ -105,36 +108,41 @@ mod full { cmd.status().expect("could not run cargo semver").success() }; - assert!(success, "cargo semver"); + assert_eq!( + cargo_semver_result, expected_result, + "cargo semver returned an unexpected exit status" + ); - success &= awk_child + let awk_result = awk_child .wait() .expect("could not wait for awk child") .success(); - assert!(success, "awk"); + assert!(awk_result, "awk"); - success &= Command::new("git") + let git_result = Command::new("git") .args(&["diff", "--ignore-space-at-eol", "--exit-code", out_file]) .env("PAGER", "") .status() .expect("could not run git diff") .success(); - assert!(success, "git"); + assert!(git_result, "git reports unexpected diff"); } macro_rules! full_test { - ($name:ident, $crate_name:expr, $old_version:expr, $new_version:expr) => { + ($name:ident, $crate_name:expr, + $old_version:expr, $new_version:expr, + $result:literal) => { #[test] fn $name() { - test_full($crate_name, $old_version, $new_version); + test_full($crate_name, $old_version, $new_version, $result); } }; } - full_test!(log, "log", "0.3.4", "0.3.8"); - full_test!(libc, "libc", "0.2.28", "0.2.31"); + full_test!(log, "log", "0.3.4", "0.3.8", true); + full_test!(libc, "libc", "0.2.28", "0.2.31", 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"); diff --git a/tests/full_cases/libc-0.2.28-0.2.31.linux b/tests/full_cases/libc-0.2.28-0.2.31.linux index 04597882ddd88..0bc8c77f579ec 100644 --- a/tests/full_cases/libc-0.2.28-0.2.31.linux +++ b/tests/full_cases/libc-0.2.28-0.2.31.linux @@ -867,3 +867,5 @@ note: added path (technically breaking) error: aborting due to 11 previous errors +error: rustc-semverver errored + diff --git a/tests/full_cases/libc-0.2.28-0.2.31.osx b/tests/full_cases/libc-0.2.28-0.2.31.osx index 6956991669aa3..fe2489ca816b9 100644 --- a/tests/full_cases/libc-0.2.28-0.2.31.osx +++ b/tests/full_cases/libc-0.2.28-0.2.31.osx @@ -2369,3 +2369,5 @@ note: added path (technically breaking) error: aborting due to previous error +error: rustc-semverver errored + From d6f928159ebf9b732fba2aab35f9ba681748e1c6 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Feb 2019 13:13:35 +0100 Subject: [PATCH 411/553] Formatting --- src/bin/cargo_semver.rs | 11 ++++++----- tests/examples.rs | 5 ++++- tests/full.rs | 7 +------ 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index e86a14fdedea6..01dec35dbde1b 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -11,9 +11,9 @@ use cargo::core::{Package, PackageId, PackageSet, Source, SourceId, SourceMap, W use log::debug; use std::{ env, + fs::File, io::BufReader, io::Write, - fs::File, path::{Path, PathBuf}, process::{Command, Stdio}, }; @@ -390,8 +390,10 @@ impl<'a> WorkInfo<'a> { opts.build_config.build_plan = true; // TODO: this is where we could insert feature flag builds (or using the CLI mechanisms) - env::set_var("RUSTFLAGS", - format!("-C metadata={}", if current { "new" } else { "old" })); + env::set_var( + "RUSTFLAGS", + format!("-C metadata={}", if current { "new" } else { "old" }), + ); let mut outdir = env::temp_dir(); outdir.push(&format!("cargo_semver_{}_{}", name, current)); @@ -410,8 +412,7 @@ impl<'a> WorkInfo<'a> { 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)?))?; + let build_plan: BuildPlan = serde_json::from_reader(BufReader::new(File::open(&outdir)?))?; // TODO: handle multiple outputs gracefully for i in &build_plan.invocations { diff --git a/tests/examples.rs b/tests/examples.rs index 36a90351c3067..d9911ae2887c4 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -78,7 +78,10 @@ mod features { cmd.env("RUST_SEMVER_API_GUIDELINES", "true"); } - let rustsemverver_result = cmd.status().expect("could not run rust-semverver").success(); + let rustsemverver_result = cmd + .status() + .expect("could not run rust-semverver") + .success(); assert_eq!( rustsemverver_result, expected_result, "rust-semverver returned an unexpected exit status" diff --git a/tests/full.rs b/tests/full.rs index a02ed25952225..a65e8c5a85fae 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -6,12 +6,7 @@ mod full { process::{Command, Stdio}, }; - fn test_full( - crate_name: &str, - old_version: &str, - new_version: &str, - expected_result: bool - ) { + fn test_full(crate_name: &str, old_version: &str, new_version: &str, expected_result: bool) { let prog = format!( r#" # wait for the actual output From eff2d7db61fab4b17f31d48b1c40d9390f1ae758 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Feb 2019 13:21:29 +0100 Subject: [PATCH 412/553] Fix clippy issues --- src/bin/cargo_semver.rs | 6 +++--- src/changes.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 01dec35dbde1b..c768db4ea996f 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -179,7 +179,9 @@ fn run(config: &cargo::Config, matches: &getopts::Matches, explain: bool) -> Res extern crate new;" ))?; } else { - return Err(failure::err_msg("could not pipe to rustc (wtf?)".to_owned()).into()); + return Err(failure::err_msg( + "could not pipe to rustc (wtf?)".to_owned(), + )); } let exit_status = child @@ -438,7 +440,6 @@ pub fn find_on_crates_io(crate_name: &str) -> Result { "failed to retrieve search results from the registry: {}", e )) - .into() }) .and_then(|(mut crates, _)| { crates @@ -446,7 +447,6 @@ pub fn find_on_crates_io(crate_name: &str) -> Result { .find(|krate| krate.name == crate_name) .ok_or_else(|| { failure::err_msg(format!("failed to find a matching crate `{}`", crate_name)) - .into() }) }) } diff --git a/src/changes.rs b/src/changes.rs index 92e8395471d4a..6f1b3a4fee25b 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -875,7 +875,7 @@ impl<'tcx> ChangeSet<'tcx> { pub fn trait_item_breaking(&self, old: DefId) -> bool { self.changes .get(&old) - .map_or(false, |change| change.trait_item_breaking()) + .map_or(false, Change::trait_item_breaking) } /// Format the contents of a change set for user output. From d43085349fbe8e25df3948021d0513a1cbd5516a Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Feb 2019 14:29:58 +0100 Subject: [PATCH 413/553] Fix whitespace in test file --- tests/full_cases/libc-0.2.28-0.2.31.osx | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/full_cases/libc-0.2.28-0.2.31.osx b/tests/full_cases/libc-0.2.28-0.2.31.osx index fe2489ca816b9..7cd9606a70576 100644 --- a/tests/full_cases/libc-0.2.28-0.2.31.osx +++ b/tests/full_cases/libc-0.2.28-0.2.31.osx @@ -2370,4 +2370,3 @@ note: added path (technically breaking) error: aborting due to previous error error: rustc-semverver errored - From b7e9ebd126ee25c5345b3e70e618fe9835f3b093 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Feb 2019 14:32:16 +0100 Subject: [PATCH 414/553] Add support for libraries with build.rs --- ci/run.sh | 3 +++ src/bin/cargo_semver.rs | 8 ++++++++ tests/full.rs | 8 +++++--- tests/full_cases/libc-0.2.47-0.2.48.osx | 1 + 4 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 tests/full_cases/libc-0.2.47-0.2.48.osx diff --git a/ci/run.sh b/ci/run.sh index fc50ec136174b..b8d424395290c 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -2,6 +2,9 @@ set -ex +# Note: this is required for correctness, +# otherwise executing multiple "full" tests in parallel +# of the same library can alter results. export RUST_TEST_THREADS=1 export RUST_BACKTRACE=full #export RUST_TEST_NOCAPTURE=1 diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index c768db4ea996f..c6fbf20f5534f 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -419,6 +419,14 @@ impl<'a> WorkInfo<'a> { // TODO: handle multiple outputs gracefully for i in &build_plan.invocations { if i.package_name == name { + // FIXME: this is a hack to avoid picking up output artifacts of + // build scrits and build programs (no outputs): + let build_script = + i.outputs.iter().any(|v| v.to_str().unwrap().contains("build_script")); + let build_program = i.outputs.is_empty(); + if build_script || build_program { + continue; + } return Ok((i.outputs[0].clone(), compilation.deps_output)); } } diff --git a/tests/full.rs b/tests/full.rs index a65e8c5a85fae..70180b2096a7c 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -46,7 +46,7 @@ mod full { }; let out_file: PathBuf = format!("{}.{}", out_file.display(), file_ext).into(); - assert!(out_file.exists()); + assert!(out_file.exists(), "file `{}` does not exist", out_file.display()); if let Some(path) = env::var_os("PATH") { let mut paths = env::split_paths(&path).collect::>(); @@ -94,7 +94,8 @@ mod full { .env("RUST_BACKTRACE", "full") .stdin(Stdio::null()) .stdout(out_pipe) - .stderr(err_pipe); + .stderr(err_pipe) + ; if let Ok(target) = std::env::var("TEST_TARGET") { cmd.args(&["--target", &target]); @@ -137,7 +138,8 @@ mod full { } full_test!(log, "log", "0.3.4", "0.3.8", true); - full_test!(libc, "libc", "0.2.28", "0.2.31", false); + full_test!(libc0, "libc", "0.2.28", "0.2.31", false); + full_test!(libc1, "libc", "0.2.47", "0.2.48", true); // 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"); diff --git a/tests/full_cases/libc-0.2.47-0.2.48.osx b/tests/full_cases/libc-0.2.47-0.2.48.osx new file mode 100644 index 0000000000000..0588e9104e1c2 --- /dev/null +++ b/tests/full_cases/libc-0.2.47-0.2.48.osx @@ -0,0 +1 @@ +version bump: 0.2.47 -> (patch) -> 0.2.48 From 0b3e046d76b8cf3907d9390a3d889d4fc6cd0ee8 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Feb 2019 15:38:19 +0100 Subject: [PATCH 415/553] Formatting --- tests/full.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/full.rs b/tests/full.rs index 70180b2096a7c..3a264fc004cee 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -46,7 +46,11 @@ mod full { }; let out_file: PathBuf = format!("{}.{}", out_file.display(), file_ext).into(); - assert!(out_file.exists(), "file `{}` does not exist", out_file.display()); + assert!( + out_file.exists(), + "file `{}` does not exist", + out_file.display() + ); if let Some(path) = env::var_os("PATH") { let mut paths = env::split_paths(&path).collect::>(); @@ -94,8 +98,7 @@ mod full { .env("RUST_BACKTRACE", "full") .stdin(Stdio::null()) .stdout(out_pipe) - .stderr(err_pipe) - ; + .stderr(err_pipe); if let Ok(target) = std::env::var("TEST_TARGET") { cmd.args(&["--target", &target]); From 6ee972f423e2454cef1559b4aab4c9e8c7f92aec Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Feb 2019 15:38:30 +0100 Subject: [PATCH 416/553] Properly forward a requested target --- src/bin/cargo_semver.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index c6fbf20f5534f..fd20931bc9c90 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -120,8 +120,10 @@ fn run(config: &cargo::Config, matches: &getopts::Matches, explain: bool) -> Res (work_info, stable_crate.max_version.clone()) }; - let (current_rlib, current_deps_output) = current.rlib_and_dep_output(config, &name, true)?; - let (stable_rlib, stable_deps_output) = stable.rlib_and_dep_output(config, &name, false)?; + 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)?; println!("current_rlib: {:?}", current_rlib); println!("stable_rlib: {:?}", stable_rlib); @@ -385,11 +387,17 @@ impl<'a> WorkInfo<'a> { 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") { + opts.build_config.requested_target = Some(target); + } + // TODO: this is where we could insert feature flag builds (or using the CLI mechanisms) env::set_var( @@ -421,8 +429,10 @@ impl<'a> WorkInfo<'a> { if i.package_name == name { // FIXME: this is a hack to avoid picking up output artifacts of // build scrits and build programs (no outputs): - let build_script = - i.outputs.iter().any(|v| v.to_str().unwrap().contains("build_script")); + let build_script = i + .outputs + .iter() + .any(|v| v.to_str().unwrap().contains("build_script")); let build_program = i.outputs.is_empty(); if build_script || build_program { continue; From 4ee87d5755f9b307b2cae64c6285158e964267cf Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Feb 2019 15:49:04 +0100 Subject: [PATCH 417/553] Add support for --no-default-features to cargo-semver --- src/bin/cargo_semver.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index fd20931bc9c90..289b25722edd8 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -153,6 +153,10 @@ fn run(config: &cargo::Config, matches: &getopts::Matches, explain: bool) -> Res child.args(&["--target", &target]); } + if !matches.opt_present("no-default-features") { + child.args(&["--cfg", "feature=\"default\""]); + } + let child = child .arg("-") .stdin(Stdio::piped()) @@ -215,6 +219,11 @@ mod cli { "api-guidelines", "report only changes that are breaking according to the API-guidelines", ); + opts.optflag( + "", + "no-default-features", + "Do not activate the `default` feature", + ); opts.optopt( "s", "stable-path", @@ -397,6 +406,7 @@ impl<'a> WorkInfo<'a> { if let Some(target) = matches.opt_str("target") { opts.build_config.requested_target = Some(target); } + opts.no_default_features = matches.opt_present("no-default-features"); // TODO: this is where we could insert feature flag builds (or using the CLI mechanisms) From 8bbf05b895942c35b12c0284aab133cd136301b3 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 27 Feb 2019 10:24:18 +0100 Subject: [PATCH 418/553] Filter outputs by lib target_kind --- src/bin/cargo_semver.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 289b25722edd8..71d54a388191e 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -23,6 +23,7 @@ pub type Result = cargo::util::CargoResult; #[derive(Debug, Deserialize)] struct Invocation { package_name: String, + target_kind: Vec, outputs: Vec, } @@ -436,18 +437,10 @@ impl<'a> WorkInfo<'a> { // TODO: handle multiple outputs gracefully for i in &build_plan.invocations { - if i.package_name == name { - // FIXME: this is a hack to avoid picking up output artifacts of - // build scrits and build programs (no outputs): - let build_script = i - .outputs - .iter() - .any(|v| v.to_str().unwrap().contains("build_script")); - let build_program = i.outputs.is_empty(); - if build_script || build_program { - continue; + if let Some(kind) = i.target_kind.get(0) { + if kind.contains("lib") && i.package_name == name { + return Ok((i.outputs[0].clone(), compilation.deps_output)); } - return Ok((i.outputs[0].clone(), compilation.deps_output)); } } From dcf165e1290add2fd8a9b7d13c6814d1d3ef3bff Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 1 Mar 2019 19:41:42 +0100 Subject: [PATCH 419/553] Fixed libc test setup in vcs. --- tests/full_cases/libc-0.2.28-0.2.31.linux | 1 - tests/full_cases/libc-0.2.47-0.2.48.linux | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 tests/full_cases/libc-0.2.47-0.2.48.linux diff --git a/tests/full_cases/libc-0.2.28-0.2.31.linux b/tests/full_cases/libc-0.2.28-0.2.31.linux index 0bc8c77f579ec..221b294700828 100644 --- a/tests/full_cases/libc-0.2.28-0.2.31.linux +++ b/tests/full_cases/libc-0.2.28-0.2.31.linux @@ -868,4 +868,3 @@ note: added path (technically breaking) error: aborting due to 11 previous errors error: rustc-semverver errored - diff --git a/tests/full_cases/libc-0.2.47-0.2.48.linux b/tests/full_cases/libc-0.2.47-0.2.48.linux new file mode 100644 index 0000000000000..0588e9104e1c2 --- /dev/null +++ b/tests/full_cases/libc-0.2.47-0.2.48.linux @@ -0,0 +1 @@ +version bump: 0.2.47 -> (patch) -> 0.2.48 From 0a0fad2ea6eb8d7787943ab13e6598628ef4a53d Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 1 Mar 2019 19:41:54 +0100 Subject: [PATCH 420/553] Fixed build with newest nightly. --- src/mismatch.rs | 6 +++--- src/translate.rs | 8 ++++---- src/traverse.rs | 8 ++++---- src/typeck.rs | 18 +++++++++--------- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/mismatch.rs b/src/mismatch.rs index 9d9376f08980a..20f4f805dcb79 100644 --- a/src/mismatch.rs +++ b/src/mismatch.rs @@ -11,7 +11,7 @@ use rustc::{ ty::{ self, relate::{Relate, RelateResult, TypeRelation}, - subst::Substs, + subst::SubstsRef, Ty, TyCtxt, Visibility::Public, }, @@ -71,8 +71,8 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> MismatchRelation<'a, 'gcx, 'tcx> { } } - /// Ensure that the pair of given `Substs` is suitable to be related. - fn check_substs(&self, a_substs: &'tcx Substs<'tcx>, b_substs: &'tcx Substs<'tcx>) -> bool { + /// 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::ty::subst::UnpackedKind::*; for (a, b) in a_substs.iter().zip(b_substs) { diff --git a/src/translate.rs b/src/translate.rs index 9c71518f6ca0c..a56309bc49d0f 100644 --- a/src/translate.rs +++ b/src/translate.rs @@ -8,7 +8,7 @@ use rustc::{ infer::InferCtxt, ty::{ fold::{BottomUpFolder, TypeFoldable, TypeFolder}, - subst::{Kind, Substs}, + subst::{InternalSubsts, Kind, SubstsRef}, GenericParamDefKind, ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt, }, }; @@ -101,8 +101,8 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { &self, index_map: &HashMap, orig_def_id: DefId, - orig_substs: &Substs<'tcx>, - ) -> Option<(DefId, &'tcx Substs<'tcx>)> { + orig_substs: SubstsRef<'tcx>, + ) -> Option<(DefId, SubstsRef<'tcx>)> { use rustc::ty::subst::UnpackedKind; use rustc::ty::ReEarlyBound; use std::cell::Cell; @@ -118,7 +118,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { let success = Cell::new(true); let target_substs = - Substs::for_item(self.tcx, target_def_id, |def, _| match def.kind { + InternalSubsts::for_item(self.tcx, target_def_id, |def, _| match def.kind { GenericParamDefKind::Lifetime => Kind::from(if !success.get() { self.tcx .mk_region(ReEarlyBound(def.to_early_bound_region_data())) diff --git a/src/traverse.rs b/src/traverse.rs index b49cbd962409c..cf2f5e0c8acc5 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -23,7 +23,7 @@ use rustc::{ def_id::DefId, }, ty::{ - subst::{Subst, Substs}, + subst::{InternalSubsts, Subst}, AssociatedItem, GenericParamDef, GenericParamDefKind, Generics, Ty, TyCtxt, Visibility, Visibility::Public, }, @@ -869,7 +869,7 @@ fn cmp_types<'a, 'tcx>( tcx.infer_ctxt().enter(|infcx| { let compcx = TypeComparisonContext::target_new(&infcx, id_mapping, false); - let orig_substs = Substs::identity_for_item(infcx.tcx, target_def_id); + 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); @@ -920,7 +920,7 @@ fn cmp_bounds<'a, 'tcx>( tcx.infer_ctxt().enter(|infcx| { let compcx = TypeComparisonContext::target_new(&infcx, id_mapping, true); - let orig_substs = Substs::identity_for_item(infcx.tcx, target_def_id); + 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( @@ -1120,7 +1120,7 @@ fn match_inherent_impl<'a, 'tcx>( ) }; - let orig_substs = Substs::identity_for_item(infcx.tcx, target_item_def_id); + 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)); diff --git a/src/typeck.rs b/src/typeck.rs index 3be8b44b9097b..d7a29fb95cd13 100644 --- a/src/typeck.rs +++ b/src/typeck.rs @@ -16,7 +16,7 @@ use rustc::{ ty::{ error::TypeError, fold::TypeFoldable, - subst::{Kind, Substs}, + subst::{InternalSubsts, Kind, SubstsRef}, GenericParamDefKind, ParamEnv, Predicate, TraitRef, Ty, TyCtxt, }, }; @@ -42,7 +42,7 @@ impl<'a, 'gcx, 'tcx> BoundContext<'a, 'gcx, 'tcx> { } /// Register the bounds of an item. - pub fn register(&mut self, checked_def_id: DefId, substs: &Substs<'tcx>) { + pub fn register(&mut self, checked_def_id: DefId, substs: SubstsRef<'tcx>) { use rustc::traits::{normalize, Normalized, SelectionContext}; let cause = ObligationCause::dummy(); @@ -161,12 +161,12 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { /// 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) -> &Substs<'tcx> { + pub fn compute_target_infer_substs(&self, target_def_id: DefId) -> SubstsRef<'tcx> { use syntax_pos::DUMMY_SP; let has_self = self.infcx.tcx.generics_of(target_def_id).has_self; - Substs::for_item(self.infcx.tcx, target_def_id, |def, _| { + 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) @@ -177,10 +177,10 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { } /// Construct a set of subsitutions for an item, which normalizes defaults. - pub fn compute_target_default_substs(&self, target_def_id: DefId) -> &Substs<'tcx> { + pub fn compute_target_default_substs(&self, target_def_id: DefId) -> SubstsRef<'tcx> { use rustc::ty::ReEarlyBound; - Substs::for_item(self.infcx.tcx, target_def_id, |def, _| match def.kind { + InternalSubsts::for_item(self.infcx.tcx, target_def_id, |def, _| match def.kind { GenericParamDefKind::Lifetime => Kind::from( self.infcx .tcx @@ -262,7 +262,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, orig_param_env: ParamEnv<'tcx>, target_def_id: DefId, - target_substs: &Substs<'tcx>, + target_substs: SubstsRef<'tcx>, ) -> Option>> { use rustc::ty::Lift; debug!( @@ -294,8 +294,8 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, orig_def_id: DefId, target_def_id: DefId, - orig_substs: &Substs<'tcx>, - target_substs: &Substs<'tcx>, + orig_substs: SubstsRef<'tcx>, + target_substs: SubstsRef<'tcx>, ) { use crate::changes::ChangeType::{BoundsLoosened, BoundsTightened}; From f1619fcc132fc1ebea4e7e6ae96282d7e2d3c0bf Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 1 Mar 2019 19:46:40 +0100 Subject: [PATCH 421/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4b2da0b1b78c6..b6c1a1a93d7f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.25" +version = "0.1.26" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From 5a66eb4b8a0eb2ea1a6806b404bccb57837f844c Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 17 Mar 2019 18:55:44 +0100 Subject: [PATCH 422/553] Updated test output. --- tests/cases/regions/stdout | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cases/regions/stdout b/tests/cases/regions/stdout index d012a2110e871..90c5706d23c27 100644 --- a/tests/cases/regions/stdout +++ b/tests/cases/regions/stdout @@ -37,7 +37,7 @@ error: breaking changes in `efg` 17 | pub fn efg(_: &str) { } | ^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected bound lifetime parameterBrAnon(0), found concrete lifetime (breaking) + = warning: type error: expected bound lifetime parameter, found concrete lifetime (breaking) error: breaking changes in `fgh` --> $REPO_PATH/tests/cases/regions/new.rs:19:1 @@ -45,7 +45,7 @@ error: breaking changes in `fgh` 19 | pub fn fgh(_: &'static str) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected bound lifetime parameterBrAnon(0), found concrete lifetime (breaking) + = warning: type error: expected bound lifetime parameter, found concrete lifetime (breaking) error: aborting due to 6 previous errors From 97534c5d9a6a9c9c31e7c04da8cd07d9e4f04b42 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 17 Mar 2019 18:56:18 +0100 Subject: [PATCH 423/553] Switched to the new rustc driver introduced in nightly. --- src/bin/rust_semverver.rs | 112 +++++++++++++++++++++----------------- src/mapping.rs | 1 + src/translate.rs | 3 +- src/traverse.rs | 12 ++-- src/typeck.rs | 3 +- 5 files changed, 72 insertions(+), 59 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 8a342adb8cb72..eeddf09dd9117 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -1,18 +1,20 @@ #![feature(rustc_private)] +#![feature(result_map_or_else)] extern crate getopts; extern crate rustc; extern crate rustc_codegen_utils; extern crate rustc_driver; extern crate rustc_errors; +extern crate rustc_interface; extern crate rustc_metadata; extern crate syntax; use log::debug; use rustc::{hir::def_id::*, middle::cstore::ExternCrate}; -use rustc_driver::{driver::CompileController, Compilation}; +use rustc_driver::Callbacks; +use rustc_interface::interface; use semverver::run_analysis; -use std::convert::TryInto; use std::{ path::Path, process::{exit, Command}, @@ -33,7 +35,7 @@ fn main() { debug!("running rust-semverver compiler driver"); exit( - rustc_driver::run(move || { + { use std::env; if std::env::args().any(|a| a == "--version" || a == "-V") { @@ -86,59 +88,67 @@ fn main() { .collect() }; - let verbose = std::env::var("RUST_SEMVER_VERBOSE") == Ok("true".to_string()); - let api_guidelines = std::env::var("RUST_SEMVER_API_GUIDELINES") == Ok("true".to_string()); - let version = if let Ok(ver) = std::env::var("RUST_SEMVER_CRATE_VERSION") { - ver - } else { - "no_version".to_owned() - }; - - let mut controller = CompileController::basic(); - - controller.after_analysis.callback = Box::new(move |state| { - debug!("running rust-semverver after_analysis..."); - let tcx = state.tcx.unwrap(); - - // 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 = DefId { - krate: *crate_num, - index: CRATE_DEF_INDEX, - }; - - match *tcx.extern_crate(def_id) { - Some(ExternCrate { - span, direct: true, .. - }) if span.data().lo.to_usize() > 0 => Some((span.data().lo.to_usize(), def_id)), - _ => None, + struct SemverCallbacks; + + impl Callbacks for SemverCallbacks { + fn after_analysis(&mut self, compiler: &interface::Compiler) -> bool { + debug!("running rust-semverver after_analysis callback"); + + let verbose = + std::env::var("RUST_SEMVER_VERBOSE") == Ok("true".to_string()); + let api_guidelines = + std::env::var("RUST_SEMVER_API_GUIDELINES") == Ok("true".to_string()); + let version = if let Ok(ver) = std::env::var("RUST_SEMVER_CRATE_VERSION") { + ver + } else { + "no_version".to_owned() + }; + + compiler.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 = DefId { + krate: *crate_num, + index: CRATE_DEF_INDEX, + }; + + match *tcx.extern_crate(def_id) { + Some(ExternCrate { + span, direct: true, .. + }) if span.data().lo.to_usize() > 0 => + Some((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); + changes.output(tcx.sess, &version, verbose, api_guidelines); + } else { + tcx.sess.err("could not find crate old and new crates"); } - }) - .collect(); + }); - crates.sort_by_key(|&(span_lo, _)| span_lo); + debug!("rust-semverver after_analysis callback finished!"); - 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); - changes.output(tcx.sess, &version, verbose, api_guidelines); - } else { - tcx.sess.err("could not find crate old and new crates"); + false } - - debug!("running rust-semverver after_analysis finished!"); - }); - controller.after_analysis.stop = Compilation::Stop; + } let args = args; - rustc_driver::run_compiler(&args, Box::new(controller), None, None) - }).try_into() - .expect("exit code too large"), + rustc_driver::run_compiler(&args, &mut SemverCallbacks, None, None) + } + .map_or_else(|_| 1, |_| 0), ) } diff --git a/src/mapping.rs b/src/mapping.rs index 98db3a495934a..87395268a5ee8 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -143,6 +143,7 @@ impl IdMapping { match param.kind { GenericParamDefKind::Lifetime => unreachable!(), GenericParamDefKind::Type { .. } => (), + GenericParamDefKind::Const => unreachable!(), }; self.type_params.insert(param.def_id, param.clone()); diff --git a/src/translate.rs b/src/translate.rs index a56309bc49d0f..053b1a5c1b0b3 100644 --- a/src/translate.rs +++ b/src/translate.rs @@ -149,7 +149,8 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { success.set(false); self.tcx.mk_param_from_def(def) } - } + }, + GenericParamDefKind::Const => unreachable!(), }); if success.get() { diff --git a/src/traverse.rs b/src/traverse.rs index cf2f5e0c8acc5..c23888612813e 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -24,8 +24,8 @@ use rustc::{ }, ty::{ subst::{InternalSubsts, Subst}, - AssociatedItem, GenericParamDef, GenericParamDefKind, Generics, Ty, TyCtxt, Visibility, - Visibility::Public, + AssociatedItem, DefIdTree, GenericParamDef, GenericParamDefKind, Generics, Ty, TyCtxt, + Visibility, Visibility::Public, }, }; use std::collections::{BTreeMap, HashSet, VecDeque}; @@ -1036,7 +1036,7 @@ fn diff_trait_impls<'a, 'tcx>( let old_trait_def_id = tcx.impl_trait_ref(*old_impl_def_id).unwrap().def_id; let old_impl_parent_def = tcx - .parent_def_id(*old_impl_def_id) + .parent(*old_impl_def_id) .and_then(|did| tcx.describe_def(did)); let old_impl_parent_is_fn = match old_impl_parent_def { Some(Def::Fn(_)) | Some(Def::Method(_)) => true, @@ -1050,7 +1050,7 @@ fn diff_trait_impls<'a, 'tcx>( if !match_trait_impl(tcx, &to_new, *old_impl_def_id) { changes.new_change_impl( *old_impl_def_id, - tcx.item_path_str(*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); @@ -1064,7 +1064,7 @@ fn diff_trait_impls<'a, 'tcx>( let new_trait_def_id = tcx.impl_trait_ref(*new_impl_def_id).unwrap().def_id; let new_impl_parent_def = tcx - .parent_def_id(*new_impl_def_id) + .parent(*new_impl_def_id) .and_then(|did| tcx.describe_def(did)); let new_impl_parent_is_fn = match new_impl_parent_def { Some(Def::Fn(_)) | Some(Def::Method(_)) => true, @@ -1078,7 +1078,7 @@ fn diff_trait_impls<'a, 'tcx>( if !match_trait_impl(tcx, &to_old, *new_impl_def_id) { changes.new_change_impl( *new_impl_def_id, - tcx.item_path_str(*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); diff --git a/src/typeck.rs b/src/typeck.rs index d7a29fb95cd13..1b55132dbb1bb 100644 --- a/src/typeck.rs +++ b/src/typeck.rs @@ -195,7 +195,8 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { } else { self.infcx.tcx.mk_param_from_def(def) } - } + }, + GenericParamDefKind::Const => unreachable!(), }) } From e56843410ae88a16b34a502616f2c42eeef890f6 Mon Sep 17 00:00:00 2001 From: whentze Date: Thu, 21 Mar 2019 20:20:30 +0100 Subject: [PATCH 424/553] Add `-q` flag to cargo-semver that limits output to important messsages --- src/bin/cargo_semver.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 71d54a388191e..52cd04a5f88bf 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -62,6 +62,10 @@ fn main() { return; } + if matches.opt_present("q") { + config.shell().set_verbosity(cargo::core::shell::Verbosity::Quiet); + } + if let Err(e) = cli::validate_args(&matches) { cli::exit_with_error(&config, e); } @@ -214,6 +218,7 @@ mod cli { 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("d", "debug", "print command to debug and exit"); opts.optflag( "a", @@ -293,6 +298,7 @@ mod cli { /// Exit with error `e`. pub fn exit_with_error(config: &cargo::Config, e: failure::Error) -> ! { + config.shell().set_verbosity(cargo::core::shell::Verbosity::Normal); cargo::exit_with_error(CliError::new(e, 1), &mut config.shell()); } } From f8f307aac8f258503e60043e046adad1b39815fd Mon Sep 17 00:00:00 2001 From: whentze Date: Thu, 21 Mar 2019 21:22:08 +0100 Subject: [PATCH 425/553] remove awk dependency from tests/full.rs instead of shelling out to awk, filter output using pure rust --- tests/full.rs | 156 ++++++++++++++++++++------------------------------ 1 file changed, 61 insertions(+), 95 deletions(-) diff --git a/tests/full.rs b/tests/full.rs index 3a264fc004cee..387b9a78224cb 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -1,38 +1,46 @@ mod full { + use log::{log_enabled, Level}; use std::{ env, fs::File, - path::{Path, PathBuf}, + io::{BufRead, Write}, + path::Path, process::{Command, Stdio}, }; fn test_full(crate_name: &str, old_version: &str, new_version: &str, expected_result: bool) { - let prog = format!( - r#" - # wait for the actual output - /^version bump/ {{ - doprint = 1; - }} + // Add target dir to PATH so cargo-semver will call the right rust-semverver + if let Some(path) = env::var_os("PATH") { + let mut paths = env::split_paths(&path).collect::>(); + let current_dir = env::current_dir().expect("could not determine current dir"); + paths.insert(0, current_dir.join("target/debug")); + let new_path = env::join_paths(paths).unwrap(); + env::set_var("PATH", &new_path); + } else { + eprintln!("no path!"); + } - {{ - # check the environ for filtering - if (ENVIRON["RUST_LOG"] == "debug") - doprint = 1; + 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]); + } - # skip compilation info - if (!doprint) - next; + let output = cmd.output().expect("could not run cargo semver"); - # sanitize paths - gsub(/-->.*{crate_name}/, "--> {crate_name}", $0); - print; - }}{crate_name}{crate_name}"#, - crate_name = crate_name + assert_eq!(output.status.success(), expected_result, + "cargo-semver returned unexpected exit status {}", output.status ); - let out_file = Path::new("tests/full_cases") - .join(format!("{}-{}-{}", crate_name, old_version, new_version)); - // Choose solution depending on the platform let file_ext = if cfg!(target_os = "macos") { "osx" @@ -45,82 +53,40 @@ mod full { return; }; - let out_file: PathBuf = format!("{}.{}", out_file.display(), file_ext).into(); - assert!( - out_file.exists(), - "file `{}` does not exist", - out_file.display() - ); - - if let Some(path) = env::var_os("PATH") { - let mut paths = env::split_paths(&path).collect::>(); - let current_dir = env::current_dir().expect("could not determine current dir"); - paths.insert(0, current_dir.join("target/debug")); - let new_path = env::join_paths(paths).unwrap(); - env::set_var("PATH", &new_path); - } else { - eprintln!("no path!"); + let filename = Path::new("tests/full_cases").join(format!( + "{}-{}-{}.{}", + crate_name, old_version, new_version, file_ext + )); + + assert!(filename.exists(), "file `{}` does not exist", filename.display()); + + let mut file = File::create(&filename).expect("could not create output file"); + + for line in output.stdout.lines() + .chain(output.stderr.lines()) + .map(|r| r.expect("could not read line from cargo-semver output")) + .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)) + { + // sanitize paths for reproducibility + let output = 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, + } + } + None => line, + }; + writeln!(file, "{}", output).expect("error writing to output file"); } - let stdout = File::create(&out_file).expect("could not create `stdout` file"); - let out_file = out_file.to_str().unwrap(); - - let mut awk_child = Command::new("awk") - .arg(&prog) - .stdin(Stdio::piped()) - .stdout(stdout) - .spawn() - .expect("could not run awk"); - - let (err_pipe, out_pipe) = if let Some(ref stdin) = awk_child.stdin { - #[cfg(unix)] - { - use std::os::unix::io::{AsRawFd, FromRawFd}; - let fd = stdin.as_raw_fd(); - unsafe { (Stdio::from_raw_fd(fd), Stdio::from_raw_fd(fd)) } - } - #[cfg(windows)] - { - use std::os::windows::io::{AsRawHandle, FromRawHandle}; - let fd = stdin.as_raw_handle(); - unsafe { (Stdio::from_raw_handle(fd), Stdio::from_raw_handle(fd)) } - } - } else { - panic!("could not pipe to awk"); - }; - - let old_version = format!("{}:{}", crate_name, old_version); - let new_version = format!("{}:{}", crate_name, new_version); - - let cargo_semver_result = { - let mut cmd = Command::new("./target/debug/cargo-semver"); - cmd.args(&["-S", &old_version, "-C", &new_version]) - .env("RUST_BACKTRACE", "full") - .stdin(Stdio::null()) - .stdout(out_pipe) - .stderr(err_pipe); - - if let Ok(target) = std::env::var("TEST_TARGET") { - cmd.args(&["--target", &target]); - } - - cmd.status().expect("could not run cargo semver").success() - }; - - assert_eq!( - cargo_semver_result, expected_result, - "cargo semver returned an unexpected exit status" - ); - - let awk_result = awk_child - .wait() - .expect("could not wait for awk child") - .success(); - - assert!(awk_result, "awk"); - let git_result = Command::new("git") - .args(&["diff", "--ignore-space-at-eol", "--exit-code", out_file]) + .args(&["diff", "--ignore-space-at-eol", "--exit-code", filename.to_str().unwrap()]) .env("PAGER", "") .status() .expect("could not run git diff") From 059b404b2826b7ba0363b048b18ad93bfdcaf6c7 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 17 Mar 2019 23:18:48 +0100 Subject: [PATCH 426/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b6c1a1a93d7f4..ab9755998961e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.26" +version = "0.1.27" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From 9022599783499e0237cf2ff2765107dffb34f011 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Mar 2019 10:45:22 +0100 Subject: [PATCH 427/553] Fix build --- src/mapping.rs | 3 +-- src/traverse.rs | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/mapping.rs b/src/mapping.rs index 87395268a5ee8..93fc7391a3186 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -334,9 +334,8 @@ impl NameMapping { Const(_) | ConstParam(_) | Static(_, _) | - StructCtor(_, _) | + Ctor(_, _, _) | SelfCtor(_) | - VariantCtor(_, _) | Method(_) | AssociatedConst(_) | Local(_) | diff --git a/src/traverse.rs b/src/traverse.rs index c23888612813e..7e7d73de2c2eb 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -19,7 +19,7 @@ use crate::{ use log::{debug, info}; use rustc::{ hir::{ - def::{CtorKind, Def, Export}, + def::{CtorKind, CtorOf, Def, Export}, def_id::DefId, }, ty::{ @@ -146,7 +146,8 @@ fn diff_structure<'a, 'tcx>( } } else if id_mapping.add_export(o.def, n.def) { // struct constructors are weird/hard - let's go shopping! - if let (StructCtor(_, _), StructCtor(_, _)) = (o.def, n.def) { + if let (Ctor(_, CtorOf::Struct, _), + Ctor(_, CtorOf::Struct, _)) = (o.def, n.def) { continue; } @@ -183,8 +184,8 @@ fn diff_structure<'a, 'tcx>( | (PrimTy(_), PrimTy(_)) | (TyParam(_), TyParam(_)) | (SelfTy(_, _), SelfTy(_, _)) - | (StructCtor(_, _), StructCtor(_, _)) - | (VariantCtor(_, _), VariantCtor(_, _)) + | (Ctor(_, CtorOf::Struct, _), Ctor(_, CtorOf::Struct, _)) + | (Ctor(_, CtorOf::Variant, _), Ctor(_, CtorOf::Variant, _)) | (AssociatedConst(_), AssociatedConst(_)) | (Local(_), Local(_)) | (Upvar(_, _, _), Upvar(_, _, _)) @@ -254,7 +255,7 @@ fn diff_structure<'a, 'tcx>( // only an old item is found (Some(o), None) => { // struct constructors are weird/hard - let's go shopping! - if let StructCtor(_, _) = o.def { + if let Ctor(_, CtorOf::Struct, _) = o.def { continue; } @@ -266,7 +267,7 @@ fn diff_structure<'a, 'tcx>( // only a new item is found (None, Some(n)) => { // struct constructors are weird/hard - let's go shopping! - if let StructCtor(_, _) = n.def { + if let Ctor(_, CtorOf::Struct, _) = n.def { continue; } @@ -421,7 +422,7 @@ fn diff_adts(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, o now_struct: new.ctor_kind == CtorKind::Fictive, total_private, }; - changes.add_change(c, old_def_id, Some(tcx.def_span(new.did))); + changes.add_change(c, old_def_id, Some(tcx.def_span(new.def_id))); continue; } @@ -469,14 +470,14 @@ fn diff_adts(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, o changes.add_change( ChangeType::VariantRemoved, old_def_id, - Some(tcx.def_span(old.did)), + Some(tcx.def_span(old.def_id)), ); } (None, Some(new)) => { changes.add_change( ChangeType::VariantAdded, old_def_id, - Some(tcx.def_span(new.did)), + Some(tcx.def_span(new.def_id)), ); } (None, None) => unreachable!(), From ad947141a16cc2d043924154b08e34b7306b2d09 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Mar 2019 10:45:54 +0100 Subject: [PATCH 428/553] Formatting --- src/bin/cargo_semver.rs | 14 +++++++++++--- src/translate.rs | 2 +- src/traverse.rs | 8 +++++--- src/typeck.rs | 2 +- tests/full.rs | 32 ++++++++++++++++++++++++-------- 5 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 52cd04a5f88bf..ede091eb71f4c 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -63,7 +63,9 @@ fn main() { } if matches.opt_present("q") { - config.shell().set_verbosity(cargo::core::shell::Verbosity::Quiet); + config + .shell() + .set_verbosity(cargo::core::shell::Verbosity::Quiet); } if let Err(e) = cli::validate_args(&matches) { @@ -218,7 +220,11 @@ mod cli { 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( + "q", + "quiet", + "surpress regular cargo output, print only important messages", + ); opts.optflag("d", "debug", "print command to debug and exit"); opts.optflag( "a", @@ -298,7 +304,9 @@ mod cli { /// Exit with error `e`. pub fn exit_with_error(config: &cargo::Config, e: failure::Error) -> ! { - config.shell().set_verbosity(cargo::core::shell::Verbosity::Normal); + config + .shell() + .set_verbosity(cargo::core::shell::Verbosity::Normal); cargo::exit_with_error(CliError::new(e, 1), &mut config.shell()); } } diff --git a/src/translate.rs b/src/translate.rs index 053b1a5c1b0b3..3ec7b545e6b49 100644 --- a/src/translate.rs +++ b/src/translate.rs @@ -149,7 +149,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { success.set(false); self.tcx.mk_param_from_def(def) } - }, + } GenericParamDefKind::Const => unreachable!(), }); diff --git a/src/traverse.rs b/src/traverse.rs index 7e7d73de2c2eb..73df3d84e064a 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -25,7 +25,8 @@ use rustc::{ ty::{ subst::{InternalSubsts, Subst}, AssociatedItem, DefIdTree, GenericParamDef, GenericParamDefKind, Generics, Ty, TyCtxt, - Visibility, Visibility::Public, + Visibility, + Visibility::Public, }, }; use std::collections::{BTreeMap, HashSet, VecDeque}; @@ -146,8 +147,9 @@ fn diff_structure<'a, 'tcx>( } } else if id_mapping.add_export(o.def, n.def) { // struct constructors are weird/hard - let's go shopping! - if let (Ctor(_, CtorOf::Struct, _), - Ctor(_, CtorOf::Struct, _)) = (o.def, n.def) { + if let (Ctor(_, CtorOf::Struct, _), Ctor(_, CtorOf::Struct, _)) = + (o.def, n.def) + { continue; } diff --git a/src/typeck.rs b/src/typeck.rs index 1b55132dbb1bb..fe8322f3f2882 100644 --- a/src/typeck.rs +++ b/src/typeck.rs @@ -195,7 +195,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { } else { self.infcx.tcx.mk_param_from_def(def) } - }, + } GenericParamDefKind::Const => unreachable!(), }) } diff --git a/tests/full.rs b/tests/full.rs index 387b9a78224cb..ed764747211b3 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -22,9 +22,11 @@ mod full { let mut cmd = Command::new("./target/debug/cargo-semver"); cmd.args(&[ - "-S", &format!("{}:{}", crate_name, old_version), - "-C", &format!("{}:{}", crate_name, new_version), - "-q" + "-S", + &format!("{}:{}", crate_name, old_version), + "-C", + &format!("{}:{}", crate_name, new_version), + "-q", ]) .env("RUST_BACKTRACE", "full") .stdin(Stdio::null()) @@ -37,8 +39,11 @@ mod full { let output = cmd.output().expect("could not run cargo semver"); - assert_eq!(output.status.success(), expected_result, - "cargo-semver returned unexpected exit status {}", output.status + assert_eq!( + output.status.success(), + expected_result, + "cargo-semver returned unexpected exit status {}", + output.status ); // Choose solution depending on the platform @@ -58,11 +63,17 @@ mod full { crate_name, old_version, new_version, file_ext )); - assert!(filename.exists(), "file `{}` does not exist", filename.display()); + assert!( + filename.exists(), + "file `{}` does not exist", + filename.display() + ); let mut file = File::create(&filename).expect("could not create output file"); - for line in output.stdout.lines() + for line in output + .stdout + .lines() .chain(output.stderr.lines()) .map(|r| r.expect("could not read line from cargo-semver output")) .skip_while(|line| @@ -86,7 +97,12 @@ mod full { } let git_result = Command::new("git") - .args(&["diff", "--ignore-space-at-eol", "--exit-code", filename.to_str().unwrap()]) + .args(&[ + "diff", + "--ignore-space-at-eol", + "--exit-code", + filename.to_str().unwrap(), + ]) .env("PAGER", "") .status() .expect("could not run git diff") From c35c0fa129803cb91864527e7d562c6881bf23da Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Mar 2019 10:45:43 +0100 Subject: [PATCH 429/553] Bump version to 0.1.28 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ab9755998961e..235332c3ba196 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.27" +version = "0.1.28" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From fc01b0209ee2e74b781f116262c4ebf7fdec1263 Mon Sep 17 00:00:00 2001 From: whentze Date: Thu, 28 Mar 2019 02:10:37 +0100 Subject: [PATCH 430/553] add dummy build.rs --- build.rs | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 build.rs diff --git a/build.rs b/build.rs new file mode 100644 index 0000000000000..4c9b6c19d6bc7 --- /dev/null +++ b/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"); +} From 62af748c07c029832f0f24c08debb8e6804f93c2 Mon Sep 17 00:00:00 2001 From: whentze Date: Thu, 28 Mar 2019 02:49:17 +0100 Subject: [PATCH 431/553] instead of shelling out to `git diff` in tests/full.rs, compare output from rust and, if required, write new version to $OUT DIR also, give a tip on how to view the diff --- tests/full.rs | 82 +++++++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 42 deletions(-) diff --git a/tests/full.rs b/tests/full.rs index ed764747211b3..a35e0c875c98f 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -2,7 +2,7 @@ mod full { use log::{log_enabled, Level}; use std::{ env, - fs::File, + fs::{read_to_string, File}, io::{BufRead, Write}, path::Path, process::{Command, Stdio}, @@ -39,13 +39,6 @@ mod full { let output = cmd.output().expect("could not run cargo semver"); - assert_eq!( - output.status.success(), - expected_result, - "cargo-semver returned unexpected exit status {}", - output.status - ); - // Choose solution depending on the platform let file_ext = if cfg!(target_os = "macos") { "osx" @@ -58,20 +51,17 @@ mod full { return; }; - let filename = Path::new("tests/full_cases").join(format!( + let filename = format!( "{}-{}-{}.{}", crate_name, old_version, new_version, file_ext - )); - - assert!( - filename.exists(), - "file `{}` does not exist", - filename.display() ); - let mut file = File::create(&filename).expect("could not create output file"); + let expected_path = Path::new("tests/full_cases").join(&filename); - for line in output + let expected_output = + read_to_string(&expected_path).expect("could not read expected output from file"); + + let new_output = output .stdout .lines() .chain(output.stderr.lines()) @@ -81,34 +71,42 @@ mod full { !line.starts_with("version bump") && // ...unless debugging is enabled !log_enabled!(Level::Debug)) - { - // sanitize paths for reproducibility - let output = 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, + .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, + } } - } - None => line, - }; - writeln!(file, "{}", output).expect("error writing to output file"); - } + None => line, + }) + "\n" + }) + .collect::(); - let git_result = Command::new("git") - .args(&[ - "diff", - "--ignore-space-at-eol", - "--exit-code", - filename.to_str().unwrap(), - ]) - .env("PAGER", "") - .status() - .expect("could not run git diff") - .success(); + if expected_output != new_output { + eprintln!("cargo-semver failed to produce the expected output"); - assert!(git_result, "git reports unexpected diff"); + 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(); + + eprintln!( + "For details, try this command: \n\n diff {} {}\n\n", + expected_path.display(), + new_path.display() + ); + panic!("unexpected output diff"); + } + + assert_eq!( + output.status.success(), + expected_result, + "cargo-semver returned unexpected exit status {}", + output.status + ); } macro_rules! full_test { From 2a3feede86c963b67632030817dcdd0e4551e21e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 3 Apr 2019 09:15:21 +0200 Subject: [PATCH 432/553] Fixed compiler warnings. --- src/changes.rs | 2 +- src/lib.rs | 2 ++ src/translate.rs | 4 ++-- src/traverse.rs | 2 -- src/typeck.rs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/changes.rs b/src/changes.rs index 6f1b3a4fee25b..e001107bb0388 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -969,7 +969,7 @@ pub mod tests { impl Arbitrary for DefId_ { fn arbitrary(g: &mut G) -> DefId_ { - use rustc::hir::def_id::{CrateNum, DefId, DefIndex}; + use rustc::hir::def_id::{CrateNum, DefIndex}; let a: u32 = Arbitrary::arbitrary(g); let b: u32 = Arbitrary::arbitrary(g); diff --git a/src/lib.rs b/src/lib.rs index 2ceb224f740cd..4eab9ead20750 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,8 @@ #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] +#[deny(warnings)] + extern crate rustc; extern crate syntax; extern crate syntax_pos; diff --git a/src/translate.rs b/src/translate.rs index 3ec7b545e6b49..4efd21e585adf 100644 --- a/src/translate.rs +++ b/src/translate.rs @@ -201,7 +201,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { } TyKind::Dynamic(preds, region) => { // hacky error catching mechanism - use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; + use rustc::hir::def_id::CRATE_DEF_INDEX; use std::cell::Cell; let success = Cell::new(true); @@ -364,7 +364,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { ) -> Option> { use rustc::ty::{ Binder, /*EquatePredicate,*/ OutlivesPredicate, ProjectionPredicate, ProjectionTy, - SubtypePredicate, TraitPredicate, TraitRef, + SubtypePredicate, TraitPredicate, }; Some(match predicate { diff --git a/src/traverse.rs b/src/traverse.rs index 73df3d84e064a..ad78b0d15530c 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -1025,8 +1025,6 @@ fn diff_trait_impls<'a, 'tcx>( id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, ) { - use rustc::hir::def::Def; - debug!("diffing trait impls"); let to_new = TranslationContext::target_new(tcx, id_mapping, false); diff --git a/src/typeck.rs b/src/typeck.rs index fe8322f3f2882..7ba612bdff904 100644 --- a/src/typeck.rs +++ b/src/typeck.rs @@ -69,7 +69,7 @@ impl<'a, 'gcx, 'tcx> BoundContext<'a, 'gcx, 'tcx> { /// Register the trait bound represented by a `TraitRef`. pub fn register_trait_ref(&mut self, checked_trait_ref: TraitRef<'tcx>) { - use rustc::ty::{Binder, Predicate, TraitPredicate}; + use rustc::ty::{Binder, TraitPredicate}; let predicate = Predicate::Trait(Binder::bind(TraitPredicate { trait_ref: checked_trait_ref, From e2c07b5c0230d302b86992e8f25607b86323a851 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 20 Apr 2019 00:06:41 +0200 Subject: [PATCH 433/553] Fixed build on newest nightly. --- src/mapping.rs | 13 +++++++------ src/traverse.rs | 3 ++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/mapping.rs b/src/mapping.rs index 93fc7391a3186..6a49f07f8189d 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -7,6 +7,7 @@ use rustc::{ hir::{ def::{Def, Export}, def_id::{CrateNum, DefId}, + HirId, }, ty::{AssociatedKind, GenericParamDef, GenericParamDefKind}, }; @@ -301,16 +302,16 @@ impl IdMapping { #[cfg_attr(feature = "cargo-clippy", allow(clippy::module_name_repetitions))] pub struct NameMapping { /// The exports in the type namespace. - type_map: HashMap, Option)>, + type_map: HashMap>, Option>)>, /// The exports in the value namespace. - value_map: HashMap, Option)>, + value_map: HashMap>, Option>)>, /// The exports in the macro namespace. - macro_map: HashMap, Option)>, + macro_map: HashMap>, Option>)>, } impl NameMapping { /// Insert a single export in the appropriate map, at the appropriate position. - fn insert(&mut self, item: Export, old: bool) { + fn insert(&mut self, item: Export, old: bool) { use rustc::hir::def::Def::*; let map = match item.def { @@ -356,7 +357,7 @@ impl NameMapping { } /// Add all items from two vectors of old/new exports. - pub fn add(&mut self, old_items: Vec, new_items: Vec) { + pub fn add(&mut self, old_items: Vec>, new_items: Vec>) { for item in old_items { self.insert(item, true); } @@ -367,7 +368,7 @@ impl NameMapping { } /// Drain the item pairs being stored. - pub fn drain<'a>(&'a mut self) -> impl Iterator, Option)> + 'a { + pub fn drain<'a>(&'a mut self) -> impl Iterator>, Option>)> + 'a { self.type_map .drain() .chain(self.value_map.drain()) diff --git a/src/traverse.rs b/src/traverse.rs index ad78b0d15530c..d76582d3d1ee5 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -21,6 +21,7 @@ use rustc::{ hir::{ def::{CtorKind, CtorOf, Def, Export}, def_id::DefId, + HirId, }, ty::{ subst::{InternalSubsts, Subst}, @@ -87,7 +88,7 @@ fn diff_structure<'a, 'tcx>( use rustc::hir::def::Def::*; // Get the visibility of the inner item, given the outer item's visibility. - fn get_vis(outer_vis: Visibility, def: Export) -> Visibility { + fn get_vis(outer_vis: Visibility, def: Export) -> Visibility { if outer_vis == Public { def.vis } else { From 46b2b020e5147f92d1ecf4cfd6821f74f25b0875 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 20 Apr 2019 00:07:17 +0200 Subject: [PATCH 434/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 235332c3ba196..93d73e3567813 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.28" +version = "0.1.29" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From 690ff68d440bd82b7f25d6873a9663b62262c3f3 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 20 Apr 2019 21:29:41 +0200 Subject: [PATCH 435/553] Ran rustfmt. --- src/lib.rs | 1 - src/mapping.rs | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4eab9ead20750..12c0bafd66d79 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,6 @@ #![feature(rustc_private)] #[deny(warnings)] - extern crate rustc; extern crate syntax; extern crate syntax_pos; diff --git a/src/mapping.rs b/src/mapping.rs index 6a49f07f8189d..9ff54ed4b0806 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -368,7 +368,9 @@ impl NameMapping { } /// Drain the item pairs being stored. - pub fn drain<'a>(&'a mut self) -> impl Iterator>, Option>)> + 'a { + pub fn drain<'a>( + &'a mut self, + ) -> impl Iterator>, Option>)> + 'a { self.type_map .drain() .chain(self.value_map.drain()) From bef6155cbf01bc9a74dd0fcc8ecbd2d7edf404f2 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 20 Apr 2019 22:40:04 +0200 Subject: [PATCH 436/553] Fixed a number of clippy warnings. --- src/lib.rs | 2 +- src/mapping.rs | 9 ++++++--- src/traverse.rs | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 12c0bafd66d79..da57a66bd8545 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] -#[deny(warnings)] +#![deny(warnings)] extern crate rustc; extern crate syntax; extern crate syntax_pos; diff --git a/src/mapping.rs b/src/mapping.rs index 9ff54ed4b0806..4ffcdf2722ed4 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -295,6 +295,9 @@ impl IdMapping { } } +/// An export that could be missing from one of the crate versions. +type OptionalExport = Option>; + /// A mapping from names to pairs of old and new exports. /// /// Both old and new exports can be missing. Allows for reuse of the `HashMap`s used for storage. @@ -302,11 +305,11 @@ impl IdMapping { #[cfg_attr(feature = "cargo-clippy", allow(clippy::module_name_repetitions))] pub struct NameMapping { /// The exports in the type namespace. - type_map: HashMap>, Option>)>, + type_map: HashMap, /// The exports in the value namespace. - value_map: HashMap>, Option>)>, + value_map: HashMap, /// The exports in the macro namespace. - macro_map: HashMap>, Option>)>, + macro_map: HashMap, } impl NameMapping { diff --git a/src/traverse.rs b/src/traverse.rs index d76582d3d1ee5..469dfbe48ef68 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -77,7 +77,7 @@ pub fn run_analysis<'a, 'tcx>( /// 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::cyclomatic_complexity))] +#[cfg_attr(feature = "cargo-clippy", allow(clippy::cognitive_complexity))] fn diff_structure<'a, 'tcx>( changes: &mut ChangeSet, id_mapping: &mut IdMapping, From 1bd1d37149921ffdfa6cf3468718150d8a53b3b7 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 22 Apr 2019 21:09:22 +0200 Subject: [PATCH 437/553] Appease clippy and rustfmt. --- src/bin/rust_semverver.rs | 100 +++++++++++++++++++------------------- src/lib.rs | 1 - 2 files changed, 50 insertions(+), 51 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index eeddf09dd9117..5de9b50c0a5c2 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -38,56 +38,6 @@ fn main() { { use std::env; - if std::env::args().any(|a| a == "--version" || a == "-V") { - show_version(); - exit(0); - } - - let sys_root = option_env!("SYSROOT") - .map(String::from) - .or_else(|| std::env::var("SYSROOT").ok()) - .or_else(|| { - let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); - let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); - home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain))) - }) - .or_else(|| { - Command::new("rustc") - .arg("--print") - .arg("sysroot") - .output() - .ok() - .and_then(|out| String::from_utf8(out.stdout).ok()) - .map(|s| s.trim().to_owned()) - }) - .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); - - // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. - // We're invoking the compiler programmatically, so we ignore this/ - let mut orig_args: Vec = env::args().collect(); - if orig_args.len() <= 1 { - std::process::exit(1); - } - - if Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref()) { - // we still want to be able to invoke it normally though - orig_args.remove(1); - } - - // this conditional check for the --sysroot flag is there so users can call - // `clippy_driver` directly - // without having to pass --sysroot or anything - let args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { - orig_args.clone() - } else { - orig_args - .clone() - .into_iter() - .chain(Some("--sysroot".to_owned())) - .chain(Some(sys_root)) - .collect() - }; - struct SemverCallbacks; impl Callbacks for SemverCallbacks { @@ -146,6 +96,56 @@ fn main() { } } + if std::env::args().any(|a| a == "--version" || a == "-V") { + show_version(); + exit(0); + } + + let sys_root = option_env!("SYSROOT") + .map(String::from) + .or_else(|| std::env::var("SYSROOT").ok()) + .or_else(|| { + let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); + let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); + home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain))) + }) + .or_else(|| { + Command::new("rustc") + .arg("--print") + .arg("sysroot") + .output() + .ok() + .and_then(|out| String::from_utf8(out.stdout).ok()) + .map(|s| s.trim().to_owned()) + }) + .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); + + // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. + // We're invoking the compiler programmatically, so we ignore this/ + let mut orig_args: Vec = env::args().collect(); + if orig_args.len() <= 1 { + std::process::exit(1); + } + + if Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref()) { + // we still want to be able to invoke it normally though + orig_args.remove(1); + } + + // this conditional check for the --sysroot flag is there so users can call + // `clippy_driver` directly + // without having to pass --sysroot or anything + let args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { + orig_args.clone() + } else { + orig_args + .clone() + .into_iter() + .chain(Some("--sysroot".to_owned())) + .chain(Some(sys_root)) + .collect() + }; + let args = args; rustc_driver::run_compiler(&args, &mut SemverCallbacks, None, None) } diff --git a/src/lib.rs b/src/lib.rs index da57a66bd8545..2e63e1a2c7333 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,5 @@ #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] - #![deny(warnings)] extern crate rustc; extern crate syntax; From 52e94561991ca5add0df52a12dfb3e05b38a7f63 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 22 Apr 2019 21:45:58 +0200 Subject: [PATCH 438/553] Fixed build with newest nightly. --- src/mapping.rs | 2 +- src/traverse.rs | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/mapping.rs b/src/mapping.rs index 4ffcdf2722ed4..ed78329797712 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -337,7 +337,7 @@ impl NameMapping { Fn(_) | Const(_) | ConstParam(_) | - Static(_, _) | + Static(_) | Ctor(_, _, _) | SelfCtor(_) | Method(_) | diff --git a/src/traverse.rs b/src/traverse.rs index 469dfbe48ef68..2795bacdc4fe9 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -199,7 +199,9 @@ fn diff_structure<'a, 'tcx>( | (Method(_), Method(_)) | (Err, Err) => {} // statics are subject to mutability comparison - (Static(_, old_mut), Static(_, new_mut)) => { + (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 }; @@ -810,7 +812,7 @@ fn diff_types<'a, 'tcx>( match old { // type aliases, consts and statics just need their type to be checked - TyAlias(_) | Const(_) | Static(_, _) => { + TyAlias(_) | Const(_) | Static(_) => { cmp_types( changes, id_mapping, From acd6303daf1ca8429a7c83b6e91f2782f49a03a9 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 22 Apr 2019 21:46:26 +0200 Subject: [PATCH 439/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 93d73e3567813..9183fbff1dfab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.29" +version = "0.1.30" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From f67e851879456fa1d8438a49abd69d22bf27e4fb Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 24 Apr 2019 14:25:47 +0200 Subject: [PATCH 440/553] Fixed CI script by removing useless output. --- src/bin/cargo_semver.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index ede091eb71f4c..82caf68e862b1 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -132,9 +132,6 @@ fn run(config: &cargo::Config, matches: &getopts::Matches, explain: bool) -> Res let (stable_rlib, stable_deps_output) = stable.rlib_and_dep_output(config, &name, false, matches)?; - println!("current_rlib: {:?}", current_rlib); - println!("stable_rlib: {:?}", stable_rlib); - if matches.opt_present("d") { println!( "--extern old={} -L{} --extern new={} -L{}", From 8a0aa515549b708e9a6a3e6415037207851404d9 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 16 May 2019 12:00:35 +0200 Subject: [PATCH 441/553] Partial fix for current nightlies. --- src/mapping.rs | 83 ++++++++++----------- src/mismatch.rs | 85 +++++++++++++++++----- src/translate.rs | 13 ++-- src/traverse.rs | 186 ++++++++++++++++++++++++----------------------- 4 files changed, 211 insertions(+), 156 deletions(-) diff --git a/src/mapping.rs b/src/mapping.rs index ed78329797712..fe3947e874b22 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -5,7 +5,7 @@ use rustc::{ hir::{ - def::{Def, Export}, + def::{Export, Res}, def_id::{CrateNum, DefId}, HirId, }, @@ -39,13 +39,13 @@ pub struct IdMapping { old_crate: CrateNum, /// The new crate. new_crate: CrateNum, - /// Toplevel items' old `DefId` mapped to old and new `Def`. - toplevel_mapping: HashMap, + /// Toplevel items' old `DefId` mapped to old and new `Res`. + toplevel_mapping: HashMap, /// The set of items that have been removed or added and thus have no corresponding item in /// the other crate. non_mapped_items: HashSet, - /// Trait items' old `DefId` mapped to old and new `Def`, and the enclosing trait's `DefId`. - trait_item_mapping: HashMap, + /// Trait items' old `DefId` mapped to old and new `Res`, and the enclosing trait's `DefId`. + trait_item_mapping: HashMap, /// The set of private traits in both crates. private_traits: HashSet, /// Other items' old `DefId` mapped to new `DefId`. @@ -79,7 +79,7 @@ impl IdMapping { } /// Register two exports representing the same item across versions. - pub fn add_export(&mut self, old: Def, new: Def) -> bool { + pub fn add_export(&mut self, old: Res, new: Res) -> bool { let old_def_id = old.def_id(); if !self.in_old_crate(old_def_id) || self.toplevel_mapping.contains_key(&old_def_id) { @@ -98,7 +98,7 @@ impl IdMapping { } /// Add any trait item's old and new `DefId`s. - pub fn add_trait_item(&mut self, old: Def, new: Def, old_trait: DefId) { + 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)); @@ -244,15 +244,15 @@ impl IdMapping { } /// Construct a queue of toplevel item pairs' `DefId`s. - pub fn toplevel_queue(&self) -> VecDeque<(DefId, DefId)> { + pub fn toplevel_queue(&self) -> VecDeque<(Res, Res)> { self.toplevel_mapping .values() - .map(|&(old, new)| (old.def_id(), new.def_id())) + .map(|t| *t) .collect() } /// Iterate over the toplevel and trait item pairs. - pub fn items<'a>(&'a self) -> impl Iterator + 'a { + pub fn items<'a>(&'a self) -> impl Iterator + 'a { self.toplevel_mapping .values() .cloned() @@ -315,39 +315,36 @@ pub struct NameMapping { impl NameMapping { /// Insert a single export in the appropriate map, at the appropriate position. fn insert(&mut self, item: Export, old: bool) { - use rustc::hir::def::Def::*; - - let map = match item.def { - Mod(_) | - Struct(_) | - Union(_) | - Enum(_) | - Variant(_) | - Trait(_) | - Existential(_) | - TyAlias(_) | - ForeignTy(_) | - TraitAlias(_) | // TODO: will need some handling later on. - AssociatedTy(_) | - AssociatedExistential(_) | - PrimTy(_) | - TyParam(_) | - SelfTy(_, _) | - ToolMod => Some(&mut self.type_map), - Fn(_) | - Const(_) | - ConstParam(_) | - Static(_) | - Ctor(_, _, _) | - SelfCtor(_) | - Method(_) | - AssociatedConst(_) | - Local(_) | - Upvar(_, _, _) | - Label(_) => Some(&mut self.value_map), - Macro(_, _) => Some(&mut self.macro_map), - NonMacroAttr(_) | - Err => None, + use rustc::hir::def::Res::*; + use rustc::hir::def::DefKind::*; + + let map = match item.res { + Def(kind, _) => match kind { + Mod | + Struct | + Union | + Enum | + Variant | + Trait | + Existential | + TyAlias | + ForeignTy | + TraitAlias | // TODO: will need some handling later on + AssociatedTy | + AssociatedExistential | + TyParam => Some(&mut self.type_map), + Fn | + Const | + ConstParam | + Static | + Ctor(_, _) | + Method | + AssociatedConst => Some(&mut self.value_map), + Macro(_) => Some(&mut self.macro_map), + }, + PrimTy(_) | SelfTy(_, _) => Some(&mut self.type_map), + SelfCtor(_) | Local(_) | Upvar(_, _, _) => Some(&mut self.value_map), + _ => None, }; if let Some(map) = map { diff --git a/src/mismatch.rs b/src/mismatch.rs index 20f4f805dcb79..cf2ba04ed99b5 100644 --- a/src/mismatch.rs +++ b/src/mismatch.rs @@ -7,7 +7,7 @@ use crate::mapping::IdMapping; use log::debug; use rustc::{ - hir::def_id::DefId, + hir::def::{DefKind, Res}, ty::{ self, relate::{Relate, RelateResult, TypeRelation}, @@ -28,7 +28,7 @@ pub struct MismatchRelation<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { /// The type context used. tcx: TyCtxt<'a, 'gcx, 'tcx>, /// The queue of found item pairings to be processed. - item_queue: VecDeque<(DefId, DefId)>, + 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. @@ -51,18 +51,32 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> MismatchRelation<'a, 'gcx, 'tcx> { /// Process the next pair of `DefId`s in the queue. pub fn process(&mut self) { - use rustc::hir::def::Def::*; + // use rustc::hir::def::DefKind::*; - while let Some((old_def_id, new_def_id)) = self.item_queue.pop_front() { + 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_def_id, new_def_id); - match self.tcx.describe_def(old_def_id) { - Some(Trait(_)) | Some(Macro(_, _)) => continue, - _ => (), - } + 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); @@ -147,7 +161,23 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, } } - Some((a_def.did, b_def.did)) + 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 /* if a_def.is_enum() */ { + 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 /* if b_def.is_enum() */ { + Res::Def(DefKind::Enum, b_def.did) + }; + + Some((a, b)) } else { None } @@ -174,7 +204,10 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, let _ = self.relate(a_sig.skip_binder(), b_sig.skip_binder())?; } - Some((a_def_id, b_def_id)) + 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)?; @@ -188,7 +221,9 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, 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)?; - Some((a.skip_binder().def_id, b.skip_binder().def_id)) + 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 } @@ -202,14 +237,21 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, } (&TyKind::Projection(a_data), &TyKind::Projection(b_data)) => { let _ = self.relate(&a_data, &b_data)?; - Some((a_data.item_def_id, b_data.item_def_id)) + + let a = Res::Def(DefKind::AssociatedTy, a_data.item_def_id); + let b = Res::Def(DefKind::AssociatedTy, b_data.item_def_id); + + Some((a, b)) } - (&TyKind::Opaque(a_def_id, a_substs), &TyKind::Opaque(b_def_id, b_substs)) => { + (&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)?; } - Some((a_def_id, b_def_id)) + // 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. @@ -221,12 +263,15 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, self.current_old_types.remove(a); self.current_new_types.remove(b); - if let Some((old_def_id, new_def_id)) = matching { + 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_def_id, new_def_id)); + self.item_queue.push_back((old, new)); } } @@ -241,6 +286,12 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, Ok(a) } + fn consts(&mut self, a: &'tcx ty::Const<'tcx>, _: &'tcx ty::Const<'tcx>) + -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> + { + Ok(a) // TODO + } + fn binders>( &mut self, a: &ty::Binder, diff --git a/src/translate.rs b/src/translate.rs index 4efd21e585adf..f2a384baa760c 100644 --- a/src/translate.rs +++ b/src/translate.rs @@ -170,7 +170,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { orig.fold_with(&mut BottomUpFolder { tcx: self.tcx, - fldop: |ty| { + ty_op: |ty| { match ty.sty { TyKind::Adt(&AdtDef { ref did, .. }, substs) if self.needs_translation(*did) => @@ -289,9 +289,9 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { } TyKind::Param(param) => { // FIXME: we should check `has_self` if this gets used again! - if param.idx != 0 && self.translate_params { + if param.index != 0 && self.translate_params { // `Self` is special - let orig_def_id = index_map[¶m.idx]; + let orig_def_id = index_map[¶m.index]; if self.needs_translation(orig_def_id) { use rustc::ty::subst::UnpackedKind; @@ -313,7 +313,8 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { _ => ty, } }, - reg_op: |region| self.translate_region(region), + lt_op: |region| self.translate_region(region), + ct_op: |konst| konst, // TODO: translate consts }) } @@ -546,7 +547,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceCleanupFolder<'a, 'gcx, let ty_and_mut = TypeAndMut { ty, mutbl }; self.infcx .tcx - .mk_ref(self.infcx.tcx.types.re_erased, ty_and_mut) + .mk_ref(self.infcx.tcx.lifetimes.re_erased, ty_and_mut) } TyKind::Infer(_) => self.infcx.tcx.mk_ty(TyKind::Error), _ => t1, @@ -556,7 +557,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceCleanupFolder<'a, 'gcx, fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> { let r1 = r.super_fold_with(self); if r1.needs_infer() { - self.infcx.tcx.types.re_erased + self.infcx.tcx.lifetimes.re_erased } else { r1 } diff --git a/src/traverse.rs b/src/traverse.rs index 2795bacdc4fe9..a715334e1f771 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -19,13 +19,13 @@ use crate::{ use log::{debug, info}; use rustc::{ hir::{ - def::{CtorKind, CtorOf, Def, Export}, + def::{CtorKind, CtorOf, DefKind, Export, Res, Res::Def}, def_id::DefId, HirId, }, ty::{ subst::{InternalSubsts, Subst}, - AssociatedItem, DefIdTree, GenericParamDef, GenericParamDefKind, Generics, Ty, TyCtxt, + AssociatedItem, GenericParamDef, GenericParamDefKind, Generics, Ty, TyCtxt, Visibility, Visibility::Public, }, @@ -85,7 +85,7 @@ fn diff_structure<'a, 'tcx>( old: DefId, new: DefId, ) { - use rustc::hir::def::Def::*; + use rustc::hir::def::DefKind::*; // Get the visibility of the inner item, given the outer item's visibility. fn get_vis(outer_vis: Visibility, def: Export) -> Visibility { @@ -120,7 +120,7 @@ fn diff_structure<'a, 'tcx>( match items { // an item pair is found (Some(o), Some(n)) => { - if let (Mod(o_def_id), Mod(n_def_id)) = (o.def, n.def) { + 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); @@ -146,16 +146,16 @@ fn diff_structure<'a, 'tcx>( mod_queue.push_back((o_def_id, n_def_id, o_vis, n_vis)); } - } else if id_mapping.add_export(o.def, n.def) { + } else if id_mapping.add_export(o.res, n.res) { // struct constructors are weird/hard - let's go shopping! - if let (Ctor(_, CtorOf::Struct, _), Ctor(_, CtorOf::Struct, _)) = - (o.def, n.def) + if let (Def(Ctor(CtorOf::Struct, _), _), Def(Ctor(CtorOf::Struct, _), _)) = + (o.res, n.res) { continue; } - let o_def_id = o.def.def_id(); - let n_def_id = n.def.def_id(); + 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); @@ -175,31 +175,43 @@ fn diff_structure<'a, 'tcx>( changes.add_change(ChangeType::ItemMadePublic, o_def_id, None); } - match (o.def, n.def) { + 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, AssociatedTy, PrimTy, - // TyParam, SelfTy, StructCtor, VariantCtor, AssociatedConst, Local, - // Upvar, Label, Variant, Method, Err), whose analysis is out scope - // for us (GlobalAsm, Macro), or which don't requite further analysis - // at this stage (Const) - (Mod(_), Mod(_)) - | (AssociatedTy(_), AssociatedTy(_)) - | (PrimTy(_), PrimTy(_)) - | (TyParam(_), TyParam(_)) - | (SelfTy(_, _), SelfTy(_, _)) - | (Ctor(_, CtorOf::Struct, _), Ctor(_, CtorOf::Struct, _)) - | (Ctor(_, CtorOf::Variant, _), Ctor(_, CtorOf::Variant, _)) - | (AssociatedConst(_), AssociatedConst(_)) - | (Local(_), Local(_)) - | (Upvar(_, _, _), Upvar(_, _, _)) - | (Label(_), Label(_)) - | (Macro(_, _), Macro(_, _)) - | (Variant(_), Variant(_)) - | (Const(_), Const(_)) - | (Method(_), Method(_)) - | (Err, Err) => {} + // TyParam, SelfTy, Ctor, AssociatedConst, 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) + | (AssociatedTy, AssociatedTy) + | (TyParam, TyParam) + | (Ctor(CtorOf::Struct, _), Ctor(CtorOf::Struct, _)) + | (Ctor(CtorOf::Variant, _), Ctor(CtorOf::Variant, _)) + | (AssociatedConst, AssociatedConst) + | (Variant, Variant) + | (Const, Const) + | (Method, Method) + | (Macro(_), Macro(_)) + | (TraitAlias, TraitAlias) + | (ForeignTy, ForeignTy) + | (ConstParam, ConstParam) + | (AssociatedExistential, AssociatedExistential) + | (Existential, Existential) => {} // statics are subject to mutability comparison - (Static(_), Static(_)) => { + (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 { @@ -211,25 +223,25 @@ fn diff_structure<'a, 'tcx>( } // functions can declare generics and have structural properties // that need to be compared - (Fn(_), Fn(_)) => { + (Fn, Fn) => { diff_generics(changes, id_mapping, tcx, true, o_def_id, n_def_id); - diff_fn(changes, tcx, o.def, n.def); + diff_fn(changes, tcx, o.res, n.res); } // type aliases can declare generics, too - (TyAlias(_), TyAlias(_)) => { + (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(_)) => { + (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.def, n.def); + 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(_)) => { + (Trait, Trait) => { if o_vis != Public { debug!("private trait: {:?}", o_def_id); id_mapping.add_private_trait(o_def_id); @@ -242,12 +254,6 @@ fn diff_structure<'a, 'tcx>( diff_generics(changes, id_mapping, tcx, false, o_def_id, n_def_id); traits.push((o_def_id, n_def_id, output)); - /* diff_traits(changes, - id_mapping, - tcx, - o_def_id, - n_def_id, - output); */ } // a non-matching item pair - register the change and abort further // analysis of it @@ -260,7 +266,7 @@ fn diff_structure<'a, 'tcx>( // only an old item is found (Some(o), None) => { // struct constructors are weird/hard - let's go shopping! - if let Ctor(_, CtorOf::Struct, _) = o.def { + if let Def(Ctor(CtorOf::Struct, _), _) = o.res { continue; } @@ -272,7 +278,7 @@ fn diff_structure<'a, 'tcx>( // only a new item is found (None, Some(n)) => { // struct constructors are weird/hard - let's go shopping! - if let Ctor(_, CtorOf::Struct, _) = n.def { + if let Def(Ctor(CtorOf::Struct, _), _) = n.res { continue; } @@ -289,7 +295,7 @@ fn diff_structure<'a, 'tcx>( // finally, process item additions and removals for n in additions { - let n_def_id = n.def.def_id(); + 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); @@ -300,7 +306,7 @@ fn diff_structure<'a, 'tcx>( } for o in removals { - let o_def_id = o.def.def_id(); + 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) { @@ -320,7 +326,10 @@ fn diff_structure<'a, 'tcx>( } /// Given two fn items, perform structural checks. -fn diff_fn<'a, 'tcx>(changes: &mut ChangeSet, tcx: TyCtxt<'a, 'tcx, 'tcx>, old: Def, new: Def) { +fn diff_fn<'a, 'tcx>(changes: &mut ChangeSet, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + old: Res, + new: Res) { let old_def_id = old.def_id(); let new_def_id = new.def_id(); @@ -367,8 +376,8 @@ fn diff_method<'a, 'tcx>( diff_fn( changes, tcx, - Def::Method(old.def_id), - Def::Method(new.def_id), + Def(DefKind::Method, old.def_id), + Def(DefKind::Method, new.def_id), ); } @@ -376,14 +385,19 @@ fn diff_method<'a, 'tcx>( /// /// 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: Def, new: Def) { - use rustc::hir::def::Def::*; +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) { - (Struct(_), Struct(_)) | (Union(_), Union(_)) | (Enum(_), Enum(_)) => { + (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, @@ -559,7 +573,7 @@ fn diff_traits<'a, 'tcx>( if id_mapping.is_private_trait(trait_ref.def_id) && trait_ref.substs.len() == 1 { if let Type(&TyS { - sty: TyKind::Param(ParamTy { idx: 0, .. }), + sty: TyKind::Param(ParamTy { index: 0, .. }), .. }) = trait_ref.substs[0].unpack() { @@ -573,23 +587,25 @@ fn diff_traits<'a, 'tcx>( 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 = - tcx.describe_def(*old_def_id).map(|d| (d, item)); + 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 = - tcx.describe_def(*new_def_id).map(|d| (d, item)); + 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_def, old_item)), Some((new_def, new_item))) => { - let old_def_id = old_def.def_id(); - let new_def_id = new_def.def_id(); + (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.def_kind(), old_def_id); + let new_res = Res::Def(new_item.def_kind(), new_def_id); - id_mapping.add_trait_item(old_def, new_def, old); + id_mapping.add_trait_item(old_res, new_res, old); changes.new_change( old_def_id, new_def_id, @@ -602,14 +618,14 @@ fn diff_traits<'a, 'tcx>( 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) => { + (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))) => { + (None, Some(new_item)) => { let change_type = ChangeType::TraitItemAdded { defaulted: new_item.defaultness.has_value(), sealed_trait: old_sealed, @@ -793,10 +809,10 @@ fn diff_types<'a, 'tcx>( changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, - old: Def, - new: Def, + old: Res, + new: Res, ) { - use rustc::hir::def::Def::*; + use rustc::hir::def::DefKind::*; let old_def_id = old.def_id(); let new_def_id = new.def_id(); @@ -812,7 +828,7 @@ fn diff_types<'a, 'tcx>( match old { // type aliases, consts and statics just need their type to be checked - TyAlias(_) | Const(_) | Static(_) => { + Def(TyAlias, _) | Def(Const, _) | Def(Static, _) => { cmp_types( changes, id_mapping, @@ -824,7 +840,7 @@ fn diff_types<'a, 'tcx>( ); } // functions and methods require us to compare their signatures, not types - Fn(_) | Method(_) => { + Def(Fn, _) | Def(Method, _) => { 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); @@ -839,7 +855,7 @@ fn diff_types<'a, 'tcx>( ); } // ADTs' types are compared field-wise - Struct(_) | Enum(_) | Union(_) => { + 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); @@ -850,7 +866,7 @@ fn diff_types<'a, 'tcx>( } } // a trait definition has no type, so only it's trait bounds are compared - Trait(_) => { + Def(Trait, _) => { cmp_bounds(changes, id_mapping, tcx, old_def_id, new_def_id); } _ => (), @@ -1028,6 +1044,8 @@ fn diff_trait_impls<'a, 'tcx>( id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, ) { + // use rustc::ty::TyKind; + debug!("diffing trait impls"); let to_new = TranslationContext::target_new(tcx, id_mapping, false); @@ -1037,17 +1055,11 @@ fn diff_trait_impls<'a, '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; - - let old_impl_parent_def = tcx - .parent(*old_impl_def_id) - .and_then(|did| tcx.describe_def(did)); - let old_impl_parent_is_fn = match old_impl_parent_def { - Some(Def::Fn(_)) | Some(Def::Method(_)) => true, - _ => false, - }; - if !to_new.can_translate(old_trait_def_id) || old_impl_parent_is_fn { + 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) + || tcx.visibility(*old_impl_def_id) != Public + { continue; } @@ -1067,15 +1079,9 @@ fn diff_trait_impls<'a, 'tcx>( { let new_trait_def_id = tcx.impl_trait_ref(*new_impl_def_id).unwrap().def_id; - let new_impl_parent_def = tcx - .parent(*new_impl_def_id) - .and_then(|did| tcx.describe_def(did)); - let new_impl_parent_is_fn = match new_impl_parent_def { - Some(Def::Fn(_)) | Some(Def::Method(_)) => true, - _ => false, - }; - - if !to_old.can_translate(new_trait_def_id) || new_impl_parent_is_fn { + if !to_old.can_translate(new_trait_def_id) + || tcx.visibility(*new_impl_def_id) != Public + { continue; } From 0f2637746c2a0576be15d81efbc067c3cd7887b9 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 19 May 2019 14:56:14 +0200 Subject: [PATCH 442/553] Made cargo plugin use a user agent when talking to crates.io. Fixes #103. --- Cargo.toml | 3 ++- src/bin/cargo_semver.rs | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9183fbff1dfab..47e6ed009f967 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,8 @@ path = "src/bin/rust_semverver.rs" [dependencies] cargo = "0.32" -crates-io = "0.20" +crates-io = "0.23" +curl = "0.4.21" env_logger = "0.6" failure = "0.1" log = "0.4" diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 82caf68e862b1..e4b2722a33b31 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -1,6 +1,7 @@ #![feature(rustc_private)] #![feature(set_stdio)] +extern crate curl; extern crate getopts; extern crate serde; #[macro_use] @@ -8,6 +9,7 @@ extern crate serde_derive; extern crate serde_json; use cargo::core::{Package, PackageId, PackageSet, Source, SourceId, SourceMap, Workspace}; +use curl::easy::Easy; use log::debug; use std::{ env, @@ -463,7 +465,10 @@ impl<'a> WorkInfo<'a> { /// /// If no crate with the exact name is present, error out. pub fn find_on_crates_io(crate_name: &str) -> Result { - let mut registry = crates_io::Registry::new("https://crates.io".to_owned(), None); + 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) From 4254f33b18e90639439380c921ddb5fb014ffa62 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 19 May 2019 14:57:46 +0200 Subject: [PATCH 443/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 47e6ed009f967..fb8c97b394bad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.30" +version = "0.1.31" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From b946692c05bf7078ac0e1e1273e008cc01f23c0c Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 24 May 2019 18:56:01 +0000 Subject: [PATCH 444/553] Fixed build with newest nightly. --- src/changes.rs | 2 +- tests/cases/trait_impls/stdout | 56 +--------------------------------- 2 files changed, 2 insertions(+), 56 deletions(-) diff --git a/src/changes.rs b/src/changes.rs index e001107bb0388..940ca50b6a22e 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -975,7 +975,7 @@ pub mod tests { let b: u32 = Arbitrary::arbitrary(g); DefId_(DefId { krate: CrateNum::new(a as usize), - index: DefIndex::from_raw_u32(b), + index: DefIndex::from(b), }) } } diff --git a/tests/cases/trait_impls/stdout b/tests/cases/trait_impls/stdout index 5169b41301c16..f8c2af4c949b7 100644 --- a/tests/cases/trait_impls/stdout +++ b/tests/cases/trait_impls/stdout @@ -1,55 +1 @@ -version bump: 1.0.0 -> (breaking) -> 2.0.0 -error: breaking changes in ` as old::Abc>` - --> $REPO_PATH/tests/cases/trait_impls/old.rs:9:1 - | -9 | impl Abc for Vec { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: trait impl specialized or removed (breaking) - -error: breaking changes in `` - --> $REPO_PATH/tests/cases/trait_impls/old.rs:11:1 - | -11 | / impl Clone for Def { -12 | | fn clone(&self) -> Def { -13 | | Def -14 | | } -15 | | } - | |_^ - | - = warning: trait impl specialized or removed (breaking) - -warning: technically breaking changes in ` as new::Abc>` - --> $REPO_PATH/tests/cases/trait_impls/new.rs:11:1 - | -11 | impl Abc for Box { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in ` as new::Abc>` - --> $REPO_PATH/tests/cases/trait_impls/new.rs:13:1 - | -13 | impl Abc for Box { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in `<() as new::Abc>` - --> $REPO_PATH/tests/cases/trait_impls/new.rs:15:1 - | -15 | impl Abc for () { } - | ^^^^^^^^^^^^^^^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -warning: technically breaking changes in ` as new::Abc>` - --> $REPO_PATH/tests/cases/trait_impls/new.rs:17:1 - | -17 | impl Abc for Cell<(bool, T)> { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: trait impl generalized or newly added (technically breaking) - -error: aborting due to 2 previous errors - +version bump: 1.0.0 -> (patch) -> 1.0.1 From 51d949a6b374ea03a0b5d7825177324cc99e3da4 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 24 May 2019 19:00:05 +0000 Subject: [PATCH 445/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index fb8c97b394bad..898dae5ea50c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.31" +version = "0.1.32" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From ba6ab95a80b78db824f5fc5e13976b39c61bf5a0 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 24 May 2019 19:05:05 +0000 Subject: [PATCH 446/553] Replaced erronously updated test output. --- tests/cases/trait_impls/stdout | 56 +++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/tests/cases/trait_impls/stdout b/tests/cases/trait_impls/stdout index f8c2af4c949b7..5169b41301c16 100644 --- a/tests/cases/trait_impls/stdout +++ b/tests/cases/trait_impls/stdout @@ -1 +1,55 @@ -version bump: 1.0.0 -> (patch) -> 1.0.1 +version bump: 1.0.0 -> (breaking) -> 2.0.0 +error: breaking changes in ` as old::Abc>` + --> $REPO_PATH/tests/cases/trait_impls/old.rs:9:1 + | +9 | impl Abc for Vec { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `` + --> $REPO_PATH/tests/cases/trait_impls/old.rs:11:1 + | +11 | / impl Clone for Def { +12 | | fn clone(&self) -> Def { +13 | | Def +14 | | } +15 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +warning: technically breaking changes in ` as new::Abc>` + --> $REPO_PATH/tests/cases/trait_impls/new.rs:11:1 + | +11 | impl Abc for Box { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Abc>` + --> $REPO_PATH/tests/cases/trait_impls/new.rs:13:1 + | +13 | impl Abc for Box { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `<() as new::Abc>` + --> $REPO_PATH/tests/cases/trait_impls/new.rs:15:1 + | +15 | impl Abc for () { } + | ^^^^^^^^^^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in ` as new::Abc>` + --> $REPO_PATH/tests/cases/trait_impls/new.rs:17:1 + | +17 | impl Abc for Cell<(bool, T)> { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: trait impl generalized or newly added (technically breaking) + +error: aborting due to 2 previous errors + From ec346e1245af86518bebce452e61cb5dc2a0874f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 29 May 2019 18:58:13 +0000 Subject: [PATCH 447/553] Fixed build for newest nightly. --- src/bin/rust_semverver.rs | 2 +- src/mapping.rs | 12 ++++++------ src/mismatch.rs | 4 ++-- src/traverse.rs | 28 ++++++++++++++-------------- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 5de9b50c0a5c2..831f4cf4a7b71 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -69,7 +69,7 @@ fn main() { index: CRATE_DEF_INDEX, }; - match *tcx.extern_crate(def_id) { + match tcx.extern_crate(def_id) { Some(ExternCrate { span, direct: true, .. }) if span.data().lo.to_usize() > 0 => diff --git a/src/mapping.rs b/src/mapping.rs index fe3947e874b22..0ce37dc0a9787 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -9,7 +9,7 @@ use rustc::{ def_id::{CrateNum, DefId}, HirId, }, - ty::{AssociatedKind, GenericParamDef, GenericParamDefKind}, + ty::{AssocKind, GenericParamDef, GenericParamDefKind}, }; use std::collections::{BTreeSet, HashMap, HashSet, VecDeque}; use syntax::ast::Name; @@ -20,7 +20,7 @@ pub struct InherentEntry { /// The parent item's `DefId`. pub parent_def_id: DefId, /// The kind of the item. - pub kind: AssociatedKind, + pub kind: AssocKind, /// The item's name. pub name: Name, } @@ -171,7 +171,7 @@ impl IdMapping { pub fn add_inherent_item( &mut self, parent_def_id: DefId, - kind: AssociatedKind, + kind: AssocKind, name: Name, impl_def_id: DefId, item_def_id: DefId, @@ -330,8 +330,8 @@ impl NameMapping { TyAlias | ForeignTy | TraitAlias | // TODO: will need some handling later on - AssociatedTy | - AssociatedExistential | + AssocTy | + AssocExistential | TyParam => Some(&mut self.type_map), Fn | Const | @@ -339,7 +339,7 @@ impl NameMapping { Static | Ctor(_, _) | Method | - AssociatedConst => Some(&mut self.value_map), + AssocConst => Some(&mut self.value_map), Macro(_) => Some(&mut self.macro_map), }, PrimTy(_) | SelfTy(_, _) => Some(&mut self.type_map), diff --git a/src/mismatch.rs b/src/mismatch.rs index cf2ba04ed99b5..d1ccb5048ee35 100644 --- a/src/mismatch.rs +++ b/src/mismatch.rs @@ -238,8 +238,8 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, (&TyKind::Projection(a_data), &TyKind::Projection(b_data)) => { let _ = self.relate(&a_data, &b_data)?; - let a = Res::Def(DefKind::AssociatedTy, a_data.item_def_id); - let b = Res::Def(DefKind::AssociatedTy, b_data.item_def_id); + 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)) } diff --git a/src/traverse.rs b/src/traverse.rs index a715334e1f771..e68426be46932 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -25,7 +25,7 @@ use rustc::{ }, ty::{ subst::{InternalSubsts, Subst}, - AssociatedItem, GenericParamDef, GenericParamDefKind, Generics, Ty, TyCtxt, + AssocItem, GenericParamDef, GenericParamDefKind, Generics, Ty, TyCtxt, Visibility, Visibility::Public, }, @@ -190,17 +190,17 @@ fn diff_structure<'a, 'tcx>( 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, AssociatedTy, PrimTy, - // TyParam, SelfTy, Ctor, AssociatedConst, Local, Upvar, + // 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) - | (AssociatedTy, AssociatedTy) + | (AssocTy, AssocTy) | (TyParam, TyParam) | (Ctor(CtorOf::Struct, _), Ctor(CtorOf::Struct, _)) | (Ctor(CtorOf::Variant, _), Ctor(CtorOf::Variant, _)) - | (AssociatedConst, AssociatedConst) + | (AssocConst, AssocConst) | (Variant, Variant) | (Const, Const) | (Method, Method) @@ -208,7 +208,7 @@ fn diff_structure<'a, 'tcx>( | (TraitAlias, TraitAlias) | (ForeignTy, ForeignTy) | (ConstParam, ConstParam) - | (AssociatedExistential, AssociatedExistential) + | (AssocExistential, AssocExistential) | (Existential, Existential) => {} // statics are subject to mutability comparison (Static, Static) => { @@ -351,8 +351,8 @@ fn diff_fn<'a, 'tcx>(changes: &mut ChangeSet, fn diff_method<'a, 'tcx>( changes: &mut ChangeSet, tcx: TyCtxt<'a, 'tcx, 'tcx>, - old: AssociatedItem, - new: AssociatedItem, + old: AssocItem, + new: AssocItem, ) { if old.method_has_self_argument != new.method_has_self_argument { changes.add_change( @@ -1104,10 +1104,10 @@ fn match_inherent_impl<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, orig_impl_def_id: DefId, target_impl_def_id: DefId, - orig_item: AssociatedItem, - target_item: AssociatedItem, + orig_item: AssocItem, + target_item: AssocItem, ) -> bool { - use rustc::ty::AssociatedKind; + use rustc::ty::AssocKind; debug!( "match_inherent_impl: orig_impl/item: {:?}/{:?}, target_impl/item: {:?}/{:?}", @@ -1181,12 +1181,12 @@ fn match_inherent_impl<'a, 'tcx>( // prepare the item type for comparison, as we do for toplevel items' types let (orig, target) = match (orig_item.kind, target_item.kind) { - (AssociatedKind::Const, AssociatedKind::Const) - | (AssociatedKind::Type, AssociatedKind::Type) => ( + (AssocKind::Const, AssocKind::Const) + | (AssocKind::Type, AssocKind::Type) => ( infcx.tcx.type_of(orig_item_def_id), infcx.tcx.type_of(target_item_def_id), ), - (AssociatedKind::Method, AssociatedKind::Method) => { + (AssocKind::Method, AssocKind::Method) => { 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); From 708a534fc0e66f078c0ff1fae5e1fc74005ea2b3 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 29 May 2019 18:59:12 +0000 Subject: [PATCH 448/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 898dae5ea50c7..55b924226d9ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.32" +version = "0.1.33" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From 0d7eb17bb9a804537f2e3dc93dad5dbb4b231641 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 29 May 2019 20:16:09 +0000 Subject: [PATCH 449/553] Moved away from `git-diff`-based feature tests. Akin to full tests, we now have a relatively clean rust pipeline running rust-semverver and friends, and performing all output transformations and diffing without shelling out to git and overwriting checked-out expected outputs in the process. --- tests/cases/addition/stdout | 12 +- tests/cases/addition_path/stdout | 10 +- tests/cases/addition_use/stdout | 6 +- .../cases/addition_use/stdout_api_guidelines | 2 +- tests/cases/bounds/stdout | 8 +- tests/cases/consts/stdout | 8 +- tests/cases/enums/stdout | 32 +-- tests/cases/func/stdout | 16 +- tests/cases/infer_regress/stdout | 4 +- tests/cases/inherent_impls/stdout | 12 +- tests/cases/kind_change/stdout | 2 +- tests/cases/macros/stdout | 8 +- tests/cases/mix/stdout | 14 +- tests/cases/pathologic_paths/stdout | 4 +- tests/cases/regions/stdout | 12 +- tests/cases/removal/stdout | 12 +- tests/cases/removal_path/stdout | 8 +- tests/cases/removal_use/stdout | 6 +- tests/cases/sealed_traits/stdout | 4 +- tests/cases/structs/stdout | 20 +- tests/cases/trait_impls/stdout | 12 +- tests/cases/traits/stdout | 40 ++-- tests/cases/ty_alias/stdout | 14 +- tests/examples.rs | 221 +++++++++--------- 24 files changed, 238 insertions(+), 249 deletions(-) diff --git a/tests/cases/addition/stdout b/tests/cases/addition/stdout index 5371868cfbd7c..a560292dccc36 100644 --- a/tests/cases/addition/stdout +++ b/tests/cases/addition/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (technically breaking) -> 1.1.0 warning: technically breaking changes in `Bcd` - --> $REPO_PATH/tests/cases/addition/new.rs:3:1 + --> addition/new.rs:3:1 | 3 | pub struct Bcd; | ^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ warning: technically breaking changes in `Bcd` = note: item made public (technically breaking) warning: technically breaking changes in `b` - --> $REPO_PATH/tests/cases/addition/new.rs:9:1 + --> addition/new.rs:9:1 | 9 | / pub mod b { 10 | | #[allow(dead_code)] @@ -19,7 +19,7 @@ warning: technically breaking changes in `b` = note: item made public (technically breaking) warning: technically breaking changes in `d` - --> $REPO_PATH/tests/cases/addition/new.rs:19:1 + --> addition/new.rs:19:1 | 19 | / pub mod d { 20 | | @@ -29,7 +29,7 @@ warning: technically breaking changes in `d` = note: item made public (technically breaking) warning: path changes to `Abc` - --> $REPO_PATH/tests/cases/addition/new.rs:1:1 + --> addition/new.rs:1:1 | 1 | pub struct Abc; | ^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ warning: path changes to `Abc` = note: added definition (technically breaking) warning: path changes to `a` - --> $REPO_PATH/tests/cases/addition/new.rs:5:1 + --> addition/new.rs:5:1 | 5 | / pub mod a { 6 | | @@ -47,7 +47,7 @@ warning: path changes to `a` = note: added definition (technically breaking) warning: path changes to `Cde` - --> $REPO_PATH/tests/cases/addition/new.rs:11:5 + --> addition/new.rs:11:5 | 11 | pub struct Cde; | ^^^^^^^^^^^^^^^ diff --git a/tests/cases/addition_path/stdout b/tests/cases/addition_path/stdout index e8d8730a5baed..18e595034b2e0 100644 --- a/tests/cases/addition_path/stdout +++ b/tests/cases/addition_path/stdout @@ -1,28 +1,28 @@ version bump: 1.0.0 -> (technically breaking) -> 1.1.0 warning: path changes to `Abc` - --> $REPO_PATH/tests/cases/addition_path/new.rs:2:5 + --> addition_path/new.rs:2:5 | 2 | pub struct Abc; | ^^^^^^^^^^^^^^^ | note: added path (technically breaking) - --> $REPO_PATH/tests/cases/addition_path/new.rs:6:13 + --> addition_path/new.rs:6:13 | 6 | pub use a::*; | ^^^^ note: added path (technically breaking) - --> $REPO_PATH/tests/cases/addition_path/new.rs:10:13 + --> addition_path/new.rs:10:13 | 10| pub use a::Abc; | ^^^^^^ note: added path (technically breaking) - --> $REPO_PATH/tests/cases/addition_path/new.rs:13:9 + --> addition_path/new.rs:13:9 | 13| pub use self::a::Abc; | ^^^^^^^^^^^^ warning: path changes to `d` - --> $REPO_PATH/tests/cases/addition_path/new.rs:15:1 + --> addition_path/new.rs:15:1 | 15 | / pub mod d { 16 | | diff --git a/tests/cases/addition_use/stdout b/tests/cases/addition_use/stdout index 297904f044b77..fad808614b61c 100644 --- a/tests/cases/addition_use/stdout +++ b/tests/cases/addition_use/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: breaking changes in `Def` - --> $REPO_PATH/tests/cases/addition_use/new.rs:5:1 + --> addition_use/new.rs:5:1 | 5 | / pub struct Def<'a> { 6 | | pub field1: Abc, @@ -12,7 +12,7 @@ error: breaking changes in `Def` = warning: type error: expected (), found trait new::Bcd (breaking) warning: path changes to `Abc` - --> $REPO_PATH/tests/cases/addition_use/new.rs:1:1 + --> addition_use/new.rs:1:1 | 1 | pub struct Abc; | ^^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ warning: path changes to `Abc` = note: added definition (technically breaking) warning: path changes to `Bcd` - --> $REPO_PATH/tests/cases/addition_use/new.rs:3:1 + --> addition_use/new.rs:3:1 | 3 | pub trait Bcd {} | ^^^^^^^^^^^^^^^^ diff --git a/tests/cases/addition_use/stdout_api_guidelines b/tests/cases/addition_use/stdout_api_guidelines index 744aefb460742..120e387a6f472 100644 --- a/tests/cases/addition_use/stdout_api_guidelines +++ b/tests/cases/addition_use/stdout_api_guidelines @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: breaking changes in `Def` - --> $REPO_PATH/tests/cases/addition_use/new.rs:5:1 + --> addition_use/new.rs:5:1 | 5 | / pub struct Def<'a> { 6 | | pub field1: Abc, diff --git a/tests/cases/bounds/stdout b/tests/cases/bounds/stdout index 7bf7db721bb5a..5a2d4922c3cdf 100644 --- a/tests/cases/bounds/stdout +++ b/tests/cases/bounds/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: breaking changes in `Abc` - --> $REPO_PATH/tests/cases/bounds/new.rs:1:1 + --> bounds/new.rs:1:1 | 1 | / pub struct Abc { 2 | | pub a: A, @@ -10,7 +10,7 @@ error: breaking changes in `Abc` = warning: added bound: `A: std::clone::Clone` (breaking) warning: technically breaking changes in `Def` - --> $REPO_PATH/tests/cases/bounds/new.rs:5:1 + --> bounds/new.rs:5:1 | 5 | / pub struct Def { 6 | | pub d: A, @@ -20,7 +20,7 @@ warning: technically breaking changes in `Def` = note: removed bound: `A: std::clone::Clone` (technically breaking) error: breaking changes in `abc` - --> $REPO_PATH/tests/cases/bounds/new.rs:9:1 + --> bounds/new.rs:9:1 | 9 | pub fn abc(_: A) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ error: breaking changes in `abc` = warning: added bound: `A: std::clone::Clone` (breaking) warning: technically breaking changes in `def` - --> $REPO_PATH/tests/cases/bounds/new.rs:11:1 + --> bounds/new.rs:11:1 | 11 | pub fn def(_: A) {} | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/cases/consts/stdout b/tests/cases/consts/stdout index c6473bc5168e8..59ae75aed28da 100644 --- a/tests/cases/consts/stdout +++ b/tests/cases/consts/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: breaking changes in `A` - --> $REPO_PATH/tests/cases/consts/new.rs:1:1 + --> consts/new.rs:1:1 | 1 | pub const A: u16 = 0; | ^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ error: breaking changes in `A` = warning: type error: expected u8, found u16 (breaking) error: breaking changes in `B` - --> $REPO_PATH/tests/cases/consts/new.rs:3:1 + --> consts/new.rs:3:1 | 3 | pub static B: u16 = 1; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ error: breaking changes in `B` = warning: type error: expected u8, found u16 (breaking) error: breaking changes in `D` - --> $REPO_PATH/tests/cases/consts/new.rs:7:1 + --> consts/new.rs:7:1 | 7 | pub static D: bool = true; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ error: breaking changes in `D` = warning: static item made immutable (breaking) warning: non-breaking changes in `E` - --> $REPO_PATH/tests/cases/consts/new.rs:9:1 + --> consts/new.rs:9:1 | 9 | pub static mut E: bool = true; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/cases/enums/stdout b/tests/cases/enums/stdout index 87d10b98338d1..0dfd45ab46431 100644 --- a/tests/cases/enums/stdout +++ b/tests/cases/enums/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: breaking changes in `Abc` - --> $REPO_PATH/tests/cases/enums/new.rs:1:1 + --> enums/new.rs:1:1 | 1 | / pub enum Abc { 2 | | Abc, @@ -8,13 +8,13 @@ error: breaking changes in `Abc` | |_^ | warning: enum variant added (breaking) - --> $REPO_PATH/tests/cases/enums/new.rs:2:5 + --> enums/new.rs:2:5 | 2 | Abc, | ^^^ error: breaking changes in `Bcd` - --> $REPO_PATH/tests/cases/enums/new.rs:5:1 + --> enums/new.rs:5:1 | 5 | / pub enum Bcd { 6 | | @@ -22,13 +22,13 @@ error: breaking changes in `Bcd` | |_^ | warning: enum variant removed (breaking) - --> $REPO_PATH/tests/cases/enums/old.rs:6:5 + --> enums/old.rs:6:5 | 6 | Abc, | ^^^ error: breaking changes in `Cde` - --> $REPO_PATH/tests/cases/enums/new.rs:9:1 + --> enums/new.rs:9:1 | 9 | / pub enum Cde { 10 | | Abc, @@ -37,13 +37,13 @@ error: breaking changes in `Cde` | |_^ | warning: enum variant added (breaking) - --> $REPO_PATH/tests/cases/enums/new.rs:11:5 + --> enums/new.rs:11:5 | 11 | Bcd, | ^^^ error: breaking changes in `Def` - --> $REPO_PATH/tests/cases/enums/new.rs:14:1 + --> enums/new.rs:14:1 | 14 | / pub enum Def { 15 | | Abc, @@ -51,13 +51,13 @@ error: breaking changes in `Def` | |_^ | warning: enum variant removed (breaking) - --> $REPO_PATH/tests/cases/enums/old.rs:15:5 + --> enums/old.rs:15:5 | 15 | Bcd, | ^^^ error: breaking changes in `Efg` - --> $REPO_PATH/tests/cases/enums/new.rs:18:1 + --> enums/new.rs:18:1 | 18 | / pub enum Efg { 19 | | Abc(u8), @@ -69,37 +69,37 @@ error: breaking changes in `Efg` | |_^ | warning: variant with no public fields changed to a tuple variant (breaking) - --> $REPO_PATH/tests/cases/enums/new.rs:19:5 + --> enums/new.rs:19:5 | 19 | Abc(u8), | ^^^^^^^ warning: variant with no public fields changed to a tuple variant (breaking) - --> $REPO_PATH/tests/cases/enums/new.rs:20:5 + --> enums/new.rs:20:5 | 20 | Bcd, | ^^^ warning: variant with no public fields changed to a struct variant (breaking) - --> $REPO_PATH/tests/cases/enums/new.rs:21:5 + --> enums/new.rs:21:5 | 21 | Cde { f: u8 }, | ^^^^^^^^^^^^^ warning: variant with no public fields changed to a tuple variant (breaking) - --> $REPO_PATH/tests/cases/enums/new.rs:22:5 + --> enums/new.rs:22:5 | 22 | Def, | ^^^ warning: variant with no public fields changed to a struct variant (breaking) - --> $REPO_PATH/tests/cases/enums/new.rs:23:5 + --> enums/new.rs:23:5 | 23 | Efg { f: u8 }, | ^^^^^^^^^^^^^ warning: variant field removed from variant with private fields (breaking) - --> $REPO_PATH/tests/cases/enums/old.rs:25:11 + --> enums/old.rs:25:11 | 25 | Ghi { f: u8 }, | ^^^^^ warning: variant field added to variant with private fields (breaking) - --> $REPO_PATH/tests/cases/enums/new.rs:25:11 + --> enums/new.rs:25:11 | 25 | Ghi { g: u8 }, | ^^^^^ diff --git a/tests/cases/func/stdout b/tests/cases/func/stdout index 282e8f15e85af..3bddfc0093c35 100644 --- a/tests/cases/func/stdout +++ b/tests/cases/func/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: breaking changes in `bcd` - --> $REPO_PATH/tests/cases/func/new.rs:4:1 + --> func/new.rs:4:1 | 4 | pub fn bcd(_: u8) {} | ^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ error: breaking changes in `bcd` = warning: type error: incorrect number of function parameters (breaking) error: breaking changes in `cde` - --> $REPO_PATH/tests/cases/func/new.rs:6:1 + --> func/new.rs:6:1 | 6 | / pub fn cde() -> u16 { 7 | | 0xcde @@ -18,7 +18,7 @@ error: breaking changes in `cde` = warning: type error: expected (), found u16 (breaking) error: breaking changes in `def` - --> $REPO_PATH/tests/cases/func/new.rs:10:1 + --> func/new.rs:10:1 | 10 | pub fn def() {} | ^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ error: breaking changes in `def` = warning: type error: incorrect number of function parameters (breaking) warning: non-breaking changes in `efg` - --> $REPO_PATH/tests/cases/func/new.rs:12:1 + --> func/new.rs:12:1 | 12 | / pub fn efg(a: A, _: A) -> A { 13 | | a @@ -36,7 +36,7 @@ warning: non-breaking changes in `efg` = note: defaulted type parameter added (non-breaking) error: breaking changes in `fgh` - --> $REPO_PATH/tests/cases/func/new.rs:16:1 + --> func/new.rs:16:1 | 16 | / pub fn fgh(a: u8, _: u16) -> u8 { 17 | | a @@ -46,7 +46,7 @@ error: breaking changes in `fgh` = warning: type error: expected u8, found u16 (breaking) error: breaking changes in `ghi` - --> $REPO_PATH/tests/cases/func/new.rs:20:1 + --> func/new.rs:20:1 | 20 | / pub fn ghi(a: u8, _: u8) -> u16 { 21 | | a as u16 @@ -56,7 +56,7 @@ error: breaking changes in `ghi` = warning: type error: expected u8, found u16 (breaking) warning: non-breaking changes in `hij` - --> $REPO_PATH/tests/cases/func/new.rs:24:1 + --> func/new.rs:24:1 | 24 | / pub const fn hij() -> u8 { 25 | | 0 @@ -66,7 +66,7 @@ warning: non-breaking changes in `hij` = note: fn item made const (non-breaking) error: breaking changes in `ijk` - --> $REPO_PATH/tests/cases/func/new.rs:28:1 + --> func/new.rs:28:1 | 28 | / pub fn ijk() -> u8 { 29 | | 0 diff --git a/tests/cases/infer_regress/stdout b/tests/cases/infer_regress/stdout index eab24a7480d36..8c629f58474ba 100644 --- a/tests/cases/infer_regress/stdout +++ b/tests/cases/infer_regress/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: breaking changes in `abc` - --> $REPO_PATH/tests/cases/infer_regress/new.rs:1:1 + --> infer_regress/new.rs:1:1 | 1 | pub fn abc(_: A) { } | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ error: breaking changes in `abc` = warning: type error: expected type parameter, found () (breaking) error: breaking changes in `Abc` - --> $REPO_PATH/tests/cases/infer_regress/new.rs:3:1 + --> infer_regress/new.rs:3:1 | 3 | pub struct Abc(pub A, pub ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/cases/inherent_impls/stdout b/tests/cases/inherent_impls/stdout index 2f1ef38d71c40..ff6a2f58140cb 100644 --- a/tests/cases/inherent_impls/stdout +++ b/tests/cases/inherent_impls/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: breaking changes in `ghi` - --> $REPO_PATH/tests/cases/inherent_impls/old.rs:14:5 + --> inherent_impls/old.rs:14:5 | 14 | / pub fn ghi(&self, a: A) -> A { 15 | | a @@ -10,7 +10,7 @@ error: breaking changes in `ghi` = warning: type error: expected type parameter, found u8 (breaking) error: breaking changes in `def` - --> $REPO_PATH/tests/cases/inherent_impls/old.rs:26:5 + --> inherent_impls/old.rs:26:5 | 26 | / pub fn def(&self) -> u8 { 27 | | 0 @@ -20,7 +20,7 @@ error: breaking changes in `def` = warning: removed item in inherent impl (breaking) error: breaking changes in `def` - --> $REPO_PATH/tests/cases/inherent_impls/old.rs:33:5 + --> inherent_impls/old.rs:33:5 | 33 | / pub fn def(&self) -> u8 { 34 | | 0 @@ -30,7 +30,7 @@ error: breaking changes in `def` = warning: type error: expected u8, found u16 (breaking) error: breaking changes in `ghi` - --> $REPO_PATH/tests/cases/inherent_impls/old.rs:37:5 + --> inherent_impls/old.rs:37:5 | 37 | pub fn ghi() { } | ^^^^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ error: breaking changes in `ghi` = warning: removed item in inherent impl (breaking) warning: technically breaking changes in `abc` - --> $REPO_PATH/tests/cases/inherent_impls/new.rs:30:5 + --> inherent_impls/new.rs:30:5 | 30 | pub fn abc() { } | ^^^^^^^^^^^^^^^^ @@ -46,7 +46,7 @@ warning: technically breaking changes in `abc` = note: added item in inherent impl (technically breaking) warning: technically breaking changes in `def` - --> $REPO_PATH/tests/cases/inherent_impls/new.rs:37:5 + --> inherent_impls/new.rs:37:5 | 37 | / pub fn def(&self) -> u8 { 38 | | 0 diff --git a/tests/cases/kind_change/stdout b/tests/cases/kind_change/stdout index f744fe3ccf44e..f8d9d0dd81207 100644 --- a/tests/cases/kind_change/stdout +++ b/tests/cases/kind_change/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: breaking changes in `Abc` - --> $REPO_PATH/tests/cases/kind_change/new.rs:1:1 + --> kind_change/new.rs:1:1 | 1 | / pub enum Abc { 2 | | diff --git a/tests/cases/macros/stdout b/tests/cases/macros/stdout index da768f9909b37..4112572826ecb 100644 --- a/tests/cases/macros/stdout +++ b/tests/cases/macros/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: path changes to `qux1` - --> $REPO_PATH/tests/cases/macros/old.rs:15:1 + --> macros/old.rs:15:1 | 15 | pub macro qux1() { Item } | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ error: path changes to `qux1` = warning: removed definition (breaking) error: path changes to `qux2` - --> $REPO_PATH/tests/cases/macros/old.rs:18:1 + --> macros/old.rs:18:1 | 18 | / macro_rules! qux2 { 19 | | () => { @@ -20,7 +20,7 @@ error: path changes to `qux2` = warning: removed definition (breaking) warning: path changes to `quux1` - --> $REPO_PATH/tests/cases/macros/new.rs:15:1 + --> macros/new.rs:15:1 | 15 | pub macro quux1() { Item } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ warning: path changes to `quux1` = note: added definition (technically breaking) warning: path changes to `quux2` - --> $REPO_PATH/tests/cases/macros/new.rs:18:1 + --> macros/new.rs:18:1 | 18 | / macro_rules! quux2 { 19 | | () => { diff --git a/tests/cases/mix/stdout b/tests/cases/mix/stdout index 9ba0b514a8cfd..38fcc5e565209 100644 --- a/tests/cases/mix/stdout +++ b/tests/cases/mix/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: breaking changes in `Abc` - --> $REPO_PATH/tests/cases/mix/new.rs:2:5 + --> mix/new.rs:2:5 | 2 | pub enum Abc {} | ^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ error: breaking changes in `Abc` = warning: item kind changed (breaking) error: breaking changes in `Def` - --> $REPO_PATH/tests/cases/mix/new.rs:3:5 + --> mix/new.rs:3:5 | 3 | pub struct Def; | ^^^^^^^^^^^^^^^ @@ -16,30 +16,30 @@ error: breaking changes in `Def` = warning: item kind changed (breaking) error: path changes to `Abc` - --> $REPO_PATH/tests/cases/mix/new.rs:2:5 + --> mix/new.rs:2:5 | 2 | pub enum Abc {} | ^^^^^^^^^^^^^^^ | warning: removed path (breaking) - --> $REPO_PATH/tests/cases/mix/old.rs:10:9 + --> mix/old.rs:10:9 | 10| pub use self::a::Abc; | ^^^^^^^^^^^^ note: added path (technically breaking) - --> $REPO_PATH/tests/cases/mix/new.rs:7:13 + --> mix/new.rs:7:13 | 7 | pub use a::Abc; | ^^^^^^ warning: path changes to `Def` - --> $REPO_PATH/tests/cases/mix/new.rs:3:5 + --> mix/new.rs:3:5 | 3 | pub struct Def; | ^^^^^^^^^^^^^^^ | note: added path (technically breaking) - --> $REPO_PATH/tests/cases/mix/new.rs:10:9 + --> mix/new.rs:10:9 | 10| pub use self::a::Def; | ^^^^^^^^^^^^ diff --git a/tests/cases/pathologic_paths/stdout b/tests/cases/pathologic_paths/stdout index 2e4d2db681784..9f8702d0d2557 100644 --- a/tests/cases/pathologic_paths/stdout +++ b/tests/cases/pathologic_paths/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (technically breaking) -> 1.1.0 warning: path changes to `a` - --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:5:9 + --> pathologic_paths/new.rs:5:9 | 5 | pub mod a { blow!($($rest)*); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ warning: path changes to `a` = note: added definition (technically breaking) warning: path changes to `b` - --> $REPO_PATH/tests/cases/pathologic_paths/new.rs:6:9 + --> pathologic_paths/new.rs:6:9 | 6 | pub mod b { pub use super::a::*; } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/cases/regions/stdout b/tests/cases/regions/stdout index 90c5706d23c27..668dc986f8914 100644 --- a/tests/cases/regions/stdout +++ b/tests/cases/regions/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: breaking changes in `D` - --> $REPO_PATH/tests/cases/regions/new.rs:9:1 + --> regions/new.rs:9:1 | 9 | pub type D = ::IntoIter; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ error: breaking changes in `D` = warning: type error: expected std::iter::IntoIterator::Item, found std::iter::IntoIterator::IntoIter (breaking) error: breaking changes in `E` - --> $REPO_PATH/tests/cases/regions/new.rs:11:1 + --> regions/new.rs:11:1 | 11 | pub type E = T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ error: breaking changes in `E` = warning: type error: expected associated type, found type parameter (breaking) error: breaking changes in `abc` - --> $REPO_PATH/tests/cases/regions/new.rs:13:1 + --> regions/new.rs:13:1 | 13 | pub fn abc(_: &bool) { } | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ error: breaking changes in `abc` = warning: type error: expected bool, found reference (breaking) error: breaking changes in `def` - --> $REPO_PATH/tests/cases/regions/new.rs:15:1 + --> regions/new.rs:15:1 | 15 | pub fn def(_: bool) { } | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ error: breaking changes in `def` = warning: type error: expected reference, found bool (breaking) error: breaking changes in `efg` - --> $REPO_PATH/tests/cases/regions/new.rs:17:1 + --> regions/new.rs:17:1 | 17 | pub fn efg(_: &str) { } | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ error: breaking changes in `efg` = warning: type error: expected bound lifetime parameter, found concrete lifetime (breaking) error: breaking changes in `fgh` - --> $REPO_PATH/tests/cases/regions/new.rs:19:1 + --> regions/new.rs:19:1 | 19 | pub fn fgh(_: &'static str) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/cases/removal/stdout b/tests/cases/removal/stdout index 25c647e52be0f..187fe489cb402 100644 --- a/tests/cases/removal/stdout +++ b/tests/cases/removal/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: path changes to `Abc` - --> $REPO_PATH/tests/cases/removal/old.rs:1:1 + --> removal/old.rs:1:1 | 1 | pub struct Abc; | ^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ error: path changes to `Abc` = warning: removed definition (breaking) error: breaking changes in `Bcd` - --> $REPO_PATH/tests/cases/removal/new.rs:2:1 + --> removal/new.rs:2:1 | 2 | struct Bcd; | ^^^^^^^^^^^ @@ -16,7 +16,7 @@ error: breaking changes in `Bcd` = warning: item made private (breaking) error: path changes to `a` - --> $REPO_PATH/tests/cases/removal/old.rs:5:1 + --> removal/old.rs:5:1 | 5 | / pub mod a { 6 | | @@ -26,7 +26,7 @@ error: path changes to `a` = warning: removed definition (breaking) error: breaking changes in `b` - --> $REPO_PATH/tests/cases/removal/new.rs:4:1 + --> removal/new.rs:4:1 | 4 | / mod b { 5 | | @@ -36,7 +36,7 @@ error: breaking changes in `b` = warning: item made private (breaking) error: path changes to `Cde` - --> $REPO_PATH/tests/cases/removal/old.rs:11:5 + --> removal/old.rs:11:5 | 11 | pub struct Cde; | ^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ error: path changes to `Cde` = warning: removed definition (breaking) error: breaking changes in `d` - --> $REPO_PATH/tests/cases/removal/new.rs:12:1 + --> removal/new.rs:12:1 | 12 | / mod d { 13 | | diff --git a/tests/cases/removal_path/stdout b/tests/cases/removal_path/stdout index e404c4c92ac01..ea1d1711caf30 100644 --- a/tests/cases/removal_path/stdout +++ b/tests/cases/removal_path/stdout @@ -1,22 +1,22 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: path changes to `Abc` - --> $REPO_PATH/tests/cases/removal_path/new.rs:2:5 + --> removal_path/new.rs:2:5 | 2 | pub struct Abc; | ^^^^^^^^^^^^^^^ | warning: removed path (breaking) - --> $REPO_PATH/tests/cases/removal_path/old.rs:6:13 + --> removal_path/old.rs:6:13 | 6 | pub use a::*; | ^^^^ warning: removed path (breaking) - --> $REPO_PATH/tests/cases/removal_path/old.rs:10:13 + --> removal_path/old.rs:10:13 | 10| pub use a::Abc; | ^^^^^^ warning: removed path (breaking) - --> $REPO_PATH/tests/cases/removal_path/old.rs:13:9 + --> removal_path/old.rs:13:9 | 13| pub use self::a::Abc; | ^^^^^^^^^^^^ diff --git a/tests/cases/removal_use/stdout b/tests/cases/removal_use/stdout index 5d72bb3749f03..2d245d7c28b37 100644 --- a/tests/cases/removal_use/stdout +++ b/tests/cases/removal_use/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: path changes to `Abc` - --> $REPO_PATH/tests/cases/removal_use/old.rs:1:1 + --> removal_use/old.rs:1:1 | 1 | pub struct Abc; | ^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ error: path changes to `Abc` = warning: removed definition (breaking) error: path changes to `Bcd` - --> $REPO_PATH/tests/cases/removal_use/old.rs:3:1 + --> removal_use/old.rs:3:1 | 3 | pub trait Bcd {} | ^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ error: path changes to `Bcd` = warning: removed definition (breaking) error: breaking changes in `Def` - --> $REPO_PATH/tests/cases/removal_use/new.rs:1:1 + --> removal_use/new.rs:1:1 | 1 | / pub struct Def<'a> { 2 | | pub field1: (), diff --git a/tests/cases/sealed_traits/stdout b/tests/cases/sealed_traits/stdout index 87b33459f55a5..d0f32d42a8b6d 100644 --- a/tests/cases/sealed_traits/stdout +++ b/tests/cases/sealed_traits/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (technically breaking) -> 1.1.0 warning: technically breaking changes in `PublicTrait` - --> $REPO_PATH/tests/cases/sealed_traits/new.rs:1:1 + --> sealed_traits/new.rs:1:1 | 1 | / pub trait PublicTrait : private::PrivateTrait { 2 | | fn abc(&self) -> bool; @@ -8,7 +8,7 @@ warning: technically breaking changes in `PublicTrait` | |_^ | note: added item to sealed trait (technically breaking) - --> $REPO_PATH/tests/cases/sealed_traits/new.rs:2:5 + --> sealed_traits/new.rs:2:5 | 2 | fn abc(&self) -> bool; | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/cases/structs/stdout b/tests/cases/structs/stdout index 32025a98d4273..7a5e019ceabbc 100644 --- a/tests/cases/structs/stdout +++ b/tests/cases/structs/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 warning: technically breaking changes in `Def` - --> $REPO_PATH/tests/cases/structs/new.rs:6:1 + --> structs/new.rs:6:1 | 6 | / pub struct Def { 7 | | pub field: A, @@ -9,13 +9,13 @@ warning: technically breaking changes in `Def` | = note: defaulted type parameter added (non-breaking) note: item made public (technically breaking) - --> $REPO_PATH/tests/cases/structs/new.rs:7:5 + --> structs/new.rs:7:5 | 7 | pub field: A, | ^^^^^^^^^^^^ error: breaking changes in `Def2` - --> $REPO_PATH/tests/cases/structs/new.rs:10:1 + --> structs/new.rs:10:1 | 10 | / pub struct Def2 { 11 | | pub field: A, @@ -26,7 +26,7 @@ error: breaking changes in `Def2` = warning: type error: expected u8, found u16 (breaking) error: breaking changes in `Efg` - --> $REPO_PATH/tests/cases/structs/new.rs:14:1 + --> structs/new.rs:14:1 | 14 | / pub struct Efg { 15 | | pub field: u16, @@ -36,7 +36,7 @@ error: breaking changes in `Efg` = warning: type error: expected u8, found u16 (breaking) warning: technically breaking changes in `Fgh` - --> $REPO_PATH/tests/cases/structs/new.rs:18:1 + --> structs/new.rs:18:1 | 18 | / pub struct Fgh { 19 | | pub field: u8, @@ -44,13 +44,13 @@ warning: technically breaking changes in `Fgh` | |_^ | note: item made public (technically breaking) - --> $REPO_PATH/tests/cases/structs/new.rs:19:5 + --> structs/new.rs:19:5 | 19 | pub field: u8, | ^^^^^^^^^^^^^ error: breaking changes in `Ghi` - --> $REPO_PATH/tests/cases/structs/new.rs:22:1 + --> structs/new.rs:22:1 | 22 | / pub struct Ghi { 23 | | field: u8, @@ -58,13 +58,13 @@ error: breaking changes in `Ghi` | |_^ | warning: item made private (breaking) - --> $REPO_PATH/tests/cases/structs/new.rs:23:5 + --> structs/new.rs:23:5 | 23 | field: u8, | ^^^^^^^^^ error: breaking changes in `Hij` - --> $REPO_PATH/tests/cases/structs/new.rs:26:1 + --> structs/new.rs:26:1 | 26 | / pub struct Hij { 27 | | field: u8, @@ -72,7 +72,7 @@ error: breaking changes in `Hij` | |_^ | warning: variant with no public fields changed to a struct variant (breaking) - --> $REPO_PATH/tests/cases/structs/new.rs:26:1 + --> structs/new.rs:26:1 | 26 | / pub struct Hij { 27 | | field: u8, diff --git a/tests/cases/trait_impls/stdout b/tests/cases/trait_impls/stdout index 5169b41301c16..976c04c9f62b1 100644 --- a/tests/cases/trait_impls/stdout +++ b/tests/cases/trait_impls/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: breaking changes in ` as old::Abc>` - --> $REPO_PATH/tests/cases/trait_impls/old.rs:9:1 + --> trait_impls/old.rs:9:1 | 9 | impl Abc for Vec { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ error: breaking changes in ` as old::Abc>` = warning: trait impl specialized or removed (breaking) error: breaking changes in `` - --> $REPO_PATH/tests/cases/trait_impls/old.rs:11:1 + --> trait_impls/old.rs:11:1 | 11 | / impl Clone for Def { 12 | | fn clone(&self) -> Def { @@ -20,7 +20,7 @@ error: breaking changes in `` = warning: trait impl specialized or removed (breaking) warning: technically breaking changes in ` as new::Abc>` - --> $REPO_PATH/tests/cases/trait_impls/new.rs:11:1 + --> trait_impls/new.rs:11:1 | 11 | impl Abc for Box { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ warning: technically breaking changes in ` as new::Abc>` = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in ` as new::Abc>` - --> $REPO_PATH/tests/cases/trait_impls/new.rs:13:1 + --> trait_impls/new.rs:13:1 | 13 | impl Abc for Box { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ warning: technically breaking changes in ` as new::Abc = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in `<() as new::Abc>` - --> $REPO_PATH/tests/cases/trait_impls/new.rs:15:1 + --> trait_impls/new.rs:15:1 | 15 | impl Abc for () { } | ^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ warning: technically breaking changes in `<() as new::Abc>` = note: trait impl generalized or newly added (technically breaking) warning: technically breaking changes in ` as new::Abc>` - --> $REPO_PATH/tests/cases/trait_impls/new.rs:17:1 + --> trait_impls/new.rs:17:1 | 17 | impl Abc for Cell<(bool, T)> { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/cases/traits/stdout b/tests/cases/traits/stdout index a3f2a4e292452..451336c654763 100644 --- a/tests/cases/traits/stdout +++ b/tests/cases/traits/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: breaking changes in `Abc` - --> $REPO_PATH/tests/cases/traits/new.rs:1:1 + --> traits/new.rs:1:1 | 1 | / pub trait Abc { 2 | | type A; @@ -12,24 +12,24 @@ error: breaking changes in `Abc` | |_^ | warning: removed item from trait (breaking) - --> $REPO_PATH/tests/cases/traits/old.rs:4:5 + --> traits/old.rs:4:5 | 4 | fn test2(&self) -> u8; | ^^^^^^^^^^^^^^^^^^^^^^ warning: removed defaulted item from trait (breaking) - --> $REPO_PATH/tests/cases/traits/old.rs:8:5 + --> traits/old.rs:8:5 | 8 | / fn test5() -> u8 { 9 | | 0 10 | | } | |_____^ warning: added item to trait (breaking) - --> $REPO_PATH/tests/cases/traits/new.rs:4:5 + --> traits/new.rs:4:5 | 4 | fn test3(&self) -> u8; | ^^^^^^^^^^^^^^^^^^^^^^ note: added defaulted item to trait (technically breaking) - --> $REPO_PATH/tests/cases/traits/new.rs:8:5 + --> traits/new.rs:8:5 | 8 | / fn test6() -> u8 { 9 | | 0 @@ -37,7 +37,7 @@ note: added defaulted item to trait (technically breaking) | |_____^ error: breaking changes in `test7` - --> $REPO_PATH/tests/cases/traits/new.rs:11:5 + --> traits/new.rs:11:5 | 11 | fn test7() -> u16; | ^^^^^^^^^^^^^^^^^^ @@ -45,7 +45,7 @@ error: breaking changes in `test7` = warning: type error: expected u8, found u16 (breaking) error: breaking changes in `test8` - --> $REPO_PATH/tests/cases/traits/new.rs:12:5 + --> traits/new.rs:12:5 | 12 | fn test8(_: &Self) -> u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -53,7 +53,7 @@ error: breaking changes in `test8` = warning: removed self-argument from method (breaking) warning: technically breaking changes in `test9` - --> $REPO_PATH/tests/cases/traits/new.rs:13:5 + --> traits/new.rs:13:5 | 13 | fn test9(&self) -> u8; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ warning: technically breaking changes in `test9` = note: added self-argument to method (technically breaking) error: breaking changes in `Bcd` - --> $REPO_PATH/tests/cases/traits/new.rs:16:1 + --> traits/new.rs:16:1 | 16 | pub trait Bcd {} | ^^^^^^^^^^^^^^^^^^^ @@ -69,7 +69,7 @@ error: breaking changes in `Bcd` = warning: type parameter added (breaking) error: breaking changes in `Cde` - --> $REPO_PATH/tests/cases/traits/new.rs:18:1 + --> traits/new.rs:18:1 | 18 | pub trait Cde {} | ^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ error: breaking changes in `Cde` = warning: type parameter removed (breaking) error: breaking changes in `Def` - --> $REPO_PATH/tests/cases/traits/new.rs:20:1 + --> traits/new.rs:20:1 | 20 | / pub trait Def { 21 | | // The method is not broken - the impls are, but calls should work as expected, as @@ -89,7 +89,7 @@ error: breaking changes in `Def` = warning: type parameter added (breaking) error: breaking changes in `Efg` - --> $REPO_PATH/tests/cases/traits/new.rs:26:1 + --> traits/new.rs:26:1 | 26 | / pub trait Efg { 27 | | fn efg(&self, a: A) -> bool; @@ -99,19 +99,19 @@ error: breaking changes in `Efg` = warning: type parameter removed (breaking) error: breaking changes in `Ghi` - --> $REPO_PATH/tests/cases/traits/new.rs:36:1 + --> traits/new.rs:36:1 | 36 | pub trait Ghi { } | ^^^^^^^^^^^^^^^^^ | warning: removed item from trait (breaking) - --> $REPO_PATH/tests/cases/traits/old.rs:35:5 + --> traits/old.rs:35:5 | 35 | type A; | ^^^^^^^ error: breaking changes in `Hij` - --> $REPO_PATH/tests/cases/traits/new.rs:38:1 + --> traits/new.rs:38:1 | 38 | / pub trait Hij { 39 | | type A; @@ -119,13 +119,13 @@ error: breaking changes in `Hij` | |_^ | warning: added item to trait (breaking) - --> $REPO_PATH/tests/cases/traits/new.rs:39:5 + --> traits/new.rs:39:5 | 39 | type A; | ^^^^^^^ error: breaking changes in `Klm` - --> $REPO_PATH/tests/cases/traits/new.rs:42:1 + --> traits/new.rs:42:1 | 42 | pub trait Klm : Clone { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ error: breaking changes in `Klm` = warning: added bound: `Self: std::clone::Clone` (breaking) error: breaking changes in `Nop` - --> $REPO_PATH/tests/cases/traits/new.rs:44:1 + --> traits/new.rs:44:1 | 44 | pub trait Nop { } | ^^^^^^^^^^^^^^^^^ @@ -141,7 +141,7 @@ error: breaking changes in `Nop` = warning: removed bound on trait definition: `Self: std::clone::Clone` (breaking) error: breaking changes in `Qrs` - --> $REPO_PATH/tests/cases/traits/new.rs:46:1 + --> traits/new.rs:46:1 | 46 | pub trait Qrs { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -149,7 +149,7 @@ error: breaking changes in `Qrs` = warning: added bound: `A: std::clone::Clone` (breaking) error: breaking changes in `Tuv` - --> $REPO_PATH/tests/cases/traits/new.rs:48:1 + --> traits/new.rs:48:1 | 48 | pub trait Tuv { } | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/cases/ty_alias/stdout b/tests/cases/ty_alias/stdout index 1eef78d287335..d2abe29b0b8ff 100644 --- a/tests/cases/ty_alias/stdout +++ b/tests/cases/ty_alias/stdout @@ -1,6 +1,6 @@ version bump: 1.0.0 -> (breaking) -> 2.0.0 error: breaking changes in `A` - --> $REPO_PATH/tests/cases/ty_alias/new.rs:3:1 + --> ty_alias/new.rs:3:1 | 3 | pub type A = u16; | ^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ error: breaking changes in `A` = warning: type error: expected u8, found u16 (breaking) error: breaking changes in `B` - --> $REPO_PATH/tests/cases/ty_alias/new.rs:4:1 + --> ty_alias/new.rs:4:1 | 4 | pub type B<'a, 'b : 'a, T> = (&'a T, &'b T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ error: breaking changes in `B` = warning: region parameter added (breaking) error: breaking changes in `C` - --> $REPO_PATH/tests/cases/ty_alias/new.rs:5:1 + --> ty_alias/new.rs:5:1 | 5 | pub type C = T; | ^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ error: breaking changes in `C` = warning: region parameter removed (breaking) error: breaking changes in `D` - --> $REPO_PATH/tests/cases/ty_alias/new.rs:6:1 + --> ty_alias/new.rs:6:1 | 6 | pub type D<'a, T, U=Box> = (&'a T, U); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ error: breaking changes in `D` = warning: type error: expected reference, found tuple (breaking) error: breaking changes in `E` - --> $REPO_PATH/tests/cases/ty_alias/new.rs:7:1 + --> ty_alias/new.rs:7:1 | 7 | pub type E<'a, T, U> = (&'a T, U); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ error: breaking changes in `E` = warning: type parameter added (breaking) error: breaking changes in `F` - --> $REPO_PATH/tests/cases/ty_alias/new.rs:8:1 + --> ty_alias/new.rs:8:1 | 8 | pub type F<'a> = &'a u8; | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ error: breaking changes in `F` = warning: defaulted type parameter removed (breaking) error: breaking changes in `G` - --> $REPO_PATH/tests/cases/ty_alias/new.rs:9:1 + --> ty_alias/new.rs:9:1 | 9 | pub type G<'a> = (&'a u8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/examples.rs b/tests/examples.rs index d9911ae2887c4..6254100b06fbe 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -1,139 +1,128 @@ mod features { use std::{ - env, fs, io, + env, + fs::{read_to_string, File}, + io::{BufRead, Write}, path::Path, process::{Command, Stdio}, }; - fn test_example(path: &Path, out_file: &Path, expected_result: bool) { + 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 stdout = fs::File::create(&out_file).expect("could not create `stdout` file"); - let stderr = stdout - .try_clone() - .expect("could not create `stderr` file by cloning `stdout`"); + let target_args = std::env::var("TEST_TARGET").map(|t| ["--target".to_string(), t]); - 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()); + 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); - } + 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 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( - 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(), - ]) + let mut cmd = Command::new("rustc"); + cmd.args(&["--crate-type=lib", "-o", &new_rlib]) + .arg(path.join("new.rs")) .env("RUST_BACKTRACE", "full") - .env("RUST_SEMVER_CRATE_VERSION", "1.0.0") - .stdin(Stdio::null()) - .stdout(Stdio::from(stdout)) - .stderr(Stdio::from(stderr)); + .stdin(Stdio::null()); - if let Ok(target_args) = &target_args { - cmd.args(target_args); - } + if let Ok(target_args) = &target_args { + cmd.args(target_args); + } - if out_file.to_str().unwrap().contains("stdout_api_guidelines") { - cmd.env("RUST_SEMVER_API_GUIDELINES", "true"); - } + 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); + } - let rustsemverver_result = cmd - .status() - .expect("could not run rust-semverver") - .success(); - assert_eq!( - rustsemverver_result, expected_result, - "rust-semverver returned an unexpected exit status" - ); + if expected_path.to_str().unwrap().contains("stdout_api_guidelines") { + cmd.env("RUST_SEMVER_API_GUIDELINES", "true"); + } - { - // replace root path with with $REPO_PATH - use self::io::{Read, Write}; - let current_dir = env::current_dir().expect("could not determine current dir"); - let mut contents = { - let mut f = fs::File::open(&out_file).expect("file not found"); - let mut contents = String::new(); - f.read_to_string(&mut contents) - .expect("something went wrong reading the file"); - contents - }; - - contents = contents.replace(current_dir.to_str().unwrap(), "$REPO_PATH"); - - if cfg!(target_os = "windows") { - let mut lines = Vec::new(); - - for line in contents.lines() { - if line.contains("$REPO_PATH") { - lines.push(line.replace('\\', "/")); - } else { - lines.push(line.to_owned()); + let output = cmd.output().expect("could not run rust-semverver"); + + let expected_output = + read_to_string(&expected_path).expect("could not read expected output from file"); + + let new_output = output + .stdout + .lines() + .chain(output.stderr.lines()) + .map(|r| r.expect("could not read line from rust-semverver output")) + .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, } } - lines.push(String::new()); - contents = lines.join("\r\n"); - } - - let mut file = fs::File::create(&out_file).expect("cannot create file"); - file.write_all(contents.as_bytes()) - .expect("cannot write to file"); - } + None => line, + }) + "\n" + }) + .map(|l| if cfg!(target_os = "windows") { + l.replace('\\', "/") + } else { + l + }) + .collect::(); + + 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(); + + eprintln!( + "For details, try this command: \n\n diff {} {}\n\n", + expected_path.display(), + new_path.display() + ); + panic!("unexpected output diff"); } - let git_result = Command::new("git") - .args(&[ - "diff", - "--ignore-space-at-eol", - "--exit-code", - out_file.to_str().unwrap(), - ]) - .env("PAGER", "") - .status() - .expect("could not run git diff") - .success(); - - assert!(git_result, "git reports unexpected diff"); + assert_eq!( + output.status.success(), expected_result, + "rust-semverver returned an unexpected exit status" + ); Command::new("rm") .args(&[&old_rlib, &new_rlib]) @@ -146,11 +135,11 @@ mod features { #[test] fn $name() { let path = Path::new("tests").join("cases").join(stringify!($name)); - test_example(&path, &path.join("stdout"), $result); + test_example2(stringify!($name), &path, &path.join("stdout"), $result); if path.join("stdout_api_guidelines").exists() { eprintln!("api-guidelines"); - test_example(&path, &path.join("stdout_api_guidelines"), $result); + test_example2(stringify!($name), &path, &path.join("stdout_api_guidelines"), $result); } } }; From ba296e72ecea1776a7ad5bc8359e3f863717c22c Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Sun, 2 Jun 2019 17:45:35 +0100 Subject: [PATCH 450/553] Semverver compiles again. --- src/typeck.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/typeck.rs b/src/typeck.rs index 7ba612bdff904..580813770d40f 100644 --- a/src/typeck.rs +++ b/src/typeck.rs @@ -246,7 +246,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { let err = self .infcx - .resolve_type_vars_if_possible(&err) + .resolve_vars_if_possible(&err) .fold_with(&mut self.folder.clone()) .lift_to_tcx(lift_tcx) .unwrap(); @@ -279,7 +279,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { .iter() .map(|err| { self.infcx - .resolve_type_vars_if_possible(&err.obligation.predicate) + .resolve_vars_if_possible(&err.obligation.predicate) .fold_with(&mut self.folder.clone()) .lift_to_tcx(lift_tcx) .unwrap() From 8d4d76d56daa59fecf294305df9c204feb2c2fcf Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Sun, 2 Jun 2019 18:19:28 +0100 Subject: [PATCH 451/553] Fix `dyn` is deprecated warnings. --- src/bin/cargo_semver.rs | 2 +- src/traverse.rs | 2 -- tests/cases/addition_use/new.rs | 2 +- tests/cases/addition_use/stdout | 2 +- tests/cases/addition_use/stdout_api_guidelines | 2 +- tests/cases/infer/new.rs | 4 ++-- tests/cases/infer/old.rs | 4 ++-- tests/cases/removal_use/old.rs | 2 +- tests/cases/trait_objects/new.rs | 4 ++-- tests/cases/trait_objects/old.rs | 4 ++-- 10 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index e4b2722a33b31..1ec061cfe5f71 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -343,7 +343,7 @@ pub struct SourceInfo<'a> { /// The source id to be used. id: SourceId, /// The source to be used. - source: Box, + source: Box, } impl<'a> SourceInfo<'a> { diff --git a/src/traverse.rs b/src/traverse.rs index e68426be46932..df4def82801ea 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -1044,8 +1044,6 @@ fn diff_trait_impls<'a, 'tcx>( id_mapping: &IdMapping, tcx: TyCtxt<'a, 'tcx, 'tcx>, ) { - // use rustc::ty::TyKind; - debug!("diffing trait impls"); let to_new = TranslationContext::target_new(tcx, id_mapping, false); diff --git a/tests/cases/addition_use/new.rs b/tests/cases/addition_use/new.rs index 64d1e65a5233b..014b777d8fff8 100644 --- a/tests/cases/addition_use/new.rs +++ b/tests/cases/addition_use/new.rs @@ -4,5 +4,5 @@ pub trait Bcd {} pub struct Def<'a> { pub field1: Abc, - pub field2: &'a Bcd, + pub field2: &'a dyn Bcd, } diff --git a/tests/cases/addition_use/stdout b/tests/cases/addition_use/stdout index fad808614b61c..8ab043f7c3f82 100644 --- a/tests/cases/addition_use/stdout +++ b/tests/cases/addition_use/stdout @@ -4,7 +4,7 @@ error: breaking changes in `Def` | 5 | / pub struct Def<'a> { 6 | | pub field1: Abc, -7 | | pub field2: &'a Bcd, +7 | | pub field2: &'a dyn Bcd, 8 | | } | |_^ | diff --git a/tests/cases/addition_use/stdout_api_guidelines b/tests/cases/addition_use/stdout_api_guidelines index 120e387a6f472..1683f9a1596dd 100644 --- a/tests/cases/addition_use/stdout_api_guidelines +++ b/tests/cases/addition_use/stdout_api_guidelines @@ -4,7 +4,7 @@ error: breaking changes in `Def` | 5 | / pub struct Def<'a> { 6 | | pub field1: Abc, -7 | | pub field2: &'a Bcd, +7 | | pub field2: &'a dyn Bcd, 8 | | } | |_^ | diff --git a/tests/cases/infer/new.rs b/tests/cases/infer/new.rs index 2f18b8e0137e3..1067118189f91 100644 --- a/tests/cases/infer/new.rs +++ b/tests/cases/infer/new.rs @@ -15,6 +15,6 @@ pub fn b() -> a::Opq { } pub struct Hij<'a> { - pub field: &'a a::Def, - pub field2: ::std::rc::Rc, + pub field: &'a dyn a::Def, + pub field2: ::std::rc::Rc, } diff --git a/tests/cases/infer/old.rs b/tests/cases/infer/old.rs index 9f14c969f7132..6ef1267587eca 100644 --- a/tests/cases/infer/old.rs +++ b/tests/cases/infer/old.rs @@ -15,6 +15,6 @@ pub fn b() -> a::Klm { } pub struct Hij<'a> { - pub field: &'a a::Abc, - pub field2: ::std::rc::Rc, + pub field: &'a dyn a::Abc, + pub field2: ::std::rc::Rc, } diff --git a/tests/cases/removal_use/old.rs b/tests/cases/removal_use/old.rs index 64d1e65a5233b..014b777d8fff8 100644 --- a/tests/cases/removal_use/old.rs +++ b/tests/cases/removal_use/old.rs @@ -4,5 +4,5 @@ pub trait Bcd {} pub struct Def<'a> { pub field1: Abc, - pub field2: &'a Bcd, + pub field2: &'a dyn Bcd, } diff --git a/tests/cases/trait_objects/new.rs b/tests/cases/trait_objects/new.rs index 2491fd9c96194..12130d827590b 100644 --- a/tests/cases/trait_objects/new.rs +++ b/tests/cases/trait_objects/new.rs @@ -6,8 +6,8 @@ pub struct Def; impl Abc for Def { } -pub fn a(_: &Abc) { } +pub fn a(_: &dyn Abc) { } pub trait A { } -pub type Something = A<()>; +pub type Something = dyn A<()>; diff --git a/tests/cases/trait_objects/old.rs b/tests/cases/trait_objects/old.rs index 2491fd9c96194..12130d827590b 100644 --- a/tests/cases/trait_objects/old.rs +++ b/tests/cases/trait_objects/old.rs @@ -6,8 +6,8 @@ pub struct Def; impl Abc for Def { } -pub fn a(_: &Abc) { } +pub fn a(_: &dyn Abc) { } pub trait A { } -pub type Something = A<()>; +pub type Something = dyn A<()>; From 1df1de23c173cb2c25167ebb4f96ae424bda4bbc Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Sun, 2 Jun 2019 23:05:21 +0100 Subject: [PATCH 452/553] Fix race condition when multiple cargo-semver ran concurrently. --- src/bin/cargo_semver.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 1ec061cfe5f71..78a3f98d0a9c7 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -19,6 +19,7 @@ use std::{ path::{Path, PathBuf}, process::{Command, Stdio}, }; +use rand::Rng; pub type Result = cargo::util::CargoResult; @@ -430,7 +431,8 @@ impl<'a> WorkInfo<'a> { ); let mut outdir = env::temp_dir(); - outdir.push(&format!("cargo_semver_{}_{}", name, current)); + // The filename is randomized to avoid clashes when multiple cargo semver are running. + outdir.push(&format!("cargo_semver_{}_{}_{}", name, current, rand::thread_rng().gen::())); // redirection gang let outfile = File::create(&outdir)?; From 69ff6f7077b7f615af90bf72c98d553c043f20a3 Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Sun, 2 Jun 2019 18:36:54 +0100 Subject: [PATCH 453/553] Fix impl trait visibility issue. --- src/traverse.rs | 52 +++++++++++++++---- tests/full_cases/log-0.3.4-0.3.8.linux | 12 ----- tests/full_cases/log-0.3.4-0.3.8.osx | 12 ----- tests/full_cases/log-0.3.4-0.3.8.windows_msvc | 12 ----- 4 files changed, 42 insertions(+), 46 deletions(-) diff --git a/src/traverse.rs b/src/traverse.rs index df4def82801ea..1be1f88e9602b 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -25,8 +25,8 @@ use rustc::{ }, ty::{ subst::{InternalSubsts, Subst}, - AssocItem, GenericParamDef, GenericParamDefKind, Generics, Ty, TyCtxt, - Visibility, + AssocItem, GenericParamDef, GenericParamDefKind, Generics, TraitRef, Ty, TyCtxt, TyKind, + TypeAndMut, Visibility, Visibility::Public, }, }; @@ -544,7 +544,7 @@ fn diff_traits<'a, 'tcx>( ) { use rustc::hir::Unsafety::Unsafe; use rustc::ty::subst::UnpackedKind::Type; - use rustc::ty::{ParamTy, Predicate, TyKind, TyS}; + use rustc::ty::{ParamTy, Predicate, TyS}; debug!( "diff_traits: old: {:?}, new: {:?}, output: {:?}", @@ -1038,6 +1038,42 @@ fn diff_inherent_impls<'a, 'tcx>( } } +// 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). +fn is_impl_trait_public<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_def_id: DefId) -> bool { + fn type_visibility<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty) -> Visibility { + match ty.sty { + TyKind::Adt(def, _) => tcx.visibility(def.did), + TyKind::Array(t, _) => type_visibility(tcx, t), + TyKind::Slice(t) => type_visibility(tcx, t), + TyKind::RawPtr(TypeAndMut { ty: t, .. }) => type_visibility(tcx, 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 + .input_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<'a, 'tcx>( changes: &mut ChangeSet<'tcx>, @@ -1053,11 +1089,9 @@ fn diff_trait_impls<'a, '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) - || tcx.visibility(*old_impl_def_id) != Public - { + + if !to_new.can_translate(old_trait_def_id) || !is_impl_trait_public(tcx, *old_impl_def_id) { continue; } @@ -1077,9 +1111,7 @@ fn diff_trait_impls<'a, 'tcx>( { 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) - || tcx.visibility(*new_impl_def_id) != Public - { + if !to_old.can_translate(new_trait_def_id) || !is_impl_trait_public(tcx, *new_impl_def_id) { continue; } diff --git a/tests/full_cases/log-0.3.4-0.3.8.linux b/tests/full_cases/log-0.3.4-0.3.8.linux index b7ce494eadc75..08d8a82f0f695 100644 --- a/tests/full_cases/log-0.3.4-0.3.8.linux +++ b/tests/full_cases/log-0.3.4-0.3.8.linux @@ -71,18 +71,6 @@ warning: technically breaking changes in ` as std::fmt::Deb | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in `` - --> log-0.3.8/src/lib.rs:591:1 - | -591 | / impl Log for NopLogger { -592 | | fn enabled(&self, _: &LogMetadata) -> bool { false } -593 | | -594 | | fn log(&self, _: &LogRecord) {} -595 | | } - | |_^ - | - = note: trait impl generalized or newly added (technically breaking) - warning: technically breaking changes in `` --> log-0.3.8/src/lib.rs:604:30 | diff --git a/tests/full_cases/log-0.3.4-0.3.8.osx b/tests/full_cases/log-0.3.4-0.3.8.osx index b7ce494eadc75..08d8a82f0f695 100644 --- a/tests/full_cases/log-0.3.4-0.3.8.osx +++ b/tests/full_cases/log-0.3.4-0.3.8.osx @@ -71,18 +71,6 @@ warning: technically breaking changes in ` as std::fmt::Deb | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in `` - --> log-0.3.8/src/lib.rs:591:1 - | -591 | / impl Log for NopLogger { -592 | | fn enabled(&self, _: &LogMetadata) -> bool { false } -593 | | -594 | | fn log(&self, _: &LogRecord) {} -595 | | } - | |_^ - | - = note: trait impl generalized or newly added (technically breaking) - warning: technically breaking changes in `` --> log-0.3.8/src/lib.rs:604:30 | diff --git a/tests/full_cases/log-0.3.4-0.3.8.windows_msvc b/tests/full_cases/log-0.3.4-0.3.8.windows_msvc index 86b0f543b587f..0f6faa4ee4e28 100644 --- a/tests/full_cases/log-0.3.4-0.3.8.windows_msvc +++ b/tests/full_cases/log-0.3.4-0.3.8.windows_msvc @@ -71,18 +71,6 @@ warning: technically breaking changes in ` as std::fmt::Deb | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in `` - --> log-0.3.8\src\lib.rs:591:1 - | -591 | / impl Log for NopLogger { -592 | | fn enabled(&self, _: &LogMetadata) -> bool { false } -593 | | -594 | | fn log(&self, _: &LogRecord) {} -595 | | } - | |_^ - | - = note: trait impl generalized or newly added (technically breaking) - warning: technically breaking changes in `` --> log-0.3.8\src\lib.rs:604:30 | From 06d361607e8ed32e99723c373731f7642e9ed809 Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Sun, 2 Jun 2019 23:26:20 +0100 Subject: [PATCH 454/553] Ran `cargo fmt`. --- src/bin/cargo_semver.rs | 9 +++++++-- src/mapping.rs | 7 ++----- src/mismatch.rs | 40 +++++++++++++++++++++++----------------- src/traverse.rs | 40 +++++++++++++++++----------------------- tests/examples.rs | 19 +++++++++++++------ 5 files changed, 62 insertions(+), 53 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 78a3f98d0a9c7..d84d69b4ee9e3 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -11,6 +11,7 @@ extern crate serde_json; use cargo::core::{Package, PackageId, PackageSet, Source, SourceId, SourceMap, Workspace}; use curl::easy::Easy; use log::debug; +use rand::Rng; use std::{ env, fs::File, @@ -19,7 +20,6 @@ use std::{ path::{Path, PathBuf}, process::{Command, Stdio}, }; -use rand::Rng; pub type Result = cargo::util::CargoResult; @@ -432,7 +432,12 @@ impl<'a> WorkInfo<'a> { let mut outdir = env::temp_dir(); // The filename is randomized to avoid clashes when multiple cargo semver are running. - outdir.push(&format!("cargo_semver_{}_{}_{}", name, current, rand::thread_rng().gen::())); + outdir.push(&format!( + "cargo_semver_{}_{}_{}", + name, + current, + rand::thread_rng().gen::() + )); // redirection gang let outfile = File::create(&outdir)?; diff --git a/src/mapping.rs b/src/mapping.rs index 0ce37dc0a9787..1f8f4c523a191 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -245,10 +245,7 @@ impl IdMapping { /// Construct a queue of toplevel item pairs' `DefId`s. pub fn toplevel_queue(&self) -> VecDeque<(Res, Res)> { - self.toplevel_mapping - .values() - .map(|t| *t) - .collect() + self.toplevel_mapping.values().map(|t| *t).collect() } /// Iterate over the toplevel and trait item pairs. @@ -315,8 +312,8 @@ pub struct NameMapping { impl NameMapping { /// Insert a single export in the appropriate map, at the appropriate position. fn insert(&mut self, item: Export, old: bool) { - use rustc::hir::def::Res::*; use rustc::hir::def::DefKind::*; + use rustc::hir::def::Res::*; let map = match item.res { Def(kind, _) => match kind { diff --git a/src/mismatch.rs b/src/mismatch.rs index d1ccb5048ee35..6288789e3982e 100644 --- a/src/mismatch.rs +++ b/src/mismatch.rs @@ -63,18 +63,18 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> MismatchRelation<'a, 'gcx, 'tcx> { // 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) - }, + match k1 { + DefKind::Trait | DefKind::Macro(_) => continue, + _ => (), + }; + + match k2 { + DefKind::Trait | DefKind::Macro(_) => continue, + _ => (), + }; + + (o, n) + } _ => continue, }; @@ -165,7 +165,9 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, Res::Def(DefKind::Struct, a_def.did) } else if a_def.is_union() { Res::Def(DefKind::Union, a_def.did) - } else /* if a_def.is_enum() */ { + } else + /* if a_def.is_enum() */ + { Res::Def(DefKind::Enum, a_def.did) }; @@ -173,7 +175,9 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, Res::Def(DefKind::Struct, b_def.did) } else if b_def.is_union() { Res::Def(DefKind::Union, b_def.did) - } else /* if b_def.is_enum() */ { + } else + /* if b_def.is_enum() */ + { Res::Def(DefKind::Enum, b_def.did) }; @@ -286,9 +290,11 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, Ok(a) } - fn consts(&mut self, a: &'tcx ty::Const<'tcx>, _: &'tcx ty::Const<'tcx>) - -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> - { + fn consts( + &mut self, + a: &'tcx ty::Const<'tcx>, + _: &'tcx ty::Const<'tcx>, + ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { Ok(a) // TODO } diff --git a/src/traverse.rs b/src/traverse.rs index 1be1f88e9602b..4ac4ce39cd13e 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -176,15 +176,13 @@ fn diff_structure<'a, 'tcx>( } let (o_kind, n_kind) = match (o.res, n.res) { - (Res::Def(o_kind, _), Res::Def(n_kind, _)) => { - (o_kind, n_kind) - }, + (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) { @@ -326,10 +324,7 @@ fn diff_structure<'a, 'tcx>( } /// Given two fn items, perform structural checks. -fn diff_fn<'a, 'tcx>(changes: &mut ChangeSet, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - old: Res, - new: Res) { +fn diff_fn<'a, 'tcx>(changes: &mut ChangeSet, tcx: TyCtxt<'a, 'tcx, 'tcx>, old: Res, new: Res) { let old_def_id = old.def_id(); let new_def_id = new.def_id(); @@ -385,21 +380,16 @@ fn diff_method<'a, 'tcx>( /// /// 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) { +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)) - } + (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, }; @@ -588,13 +578,13 @@ fn diff_traits<'a, 'tcx>( 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)); + // 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)); + // tcx.describe_def(*new_def_id).map(|d| (d, item)); } for (name, item_pair) in &items { @@ -1049,8 +1039,13 @@ fn is_impl_trait_public<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_def_id: DefI TyKind::Slice(t) => type_visibility(tcx, t), TyKind::RawPtr(TypeAndMut { ty: t, .. }) => type_visibility(tcx, t), TyKind::Ref(_, t, _) => type_visibility(tcx, t), - TyKind::Bool | TyKind::Char | TyKind::Int(_) | TyKind::Uint(_) | TyKind::Float(_) - | TyKind::Str | TyKind:: Never => Visibility::Public, + 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. @@ -1211,8 +1206,7 @@ fn match_inherent_impl<'a, 'tcx>( // 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) => ( + (AssocKind::Const, AssocKind::Const) | (AssocKind::Type, AssocKind::Type) => ( infcx.tcx.type_of(orig_item_def_id), infcx.tcx.type_of(target_item_def_id), ), diff --git a/tests/examples.rs b/tests/examples.rs index 6254100b06fbe..b7adf355562a4 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -70,7 +70,11 @@ mod features { cmd.args(target_args); } - if expected_path.to_str().unwrap().contains("stdout_api_guidelines") { + if expected_path + .to_str() + .unwrap() + .contains("stdout_api_guidelines") + { cmd.env("RUST_SEMVER_API_GUIDELINES", "true"); } @@ -97,10 +101,12 @@ mod features { None => line, }) + "\n" }) - .map(|l| if cfg!(target_os = "windows") { - l.replace('\\', "/") - } else { - l + .map(|l| { + if cfg!(target_os = "windows") { + l.replace('\\', "/") + } else { + l + } }) .collect::(); @@ -120,7 +126,8 @@ mod features { } assert_eq!( - output.status.success(), expected_result, + output.status.success(), + expected_result, "rust-semverver returned an unexpected exit status" ); From 0d7f37666525ed865855dad68c7568d7fbfdb509 Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Sun, 2 Jun 2019 23:47:11 +0100 Subject: [PATCH 455/553] Fix clippy warnings. --- src/lib.rs | 2 ++ src/mapping.rs | 2 +- src/mismatch.rs | 8 ++------ src/traverse.rs | 12 ++++++++---- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2e63e1a2c7333..cd88fd8a38df5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,7 @@ #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] +#![allow(clippy::similar_names)] +#![allow(clippy::single_match_else)] #![deny(warnings)] extern crate rustc; extern crate syntax; diff --git a/src/mapping.rs b/src/mapping.rs index 1f8f4c523a191..c370b3edd5c9f 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -245,7 +245,7 @@ impl IdMapping { /// Construct a queue of toplevel item pairs' `DefId`s. pub fn toplevel_queue(&self) -> VecDeque<(Res, Res)> { - self.toplevel_mapping.values().map(|t| *t).collect() + self.toplevel_mapping.values().copied().collect() } /// Iterate over the toplevel and trait item pairs. diff --git a/src/mismatch.rs b/src/mismatch.rs index 6288789e3982e..d68cd15d5fe66 100644 --- a/src/mismatch.rs +++ b/src/mismatch.rs @@ -165,9 +165,7 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, Res::Def(DefKind::Struct, a_def.did) } else if a_def.is_union() { Res::Def(DefKind::Union, a_def.did) - } else - /* if a_def.is_enum() */ - { + } else { Res::Def(DefKind::Enum, a_def.did) }; @@ -175,9 +173,7 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, Res::Def(DefKind::Struct, b_def.did) } else if b_def.is_union() { Res::Def(DefKind::Union, b_def.did) - } else - /* if b_def.is_enum() */ - { + } else { Res::Def(DefKind::Enum, b_def.did) }; diff --git a/src/traverse.rs b/src/traverse.rs index 4ac4ce39cd13e..c29e69836b9ae 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -1031,14 +1031,18 @@ fn diff_inherent_impls<'a, 'tcx>( // 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<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_def_id: DefId) -> bool { fn type_visibility<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty) -> Visibility { match ty.sty { TyKind::Adt(def, _) => tcx.visibility(def.did), - TyKind::Array(t, _) => type_visibility(tcx, t), - TyKind::Slice(t) => type_visibility(tcx, t), - TyKind::RawPtr(TypeAndMut { ty: t, .. }) => type_visibility(tcx, t), - TyKind::Ref(_, t, _) => type_visibility(tcx, t), + + TyKind::Array(t, _) + | TyKind::Slice(t) + | TyKind::RawPtr(TypeAndMut { ty: t, .. }) + | TyKind::Ref(_, t, _) => type_visibility(tcx, t), + TyKind::Bool | TyKind::Char | TyKind::Int(_) From 97005d44f5e4f76051db4ee3391d3e6abe3542c7 Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Sun, 2 Jun 2019 23:57:37 +0100 Subject: [PATCH 456/553] Improved test failure output when running full tests in travis. --- tests/full.rs | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/tests/full.rs b/tests/full.rs index a35e0c875c98f..2aa438b23e871 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -93,11 +93,24 @@ mod full { let mut new_file = File::create(&new_path).unwrap(); new_file.write_all(new_output.as_bytes()).unwrap(); - eprintln!( - "For details, try this command: \n\n diff {} {}\n\n", - expected_path.display(), - new_path.display() - ); + 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 ==="); + eprint!("{}", expected_output); + eprintln!("=== End of expected output ==="); + eprintln!("=== Actual output ==="); + eprint!("{}", new_output); + eprintln!("=== End of actual output ==="); + } + }; + panic!("unexpected output diff"); } From 30d2863c645a19dcc08d5cba13d480fe6887341a Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Mon, 3 Jun 2019 00:49:09 +0100 Subject: [PATCH 457/553] Updated cargo dependency. --- Cargo.toml | 2 +- src/bin/cargo_semver.rs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 55b924226d9ff..d124973d92e97 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ name = "rust-semverver" path = "src/bin/rust_semverver.rs" [dependencies] -cargo = "0.32" +cargo = "0.35" crates-io = "0.23" curl = "0.4.21" env_logger = "0.6" diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index d84d69b4ee9e3..239e645de448a 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -12,6 +12,7 @@ use cargo::core::{Package, PackageId, PackageSet, Source, SourceId, SourceMap, W use curl::easy::Easy; use log::debug; use rand::Rng; +use std::collections::HashSet; use std::{ env, fs::File, @@ -351,7 +352,7 @@ impl<'a> SourceInfo<'a> { /// Construct a new source info for `crates.io`. pub fn new(config: &'a cargo::Config) -> Result> { let source_id = SourceId::crates_io(config)?; - let source = source_id.load(config)?; + let source = source_id.load(config, &HashSet::new())?; debug!("source id loaded: {:?}", source_id); @@ -387,7 +388,7 @@ impl<'a> WorkInfo<'a> { ) -> Result> { // TODO: fall back to locally cached package instance, or better yet, search for it // first. - let package_ids = [PackageId::new(name, version, &source.id)?]; + let package_ids = [PackageId::new(name, version, source.id)?]; debug!("(remote) package id: {:?}", package_ids[0]); let sources = { let mut s = SourceMap::new(); @@ -396,7 +397,7 @@ impl<'a> WorkInfo<'a> { }; let package_set = PackageSet::new(&package_ids, sources, config)?; - let package = package_set.get_one(&package_ids[0])?; + let package = package_set.get_one(package_ids[0])?; let workspace = Workspace::ephemeral(package.clone(), config, None, false)?; Ok(Self { From d753b66f07e7999704d524c07a7ca548218438d6 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 6 Jun 2019 22:47:57 +0000 Subject: [PATCH 458/553] Fixed bits of the build. --- src/mapping.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mapping.rs b/src/mapping.rs index c370b3edd5c9f..092dca2c695d9 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -340,7 +340,7 @@ impl NameMapping { Macro(_) => Some(&mut self.macro_map), }, PrimTy(_) | SelfTy(_, _) => Some(&mut self.type_map), - SelfCtor(_) | Local(_) | Upvar(_, _, _) => Some(&mut self.value_map), + SelfCtor(_) | Local(_) => Some(&mut self.value_map), _ => None, }; From 6a9aaaa3d0b38c174a230e7148ffd10e927218cc Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 6 Jun 2019 22:50:12 +0000 Subject: [PATCH 459/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d124973d92e97..a20cecf49e9d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.33" +version = "0.1.34" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From 8edc71fcc8cb6e58e5626b269cef69cbce99a639 Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Fri, 7 Jun 2019 23:28:25 +0100 Subject: [PATCH 460/553] Always update an index before using it. --- Cargo.toml | 4 ++-- ci/run.sh | 4 ---- src/bin/cargo_semver.rs | 6 +++++- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a20cecf49e9d9..98fd7e63572f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,8 +23,8 @@ name = "rust-semverver" path = "src/bin/rust_semverver.rs" [dependencies] -cargo = "0.35" -crates-io = "0.23" +cargo = "0.36" +crates-io = "0.24" curl = "0.4.21" env_logger = "0.6" failure = "0.1" diff --git a/ci/run.sh b/ci/run.sh index b8d424395290c..63465e5356f6d 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -2,10 +2,6 @@ set -ex -# Note: this is required for correctness, -# otherwise executing multiple "full" tests in parallel -# of the same library can alter results. -export RUST_TEST_THREADS=1 export RUST_BACKTRACE=full #export RUST_TEST_NOCAPTURE=1 diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 239e645de448a..baf6a288f2311 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -352,10 +352,14 @@ impl<'a> SourceInfo<'a> { /// Construct a new source info for `crates.io`. pub fn new(config: &'a cargo::Config) -> Result> { let source_id = SourceId::crates_io(config)?; - let source = source_id.load(config, &HashSet::new())?; + let mut source = source_id.load(config, &HashSet::new())?; debug!("source id loaded: {:?}", source_id); + // Update the index. Without this we would not be able to fetch recent packages if the + // index is not up-to-date. + source.update()?; + Ok(Self { id: source_id, source, From 741771f0db5aee7cd76371b70401947aba20586b Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Fri, 7 Jun 2019 23:57:53 +0100 Subject: [PATCH 461/553] Include diff when running on travis. --- tests/examples.rs | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/tests/examples.rs b/tests/examples.rs index b7adf355562a4..80bc9e189cb1d 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -117,11 +117,24 @@ mod features { let mut new_file = File::create(&new_path).unwrap(); new_file.write_all(new_output.as_bytes()).unwrap(); - eprintln!( - "For details, try this command: \n\n diff {} {}\n\n", - expected_path.display(), - new_path.display() - ); + 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 ==="); + eprint!("{}", expected_output); + eprintln!("=== End of expected output ==="); + eprintln!("=== Actual output ==="); + eprint!("{}", new_output); + eprintln!("=== End of actual output ==="); + } + }; + panic!("unexpected output diff"); } From b915e06aaaa4da6e55c0f6f62a153c37252f3ca5 Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Sat, 8 Jun 2019 00:26:43 +0100 Subject: [PATCH 462/553] Fix example tests on windows. For whatever reason some of the output of the error reporting of rustc includes trailing whitespace. This commit trims the lines before checking the tests' output. --- tests/examples.rs | 83 +++++++++++++++++++++++++++++------------------ tests/full.rs | 79 +++++++++++++++++++++++++++----------------- 2 files changed, 102 insertions(+), 60 deletions(-) diff --git a/tests/examples.rs b/tests/examples.rs index 80bc9e189cb1d..02dbd2f48dd25 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -2,9 +2,10 @@ mod features { use std::{ env, fs::{read_to_string, File}, - io::{BufRead, Write}, + io::Write, path::Path, process::{Command, Stdio}, + str, }; fn test_example2(name: &str, path: &Path, expected_path: &Path, expected_result: bool) { @@ -78,37 +79,57 @@ mod features { cmd.env("RUST_SEMVER_API_GUIDELINES", "true"); } - let output = cmd.output().expect("could not run rust-semverver"); + let expected_output = read_to_string(&expected_path) + .expect(&format!( + "could not read expected output from file {}", + expected_path.display() + )) + .lines() + .map(|l| l.trim_end()) + .map(|l| l.to_string() + "\n") + .collect::() + .trim_end() + .to_string(); - let expected_output = - read_to_string(&expected_path).expect("could not read expected output from file"); + let output = cmd.output().expect("could not run rust-semverver"); - let new_output = output - .stdout - .lines() - .chain(output.stderr.lines()) - .map(|r| r.expect("could not read line from rust-semverver output")) - .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, + 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 } - None => line, - }) + "\n" - }) - .map(|l| { - if cfg!(target_os = "windows") { - l.replace('\\', "/") - } else { - l - } - }) - .collect::(); + }) + .map(|l| l + "\n") + .collect::() + .trim_end() + .to_string() + }; if expected_output != new_output { eprintln!("rust-semverver failed to produce the expected result"); @@ -120,17 +141,17 @@ mod features { match std::env::var_os("CI") { None => { eprintln!( - "For details, try this command: \n\n diff {} {}\n\n", + "For details, try this command:\n\n diff {} {}\n\n", expected_path.display(), new_path.display() ); } Some(_) => { eprintln!("=== Expected output ==="); - eprint!("{}", expected_output); + eprintln!("{}", expected_output); eprintln!("=== End of expected output ==="); eprintln!("=== Actual output ==="); - eprint!("{}", new_output); + eprintln!("{}", new_output); eprintln!("=== End of actual output ==="); } }; diff --git a/tests/full.rs b/tests/full.rs index 2aa438b23e871..21d9620bb12a1 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -3,9 +3,10 @@ mod full { use std::{ env, fs::{read_to_string, File}, - io::{BufRead, Write}, + io::Write, path::Path, process::{Command, Stdio}, + str, }; fn test_full(crate_name: &str, old_version: &str, new_version: &str, expected_result: bool) { @@ -58,33 +59,53 @@ mod full { let expected_path = Path::new("tests/full_cases").join(&filename); - let expected_output = - read_to_string(&expected_path).expect("could not read expected output from file"); - - let new_output = output - .stdout + let expected_output = read_to_string(&expected_path) + .expect(&format!( + "could not read expected output from file {}", + expected_path.display() + )) .lines() - .chain(output.stderr.lines()) - .map(|r| r.expect("could not read line from cargo-semver output")) - .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, + .map(|l| l.trim_end()) + .map(|l| l.to_string() + "\n") + .collect::() + .trim_end() + .to_string(); + + let new_output = { + let stdout: &str = str::from_utf8(&output.stdout) + .expect("could not read line from rust-semverver output") + .trim_end(); + let stderr: &str = str::from_utf8(&output.stderr) + .expect("could not read line from rust-semverver output") + .trim_end(); + + stdout + .lines() + .chain(stderr.lines()) + .map(|l| l.trim_end()) + .skip_while(|line| + // skip everything before the first important bit of info + !line.starts_with("version bump") && + // ...unless debugging is enabled + !log_enabled!(Level::Debug)) + .map(|line| { + // sanitize paths for reproducibility + (match line.find("-->") { + Some(idx) => { + let (start, end) = line.split_at(idx); + match end.find(crate_name) { + Some(idx) => format!("{}--> {}", start, end.split_at(idx).1), + None => line.to_string(), + } } - } - None => line, - }) + "\n" - }) - .collect::(); + None => line.to_string(), + }) + }) + .map(|l| l + "\n") + .collect::() + .trim_end() + .to_string() + }; if expected_output != new_output { eprintln!("cargo-semver failed to produce the expected output"); @@ -96,17 +117,17 @@ mod full { match std::env::var_os("CI") { None => { eprintln!( - "For details, try this command: \n\n diff {} {}\n\n", + "For details, try this command:\n\n diff {} {}\n\n", expected_path.display(), new_path.display() ); } Some(_) => { eprintln!("=== Expected output ==="); - eprint!("{}", expected_output); + eprintln!("{}", expected_output); eprintln!("=== End of expected output ==="); eprintln!("=== Actual output ==="); - eprint!("{}", new_output); + eprintln!("{}", new_output); eprintln!("=== End of actual output ==="); } }; From 26073be66ff0dface003bd8a2d041d5f7c967dde Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Sat, 8 Jun 2019 15:55:12 +0100 Subject: [PATCH 463/553] Disabled full test on windows when running on Travis. See issue #105. --- tests/full.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/full.rs b/tests/full.rs index 21d9620bb12a1..6bcbb0e41bb4d 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -10,6 +10,16 @@ mod full { }; fn test_full(crate_name: &str, old_version: &str, new_version: &str, expected_result: bool) { + // Full test are not working on windows. See issue #105. + if std::env::var_os("CI").is_some() && cfg!(all(target_os = "windows", target_env = "msvc")) + { + eprintln!( + "Skipping full test of crate {} ({} -> {}) on windows. See issue #105.", + crate_name, old_version, new_version + ); + return; + } + // 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::>(); From ca92884ab0a3549ab3b2eab97bececc4b5291b80 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 8 Jun 2019 20:51:26 +0000 Subject: [PATCH 464/553] Updated .travis.yml to have more notifications. --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 146f85b6de2b7..80fa7b412617e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,10 @@ language: rust rust: nightly sudo: false +notifications: + email: + on_failure: always + matrix: fast_finish: true include: From f0011156d7395e514e898d0b1b63a957338db641 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 8 Jun 2019 21:13:04 +0000 Subject: [PATCH 465/553] An attempt to fix windows runs on travis. --- tests/full.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/full.rs b/tests/full.rs index 6bcbb0e41bb4d..15d3992b126bb 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -4,21 +4,21 @@ mod full { env, fs::{read_to_string, File}, io::Write, - path::Path, + path::{Path, PathBuf}, process::{Command, Stdio}, str, }; fn test_full(crate_name: &str, old_version: &str, new_version: &str, expected_result: bool) { // Full test are not working on windows. See issue #105. - if std::env::var_os("CI").is_some() && cfg!(all(target_os = "windows", target_env = "msvc")) + /* if std::env::var_os("CI").is_some() && cfg!(all(target_os = "windows", target_env = "msvc")) { eprintln!( "Skipping full test of crate {} ({} -> {}) on windows. See issue #105.", crate_name, old_version, new_version ); return; - } + } */ // Add target dir to PATH so cargo-semver will call the right rust-semverver if let Some(path) = env::var_os("PATH") { @@ -67,7 +67,15 @@ mod full { crate_name, old_version, new_version, file_ext ); - let expected_path = Path::new("tests/full_cases").join(&filename); + 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!( From 130dd8ae632e49792cfac684c3614525f2b1aed9 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 8 Jun 2019 21:44:46 +0000 Subject: [PATCH 466/553] Fixed one of the remaining full tests on windows. --- tests/full.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/full.rs b/tests/full.rs index 15d3992b126bb..bf7e453a8ae22 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -164,7 +164,7 @@ mod full { macro_rules! full_test { ($name:ident, $crate_name:expr, $old_version:expr, $new_version:expr, - $result:literal) => { + $result:expr) => { #[test] fn $name() { test_full($crate_name, $old_version, $new_version, $result); @@ -173,7 +173,8 @@ mod full { } full_test!(log, "log", "0.3.4", "0.3.8", true); - full_test!(libc0, "libc", "0.2.28", "0.2.31", false); + // 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!(mozjs, "mozjs", "0.2.0", "0.3.0"); // full_test!(rand, "rand", "0.3.10", "0.3.16"); From a97e1c9dad9757766311dc066a224e51aeeba47d Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 8 Jun 2019 21:49:35 +0000 Subject: [PATCH 467/553] Added output for remaining windows test case. Fixes #105. --- tests/full_cases/libc-0.2.47-0.2.48.windows_msvc | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/full_cases/libc-0.2.47-0.2.48.windows_msvc diff --git a/tests/full_cases/libc-0.2.47-0.2.48.windows_msvc b/tests/full_cases/libc-0.2.47-0.2.48.windows_msvc new file mode 100644 index 0000000000000..0588e9104e1c2 --- /dev/null +++ b/tests/full_cases/libc-0.2.47-0.2.48.windows_msvc @@ -0,0 +1 @@ +version bump: 0.2.47 -> (patch) -> 0.2.48 From 749d20615f494024f9a3298126d76e8dec3f5dc6 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 8 Jun 2019 23:12:39 +0000 Subject: [PATCH 468/553] Updated AppVeyor path configuration. --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 11e21d4cade1e..7d316a9f77b95 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,7 +4,7 @@ environment: OTHER_TARGET: i686-pc-windows-msvc install: - - set PATH=C:\Program Files\Git\mingw64\bin;%PATH% + - set PATH=%PATH%;C:\Program Files\Git\mingw64\bin - curl -sSf -o rustup-init.exe https://win.rustup.rs/ - rustup-init.exe -y --default-host %TARGET% --default-toolchain nightly - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin;C:\Users\appveyor\.rustup\toolchains\nightly-%TARGET%\bin From ce033058bc93754e7c1660ee8e25c300abae1c0f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 8 Jun 2019 23:56:14 +0000 Subject: [PATCH 469/553] Disabled some tests on appveyor for now. --- ci/run.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ci/run.sh b/ci/run.sh index 63465e5356f6d..27e664c88d188 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -8,6 +8,11 @@ export RUST_BACKTRACE=full cargo build cargo test --verbose -- --nocapture +# avoid weird cygwin issues for now +if [ -n "$APPVEYOR" ]; then + exit 0 +fi + case "${TRAVIS_OS_NAME}" in *"linux"*) TEST_TARGET=x86_64-unknown-linux-gnu cargo test --verbose -- --nocapture From 8361ace23e74366748452e39674dbdff3c17126b Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 9 Jun 2019 13:49:26 +0000 Subject: [PATCH 470/553] Stopped lying about passing options to cargo (see #97), --- src/bin/cargo_semver.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index baf6a288f2311..7efbb4e2a56ae 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -294,7 +294,8 @@ mod cli { /// Print a help message pub fn print_help(opts: &getopts::Options) { - let brief = "usage: cargo semver [options] [-- cargo options]"; + // FIXME: pass remaining options to cargo + let brief = "usage: cargo semver [options]"; print!("{}", opts.usage(brief)); } From 5e17913e708ad4600c905083bab77a71c488ecd3 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 9 Jun 2019 13:50:16 +0000 Subject: [PATCH 471/553] Switched to cargo's `Source::download_now`. Closes #90. Instead of rolling our own, complicated, download machinery, we now reuse a bit mroe code from cargo. --- src/bin/cargo_semver.rs | 61 +++++++++++++---------------------------- 1 file changed, 19 insertions(+), 42 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 7efbb4e2a56ae..9eec819c7883b 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -8,7 +8,8 @@ extern crate serde; extern crate serde_derive; extern crate serde_json; -use cargo::core::{Package, PackageId, PackageSet, Source, SourceId, SourceMap, Workspace}; +use cargo::core::{Package, PackageId, Source, SourceId, Workspace}; +use cargo::sources::RegistrySource; use curl::easy::Easy; use log::debug; use rand::Rng; @@ -94,7 +95,6 @@ fn run(config: &cargo::Config, matches: &getopts::Matches, explain: bool) -> Res // -C "name:version" requires fetching the appropriate package: WorkInfo::remote( config, - SourceInfo::new(config)?, &PackageNameAndVersion::parse(&name_and_version)?, )? } else if let Some(path) = matches.opt_str("c").map(PathBuf::from) { @@ -112,7 +112,7 @@ fn run(config: &cargo::Config, matches: &getopts::Matches, explain: bool) -> Res // -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, SourceInfo::new(config)?, &info)?; + let work_info = WorkInfo::remote(config, &info)?; (work_info, version) } else if let Some(path) = matches.opt_str("s") { // -s "local_path": @@ -127,7 +127,7 @@ fn run(config: &cargo::Config, matches: &getopts::Matches, explain: bool) -> Res name: &name, version: &stable_crate.max_version, }; - let work_info = WorkInfo::remote(config, SourceInfo::new(config)?, &info)?; + let work_info = WorkInfo::remote(config, &info)?; (work_info, stable_crate.max_version.clone()) }; @@ -341,33 +341,6 @@ impl<'a> PackageNameAndVersion<'a> { } } -/// A specification of a package source to fetch remote packages from. -pub struct SourceInfo<'a> { - /// The source id to be used. - id: SourceId, - /// The source to be used. - source: Box, -} - -impl<'a> SourceInfo<'a> { - /// Construct a new source info for `crates.io`. - pub fn new(config: &'a cargo::Config) -> Result> { - let source_id = SourceId::crates_io(config)?; - let mut source = source_id.load(config, &HashSet::new())?; - - debug!("source id loaded: {:?}", source_id); - - // Update the index. Without this we would not be able to fetch recent packages if the - // index is not up-to-date. - source.update()?; - - Ok(Self { - id: source_id, - source, - }) - } -} - /// A specification of a package and it's workspace. pub struct WorkInfo<'a> { /// The package to be compiled. @@ -388,25 +361,29 @@ impl<'a> WorkInfo<'a> { /// specified `PackageNameAndVersion` from the `source`. pub fn remote( config: &'a cargo::Config, - source: SourceInfo<'a>, &PackageNameAndVersion { name, version }: &PackageNameAndVersion, ) -> Result> { + let source = { + let source_id = SourceId::crates_io(&config)?; + let mut source = RegistrySource::remote(source_id, &HashSet::new(), config); + + debug!("source id loaded: {:?}", source_id); + + source.update()?; + + Box::new(source) + }; + // TODO: fall back to locally cached package instance, or better yet, search for it // first. - let package_ids = [PackageId::new(name, version, source.id)?]; - debug!("(remote) package id: {:?}", package_ids[0]); - let sources = { - let mut s = SourceMap::new(); - s.insert(source.source); - s - }; + let package_id = PackageId::new(name, version, source.source_id())?; + debug!("(remote) package id: {:?}", package_id); - let package_set = PackageSet::new(&package_ids, sources, config)?; - let package = package_set.get_one(package_ids[0])?; + let package = source.download_now(package_id, config)?; let workspace = Workspace::ephemeral(package.clone(), config, None, false)?; Ok(Self { - package: package.clone(), + package: package, workspace, }) } From 083576b9cd24695fe20079de5f2fa40764aabf92 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 9 Jun 2019 14:28:19 +0000 Subject: [PATCH 472/553] Implemented --compact flag for #61. --- src/bin/cargo_semver.rs | 13 +++++++++++-- src/bin/rust_semverver.rs | 4 +++- src/changes.rs | 19 ++++++++++++++----- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 9eec819c7883b..dd61b5e354c06 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -77,7 +77,7 @@ fn main() { cli::exit_with_error(&config, e); } - if let Err(e) = run(&config, &matches, matches.opt_present("e")) { + if let Err(e) = run(&config, &matches) { cli::exit_with_error(&config, e); } } @@ -86,10 +86,13 @@ fn main() { /// "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, explain: bool) -> Result<()> { +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"); + // 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: @@ -170,6 +173,7 @@ fn run(config: &cargo::Config, matches: &getopts::Matches, explain: bool) -> Res .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_API_GUIDELINES", if matches.opt_present("a") { @@ -237,6 +241,11 @@ mod cli { "no-default-features", "Do not activate the `default` feature", ); + opts.optflag( + "", + "compact", + "Only output the suggested version on stdout for further processing", + ); opts.optopt( "s", "stable-path", diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 831f4cf4a7b71..404925bc0f82a 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -46,6 +46,8 @@ fn main() { let verbose = std::env::var("RUST_SEMVER_VERBOSE") == Ok("true".to_string()); + let compact = + std::env::var("RUST_SEMVER_COMPACT") == Ok("true".to_string()); let api_guidelines = std::env::var("RUST_SEMVER_API_GUIDELINES") == Ok("true".to_string()); let version = if let Ok(ver) = std::env::var("RUST_SEMVER_CRATE_VERSION") { @@ -84,7 +86,7 @@ fn main() { 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); - changes.output(tcx.sess, &version, verbose, api_guidelines); + changes.output(tcx.sess, &version, verbose, compact, api_guidelines); } else { tcx.sess.err("could not find crate old and new crates"); } diff --git a/src/changes.rs b/src/changes.rs index 940ca50b6a22e..69a9eab27e19d 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -879,7 +879,12 @@ impl<'tcx> ChangeSet<'tcx> { } /// Format the contents of a change set for user output. - pub fn output(&self, session: &Session, version: &str, verbose: bool, api_guidelines: bool) { + pub fn output(&self, + session: &Session, + version: &str, + verbose: bool, + compact: bool, + api_guidelines: bool) { if let Ok(mut new_version) = Version::parse(version) { if new_version.major == 0 { new_version.increment_patch(); @@ -891,10 +896,14 @@ impl<'tcx> ChangeSet<'tcx> { } } - println!( - "version bump: {} -> ({}) -> {}", - version, self.max, new_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); } From f9180cbcbdc53d4ca998143f5d54cb0e647133f9 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 9 Jun 2019 14:50:08 +0000 Subject: [PATCH 473/553] Reviewed error explanations. This closes #36. --- src/changes.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/changes.rs b/src/changes.rs index 69a9eab27e19d..aeedd59d228c2 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -344,14 +344,22 @@ user code is guaranteed to use them in a read-only fashion." user code that tries to mutate them will break." } VarianceLoosened => { - "The variance of a type or region parameter in an item loosens iff ." + "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 iff ." + "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 goes -from covariant to contravariant, or vice-versa." + "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 @@ -360,7 +368,7 @@ before." } RegionParameterRemoved => { "Removing a region parameter is a breaking change, because it can break -explicit type annotations, well as prevent region inference working as +explicit type annotations, as well as prevent region inference working as before." } TypeParameterAdded { defaulted: true } => { From bdcc6cfd9d753e757c3378d23d56c953d7c6abde Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 9 Jun 2019 15:07:54 +0000 Subject: [PATCH 474/553] Fixed formatting. --- src/bin/cargo_semver.rs | 5 +---- src/changes.rs | 14 ++++++++------ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index dd61b5e354c06..8c4505ed0f36d 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -96,10 +96,7 @@ fn run(config: &cargo::Config, matches: &getopts::Matches) -> Result<()> { // 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)?, - )? + 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)?)? diff --git a/src/changes.rs b/src/changes.rs index aeedd59d228c2..c7d1daf7d071f 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -887,12 +887,14 @@ impl<'tcx> ChangeSet<'tcx> { } /// 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) { + pub fn output( + &self, + session: &Session, + version: &str, + verbose: bool, + compact: bool, + api_guidelines: bool, + ) { if let Ok(mut new_version) = Version::parse(version) { if new_version.major == 0 { new_version.increment_patch(); From 028161394f6129fb6957a5c84677a460b3fc0f63 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 9 Jun 2019 21:19:19 +0000 Subject: [PATCH 475/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 98fd7e63572f2..c2b588a307fad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.34" +version = "0.1.35" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From ae7ae57be281c7ef0c3fb6e9826c17b1a30880e1 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 10 Jun 2019 00:41:22 +0000 Subject: [PATCH 476/553] Implemented a basic vesion of exported type querying. As requested in #63, this adds a way to list all items in the type namespace of a crate. --- Cargo.toml | 4 ++ src/bin/cargo_semver.rs | 51 +++++++++++++ src/bin/rust_semver_public.rs | 131 ++++++++++++++++++++++++++++++++++ src/bin/rust_semverver.rs | 18 +++-- src/lib.rs | 2 +- src/traverse.rs | 50 ++++++++++--- 6 files changed, 236 insertions(+), 20 deletions(-) create mode 100644 src/bin/rust_semver_public.rs diff --git a/Cargo.toml b/Cargo.toml index c2b588a307fad..2d2dd737a7118 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,10 @@ path = "src/bin/cargo_semver.rs" name = "rust-semverver" path = "src/bin/rust_semverver.rs" +[[bin]] +name = "rust-semver-public" +path = "src/bin/rust_semver_public.rs" + [dependencies] cargo = "0.36" crates-io = "0.24" diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 8c4505ed0f36d..bdeb8b10860bf 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -107,6 +107,52 @@ fn run(config: &cargo::Config, matches: &getopts::Matches) -> Result<()> { }; let name = current.package.name().to_owned(); + 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]); + } + + if !matches.opt_present("no-default-features") { + child.args(&["--cfg", "feature=\"default\""]); + } + + let mut child = child + .arg("-") + .stdin(Stdio::piped()) + .spawn() + .map_err(|e| failure::err_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(failure::err_msg( + "could not pipe to rustc (wtf?)".to_owned(), + )); + } + + let exit_status = child + .wait() + .map_err(|e| failure::err_msg(format!("failed to wait for rustc: {}", e)))?; + + return if exit_status.success() { + Ok(()) + } else { + Err(failure::err_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: @@ -227,6 +273,11 @@ mod cli { "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", diff --git a/src/bin/rust_semver_public.rs b/src/bin/rust_semver_public.rs new file mode 100644 index 0000000000000..cfc06cf5dda4f --- /dev/null +++ b/src/bin/rust_semver_public.rs @@ -0,0 +1,131 @@ +#![feature(rustc_private)] +#![feature(result_map_or_else)] + +extern crate rustc; +extern crate rustc_driver; +extern crate rustc_interface; +extern crate syntax; + +use log::debug; +use rustc::{hir::def_id::*, middle::cstore::ExternCrate}; +use rustc_driver::Callbacks; +use rustc_interface::interface; +use semverver::run_traversal; +use std::{ + path::Path, + process::{exit, Command}, +}; +use syntax::source_map::Pos; + +/// 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(&mut self, compiler: &interface::Compiler) -> bool { + debug!("running rust-semver-public after_analysis callback"); + + compiler.global_ctxt().unwrap().peek_mut().enter(|tcx| { + let krate = tcx + .crates() + .iter() + .flat_map(|crate_num| { + let def_id = DefId { + krate: *crate_num, + index: CRATE_DEF_INDEX, + }; + + match tcx.extern_crate(def_id) { + Some(ExternCrate { + span, direct: true, .. + }) if 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!"); + + false + } + } + + if env::args().any(|a| a == "--version" || a == "-V") { + show_version(); + exit(0); + } + + let sys_root = option_env!("SYSROOT") + .map(String::from) + .or_else(|| env::var("SYSROOT").ok()) + .or_else(|| { + let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); + let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); + home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain))) + }) + .or_else(|| { + Command::new("rustc") + .arg("--print") + .arg("sysroot") + .output() + .ok() + .and_then(|out| String::from_utf8(out.stdout).ok()) + .map(|s| s.trim().to_owned()) + }) + .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); + + // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. + // We're invoking the compiler programmatically, so we ignore this/ + let mut orig_args: Vec = env::args().collect(); + if orig_args.len() <= 1 { + std::process::exit(1); + } + + if Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref()) { + // we still want to be able to invoke it normally though + orig_args.remove(1); + } + + // this conditional check for the --sysroot flag is there so users can call + // `clippy_driver` directly + // without having to pass --sysroot or anything + let args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { + orig_args.clone() + } else { + orig_args + .clone() + .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/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 404925bc0f82a..e75fb4d4fccd4 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -1,7 +1,6 @@ #![feature(rustc_private)] #![feature(result_map_or_else)] -extern crate getopts; extern crate rustc; extern crate rustc_codegen_utils; extern crate rustc_driver; @@ -28,8 +27,7 @@ fn show_version() { /// Main routine. /// -/// Find the sysroot before passing our args to the compiler driver, after registering our custom -/// compiler driver. +/// Find the sysroot before passing our args to the custom compiler driver we register. fn main() { rustc_driver::init_rustc_env_logger(); @@ -45,12 +43,12 @@ fn main() { debug!("running rust-semverver after_analysis callback"); let verbose = - std::env::var("RUST_SEMVER_VERBOSE") == Ok("true".to_string()); + env::var("RUST_SEMVER_VERBOSE") == Ok("true".to_string()); let compact = - std::env::var("RUST_SEMVER_COMPACT") == Ok("true".to_string()); + env::var("RUST_SEMVER_COMPACT") == Ok("true".to_string()); let api_guidelines = - std::env::var("RUST_SEMVER_API_GUIDELINES") == Ok("true".to_string()); - let version = if let Ok(ver) = std::env::var("RUST_SEMVER_CRATE_VERSION") { + 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() @@ -88,7 +86,7 @@ fn main() { let changes = run_analysis(tcx, old_def_id, new_def_id); changes.output(tcx.sess, &version, verbose, compact, api_guidelines); } else { - tcx.sess.err("could not find crate old and new crates"); + tcx.sess.err("could not find `old` and `new` crates"); } }); @@ -98,14 +96,14 @@ fn main() { } } - if std::env::args().any(|a| a == "--version" || a == "-V") { + if env::args().any(|a| a == "--version" || a == "-V") { show_version(); exit(0); } let sys_root = option_env!("SYSROOT") .map(String::from) - .or_else(|| std::env::var("SYSROOT").ok()) + .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")); diff --git a/src/lib.rs b/src/lib.rs index cd88fd8a38df5..2b37843f4671a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,4 +14,4 @@ mod translate; mod traverse; mod typeck; -pub use self::traverse::run_analysis; +pub use self::traverse::{run_analysis, run_traversal}; diff --git a/src/traverse.rs b/src/traverse.rs index c29e69836b9ae..a9441dbe91aaf 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -69,6 +69,47 @@ pub fn run_analysis<'a, 'tcx>( changes } +// Get the visibility of the inner item, given the outer item's visibility. +fn get_vis(outer_vis: Visibility, def: Export) -> Visibility { + if outer_vis == Public { + def.vis + } else { + outer_vis + } +} + +pub fn run_traversal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, 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, Public)); + + // Pull a module from the queue, with its global visibility. + while let Some((new_def_id, 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) { + mod_queue.push_back((n_def_id, n_vis)); + } + }, + Def(n_kind, n_def_id) if n_vis == Public => { + match n_kind { + TyAlias | Struct | Union | Enum | Trait => { + println!("{:?}", n_def_id); + }, + _ => (), + }; + }, + _ => (), + } + } + } +} + // 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. @@ -87,15 +128,6 @@ fn diff_structure<'a, 'tcx>( ) { use rustc::hir::def::DefKind::*; - // Get the visibility of the inner item, given the outer item's visibility. - fn get_vis(outer_vis: Visibility, def: Export) -> Visibility { - if outer_vis == Public { - def.vis - } else { - outer_vis - } - } - let mut visited = HashSet::new(); let mut children = NameMapping::default(); let mut mod_queue = VecDeque::new(); From cc734abfb7e2111a338332def56ab44efa1f5e44 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 10 Jun 2019 11:40:51 +0000 Subject: [PATCH 477/553] Applied rustfmt. --- src/traverse.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/traverse.rs b/src/traverse.rs index a9441dbe91aaf..cf62535854afa 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -95,15 +95,15 @@ pub fn run_traversal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, new: DefId) { if visited.insert(n_def_id) { mod_queue.push_back((n_def_id, n_vis)); } - }, + } Def(n_kind, n_def_id) if n_vis == Public => { match n_kind { - TyAlias | Struct | Union | Enum | Trait => { + TyAlias | Struct | Union | Enum | Trait => { println!("{:?}", n_def_id); - }, + } _ => (), }; - }, + } _ => (), } } From 3d940f359a21b6e0f11d83126cfaf60f942fc4df Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 10 Jun 2019 22:02:38 +0000 Subject: [PATCH 478/553] Polished the type output feature. --- src/bin/rust_semver_public.rs | 7 ++----- src/bin/rust_semverver.rs | 7 ++----- src/traverse.rs | 16 +++++++++++----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/bin/rust_semver_public.rs b/src/bin/rust_semver_public.rs index cfc06cf5dda4f..61ebe44c94b29 100644 --- a/src/bin/rust_semver_public.rs +++ b/src/bin/rust_semver_public.rs @@ -7,7 +7,7 @@ extern crate rustc_interface; extern crate syntax; use log::debug; -use rustc::{hir::def_id::*, middle::cstore::ExternCrate}; +use rustc::middle::cstore::ExternCrate; use rustc_driver::Callbacks; use rustc_interface::interface; use semverver::run_traversal; @@ -45,10 +45,7 @@ fn main() { .crates() .iter() .flat_map(|crate_num| { - let def_id = DefId { - krate: *crate_num, - index: CRATE_DEF_INDEX, - }; + let def_id = crate_num.as_def_id(); match tcx.extern_crate(def_id) { Some(ExternCrate { diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index e75fb4d4fccd4..3ab25fd0523d2 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -10,7 +10,7 @@ extern crate rustc_metadata; extern crate syntax; use log::debug; -use rustc::{hir::def_id::*, middle::cstore::ExternCrate}; +use rustc::middle::cstore::ExternCrate; use rustc_driver::Callbacks; use rustc_interface::interface; use semverver::run_analysis; @@ -64,10 +64,7 @@ fn main() { .crates() .iter() .flat_map(|crate_num| { - let def_id = DefId { - krate: *crate_num, - index: CRATE_DEF_INDEX, - }; + let def_id = crate_num.as_def_id(); match tcx.extern_crate(def_id) { Some(ExternCrate { diff --git a/src/traverse.rs b/src/traverse.rs index cf62535854afa..a7762cb5fec65 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -84,22 +84,28 @@ pub fn run_traversal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, new: DefId) { let mut mod_queue = VecDeque::new(); // Start off with the root module. - mod_queue.push_back((new, Public)); + mod_queue.push_back((new, Vec::new(), Public)); // Pull a module from the queue, with its global visibility. - while let Some((new_def_id, new_vis)) = mod_queue.pop_front() { + 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) { - mod_queue.push_back((n_def_id, n_vis)); + let mut idents = idents.clone(); + idents.push(format!("{}", item.ident)); + + mod_queue.push_back((n_def_id, idents, n_vis)); } } - Def(n_kind, n_def_id) if n_vis == Public => { + Def(n_kind, _) if n_vis == Public => { match n_kind { TyAlias | Struct | Union | Enum | Trait => { - println!("{:?}", n_def_id); + let mut idents = idents.clone(); + idents.push(format!("{}", item.ident)); + + println!("{}", idents.join("::")); } _ => (), }; From 5e754f093f41518de6e8ff61d840972cff9c0eba Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 10 Jun 2019 22:06:00 +0000 Subject: [PATCH 479/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 2d2dd737a7118..a0c619104930c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.35" +version = "0.1.36" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From 76a5ca3970e79a4dba59a5d8fe39e2de2e6305a1 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 14 Jun 2019 12:45:58 +0000 Subject: [PATCH 480/553] Fixed build with newest nightly. --- src/bin/cargo_semver.rs | 5 +--- src/mismatch.rs | 12 +++++----- src/translate.rs | 10 ++++---- src/traverse.rs | 52 +++++++++++++++++++---------------------- src/typeck.rs | 12 +++++----- 5 files changed, 42 insertions(+), 49 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index bdeb8b10860bf..267654f2b8f1d 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -439,10 +439,7 @@ impl<'a> WorkInfo<'a> { let package = source.download_now(package_id, config)?; let workspace = Workspace::ephemeral(package.clone(), config, None, false)?; - Ok(Self { - package: package, - workspace, - }) + Ok(Self { package, workspace }) } /// Obtain the paths to the produced rlib and the dependency output directory. diff --git a/src/mismatch.rs b/src/mismatch.rs index d68cd15d5fe66..a389bfad8977b 100644 --- a/src/mismatch.rs +++ b/src/mismatch.rs @@ -24,9 +24,9 @@ use std::collections::{HashMap, HashSet, VecDeque}; /// 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, 'gcx: 'a + 'tcx, 'tcx: 'a> { +pub struct MismatchRelation<'a, 'gcx: 'tcx, 'tcx> { /// The type context used. - tcx: TyCtxt<'a, 'gcx, 'tcx>, + tcx: TyCtxt<'gcx, 'tcx>, /// The queue of found item pairings to be processed. item_queue: VecDeque<(Res, Res)>, /// The id mapping to use. @@ -37,9 +37,9 @@ pub struct MismatchRelation<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { current_new_types: HashSet>, } -impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> MismatchRelation<'a, 'gcx, 'tcx> { +impl<'a, 'gcx: 'tcx, 'tcx> MismatchRelation<'a, 'gcx, 'tcx> { /// Construct a new mismtach type relation. - pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, id_mapping: &'a mut IdMapping) -> Self { + pub fn new(tcx: TyCtxt<'gcx, 'tcx>, id_mapping: &'a mut IdMapping) -> Self { Self { tcx, item_queue: id_mapping.toplevel_queue(), @@ -100,8 +100,8 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> MismatchRelation<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx, 'tcx> { - fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> TypeRelation<'gcx, 'tcx> for MismatchRelation<'a, 'gcx, 'tcx> { + fn tcx(&self) -> TyCtxt<'gcx, 'tcx> { self.tcx } diff --git a/src/translate.rs b/src/translate.rs index f2a384baa760c..281e2391f95d5 100644 --- a/src/translate.rs +++ b/src/translate.rs @@ -15,9 +15,9 @@ use rustc::{ use std::collections::HashMap; /// The context in which `DefId` translation happens. -pub struct TranslationContext<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> { +pub struct TranslationContext<'a, 'gcx: 'tcx, 'tcx> { /// The type context to use. - tcx: TyCtxt<'a, 'gcx, 'tcx>, + tcx: TyCtxt<'gcx, 'tcx>, /// The id mapping to use. id_mapping: &'a IdMapping, /// Whether to translate type and region parameters. @@ -31,7 +31,7 @@ pub struct TranslationContext<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { /// Construct a translation context translating to the new crate's `DefId`s. pub fn target_new( - tcx: TyCtxt<'a, 'gcx, 'tcx>, + tcx: TyCtxt<'gcx, 'tcx>, id_mapping: &'a IdMapping, translate_params: bool, ) -> TranslationContext<'a, 'gcx, 'tcx> { @@ -46,7 +46,7 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { /// Construct a translation context translating to the old crate's `DefId`s. pub fn target_old( - tcx: TyCtxt<'a, 'gcx, 'tcx>, + tcx: TyCtxt<'gcx, 'tcx>, id_mapping: &'a IdMapping, translate_params: bool, ) -> TranslationContext<'a, 'gcx, 'tcx> { @@ -533,7 +533,7 @@ impl<'a, 'gcx, 'tcx> InferenceCleanupFolder<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceCleanupFolder<'a, 'gcx, 'tcx> { - fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { + fn tcx(&self) -> TyCtxt<'gcx, 'tcx> { self.infcx.tcx } diff --git a/src/traverse.rs b/src/traverse.rs index a7762cb5fec65..3cd51bee30990 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -35,11 +35,7 @@ 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<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - old: DefId, - new: DefId, -) -> ChangeSet<'tcx> { +pub fn run_analysis<'tcx>(tcx: TyCtxt<'tcx, 'tcx>, old: DefId, new: DefId) -> ChangeSet<'tcx> { let mut changes = ChangeSet::default(); let mut id_mapping = IdMapping::new(old.krate, new.krate); @@ -78,7 +74,7 @@ fn get_vis(outer_vis: Visibility, def: Export) -> Visibility { } } -pub fn run_traversal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, new: DefId) { +pub fn run_traversal<'tcx>(tcx: TyCtxt<'tcx, 'tcx>, new: DefId) { use rustc::hir::def::DefKind::*; let mut visited = HashSet::new(); let mut mod_queue = VecDeque::new(); @@ -125,10 +121,10 @@ pub fn run_traversal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, new: DefId) { /// 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<'a, 'tcx>( +fn diff_structure<'tcx>( changes: &mut ChangeSet, id_mapping: &mut IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, + tcx: TyCtxt<'tcx, 'tcx>, old: DefId, new: DefId, ) { @@ -362,7 +358,7 @@ fn diff_structure<'a, 'tcx>( } /// Given two fn items, perform structural checks. -fn diff_fn<'a, 'tcx>(changes: &mut ChangeSet, tcx: TyCtxt<'a, 'tcx, 'tcx>, old: Res, new: Res) { +fn diff_fn<'tcx>(changes: &mut ChangeSet, tcx: TyCtxt<'tcx, 'tcx>, old: Res, new: Res) { let old_def_id = old.def_id(); let new_def_id = new.def_id(); @@ -381,9 +377,9 @@ fn diff_fn<'a, 'tcx>(changes: &mut ChangeSet, tcx: TyCtxt<'a, 'tcx, 'tcx>, old: } /// Given two method items, perform structural checks. -fn diff_method<'a, 'tcx>( +fn diff_method<'tcx>( changes: &mut ChangeSet, - tcx: TyCtxt<'a, 'tcx, 'tcx>, + tcx: TyCtxt<'tcx, 'tcx>, old: AssocItem, new: AssocItem, ) { @@ -562,10 +558,10 @@ fn diff_adts(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, o /// /// This establishes the needed correspondence between non-toplevel items found in the trait /// definition. -fn diff_traits<'a, 'tcx>( +fn diff_traits<'tcx>( changes: &mut ChangeSet, id_mapping: &mut IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, + tcx: TyCtxt<'tcx, 'tcx>, old: DefId, new: DefId, output: bool, @@ -833,10 +829,10 @@ fn diff_generics( // of matching items are compared for changes. /// Given two items, compare their types. -fn diff_types<'a, 'tcx>( +fn diff_types<'tcx>( changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, + tcx: TyCtxt<'tcx, 'tcx>, old: Res, new: Res, ) { @@ -902,10 +898,10 @@ fn diff_types<'a, 'tcx>( } /// Compare two types and their trait bounds, possibly registering the resulting change. -fn cmp_types<'a, 'tcx>( +fn cmp_types<'tcx>( changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, + tcx: TyCtxt<'tcx, 'tcx>, orig_def_id: DefId, target_def_id: DefId, orig: Ty<'tcx>, @@ -955,10 +951,10 @@ fn cmp_types<'a, 'tcx>( } /// Compare the trait bounds of two items, possibly registering the resulting change. -fn cmp_bounds<'a, 'tcx>( +fn cmp_bounds<'tcx>( changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, + tcx: TyCtxt<'tcx, 'tcx>, orig_def_id: DefId, target_def_id: DefId, ) { @@ -988,10 +984,10 @@ fn cmp_bounds<'a, 'tcx>( // their trait bounds and compared for changes, if applicable. /// Compare the inherent implementations of all matching items. -fn diff_inherent_impls<'a, 'tcx>( +fn diff_inherent_impls<'tcx>( changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, + tcx: TyCtxt<'tcx, 'tcx>, ) { debug!("diffing inherent impls"); @@ -1071,8 +1067,8 @@ fn diff_inherent_impls<'a, 'tcx>( // 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<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_def_id: DefId) -> bool { - fn type_visibility<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty) -> Visibility { +fn is_impl_trait_public<'tcx>(tcx: TyCtxt<'tcx, 'tcx>, impl_def_id: DefId) -> bool { + fn type_visibility<'tcx>(tcx: TyCtxt<'tcx, 'tcx>, ty: Ty) -> Visibility { match ty.sty { TyKind::Adt(def, _) => tcx.visibility(def.did), @@ -1112,10 +1108,10 @@ fn is_impl_trait_public<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_def_id: DefI } /// Compare the implementations of all matching traits. -fn diff_trait_impls<'a, 'tcx>( +fn diff_trait_impls<'tcx>( changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, + tcx: TyCtxt<'tcx, 'tcx>, ) { debug!("diffing trait impls"); @@ -1165,10 +1161,10 @@ fn diff_trait_impls<'a, 'tcx>( /// Compare an item pair in two inherent implementations and indicate whether the target one is /// compatible with the original one. -fn match_inherent_impl<'a, 'tcx>( +fn match_inherent_impl<'tcx>( changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, - tcx: TyCtxt<'a, 'tcx, 'tcx>, + tcx: TyCtxt<'tcx, 'tcx>, orig_impl_def_id: DefId, target_impl_def_id: DefId, orig_item: AssocItem, @@ -1294,7 +1290,7 @@ fn match_inherent_impl<'a, 'tcx>( /// Compare two implementations and indicate whether the target one is compatible with the /// original one. fn match_trait_impl<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, + tcx: TyCtxt<'tcx, 'tcx>, trans: &TranslationContext<'a, 'tcx, 'tcx>, orig_def_id: DefId, ) -> bool { diff --git a/src/typeck.rs b/src/typeck.rs index 580813770d40f..00a5a019df41c 100644 --- a/src/typeck.rs +++ b/src/typeck.rs @@ -201,9 +201,9 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { } /// Check for type mismatches in a pair of items. - pub fn check_type_error<'b, 'tcx2>( + pub fn check_type_error<'tcx2>( &self, - lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, + lift_tcx: TyCtxt<'tcx2, 'tcx2>, target_def_id: DefId, target_param_env: ParamEnv<'tcx>, orig: Ty<'tcx>, @@ -258,9 +258,9 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { } /// Check for trait bound mismatches in a pair of items. - pub fn check_bounds_error<'b, 'tcx2>( + pub fn check_bounds_error<'tcx2>( &self, - lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, + lift_tcx: TyCtxt<'tcx2, 'tcx2>, orig_param_env: ParamEnv<'tcx>, target_def_id: DefId, target_substs: SubstsRef<'tcx>, @@ -289,10 +289,10 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { } /// Check the bounds on an item in both directions and register changes found. - pub fn check_bounds_bidirectional<'b, 'tcx2>( + pub fn check_bounds_bidirectional<'tcx2>( &self, changes: &mut ChangeSet<'tcx2>, - lift_tcx: TyCtxt<'b, 'tcx2, 'tcx2>, + lift_tcx: TyCtxt<'tcx2, 'tcx2>, orig_def_id: DefId, target_def_id: DefId, orig_substs: SubstsRef<'tcx>, From 091939bf5f64a0a5d64644d208fa75e9f8107e9b Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 14 Jun 2019 12:47:31 +0000 Subject: [PATCH 481/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index a0c619104930c..c0e63cf370ce9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.36" +version = "0.1.37" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From bdefd588e4ccb67aaa04a37521a8fde91564c92f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 15 Jun 2019 19:38:26 +0000 Subject: [PATCH 482/553] Implemented feature flag support. We now support `--features`, `--all-features` in addition to `--no-default-features`. This closes #91. --- src/bin/cargo_semver.rs | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 267654f2b8f1d..60e99ac522402 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -121,10 +121,6 @@ fn run(config: &cargo::Config, matches: &getopts::Matches) -> Result<()> { child.args(&["--target", &target]); } - if !matches.opt_present("no-default-features") { - child.args(&["--cfg", "feature=\"default\""]); - } - let mut child = child .arg("-") .stdin(Stdio::piped()) @@ -207,10 +203,6 @@ fn run(config: &cargo::Config, matches: &getopts::Matches) -> Result<()> { child.args(&["--target", &target]); } - if !matches.opt_present("no-default-features") { - child.args(&["--cfg", "feature=\"default\""]); - } - let child = child .arg("-") .stdin(Stdio::piped()) @@ -284,6 +276,17 @@ mod cli { "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", @@ -458,9 +461,13 @@ impl<'a> WorkInfo<'a> { if let Some(target) = matches.opt_str("target") { opts.build_config.requested_target = Some(target); } - opts.no_default_features = matches.opt_present("no-default-features"); - // TODO: this is where we could insert feature flag builds (or using the CLI mechanisms) + 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", From 182ad8716808f7b9f31acf9d55cf5d10738c26f0 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 15 Jun 2019 20:05:35 +0000 Subject: [PATCH 483/553] Fixed build with newest nightly. The `TyCtxt` and `InferCtxt` refactoring truly was a blessing. --- src/bin/cargo_semver.rs | 6 +----- src/mismatch.rs | 12 ++++++------ src/translate.rs | 26 +++++++++++++------------- src/traverse.rs | 37 ++++++++++++++++--------------------- src/typeck.rs | 36 ++++++++++++++++++------------------ 5 files changed, 54 insertions(+), 63 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 60e99ac522402..4b44827cd41c0 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -282,11 +282,7 @@ mod cli { "Space-separated list of features to activate", "FEATURES", ); - opts.optflag( - "", - "all-features", - "Activate all available features", - ); + opts.optflag("", "all-features", "Activate all available features"); opts.optflag( "", "no-default-features", diff --git a/src/mismatch.rs b/src/mismatch.rs index a389bfad8977b..01cc4b7116475 100644 --- a/src/mismatch.rs +++ b/src/mismatch.rs @@ -24,9 +24,9 @@ use std::collections::{HashMap, HashSet, VecDeque}; /// 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, 'gcx: 'tcx, 'tcx> { +pub struct MismatchRelation<'a, 'tcx> { /// The type context used. - tcx: TyCtxt<'gcx, 'tcx>, + tcx: TyCtxt<'tcx>, /// The queue of found item pairings to be processed. item_queue: VecDeque<(Res, Res)>, /// The id mapping to use. @@ -37,9 +37,9 @@ pub struct MismatchRelation<'a, 'gcx: 'tcx, 'tcx> { current_new_types: HashSet>, } -impl<'a, 'gcx: 'tcx, 'tcx> MismatchRelation<'a, 'gcx, 'tcx> { +impl<'a, 'tcx> MismatchRelation<'a, 'tcx> { /// Construct a new mismtach type relation. - pub fn new(tcx: TyCtxt<'gcx, 'tcx>, id_mapping: &'a mut IdMapping) -> Self { + pub fn new(tcx: TyCtxt<'tcx>, id_mapping: &'a mut IdMapping) -> Self { Self { tcx, item_queue: id_mapping.toplevel_queue(), @@ -100,8 +100,8 @@ impl<'a, 'gcx: 'tcx, 'tcx> MismatchRelation<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> TypeRelation<'gcx, 'tcx> for MismatchRelation<'a, 'gcx, 'tcx> { - fn tcx(&self) -> TyCtxt<'gcx, 'tcx> { +impl<'a, 'tcx> TypeRelation<'tcx> for MismatchRelation<'a, 'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } diff --git a/src/translate.rs b/src/translate.rs index 281e2391f95d5..8abf0294d5f1f 100644 --- a/src/translate.rs +++ b/src/translate.rs @@ -15,9 +15,9 @@ use rustc::{ use std::collections::HashMap; /// The context in which `DefId` translation happens. -pub struct TranslationContext<'a, 'gcx: 'tcx, 'tcx> { +pub struct TranslationContext<'a, 'tcx> { /// The type context to use. - tcx: TyCtxt<'gcx, 'tcx>, + tcx: TyCtxt<'tcx>, /// The id mapping to use. id_mapping: &'a IdMapping, /// Whether to translate type and region parameters. @@ -28,13 +28,13 @@ pub struct TranslationContext<'a, 'gcx: 'tcx, 'tcx> { translate_orig: fn(&IdMapping, DefId) -> Option, } -impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { +impl<'a, 'tcx> TranslationContext<'a, 'tcx> { /// Construct a translation context translating to the new crate's `DefId`s. pub fn target_new( - tcx: TyCtxt<'gcx, 'tcx>, + tcx: TyCtxt<'tcx>, id_mapping: &'a IdMapping, translate_params: bool, - ) -> TranslationContext<'a, 'gcx, 'tcx> { + ) -> TranslationContext<'a, 'tcx> { TranslationContext { tcx, id_mapping, @@ -46,10 +46,10 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { /// Construct a translation context translating to the old crate's `DefId`s. pub fn target_old( - tcx: TyCtxt<'gcx, 'tcx>, + tcx: TyCtxt<'tcx>, id_mapping: &'a IdMapping, translate_params: bool, - ) -> TranslationContext<'a, 'gcx, 'tcx> { + ) -> TranslationContext<'a, 'tcx> { TranslationContext { tcx, id_mapping, @@ -520,20 +520,20 @@ impl<'a, 'gcx, 'tcx> TranslationContext<'a, 'gcx, 'tcx> { /// /// Used to lift type errors and predicates to wrap them in an error type. #[derive(Clone)] -pub struct InferenceCleanupFolder<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { +pub struct InferenceCleanupFolder<'a, 'tcx: 'a> { /// The inference context used. - infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + infcx: &'a InferCtxt<'a, 'tcx>, } -impl<'a, 'gcx, 'tcx> InferenceCleanupFolder<'a, 'gcx, 'tcx> { +impl<'a, 'tcx> InferenceCleanupFolder<'a, 'tcx> { /// Construct a new folder. - pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self { + pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self { InferenceCleanupFolder { infcx } } } -impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceCleanupFolder<'a, 'gcx, 'tcx> { - fn tcx(&self) -> TyCtxt<'gcx, 'tcx> { +impl<'a, 'tcx> TypeFolder<'tcx> for InferenceCleanupFolder<'a, 'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } diff --git a/src/traverse.rs b/src/traverse.rs index 3cd51bee30990..284089060bd6a 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -35,7 +35,7 @@ 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>(tcx: TyCtxt<'tcx, 'tcx>, old: DefId, new: DefId) -> ChangeSet<'tcx> { +pub fn run_analysis<'tcx>(tcx: TyCtxt<'tcx>, old: DefId, new: DefId) -> ChangeSet<'tcx> { let mut changes = ChangeSet::default(); let mut id_mapping = IdMapping::new(old.krate, new.krate); @@ -74,7 +74,7 @@ fn get_vis(outer_vis: Visibility, def: Export) -> Visibility { } } -pub fn run_traversal<'tcx>(tcx: TyCtxt<'tcx, 'tcx>, new: DefId) { +pub fn run_traversal<'tcx>(tcx: TyCtxt<'tcx>, new: DefId) { use rustc::hir::def::DefKind::*; let mut visited = HashSet::new(); let mut mod_queue = VecDeque::new(); @@ -124,7 +124,7 @@ pub fn run_traversal<'tcx>(tcx: TyCtxt<'tcx, 'tcx>, new: DefId) { fn diff_structure<'tcx>( changes: &mut ChangeSet, id_mapping: &mut IdMapping, - tcx: TyCtxt<'tcx, 'tcx>, + tcx: TyCtxt<'tcx>, old: DefId, new: DefId, ) { @@ -358,7 +358,7 @@ fn diff_structure<'tcx>( } /// Given two fn items, perform structural checks. -fn diff_fn<'tcx>(changes: &mut ChangeSet, tcx: TyCtxt<'tcx, 'tcx>, old: Res, new: Res) { +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(); @@ -377,12 +377,7 @@ fn diff_fn<'tcx>(changes: &mut ChangeSet, tcx: TyCtxt<'tcx, 'tcx>, old: Res, new } /// Given two method items, perform structural checks. -fn diff_method<'tcx>( - changes: &mut ChangeSet, - tcx: TyCtxt<'tcx, 'tcx>, - old: AssocItem, - new: AssocItem, -) { +fn diff_method<'tcx>(changes: &mut ChangeSet, tcx: TyCtxt<'tcx>, old: AssocItem, new: AssocItem) { if old.method_has_self_argument != new.method_has_self_argument { changes.add_change( ChangeType::MethodSelfChanged { @@ -561,7 +556,7 @@ fn diff_adts(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, o fn diff_traits<'tcx>( changes: &mut ChangeSet, id_mapping: &mut IdMapping, - tcx: TyCtxt<'tcx, 'tcx>, + tcx: TyCtxt<'tcx>, old: DefId, new: DefId, output: bool, @@ -832,7 +827,7 @@ fn diff_generics( fn diff_types<'tcx>( changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, - tcx: TyCtxt<'tcx, 'tcx>, + tcx: TyCtxt<'tcx>, old: Res, new: Res, ) { @@ -901,7 +896,7 @@ fn diff_types<'tcx>( fn cmp_types<'tcx>( changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, - tcx: TyCtxt<'tcx, 'tcx>, + tcx: TyCtxt<'tcx>, orig_def_id: DefId, target_def_id: DefId, orig: Ty<'tcx>, @@ -954,7 +949,7 @@ fn cmp_types<'tcx>( fn cmp_bounds<'tcx>( changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, - tcx: TyCtxt<'tcx, 'tcx>, + tcx: TyCtxt<'tcx>, orig_def_id: DefId, target_def_id: DefId, ) { @@ -987,7 +982,7 @@ fn cmp_bounds<'tcx>( fn diff_inherent_impls<'tcx>( changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, - tcx: TyCtxt<'tcx, 'tcx>, + tcx: TyCtxt<'tcx>, ) { debug!("diffing inherent impls"); @@ -1067,8 +1062,8 @@ fn diff_inherent_impls<'tcx>( // 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, 'tcx>, impl_def_id: DefId) -> bool { - fn type_visibility<'tcx>(tcx: TyCtxt<'tcx, 'tcx>, ty: Ty) -> Visibility { +fn is_impl_trait_public<'tcx>(tcx: TyCtxt<'tcx>, impl_def_id: DefId) -> bool { + fn type_visibility<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty) -> Visibility { match ty.sty { TyKind::Adt(def, _) => tcx.visibility(def.did), @@ -1111,7 +1106,7 @@ fn is_impl_trait_public<'tcx>(tcx: TyCtxt<'tcx, 'tcx>, impl_def_id: DefId) -> bo fn diff_trait_impls<'tcx>( changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, - tcx: TyCtxt<'tcx, 'tcx>, + tcx: TyCtxt<'tcx>, ) { debug!("diffing trait impls"); @@ -1164,7 +1159,7 @@ fn diff_trait_impls<'tcx>( fn match_inherent_impl<'tcx>( changes: &mut ChangeSet<'tcx>, id_mapping: &IdMapping, - tcx: TyCtxt<'tcx, 'tcx>, + tcx: TyCtxt<'tcx>, orig_impl_def_id: DefId, target_impl_def_id: DefId, orig_item: AssocItem, @@ -1290,8 +1285,8 @@ fn match_inherent_impl<'tcx>( /// Compare two implementations and indicate whether the target one is compatible with the /// original one. fn match_trait_impl<'a, 'tcx>( - tcx: TyCtxt<'tcx, 'tcx>, - trans: &TranslationContext<'a, 'tcx, 'tcx>, + tcx: TyCtxt<'tcx>, + trans: &TranslationContext<'a, 'tcx>, orig_def_id: DefId, ) -> bool { debug!("matching: {:?}", orig_def_id); diff --git a/src/typeck.rs b/src/typeck.rs index 00a5a019df41c..38de7360fda3f 100644 --- a/src/typeck.rs +++ b/src/typeck.rs @@ -22,18 +22,18 @@ use rustc::{ }; /// The context in which bounds analysis happens. -pub struct BoundContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { +pub struct BoundContext<'a, 'tcx: 'a> { /// The inference context to use. - infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + 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, 'gcx, 'tcx> BoundContext<'a, 'gcx, 'tcx> { +impl<'a, 'tcx> BoundContext<'a, 'tcx> { /// Construct a new bound context. - pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, given_param_env: ParamEnv<'tcx>) -> Self { + pub fn new(infcx: &'a InferCtxt<'a, 'tcx>, given_param_env: ParamEnv<'tcx>) -> Self { BoundContext { infcx, fulfill_cx: FulfillmentContext::new(), @@ -91,25 +91,25 @@ impl<'a, 'gcx, 'tcx> BoundContext<'a, 'gcx, 'tcx> { } /// The context in which types and their bounds can be compared. -pub struct TypeComparisonContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { +pub struct TypeComparisonContext<'a, 'tcx: 'a> { /// The inference context to use. - infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + 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, 'gcx, 'tcx>, + folder: InferenceCleanupFolder<'a, 'tcx>, /// The translation context translating from original to target items. - pub forward_trans: TranslationContext<'a, 'gcx, 'tcx>, + pub forward_trans: TranslationContext<'a, 'tcx>, /// The translation context translating from target to original items. - pub backward_trans: TranslationContext<'a, 'gcx, 'tcx>, + pub backward_trans: TranslationContext<'a, 'tcx>, /// Whether we are checking a trait definition. checking_trait_def: bool, } -impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { +impl<'a, 'tcx> TypeComparisonContext<'a, 'tcx> { /// Construct a new context where the original item is old. pub fn target_new( - infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + infcx: &'a InferCtxt<'a, 'tcx>, id_mapping: &'a IdMapping, checking_trait_def: bool, ) -> Self { @@ -126,7 +126,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { /// Construct a new context where the original item is new. pub fn target_old( - infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + infcx: &'a InferCtxt<'a, 'tcx>, id_mapping: &'a IdMapping, checking_trait_def: bool, ) -> Self { @@ -143,10 +143,10 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { /// Construct a new context given a pair of translation contexts. fn from_trans( - infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + infcx: &'a InferCtxt<'a, 'tcx>, id_mapping: &'a IdMapping, - forward_trans: TranslationContext<'a, 'gcx, 'tcx>, - backward_trans: TranslationContext<'a, 'gcx, 'tcx>, + forward_trans: TranslationContext<'a, 'tcx>, + backward_trans: TranslationContext<'a, 'tcx>, checking_trait_def: bool, ) -> Self { TypeComparisonContext { @@ -203,7 +203,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { /// Check for type mismatches in a pair of items. pub fn check_type_error<'tcx2>( &self, - lift_tcx: TyCtxt<'tcx2, 'tcx2>, + lift_tcx: TyCtxt<'tcx2>, target_def_id: DefId, target_param_env: ParamEnv<'tcx>, orig: Ty<'tcx>, @@ -260,7 +260,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { /// Check for trait bound mismatches in a pair of items. pub fn check_bounds_error<'tcx2>( &self, - lift_tcx: TyCtxt<'tcx2, 'tcx2>, + lift_tcx: TyCtxt<'tcx2>, orig_param_env: ParamEnv<'tcx>, target_def_id: DefId, target_substs: SubstsRef<'tcx>, @@ -292,7 +292,7 @@ impl<'a, 'gcx, 'tcx> TypeComparisonContext<'a, 'gcx, 'tcx> { pub fn check_bounds_bidirectional<'tcx2>( &self, changes: &mut ChangeSet<'tcx2>, - lift_tcx: TyCtxt<'tcx2, 'tcx2>, + lift_tcx: TyCtxt<'tcx2>, orig_def_id: DefId, target_def_id: DefId, orig_substs: SubstsRef<'tcx>, From 602759e76a7ca1bd4f081d3b2147aaadac81aa85 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 15 Jun 2019 20:08:30 +0000 Subject: [PATCH 484/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c0e63cf370ce9..8acb7bb222146 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.37" +version = "0.1.38" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From 0595417c16ffe110cace86855375dceb552d1c00 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 15 Jun 2019 20:43:56 +0000 Subject: [PATCH 485/553] Moved some bits into place to support offline mode. We currently depend on cargo 0.36 (which is the latest version from crates.io), which doesn't have a stable `--offline` flag yet. However, with the new call to `Config::configure`, we will be able to support it properly in the future. With some minor changes to places where we explicitly update the index, #26 could be solved. --- src/bin/cargo_semver.rs | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 4b44827cd41c0..2c7e1b5902dc9 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -45,7 +45,7 @@ fn main() { eprintln!("ERROR: could not initialize logger"); } - let config = match cargo::Config::default() { + let mut config = match cargo::Config::default() { Ok(cfg) => cfg, Err(e) => panic!("can't obtain cargo config: {:?}", e), }; @@ -67,13 +67,28 @@ fn main() { return; } - if matches.opt_present("q") { - config - .shell() - .set_verbosity(cargo::core::shell::Verbosity::Quiet); + if let Err(e) = cli::validate_args(&matches) { + cli::exit_with_error(&config, e); } - if let Err(e) = cli::validate_args(&matches) { + let quiet = if matches.opt_present("q") { + Some(true) + } else { + None + }; + + let config_res = config.configure( + 0, // verbose + quiet, + &None, // color + false, // frozen + false, // locked + // matches.opt_present("offline"), + &None, // target_dir + &[], // unstable_flags + ); + + if let Err(e) = config_res { cli::exit_with_error(&config, e); } @@ -317,6 +332,7 @@ mod cli { "use a `name:version` string as current/new crate", "NAME:VERSION", ); + opts.optflag("", "offline", "Run without accessing the network."); opts.optopt("", "target", "Build for the target triple", ""); opts } @@ -471,7 +487,7 @@ impl<'a> WorkInfo<'a> { ); let mut outdir = env::temp_dir(); - // The filename is randomized to avoid clashes when multiple cargo semver are running. + // The filename is randomized to avoid clashes when multiple cargo-semver instances are running. outdir.push(&format!( "cargo_semver_{}_{}_{}", name, From 160b1aaa74f925a625b481f317908e179e5617a5 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 15 Jun 2019 22:55:17 +0000 Subject: [PATCH 486/553] Implemented something resembling offline mode. This will address #26 once we can merge this into master, until a `cargo` with offline mode hits stable/crates.io this branch can be used instead. --- Cargo.toml | 2 +- src/bin/cargo_semver.rs | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8acb7bb222146..dd9c3d487b980 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ name = "rust-semver-public" path = "src/bin/rust_semver_public.rs" [dependencies] -cargo = "0.36" +cargo = { git = "https://github.com/rust-lang/cargo", branch = "master" } crates-io = "0.24" curl = "0.4.21" env_logger = "0.6" diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 2c7e1b5902dc9..c719bab03f05f 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -83,7 +83,7 @@ fn main() { &None, // color false, // frozen false, // locked - // matches.opt_present("offline"), + matches.opt_present("offline"), &None, // target_dir &[], // unstable_flags ); @@ -441,7 +441,10 @@ impl<'a> WorkInfo<'a> { debug!("source id loaded: {:?}", source_id); - source.update()?; + if !config.offline() { + let _lock = config.acquire_package_cache_lock()?; + source.update()?; + } Box::new(source) }; From 865ac0e72a9d94cb9c54ea169b586a97cb8f9ba1 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 15 Jun 2019 23:22:59 +0000 Subject: [PATCH 487/553] Updated our public facade. --- CONTRIBUTING.md | 38 ++++++++++++++++++++++++++++++++++++++ LICENSE | 2 +- README.md | 42 +++++++++++++++++++++++++++++++++--------- 3 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000000..e5739bc9a0a25 --- /dev/null +++ b/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/LICENSE b/LICENSE index 0a222f044ff56..1220f8e7cac03 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright Inokentiy Babushkin (c) 2017 +Copyright Inokentiy Babushkin (c) 2017-2019 All rights reserved. diff --git a/README.md b/README.md index 9334ef5dae429..8944a0272c4df 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,8 @@ [![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) -This repository is hosting a proof-of-concept implementation of an automatic tool checking -rust library crates for semantic versioning adherence, developed during the Google Summer -of Code 2017. The goal is to provide an automated command akin to `cargo clippy` that -analyzes the current crate's source code for changes compared to the most recent version -on `crates.io`. +`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). @@ -38,7 +35,7 @@ $ rustup update nightly $ cargo +nightly install semverver ``` -You'd also need `cmake` for some dependencies, and a few common libraries (if I you hit +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). @@ -89,13 +86,27 @@ the cargo plugin: ```sh $ cargo semver -h -usage: cargo semver [options] [-- cargo options] +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 -s, --stable-path PATH use local path as stable/old crate -c, --current-path PATH @@ -104,6 +115,8 @@ Options: use a `name:version` string as stable/old crate -C, --current-pkg NAME:VERSION use a `name:version` string as current/new crate + --target + Build for the target triple ``` This means that you can compare any two crates' specified versions, as long as they are @@ -159,5 +172,16 @@ correctly: * additions and removals of inherent impls or methods contained therein * additions and removals of trait impls -Yet, the results presented to the user are merely an approximation of the required -versioning policy, especially at such an early stage of development. +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. From 9f2daf83aca1acbd7897127bc4cf6d41ec671efc Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 19 Jun 2019 16:00:22 +0000 Subject: [PATCH 488/553] Applied clippy lints. --- src/bin/cargo_semver.rs | 2 +- src/traverse.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 2c7e1b5902dc9..189aca90f6a4c 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -475,7 +475,7 @@ impl<'a> WorkInfo<'a> { } if let Some(s) = matches.opt_str("features") { - opts.features = s.split(" ").map(str::to_owned).collect(); + opts.features = s.split(' ').map(str::to_owned).collect(); } opts.all_features = matches.opt_present("all-features"); diff --git a/src/traverse.rs b/src/traverse.rs index 284089060bd6a..45422b0f99aba 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -35,7 +35,7 @@ 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>(tcx: TyCtxt<'tcx>, old: DefId, new: DefId) -> ChangeSet<'tcx> { +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); @@ -74,7 +74,7 @@ fn get_vis(outer_vis: Visibility, def: Export) -> Visibility { } } -pub fn run_traversal<'tcx>(tcx: TyCtxt<'tcx>, new: DefId) { +pub fn run_traversal(tcx: TyCtxt, new: DefId) { use rustc::hir::def::DefKind::*; let mut visited = HashSet::new(); let mut mod_queue = VecDeque::new(); @@ -1063,7 +1063,7 @@ fn diff_inherent_impls<'tcx>( #[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>(tcx: TyCtxt<'tcx>, ty: Ty) -> Visibility { + fn type_visibility(tcx: TyCtxt, ty: Ty) -> Visibility { match ty.sty { TyKind::Adt(def, _) => tcx.visibility(def.did), From 646726d50c7f5ca84dab6a9e9bd577eeb92747c2 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 6 Jul 2019 22:46:21 +0000 Subject: [PATCH 489/553] Switched offline mode implementation to stable cargo. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index dd9c3d487b980..a224d080eabc6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ name = "rust-semver-public" path = "src/bin/rust_semver_public.rs" [dependencies] -cargo = { git = "https://github.com/rust-lang/cargo", branch = "master" } +cargo = "0.37" crates-io = "0.24" curl = "0.4.21" env_logger = "0.6" From 2b27295ff72b173643f58dece74083829974a190 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 6 Jul 2019 22:49:01 +0000 Subject: [PATCH 490/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index a224d080eabc6..c9870115b8bb8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.38" +version = "0.1.39" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From d7522eedb813c138b7c33767c2021cc194b8cbf2 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 10 Jul 2019 17:09:20 +0000 Subject: [PATCH 491/553] Fixed debug logging for our purposes. --- src/bin/rust_semverver.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 3ab25fd0523d2..81c820bcd622e 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -29,7 +29,7 @@ fn show_version() { /// /// Find the sysroot before passing our args to the custom compiler driver we register. fn main() { - rustc_driver::init_rustc_env_logger(); + env_logger::init_from_env("RUSTC_LOG"); debug!("running rust-semverver compiler driver"); exit( From 4bc81904c6ac9179df727c2aa099063cbeb301c6 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 19 Jul 2019 14:06:55 +0000 Subject: [PATCH 492/553] Fixed formatting for new rustfmt. --- src/changes.rs | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/src/changes.rs b/src/changes.rs index c7d1daf7d071f..d0eaaa9429e47 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -430,19 +430,15 @@ 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 + } => "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\"." - } +is classified as \"technically breaking\".", TraitItemAdded { sealed_trait: true, .. - } => { - "Adding a new trait item is a non-breaking change, when user code can't + } => "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." - } +inheriting from an unnamable (crate-local) item.", TraitItemAdded { .. } => // neither defaulted or sealed { @@ -468,30 +464,22 @@ 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 + } => "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." - } +trait implementation or usage.", BoundsLoosened { trait_def: false, .. - } => { - "Loosening the bounds of a lifetime or type parameter in a non-trait + } => "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 +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 +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." - } +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 From c6abc9a35725e3fd5ae8171fbf12f6537a0a4e59 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 21 Jul 2019 20:43:52 +0000 Subject: [PATCH 493/553] Fixed build with newest nightly. --- src/bin/rust_semver_public.rs | 6 +++--- src/bin/rust_semverver.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/bin/rust_semver_public.rs b/src/bin/rust_semver_public.rs index 61ebe44c94b29..08f9e24cb909c 100644 --- a/src/bin/rust_semver_public.rs +++ b/src/bin/rust_semver_public.rs @@ -8,7 +8,7 @@ extern crate syntax; use log::debug; use rustc::middle::cstore::ExternCrate; -use rustc_driver::Callbacks; +use rustc_driver::{Callbacks, Compilation}; use rustc_interface::interface; use semverver::run_traversal; use std::{ @@ -37,7 +37,7 @@ fn main() { struct PubCallbacks; impl Callbacks for PubCallbacks { - fn after_analysis(&mut self, compiler: &interface::Compiler) -> bool { + fn after_analysis(&mut self, compiler: &interface::Compiler) -> Compilation { debug!("running rust-semver-public after_analysis callback"); compiler.global_ctxt().unwrap().peek_mut().enter(|tcx| { @@ -66,7 +66,7 @@ fn main() { debug!("rust-semver-public after_analysis callback finished!"); - false + Compilation::Stop } } diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 81c820bcd622e..593625edbb8a9 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -11,7 +11,7 @@ extern crate syntax; use log::debug; use rustc::middle::cstore::ExternCrate; -use rustc_driver::Callbacks; +use rustc_driver::{Callbacks, Compilation}; use rustc_interface::interface; use semverver::run_analysis; use std::{ @@ -39,7 +39,7 @@ fn main() { struct SemverCallbacks; impl Callbacks for SemverCallbacks { - fn after_analysis(&mut self, compiler: &interface::Compiler) -> bool { + fn after_analysis(&mut self, compiler: &interface::Compiler) -> Compilation { debug!("running rust-semverver after_analysis callback"); let verbose = @@ -89,7 +89,7 @@ fn main() { debug!("rust-semverver after_analysis callback finished!"); - false + Compilation::Stop } } From 19d78da1fb9f4cb526c98d331e92b2a3755671c1 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 21 Jul 2019 20:46:04 +0000 Subject: [PATCH 494/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c9870115b8bb8..ab5dbe7432c5a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.39" +version = "0.1.40" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From 056366b9007ff822b3ba96d7f92d0cf077c6d6b7 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 22 Jul 2019 17:19:34 +0000 Subject: [PATCH 495/553] Implemented a simple JSON output format (without spans). See #108 for details. --- src/bin/cargo_semver.rs | 8 +++ src/bin/rust_semverver.rs | 8 ++- src/changes.rs | 145 +++++++++++++++++++++++++++++++++----- 3 files changed, 142 insertions(+), 19 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index b1cf079c9c0a9..fd93d7f587d81 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -107,6 +107,7 @@ fn run(config: &cargo::Config, matches: &getopts::Matches) -> Result<()> { 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") { @@ -122,6 +123,7 @@ fn run(config: &cargo::Config, matches: &getopts::Matches) -> Result<()> { }; 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)?; @@ -224,6 +226,7 @@ fn run(config: &cargo::Config, matches: &getopts::Matches) -> Result<()> { .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") { @@ -308,6 +311,11 @@ mod cli { "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", diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 593625edbb8a9..f3d20adb23dbc 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -46,6 +46,8 @@ fn main() { 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") { @@ -81,7 +83,11 @@ fn main() { 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); - changes.output(tcx.sess, &version, verbose, compact, api_guidelines); + if json { + changes.output_json(&version); + } else { + changes.output(tcx.sess, &version, verbose, compact, api_guidelines); + } } else { tcx.sess.err("could not find `old` and `new` crates"); } diff --git a/src/changes.rs b/src/changes.rs index d0eaaa9429e47..648bd42ca17f6 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -23,6 +23,9 @@ use std::{ use syntax::symbol::Symbol; use syntax_pos::Span; +use serde::Serialize; +use serde::ser::{Serializer, SerializeStruct}; + /// The categories we use when analyzing changes between crate versions. /// /// These directly correspond to the semantic versioning spec, with the exception that some @@ -31,7 +34,7 @@ use syntax_pos::Span; /// 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)] +#[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, @@ -64,25 +67,52 @@ impl<'a> fmt::Display for ChangeCategory { } } +pub struct RSymbol(pub Symbol); + +impl Serialize for RSymbol { + fn serialize(&self, serializer: S) -> Result + where S: Serializer, + { + serializer.serialize_str(&format!("{}", self.0)) + } +} + /// 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(Symbol), + Symbol(RSymbol), /// A textutal description of the item, used for trait impls. ImplDesc(String), } -impl<'a> fmt::Display for Name { +impl Name { + pub fn symbol(symbol: Symbol) -> Self { + Name::Symbol(RSymbol(symbol)) + } +} + +impl fmt::Display for Name { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Name::Symbol(name) => write!(f, "`{}`", name), + Name::Symbol(ref name) => write!(f, "`{}`", name.0), Name::ImplDesc(ref desc) => write!(f, "`{}`", desc), } } } +impl Serialize for Name { + fn serialize(&self, serializer: S) -> Result + where S: Serializer, + { + match *self { + Name::Symbol(ref name) => serializer.serialize_str(&format!("{}", name.0)), + Name::ImplDesc(ref desc) => serializer.serialize_str(&format!("{}", 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 @@ -90,7 +120,7 @@ impl<'a> fmt::Display for Name { 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: Symbol, + name: RSymbol, /// The definition span of the item. def_span: Span, /// The set of spans of added exports of the item. @@ -103,7 +133,7 @@ impl PathChange { /// Construct a new empty path change record for an item. fn new(name: Symbol, def_span: Span) -> Self { Self { - name, + name: RSymbol(name), def_span, additions: BTreeSet::new(), removals: BTreeSet::new(), @@ -142,7 +172,7 @@ impl PathChange { return; } - let msg = format!("path changes to `{}`", self.name); + let msg = format!("path changes to `{}`", self.name.0); let mut builder = if cat == Breaking { session.struct_span_err(self.def_span, &msg) } else { @@ -189,6 +219,18 @@ impl Ord for PathChange { } } +impl Serialize for PathChange { + fn serialize(&self, serializer: S) -> Result + where S: Serializer, + { + let mut state = serializer.serialize_struct("PathChange", 3)?; + state.serialize_field("name", &self.name)?; + state.serialize_field("additions", &!self.additions.is_empty())?; + state.serialize_field("removals", &!self.removals.is_empty())?; + state.end() + } +} + /// The types of changes we identify between items present in both crate versions. #[derive(Clone, Debug)] pub enum ChangeType<'tcx> { @@ -605,6 +647,14 @@ impl<'a> fmt::Display for ChangeType<'a> { } } +impl<'tcx> Serialize for ChangeType<'tcx> { + fn serialize(&self, serializer: S) -> Result + where S: Serializer, + { + serializer.serialize_str(&format!("{}", self)) + } +} + /// A change record of an item present in both crate versions. /// /// NB: `Eq` and `Ord` instances are constucted to only regard the *new* span of the associated @@ -758,6 +808,21 @@ impl<'tcx> Ord for Change<'tcx> { } } +impl<'tcx> Serialize for Change<'tcx> { + fn serialize(&self, serializer: S) -> Result + where S: Serializer, + { + let mut state = serializer.serialize_struct("Change", 3)?; + state.serialize_field("name", &self.name)?; + state.serialize_field("max_category", &self.max)?; + + let changes: Vec<_> = self.changes.iter().map(|(t, _)| t.clone()).collect(); + + state.serialize_field("changes", &changes)?; + state.end() + } +} + /// The total set of changes recorded for two crate versions. #[derive(Default)] pub struct ChangeSet<'tcx> { @@ -811,7 +876,7 @@ impl<'tcx> ChangeSet<'tcx> { new_span: Span, output: bool, ) { - let change = Change::new(Name::Symbol(name), new_span, output); + 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); @@ -874,15 +939,7 @@ impl<'tcx> ChangeSet<'tcx> { .map_or(false, Change::trait_item_breaking) } - /// 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, - ) { + fn get_new_version(&self, version: &str) -> Option { if let Ok(mut new_version) = Version::parse(version) { if new_version.major == 0 { new_version.increment_patch(); @@ -894,6 +951,41 @@ impl<'tcx> ChangeSet<'tcx> { } } + Some(format!("{}", new_version)) + } else { + None + } + } + + pub fn output_json(&self, version: &str) { + #[derive(Serialize)] + struct Output<'a, 'tcx> { + old_version: String, + new_version: String, + changes: &'a ChangeSet<'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: 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 { @@ -932,6 +1024,23 @@ impl<'tcx> ChangeSet<'tcx> { } } +impl<'tcx> Serialize for ChangeSet<'tcx> { + fn serialize(&self, serializer: S) -> Result + where S: Serializer, + { + let mut state = serializer.serialize_struct("ChangeSet", 3)?; + + let path_changes: Vec<_> = self.path_changes.values().collect(); + state.serialize_field("path_changes", &path_changes)?; + + let changes: Vec<_> = self.changes.values().filter(|c| c.output && !c.changes.is_empty()).collect(); + state.serialize_field("changes", &changes)?; + + state.serialize_field("max_category", &self.max)?; + state.end() + } +} + #[cfg(test)] pub mod tests { pub use super::*; @@ -1150,7 +1259,7 @@ pub mod tests { changes: Vec<(ChangeType_, Option)>, ) -> Change<'a> { let mut interner = Interner::default(); - let mut change = Change::new(Name::Symbol(interner.intern("test")), s1, output); + 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())); From 1eeca026ef80dbd597002fea43e7a393ffa359e4 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 22 Jul 2019 17:31:56 +0000 Subject: [PATCH 496/553] Fixed formatting. --- src/changes.rs | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/changes.rs b/src/changes.rs index 648bd42ca17f6..4701b4e5cae4c 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -23,8 +23,8 @@ use std::{ use syntax::symbol::Symbol; use syntax_pos::Span; +use serde::ser::{SerializeStruct, Serializer}; use serde::Serialize; -use serde::ser::{Serializer, SerializeStruct}; /// The categories we use when analyzing changes between crate versions. /// @@ -71,7 +71,8 @@ pub struct RSymbol(pub Symbol); impl Serialize for RSymbol { fn serialize(&self, serializer: S) -> Result - where S: Serializer, + where + S: Serializer, { serializer.serialize_str(&format!("{}", self.0)) } @@ -104,7 +105,8 @@ impl fmt::Display for Name { impl Serialize for Name { fn serialize(&self, serializer: S) -> Result - where S: Serializer, + where + S: Serializer, { match *self { Name::Symbol(ref name) => serializer.serialize_str(&format!("{}", name.0)), @@ -221,7 +223,8 @@ impl Ord for PathChange { impl Serialize for PathChange { fn serialize(&self, serializer: S) -> Result - where S: Serializer, + where + S: Serializer, { let mut state = serializer.serialize_struct("PathChange", 3)?; state.serialize_field("name", &self.name)?; @@ -649,7 +652,8 @@ impl<'a> fmt::Display for ChangeType<'a> { impl<'tcx> Serialize for ChangeType<'tcx> { fn serialize(&self, serializer: S) -> Result - where S: Serializer, + where + S: Serializer, { serializer.serialize_str(&format!("{}", self)) } @@ -810,7 +814,8 @@ impl<'tcx> Ord for Change<'tcx> { impl<'tcx> Serialize for Change<'tcx> { fn serialize(&self, serializer: S) -> Result - where S: Serializer, + where + S: Serializer, { let mut state = serializer.serialize_struct("Change", 3)?; state.serialize_field("name", &self.name)?; @@ -965,7 +970,9 @@ impl<'tcx> ChangeSet<'tcx> { changes: &'a ChangeSet<'tcx>, } - let new_version = self.get_new_version(version).unwrap_or_else(|| "parse error".to_owned()); + let new_version = self + .get_new_version(version) + .unwrap_or_else(|| "parse error".to_owned()); let output = Output { old_version: version.to_owned(), @@ -1026,14 +1033,19 @@ impl<'tcx> ChangeSet<'tcx> { impl<'tcx> Serialize for ChangeSet<'tcx> { fn serialize(&self, serializer: S) -> Result - where S: Serializer, + where + S: Serializer, { let mut state = serializer.serialize_struct("ChangeSet", 3)?; let path_changes: Vec<_> = self.path_changes.values().collect(); state.serialize_field("path_changes", &path_changes)?; - let changes: Vec<_> = self.changes.values().filter(|c| c.output && !c.changes.is_empty()).collect(); + let changes: Vec<_> = self + .changes + .values() + .filter(|c| c.output && !c.changes.is_empty()) + .collect(); state.serialize_field("changes", &changes)?; state.serialize_field("max_category", &self.max)?; From d5ca08e111353c41ac980455e1a263571e96ae9c Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 22 Jul 2019 17:45:20 +0000 Subject: [PATCH 497/553] Fixed a clippy warning. --- src/changes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes.rs b/src/changes.rs index 4701b4e5cae4c..469715730d476 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -110,7 +110,7 @@ impl Serialize for Name { { match *self { Name::Symbol(ref name) => serializer.serialize_str(&format!("{}", name.0)), - Name::ImplDesc(ref desc) => serializer.serialize_str(&format!("{}", desc)), + Name::ImplDesc(ref desc) => serializer.serialize_str(desc), } } } From eb8a45da2230ab26db7060e2849b4da2973935f2 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 24 Jul 2019 14:19:52 +0000 Subject: [PATCH 498/553] Implemented span serialization for JSON output. --- src/bin/rust_semverver.rs | 2 +- src/changes.rs | 111 +++++++++++++++++++++++++++++++------- 2 files changed, 92 insertions(+), 21 deletions(-) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index f3d20adb23dbc..a95a5dfabee46 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -84,7 +84,7 @@ fn main() { debug!("running semver analysis"); let changes = run_analysis(tcx, old_def_id, new_def_id); if json { - changes.output_json(&version); + changes.output_json(tcx.sess, &version); } else { changes.output(tcx.sess, &version, verbose, compact, api_guidelines); } diff --git a/src/changes.rs b/src/changes.rs index 469715730d476..52b2c460a0205 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -21,9 +21,9 @@ use std::{ fmt, }; use syntax::symbol::Symbol; -use syntax_pos::Span; +use syntax_pos::{FileName, Span}; -use serde::ser::{SerializeStruct, Serializer}; +use serde::ser::{SerializeSeq, SerializeStruct, Serializer}; use serde::Serialize; /// The categories we use when analyzing changes between crate versions. @@ -78,6 +78,33 @@ impl Serialize for RSymbol { } } +struct RSpan<'a>(&'a Session, &'a Span); + +impl<'a> Serialize for RSpan<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let lo = self.0.source_map().lookup_char_pos(self.1.lo()); + let hi = self.0.source_map().lookup_char_pos(self.1.hi()); + + assert!(lo.file.name == hi.file.name); + let file_name = if let &FileName::Real(ref p) = &lo.file.name { + format!("{}", p.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. @@ -221,15 +248,25 @@ impl Ord for PathChange { } } -impl Serialize for PathChange { +struct RPathChange<'a>(&'a Session, &'a PathChange); + +impl<'a> Serialize for RPathChange<'a> { fn serialize(&self, serializer: S) -> Result where S: Serializer, { - let mut state = serializer.serialize_struct("PathChange", 3)?; - state.serialize_field("name", &self.name)?; - state.serialize_field("additions", &!self.additions.is_empty())?; - state.serialize_field("removals", &!self.removals.is_empty())?; + 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() } } @@ -812,16 +849,24 @@ impl<'tcx> Ord for Change<'tcx> { } } -impl<'tcx> Serialize for Change<'tcx> { +struct RChange<'a, 'tcx>(&'a Session, &'a Change<'tcx>); + +impl<'a, 'tcx> Serialize for RChange<'a, 'tcx> { fn serialize(&self, serializer: S) -> Result where S: Serializer, { - let mut state = serializer.serialize_struct("Change", 3)?; - state.serialize_field("name", &self.name)?; - state.serialize_field("max_category", &self.max)?; + 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.changes.iter().map(|(t, _)| t.clone()).collect(); + 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() @@ -962,12 +1007,12 @@ impl<'tcx> ChangeSet<'tcx> { } } - pub fn output_json(&self, version: &str) { + pub fn output_json(&self, session: &Session, version: &str) { #[derive(Serialize)] struct Output<'a, 'tcx> { old_version: String, new_version: String, - changes: &'a ChangeSet<'tcx>, + changes: RChangeSet<'a, 'tcx>, } let new_version = self @@ -977,7 +1022,7 @@ impl<'tcx> ChangeSet<'tcx> { let output = Output { old_version: version.to_owned(), new_version, - changes: self, + changes: RChangeSet(session, self), }; println!("{}", serde_json::to_string(&output).unwrap()); @@ -1031,24 +1076,50 @@ impl<'tcx> ChangeSet<'tcx> { } } -impl<'tcx> Serialize for ChangeSet<'tcx> { +struct RPathChanges<'a>(&'a Session, Vec<&'a PathChange>); + +impl<'a> Serialize for RPathChanges<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut seq = serializer.serialize_seq(Some(self.1.len()))?; + + for e in &self.1 { + seq.serialize_element(&RPathChange(self.0, &e))?; + } + + seq.end() + } +} + +struct RChangeSet<'a, 'tcx>(&'a Session, &'a ChangeSet<'tcx>); + +impl<'a, 'tcx> Serialize for RChangeSet<'a, 'tcx> { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut state = serializer.serialize_struct("ChangeSet", 3)?; - let path_changes: Vec<_> = self.path_changes.values().collect(); - state.serialize_field("path_changes", &path_changes)?; + 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(|c| c.output && !c.changes.is_empty()) + .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.max)?; + state.serialize_field("max_category", &self.1.max)?; state.end() } } From 22513327ac5a64b0d8292d729c12f0cc823b7a9c Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 24 Jul 2019 15:11:04 +0000 Subject: [PATCH 499/553] Added docs for the JSON output mode. --- README.md | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/README.md b/README.md index 8944a0272c4df..d0f4712922ec7 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,8 @@ Options: 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 @@ -142,6 +144,92 @@ cargo semver | tee semver_out Make sure you do the above with access to a nightly toolchain. Check your CI provider's documentation on how to do that. +### JSON output + +By passing the `-j` flag, all output on standard out is formatted as a machine-readable +JSON blob. This can be useful for integration with other tools, and always generates all +possible output (ignoring other output-related flags). The output format is defined as +follows: + +The top level object contains the keys `old_version`, `new_version` and `changes`. The +former two hold a version number in the format `major.minor.patch`, the latter an object +describing changes between the crate versions, which contains two arrays in the keys +`path_changes` and `changes`. + +The `path_changes` array contains objects describing item additions and removals, which +have the following keys: + +* `name`: The name of the item. +* `def_span`: An object describing the location of the item in one of the crates. +* `additions`: An array of spans that describe locations where the item has been added. +* `removals`: An array of spans that describe locations where the item has been removed. + +An example object might look like this: + +```json +{ + "name": "NFT_META_CGROUP", + "def_span": { + "file": "/path/to/libc-0.2.48/src/unix/notbsd/linux/other/mod.rs", + "line_lo": 776, + "line_hi": 776, + "col_lo": 0, + "col_hi": 40 + }, + "additions": [ + { + "file": "/path/to/libc-0.2.48/src/lib.rs", + "line_lo": 195, + "line_hi": 195, + "col_lo": 16, + "col_hi": 23 + } + ], + "removals": [] +} +``` + + +The `changes` array contains objects describing all other changes, which have the +following keys: + +* `name`: The name of the item +* `max_category`: the most severe change category for this item, as a string. + * Possible values are `Patch`, `NonBreaking`, `TechnicallyBreaking`, and `Breaking`. +* `new_span`: an object describing the location of the item in the new crate (see example). +* `changes`: an array of 2-element sequences containing an error message and an optional + sub-span (`null` if none is present) + +An example object might look like this: + +```json +{ + "name": " as new::prelude::Stream>", + "max_category": "TechnicallyBreaking", + "new_span": { + "file": "/path/to/tokio-0.1.17/src/util/enumerate.rs", + "line_lo": 46, + "line_hi": 63, + "col_lo": 0, + "col_hi": 1 + }, + "changes": [ + [ + "trait impl generalized or newly added", + null + ] + ] +} +``` + +For reference, all objects describing spans have the same keys: + +* `file`: A file name. +* `line_lo`: The line the span starts on. +* `line_hi`: The line the span ends on. +* `col_lo`: The column the span starts on. +* `col_hi`: The column the span ends on. + ## Functionality The guideline used to implement semver compatibility is the [API evolution From 91a1d916a1a6e22324fd47e2feebaf1bdda50eae Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 27 Jul 2019 12:54:03 +0000 Subject: [PATCH 500/553] Cope with missing rustfmt from nightly. --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 80fa7b412617e..31a3db609a983 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,8 +22,10 @@ matrix: # Tools: - name: "rustfmt" - install: rustup component add rustfmt-preview - script: cargo fmt --all -- --check + script: | + if rustup component add rustfmt-preview; then + cargo fmt --all -- --check + fi - name: "clippy" script: | if rustup component add clippy-preview; then From c8d2849517be3bd918d0aa7c91f7fd9273ac9541 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 9 Aug 2019 21:12:17 +0000 Subject: [PATCH 501/553] Fixed build with newest nightly. --- src/mapping.rs | 6 +++--- src/mismatch.rs | 5 +++++ src/traverse.rs | 4 +--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/mapping.rs b/src/mapping.rs index 092dca2c695d9..a4d1bcfc864de 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -323,13 +323,13 @@ impl NameMapping { Enum | Variant | Trait | - Existential | TyAlias | ForeignTy | TraitAlias | // TODO: will need some handling later on AssocTy | - AssocExistential | - TyParam => Some(&mut self.type_map), + TyParam | + OpaqueTy | + AssocOpaqueTy => Some(&mut self.type_map), Fn | Const | ConstParam | diff --git a/src/mismatch.rs b/src/mismatch.rs index 01cc4b7116475..bf185a775eee6 100644 --- a/src/mismatch.rs +++ b/src/mismatch.rs @@ -12,6 +12,7 @@ use rustc::{ self, relate::{Relate, RelateResult, TypeRelation}, subst::SubstsRef, + ParamEnv, Ty, TyCtxt, Visibility::Public, }, @@ -105,6 +106,10 @@ impl<'a, 'tcx> TypeRelation<'tcx> for MismatchRelation<'a, 'tcx> { self.tcx } + fn param_env(&self) -> ParamEnv<'tcx> { + ParamEnv::empty() + } + fn tag(&self) -> &'static str { "Mismatch" } diff --git a/src/traverse.rs b/src/traverse.rs index 45422b0f99aba..d7b02bb01027b 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -239,9 +239,7 @@ fn diff_structure<'tcx>( | (Macro(_), Macro(_)) | (TraitAlias, TraitAlias) | (ForeignTy, ForeignTy) - | (ConstParam, ConstParam) - | (AssocExistential, AssocExistential) - | (Existential, Existential) => {} + | (ConstParam, ConstParam) => {} // statics are subject to mutability comparison (Static, Static) => { let old_mut = tcx.is_mutable_static(o_def_id); From 6d3a8f6a34e2a36c1d0fb589446f457df7d9cecf Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 9 Aug 2019 21:16:09 +0000 Subject: [PATCH 502/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ab5dbe7432c5a..fff3047f428b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.40" +version = "0.1.41" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From 9894b9c75adf805054282c5e329f4896b452818d Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 9 Aug 2019 21:21:09 +0000 Subject: [PATCH 503/553] Cleanup: clippy + rustfmt. --- src/changes.rs | 2 +- src/mismatch.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/changes.rs b/src/changes.rs index 52b2c460a0205..fe2881a1a4617 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -89,7 +89,7 @@ impl<'a> Serialize for RSpan<'a> { 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 p) = &lo.file.name { + let file_name = if let FileName::Real(ref p) = lo.file.name { format!("{}", p.display()) } else { "no file name".to_owned() diff --git a/src/mismatch.rs b/src/mismatch.rs index bf185a775eee6..fdde62845b77a 100644 --- a/src/mismatch.rs +++ b/src/mismatch.rs @@ -12,8 +12,7 @@ use rustc::{ self, relate::{Relate, RelateResult, TypeRelation}, subst::SubstsRef, - ParamEnv, - Ty, TyCtxt, + ParamEnv, Ty, TyCtxt, Visibility::Public, }, }; From 7be5099c192b40dd1cdac46d1ebd0cfafa5e655d Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 9 Aug 2019 22:13:23 +0000 Subject: [PATCH 504/553] Fixed some clippy warnings that didn't appear locally. --- src/changes.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/changes.rs b/src/changes.rs index fe2881a1a4617..db76f415b7920 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -117,15 +117,15 @@ pub enum Name { impl Name { pub fn symbol(symbol: Symbol) -> Self { - Name::Symbol(RSymbol(symbol)) + Self::Symbol(RSymbol(symbol)) } } impl fmt::Display for Name { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Name::Symbol(ref name) => write!(f, "`{}`", name.0), - Name::ImplDesc(ref desc) => write!(f, "`{}`", desc), + Self::Symbol(ref name) => write!(f, "`{}`", name.0), + Self::ImplDesc(ref desc) => write!(f, "`{}`", desc), } } } @@ -136,8 +136,8 @@ impl Serialize for Name { S: Serializer, { match *self { - Name::Symbol(ref name) => serializer.serialize_str(&format!("{}", name.0)), - Name::ImplDesc(ref desc) => serializer.serialize_str(desc), + Self::Symbol(ref name) => serializer.serialize_str(&format!("{}", name.0)), + Self::ImplDesc(ref desc) => serializer.serialize_str(desc), } } } From 674aca7fdfc72e72ad5858226bd0756e8220216f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 23 Aug 2019 00:17:53 +0000 Subject: [PATCH 505/553] Fixed build with newest nightly. --- src/changes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes.rs b/src/changes.rs index db76f415b7920..41df39783d9b8 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -1144,7 +1144,7 @@ pub mod tests { impl Span_ { pub fn inner(self) -> Span { - Span::new(BytePos(self.0), BytePos(self.1), SyntaxContext::empty()) + Span::new(BytePos(self.0), BytePos(self.1), SyntaxContext::root()) } } From ff5706534dd13801a036b266e05bd692fb37dae6 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 23 Aug 2019 00:19:37 +0000 Subject: [PATCH 506/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index fff3047f428b9..885276da0cf5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.41" +version = "0.1.42" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From d104e53ee25a89b9a1ee0e93440d4476ac81e800 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 9 Sep 2019 19:26:40 +0000 Subject: [PATCH 507/553] Fixed build on newest nightly. --- src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 2b37843f4671a..639d5a829c7a4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,3 @@ -#![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] #![allow(clippy::similar_names)] #![allow(clippy::single_match_else)] From f02043c217c3f49b55c4bf858fc53888511c94af Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 9 Sep 2019 19:28:35 +0000 Subject: [PATCH 508/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 885276da0cf5c..76094e3fc2d29 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.42" +version = "0.1.43" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From c8b8aefa97a158792a508b330b56a44c6b2bacac Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 18 Sep 2019 00:18:31 +0000 Subject: [PATCH 509/553] Fixed #109. The bug in question was caused by incorrect traversal of the `rustc::ty::Generics` datastructure, causing index-out-of-bound errors. --- src/changes.rs | 36 ++++-- src/traverse.rs | 34 ++++-- tests/full.rs | 1 + tests/full_cases/rmpv-0.4.0-0.4.1.linux | 111 ++++++++++++++++++ tests/full_cases/rmpv-0.4.0-0.4.1.osx | 111 ++++++++++++++++++ .../full_cases/rmpv-0.4.0-0.4.1.windows_msvc | 111 ++++++++++++++++++ 6 files changed, 385 insertions(+), 19 deletions(-) create mode 100644 tests/full_cases/rmpv-0.4.0-0.4.1.linux create mode 100644 tests/full_cases/rmpv-0.4.0-0.4.1.osx create mode 100644 tests/full_cases/rmpv-0.4.0-0.4.1.windows_msvc diff --git a/src/changes.rs b/src/changes.rs index 41df39783d9b8..d741e2d2df22d 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -512,15 +512,19 @@ 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 + } => { + "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\".", +is classified as \"technically breaking\"." + } TraitItemAdded { sealed_trait: true, .. - } => "Adding a new trait item is a non-breaking change, when user code can't + } => { + "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.", +inheriting from an unnamable (crate-local) item." + } TraitItemAdded { .. } => // neither defaulted or sealed { @@ -546,22 +550,30 @@ 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 + } => { + "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.", +trait implementation or usage." + } BoundsLoosened { trait_def: false, .. - } => "Loosening the bounds of a lifetime or type parameter in a non-trait + } => { + "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 +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 +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.", +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 diff --git a/src/traverse.rs b/src/traverse.rs index d7b02bb01027b..0aa71f2f49f09 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -718,10 +718,26 @@ fn diff_generics( 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), - get_region_from_params(new_gen, i), + 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. @@ -743,11 +759,15 @@ fn diff_generics( } } - for i in 0..max(old_count.types, new_count.types) { - match ( - get_type_from_params(old_gen, old_count.lifetimes + i), - get_type_from_params(new_gen, new_count.lifetimes + i), - ) { + 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)) = ( diff --git a/tests/full.rs b/tests/full.rs index bf7e453a8ae22..467962ecb08f9 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -176,6 +176,7 @@ mod full { // 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"); diff --git a/tests/full_cases/rmpv-0.4.0-0.4.1.linux b/tests/full_cases/rmpv-0.4.0-0.4.1.linux new file mode 100644 index 0000000000000..29a6aefddcfb6 --- /dev/null +++ b/tests/full_cases/rmpv-0.4.0-0.4.1.linux @@ -0,0 +1,111 @@ +version bump: 0.4.0 -> (breaking) -> 0.4.1 +error: breaking changes in `>` + --> rmpv-0.4.0/src/decode/mod.rs:60:1 + | +60 | / impl From for Error { +61 | | fn from(err: MarkerReadError) -> Error { +62 | | Error::InvalidMarkerRead(err.0) +63 | | } +64 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `>` + --> rmpv-0.4.0/src/decode/mod.rs:66:1 + | +66 | / impl From for Error { +67 | | fn from(err: ValueReadError) -> Error { +68 | | match err { +69 | | ValueReadError::InvalidMarkerRead(err) => Error::InvalidMarkerRead(err), +... | +75 | | } +76 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `write_value` + --> rmpv-0.4.1/src/encode/value.rs:15:1 + | +15 | / pub fn write_value(wr: &mut W, val: &Value) -> Result<(), Error> +16 | | where W: Write +17 | | { +18 | | match *val { +... | +69 | | Ok(()) +70 | | } + | |_^ + | + = warning: type error: expected enum `old::encode::Error`, found enum `new::encode::Error` (breaking) + +error: breaking changes in `write_value_ref` + --> rmpv-0.4.1/src/encode/value_ref.rs:27:1 + | +27 | / pub fn write_value_ref(wr: &mut W, val: &ValueRef) -> Result<(), Error> +28 | | where W: Write +29 | | { +30 | | match *val { +... | +81 | | Ok(()) +82 | | } + | |_^ + | + = warning: type error: expected enum `old::encode::Error`, found enum `new::encode::Error` (breaking) + +warning: technically breaking changes in `as_ref` + --> rmpv-0.4.1/src/lib.rs:253:5 + | +253 | / pub fn as_ref(&self) -> Utf8StringRef { +254 | | match self.s { +255 | | Ok(ref s) => Utf8StringRef { s: Ok(s.as_str()) }, +256 | | Err((ref buf, err)) => Utf8StringRef { s: Err((&buf[..], err)) }, +257 | | } +258 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in `as_ref` + --> rmpv-0.4.1/src/lib.rs:448:5 + | +448 | / pub fn as_ref(&self) -> ValueRef { +449 | | match self { +450 | | &Value::Nil => ValueRef::Nil, +451 | | &Value::Boolean(val) => ValueRef::Boolean(val), +... | +464 | | } +465 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in `>` + --> rmpv-0.4.1/src/decode/mod.rs:60:1 + | +60 | / impl From for Error { +61 | | fn from(err: MarkerReadError) -> Error { +62 | | Error::InvalidMarkerRead(err.0) +63 | | } +64 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> rmpv-0.4.1/src/decode/mod.rs:66:1 + | +66 | / impl From for Error { +67 | | fn from(err: ValueReadError) -> Error { +68 | | match err { +69 | | ValueReadError::InvalidMarkerRead(err) => Error::InvalidMarkerRead(err), +... | +75 | | } +76 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +error: aborting due to 4 previous errors + +error: rustc-semverver errored diff --git a/tests/full_cases/rmpv-0.4.0-0.4.1.osx b/tests/full_cases/rmpv-0.4.0-0.4.1.osx new file mode 100644 index 0000000000000..29a6aefddcfb6 --- /dev/null +++ b/tests/full_cases/rmpv-0.4.0-0.4.1.osx @@ -0,0 +1,111 @@ +version bump: 0.4.0 -> (breaking) -> 0.4.1 +error: breaking changes in `>` + --> rmpv-0.4.0/src/decode/mod.rs:60:1 + | +60 | / impl From for Error { +61 | | fn from(err: MarkerReadError) -> Error { +62 | | Error::InvalidMarkerRead(err.0) +63 | | } +64 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `>` + --> rmpv-0.4.0/src/decode/mod.rs:66:1 + | +66 | / impl From for Error { +67 | | fn from(err: ValueReadError) -> Error { +68 | | match err { +69 | | ValueReadError::InvalidMarkerRead(err) => Error::InvalidMarkerRead(err), +... | +75 | | } +76 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `write_value` + --> rmpv-0.4.1/src/encode/value.rs:15:1 + | +15 | / pub fn write_value(wr: &mut W, val: &Value) -> Result<(), Error> +16 | | where W: Write +17 | | { +18 | | match *val { +... | +69 | | Ok(()) +70 | | } + | |_^ + | + = warning: type error: expected enum `old::encode::Error`, found enum `new::encode::Error` (breaking) + +error: breaking changes in `write_value_ref` + --> rmpv-0.4.1/src/encode/value_ref.rs:27:1 + | +27 | / pub fn write_value_ref(wr: &mut W, val: &ValueRef) -> Result<(), Error> +28 | | where W: Write +29 | | { +30 | | match *val { +... | +81 | | Ok(()) +82 | | } + | |_^ + | + = warning: type error: expected enum `old::encode::Error`, found enum `new::encode::Error` (breaking) + +warning: technically breaking changes in `as_ref` + --> rmpv-0.4.1/src/lib.rs:253:5 + | +253 | / pub fn as_ref(&self) -> Utf8StringRef { +254 | | match self.s { +255 | | Ok(ref s) => Utf8StringRef { s: Ok(s.as_str()) }, +256 | | Err((ref buf, err)) => Utf8StringRef { s: Err((&buf[..], err)) }, +257 | | } +258 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in `as_ref` + --> rmpv-0.4.1/src/lib.rs:448:5 + | +448 | / pub fn as_ref(&self) -> ValueRef { +449 | | match self { +450 | | &Value::Nil => ValueRef::Nil, +451 | | &Value::Boolean(val) => ValueRef::Boolean(val), +... | +464 | | } +465 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in `>` + --> rmpv-0.4.1/src/decode/mod.rs:60:1 + | +60 | / impl From for Error { +61 | | fn from(err: MarkerReadError) -> Error { +62 | | Error::InvalidMarkerRead(err.0) +63 | | } +64 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> rmpv-0.4.1/src/decode/mod.rs:66:1 + | +66 | / impl From for Error { +67 | | fn from(err: ValueReadError) -> Error { +68 | | match err { +69 | | ValueReadError::InvalidMarkerRead(err) => Error::InvalidMarkerRead(err), +... | +75 | | } +76 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +error: aborting due to 4 previous errors + +error: rustc-semverver errored diff --git a/tests/full_cases/rmpv-0.4.0-0.4.1.windows_msvc b/tests/full_cases/rmpv-0.4.0-0.4.1.windows_msvc new file mode 100644 index 0000000000000..29a6aefddcfb6 --- /dev/null +++ b/tests/full_cases/rmpv-0.4.0-0.4.1.windows_msvc @@ -0,0 +1,111 @@ +version bump: 0.4.0 -> (breaking) -> 0.4.1 +error: breaking changes in `>` + --> rmpv-0.4.0/src/decode/mod.rs:60:1 + | +60 | / impl From for Error { +61 | | fn from(err: MarkerReadError) -> Error { +62 | | Error::InvalidMarkerRead(err.0) +63 | | } +64 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `>` + --> rmpv-0.4.0/src/decode/mod.rs:66:1 + | +66 | / impl From for Error { +67 | | fn from(err: ValueReadError) -> Error { +68 | | match err { +69 | | ValueReadError::InvalidMarkerRead(err) => Error::InvalidMarkerRead(err), +... | +75 | | } +76 | | } + | |_^ + | + = warning: trait impl specialized or removed (breaking) + +error: breaking changes in `write_value` + --> rmpv-0.4.1/src/encode/value.rs:15:1 + | +15 | / pub fn write_value(wr: &mut W, val: &Value) -> Result<(), Error> +16 | | where W: Write +17 | | { +18 | | match *val { +... | +69 | | Ok(()) +70 | | } + | |_^ + | + = warning: type error: expected enum `old::encode::Error`, found enum `new::encode::Error` (breaking) + +error: breaking changes in `write_value_ref` + --> rmpv-0.4.1/src/encode/value_ref.rs:27:1 + | +27 | / pub fn write_value_ref(wr: &mut W, val: &ValueRef) -> Result<(), Error> +28 | | where W: Write +29 | | { +30 | | match *val { +... | +81 | | Ok(()) +82 | | } + | |_^ + | + = warning: type error: expected enum `old::encode::Error`, found enum `new::encode::Error` (breaking) + +warning: technically breaking changes in `as_ref` + --> rmpv-0.4.1/src/lib.rs:253:5 + | +253 | / pub fn as_ref(&self) -> Utf8StringRef { +254 | | match self.s { +255 | | Ok(ref s) => Utf8StringRef { s: Ok(s.as_str()) }, +256 | | Err((ref buf, err)) => Utf8StringRef { s: Err((&buf[..], err)) }, +257 | | } +258 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in `as_ref` + --> rmpv-0.4.1/src/lib.rs:448:5 + | +448 | / pub fn as_ref(&self) -> ValueRef { +449 | | match self { +450 | | &Value::Nil => ValueRef::Nil, +451 | | &Value::Boolean(val) => ValueRef::Boolean(val), +... | +464 | | } +465 | | } + | |_____^ + | + = note: added item in inherent impl (technically breaking) + +warning: technically breaking changes in `>` + --> rmpv-0.4.1/src/decode/mod.rs:60:1 + | +60 | / impl From for Error { +61 | | fn from(err: MarkerReadError) -> Error { +62 | | Error::InvalidMarkerRead(err.0) +63 | | } +64 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +warning: technically breaking changes in `>` + --> rmpv-0.4.1/src/decode/mod.rs:66:1 + | +66 | / impl From for Error { +67 | | fn from(err: ValueReadError) -> Error { +68 | | match err { +69 | | ValueReadError::InvalidMarkerRead(err) => Error::InvalidMarkerRead(err), +... | +75 | | } +76 | | } + | |_^ + | + = note: trait impl generalized or newly added (technically breaking) + +error: aborting due to 4 previous errors + +error: rustc-semverver errored From eeaabc6e009260f9b312032750929b916c408800 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 18 Sep 2019 00:21:11 +0000 Subject: [PATCH 510/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 76094e3fc2d29..8ebe53ed4c363 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.43" +version = "0.1.44" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From cad2a60b56e4d6f8464e6ab4e5c397e5d6479bba Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 18 Sep 2019 00:37:50 +0000 Subject: [PATCH 511/553] Applied rustfmt. --- src/traverse.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/traverse.rs b/src/traverse.rs index 0aa71f2f49f09..338ea80833889 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -759,12 +759,17 @@ fn diff_generics( } } - for i in 0 .. max(old_count.types, new_count.types) { + 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)) + ( + 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)) + ( + get_type_from_params(old_gen, old_count.lifetimes + i), + get_type_from_params(new_gen, new_count.lifetimes + i), + ) }; match pair { From 9608fcfc4f07e212da9258cd67c92ea489924940 Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Sat, 12 Oct 2019 00:39:46 +0100 Subject: [PATCH 512/553] Fix compilation for the latest nightly. --- Cargo.toml | 10 +++++----- src/bin/rust_semver_public.rs | 5 +---- src/bin/rust_semverver.rs | 7 ++----- src/mismatch.rs | 4 ++-- src/translate.rs | 22 +++++++++++----------- src/traverse.rs | 6 +++--- src/typeck.rs | 6 +++--- tests/full.rs | 10 ---------- 8 files changed, 27 insertions(+), 43 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8ebe53ed4c363..9759a586d34fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,17 +27,17 @@ name = "rust-semver-public" path = "src/bin/rust_semver_public.rs" [dependencies] -cargo = "0.37" -crates-io = "0.24" +cargo = "0.39" +crates-io = "0.27" curl = "0.4.21" -env_logger = "0.6" +env_logger = "0.7" failure = "0.1" log = "0.4" -rand = "0.6" +rand = "0.7" semver = "0.9" serde = "1.0.84" serde_derive = "1.0.84" serde_json = "1.0.34" [dev-dependencies] -quickcheck = "0.7" +quickcheck = "0.9" diff --git a/src/bin/rust_semver_public.rs b/src/bin/rust_semver_public.rs index 08f9e24cb909c..4f57034950671 100644 --- a/src/bin/rust_semver_public.rs +++ b/src/bin/rust_semver_public.rs @@ -7,7 +7,6 @@ extern crate rustc_interface; extern crate syntax; use log::debug; -use rustc::middle::cstore::ExternCrate; use rustc_driver::{Callbacks, Compilation}; use rustc_interface::interface; use semverver::run_traversal; @@ -48,9 +47,7 @@ fn main() { let def_id = crate_num.as_def_id(); match tcx.extern_crate(def_id) { - Some(ExternCrate { - span, direct: true, .. - }) if span.data().lo.to_usize() > 0 => Some(def_id), + Some(extern_crate) if extern_crate.is_direct() && extern_crate.span.data().lo.to_usize() > 0 => Some(def_id), _ => None, } }) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index a95a5dfabee46..4621a2a1f7502 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -10,7 +10,6 @@ extern crate rustc_metadata; extern crate syntax; use log::debug; -use rustc::middle::cstore::ExternCrate; use rustc_driver::{Callbacks, Compilation}; use rustc_interface::interface; use semverver::run_analysis; @@ -69,10 +68,8 @@ fn main() { let def_id = crate_num.as_def_id(); match tcx.extern_crate(def_id) { - Some(ExternCrate { - span, direct: true, .. - }) if span.data().lo.to_usize() > 0 => - Some((span.data().lo.to_usize(), 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, } }) diff --git a/src/mismatch.rs b/src/mismatch.rs index fdde62845b77a..2e557e94565bd 100644 --- a/src/mismatch.rs +++ b/src/mismatch.rs @@ -87,7 +87,7 @@ impl<'a, 'tcx> MismatchRelation<'a, 'tcx> { /// 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::ty::subst::UnpackedKind::*; + use rustc::ty::subst::GenericArgKind::*; for (a, b) in a_substs.iter().zip(b_substs) { match (a.unpack(), b.unpack()) { @@ -142,7 +142,7 @@ impl<'a, 'tcx> TypeRelation<'tcx> for MismatchRelation<'a, 'tcx> { self.current_new_types.insert(b); debug!("tys: mismatch relation: a: {:?}, b: {:?}", a, b); - let matching = match (&a.sty, &b.sty) { + 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)?; diff --git a/src/translate.rs b/src/translate.rs index 8abf0294d5f1f..5eea689146456 100644 --- a/src/translate.rs +++ b/src/translate.rs @@ -8,7 +8,7 @@ use rustc::{ infer::InferCtxt, ty::{ fold::{BottomUpFolder, TypeFoldable, TypeFolder}, - subst::{InternalSubsts, Kind, SubstsRef}, + subst::{InternalSubsts, GenericArg, SubstsRef}, GenericParamDefKind, ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt, }, }; @@ -103,7 +103,7 @@ impl<'a, 'tcx> TranslationContext<'a, 'tcx> { orig_def_id: DefId, orig_substs: SubstsRef<'tcx>, ) -> Option<(DefId, SubstsRef<'tcx>)> { - use rustc::ty::subst::UnpackedKind; + use rustc::ty::subst::GenericArgKind; use rustc::ty::ReEarlyBound; use std::cell::Cell; @@ -119,10 +119,10 @@ impl<'a, 'tcx> TranslationContext<'a, 'tcx> { let target_substs = InternalSubsts::for_item(self.tcx, target_def_id, |def, _| match def.kind { - GenericParamDefKind::Lifetime => Kind::from(if !success.get() { + GenericParamDefKind::Lifetime => GenericArg::from(if !success.get() { self.tcx .mk_region(ReEarlyBound(def.to_early_bound_region_data())) - } else if let Some(UnpackedKind::Lifetime(region)) = + } else if let Some(GenericArgKind::Lifetime(region)) = orig_substs.get(def.index as usize).map(|k| k.unpack()) { self.translate_region(region) @@ -134,15 +134,15 @@ impl<'a, 'tcx> TranslationContext<'a, 'tcx> { GenericParamDefKind::Type { .. } => { if !success.get() { self.tcx.mk_param_from_def(def) - } else if let Some(UnpackedKind::Type(type_)) = + } else if let Some(GenericArgKind::Type(type_)) = orig_substs.get(def.index as usize).map(|k| k.unpack()) { - self.translate(index_map, &Kind::from(type_)) + self.translate(index_map, &GenericArg::from(type_)) } else if self .id_mapping .is_non_mapped_defaulted_type_param(def.def_id) { - Kind::from(self.tcx.type_of(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 { @@ -171,7 +171,7 @@ impl<'a, 'tcx> TranslationContext<'a, 'tcx> { orig.fold_with(&mut BottomUpFolder { tcx: self.tcx, ty_op: |ty| { - match ty.sty { + match ty.kind { TyKind::Adt(&AdtDef { ref did, .. }, substs) if self.needs_translation(*did) => { @@ -293,14 +293,14 @@ impl<'a, 'tcx> TranslationContext<'a, 'tcx> { // `Self` is special let orig_def_id = index_map[¶m.index]; if self.needs_translation(orig_def_id) { - use rustc::ty::subst::UnpackedKind; + use rustc::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() { - UnpackedKind::Type(param_t) => param_t, + GenericArgKind::Type(param_t) => param_t, _ => unreachable!(), } } else { @@ -542,7 +542,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for InferenceCleanupFolder<'a, 'tcx> { use rustc::ty::TypeAndMut; let t1 = ty.super_fold_with(self); - match t1.sty { + match t1.kind { TyKind::Ref(region, ty, mutbl) if region.needs_infer() => { let ty_and_mut = TypeAndMut { ty, mutbl }; self.infcx diff --git a/src/traverse.rs b/src/traverse.rs index 338ea80833889..1ef076169fa81 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -560,7 +560,7 @@ fn diff_traits<'tcx>( output: bool, ) { use rustc::hir::Unsafety::Unsafe; - use rustc::ty::subst::UnpackedKind::Type; + use rustc::ty::subst::GenericArgKind::Type; use rustc::ty::{ParamTy, Predicate, TyS}; debug!( @@ -590,7 +590,7 @@ fn diff_traits<'tcx>( if id_mapping.is_private_trait(trait_ref.def_id) && trait_ref.substs.len() == 1 { if let Type(&TyS { - sty: TyKind::Param(ParamTy { index: 0, .. }), + kind: TyKind::Param(ParamTy { index: 0, .. }), .. }) = trait_ref.substs[0].unpack() { @@ -1087,7 +1087,7 @@ fn diff_inherent_impls<'tcx>( #[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.sty { + match ty.kind { TyKind::Adt(def, _) => tcx.visibility(def.did), TyKind::Array(t, _) diff --git a/src/typeck.rs b/src/typeck.rs index 38de7360fda3f..ad170e7f61267 100644 --- a/src/typeck.rs +++ b/src/typeck.rs @@ -16,7 +16,7 @@ use rustc::{ ty::{ error::TypeError, fold::TypeFoldable, - subst::{InternalSubsts, Kind, SubstsRef}, + subst::{InternalSubsts, GenericArg, SubstsRef}, GenericParamDefKind, ParamEnv, Predicate, TraitRef, Ty, TyCtxt, }, }; @@ -181,7 +181,7 @@ impl<'a, 'tcx> TypeComparisonContext<'a, 'tcx> { use rustc::ty::ReEarlyBound; InternalSubsts::for_item(self.infcx.tcx, target_def_id, |def, _| match def.kind { - GenericParamDefKind::Lifetime => Kind::from( + GenericParamDefKind::Lifetime => GenericArg::from( self.infcx .tcx .mk_region(ReEarlyBound(def.to_early_bound_region_data())), @@ -191,7 +191,7 @@ impl<'a, 'tcx> TypeComparisonContext<'a, 'tcx> { .id_mapping .is_non_mapped_defaulted_type_param(def.def_id) { - Kind::from(self.infcx.tcx.type_of(def.def_id)) + GenericArg::from(self.infcx.tcx.type_of(def.def_id)) } else { self.infcx.tcx.mk_param_from_def(def) } diff --git a/tests/full.rs b/tests/full.rs index 467962ecb08f9..a09266a172e69 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -10,16 +10,6 @@ mod full { }; fn test_full(crate_name: &str, old_version: &str, new_version: &str, expected_result: bool) { - // Full test are not working on windows. See issue #105. - /* if std::env::var_os("CI").is_some() && cfg!(all(target_os = "windows", target_env = "msvc")) - { - eprintln!( - "Skipping full test of crate {} ({} -> {}) on windows. See issue #105.", - crate_name, old_version, new_version - ); - return; - } */ - // 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::>(); From 607af5d1f802ba7240e0da725fdd1f954a59a023 Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Sat, 12 Oct 2019 00:40:41 +0100 Subject: [PATCH 513/553] Ran rustfmt. --- src/translate.rs | 2 +- src/typeck.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/translate.rs b/src/translate.rs index 5eea689146456..802a694e7143d 100644 --- a/src/translate.rs +++ b/src/translate.rs @@ -8,7 +8,7 @@ use rustc::{ infer::InferCtxt, ty::{ fold::{BottomUpFolder, TypeFoldable, TypeFolder}, - subst::{InternalSubsts, GenericArg, SubstsRef}, + subst::{GenericArg, InternalSubsts, SubstsRef}, GenericParamDefKind, ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt, }, }; diff --git a/src/typeck.rs b/src/typeck.rs index ad170e7f61267..bd501c0b0bd1d 100644 --- a/src/typeck.rs +++ b/src/typeck.rs @@ -16,7 +16,7 @@ use rustc::{ ty::{ error::TypeError, fold::TypeFoldable, - subst::{InternalSubsts, GenericArg, SubstsRef}, + subst::{GenericArg, InternalSubsts, SubstsRef}, GenericParamDefKind, ParamEnv, Predicate, TraitRef, Ty, TyCtxt, }, }; From 599601039e14072bcd5a65603f62749e495ff193 Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Sat, 12 Oct 2019 00:44:42 +0100 Subject: [PATCH 514/553] Fix test output (presentation only). --- tests/cases/addition_path/stdout | 35 ++++++++++++------------- tests/cases/mix/stdout | 45 ++++++++++++++++---------------- tests/cases/removal_path/stdout | 35 ++++++++++++------------- 3 files changed, 56 insertions(+), 59 deletions(-) diff --git a/tests/cases/addition_path/stdout b/tests/cases/addition_path/stdout index 18e595034b2e0..b39c6cffea55b 100644 --- a/tests/cases/addition_path/stdout +++ b/tests/cases/addition_path/stdout @@ -1,25 +1,25 @@ 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; - | ^^^^^^^^^^^^^^^ - | + --> 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::*; - | ^^^^ + --> 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; - | ^^^^^^ + --> 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; - | ^^^^^^^^^^^^ + --> addition_path/new.rs:13:9 + | +13 | pub use self::a::Abc; + | ^^^^^^^^^^^^ warning: path changes to `d` --> addition_path/new.rs:15:1 @@ -30,4 +30,3 @@ warning: path changes to `d` | |_^ | = note: added definition (technically breaking) - diff --git a/tests/cases/mix/stdout b/tests/cases/mix/stdout index 38fcc5e565209..9d5774e5985fe 100644 --- a/tests/cases/mix/stdout +++ b/tests/cases/mix/stdout @@ -16,33 +16,32 @@ error: breaking changes in `Def` = warning: item kind changed (breaking) error: path changes to `Abc` - --> mix/new.rs:2:5 - | -2 | pub enum 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; - | ^^^^^^^^^^^^ + --> 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; - | ^^^^^^ + --> mix/new.rs:7:13 + | +7 | pub use a::Abc; + | ^^^^^^ warning: path changes to `Def` - --> mix/new.rs:3:5 - | -3 | pub struct 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; - | ^^^^^^^^^^^^ + --> mix/new.rs:10:9 + | +10 | pub use self::a::Def; + | ^^^^^^^^^^^^ error: aborting due to 3 previous errors - diff --git a/tests/cases/removal_path/stdout b/tests/cases/removal_path/stdout index ea1d1711caf30..1e47844de748e 100644 --- a/tests/cases/removal_path/stdout +++ b/tests/cases/removal_path/stdout @@ -1,25 +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; - | ^^^^^^^^^^^^^^^ - | + --> removal_path/new.rs:2:5 + | +2 | pub struct Abc; + | ^^^^^^^^^^^^^^^ + | warning: removed path (breaking) - --> removal_path/old.rs:6:13 - | -6 | pub use a::*; - | ^^^^ + --> 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; - | ^^^^^^ + --> 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; - | ^^^^^^^^^^^^ + --> removal_path/old.rs:13:9 + | +13 | pub use self::a::Abc; + | ^^^^^^^^^^^^ error: aborting due to previous error - From 09b0d7feaab030ed3122ae92cce9616e5cbc2a12 Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Sat, 12 Oct 2019 01:25:36 +0100 Subject: [PATCH 515/553] Fix clippy errors. --- src/bin/cargo_semver.rs | 3 ++- src/bin/rust_semver_public.rs | 3 +-- src/bin/rust_semverver.rs | 3 +-- src/lib.rs | 1 + 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index fd93d7f587d81..5ad7b83ecd15b 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -1,5 +1,6 @@ #![feature(rustc_private)] #![feature(set_stdio)] +#![allow(clippy::too_many_lines)] extern crate curl; extern crate getopts; @@ -54,7 +55,7 @@ fn main() { let matches = match cli::parse_args(&opts) { Ok(m) => m, - Err(f) => cli::exit_with_error(&config, f.to_owned().into()), + Err(f) => cli::exit_with_error(&config, f.into()), }; if matches.opt_present("h") { diff --git a/src/bin/rust_semver_public.rs b/src/bin/rust_semver_public.rs index 4f57034950671..bb5dbb2bcd54a 100644 --- a/src/bin/rust_semver_public.rs +++ b/src/bin/rust_semver_public.rs @@ -107,10 +107,9 @@ fn main() { // `clippy_driver` directly // without having to pass --sysroot or anything let args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { - orig_args.clone() + orig_args } else { orig_args - .clone() .into_iter() .chain(Some("--sysroot".to_owned())) .chain(Some(sys_root)) diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index 4621a2a1f7502..cd4c16bcd4994 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -136,10 +136,9 @@ fn main() { // `clippy_driver` directly // without having to pass --sysroot or anything let args: Vec = if orig_args.iter().any(|s| s == "--sysroot") { - orig_args.clone() + orig_args } else { orig_args - .clone() .into_iter() .chain(Some("--sysroot".to_owned())) .chain(Some(sys_root)) diff --git a/src/lib.rs b/src/lib.rs index 639d5a829c7a4..b054e4400d6fe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ #![feature(rustc_private)] #![allow(clippy::similar_names)] #![allow(clippy::single_match_else)] +#![allow(clippy::too_many_lines)] #![deny(warnings)] extern crate rustc; extern crate syntax; From f44f87302ff1c77e5a13f08d355bf6827df439d9 Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Sat, 12 Oct 2019 10:58:55 +0100 Subject: [PATCH 516/553] Do not fail the build if we can't compile the previously published semverver. --- ci/run.sh | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/ci/run.sh b/ci/run.sh index 27e664c88d188..4f8b3b68bb51d 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -31,17 +31,25 @@ cp target/debug/cargo-semver ~/rust/cargo/bin cp target/debug/rust-semverver ~/rust/cargo/bin # become semververver -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 +# +# 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 "versioning mismatch" - cat semver_out - echo "versioning mismatch" - exit 1 + echo 'Failed to check semver-compliance of semverver. Failed to compiled previous version.' >&2 fi From 4225eadc745778fa73eb496b81146246f3927945 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 2 Nov 2019 18:28:03 +0100 Subject: [PATCH 517/553] Rustup to rustc 1.40.0-nightly (87cbf0a54 2019-11-01) --- rust-toolchain | 1 + src/mapping.rs | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 rust-toolchain diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 0000000000000..bf867e0ae5b6c --- /dev/null +++ b/rust-toolchain @@ -0,0 +1 @@ +nightly diff --git a/src/mapping.rs b/src/mapping.rs index a4d1bcfc864de..174d88fa7b372 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -12,10 +12,11 @@ use rustc::{ ty::{AssocKind, GenericParamDef, GenericParamDefKind}, }; use std::collections::{BTreeSet, HashMap, HashSet, VecDeque}; +use std::hash::{Hash, Hasher}; use syntax::ast::Name; /// A description of an item found in an inherent impl. -#[derive(Debug, PartialEq, Eq, Hash)] +#[derive(Debug, PartialEq)] pub struct InherentEntry { /// The parent item's `DefId`. pub parent_def_id: DefId, @@ -25,6 +26,36 @@ pub struct InherentEntry { pub name: Name, } +impl Eq for InherentEntry {} + +fn assert_impl_eq() {} + +#[allow(dead_code)] +fn assert_inherent_entry_members_impl_eq() { + assert_impl_eq::(); + + // FIXME derive Eq again once AssocKind impls Eq again. + // assert_impl_eq::(); + + assert_impl_eq::(); +} + +impl Hash for InherentEntry { + fn hash(&self, hasher: &mut H) { + self.parent_def_id.hash(hasher); + + // FIXME derive Hash again once AssocKind derives Hash again. + match self.kind { + AssocKind::Const => 0u8.hash(hasher), + AssocKind::Method => 1u8.hash(hasher), + AssocKind::OpaqueTy => 2u8.hash(hasher), + AssocKind::Type => 3u8.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)>; From d0e3a3f86c9f63f614ac24db8cab866d926493d2 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 3 Nov 2019 16:07:12 +0100 Subject: [PATCH 518/553] Add rustc-dev component on CI --- ci/run.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci/run.sh b/ci/run.sh index 4f8b3b68bb51d..711acf56ce820 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -5,6 +5,8 @@ set -ex export RUST_BACKTRACE=full #export RUST_TEST_NOCAPTURE=1 +rustup component add rustc-dev + cargo build cargo test --verbose -- --nocapture From 6c7227d7c0a5f465bdd8e575df8e0250bc0cea90 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 3 Nov 2019 16:08:41 +0100 Subject: [PATCH 519/553] Update README for rustc-dev component requirement --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index d0f4712922ec7..32f1810a16311 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ If you are already using Rust nightly and have successfully installed tools like ```sh $ rustup update nightly +$ rustup component add rustc-dev --toolchain nightly $ cargo +nightly install semverver ``` @@ -43,6 +44,7 @@ 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 ``` From 023f943f38a98be7b8b2e864836c70a62f338c18 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 7 Nov 2019 22:47:54 +0000 Subject: [PATCH 520/553] Updated tests. --- tests/cases/infer_regress/stdout | 4 ++-- tests/cases/inherent_impls/stdout | 2 +- tests/cases/regions/stdout | 2 +- tests/cases/ty_alias/new.rs | 2 +- tests/cases/ty_alias/stdout | 4 ++-- tests/full_cases/log-0.3.4-0.3.8.linux | 4 ++-- tests/full_cases/log-0.3.4-0.3.8.osx | 4 ++-- tests/full_cases/log-0.3.4-0.3.8.windows_msvc | 4 ++-- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/cases/infer_regress/stdout b/tests/cases/infer_regress/stdout index 8c629f58474ba..c00ccce27d9df 100644 --- a/tests/cases/infer_regress/stdout +++ b/tests/cases/infer_regress/stdout @@ -6,7 +6,7 @@ error: breaking changes in `abc` | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: variance loosened (non-breaking) - = warning: type error: expected type parameter, found () (breaking) + = warning: type error: expected type parameter `A`, found () (breaking) error: breaking changes in `Abc` --> infer_regress/new.rs:3:1 @@ -14,7 +14,7 @@ error: breaking changes in `Abc` 3 | pub struct Abc(pub A, pub ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected type parameter, found () (breaking) + = warning: type error: expected type parameter `A`, found () (breaking) error: aborting due to 2 previous errors diff --git a/tests/cases/inherent_impls/stdout b/tests/cases/inherent_impls/stdout index ff6a2f58140cb..6a35e7bf1b7cd 100644 --- a/tests/cases/inherent_impls/stdout +++ b/tests/cases/inherent_impls/stdout @@ -7,7 +7,7 @@ error: breaking changes in `ghi` 16 | | } | |_____^ | - = warning: type error: expected type parameter, found u8 (breaking) + = warning: type error: expected type parameter `A`, found u8 (breaking) error: breaking changes in `def` --> inherent_impls/old.rs:26:5 diff --git a/tests/cases/regions/stdout b/tests/cases/regions/stdout index 668dc986f8914..8cc7205a1fbba 100644 --- a/tests/cases/regions/stdout +++ b/tests/cases/regions/stdout @@ -13,7 +13,7 @@ error: breaking changes in `E` 11 | pub type E = T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected associated type, found type parameter (breaking) + = warning: type error: expected associated type, found type parameter `T` (breaking) error: breaking changes in `abc` --> regions/new.rs:13:1 diff --git a/tests/cases/ty_alias/new.rs b/tests/cases/ty_alias/new.rs index bd9a08714ebd5..be5430c0828e2 100644 --- a/tests/cases/ty_alias/new.rs +++ b/tests/cases/ty_alias/new.rs @@ -6,4 +6,4 @@ pub type C = T; pub type D<'a, T, U=Box> = (&'a T, U); pub type E<'a, T, U> = (&'a T, U); pub type F<'a> = &'a u8; -pub type G<'a> = (&'a u8); +pub type G<'a> = &'a u8; diff --git a/tests/cases/ty_alias/stdout b/tests/cases/ty_alias/stdout index d2abe29b0b8ff..ddafe341a97df 100644 --- a/tests/cases/ty_alias/stdout +++ b/tests/cases/ty_alias/stdout @@ -51,8 +51,8 @@ error: breaking changes in `F` error: breaking changes in `G` --> ty_alias/new.rs:9:1 | -9 | pub type G<'a> = (&'a u8); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +9 | pub type G<'a> = &'a u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: type parameter removed (breaking) diff --git a/tests/full_cases/log-0.3.4-0.3.8.linux b/tests/full_cases/log-0.3.4-0.3.8.linux index 08d8a82f0f695..19aebffb5f7d7 100644 --- a/tests/full_cases/log-0.3.4-0.3.8.linux +++ b/tests/full_cases/log-0.3.4-0.3.8.linux @@ -31,7 +31,7 @@ warning: technically breaking changes in ` as std::cmp::Eq> | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in ` as std::cmp::PartialEq>` +warning: technically breaking changes in ` as std::marker::StructuralPartialEq>` --> log-0.3.8/src/lib.rs:552:14 | 552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] @@ -79,7 +79,7 @@ warning: technically breaking changes in `` | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in `` +warning: technically breaking changes in `` --> log-0.3.8/src/lib.rs:604:34 | 604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] diff --git a/tests/full_cases/log-0.3.4-0.3.8.osx b/tests/full_cases/log-0.3.4-0.3.8.osx index 08d8a82f0f695..19aebffb5f7d7 100644 --- a/tests/full_cases/log-0.3.4-0.3.8.osx +++ b/tests/full_cases/log-0.3.4-0.3.8.osx @@ -31,7 +31,7 @@ warning: technically breaking changes in ` as std::cmp::Eq> | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in ` as std::cmp::PartialEq>` +warning: technically breaking changes in ` as std::marker::StructuralPartialEq>` --> log-0.3.8/src/lib.rs:552:14 | 552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] @@ -79,7 +79,7 @@ warning: technically breaking changes in `` | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in `` +warning: technically breaking changes in `` --> log-0.3.8/src/lib.rs:604:34 | 604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] diff --git a/tests/full_cases/log-0.3.4-0.3.8.windows_msvc b/tests/full_cases/log-0.3.4-0.3.8.windows_msvc index 0f6faa4ee4e28..449ca25265346 100644 --- a/tests/full_cases/log-0.3.4-0.3.8.windows_msvc +++ b/tests/full_cases/log-0.3.4-0.3.8.windows_msvc @@ -31,7 +31,7 @@ warning: technically breaking changes in ` as std::cmp::Eq> | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in ` as std::cmp::PartialEq>` +warning: technically breaking changes in ` as std::marker::StructuralPartialEq>` --> log-0.3.8\src\lib.rs:552:14 | 552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] @@ -79,7 +79,7 @@ warning: technically breaking changes in `` | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in `` +warning: technically breaking changes in `` --> log-0.3.8\src\lib.rs:604:34 | 604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] From b1b07627ff546509b58912361843a54f335dd10e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 7 Nov 2019 23:13:13 +0000 Subject: [PATCH 521/553] Fixed error reporting on field changes to structs. --- src/changes.rs | 129 +++++++++++++++++++++++++++++++------ src/traverse.rs | 8 +++ tests/cases/enums/stdout | 4 +- tests/cases/structs/stdout | 2 +- 4 files changed, 120 insertions(+), 23 deletions(-) diff --git a/src/changes.rs b/src/changes.rs index d741e2d2df22d..e2a4e648bd603 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -306,11 +306,11 @@ pub enum ChangeType<'tcx> { /// 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 }, + 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 are public were public before the change. - VariantFieldRemoved { public: bool, total_public: bool }, + /// 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 @@ -319,6 +319,7 @@ pub enum ChangeType<'tcx> { VariantStyleChanged { now_struct: bool, total_private: bool, + is_enum: bool, }, /// A function has changed it's constness. FnConstChanged { now_const: bool }, @@ -373,8 +374,10 @@ impl<'tcx> ChangeType<'tcx> { TypeParameterRemoved { .. } | VariantAdded | VariantRemoved | - VariantFieldAdded { .. } | // TODO: this (and the two below) appear wrong - VariantFieldRemoved { .. } | + VariantFieldAdded { public: true, .. } | + VariantFieldAdded { public: false, total_public: true, .. } | + VariantFieldRemoved { public: true, .. } | + VariantFieldRemoved { public: false, is_enum: true, .. } | VariantStyleChanged { .. } | TypeChanged { .. } | FnConstChanged { now_const: false } | @@ -396,6 +399,8 @@ impl<'tcx> ChangeType<'tcx> { StaticMutabilityChanged { now_mut: true } | VarianceLoosened | TypeParameterAdded { defaulted: true } | + VariantFieldAdded { public: false, .. } | + VariantFieldRemoved { public: false, .. } | FnConstChanged { now_const: true } => NonBreaking, } } @@ -477,13 +482,13 @@ on said enum can become non-exhaustive." to the removed variant is rendered invalid." } VariantFieldAdded { .. } => { - "Adding a field to an enum variant is breaking, as matches on the variant are -invalidated. In case of structs, this only holds for public fields, or the -first private field being added." + "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 is breaking, as matches on the variant -are invalidated. In case of structs, this only holds for public fields." + "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 @@ -616,51 +621,123 @@ impl<'a> fmt::Display for ChangeType<'a> { VariantFieldAdded { public: true, total_public: true, - } => "public variant field added to variant with no private fields", + 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, - } => "public variant field added to variant with private fields", + 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, - } => "variant field added to variant with no private fields", + is_enum: false, + } => "private field added to struct with no private fields", VariantFieldAdded { public: false, total_public: false, - } => "variant field added to variant with private fields", + 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, - } => "public variant field removed from variant with no private fields", + 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, - } => "public variant field removed from variant with private fields", + is_enum: false, + } => "public field removed from struct with private fields", VariantFieldRemoved { public: false, total_public: true, - } => "variant field removed from variant with no private fields", + 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, - } => "variant field removed from variant with private fields", + 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, - } => "variant changed to a struct variant", + 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, - } => "variant changed to a tuple variant", + 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", @@ -1210,14 +1287,17 @@ pub mod tests { 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, @@ -1255,23 +1335,29 @@ pub mod tests { 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 }, @@ -1312,14 +1398,17 @@ pub mod tests { 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 }, diff --git a/src/traverse.rs b/src/traverse.rs index 1ef076169fa81..564ffd330df1a 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -420,6 +420,11 @@ fn diff_adts(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, o _ => return, }; + let is_enum = match old { + Def(Enum, _) => true, + _ => false, + }; + let mut variants = BTreeMap::new(); let mut fields = BTreeMap::new(); @@ -457,6 +462,7 @@ fn diff_adts(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, o 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))); @@ -486,6 +492,7 @@ fn diff_adts(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, o 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))); } @@ -493,6 +500,7 @@ fn diff_adts(changes: &mut ChangeSet, id_mapping: &mut IdMapping, tcx: TyCtxt, o 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))); } diff --git a/tests/cases/enums/stdout b/tests/cases/enums/stdout index 0dfd45ab46431..5464c9721526c 100644 --- a/tests/cases/enums/stdout +++ b/tests/cases/enums/stdout @@ -93,12 +93,12 @@ warning: variant with no public fields changed to a struct variant (breaking) | 23 | Efg { f: u8 }, | ^^^^^^^^^^^^^ -warning: variant field removed from variant with private fields (breaking) +warning: private field removed from variant with private fields (breaking) --> enums/old.rs:25:11 | 25 | Ghi { f: u8 }, | ^^^^^ -warning: variant field added to variant with private fields (breaking) +note: private field added to variant with private fields (non-breaking) --> enums/new.rs:25:11 | 25 | Ghi { g: u8 }, diff --git a/tests/cases/structs/stdout b/tests/cases/structs/stdout index 7a5e019ceabbc..0b539e1183027 100644 --- a/tests/cases/structs/stdout +++ b/tests/cases/structs/stdout @@ -71,7 +71,7 @@ error: breaking changes in `Hij` 28 | | } | |_^ | -warning: variant with no public fields changed to a struct variant (breaking) +warning: tuple struct with no public fields changed to a regular struct (breaking) --> structs/new.rs:26:1 | 26 | / pub struct Hij { From 0286d2b7cecec4f7c05fcdb3830d84a35e6db0a7 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Thu, 7 Nov 2019 23:14:48 +0000 Subject: [PATCH 522/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 9759a586d34fd..f950308c9a38b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.44" +version = "0.1.45" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From 054088af588feafc8bd2288e29b215c63d131e95 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 21 Feb 2020 07:51:43 +0900 Subject: [PATCH 523/553] Rustup to latest nightly --- .travis.yml | 2 +- Cargo.toml | 7 +- src/bin/cargo_semver.rs | 9 ++- src/bin/rust_semver_public.rs | 13 ++-- src/bin/rust_semverver.rs | 14 ++-- src/changes.rs | 36 +++++---- src/lib.rs | 12 ++- src/mapping.rs | 31 +++++--- src/mismatch.rs | 22 +++--- src/translate.rs | 77 ++++++++++--------- src/traverse.rs | 47 +++++------ src/typeck.rs | 43 ++++++----- tests/cases/addition_use/stdout | 4 +- .../cases/addition_use/stdout_api_guidelines | 4 +- tests/cases/consts/stdout | 4 +- tests/cases/func/stdout | 6 +- tests/cases/infer_regress/stdout | 4 +- tests/cases/inherent_impls/stdout | 4 +- tests/cases/regions/stdout | 4 +- tests/cases/removal_use/stdout | 4 +- tests/cases/structs/stdout | 4 +- tests/cases/traits/stdout | 2 +- tests/cases/ty_alias/stdout | 4 +- tests/debug.rs | 8 +- tests/examples.rs | 4 +- tests/full.rs | 4 +- tests/full_cases/libc-0.2.28-0.2.31.linux | 20 ++--- 27 files changed, 211 insertions(+), 182 deletions(-) diff --git a/.travis.yml b/.travis.yml index 31a3db609a983..83263b6b4c6e8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,7 @@ matrix: fi - name: "clippy" script: | - if rustup component add clippy-preview; then + if rustup component add clippy-preview rustc-dev; then cargo clippy --all -- -D clippy::pedantic fi - name: "Shellcheck" diff --git a/Cargo.toml b/Cargo.toml index f950308c9a38b..6ce54332b4176 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,16 +27,15 @@ name = "rust-semver-public" path = "src/bin/rust_semver_public.rs" [dependencies] -cargo = "0.39" -crates-io = "0.27" +cargo = "0.42" +crates-io = "0.30" curl = "0.4.21" env_logger = "0.7" failure = "0.1" log = "0.4" rand = "0.7" semver = "0.9" -serde = "1.0.84" -serde_derive = "1.0.84" +serde = { version = "1.0.84", features = ["derive"] } serde_json = "1.0.34" [dev-dependencies] diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 5ad7b83ecd15b..687936873a496 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -4,9 +4,8 @@ extern crate curl; extern crate getopts; -extern crate serde; #[macro_use] -extern crate serde_derive; +extern crate serde; extern crate serde_json; use cargo::core::{Package, PackageId, Source, SourceId, Workspace}; @@ -483,7 +482,11 @@ impl<'a> WorkInfo<'a> { opts.build_config.build_plan = true; if let Some(target) = matches.opt_str("target") { - opts.build_config.requested_target = Some(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_kind = kind; + } } if let Some(s) = matches.opt_str("features") { diff --git a/src/bin/rust_semver_public.rs b/src/bin/rust_semver_public.rs index bb5dbb2bcd54a..088ba17fcc921 100644 --- a/src/bin/rust_semver_public.rs +++ b/src/bin/rust_semver_public.rs @@ -1,20 +1,19 @@ #![feature(rustc_private)] -#![feature(result_map_or_else)] -extern crate rustc; extern crate rustc_driver; extern crate rustc_interface; -extern crate syntax; +extern crate rustc_middle; +extern crate rustc_span; use log::debug; use rustc_driver::{Callbacks, Compilation}; -use rustc_interface::interface; +use rustc_interface::{interface, Queries}; +use rustc_span::source_map::Pos; use semverver::run_traversal; use std::{ path::Path, process::{exit, Command}, }; -use syntax::source_map::Pos; /// Display semverver version. fn show_version() { @@ -36,10 +35,10 @@ fn main() { struct PubCallbacks; impl Callbacks for PubCallbacks { - fn after_analysis(&mut self, compiler: &interface::Compiler) -> Compilation { + fn after_analysis<'tcx>(&mut self, _compiler: &interface::Compiler, queries: &'tcx Queries<'tcx>) -> Compilation { debug!("running rust-semver-public after_analysis callback"); - compiler.global_ctxt().unwrap().peek_mut().enter(|tcx| { + queries.global_ctxt().unwrap().peek_mut().enter(|tcx| { let krate = tcx .crates() .iter() diff --git a/src/bin/rust_semverver.rs b/src/bin/rust_semverver.rs index cd4c16bcd4994..600d78d72334a 100644 --- a/src/bin/rust_semverver.rs +++ b/src/bin/rust_semverver.rs @@ -1,23 +1,21 @@ #![feature(rustc_private)] -#![feature(result_map_or_else)] -extern crate rustc; -extern crate rustc_codegen_utils; extern crate rustc_driver; extern crate rustc_errors; extern crate rustc_interface; extern crate rustc_metadata; -extern crate syntax; +extern crate rustc_middle; +extern crate rustc_span; use log::debug; use rustc_driver::{Callbacks, Compilation}; -use rustc_interface::interface; +use rustc_interface::{interface, Queries}; +use rustc_span::source_map::Pos; use semverver::run_analysis; use std::{ path::Path, process::{exit, Command}, }; -use syntax::source_map::Pos; /// Display semverver version. fn show_version() { @@ -38,7 +36,7 @@ fn main() { struct SemverCallbacks; impl Callbacks for SemverCallbacks { - fn after_analysis(&mut self, compiler: &interface::Compiler) -> Compilation { + fn after_analysis<'tcx>(&mut self, _compiler: &interface::Compiler, queries: &'tcx Queries<'tcx>) -> Compilation { debug!("running rust-semverver after_analysis callback"); let verbose = @@ -55,7 +53,7 @@ fn main() { "no_version".to_owned() }; - compiler.global_ctxt().unwrap().peek_mut().enter(|tcx| { + 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... diff --git a/src/changes.rs b/src/changes.rs index e2a4e648bd603..9066afa01ed67 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -9,19 +9,17 @@ //! 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, - session::Session, - ty::{error::TypeError, Predicate}, -}; +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 syntax::symbol::Symbol; -use syntax_pos::{FileName, Span}; use serde::ser::{SerializeSeq, SerializeStruct, Serializer}; use serde::Serialize; @@ -306,11 +304,19 @@ pub enum ChangeType<'tcx> { /// 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 }, + 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 }, + 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 @@ -671,7 +677,7 @@ impl<'a> fmt::Display for ChangeType<'a> { VariantFieldRemoved { public: true, total_public: false, - is_enum: true + is_enum: true, } => "public field removed from variant with private fields", VariantFieldRemoved { public: true, @@ -1219,13 +1225,13 @@ pub mod tests { extern crate quickcheck; use quickcheck::*; - use rustc::hir::def_id::DefId; + use rustc_hir::def_id::DefId; use std::cmp::{max, min}; - use syntax_pos::hygiene::SyntaxContext; - use syntax_pos::symbol::Interner; - use syntax_pos::BytePos; + 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)] @@ -1257,7 +1263,7 @@ pub mod tests { impl Arbitrary for DefId_ { fn arbitrary(g: &mut G) -> DefId_ { - use rustc::hir::def_id::{CrateNum, DefIndex}; + use rustc_hir::def_id::{CrateNum, DefIndex}; let a: u32 = Arbitrary::arbitrary(g); let b: u32 = Arbitrary::arbitrary(g); diff --git a/src/lib.rs b/src/lib.rs index b054e4400d6fe..9c603a7669210 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,9 +3,15 @@ #![allow(clippy::single_match_else)] #![allow(clippy::too_many_lines)] #![deny(warnings)] -extern crate rustc; -extern crate syntax; -extern crate syntax_pos; +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; diff --git a/src/mapping.rs b/src/mapping.rs index 174d88fa7b372..fa604d41ef8b7 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -3,17 +3,18 @@ //! 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::{Export, Res}, - def_id::{CrateNum, DefId}, - HirId, - }, +use rustc_ast::ast::Name; +use rustc_hir::{ + def::Res, + def_id::{CrateNum, DefId}, + HirId, +}; +use rustc_middle::{ + hir::exports::Export, ty::{AssocKind, GenericParamDef, GenericParamDefKind}, }; use std::collections::{BTreeSet, HashMap, HashSet, VecDeque}; use std::hash::{Hash, Hasher}; -use syntax::ast::Name; /// A description of an item found in an inherent impl. #[derive(Debug, PartialEq)] @@ -40,6 +41,7 @@ fn assert_inherent_entry_members_impl_eq() { assert_impl_eq::(); } +#[allow(clippy::derive_hash_xor_eq)] impl Hash for InherentEntry { fn hash(&self, hasher: &mut H) { self.parent_def_id.hash(hasher); @@ -111,14 +113,19 @@ impl IdMapping { /// Register two exports representing the same item across versions. pub fn add_export(&mut self, old: Res, new: Res) -> bool { - let old_def_id = old.def_id(); + 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); + self.reverse_mapping.insert(new_def_id, old_def_id); true } @@ -343,8 +350,8 @@ pub struct NameMapping { impl NameMapping { /// Insert a single export in the appropriate map, at the appropriate position. fn insert(&mut self, item: Export, old: bool) { - use rustc::hir::def::DefKind::*; - use rustc::hir::def::Res::*; + use rustc_hir::def::DefKind::*; + use rustc_hir::def::Res::*; let map = match item.res { Def(kind, _) => match kind { @@ -366,7 +373,7 @@ impl NameMapping { ConstParam | Static | Ctor(_, _) | - Method | + AssocFn | AssocConst => Some(&mut self.value_map), Macro(_) => Some(&mut self.macro_map), }, diff --git a/src/mismatch.rs b/src/mismatch.rs index 2e557e94565bd..523dbf5e53f42 100644 --- a/src/mismatch.rs +++ b/src/mismatch.rs @@ -6,15 +6,13 @@ use crate::mapping::IdMapping; use log::debug; -use rustc::{ - hir::def::{DefKind, Res}, - ty::{ - self, - relate::{Relate, RelateResult, TypeRelation}, - subst::SubstsRef, - ParamEnv, Ty, TyCtxt, - Visibility::Public, - }, +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}; @@ -51,7 +49,7 @@ impl<'a, 'tcx> MismatchRelation<'a, 'tcx> { /// Process the next pair of `DefId`s in the queue. pub fn process(&mut self) { - // use rustc::hir::def::DefKind::*; + // use rustc_middle::hir::def::DefKind::*; while let Some((old_res, new_res)) = self.item_queue.pop_front() { debug!( @@ -87,7 +85,7 @@ impl<'a, 'tcx> MismatchRelation<'a, 'tcx> { /// 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::ty::subst::GenericArgKind::*; + use rustc_middle::ty::subst::GenericArgKind::*; for (a, b) in a_substs.iter().zip(b_substs) { match (a.unpack(), b.unpack()) { @@ -132,7 +130,7 @@ impl<'a, 'tcx> TypeRelation<'tcx> for MismatchRelation<'a, 'tcx> { } fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { - use rustc::ty::TyKind; + use rustc_middle::ty::TyKind; if self.current_old_types.contains(a) || self.current_new_types.contains(b) { return Ok(self.tcx.types.err); diff --git a/src/translate.rs b/src/translate.rs index 802a694e7143d..bb99b2646a01c 100644 --- a/src/translate.rs +++ b/src/translate.rs @@ -3,14 +3,12 @@ use crate::mapping::{IdMapping, InherentEntry}; use log::{debug, info}; -use rustc::{ - hir::def_id::DefId, - infer::InferCtxt, - ty::{ - fold::{BottomUpFolder, TypeFoldable, TypeFolder}, - subst::{GenericArg, InternalSubsts, SubstsRef}, - GenericParamDefKind, ParamEnv, Predicate, Region, TraitRef, Ty, TyCtxt, - }, +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; @@ -103,8 +101,8 @@ impl<'a, 'tcx> TranslationContext<'a, 'tcx> { orig_def_id: DefId, orig_substs: SubstsRef<'tcx>, ) -> Option<(DefId, SubstsRef<'tcx>)> { - use rustc::ty::subst::GenericArgKind; - use rustc::ty::ReEarlyBound; + use rustc_middle::ty::subst::GenericArgKind; + use rustc_middle::ty::ReEarlyBound; use std::cell::Cell; debug!( @@ -163,10 +161,10 @@ impl<'a, 'tcx> TranslationContext<'a, 'tcx> { /// Fold a structure, translating all `DefId`s reachable by the folder. fn translate>(&self, index_map: &HashMap, orig: &T) -> T { - use rustc::ty::ExistentialPredicate::*; - use rustc::ty::TyKind; - use rustc::ty::TypeAndMut; - use rustc::ty::{AdtDef, Binder, ExistentialProjection, ExistentialTraitRef}; + 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, @@ -201,7 +199,7 @@ impl<'a, 'tcx> TranslationContext<'a, 'tcx> { } TyKind::Dynamic(preds, region) => { // hacky error catching mechanism - use rustc::hir::def_id::CRATE_DEF_INDEX; + use rustc_hir::def_id::CRATE_DEF_INDEX; use std::cell::Cell; let success = Cell::new(true); @@ -293,7 +291,7 @@ impl<'a, 'tcx> TranslationContext<'a, 'tcx> { // `Self` is special let orig_def_id = index_map[¶m.index]; if self.needs_translation(orig_def_id) { - use rustc::ty::subst::GenericArgKind; + use rustc_middle::ty::subst::GenericArgKind; let target_def_id = self.translate_orig(orig_def_id); debug!("translating type param: {:?}", param); @@ -320,9 +318,9 @@ impl<'a, 'tcx> TranslationContext<'a, 'tcx> { /// Translate a region. fn translate_region(&self, region: Region<'tcx>) -> Region<'tcx> { - use rustc::ty::BoundRegion::BrNamed; - use rustc::ty::RegionKind::*; - use rustc::ty::{EarlyBoundRegion, FreeRegion}; + use rustc_middle::ty::BoundRegion::BrNamed; + use rustc_middle::ty::RegionKind::*; + use rustc_middle::ty::{EarlyBoundRegion, FreeRegion}; if !self.translate_params { return region; @@ -363,28 +361,31 @@ impl<'a, 'tcx> TranslationContext<'a, 'tcx> { index_map: &HashMap, predicate: Predicate<'tcx>, ) -> Option> { - use rustc::ty::{ + use rustc_middle::ty::{ Binder, /*EquatePredicate,*/ OutlivesPredicate, ProjectionPredicate, ProjectionTy, SubtypePredicate, TraitPredicate, }; Some(match predicate { - Predicate::Trait(trait_predicate) => Predicate::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; - }, - )), + Predicate::Trait(trait_predicate, constness) => Predicate::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, + ), /*Predicate::Equate(equate_predicate) => { Predicate::Equate(equate_predicate.map_bound(|e_pred| { let l = self.translate(index_map, &e_pred.0); @@ -538,8 +539,8 @@ impl<'a, 'tcx> TypeFolder<'tcx> for InferenceCleanupFolder<'a, 'tcx> { } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - use rustc::ty::TyKind; - use rustc::ty::TypeAndMut; + use rustc_middle::ty::TyKind; + use rustc_middle::ty::TypeAndMut; let t1 = ty.super_fold_with(self); match t1.kind { diff --git a/src/traverse.rs b/src/traverse.rs index 564ffd330df1a..1d9b02e41bd6c 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -17,12 +17,12 @@ use crate::{ typeck::{BoundContext, TypeComparisonContext}, }; use log::{debug, info}; -use rustc::{ - hir::{ - def::{CtorKind, CtorOf, DefKind, Export, Res, Res::Def}, - def_id::DefId, - HirId, - }, +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, @@ -30,6 +30,7 @@ use rustc::{ Visibility::Public, }, }; +use rustc_mir::const_eval::is_const_fn; use std::collections::{BTreeMap, HashSet, VecDeque}; /// The main entry point to our analysis passes. @@ -75,7 +76,7 @@ fn get_vis(outer_vis: Visibility, def: Export) -> Visibility { } pub fn run_traversal(tcx: TyCtxt, new: DefId) { - use rustc::hir::def::DefKind::*; + use rustc_hir::def::DefKind::*; let mut visited = HashSet::new(); let mut mod_queue = VecDeque::new(); @@ -128,7 +129,7 @@ fn diff_structure<'tcx>( old: DefId, new: DefId, ) { - use rustc::hir::def::DefKind::*; + use rustc_hir::def::DefKind::*; let mut visited = HashSet::new(); let mut children = NameMapping::default(); @@ -235,7 +236,7 @@ fn diff_structure<'tcx>( | (AssocConst, AssocConst) | (Variant, Variant) | (Const, Const) - | (Method, Method) + | (AssocFn, AssocFn) | (Macro(_), Macro(_)) | (TraitAlias, TraitAlias) | (ForeignTy, ForeignTy) @@ -360,8 +361,8 @@ 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 = tcx.is_const_fn(old_def_id); - let new_const = tcx.is_const_fn(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( @@ -398,8 +399,8 @@ fn diff_method<'tcx>(changes: &mut ChangeSet, tcx: TyCtxt<'tcx>, old: AssocItem, diff_fn( changes, tcx, - Def(DefKind::Method, old.def_id), - Def(DefKind::Method, new.def_id), + Def(DefKind::Fn, old.def_id), + Def(DefKind::Fn, new.def_id), ); } @@ -408,7 +409,7 @@ fn diff_method<'tcx>(changes: &mut ChangeSet, tcx: TyCtxt<'tcx>, old: AssocItem, /// 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::*; + use rustc_hir::def::DefKind::*; let old_def_id = old.def_id(); let new_def_id = new.def_id(); @@ -567,9 +568,9 @@ fn diff_traits<'tcx>( new: DefId, output: bool, ) { - use rustc::hir::Unsafety::Unsafe; - use rustc::ty::subst::GenericArgKind::Type; - use rustc::ty::{ParamTy, Predicate, TyS}; + use rustc_hir::Unsafety::Unsafe; + use rustc_middle::ty::subst::GenericArgKind::Type; + use rustc_middle::ty::{ParamTy, Predicate, TyS}; debug!( "diff_traits: old: {:?}, new: {:?}, output: {:?}", @@ -591,7 +592,7 @@ fn diff_traits<'tcx>( let old_param_env = tcx.param_env(old); for bound in old_param_env.caller_bounds { - if let Predicate::Trait(pred) = *bound { + if let Predicate::Trait(pred, _) = *bound { let trait_ref = pred.skip_binder().trait_ref; debug!("trait_ref substs (old): {:?}", trait_ref.substs); @@ -672,8 +673,8 @@ fn diff_generics( old: DefId, new: DefId, ) { - use rustc::ty::Variance; - use rustc::ty::Variance::*; + 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> { @@ -862,7 +863,7 @@ fn diff_types<'tcx>( old: Res, new: Res, ) { - use rustc::hir::def::DefKind::*; + use rustc_hir::def::DefKind::*; let old_def_id = old.def_id(); let new_def_id = new.def_id(); @@ -890,7 +891,7 @@ fn diff_types<'tcx>( ); } // functions and methods require us to compare their signatures, not types - Def(Fn, _) | Def(Method, _) => { + 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); @@ -1196,7 +1197,7 @@ fn match_inherent_impl<'tcx>( orig_item: AssocItem, target_item: AssocItem, ) -> bool { - use rustc::ty::AssocKind; + use rustc_middle::ty::AssocKind; debug!( "match_inherent_impl: orig_impl/item: {:?}/{:?}, target_impl/item: {:?}/{:?}", diff --git a/src/typeck.rs b/src/typeck.rs index bd501c0b0bd1d..23241318e46cb 100644 --- a/src/typeck.rs +++ b/src/typeck.rs @@ -9,10 +9,11 @@ use crate::{ translate::{InferenceCleanupFolder, TranslationContext}, }; use log::debug; -use rustc::{ - hir::def_id::DefId, - infer::InferCtxt, - traits::{FulfillmentContext, FulfillmentError, Obligation, ObligationCause, TraitEngine}, +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, @@ -20,6 +21,7 @@ use rustc::{ GenericParamDefKind, ParamEnv, Predicate, TraitRef, Ty, TyCtxt, }, }; +use rustc_trait_selection::traits::FulfillmentContext; /// The context in which bounds analysis happens. pub struct BoundContext<'a, 'tcx: 'a> { @@ -43,7 +45,8 @@ impl<'a, 'tcx> BoundContext<'a, 'tcx> { /// Register the bounds of an item. pub fn register(&mut self, checked_def_id: DefId, substs: SubstsRef<'tcx>) { - use rustc::traits::{normalize, Normalized, SelectionContext}; + use rustc_infer::traits::Normalized; + use rustc_trait_selection::traits::{normalize, SelectionContext}; let cause = ObligationCause::dummy(); let mut selcx = SelectionContext::new(self.infcx); @@ -69,11 +72,15 @@ impl<'a, 'tcx> BoundContext<'a, 'tcx> { /// Register the trait bound represented by a `TraitRef`. pub fn register_trait_ref(&mut self, checked_trait_ref: TraitRef<'tcx>) { - use rustc::ty::{Binder, TraitPredicate}; - - let predicate = Predicate::Trait(Binder::bind(TraitPredicate { - trait_ref: checked_trait_ref, - })); + use rustc_hir::Constness; + use rustc_middle::ty::{Binder, TraitPredicate}; + + let predicate = Predicate::Trait( + Binder::bind(TraitPredicate { + trait_ref: checked_trait_ref, + }), + Constness::NotConst, + ); let obligation = Obligation::new(ObligationCause::dummy(), self.given_param_env, predicate); self.fulfill_cx .register_predicate_obligation(self.infcx, obligation); @@ -162,7 +169,7 @@ impl<'a, 'tcx> TypeComparisonContext<'a, 'tcx> { /// 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 syntax_pos::DUMMY_SP; + use rustc_span::DUMMY_SP; let has_self = self.infcx.tcx.generics_of(target_def_id).has_self; @@ -178,7 +185,7 @@ impl<'a, 'tcx> TypeComparisonContext<'a, 'tcx> { /// 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::ty::ReEarlyBound; + use rustc_middle::ty::ReEarlyBound; InternalSubsts::for_item(self.infcx.tcx, target_def_id, |def, _| match def.kind { GenericParamDefKind::Lifetime => GenericArg::from( @@ -209,10 +216,10 @@ impl<'a, 'tcx> TypeComparisonContext<'a, 'tcx> { orig: Ty<'tcx>, target: Ty<'tcx>, ) -> Option> { - use rustc::infer::outlives::env::OutlivesEnvironment; - use rustc::infer::{InferOk, SuppressRegionErrors}; - use rustc::middle::region::ScopeTree; - use rustc::ty::Lift; + use rustc_infer::infer::outlives::env::OutlivesEnvironment; + use rustc_infer::infer::{InferOk, RegionckMode}; + use rustc_middle::middle::region::ScopeTree; + use rustc_middle::ty::Lift; let error = self .infcx @@ -241,7 +248,7 @@ impl<'a, 'tcx> TypeComparisonContext<'a, 'tcx> { target_def_id, &scope_tree, &outlives_env, - SuppressRegionErrors::default(), + RegionckMode::default(), ); let err = self @@ -265,7 +272,7 @@ impl<'a, 'tcx> TypeComparisonContext<'a, 'tcx> { target_def_id: DefId, target_substs: SubstsRef<'tcx>, ) -> Option>> { - use rustc::ty::Lift; + use rustc_middle::ty::Lift; debug!( "check_bounds_error: orig env: {:?}, target did: {:?}, target substs: {:?}", orig_param_env, target_def_id, target_substs diff --git a/tests/cases/addition_use/stdout b/tests/cases/addition_use/stdout index 8ab043f7c3f82..71f064eb3bd1b 100644 --- a/tests/cases/addition_use/stdout +++ b/tests/cases/addition_use/stdout @@ -8,8 +8,8 @@ error: breaking changes in `Def` 8 | | } | |_^ | - = warning: type error: expected (), found struct `new::Abc` (breaking) - = warning: type error: expected (), found trait new::Bcd (breaking) + = 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 diff --git a/tests/cases/addition_use/stdout_api_guidelines b/tests/cases/addition_use/stdout_api_guidelines index 1683f9a1596dd..2b815c4bd4e92 100644 --- a/tests/cases/addition_use/stdout_api_guidelines +++ b/tests/cases/addition_use/stdout_api_guidelines @@ -8,8 +8,8 @@ error: breaking changes in `Def` 8 | | } | |_^ | - = warning: type error: expected (), found struct `new::Abc` (breaking) - = warning: type error: expected (), found trait new::Bcd (breaking) + = 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/tests/cases/consts/stdout b/tests/cases/consts/stdout index 59ae75aed28da..891be6a085e37 100644 --- a/tests/cases/consts/stdout +++ b/tests/cases/consts/stdout @@ -5,7 +5,7 @@ error: breaking changes in `A` 1 | pub const A: u16 = 0; | ^^^^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected u8, found u16 (breaking) + = warning: type error: expected `u8`, found `u16` (breaking) error: breaking changes in `B` --> consts/new.rs:3:1 @@ -13,7 +13,7 @@ error: breaking changes in `B` 3 | pub static B: u16 = 1; | ^^^^^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected u8, found u16 (breaking) + = warning: type error: expected `u8`, found `u16` (breaking) error: breaking changes in `D` --> consts/new.rs:7:1 diff --git a/tests/cases/func/stdout b/tests/cases/func/stdout index 3bddfc0093c35..9c2d9c6286eab 100644 --- a/tests/cases/func/stdout +++ b/tests/cases/func/stdout @@ -15,7 +15,7 @@ error: breaking changes in `cde` 8 | | } | |_^ | - = warning: type error: expected (), found u16 (breaking) + = warning: type error: expected `()`, found `u16` (breaking) error: breaking changes in `def` --> func/new.rs:10:1 @@ -43,7 +43,7 @@ error: breaking changes in `fgh` 18 | | } | |_^ | - = warning: type error: expected u8, found u16 (breaking) + = warning: type error: expected `u8`, found `u16` (breaking) error: breaking changes in `ghi` --> func/new.rs:20:1 @@ -53,7 +53,7 @@ error: breaking changes in `ghi` 22 | | } | |_^ | - = warning: type error: expected u8, found u16 (breaking) + = warning: type error: expected `u8`, found `u16` (breaking) warning: non-breaking changes in `hij` --> func/new.rs:24:1 diff --git a/tests/cases/infer_regress/stdout b/tests/cases/infer_regress/stdout index c00ccce27d9df..82a0c8cfc1a7a 100644 --- a/tests/cases/infer_regress/stdout +++ b/tests/cases/infer_regress/stdout @@ -6,7 +6,7 @@ error: breaking changes in `abc` | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: variance loosened (non-breaking) - = warning: type error: expected type parameter `A`, found () (breaking) + = warning: type error: expected type parameter `A`, found `()` (breaking) error: breaking changes in `Abc` --> infer_regress/new.rs:3:1 @@ -14,7 +14,7 @@ error: breaking changes in `Abc` 3 | pub struct Abc(pub A, pub ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected type parameter `A`, found () (breaking) + = warning: type error: expected type parameter `A`, found `()` (breaking) error: aborting due to 2 previous errors diff --git a/tests/cases/inherent_impls/stdout b/tests/cases/inherent_impls/stdout index 6a35e7bf1b7cd..7bf262d8a076a 100644 --- a/tests/cases/inherent_impls/stdout +++ b/tests/cases/inherent_impls/stdout @@ -7,7 +7,7 @@ error: breaking changes in `ghi` 16 | | } | |_____^ | - = warning: type error: expected type parameter `A`, found u8 (breaking) + = warning: type error: expected type parameter `A`, found `u8` (breaking) error: breaking changes in `def` --> inherent_impls/old.rs:26:5 @@ -27,7 +27,7 @@ error: breaking changes in `def` 35 | | } | |_____^ | - = warning: type error: expected u8, found u16 (breaking) + = warning: type error: expected `u8`, found `u16` (breaking) error: breaking changes in `ghi` --> inherent_impls/old.rs:37:5 diff --git a/tests/cases/regions/stdout b/tests/cases/regions/stdout index 8cc7205a1fbba..3f3ac0d275d7a 100644 --- a/tests/cases/regions/stdout +++ b/tests/cases/regions/stdout @@ -21,7 +21,7 @@ error: breaking changes in `abc` 13 | pub fn abc(_: &bool) { } | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected bool, found reference (breaking) + = warning: type error: expected `bool`, found `&bool` (breaking) error: breaking changes in `def` --> regions/new.rs:15:1 @@ -29,7 +29,7 @@ error: breaking changes in `def` 15 | pub fn def(_: bool) { } | ^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected reference, found bool (breaking) + = warning: type error: expected `&bool`, found `bool` (breaking) error: breaking changes in `efg` --> regions/new.rs:17:1 diff --git a/tests/cases/removal_use/stdout b/tests/cases/removal_use/stdout index 2d245d7c28b37..deed1be939f48 100644 --- a/tests/cases/removal_use/stdout +++ b/tests/cases/removal_use/stdout @@ -24,8 +24,8 @@ error: breaking changes in `Def` 4 | | } | |_^ | - = warning: type error: expected struct `old::Abc`, found () (breaking) - = warning: type error: expected trait old::Bcd, found () (breaking) + = 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/tests/cases/structs/stdout b/tests/cases/structs/stdout index 0b539e1183027..4f07a07358a0e 100644 --- a/tests/cases/structs/stdout +++ b/tests/cases/structs/stdout @@ -23,7 +23,7 @@ error: breaking changes in `Def2` | |_^ | = note: defaulted type parameter added (non-breaking) - = warning: type error: expected u8, found u16 (breaking) + = warning: type error: expected `u8`, found `u16` (breaking) error: breaking changes in `Efg` --> structs/new.rs:14:1 @@ -33,7 +33,7 @@ error: breaking changes in `Efg` 16 | | } | |_^ | - = warning: type error: expected u8, found u16 (breaking) + = warning: type error: expected `u8`, found `u16` (breaking) warning: technically breaking changes in `Fgh` --> structs/new.rs:18:1 diff --git a/tests/cases/traits/stdout b/tests/cases/traits/stdout index 451336c654763..ec29ba3c7d1db 100644 --- a/tests/cases/traits/stdout +++ b/tests/cases/traits/stdout @@ -42,7 +42,7 @@ error: breaking changes in `test7` 11 | fn test7() -> u16; | ^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected u8, found u16 (breaking) + = warning: type error: expected `u8`, found `u16` (breaking) error: breaking changes in `test8` --> traits/new.rs:12:5 diff --git a/tests/cases/ty_alias/stdout b/tests/cases/ty_alias/stdout index ddafe341a97df..6f61d37cfe281 100644 --- a/tests/cases/ty_alias/stdout +++ b/tests/cases/ty_alias/stdout @@ -5,7 +5,7 @@ error: breaking changes in `A` 3 | pub type A = u16; | ^^^^^^^^^^^^^^^^^ | - = warning: type error: expected u8, found u16 (breaking) + = warning: type error: expected `u8`, found `u16` (breaking) error: breaking changes in `B` --> ty_alias/new.rs:4:1 @@ -30,7 +30,7 @@ error: breaking changes in `D` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: defaulted type parameter added (non-breaking) - = warning: type error: expected reference, found tuple (breaking) + = warning: type error: expected `&T`, found tuple (breaking) error: breaking changes in `E` --> ty_alias/new.rs:7:1 diff --git a/tests/debug.rs b/tests/debug.rs index 97e040f2d8858..54e7ac587353a 100644 --- a/tests/debug.rs +++ b/tests/debug.rs @@ -17,7 +17,9 @@ fn debug() { let _ = dump.set_permissions(permissions); } - let _ = writeln!(dump, r#"#!/usr/bin/env sh + let _ = writeln!( + dump, + r#"#!/usr/bin/env sh export PATH=./target/debug:$PATH export LD_LIBRARY_PATH={} export RUST_BACKTRACE=full @@ -50,6 +52,8 @@ rust-gdb ./target/debug/rust-semverver -iex "$arg_str" -iex "$src_str" if [ $del = 1 ]; then rm "$1/lib*.rlib" -fi"#, path); +fi"#, + path + ); } } diff --git a/tests/examples.rs b/tests/examples.rs index 02dbd2f48dd25..226b6bf769e2d 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -107,7 +107,7 @@ mod features { .map(|l| l.trim_end()) .map(|line| { // sanitize paths for reproducibility - (match line.find("-->") { + match line.find("-->") { Some(idx) => { let (start, end) = line.split_at(idx); match end.find(name) { @@ -116,7 +116,7 @@ mod features { } } None => line.to_string(), - }) + } }) .map(|l| { if cfg!(target_os = "windows") { diff --git a/tests/full.rs b/tests/full.rs index a09266a172e69..c6cf564c5faa7 100644 --- a/tests/full.rs +++ b/tests/full.rs @@ -98,7 +98,7 @@ mod full { !log_enabled!(Level::Debug)) .map(|line| { // sanitize paths for reproducibility - (match line.find("-->") { + match line.find("-->") { Some(idx) => { let (start, end) = line.split_at(idx); match end.find(crate_name) { @@ -107,7 +107,7 @@ mod full { } } None => line.to_string(), - }) + } }) .map(|l| l + "\n") .collect::() diff --git a/tests/full_cases/libc-0.2.28-0.2.31.linux b/tests/full_cases/libc-0.2.28-0.2.31.linux index 221b294700828..ff6b68d821908 100644 --- a/tests/full_cases/libc-0.2.28-0.2.31.linux +++ b/tests/full_cases/libc-0.2.28-0.2.31.linux @@ -20,7 +20,7 @@ error: breaking changes in `PTRACE_O_EXITKILL` 738 | pub const PTRACE_O_EXITKILL: ::c_int = 0x00100000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected u32, found i32 (breaking) + = 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 @@ -28,7 +28,7 @@ error: breaking changes in `PTRACE_O_TRACECLONE` 733 | pub const PTRACE_O_TRACECLONE: ::c_int = 0x00000008; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected u32, found i32 (breaking) + = 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 @@ -36,7 +36,7 @@ error: breaking changes in `PTRACE_O_TRACEEXEC` 734 | pub const PTRACE_O_TRACEEXEC: ::c_int = 0x00000010; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected u32, found i32 (breaking) + = 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 @@ -44,7 +44,7 @@ error: breaking changes in `PTRACE_O_TRACEEXIT` 736 | pub const PTRACE_O_TRACEEXIT: ::c_int = 0x00000040; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected u32, found i32 (breaking) + = 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 @@ -52,7 +52,7 @@ error: breaking changes in `PTRACE_O_TRACEFORK` 731 | pub const PTRACE_O_TRACEFORK: ::c_int = 0x00000002; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected u32, found i32 (breaking) + = 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 @@ -60,7 +60,7 @@ error: breaking changes in `PTRACE_O_TRACESYSGOOD` 730 | pub const PTRACE_O_TRACESYSGOOD: ::c_int = 0x00000001; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected u32, found i32 (breaking) + = 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 @@ -68,7 +68,7 @@ error: breaking changes in `PTRACE_O_TRACEVFORK` 732 | pub const PTRACE_O_TRACEVFORK: ::c_int = 0x00000004; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected u32, found i32 (breaking) + = 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 @@ -76,7 +76,7 @@ error: breaking changes in `PTRACE_O_TRACEVFORKDONE` 735 | pub const PTRACE_O_TRACEVFORKDONE: ::c_int = 0x00000020; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected u32, found i32 (breaking) + = 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 @@ -84,7 +84,7 @@ error: breaking changes in `PTRACE_O_TRACESECCOMP` 737 | pub const PTRACE_O_TRACESECCOMP: ::c_int = 0x00000080; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected u32, found i32 (breaking) + = 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 @@ -92,7 +92,7 @@ error: breaking changes in `PTRACE_O_SUSPEND_SECCOMP` 739 | pub const PTRACE_O_SUSPEND_SECCOMP: ::c_int = 0x00200000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: type error: expected u32, found i32 (breaking) + = warning: type error: expected `u32`, found `i32` (breaking) warning: path changes to `INADDR_LOOPBACK` --> libc-0.2.31/src/unix/mod.rs:227:1 From b6783e379cd5911a5bc8d2ad85961596831b29a0 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Fri, 3 Apr 2020 13:49:09 +0200 Subject: [PATCH 524/553] Version bump. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 6ce54332b4176..d250bd3f15c2f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ 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.45" +version = "0.1.46" authors = ["Inokentiy Babushkin "] license-file = "LICENSE" edition = "2018" From da11610511c0486979a9605bc33043f6150ce9a0 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 8 Apr 2020 23:24:47 +0900 Subject: [PATCH 525/553] Rustup to the latest nightly --- src/bin/cargo_semver.rs | 5 +++-- src/mapping.rs | 2 +- src/traverse.rs | 13 +++++++------ tests/cases/addition/stdout | 2 ++ tests/cases/addition_path/stdout | 3 +++ tests/cases/addition_use/stdout | 2 +- tests/cases/bounds/stdout | 2 +- tests/cases/consts/stdout | 2 +- tests/cases/func/stdout | 2 +- tests/cases/inherent_impls/stdout | 2 +- tests/cases/macros/stdout | 2 +- tests/cases/mix/stdout | 2 +- tests/cases/pathologic_paths/stdout | 2 ++ tests/cases/sealed_traits/stdout | 2 ++ tests/cases/structs/stdout | 2 +- tests/cases/trait_impls/stdout | 2 +- tests/cases/traits/stdout | 2 +- tests/full_cases/libc-0.2.28-0.2.31.linux | 2 +- tests/full_cases/libc-0.2.28-0.2.31.osx | 2 +- tests/full_cases/log-0.3.4-0.3.8.linux | 6 ++++-- tests/full_cases/log-0.3.4-0.3.8.osx | 6 ++++-- tests/full_cases/log-0.3.4-0.3.8.windows_msvc | 2 ++ tests/full_cases/rmpv-0.4.0-0.4.1.linux | 2 +- tests/full_cases/rmpv-0.4.0-0.4.1.osx | 2 +- tests/full_cases/rmpv-0.4.0-0.4.1.windows_msvc | 2 +- 25 files changed, 45 insertions(+), 28 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 687936873a496..cd7bef755d0bf 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -3,9 +3,9 @@ #![allow(clippy::too_many_lines)] extern crate curl; -extern crate getopts; #[macro_use] extern crate serde; +extern crate rustc_session; extern crate serde_json; use cargo::core::{Package, PackageId, Source, SourceId, Workspace}; @@ -13,6 +13,7 @@ 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, @@ -268,8 +269,8 @@ fn run(config: &cargo::Config, matches: &getopts::Matches) -> Result<()> { /// CLI utils mod cli { - extern crate getopts; use cargo::util::CliError; + use rustc_session::getopts; /// CLI options pub fn options() -> getopts::Options { diff --git a/src/mapping.rs b/src/mapping.rs index fa604d41ef8b7..f0902245df7d2 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -49,7 +49,7 @@ impl Hash for InherentEntry { // FIXME derive Hash again once AssocKind derives Hash again. match self.kind { AssocKind::Const => 0u8.hash(hasher), - AssocKind::Method => 1u8.hash(hasher), + AssocKind::Fn => 1u8.hash(hasher), AssocKind::OpaqueTy => 2u8.hash(hasher), AssocKind::Type => 3u8.hash(hasher), } diff --git a/src/traverse.rs b/src/traverse.rs index 1d9b02e41bd6c..f501ca8d7c0b2 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -377,10 +377,10 @@ fn diff_fn<'tcx>(changes: &mut ChangeSet, tcx: TyCtxt<'tcx>, old: Res, new: Res) /// Given two method items, perform structural checks. fn diff_method<'tcx>(changes: &mut ChangeSet, tcx: TyCtxt<'tcx>, old: AssocItem, new: AssocItem) { - if old.method_has_self_argument != new.method_has_self_argument { + if old.fn_has_self_parameter != new.fn_has_self_parameter { changes.add_change( ChangeType::MethodSelfChanged { - now_self: new.method_has_self_argument, + now_self: new.fn_has_self_parameter, }, old.def_id, None, @@ -628,8 +628,8 @@ fn diff_traits<'tcx>( (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.def_kind(), old_def_id); - let new_res = Res::Def(new_item.def_kind(), new_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( @@ -1127,7 +1127,8 @@ fn is_impl_trait_public<'tcx>(tcx: TyCtxt<'tcx>, impl_def_id: DefId) -> bool { // Check if all input types of the trait implementation are public (including `Self`). let is_public = trait_ref - .input_types() + .substs + .types() .map(|t| type_visibility(tcx, t)) .all(|v| v == Visibility::Public); @@ -1275,7 +1276,7 @@ fn match_inherent_impl<'tcx>( infcx.tcx.type_of(orig_item_def_id), infcx.tcx.type_of(target_item_def_id), ), - (AssocKind::Method, AssocKind::Method) => { + (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); diff --git a/tests/cases/addition/stdout b/tests/cases/addition/stdout index a560292dccc36..3f8c0cbd5474a 100644 --- a/tests/cases/addition/stdout +++ b/tests/cases/addition/stdout @@ -54,3 +54,5 @@ warning: path changes to `Cde` | = note: added definition (technically breaking) +warning: 6 warnings emitted + diff --git a/tests/cases/addition_path/stdout b/tests/cases/addition_path/stdout index b39c6cffea55b..3ea7ba7fda263 100644 --- a/tests/cases/addition_path/stdout +++ b/tests/cases/addition_path/stdout @@ -30,3 +30,6 @@ warning: path changes to `d` | |_^ | = note: added definition (technically breaking) + +warning: 2 warnings emitted + diff --git a/tests/cases/addition_use/stdout b/tests/cases/addition_use/stdout index 71f064eb3bd1b..b15dcadf04ca1 100644 --- a/tests/cases/addition_use/stdout +++ b/tests/cases/addition_use/stdout @@ -27,5 +27,5 @@ warning: path changes to `Bcd` | = note: added definition (technically breaking) -error: aborting due to previous error +error: aborting due to previous error; 2 warnings emitted diff --git a/tests/cases/bounds/stdout b/tests/cases/bounds/stdout index 5a2d4922c3cdf..61cff1c07e4b8 100644 --- a/tests/cases/bounds/stdout +++ b/tests/cases/bounds/stdout @@ -35,5 +35,5 @@ warning: technically breaking changes in `def` | = note: removed bound: `A: std::clone::Clone` (technically breaking) -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 2 warnings emitted diff --git a/tests/cases/consts/stdout b/tests/cases/consts/stdout index 891be6a085e37..36f2432a874aa 100644 --- a/tests/cases/consts/stdout +++ b/tests/cases/consts/stdout @@ -31,5 +31,5 @@ warning: non-breaking changes in `E` | = note: static item made mutable (non-breaking) -error: aborting due to 3 previous errors +error: aborting due to 3 previous errors; 1 warning emitted diff --git a/tests/cases/func/stdout b/tests/cases/func/stdout index 9c2d9c6286eab..0cefacd6075e4 100644 --- a/tests/cases/func/stdout +++ b/tests/cases/func/stdout @@ -75,5 +75,5 @@ error: breaking changes in `ijk` | = warning: fn item made non-const (breaking) -error: aborting due to 6 previous errors +error: aborting due to 6 previous errors; 2 warnings emitted diff --git a/tests/cases/inherent_impls/stdout b/tests/cases/inherent_impls/stdout index 7bf262d8a076a..1756d63cefc03 100644 --- a/tests/cases/inherent_impls/stdout +++ b/tests/cases/inherent_impls/stdout @@ -55,5 +55,5 @@ warning: technically breaking changes in `def` | = note: added item in inherent impl (technically breaking) -error: aborting due to 4 previous errors +error: aborting due to 4 previous errors; 2 warnings emitted diff --git a/tests/cases/macros/stdout b/tests/cases/macros/stdout index 4112572826ecb..d279b2dd98f8a 100644 --- a/tests/cases/macros/stdout +++ b/tests/cases/macros/stdout @@ -39,5 +39,5 @@ warning: path changes to `quux2` | = note: added definition (technically breaking) -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 2 warnings emitted diff --git a/tests/cases/mix/stdout b/tests/cases/mix/stdout index 9d5774e5985fe..3f3a942e0cac4 100644 --- a/tests/cases/mix/stdout +++ b/tests/cases/mix/stdout @@ -44,4 +44,4 @@ note: added path (technically breaking) 10 | pub use self::a::Def; | ^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 3 previous errors; 1 warning emitted diff --git a/tests/cases/pathologic_paths/stdout b/tests/cases/pathologic_paths/stdout index 9f8702d0d2557..d9aae39fb923e 100644 --- a/tests/cases/pathologic_paths/stdout +++ b/tests/cases/pathologic_paths/stdout @@ -15,3 +15,5 @@ warning: path changes to `b` | = note: added definition (technically breaking) +warning: 2 warnings emitted + diff --git a/tests/cases/sealed_traits/stdout b/tests/cases/sealed_traits/stdout index d0f32d42a8b6d..4192b297d505f 100644 --- a/tests/cases/sealed_traits/stdout +++ b/tests/cases/sealed_traits/stdout @@ -13,3 +13,5 @@ note: added item to sealed trait (technically breaking) 2 | fn abc(&self) -> bool; | ^^^^^^^^^^^^^^^^^^^^^^ +warning: 1 warning emitted + diff --git a/tests/cases/structs/stdout b/tests/cases/structs/stdout index 4f07a07358a0e..537021b38cde3 100644 --- a/tests/cases/structs/stdout +++ b/tests/cases/structs/stdout @@ -79,5 +79,5 @@ warning: tuple struct with no public fields changed to a regular struct (breakin 28 | | } | |_^ -error: aborting due to 4 previous errors +error: aborting due to 4 previous errors; 2 warnings emitted diff --git a/tests/cases/trait_impls/stdout b/tests/cases/trait_impls/stdout index 976c04c9f62b1..d4ce24bbde0b9 100644 --- a/tests/cases/trait_impls/stdout +++ b/tests/cases/trait_impls/stdout @@ -51,5 +51,5 @@ warning: technically breaking changes in ` as new::Ab | = note: trait impl generalized or newly added (technically breaking) -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 4 warnings emitted diff --git a/tests/cases/traits/stdout b/tests/cases/traits/stdout index ec29ba3c7d1db..864a1ac743fdc 100644 --- a/tests/cases/traits/stdout +++ b/tests/cases/traits/stdout @@ -156,5 +156,5 @@ error: breaking changes in `Tuv` | = warning: removed bound on trait definition: `A: std::clone::Clone` (breaking) -error: aborting due to 13 previous errors +error: aborting due to 13 previous errors; 1 warning emitted diff --git a/tests/full_cases/libc-0.2.28-0.2.31.linux b/tests/full_cases/libc-0.2.28-0.2.31.linux index ff6b68d821908..a79756a6812f4 100644 --- a/tests/full_cases/libc-0.2.28-0.2.31.linux +++ b/tests/full_cases/libc-0.2.28-0.2.31.linux @@ -865,6 +865,6 @@ note: added path (technically breaking) 284 | pub use unix::*; | ^^^^^^^ -error: aborting due to 11 previous errors +error: aborting due to 11 previous errors; 63 warnings emitted error: rustc-semverver errored diff --git a/tests/full_cases/libc-0.2.28-0.2.31.osx b/tests/full_cases/libc-0.2.28-0.2.31.osx index 7cd9606a70576..eac71b884c4f4 100644 --- a/tests/full_cases/libc-0.2.28-0.2.31.osx +++ b/tests/full_cases/libc-0.2.28-0.2.31.osx @@ -2367,6 +2367,6 @@ note: added path (technically breaking) 284 | pub use unix::*; | ^^^^^^^ -error: aborting due to previous error +error: aborting due to previous error; 194 warnings emitted error: rustc-semverver errored diff --git a/tests/full_cases/log-0.3.4-0.3.8.linux b/tests/full_cases/log-0.3.4-0.3.8.linux index 19aebffb5f7d7..e77b51cc8b98d 100644 --- a/tests/full_cases/log-0.3.4-0.3.8.linux +++ b/tests/full_cases/log-0.3.4-0.3.8.linux @@ -23,7 +23,7 @@ warning: technically breaking changes in ` as std::fmt::Debug | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in ` as std::cmp::Eq>` +warning: technically breaking changes in ` as std::marker::StructuralEq>` --> log-0.3.8/src/lib.rs:552:10 | 552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] @@ -71,7 +71,7 @@ warning: technically breaking changes in ` as std::fmt::Deb | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in `` +warning: technically breaking changes in `` --> log-0.3.8/src/lib.rs:604:30 | 604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] @@ -157,3 +157,5 @@ warning: path changes to `ShutdownLoggerError` | = note: added definition (technically breaking) +warning: 18 warnings emitted + diff --git a/tests/full_cases/log-0.3.4-0.3.8.osx b/tests/full_cases/log-0.3.4-0.3.8.osx index 19aebffb5f7d7..e77b51cc8b98d 100644 --- a/tests/full_cases/log-0.3.4-0.3.8.osx +++ b/tests/full_cases/log-0.3.4-0.3.8.osx @@ -23,7 +23,7 @@ warning: technically breaking changes in ` as std::fmt::Debug | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in ` as std::cmp::Eq>` +warning: technically breaking changes in ` as std::marker::StructuralEq>` --> log-0.3.8/src/lib.rs:552:10 | 552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] @@ -71,7 +71,7 @@ warning: technically breaking changes in ` as std::fmt::Deb | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in `` +warning: technically breaking changes in `` --> log-0.3.8/src/lib.rs:604:30 | 604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] @@ -157,3 +157,5 @@ warning: path changes to `ShutdownLoggerError` | = note: added definition (technically breaking) +warning: 18 warnings emitted + diff --git a/tests/full_cases/log-0.3.4-0.3.8.windows_msvc b/tests/full_cases/log-0.3.4-0.3.8.windows_msvc index 449ca25265346..68ef6b55d481d 100644 --- a/tests/full_cases/log-0.3.4-0.3.8.windows_msvc +++ b/tests/full_cases/log-0.3.4-0.3.8.windows_msvc @@ -157,3 +157,5 @@ warning: path changes to `ShutdownLoggerError` | = note: added definition (technically breaking) +warning: 18 warnings emitted + diff --git a/tests/full_cases/rmpv-0.4.0-0.4.1.linux b/tests/full_cases/rmpv-0.4.0-0.4.1.linux index 29a6aefddcfb6..92383e1215909 100644 --- a/tests/full_cases/rmpv-0.4.0-0.4.1.linux +++ b/tests/full_cases/rmpv-0.4.0-0.4.1.linux @@ -106,6 +106,6 @@ warning: technically breaking changes in ` Date: Sun, 19 Apr 2020 15:18:29 +0900 Subject: [PATCH 526/553] Fix/suppress clippy warnings --- src/mapping.rs | 8 ++++---- src/mismatch.rs | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/mapping.rs b/src/mapping.rs index f0902245df7d2..11a2ba3758a13 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -48,10 +48,10 @@ impl Hash for InherentEntry { // FIXME derive Hash again once AssocKind derives Hash again. match self.kind { - AssocKind::Const => 0u8.hash(hasher), - AssocKind::Fn => 1u8.hash(hasher), - AssocKind::OpaqueTy => 2u8.hash(hasher), - AssocKind::Type => 3u8.hash(hasher), + AssocKind::Const => 0_u8.hash(hasher), + AssocKind::Fn => 1_u8.hash(hasher), + AssocKind::OpaqueTy => 2_u8.hash(hasher), + AssocKind::Type => 3_u8.hash(hasher), } self.name.hash(hasher); diff --git a/src/mismatch.rs b/src/mismatch.rs index 523dbf5e53f42..10e71b0822f82 100644 --- a/src/mismatch.rs +++ b/src/mismatch.rs @@ -129,6 +129,8 @@ impl<'a, 'tcx> TypeRelation<'tcx> for MismatchRelation<'a, 'tcx> { 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; From d9186edf42f06f707e7b6caa23bcc51b01a5aa01 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 19 Apr 2020 15:35:33 +0900 Subject: [PATCH 527/553] Update xcode version --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 83263b6b4c6e8..1e4ea880e41c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ matrix: env: RUST_BACKTRACE=full - name: "osx" os: osx - osx_image: xcode10 + osx_image: xcode11.3 env: RUST_BACKTRACE=full - name: "windows" os: windows From 550aae2a29df77b7b3317fe858a638b75c7172b0 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 19 Apr 2020 15:43:55 +0900 Subject: [PATCH 528/553] Add `x86_64-pc-windows-msvc` target on CI --- ci/run.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/run.sh b/ci/run.sh index 711acf56ce820..4d995b1fca0ac 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -20,6 +20,7 @@ case "${TRAVIS_OS_NAME}" in TEST_TARGET=x86_64-unknown-linux-gnu cargo test --verbose -- --nocapture ;; *"windows"*) + rustup target add x86_64-pc-windows-msvc TEST_TARGET=x86_64-pc-windows-msvc cargo test --verbose -- --nocapture ;; *"macos"*) From d8595e6eb63aeee79cb9404b258c3e898d669b24 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 19 Apr 2020 16:06:20 +0900 Subject: [PATCH 529/553] Suppress pedantic lints --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1e4ea880e41c1..5807ad3f66ca4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ matrix: - name: "clippy" script: | if rustup component add clippy-preview rustc-dev; then - cargo clippy --all -- -D clippy::pedantic + cargo clippy --all fi - name: "Shellcheck" script: From 249aa30235488e91b555e3eca751311328b92c64 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 15 Mar 2020 18:30:34 +0900 Subject: [PATCH 530/553] Update `cargo` and `crates-io` dependencies --- Cargo.toml | 6 +++--- src/bin/cargo_semver.rs | 35 ++++++++++++++++++----------------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d250bd3f15c2f..e6082eae0be71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,11 +27,11 @@ name = "rust-semver-public" path = "src/bin/rust_semver_public.rs" [dependencies] -cargo = "0.42" -crates-io = "0.30" +cargo = "0.43" +crates-io = "0.31" curl = "0.4.21" env_logger = "0.7" -failure = "0.1" +anyhow = "1.0.27" log = "0.4" rand = "0.7" semver = "0.9" diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index cd7bef755d0bf..2547256ec71f8 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -81,12 +81,13 @@ fn main() { let config_res = config.configure( 0, // verbose quiet, - &None, // color + None, // color false, // frozen false, // locked matches.opt_present("offline"), &None, // target_dir &[], // unstable_flags + &[], // cli_config ); if let Err(e) = config_res { @@ -143,7 +144,7 @@ fn run(config: &cargo::Config, matches: &getopts::Matches) -> Result<()> { .arg("-") .stdin(Stdio::piped()) .spawn() - .map_err(|e| failure::err_msg(format!("could not spawn rustc: {}", e)))?; + .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!( @@ -151,19 +152,19 @@ fn run(config: &cargo::Config, matches: &getopts::Matches) -> Result<()> { extern crate new;" ))?; } else { - return Err(failure::err_msg( + return Err(anyhow::Error::msg( "could not pipe to rustc (wtf?)".to_owned(), )); } let exit_status = child .wait() - .map_err(|e| failure::err_msg(format!("failed to wait for rustc: {}", e)))?; + .map_err(|e| anyhow::Error::msg(format!("failed to wait for rustc: {}", e)))?; return if exit_status.success() { Ok(()) } else { - Err(failure::err_msg("rustc-semver-public errored".to_owned())) + Err(anyhow::Error::msg("rustc-semver-public errored".to_owned())) }; } @@ -239,7 +240,7 @@ fn run(config: &cargo::Config, matches: &getopts::Matches) -> Result<()> { let mut child = child .spawn() - .map_err(|e| failure::err_msg(format!("could not spawn rustc: {}", e)))?; + .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 @@ -251,19 +252,19 @@ fn run(config: &cargo::Config, matches: &getopts::Matches) -> Result<()> { extern crate new;" ))?; } else { - return Err(failure::err_msg( + return Err(anyhow::Error::msg( "could not pipe to rustc (wtf?)".to_owned(), )); } let exit_status = child .wait() - .map_err(|e| failure::err_msg(format!("failed to wait for rustc: {}", e)))?; + .map_err(|e| anyhow::Error::msg(format!("failed to wait for rustc: {}", e)))?; if exit_status.success() { Ok(()) } else { - Err(failure::err_msg("rustc-semverver errored".to_owned())) + Err(anyhow::Error::msg("rustc-semverver errored".to_owned())) } } @@ -353,13 +354,13 @@ mod cli { } /// Validate CLI arguments - pub fn validate_args(matches: &getopts::Matches) -> Result<(), failure::Error> { + 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(failure::err_msg(msg.to_owned())); + return Err(anyhow::Error::msg(msg.to_owned())); } if (matches.opt_present("c") && matches.opt_present("C")) @@ -367,7 +368,7 @@ mod cli { || matches.opt_count("C") > 1 { let msg = "at most one of `-c,--current-path` and `-C,--current-pkg` allowed"; - return Err(failure::err_msg(msg.to_owned())); + return Err(anyhow::Error::msg(msg.to_owned())); } Ok(()) @@ -386,7 +387,7 @@ mod cli { } /// Exit with error `e`. - pub fn exit_with_error(config: &cargo::Config, e: failure::Error) -> ! { + pub fn exit_with_error(config: &cargo::Config, e: anyhow::Error) -> ! { config .shell() .set_verbosity(cargo::core::shell::Verbosity::Normal); @@ -406,7 +407,7 @@ impl<'a> PackageNameAndVersion<'a> { /// Parses the string "name:version" into `Self` pub fn parse(s: &'a str) -> Result { let err = || { - failure::err_msg(format!( + anyhow::Error::msg(format!( "spec has to be of form `name:version` but is `{}`", s )) @@ -536,7 +537,7 @@ impl<'a> WorkInfo<'a> { } } - Err(failure::err_msg("lost build artifact".to_owned())) + Err(anyhow::Error::msg("lost build artifact".to_owned())) } } @@ -552,7 +553,7 @@ pub fn find_on_crates_io(crate_name: &str) -> Result { registry .search(crate_name, 1) .map_err(|e| { - failure::err_msg(format!( + anyhow::Error::msg(format!( "failed to retrieve search results from the registry: {}", e )) @@ -562,7 +563,7 @@ pub fn find_on_crates_io(crate_name: &str) -> Result { .drain(..) .find(|krate| krate.name == crate_name) .ok_or_else(|| { - failure::err_msg(format!("failed to find a matching crate `{}`", crate_name)) + anyhow::Error::msg(format!("failed to find a matching crate `{}`", crate_name)) }) }) } From 9eef88ee218a8e81b7a742133d284c32d4b38fa8 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 30 Apr 2020 04:20:38 +0900 Subject: [PATCH 531/553] Rustup to the latest nightly --- src/mapping.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/mapping.rs b/src/mapping.rs index 11a2ba3758a13..8f1612a94dac5 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -376,6 +376,17 @@ impl NameMapping { 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), From 504c23469d5c5d056d34ad8074026cd4dccc482b Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 6 May 2020 13:37:05 +0900 Subject: [PATCH 532/553] Rustup to the latest nightly --- src/traverse.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/traverse.rs b/src/traverse.rs index f501ca8d7c0b2..b72899e34e36a 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -642,7 +642,7 @@ fn diff_traits<'tcx>( ); diff_generics(changes, id_mapping, tcx, true, old_def_id, new_def_id); - diff_method(changes, tcx, old_item, new_item); + diff_method(changes, tcx, *old_item, *new_item); } (Some(old_item), None) => { let change_type = ChangeType::TraitItemRemoved { @@ -1076,8 +1076,8 @@ fn diff_inherent_impls<'tcx>( tcx, orig_impl_def_id, target_impl_def_id, - orig_assoc_item, - target_assoc_item, + *orig_assoc_item, + *target_assoc_item, ) }); From f65b2689ce448938334fc66cb5ca0cae3c4687ed Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 30 Apr 2020 04:36:44 +0900 Subject: [PATCH 533/553] Update `cargo` and `crates-io` deps --- Cargo.toml | 4 ++-- src/bin/cargo_semver.rs | 8 +------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e6082eae0be71..dbcadfbed3660 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,8 +27,8 @@ name = "rust-semver-public" path = "src/bin/rust_semver_public.rs" [dependencies] -cargo = "0.43" -crates-io = "0.31" +cargo = "0.44" +crates-io = "0.32" curl = "0.4.21" env_logger = "0.7" anyhow = "1.0.27" diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index 2547256ec71f8..e87ff71459e49 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -72,15 +72,9 @@ fn main() { cli::exit_with_error(&config, e); } - let quiet = if matches.opt_present("q") { - Some(true) - } else { - None - }; - let config_res = config.configure( 0, // verbose - quiet, + matches.opt_present("q"), // quiet None, // color false, // frozen false, // locked From ac3af006fffea4b6a3640b643156371595b495ec Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 13 May 2020 01:40:09 +0900 Subject: [PATCH 534/553] Rustup to the latest nightly --- src/mapping.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/mapping.rs b/src/mapping.rs index 8f1612a94dac5..f7aaffda7941d 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -3,7 +3,6 @@ //! 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_ast::ast::Name; use rustc_hir::{ def::Res, def_id::{CrateNum, DefId}, @@ -13,6 +12,7 @@ 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}; @@ -24,7 +24,7 @@ pub struct InherentEntry { /// The kind of the item. pub kind: AssocKind, /// The item's name. - pub name: Name, + pub name: Symbol, } impl Eq for InherentEntry {} @@ -38,7 +38,7 @@ fn assert_inherent_entry_members_impl_eq() { // FIXME derive Eq again once AssocKind impls Eq again. // assert_impl_eq::(); - assert_impl_eq::(); + assert_impl_eq::(); } #[allow(clippy::derive_hash_xor_eq)] @@ -210,7 +210,7 @@ impl IdMapping { &mut self, parent_def_id: DefId, kind: AssocKind, - name: Name, + name: Symbol, impl_def_id: DefId, item_def_id: DefId, ) { @@ -340,11 +340,11 @@ type OptionalExport = Option>; #[cfg_attr(feature = "cargo-clippy", allow(clippy::module_name_repetitions))] pub struct NameMapping { /// The exports in the type namespace. - type_map: HashMap, + type_map: HashMap, /// The exports in the value namespace. - value_map: HashMap, + value_map: HashMap, /// The exports in the macro namespace. - macro_map: HashMap, + macro_map: HashMap, } impl NameMapping { From 128f744fd1ef30d8caa0d587a8c816870b4b3d11 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 20 May 2020 16:00:15 +0900 Subject: [PATCH 535/553] Rustup to the latest nightly --- src/translate.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/translate.rs b/src/translate.rs index bb99b2646a01c..1e65c0867ccaa 100644 --- a/src/translate.rs +++ b/src/translate.rs @@ -362,8 +362,8 @@ impl<'a, 'tcx> TranslationContext<'a, 'tcx> { predicate: Predicate<'tcx>, ) -> Option> { use rustc_middle::ty::{ - Binder, /*EquatePredicate,*/ OutlivesPredicate, ProjectionPredicate, ProjectionTy, - SubtypePredicate, TraitPredicate, + Binder, OutlivesPredicate, ProjectionPredicate, ProjectionTy, SubtypePredicate, + TraitPredicate, }; Some(match predicate { @@ -386,13 +386,6 @@ impl<'a, 'tcx> TranslationContext<'a, 'tcx> { ), constness, ), - /*Predicate::Equate(equate_predicate) => { - Predicate::Equate(equate_predicate.map_bound(|e_pred| { - let l = self.translate(index_map, &e_pred.0); - let r = self.translate(index_map, &e_pred.1); - EquatePredicate(l, r) - })) - },*/ Predicate::RegionOutlives(region_outlives_predicate) => { Predicate::RegionOutlives(region_outlives_predicate.map_bound(|r_pred| { let l = self.translate_region(r_pred.0); @@ -451,6 +444,10 @@ impl<'a, 'tcx> TranslationContext<'a, 'tcx> { return None; } } + Predicate::ConstEquate(c1, c2) => Predicate::ConstEquate( + self.translate(index_map, &c1), + self.translate(index_map, &c2), + ), }) } From fa3fc7a59677ed72dd2207e301548279e39f16ea Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 21 May 2020 01:23:55 +0900 Subject: [PATCH 536/553] Use rustup-toolchain-install-master on CI --- .travis.yml | 2 ++ ci/run.sh | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5807ad3f66ca4..18aa1f9d7b9e1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,8 @@ language: rust rust: nightly sudo: false +cache: cargo + notifications: email: on_failure: always diff --git a/ci/run.sh b/ci/run.sh index 4d995b1fca0ac..30385b2bf1152 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -5,7 +5,13 @@ set -ex export RUST_BACKTRACE=full #export RUST_TEST_NOCAPTURE=1 -rustup component add rustc-dev +cargo +nightly install rustup-toolchain-install-master +if [ "${TRAVIS_OS_NAME}" = "windows" ]; then + rustup-toolchain-install-master -f -n master -c rustc-dev -i x86_64-pc-windows-msvc +else + rustup-toolchain-install-master -f -n master -c rustc-dev +fi +rustup override set master cargo build cargo test --verbose -- --nocapture @@ -20,7 +26,6 @@ case "${TRAVIS_OS_NAME}" in TEST_TARGET=x86_64-unknown-linux-gnu cargo test --verbose -- --nocapture ;; *"windows"*) - rustup target add x86_64-pc-windows-msvc TEST_TARGET=x86_64-pc-windows-msvc cargo test --verbose -- --nocapture ;; *"macos"*) From eab2c00f5858eb5720eaafe5d13b1ec42956dd07 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 21 May 2020 01:48:27 +0900 Subject: [PATCH 537/553] Update stderr file --- tests/full_cases/log-0.3.4-0.3.8.osx | 4 ++-- tests/full_cases/log-0.3.4-0.3.8.windows_msvc | 4 ++-- tests/full_cases/rmpv-0.4.0-0.4.1.windows_msvc | 16 ++++++++-------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/full_cases/log-0.3.4-0.3.8.osx b/tests/full_cases/log-0.3.4-0.3.8.osx index e77b51cc8b98d..6f0122e2e37c7 100644 --- a/tests/full_cases/log-0.3.4-0.3.8.osx +++ b/tests/full_cases/log-0.3.4-0.3.8.osx @@ -23,7 +23,7 @@ warning: technically breaking changes in ` as std::fmt::Debug | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in ` as std::marker::StructuralEq>` +warning: technically breaking changes in ` as std::cmp::Eq>` --> log-0.3.8/src/lib.rs:552:10 | 552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] @@ -71,7 +71,7 @@ warning: technically breaking changes in ` as std::fmt::Deb | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in `` +warning: technically breaking changes in `` --> log-0.3.8/src/lib.rs:604:30 | 604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] diff --git a/tests/full_cases/log-0.3.4-0.3.8.windows_msvc b/tests/full_cases/log-0.3.4-0.3.8.windows_msvc index 68ef6b55d481d..ecd8f1c4bf6e7 100644 --- a/tests/full_cases/log-0.3.4-0.3.8.windows_msvc +++ b/tests/full_cases/log-0.3.4-0.3.8.windows_msvc @@ -23,7 +23,7 @@ warning: technically breaking changes in ` as std::fmt::Debug | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in ` as std::cmp::Eq>` +warning: technically breaking changes in ` as std::marker::StructuralEq>` --> log-0.3.8\src\lib.rs:552:10 | 552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] @@ -71,7 +71,7 @@ warning: technically breaking changes in ` as std::fmt::Deb | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in `` +warning: technically breaking changes in `` --> log-0.3.8\src\lib.rs:604:30 | 604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] diff --git a/tests/full_cases/rmpv-0.4.0-0.4.1.windows_msvc b/tests/full_cases/rmpv-0.4.0-0.4.1.windows_msvc index 92383e1215909..6164e8b4e0e4e 100644 --- a/tests/full_cases/rmpv-0.4.0-0.4.1.windows_msvc +++ b/tests/full_cases/rmpv-0.4.0-0.4.1.windows_msvc @@ -1,6 +1,6 @@ version bump: 0.4.0 -> (breaking) -> 0.4.1 error: breaking changes in `>` - --> rmpv-0.4.0/src/decode/mod.rs:60:1 + --> rmpv-0.4.0\src\decode\mod.rs:60:1 | 60 | / impl From for Error { 61 | | fn from(err: MarkerReadError) -> Error { @@ -12,7 +12,7 @@ error: breaking changes in `>` - --> rmpv-0.4.0/src/decode/mod.rs:66:1 + --> rmpv-0.4.0\src\decode\mod.rs:66:1 | 66 | / impl From for Error { 67 | | fn from(err: ValueReadError) -> Error { @@ -26,7 +26,7 @@ error: breaking changes in ` rmpv-0.4.1/src/encode/value.rs:15:1 + --> rmpv-0.4.1\src\encode\value.rs:15:1 | 15 | / pub fn write_value(wr: &mut W, val: &Value) -> Result<(), Error> 16 | | where W: Write @@ -40,7 +40,7 @@ error: breaking changes in `write_value` = 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 + --> rmpv-0.4.1\src\encode\value_ref.rs:27:1 | 27 | / pub fn write_value_ref(wr: &mut W, val: &ValueRef) -> Result<(), Error> 28 | | where W: Write @@ -54,7 +54,7 @@ error: breaking changes in `write_value_ref` = 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 + --> rmpv-0.4.1\src\lib.rs:253:5 | 253 | / pub fn as_ref(&self) -> Utf8StringRef { 254 | | match self.s { @@ -67,7 +67,7 @@ warning: technically breaking changes in `as_ref` = note: added item in inherent impl (technically breaking) warning: technically breaking changes in `as_ref` - --> rmpv-0.4.1/src/lib.rs:448:5 + --> rmpv-0.4.1\src\lib.rs:448:5 | 448 | / pub fn as_ref(&self) -> ValueRef { 449 | | match self { @@ -81,7 +81,7 @@ warning: technically breaking changes in `as_ref` = note: added item in inherent impl (technically breaking) warning: technically breaking changes in `>` - --> rmpv-0.4.1/src/decode/mod.rs:60:1 + --> rmpv-0.4.1\src\decode\mod.rs:60:1 | 60 | / impl From for Error { 61 | | fn from(err: MarkerReadError) -> Error { @@ -93,7 +93,7 @@ warning: technically breaking changes in `>` - --> rmpv-0.4.1/src/decode/mod.rs:66:1 + --> rmpv-0.4.1\src\decode\mod.rs:66:1 | 66 | / impl From for Error { 67 | | fn from(err: ValueReadError) -> Error { From 411cbcc352d293120003d45a81bc47d973557497 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 21 May 2020 10:15:08 +0900 Subject: [PATCH 538/553] Skip installing semverver on Windows CI --- ci/run.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ci/run.sh b/ci/run.sh index 30385b2bf1152..4443668f551fe 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -33,6 +33,11 @@ case "${TRAVIS_OS_NAME}" in ;; esac +# FIXME: Somehow we couldn't install semverver on Travis' Windows builder. +if [ "${TRAVIS_OS_NAME}" = "windows" ]; then + exit 0 +fi + # install mkdir -p ~/rust/cargo/bin cp target/debug/cargo-semver ~/rust/cargo/bin @@ -59,5 +64,5 @@ if cargo install --root "$(mktemp -d)" semverver > /dev/null 2>/dev/null; then exit 1 fi else - echo 'Failed to check semver-compliance of semverver. Failed to compiled previous version.' >&2 + echo 'Failed to check semver-compliance of semverver. Failed to compiled previous version.' >&2 fi From 19b0f1d980663a30069161d5697b9753de74ffda Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 25 May 2020 14:50:20 +0900 Subject: [PATCH 539/553] Rustup to the latest nightly --- src/translate.rs | 94 +++++++++++++++++++++++++++--------------------- src/traverse.rs | 4 +-- src/typeck.rs | 10 +++--- 3 files changed, 60 insertions(+), 48 deletions(-) diff --git a/src/translate.rs b/src/translate.rs index 1e65c0867ccaa..e5be434c70888 100644 --- a/src/translate.rs +++ b/src/translate.rs @@ -362,12 +362,12 @@ impl<'a, 'tcx> TranslationContext<'a, 'tcx> { predicate: Predicate<'tcx>, ) -> Option> { use rustc_middle::ty::{ - Binder, OutlivesPredicate, ProjectionPredicate, ProjectionTy, SubtypePredicate, - TraitPredicate, + Binder, OutlivesPredicate, PredicateKind, ProjectionPredicate, ProjectionTy, + SubtypePredicate, ToPredicate, TraitPredicate, }; - Some(match predicate { - Predicate::Trait(trait_predicate, constness) => Predicate::Trait( + 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, @@ -384,48 +384,59 @@ impl<'a, 'tcx> TranslationContext<'a, 'tcx> { return None; }, ), - constness, - ), - Predicate::RegionOutlives(region_outlives_predicate) => { - Predicate::RegionOutlives(region_outlives_predicate.map_bound(|r_pred| { + *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) } - Predicate::TypeOutlives(type_outlives_predicate) => { - Predicate::TypeOutlives(type_outlives_predicate.map_bound(|r_pred| { + 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) } - Predicate::Projection(projection_predicate) => Predicate::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; - }, - )), - Predicate::WellFormed(ty) => Predicate::WellFormed(self.translate(index_map, &ty)), - Predicate::ObjectSafe(did) => Predicate::ObjectSafe(self.translate_orig(did)), - Predicate::ClosureKind(did, substs, kind) => Predicate::ClosureKind( - self.translate_orig(did), + 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, - ), - Predicate::Subtype(subtype_predicate) => { - Predicate::Subtype(subtype_predicate.map_bound(|s_pred| { + *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 { @@ -434,20 +445,23 @@ impl<'a, 'tcx> TranslationContext<'a, 'tcx> { b: r, } })) + .to_predicate(self.tcx) } - Predicate::ConstEvaluatable(orig_did, orig_substs) => { + PredicateKind::ConstEvaluatable(orig_did, orig_substs) => { if let Some((target_def_id, target_substs)) = - self.translate_orig_substs(index_map, orig_did, orig_substs) + self.translate_orig_substs(index_map, *orig_did, orig_substs) { - Predicate::ConstEvaluatable(target_def_id, target_substs) + PredicateKind::ConstEvaluatable(target_def_id, target_substs) + .to_predicate(self.tcx) } else { return None; } } - Predicate::ConstEquate(c1, c2) => Predicate::ConstEquate( + PredicateKind::ConstEquate(c1, c2) => PredicateKind::ConstEquate( self.translate(index_map, &c1), self.translate(index_map, &c2), - ), + ) + .to_predicate(self.tcx), }) } diff --git a/src/traverse.rs b/src/traverse.rs index b72899e34e36a..5191318abfa37 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -570,7 +570,7 @@ fn diff_traits<'tcx>( ) { use rustc_hir::Unsafety::Unsafe; use rustc_middle::ty::subst::GenericArgKind::Type; - use rustc_middle::ty::{ParamTy, Predicate, TyS}; + use rustc_middle::ty::{ParamTy, PredicateKind, TyS}; debug!( "diff_traits: old: {:?}, new: {:?}, output: {:?}", @@ -592,7 +592,7 @@ fn diff_traits<'tcx>( let old_param_env = tcx.param_env(old); for bound in old_param_env.caller_bounds { - if let Predicate::Trait(pred, _) = *bound { + if let PredicateKind::Trait(pred, _) = *bound.kind() { let trait_ref = pred.skip_binder().trait_ref; debug!("trait_ref substs (old): {:?}", trait_ref.substs); diff --git a/src/typeck.rs b/src/typeck.rs index 23241318e46cb..91a16b4f25719 100644 --- a/src/typeck.rs +++ b/src/typeck.rs @@ -18,7 +18,7 @@ use rustc_middle::{ error::TypeError, fold::TypeFoldable, subst::{GenericArg, InternalSubsts, SubstsRef}, - GenericParamDefKind, ParamEnv, Predicate, TraitRef, Ty, TyCtxt, + GenericParamDefKind, ParamEnv, Predicate, PredicateKind, ToPredicate, TraitRef, Ty, TyCtxt, }, }; use rustc_trait_selection::traits::FulfillmentContext; @@ -75,12 +75,13 @@ impl<'a, 'tcx> BoundContext<'a, 'tcx> { use rustc_hir::Constness; use rustc_middle::ty::{Binder, TraitPredicate}; - let predicate = Predicate::Trait( + 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); @@ -218,7 +219,6 @@ impl<'a, 'tcx> TypeComparisonContext<'a, 'tcx> { ) -> Option> { use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{InferOk, RegionckMode}; - use rustc_middle::middle::region::ScopeTree; use rustc_middle::ty::Lift; let error = self @@ -230,7 +230,6 @@ impl<'a, 'tcx> TypeComparisonContext<'a, 'tcx> { }); if let Err(err) = error { - let scope_tree = ScopeTree::default(); let outlives_env = OutlivesEnvironment::new(target_param_env); // The old code here added the bounds from the target param env by hand. However, at @@ -246,7 +245,6 @@ impl<'a, 'tcx> TypeComparisonContext<'a, 'tcx> { self.infcx.resolve_regions_and_report_errors( target_def_id, - &scope_tree, &outlives_env, RegionckMode::default(), ); From cca51fd8cc7f804c0279f29f14987a8cac207b0d Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 25 May 2020 15:16:37 +0900 Subject: [PATCH 540/553] Install llvm-tools --- ci/run.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/run.sh b/ci/run.sh index 4443668f551fe..2b5553fbe400e 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -7,9 +7,9 @@ export RUST_BACKTRACE=full cargo +nightly install rustup-toolchain-install-master if [ "${TRAVIS_OS_NAME}" = "windows" ]; then - rustup-toolchain-install-master -f -n master -c rustc-dev -i x86_64-pc-windows-msvc + 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 + rustup-toolchain-install-master -f -n master -c rustc-dev -c llvm-tools fi rustup override set master From b55a3e73dc7d6c5aa87d567a438edc369c80cbd8 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 25 May 2020 15:38:24 +0900 Subject: [PATCH 541/553] Bless tests --- tests/full_cases/log-0.3.4-0.3.8.osx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/full_cases/log-0.3.4-0.3.8.osx b/tests/full_cases/log-0.3.4-0.3.8.osx index 6f0122e2e37c7..e77b51cc8b98d 100644 --- a/tests/full_cases/log-0.3.4-0.3.8.osx +++ b/tests/full_cases/log-0.3.4-0.3.8.osx @@ -23,7 +23,7 @@ warning: technically breaking changes in ` as std::fmt::Debug | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in ` as std::cmp::Eq>` +warning: technically breaking changes in ` as std::marker::StructuralEq>` --> log-0.3.8/src/lib.rs:552:10 | 552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] @@ -71,7 +71,7 @@ warning: technically breaking changes in ` as std::fmt::Deb | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in `` +warning: technically breaking changes in `` --> log-0.3.8/src/lib.rs:604:30 | 604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] From 65cdbd3cde1886e14a9e220674ec23eff763f606 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 29 May 2020 18:26:00 +0900 Subject: [PATCH 542/553] Rustup to the latest nightly --- src/mismatch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mismatch.rs b/src/mismatch.rs index 10e71b0822f82..98ee0e60f931f 100644 --- a/src/mismatch.rs +++ b/src/mismatch.rs @@ -236,7 +236,7 @@ impl<'a, 'tcx> TypeRelation<'tcx> for MismatchRelation<'a, 'tcx> { } } (&TyKind::Tuple(as_), &TyKind::Tuple(bs)) => { - let _ = as_.iter().zip(bs).map(|(a, b)| self.relate(a, b)); + let _ = as_.iter().zip(bs).map(|(a, b)| self.relate(&a, &b)); None } (&TyKind::Projection(a_data), &TyKind::Projection(b_data)) => { From 65217be8178298345343cbe8fc627a18b3a62f43 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 29 May 2020 19:49:15 +0900 Subject: [PATCH 543/553] Reduce cache size --- .travis.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 18aa1f9d7b9e1..462f7f4138d34 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,12 @@ language: rust rust: nightly sudo: false -cache: cargo +cache: + directories: + - $HOME/.cargo + - $HOME/.rustup +before_cache: + - rm -rf /home/travis/.cargo/registry notifications: email: From 5edcb4260bcfe6b6038608966bf61bafb3b1cd9f Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 30 May 2020 02:36:11 +0900 Subject: [PATCH 544/553] Skip semverver installation on macOS as well --- ci/run.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/run.sh b/ci/run.sh index 2b5553fbe400e..d76e82535528e 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -33,8 +33,8 @@ case "${TRAVIS_OS_NAME}" in ;; esac -# FIXME: Somehow we couldn't install semverver on Travis' Windows builder. -if [ "${TRAVIS_OS_NAME}" = "windows" ]; then +# FIXME: Sometimes we couldn't install semverver on Travis' Windows builder. +if [ "${TRAVIS_OS_NAME}" != "linux" ]; then exit 0 fi From b3d60d35751160950df3a2b8e07fa42d840ea990 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 30 May 2020 08:14:01 +0900 Subject: [PATCH 545/553] Setup GitHub Actions --- .github/workflows/ci.yml | 37 ++++++++++++++++++++++++++++++++++ .github/workflows/style.yml | 40 +++++++++++++++++++++++++++++++++++++ ci/run.sh | 22 ++++++++------------ 3 files changed, 85 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/style.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000000..e1addbb824348 --- /dev/null +++ b/.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/.github/workflows/style.yml b/.github/workflows/style.yml new file mode 100644 index 0000000000000..1adab1560eae0 --- /dev/null +++ b/.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/ci/run.sh b/ci/run.sh index d76e82535528e..bf17dd4098ff3 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -2,11 +2,15 @@ set -ex +OS=${1} + export RUST_BACKTRACE=full #export RUST_TEST_NOCAPTURE=1 +rustup update nightly + cargo +nightly install rustup-toolchain-install-master -if [ "${TRAVIS_OS_NAME}" = "windows" ]; then +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 @@ -16,12 +20,7 @@ rustup override set master cargo build cargo test --verbose -- --nocapture -# avoid weird cygwin issues for now -if [ -n "$APPVEYOR" ]; then - exit 0 -fi - -case "${TRAVIS_OS_NAME}" in +case "${OS}" in *"linux"*) TEST_TARGET=x86_64-unknown-linux-gnu cargo test --verbose -- --nocapture ;; @@ -33,11 +32,6 @@ case "${TRAVIS_OS_NAME}" in ;; esac -# FIXME: Sometimes we couldn't install semverver on Travis' Windows builder. -if [ "${TRAVIS_OS_NAME}" != "linux" ]; then - exit 0 -fi - # install mkdir -p ~/rust/cargo/bin cp target/debug/cargo-semver ~/rust/cargo/bin @@ -46,7 +40,7 @@ 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 +# 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 @@ -64,5 +58,5 @@ if cargo install --root "$(mktemp -d)" semverver > /dev/null 2>/dev/null; then exit 1 fi else - echo 'Failed to check semver-compliance of semverver. Failed to compiled previous version.' >&2 + echo 'Failed to check semver-compliance of semverver. Failed to compiled previous version.' >&2 fi From 952b2f09ca2bb9aaf7d81eb45baf452474bbcbf1 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 30 May 2020 08:15:04 +0900 Subject: [PATCH 546/553] Remove AppVeyor and Travis config --- .travis.yml | 46 ---------------------------------------------- appveyor.yml | 21 --------------------- 2 files changed, 67 deletions(-) delete mode 100644 .travis.yml delete mode 100644 appveyor.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 462f7f4138d34..0000000000000 --- a/.travis.yml +++ /dev/null @@ -1,46 +0,0 @@ -language: rust -rust: nightly -sudo: false - -cache: - directories: - - $HOME/.cargo - - $HOME/.rustup -before_cache: - - rm -rf /home/travis/.cargo/registry - -notifications: - email: - on_failure: always - -matrix: - fast_finish: true - include: - # Targets - - name: "linux" - os: linux - env: RUST_BACKTRACE=full - - name: "osx" - os: osx - osx_image: xcode11.3 - env: RUST_BACKTRACE=full - - name: "windows" - os: windows - - # Tools: - - name: "rustfmt" - script: | - if rustup component add rustfmt-preview; then - cargo fmt --all -- --check - fi - - name: "clippy" - script: | - if rustup component add clippy-preview rustc-dev; then - cargo clippy --all - fi - - name: "Shellcheck" - script: - - shellcheck --version - - shellcheck ci/*.sh - -script: sh ci/run.sh diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 7d316a9f77b95..0000000000000 --- a/appveyor.yml +++ /dev/null @@ -1,21 +0,0 @@ -environment: - matrix: - - TARGET: x86_64-pc-windows-msvc - OTHER_TARGET: i686-pc-windows-msvc - -install: - - set PATH=%PATH%;C:\Program Files\Git\mingw64\bin - - curl -sSf -o rustup-init.exe https://win.rustup.rs/ - - rustup-init.exe -y --default-host %TARGET% --default-toolchain nightly - - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin;C:\Users\appveyor\.rustup\toolchains\nightly-%TARGET%\bin - - if defined MSYS2_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS2_BITS%\bin - - rustc -V - - cargo -V - -build: false - -test_script: C:\msys64\usr\bin\sh ci\run.sh - -notifications: - - provider: Email - on_build_success: false From 7f648dcd641e788cc038cd8fa5612c92fe8248a9 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 30 May 2020 09:28:35 +0900 Subject: [PATCH 547/553] Update test --- tests/full_cases/log-0.3.4-0.3.8.windows_msvc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/full_cases/log-0.3.4-0.3.8.windows_msvc b/tests/full_cases/log-0.3.4-0.3.8.windows_msvc index ecd8f1c4bf6e7..68ef6b55d481d 100644 --- a/tests/full_cases/log-0.3.4-0.3.8.windows_msvc +++ b/tests/full_cases/log-0.3.4-0.3.8.windows_msvc @@ -23,7 +23,7 @@ warning: technically breaking changes in ` as std::fmt::Debug | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in ` as std::marker::StructuralEq>` +warning: technically breaking changes in ` as std::cmp::Eq>` --> log-0.3.8\src\lib.rs:552:10 | 552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] @@ -71,7 +71,7 @@ warning: technically breaking changes in ` as std::fmt::Deb | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in `` +warning: technically breaking changes in `` --> log-0.3.8\src\lib.rs:604:30 | 604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] From 0bc63bb971346b1bf53d47b99c7e7828f3b06944 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 30 May 2020 10:40:18 +0900 Subject: [PATCH 548/553] Fix format --- src/bin/cargo_semver.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bin/cargo_semver.rs b/src/bin/cargo_semver.rs index e87ff71459e49..3b3672d57b391 100644 --- a/src/bin/cargo_semver.rs +++ b/src/bin/cargo_semver.rs @@ -73,11 +73,11 @@ fn main() { } let config_res = config.configure( - 0, // verbose + 0, // verbose matches.opt_present("q"), // quiet - None, // color - false, // frozen - false, // locked + None, // color + false, // frozen + false, // locked matches.opt_present("offline"), &None, // target_dir &[], // unstable_flags From 773b25a5568ceb5cde1124101cd2dcce37eec28f Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 2 Jun 2020 19:03:00 +0900 Subject: [PATCH 549/553] Rustup to the latest nightly --- src/changes.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/changes.rs b/src/changes.rs index 9066afa01ed67..ae418b1ff0dbe 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -87,8 +87,8 @@ impl<'a> Serialize for RSpan<'a> { 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 p) = lo.file.name { - format!("{}", p.display()) + let file_name = if let FileName::Real(ref name) = lo.file.name { + format!("{}", name.local_path().display()) } else { "no file name".to_owned() }; From 51d313ebcfa398223cbbb1938bacdebd136377c3 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 2 Jun 2020 20:33:57 +0900 Subject: [PATCH 550/553] Update test --- tests/full_cases/log-0.3.4-0.3.8.windows_msvc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/full_cases/log-0.3.4-0.3.8.windows_msvc b/tests/full_cases/log-0.3.4-0.3.8.windows_msvc index 68ef6b55d481d..ecd8f1c4bf6e7 100644 --- a/tests/full_cases/log-0.3.4-0.3.8.windows_msvc +++ b/tests/full_cases/log-0.3.4-0.3.8.windows_msvc @@ -23,7 +23,7 @@ warning: technically breaking changes in ` as std::fmt::Debug | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in ` as std::cmp::Eq>` +warning: technically breaking changes in ` as std::marker::StructuralEq>` --> log-0.3.8\src\lib.rs:552:10 | 552 | #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] @@ -71,7 +71,7 @@ warning: technically breaking changes in ` as std::fmt::Deb | = note: trait impl generalized or newly added (technically breaking) -warning: technically breaking changes in `` +warning: technically breaking changes in `` --> log-0.3.8\src\lib.rs:604:30 | 604 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] From f726125f629a8b0415f8c55e88bf5e48ffdd788f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 30 Jun 2020 22:21:18 +0300 Subject: [PATCH 551/553] tidy, rustfmt: skip src/tools/semverver. --- rustfmt.toml | 1 + src/tools/tidy/src/lib.rs | 1 + 2 files changed, 2 insertions(+) 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/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", From 0527be99a27d9d0a0b68b8a70fec4ba0b821febd Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 30 Jun 2020 21:42:36 +0300 Subject: [PATCH 552/553] bootstrap: test that src/tools/semverver builds. --- Cargo.lock | 47 ++++++++++++++++++- Cargo.toml | 4 ++ config.toml.example | 2 +- src/bootstrap/builder.rs | 6 ++- src/bootstrap/check.rs | 10 ++-- src/bootstrap/test.rs | 39 +++++++++++++++ src/bootstrap/tool.rs | 7 +++ .../x86_64-gnu-tools/checktools.sh | 2 +- src/tools/semverver/Cargo.toml | 7 ++- 9 files changed, 115 insertions(+), 9 deletions(-) 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/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 3cbecbbaa06cb..8764d3e23ee81 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -372,6 +372,9 @@ impl<'a> Builder<'a> { tool::Rustdoc, tool::Clippy, tool::CargoClippy, + tool::Semverver, + tool::SemverPublic, + tool::CargoSemver, native::Llvm, native::Sanitizers, tool::Rustfmt, @@ -380,7 +383,7 @@ impl<'a> Builder<'a> { native::Lld ), Kind::Check | Kind::Clippy | Kind::Fix | Kind::Format => { - describe!(check::Std, check::Rustc, check::Rustdoc, check::Clippy) + describe!(check::Std, check::Rustc, check::Rustdoc, check::Clippy, check::Semverver) } Kind::Test => describe!( crate::toolstate::ToolStateCheck, @@ -426,6 +429,7 @@ impl<'a> Builder<'a> { test::RustdocJSNotStd, test::RustdocTheme, test::RustdocUi, + test::Semverver, // Run bootstrap close to the end as it's unlikely to fail test::Bootstrap, // Run run-make last, since these won't pass without make on Windows diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 0d38d2eebe793..9b209915b2f2f 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -196,11 +196,13 @@ macro_rules! tool_check_step { } tool_check_step!(Rustdoc, "src/tools/rustdoc", SourceType::InTree); -// Clippy is a hybrid. It is an external tool, but uses a git subtree instead -// of a submodule. Since the SourceType only drives the deny-warnings -// behavior, treat it as in-tree so that any new warnings in clippy will be -// rejected. +// Clippy and semverver are hybrids. They're external tools, but use git subtrees +// instead of submodules. Since the SourceType only drives the deny-warnings +// behavior, treat it as in-tree so that any new warnings will be rejected. tool_check_step!(Clippy, "src/tools/clippy", SourceType::InTree); +// FIXME(eddyb) use `InTree` here as per the comment above, when Cargo can build +// with deny-warnings + `-Wrust_2018_idioms` (which it can't today). +tool_check_step!(Semverver, "src/tools/semverver", SourceType::Submodule); /// Cargo's output path for the standard library in a given stage, compiled /// by a particular compiler for the specified target. diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 77bcc00d75b2b..cb4ed39528e90 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -559,6 +559,45 @@ impl Step for Clippy { } } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Semverver { + stage: u32, + host: Interned, +} + +impl Step for Semverver { + type Output = (); + const ONLY_HOSTS: bool = true; + const DEFAULT: bool = false; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/semverver") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(Semverver { stage: run.builder.top_stage, host: run.target }); + } + + /// Runs `cargo test` for semverver. + fn run(self, builder: &Builder<'_>) { + let stage = self.stage; + let host = self.host; + let compiler = builder.compiler(stage, host); + + builder + .ensure(tool::CargoSemver { compiler, target: self.host, extra_features: Vec::new() }) + .expect("in-tree tool"); + builder + .ensure(tool::Semverver { compiler, target: self.host, extra_features: Vec::new() }) + .expect("in-tree tool"); + builder + .ensure(tool::SemverPublic { compiler, target: self.host, extra_features: Vec::new() }) + .expect("in-tree tool"); + + // FIXME(eddyb) actually run tests from `src/tools/semverver`. + } +} + fn path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString { // Configure PATH to find the right rustc. NB. we have to use PATH // and not RUSTC because the Cargo test suite has tests that will diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 450b534d5dfdb..7dbb0f8ebf0b5 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -237,6 +237,7 @@ pub fn prepare_tool_cargo( || path.ends_with("clippy") || path.ends_with("miri") || path.ends_with("rustfmt") + || path.ends_with("semverver") { cargo.env("LIBZ_SYS_STATIC", "1"); features.push("rustc-workspace-hack/all-static".to_string()); @@ -604,6 +605,7 @@ macro_rules! tool_extended { |tools| { tools.iter().any(|tool| match tool.as_ref() { "clippy" => $tool_name == "clippy-driver", + "semverver" => $tool_name == "rust-semverver", x => $tool_name == x, }) }), @@ -659,6 +661,11 @@ tool_extended!((self, builder), }; Rustfmt, rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, {}; RustAnalyzer, rust_analyzer, "src/tools/rust-analyzer/crates/rust-analyzer", "rust-analyzer", stable=false, {}; + // FIXME(eddyb) use `in_tree=true` for semverver, when Cargo can build + // with deny-warnings + `-Wrust_2018_idioms` (which it can't today). + CargoSemver, semverver, "src/tools/semverver", "cargo-semver", stable=false, {}; + Semverver, semverver, "src/tools/semverver", "rust-semverver", stable=false, {}; + SemverPublic, semverver, "src/tools/semverver", "rust-semver-public", stable=false, {}; ); impl<'a> Builder<'a> { diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh index b4b23a245e0aa..fc13b3b492e05 100755 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh @@ -23,4 +23,4 @@ set -e # debugging: print out the saved toolstates cat /tmp/toolstate/toolstates.json python3 "$X_PY" test check-tools -python3 "$X_PY" test src/tools/clippy +python3 "$X_PY" test src/tools/clippy src/tools/semverver diff --git a/src/tools/semverver/Cargo.toml b/src/tools/semverver/Cargo.toml index dbcadfbed3660..efe182cc48874 100644 --- a/src/tools/semverver/Cargo.toml +++ b/src/tools/semverver/Cargo.toml @@ -27,7 +27,7 @@ name = "rust-semver-public" path = "src/bin/rust_semver_public.rs" [dependencies] -cargo = "0.44" +cargo = "0.47" crates-io = "0.32" curl = "0.4.21" env_logger = "0.7" @@ -40,3 +40,8 @@ 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" From be7f4b35b53fe65f5a9e5b2af9fde3e45fa33044 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 30 Jun 2020 23:19:57 +0300 Subject: [PATCH 553/553] semverver: update for rustc and Cargo changes. --- src/tools/semverver/src/bin/cargo_semver.rs | 5 +-- src/tools/semverver/src/mapping.rs | 6 ++-- src/tools/semverver/src/mismatch.rs | 36 ++++++++++----------- src/tools/semverver/src/translate.rs | 8 ++--- 4 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/tools/semverver/src/bin/cargo_semver.rs b/src/tools/semverver/src/bin/cargo_semver.rs index 3b3672d57b391..600af2aafb6ed 100644 --- a/src/tools/semverver/src/bin/cargo_semver.rs +++ b/src/tools/semverver/src/bin/cargo_semver.rs @@ -481,7 +481,7 @@ impl<'a> WorkInfo<'a> { 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_kind = kind; + opts.build_config.requested_kinds = vec![kind]; } } @@ -526,7 +526,8 @@ impl<'a> WorkInfo<'a> { for i in &build_plan.invocations { if let Some(kind) = i.target_kind.get(0) { if kind.contains("lib") && i.package_name == name { - return Ok((i.outputs[0].clone(), compilation.deps_output)); + // FIXME(eddyb) handle multiple targets. + return Ok((i.outputs[0].clone(), compilation.deps_output.into_iter().next().unwrap().1)); } } } diff --git a/src/tools/semverver/src/mapping.rs b/src/tools/semverver/src/mapping.rs index f7aaffda7941d..9de89d1dd7682 100644 --- a/src/tools/semverver/src/mapping.rs +++ b/src/tools/semverver/src/mapping.rs @@ -50,8 +50,7 @@ impl Hash for InherentEntry { match self.kind { AssocKind::Const => 0_u8.hash(hasher), AssocKind::Fn => 1_u8.hash(hasher), - AssocKind::OpaqueTy => 2_u8.hash(hasher), - AssocKind::Type => 3_u8.hash(hasher), + AssocKind::Type => 2_u8.hash(hasher), } self.name.hash(hasher); @@ -366,8 +365,7 @@ impl NameMapping { TraitAlias | // TODO: will need some handling later on AssocTy | TyParam | - OpaqueTy | - AssocOpaqueTy => Some(&mut self.type_map), + OpaqueTy => Some(&mut self.type_map), Fn | Const | ConstParam | diff --git a/src/tools/semverver/src/mismatch.rs b/src/tools/semverver/src/mismatch.rs index 98ee0e60f931f..9b83e30dc1c01 100644 --- a/src/tools/semverver/src/mismatch.rs +++ b/src/tools/semverver/src/mismatch.rs @@ -79,7 +79,7 @@ impl<'a, 'tcx> MismatchRelation<'a, 'tcx> { 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); + let _ = self.relate(old_ty, new_ty); } } @@ -118,13 +118,13 @@ impl<'a, 'tcx> TypeRelation<'tcx> for MismatchRelation<'a, 'tcx> { fn relate_with_variance>( &mut self, _: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { self.relate(a, b) } - fn relate>(&mut self, a: &T, b: &T) -> RelateResult<'tcx, T> { + fn relate>(&mut self, a: T, b: T) -> RelateResult<'tcx, T> { debug!("relate: mismatch relation: a: {:?}, b: {:?}", a, b); Relate::relate(self, a, b) } @@ -135,7 +135,7 @@ impl<'a, 'tcx> TypeRelation<'tcx> for MismatchRelation<'a, 'tcx> { use rustc_middle::ty::TyKind; if self.current_old_types.contains(a) || self.current_new_types.contains(b) { - return Ok(self.tcx.types.err); + return Ok(self.tcx.ty_error()); } self.current_old_types.insert(a); @@ -161,7 +161,7 @@ impl<'a, 'tcx> TypeRelation<'tcx> for MismatchRelation<'a, 'tcx> { { let b_field_ty = b_field.ty(self.tcx, b_substs); - let _ = self.relate(&a_field_ty, &b_field_ty)?; + let _ = self.relate(a_field_ty, b_field_ty)?; } } @@ -188,16 +188,16 @@ impl<'a, 'tcx> TypeRelation<'tcx> for MismatchRelation<'a, 'tcx> { } (&TyKind::Array(a_t, _), &TyKind::Array(b_t, _)) | (&TyKind::Slice(a_t), &TyKind::Slice(b_t)) => { - let _ = self.relate(&a_t, &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)?; + 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)?; + 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)) => { @@ -214,17 +214,17 @@ impl<'a, 'tcx> TypeRelation<'tcx> for MismatchRelation<'a, 'tcx> { Some((a, b)) } (&TyKind::FnPtr(a_fty), &TyKind::FnPtr(b_fty)) => { - let _ = self.relate(&a_fty, &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 _ = 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 _ = 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)) @@ -236,11 +236,11 @@ impl<'a, 'tcx> TypeRelation<'tcx> for MismatchRelation<'a, 'tcx> { } } (&TyKind::Tuple(as_), &TyKind::Tuple(bs)) => { - let _ = as_.iter().zip(bs).map(|(a, b)| self.relate(&a, &b)); + 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 _ = 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); @@ -279,7 +279,7 @@ impl<'a, 'tcx> TypeRelation<'tcx> for MismatchRelation<'a, 'tcx> { } } - Ok(self.tcx.types.err) + Ok(self.tcx.ty_error()) } fn regions( @@ -300,8 +300,8 @@ impl<'a, 'tcx> TypeRelation<'tcx> for MismatchRelation<'a, 'tcx> { fn binders>( &mut self, - a: &ty::Binder, - b: &ty::Binder, + a: ty::Binder, + b: ty::Binder, ) -> RelateResult<'tcx, ty::Binder> { Ok(ty::Binder::bind( self.relate(a.skip_binder(), b.skip_binder())?, diff --git a/src/tools/semverver/src/translate.rs b/src/tools/semverver/src/translate.rs index e5be434c70888..944ed0acbdea3 100644 --- a/src/tools/semverver/src/translate.rs +++ b/src/tools/semverver/src/translate.rs @@ -208,10 +208,10 @@ impl<'a, 'tcx> TranslationContext<'a, 'tcx> { let res: Vec<_> = preds .iter() .map(|p| { - match *p.skip_binder() { + match p.skip_binder() { Trait(existential_trait_ref) => { let trait_ref = Binder::bind(existential_trait_ref) - .with_self_ty(self.tcx, self.tcx.types.err); + .with_self_ty(self.tcx, self.tcx.ty_error()); let did = trait_ref.skip_binder().def_id; let substs = trait_ref.skip_binder().substs; @@ -234,7 +234,7 @@ impl<'a, 'tcx> TranslationContext<'a, 'tcx> { } Projection(existential_projection) => { let projection_pred = Binder::bind(existential_projection) - .with_self_ty(self.tcx, self.tcx.types.err); + .with_self_ty(self.tcx, self.tcx.ty_error()); let item_def_id = projection_pred.skip_binder().projection_ty.item_def_id; let substs = @@ -561,7 +561,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for InferenceCleanupFolder<'a, 'tcx> { .tcx .mk_ref(self.infcx.tcx.lifetimes.re_erased, ty_and_mut) } - TyKind::Infer(_) => self.infcx.tcx.mk_ty(TyKind::Error), + TyKind::Infer(_) => self.infcx.tcx.ty_error(), _ => t1, } }