From 8205c348b4a793878a1cda06ebbc93860e9fea0c Mon Sep 17 00:00:00 2001 From: Yorwba Date: Thu, 22 Jun 2017 17:07:38 +0800 Subject: [PATCH 01/10] Note different versions of same crate when absolute paths of different types match. --- src/librustc/infer/error_reporting/mod.rs | 5 ++- .../type-mismatch-same-crate-name/Makefile | 19 ++++++++++ .../type-mismatch-same-crate-name/crateA.rs | 26 ++++++++++++++ .../type-mismatch-same-crate-name/crateB.rs | 14 ++++++++ .../type-mismatch-same-crate-name/crateC.rs | 35 +++++++++++++++++++ 5 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 src/test/run-make/type-mismatch-same-crate-name/Makefile create mode 100644 src/test/run-make/type-mismatch-same-crate-name/crateA.rs create mode 100644 src/test/run-make/type-mismatch-same-crate-name/crateB.rs create mode 100644 src/test/run-make/type-mismatch-same-crate-name/crateC.rs diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 11bac21bc429e..2265c0c0a8c70 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -337,9 +337,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate { let exp_path = self.tcx.item_path_str(did1); let found_path = self.tcx.item_path_str(did2); + let exp_abs_path = self.tcx.absolute_item_path_str(did1); + let found_abs_path = self.tcx.absolute_item_path_str(did2); // We compare strings because DefPath can be different // for imported and non-imported crates - if exp_path == found_path { + if exp_path == found_path + || exp_abs_path == found_abs_path { let crate_name = self.tcx.sess.cstore.crate_name(did1.krate); err.span_note(sp, &format!("Perhaps two different versions \ of crate `{}` are being used?", diff --git a/src/test/run-make/type-mismatch-same-crate-name/Makefile b/src/test/run-make/type-mismatch-same-crate-name/Makefile new file mode 100644 index 0000000000000..24ef203278a74 --- /dev/null +++ b/src/test/run-make/type-mismatch-same-crate-name/Makefile @@ -0,0 +1,19 @@ +-include ../tools.mk + +all: + # compile two different versions of crateA + $(RUSTC) --crate-type=rlib crateA.rs -C metadata=-1 -C extra-filename=-1 + $(RUSTC) --crate-type=rlib crateA.rs -C metadata=-2 -C extra-filename=-2 + # make crateB depend on version 1 of crateA + $(RUSTC) --crate-type=rlib crateB.rs --extern crateA=$(TMPDIR)/libcrateA-1.rlib + # make crateC depend on version 2 of crateA + $(RUSTC) crateC.rs --extern crateA=$(TMPDIR)/libcrateA-2.rlib 2>&1 | \ + grep -z \ + "mismatched types.*\ + crateB::try_foo(foo2);.*\ + expected struct \`crateA::foo::Foo\`, found struct \`crateA::Foo\`.*\ + different versions of crate \`crateA\`.*\ + mismatched types.*\ + crateB::try_bar(bar2);.*\ + expected trait \`crateA::bar::Bar\`, found trait \`crateA::Bar\`.*\ + different versions of crate \`crateA\`" diff --git a/src/test/run-make/type-mismatch-same-crate-name/crateA.rs b/src/test/run-make/type-mismatch-same-crate-name/crateA.rs new file mode 100644 index 0000000000000..e40266bb4cdaa --- /dev/null +++ b/src/test/run-make/type-mismatch-same-crate-name/crateA.rs @@ -0,0 +1,26 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// 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. + +mod foo { + pub struct Foo; +} + +mod bar { + pub trait Bar{} + + pub fn bar() -> Box { + unimplemented!() + } +} + +// This makes the publicly accessible path +// differ from the internal one. +pub use foo::Foo; +pub use bar::{Bar, bar}; diff --git a/src/test/run-make/type-mismatch-same-crate-name/crateB.rs b/src/test/run-make/type-mismatch-same-crate-name/crateB.rs new file mode 100644 index 0000000000000..da4ea1c9387e9 --- /dev/null +++ b/src/test/run-make/type-mismatch-same-crate-name/crateB.rs @@ -0,0 +1,14 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// 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. + +extern crate crateA; + +pub fn try_foo(x: crateA::Foo){} +pub fn try_bar(x: Box){} diff --git a/src/test/run-make/type-mismatch-same-crate-name/crateC.rs b/src/test/run-make/type-mismatch-same-crate-name/crateC.rs new file mode 100644 index 0000000000000..da869d2145fe1 --- /dev/null +++ b/src/test/run-make/type-mismatch-same-crate-name/crateC.rs @@ -0,0 +1,35 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// 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. + +// This tests the extra note reported when a type error deals with +// seemingly identical types. +// The main use case of this error is when there are two crates +// (generally different versions of the same crate) with the same name +// causing a type mismatch. + +// The test is nearly the same as the one in +// compile-fail/type-mismatch-same-crate-name.rs +// but deals with the case where one of the crates +// is only introduced as an indirect dependency. +// and the type is accessed via a reexport. +// This is similar to how the error can be introduced +// when using cargo's automatic dependency resolution. + +extern crate crateA; + +fn main() { + let foo2 = crateA::Foo; + let bar2 = crateA::bar(); + { + extern crate crateB; + crateB::try_foo(foo2); + crateB::try_bar(bar2); + } +} From b9a44fc489a55ebdcc04b09067e2ab9164f30810 Mon Sep 17 00:00:00 2001 From: Ryan Thomas Date: Thu, 22 Jun 2017 19:50:56 +0100 Subject: [PATCH 02/10] Update docs for fmt::write. I reworded it slightly to make it more clear that the function only take two arguments - the output and the Arguments struct that can be generated from the format_args! macro. r? @steveklabnik --- src/libcore/fmt/mod.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 8c3d3ce7d886b..bcc6d53c81d3b 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -897,14 +897,11 @@ pub trait UpperExp { fn fmt(&self, f: &mut Formatter) -> Result; } -/// The `write` function takes an output stream, a precompiled format string, -/// and a list of arguments. The arguments will be formatted according to the -/// specified format string into the output stream provided. +/// The `write` function takes an output stream, and an `Arguments` struct +/// that can be precompiled with the `format_args!` macro. /// -/// # Arguments -/// -/// * output - the buffer to write output to -/// * args - the precompiled arguments generated by `format_args!` +/// The arguments will be formatted according to the specified format string +/// into the output stream provided. /// /// # Examples /// From c5d078fd8cf554aa1ee6e6b3a0d670ca9afa4054 Mon Sep 17 00:00:00 2001 From: Ryan Thomas Date: Thu, 22 Jun 2017 20:02:57 +0100 Subject: [PATCH 03/10] Update docs for std::fmt::format #29355. This rewords and removes the `Arguments` section from the docs for fmt::format. r? @steveklabnik --- src/liballoc/fmt.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index 62a8816462191..3afce884b1183 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -498,12 +498,10 @@ pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; use string; -/// The format function takes a precompiled format string and a list of -/// arguments, to return the resulting formatted string. +/// The `format` function takes an `Arguments` struct and returns the resulting +/// formatted string. /// -/// # Arguments -/// -/// * args - a structure of arguments generated via the `format_args!` macro. +/// The `Arguments` instance can be created with the `format_args!` macro. /// /// # Examples /// From d24d408af387e99e7237f21e9a8d13a35552e01a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 25 Jun 2017 11:33:47 -0700 Subject: [PATCH 04/10] std: Fix implementation of `Alloc::alloc_one` This had an accidental `u8 as *mut T` where it was intended to have just a normal pointer-to-pointer cast. Closes #42827 --- src/liballoc/allocator.rs | 2 +- src/test/run-pass/allocator-alloc-one.rs | 27 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/allocator-alloc-one.rs diff --git a/src/liballoc/allocator.rs b/src/liballoc/allocator.rs index 9bddce29957e1..bf38629ed38a7 100644 --- a/src/liballoc/allocator.rs +++ b/src/liballoc/allocator.rs @@ -873,7 +873,7 @@ pub unsafe trait Alloc { { let k = Layout::new::(); if k.size() > 0 { - unsafe { self.alloc(k).map(|p|Unique::new(*p as *mut T)) } + unsafe { self.alloc(k).map(|p| Unique::new(p as *mut T)) } } else { Err(AllocErr::invalid_input("zero-sized type invalid for alloc_one")) } diff --git a/src/test/run-pass/allocator-alloc-one.rs b/src/test/run-pass/allocator-alloc-one.rs new file mode 100644 index 0000000000000..7cc547dcc04e2 --- /dev/null +++ b/src/test/run-pass/allocator-alloc-one.rs @@ -0,0 +1,27 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// 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. + +#![feature(alloc, allocator_api, heap_api, unique)] + +extern crate alloc; + +use alloc::heap::HeapAlloc; +use alloc::allocator::Alloc; + +fn main() { + unsafe { + let ptr = HeapAlloc.alloc_one::().unwrap_or_else(|e| { + HeapAlloc.oom(e) + }); + *ptr.as_ptr() = 4; + assert_eq!(*ptr.as_ptr(), 4); + HeapAlloc.dealloc_one(ptr); + } +} From 71252d9b80020d932aa7960a3930684489a6e167 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Tue, 27 Jun 2017 12:09:56 +0200 Subject: [PATCH 05/10] Document possible `io::ErrorKind`s of `fs::open` Try to make clear that this isn't an API guarantee for now, as we likely want to refine these errors in the future, e.g. `ENOSPC` "No space left on device". CC #40322 --- src/libstd/fs.rs | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 5b8c0c339900d..f1ec4d2dff01d 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -653,15 +653,29 @@ impl OpenOptions { /// # Errors /// /// This function will return an error under a number of different - /// circumstances, to include but not limited to: - /// - /// * Opening a file that does not exist without setting `create` or - /// `create_new`. - /// * Attempting to open a file with access that the user lacks - /// permissions for - /// * Filesystem-level errors (full disk, etc) - /// * Invalid combinations of open options (truncate without write access, - /// no access mode set, etc) + /// circumstances. Some of these error conditions are listed here, together + /// with their [`ErrorKind`]. The mapping to `ErrorKind`s is not part of + /// the compatiblity contract of the function, especially the `Other` kind + /// might change to more specific kinds in the future. + /// + /// * `NotFound`: The specified file does not exist and neither `create` or + /// `create_new` is set, + /// * `NotFound`: One of the directory components of the file path does not + /// exist. + /// * `PermissionDenied`: The user lacks permission to get the specified + /// access rights for the file. + /// * `PermissionDenied`: The user lacks permission to open one of the + /// directory components of the specified path. + /// * `AlreadyExists`: `create_new` was specified and the file already + /// exists. + /// * `InvalidInput`: Invalid combinations of open options (truncate + /// without write access, no access mode set, etc.). + /// * `Other`: One of the directory components of the specified file path + /// was not, in fact, a directory. + /// * `Other`: Filesystem-level errors: full disk, write permission + /// requested on a read-only file system, exceeded disk quota, too many + /// open files, too long filename, too many symbolic links in the + /// specified path (Unix-like systems only), etc. /// /// # Examples /// @@ -670,6 +684,8 @@ impl OpenOptions { /// /// let file = OpenOptions::new().open("foo.txt"); /// ``` + /// + /// [`ErrorKind`]: ../io/enum.ErrorKind.html #[stable(feature = "rust1", since = "1.0.0")] pub fn open>(&self, path: P) -> io::Result { self._open(path.as_ref()) From 4fb67dcf8f51e0a875ec7f00a3ef2649758b9b9a Mon Sep 17 00:00:00 2001 From: Andreas Sommer Date: Wed, 28 Jun 2017 10:55:57 +0200 Subject: [PATCH 06/10] Fix link reference --- src/doc/unstable-book/src/language-features/compile-error.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/unstable-book/src/language-features/compile-error.md b/src/doc/unstable-book/src/language-features/compile-error.md index 1b25eeda3f662..4b24c0a6a0d39 100644 --- a/src/doc/unstable-book/src/language-features/compile-error.md +++ b/src/doc/unstable-book/src/language-features/compile-error.md @@ -2,7 +2,7 @@ The tracking issue for this feature is: [#40872] -[#29599]: https://github.com/rust-lang/rust/issues/40872 +[#40872]: https://github.com/rust-lang/rust/issues/40872 ------------------------ From 2783d0f7dac17f764c6580a04877e6813be574d2 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Wed, 28 Jun 2017 13:43:56 +0200 Subject: [PATCH 07/10] Add links to the `ErrorKind` variants in errors of `open` --- src/libstd/fs.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index f1ec4d2dff01d..88994b284c90d 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -654,25 +654,25 @@ impl OpenOptions { /// /// This function will return an error under a number of different /// circumstances. Some of these error conditions are listed here, together - /// with their [`ErrorKind`]. The mapping to `ErrorKind`s is not part of + /// with their [`ErrorKind`]. The mapping to [`ErrorKind`]s is not part of /// the compatiblity contract of the function, especially the `Other` kind /// might change to more specific kinds in the future. /// - /// * `NotFound`: The specified file does not exist and neither `create` or - /// `create_new` is set, - /// * `NotFound`: One of the directory components of the file path does not - /// exist. - /// * `PermissionDenied`: The user lacks permission to get the specified + /// * [`NotFound`]: The specified file does not exist and neither `create` + /// or `create_new` is set. + /// * [`NotFound`]: One of the directory components of the file path does + /// not exist. + /// * [`PermissionDenied`]: The user lacks permission to get the specified /// access rights for the file. - /// * `PermissionDenied`: The user lacks permission to open one of the + /// * [`PermissionDenied`]: The user lacks permission to open one of the /// directory components of the specified path. - /// * `AlreadyExists`: `create_new` was specified and the file already + /// * [`AlreadyExists`]: `create_new` was specified and the file already /// exists. - /// * `InvalidInput`: Invalid combinations of open options (truncate + /// * [`InvalidInput`]: Invalid combinations of open options (truncate /// without write access, no access mode set, etc.). - /// * `Other`: One of the directory components of the specified file path + /// * [`Other`]: One of the directory components of the specified file path /// was not, in fact, a directory. - /// * `Other`: Filesystem-level errors: full disk, write permission + /// * [`Other`]: Filesystem-level errors: full disk, write permission /// requested on a read-only file system, exceeded disk quota, too many /// open files, too long filename, too many symbolic links in the /// specified path (Unix-like systems only), etc. @@ -686,6 +686,11 @@ impl OpenOptions { /// ``` /// /// [`ErrorKind`]: ../io/enum.ErrorKind.html + /// [`AlreadyExists`]: ../io/enum.ErrorKind.html#variant.AlreadyExists + /// [`InvalidInput`]: ../io/enum.ErrorKind.html#variant.InvalidInput + /// [`NotFound`]: ../io/enum.ErrorKind.html#variant.NotFound + /// [`Other`]: ../io/enum.ErrorKind.html#variant.Other + /// [`PermissionDenied`]: ../io/enum.ErrorKind.html#variant.PermissionDenied #[stable(feature = "rust1", since = "1.0.0")] pub fn open>(&self, path: P) -> io::Result { self._open(path.as_ref()) From 40dec0984ed2040532ac763f104b3bbbc13f514a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 28 Jun 2017 23:14:06 +0300 Subject: [PATCH 08/10] Document that `/` works as separator on Windows --- src/libstd/path.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 42a54ed6d754c..472ce6bc4fe9e 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -276,7 +276,7 @@ impl<'a> Prefix<'a> { /// ``` /// use std::path; /// -/// assert!(path::is_separator('/')); +/// assert!(path::is_separator('/')); // '/' works for both Unix and Windows /// assert!(!path::is_separator('❤')); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -1499,9 +1499,9 @@ impl AsRef for PathBuf { /// A slice of a path (akin to [`str`]). /// /// This type supports a number of operations for inspecting a path, including -/// breaking the path into its components (separated by `/` or `\`, depending on -/// the platform), extracting the file name, determining whether the path is -/// absolute, and so on. +/// breaking the path into its components (separated by `/` on Unix and by either +/// `/` or `\` on Windows), extracting the file name, determining whether the path +/// is absolute, and so on. /// /// This is an *unsized* type, meaning that it must always be used behind a /// pointer like `&` or [`Box`]. For an owned version of this type, @@ -1520,10 +1520,11 @@ impl AsRef for PathBuf { /// use std::path::Path; /// use std::ffi::OsStr; /// -/// let path = Path::new("/tmp/foo/bar.txt"); +/// // Note: this example does work on Windows +/// let path = Path::new("./foo/bar.txt"); /// /// let parent = path.parent(); -/// assert_eq!(parent, Some(Path::new("/tmp/foo"))); +/// assert_eq!(parent, Some(Path::new("./foo"))); /// /// let file_stem = path.file_stem(); /// assert_eq!(file_stem, Some(OsStr::new("bar"))); From b689e46c628ea8f71f45709c969b19c220baa49c Mon Sep 17 00:00:00 2001 From: Aidan Hobson Sayers Date: Wed, 28 Jun 2017 22:54:05 +0100 Subject: [PATCH 09/10] Stamp the whole build script --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index b95196da356c8..96163c75c9d9d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -171,16 +171,16 @@ before_script: if [[ "$SKIP_BUILD" == true ]]; then export RUN_SCRIPT="echo 'skipping, not a full build'"; else - RUN_SCRIPT="stamp src/ci/init_repo.sh . $HOME/rustsrc"; + RUN_SCRIPT="src/ci/init_repo.sh . $HOME/rustsrc"; if [ "$TRAVIS_OS_NAME" = "osx" ]; then - export RUN_SCRIPT="$RUN_SCRIPT && stamp src/ci/run.sh"; + export RUN_SCRIPT="$RUN_SCRIPT && src/ci/run.sh"; else - export RUN_SCRIPT="$RUN_SCRIPT && stamp src/ci/docker/run.sh $IMAGE"; + export RUN_SCRIPT="$RUN_SCRIPT && src/ci/docker/run.sh $IMAGE"; fi fi script: - - sh -x -c "$RUN_SCRIPT" + - stamp sh -x -c "$RUN_SCRIPT" after_success: - > From 984e76468b34c6874220cc2fbce9dc2f98c6eecc Mon Sep 17 00:00:00 2001 From: Aidan Hobson Sayers Date: Wed, 28 Jun 2017 23:05:29 +0100 Subject: [PATCH 10/10] Record some details to help with possible bad clocks --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index 96163c75c9d9d..21877ecb43e10 100644 --- a/.travis.yml +++ b/.travis.yml @@ -179,8 +179,14 @@ before_script: fi fi +# Log time information from this machine and an external machine for insight into possible +# clock drift. Timezones don't matter since relative deltas give all the necessary info. script: + - > + date && curl -s --head https://google.com | grep ^Date: | sed 's/Date: //g' - stamp sh -x -c "$RUN_SCRIPT" + - > + date && curl -s --head https://google.com | grep ^Date: | sed 's/Date: //g' after_success: - >