mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-06 20:28:33 +00:00
Auto merge of #45907 - kennytm:rollup, r=kennytm
Rollup of 9 pull requests - Successful merges: #45783, #45856, #45863, #45869, #45878, #45882, #45887, #45895, #45901 - Failed merges:
This commit is contained in:
commit
c0d326f06d
10
.travis.yml
10
.travis.yml
@ -253,7 +253,14 @@ after_failure:
|
|||||||
|
|
||||||
# Random attempt at debugging currently. Just poking around in here to see if
|
# Random attempt at debugging currently. Just poking around in here to see if
|
||||||
# anything shows up.
|
# anything shows up.
|
||||||
- ls $HOME/Library/Logs/DiagnosticReports/
|
- ls -lat $HOME/Library/Logs/DiagnosticReports/
|
||||||
|
- find $HOME/Library/Logs/DiagnosticReports/ ! \(
|
||||||
|
-name '*.stage2-*.crash'
|
||||||
|
-name 'com.apple.CoreSimulator.CoreSimulatorService-*.crash'
|
||||||
|
\)
|
||||||
|
-exec echo -e travis_fold":start:crashlog\n\033[31;1m" {} "\033[0m" \;
|
||||||
|
-exec head -750 {} \;
|
||||||
|
-exec echo travis_fold":"end:crashlog \;
|
||||||
|
|
||||||
# attempt to debug anything killed by the oom killer on linux, just to see if
|
# attempt to debug anything killed by the oom killer on linux, just to see if
|
||||||
# it happened
|
# it happened
|
||||||
@ -286,6 +293,7 @@ before_deploy:
|
|||||||
rm -rf obj/build/dist/doc &&
|
rm -rf obj/build/dist/doc &&
|
||||||
cp -r obj/build/dist/* deploy/$TRAVIS_COMMIT;
|
cp -r obj/build/dist/* deploy/$TRAVIS_COMMIT;
|
||||||
fi
|
fi
|
||||||
|
- travis_retry gem update --system
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
- provider: s3
|
- provider: s3
|
||||||
|
2
src/Cargo.lock
generated
2
src/Cargo.lock
generated
@ -348,7 +348,9 @@ dependencies = [
|
|||||||
"getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
"getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -22,6 +22,48 @@ Images will output artifacts in an `obj` dir at the root of a repository.
|
|||||||
- `scripts` contains files shared by docker images
|
- `scripts` contains files shared by docker images
|
||||||
- `disabled` contains images that are not built on travis
|
- `disabled` contains images that are not built on travis
|
||||||
|
|
||||||
|
## Docker Toolbox on Windows
|
||||||
|
|
||||||
|
For Windows before Windows 10, the docker images can be run on Windows via
|
||||||
|
[Docker Toolbox]. There are several preparation needs to be made before running
|
||||||
|
a Docker image.
|
||||||
|
|
||||||
|
1. Stop the virtual machine from the terminal with `docker-machine stop`
|
||||||
|
|
||||||
|
2. If your Rust source is placed outside of `C:\Users\**`, e.g. if you place the
|
||||||
|
repository in the `E:\rust` folder, please add a shared folder from
|
||||||
|
VirtualBox by:
|
||||||
|
|
||||||
|
1. Select the "default" virtual machine inside VirtualBox, then click
|
||||||
|
"Settings"
|
||||||
|
2. Go to "Shared Folders", click "Add shared foldrer" (the folder icon with
|
||||||
|
a plus sign), fill in the following information, then click "OK":
|
||||||
|
|
||||||
|
* Folder path: `E:\rust`
|
||||||
|
* Folder name: `e/rust`
|
||||||
|
* Read-only: ☐ *unchecked*
|
||||||
|
* Auto-mount: ☑ *checked*
|
||||||
|
* Make Permanant: ☑ *checked*
|
||||||
|
|
||||||
|
3. VirtualBox might not support creating symbolic links inside a shared folder
|
||||||
|
by default. You can enable it manually by running these from `cmd.exe`:
|
||||||
|
|
||||||
|
```bat
|
||||||
|
cd "C:\Program Files\Oracle\VirtualBox"
|
||||||
|
VBoxManage setextradata default VBoxInternal2/SharedFoldersEnableSymlinksCreate/e/rust 1
|
||||||
|
:: ^~~~~~
|
||||||
|
:: folder name
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Restart the virtual machine from terminal with `docker-machine start`.
|
||||||
|
|
||||||
|
To run the image,
|
||||||
|
|
||||||
|
1. Launch the "Docker Quickstart Terminal".
|
||||||
|
2. Execute `./src/ci/docker/run.sh $image_name` as explained at the beginning.
|
||||||
|
|
||||||
|
[Docker Toolbox]: https://www.docker.com/products/docker-toolbox
|
||||||
|
|
||||||
## Cross toolchains
|
## Cross toolchains
|
||||||
|
|
||||||
A number of these images take quite a long time to compile as they're building
|
A number of these images take quite a long time to compile as they're building
|
||||||
@ -137,7 +179,7 @@ For targets: `armv7-unknown-linux-gnueabihf`
|
|||||||
libraries like jemalloc. See the mk/cfg/arm(v7)-uknown-linux-gnueabi{,hf}.mk
|
libraries like jemalloc. See the mk/cfg/arm(v7)-uknown-linux-gnueabi{,hf}.mk
|
||||||
file in Rust's source code.
|
file in Rust's source code.
|
||||||
|
|
||||||
## `aarch64-linux-gnu.config`
|
### `aarch64-linux-gnu.config`
|
||||||
|
|
||||||
For targets: `aarch64-unknown-linux-gnu`
|
For targets: `aarch64-unknown-linux-gnu`
|
||||||
|
|
||||||
@ -150,7 +192,7 @@ For targets: `aarch64-unknown-linux-gnu`
|
|||||||
- C compiler > gcc version = 5.2.0
|
- C compiler > gcc version = 5.2.0
|
||||||
- C compiler > C++ = ENABLE -- to cross compile LLVM
|
- C compiler > C++ = ENABLE -- to cross compile LLVM
|
||||||
|
|
||||||
## `powerpc-linux-gnu.config`
|
### `powerpc-linux-gnu.config`
|
||||||
|
|
||||||
For targets: `powerpc-unknown-linux-gnu`
|
For targets: `powerpc-unknown-linux-gnu`
|
||||||
|
|
||||||
@ -165,7 +207,7 @@ For targets: `powerpc-unknown-linux-gnu`
|
|||||||
- C compiler > gcc version = 4.9.3
|
- C compiler > gcc version = 4.9.3
|
||||||
- C compiler > C++ = ENABLE -- to cross compile LLVM
|
- C compiler > C++ = ENABLE -- to cross compile LLVM
|
||||||
|
|
||||||
## `powerpc64-linux-gnu.config`
|
### `powerpc64-linux-gnu.config`
|
||||||
|
|
||||||
For targets: `powerpc64-unknown-linux-gnu`
|
For targets: `powerpc64-unknown-linux-gnu`
|
||||||
|
|
||||||
@ -184,7 +226,7 @@ For targets: `powerpc64-unknown-linux-gnu`
|
|||||||
|
|
||||||
(+) These CPU options match the configuration of the toolchains in RHEL6.
|
(+) These CPU options match the configuration of the toolchains in RHEL6.
|
||||||
|
|
||||||
## `s390x-linux-gnu.config`
|
### `s390x-linux-gnu.config`
|
||||||
|
|
||||||
For targets: `s390x-unknown-linux-gnu`
|
For targets: `s390x-unknown-linux-gnu`
|
||||||
|
|
||||||
|
@ -23,9 +23,9 @@ SYSROOT=/usr/local/$TARGET/sysroot
|
|||||||
mkdir -p $SYSROOT
|
mkdir -p $SYSROOT
|
||||||
pushd $SYSROOT
|
pushd $SYSROOT
|
||||||
|
|
||||||
centos_base=http://mirror.centos.org/altarch/7/os/ppc64le/Packages
|
centos_base=http://vault.centos.org/altarch/7.3.1611/os/ppc64le/Packages/
|
||||||
glibc_v=2.17-196.el7
|
glibc_v=2.17-157.el7
|
||||||
kernel_v=3.10.0-693.el7
|
kernel_v=3.10.0-514.el7
|
||||||
for package in glibc{,-devel,-headers}-$glibc_v kernel-headers-$kernel_v; do
|
for package in glibc{,-devel,-headers}-$glibc_v kernel-headers-$kernel_v; do
|
||||||
curl $centos_base/$package.ppc64le.rpm | \
|
curl $centos_base/$package.ppc64le.rpm | \
|
||||||
rpm2cpio - | cpio -idm
|
rpm2cpio - | cpio -idm
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
export MSYS_NO_PATHCONV=1
|
||||||
|
|
||||||
script=`cd $(dirname $0) && pwd`/`basename $0`
|
script=`cd $(dirname $0) && pwd`/`basename $0`
|
||||||
image=$1
|
image=$1
|
||||||
|
|
||||||
@ -25,12 +27,19 @@ travis_fold start build_docker
|
|||||||
travis_time_start
|
travis_time_start
|
||||||
|
|
||||||
if [ -f "$docker_dir/$image/Dockerfile" ]; then
|
if [ -f "$docker_dir/$image/Dockerfile" ]; then
|
||||||
|
dockerfile="$docker_dir/$image/Dockerfile"
|
||||||
|
if [ -x /usr/bin/cygpath ]; then
|
||||||
|
context="`cygpath -w $docker_dir`"
|
||||||
|
dockerfile="`cygpath -w $dockerfile`"
|
||||||
|
else
|
||||||
|
context="$docker_dir"
|
||||||
|
fi
|
||||||
retry docker \
|
retry docker \
|
||||||
build \
|
build \
|
||||||
--rm \
|
--rm \
|
||||||
-t rust-ci \
|
-t rust-ci \
|
||||||
-f "$docker_dir/$image/Dockerfile" \
|
-f "$dockerfile" \
|
||||||
"$docker_dir"
|
"$context"
|
||||||
elif [ -f "$docker_dir/disabled/$image/Dockerfile" ]; then
|
elif [ -f "$docker_dir/disabled/$image/Dockerfile" ]; then
|
||||||
if [ -n "$TRAVIS_OS_NAME" ]; then
|
if [ -n "$TRAVIS_OS_NAME" ]; then
|
||||||
echo Cannot run disabled images on travis!
|
echo Cannot run disabled images on travis!
|
||||||
|
@ -363,16 +363,16 @@ impl str {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let mut v = String::from("🗻∈🌏");
|
/// let v = String::from("🗻∈🌏");
|
||||||
///
|
///
|
||||||
/// assert_eq!(Some("🗻"), v.get(0..4));
|
/// assert_eq!(Some("🗻"), v.get(0..4));
|
||||||
///
|
///
|
||||||
/// // indices not on UTF-8 sequence boundaries
|
/// // indices not on UTF-8 sequence boundaries
|
||||||
/// assert!(v.get_mut(1..).is_none());
|
/// assert!(v.get(1..).is_none());
|
||||||
/// assert!(v.get_mut(..8).is_none());
|
/// assert!(v.get(..8).is_none());
|
||||||
///
|
///
|
||||||
/// // out of bounds
|
/// // out of bounds
|
||||||
/// assert!(v.get_mut(..42).is_none());
|
/// assert!(v.get(..42).is_none());
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "str_checked_slicing", since = "1.20.0")]
|
#[stable(feature = "str_checked_slicing", since = "1.20.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -525,6 +525,26 @@ impl<'a> Display for Arguments<'a> {
|
|||||||
#[lang = "debug_trait"]
|
#[lang = "debug_trait"]
|
||||||
pub trait Debug {
|
pub trait Debug {
|
||||||
/// Formats the value using the given formatter.
|
/// Formats the value using the given formatter.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::fmt;
|
||||||
|
///
|
||||||
|
/// struct Position {
|
||||||
|
/// longitude: f32,
|
||||||
|
/// latitude: f32,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// impl fmt::Debug for Position {
|
||||||
|
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
/// write!(f, "({:?}, {:?})", self.longitude, self.latitude)
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// assert_eq!("(1.987, 2.983)".to_owned(),
|
||||||
|
/// format!("{:?}", Position { longitude: 1.987, latitude: 2.983, }));
|
||||||
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result;
|
fn fmt(&self, f: &mut Formatter) -> Result;
|
||||||
}
|
}
|
||||||
|
@ -120,6 +120,9 @@ macro_rules! assert_eq {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
($left:expr, $right:expr,) => ({
|
||||||
|
assert_eq!($left, $right)
|
||||||
|
});
|
||||||
($left:expr, $right:expr, $($arg:tt)+) => ({
|
($left:expr, $right:expr, $($arg:tt)+) => ({
|
||||||
match (&($left), &($right)) {
|
match (&($left), &($right)) {
|
||||||
(left_val, right_val) => {
|
(left_val, right_val) => {
|
||||||
@ -168,6 +171,9 @@ macro_rules! assert_ne {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
($left:expr, $right:expr,) => {
|
||||||
|
assert_ne!($left, $right)
|
||||||
|
};
|
||||||
($left:expr, $right:expr, $($arg:tt)+) => ({
|
($left:expr, $right:expr, $($arg:tt)+) => ({
|
||||||
match (&($left), &($right)) {
|
match (&($left), &($right)) {
|
||||||
(left_val, right_val) => {
|
(left_val, right_val) => {
|
||||||
|
@ -607,6 +607,45 @@ impl<T> Option<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `None` if the option is `None`, otherwise calls `predicate`
|
||||||
|
/// with the wrapped value and returns:
|
||||||
|
///
|
||||||
|
/// - `Some(t)` if `predicate` returns `true` (where `t` is the wrapped
|
||||||
|
/// value), and
|
||||||
|
/// - `None` if `predicate` returns `false`.
|
||||||
|
///
|
||||||
|
/// This function works similar to `Iterator::filter()`. You can imagine
|
||||||
|
/// the `Option<T>` being an iterator over one or zero elements. `filter()`
|
||||||
|
/// lets you decide which elements to keep.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// #![feature(option_filter)]
|
||||||
|
///
|
||||||
|
/// fn is_even(n: &i32) -> bool {
|
||||||
|
/// n % 2 == 0
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// assert_eq!(None.filter(is_even), None);
|
||||||
|
/// assert_eq!(Some(3).filter(is_even), None);
|
||||||
|
/// assert_eq!(Some(4).filter(is_even), Some(4));
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "option_filter", issue = "45860")]
|
||||||
|
pub fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Self {
|
||||||
|
match self {
|
||||||
|
Some(x) => {
|
||||||
|
if predicate(&x) {
|
||||||
|
Some(x)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the option if it contains a value, otherwise returns `optb`.
|
/// Returns the option if it contains a value, otherwise returns `optb`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
@ -927,6 +927,7 @@ impl<T> AtomicPtr<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_has_atomic = "ptr")]
|
||||||
#[stable(feature = "atomic_from", since = "1.23.0")]
|
#[stable(feature = "atomic_from", since = "1.23.0")]
|
||||||
impl<T> From<*mut T> for AtomicPtr<T> {
|
impl<T> From<*mut T> for AtomicPtr<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -37,7 +37,7 @@ const UNKNOWN_SIZE_COST: usize = 10;
|
|||||||
|
|
||||||
pub struct Inline;
|
pub struct Inline;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
struct CallSite<'tcx> {
|
struct CallSite<'tcx> {
|
||||||
callee: DefId,
|
callee: DefId,
|
||||||
substs: &'tcx Substs<'tcx>,
|
substs: &'tcx Substs<'tcx>,
|
||||||
@ -113,7 +113,9 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
|||||||
loop {
|
loop {
|
||||||
local_change = false;
|
local_change = false;
|
||||||
while let Some(callsite) = callsites.pop_front() {
|
while let Some(callsite) = callsites.pop_front() {
|
||||||
|
debug!("checking whether to inline callsite {:?}", callsite);
|
||||||
if !self.tcx.is_mir_available(callsite.callee) {
|
if !self.tcx.is_mir_available(callsite.callee) {
|
||||||
|
debug!("checking whether to inline callsite {:?} - MIR unavailable", callsite);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,10 +135,12 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let start = caller_mir.basic_blocks().len();
|
let start = caller_mir.basic_blocks().len();
|
||||||
|
debug!("attempting to inline callsite {:?} - mir={:?}", callsite, callee_mir);
|
||||||
if !self.inline_call(callsite, caller_mir, callee_mir) {
|
if !self.inline_call(callsite, caller_mir, callee_mir) {
|
||||||
|
debug!("attempting to inline callsite {:?} - failure", callsite);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
debug!("attempting to inline callsite {:?} - success", callsite);
|
||||||
|
|
||||||
// Add callsites from inlined function
|
// Add callsites from inlined function
|
||||||
for (bb, bb_data) in caller_mir.basic_blocks().iter_enumerated().skip(start) {
|
for (bb, bb_data) in caller_mir.basic_blocks().iter_enumerated().skip(start) {
|
||||||
@ -180,16 +184,19 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
|||||||
callee_mir: &Mir<'tcx>)
|
callee_mir: &Mir<'tcx>)
|
||||||
-> bool
|
-> bool
|
||||||
{
|
{
|
||||||
|
debug!("should_inline({:?})", callsite);
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
|
|
||||||
// Don't inline closures that have captures
|
// Don't inline closures that have captures
|
||||||
// FIXME: Handle closures better
|
// FIXME: Handle closures better
|
||||||
if callee_mir.upvar_decls.len() > 0 {
|
if callee_mir.upvar_decls.len() > 0 {
|
||||||
|
debug!(" upvar decls present - not inlining");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cannot inline generators which haven't been transformed yet
|
// Cannot inline generators which haven't been transformed yet
|
||||||
if callee_mir.yield_ty.is_some() {
|
if callee_mir.yield_ty.is_some() {
|
||||||
|
debug!(" yield ty present - not inlining");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,7 +208,10 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
|||||||
// there are cases that prevent inlining that we
|
// there are cases that prevent inlining that we
|
||||||
// need to check for first.
|
// need to check for first.
|
||||||
attr::InlineAttr::Always => true,
|
attr::InlineAttr::Always => true,
|
||||||
attr::InlineAttr::Never => return false,
|
attr::InlineAttr::Never => {
|
||||||
|
debug!("#[inline(never)] present - not inlining");
|
||||||
|
return false
|
||||||
|
}
|
||||||
attr::InlineAttr::Hint => true,
|
attr::InlineAttr::Hint => true,
|
||||||
attr::InlineAttr::None => false,
|
attr::InlineAttr::None => false,
|
||||||
};
|
};
|
||||||
@ -211,6 +221,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
|||||||
// reference unexported symbols
|
// reference unexported symbols
|
||||||
if callsite.callee.is_local() {
|
if callsite.callee.is_local() {
|
||||||
if callsite.substs.types().count() == 0 && !hinted {
|
if callsite.substs.types().count() == 0 && !hinted {
|
||||||
|
debug!(" callee is an exported function - not inlining");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,6 +243,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
|||||||
if callee_mir.basic_blocks().len() <= 3 {
|
if callee_mir.basic_blocks().len() <= 3 {
|
||||||
threshold += threshold / 4;
|
threshold += threshold / 4;
|
||||||
}
|
}
|
||||||
|
debug!(" final inline threshold = {}", threshold);
|
||||||
|
|
||||||
// FIXME: Give a bonus to functions with only a single caller
|
// FIXME: Give a bonus to functions with only a single caller
|
||||||
|
|
||||||
@ -327,12 +339,17 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Inline cost for {:?} is {}", callsite.callee, cost);
|
|
||||||
|
|
||||||
if let attr::InlineAttr::Always = hint {
|
if let attr::InlineAttr::Always = hint {
|
||||||
|
debug!("INLINING {:?} because inline(always) [cost={}]", callsite, cost);
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
cost <= threshold
|
if cost <= threshold {
|
||||||
|
debug!("INLINING {:?} [cost={} <= threshold={}]", callsite, cost, threshold);
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
debug!("NOT inlining {:?} [cost={} > threshold={}]", callsite, cost, threshold);
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ impl<'a> Resolver<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemKind::ExternCrate(_) => {
|
ItemKind::ExternCrate(as_name) => {
|
||||||
self.crate_loader.process_item(item, &self.definitions);
|
self.crate_loader.process_item(item, &self.definitions);
|
||||||
|
|
||||||
// n.b. we don't need to look at the path option here, because cstore already did
|
// n.b. we don't need to look at the path option here, because cstore already did
|
||||||
@ -265,7 +265,7 @@ impl<'a> Resolver<'a> {
|
|||||||
id: item.id,
|
id: item.id,
|
||||||
parent,
|
parent,
|
||||||
imported_module: Cell::new(Some(module)),
|
imported_module: Cell::new(Some(module)),
|
||||||
subclass: ImportDirectiveSubclass::ExternCrate,
|
subclass: ImportDirectiveSubclass::ExternCrate(as_name),
|
||||||
span: item.span,
|
span: item.span,
|
||||||
module_path: Vec::new(),
|
module_path: Vec::new(),
|
||||||
vis: Cell::new(vis),
|
vis: Cell::new(vis),
|
||||||
|
@ -120,7 +120,7 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) {
|
|||||||
_ if directive.used.get() ||
|
_ if directive.used.get() ||
|
||||||
directive.vis.get() == ty::Visibility::Public ||
|
directive.vis.get() == ty::Visibility::Public ||
|
||||||
directive.span.source_equal(&DUMMY_SP) => {}
|
directive.span.source_equal(&DUMMY_SP) => {}
|
||||||
ImportDirectiveSubclass::ExternCrate => {
|
ImportDirectiveSubclass::ExternCrate(_) => {
|
||||||
resolver.maybe_unused_extern_crates.push((directive.id, directive.span));
|
resolver.maybe_unused_extern_crates.push((directive.id, directive.span));
|
||||||
}
|
}
|
||||||
ImportDirectiveSubclass::MacroUse => {
|
ImportDirectiveSubclass::MacroUse => {
|
||||||
|
@ -1118,7 +1118,7 @@ impl<'a> NameBinding<'a> {
|
|||||||
match self.kind {
|
match self.kind {
|
||||||
NameBindingKind::Import {
|
NameBindingKind::Import {
|
||||||
directive: &ImportDirective {
|
directive: &ImportDirective {
|
||||||
subclass: ImportDirectiveSubclass::ExternCrate, ..
|
subclass: ImportDirectiveSubclass::ExternCrate(_), ..
|
||||||
}, ..
|
}, ..
|
||||||
} => true,
|
} => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
@ -1132,6 +1132,15 @@ impl<'a> NameBinding<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_renamed_extern_crate(&self) -> bool {
|
||||||
|
if let NameBindingKind::Import { directive, ..} = self.kind {
|
||||||
|
if let ImportDirectiveSubclass::ExternCrate(Some(_)) = directive.subclass {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn is_glob_import(&self) -> bool {
|
fn is_glob_import(&self) -> bool {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
NameBindingKind::Import { directive, .. } => directive.is_glob(),
|
NameBindingKind::Import { directive, .. } => directive.is_glob(),
|
||||||
@ -3700,7 +3709,8 @@ impl<'a> Resolver<'a> {
|
|||||||
let cm = self.session.codemap();
|
let cm = self.session.codemap();
|
||||||
let rename_msg = "You can use `as` to change the binding name of the import";
|
let rename_msg = "You can use `as` to change the binding name of the import";
|
||||||
|
|
||||||
if let Ok(snippet) = cm.span_to_snippet(binding.span) {
|
if let (Ok(snippet), false) = (cm.span_to_snippet(binding.span),
|
||||||
|
binding.is_renamed_extern_crate()) {
|
||||||
err.span_suggestion(binding.span,
|
err.span_suggestion(binding.span,
|
||||||
rename_msg,
|
rename_msg,
|
||||||
format!("{} as Other{}", snippet, name));
|
format!("{} as Other{}", snippet, name));
|
||||||
|
@ -23,7 +23,7 @@ use rustc::hir::def_id::DefId;
|
|||||||
use rustc::hir::def::*;
|
use rustc::hir::def::*;
|
||||||
use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
use syntax::ast::{Ident, SpannedIdent, NodeId};
|
use syntax::ast::{Ident, Name, SpannedIdent, NodeId};
|
||||||
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
|
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
|
||||||
use syntax::ext::hygiene::Mark;
|
use syntax::ext::hygiene::Mark;
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
@ -48,7 +48,7 @@ pub enum ImportDirectiveSubclass<'a> {
|
|||||||
max_vis: Cell<ty::Visibility>, // The visibility of the greatest reexport.
|
max_vis: Cell<ty::Visibility>, // The visibility of the greatest reexport.
|
||||||
// n.b. `max_vis` is only used in `finalize_import` to check for reexport errors.
|
// n.b. `max_vis` is only used in `finalize_import` to check for reexport errors.
|
||||||
},
|
},
|
||||||
ExternCrate,
|
ExternCrate(Option<Name>),
|
||||||
MacroUse,
|
MacroUse,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -923,7 +923,7 @@ fn import_directive_subclass_to_string(subclass: &ImportDirectiveSubclass) -> St
|
|||||||
match *subclass {
|
match *subclass {
|
||||||
SingleImport { source, .. } => source.to_string(),
|
SingleImport { source, .. } => source.to_string(),
|
||||||
GlobImport { .. } => "*".to_string(),
|
GlobImport { .. } => "*".to_string(),
|
||||||
ExternCrate => "<extern crate>".to_string(),
|
ExternCrate(_) => "<extern crate>".to_string(),
|
||||||
MacroUse => "#[macro_use]".to_string(),
|
MacroUse => "#[macro_use]".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -671,11 +671,12 @@ fn link_natively(sess: &Session,
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
sess.struct_warn("looks like the linker segfaulted when we tried to \
|
warn!(
|
||||||
call it, automatically retrying again")
|
"looks like the linker segfaulted when we tried to call it, \
|
||||||
.note(&format!("{:?}", cmd))
|
automatically retrying again. cmd = {:?}, out = {}.",
|
||||||
.note(&out)
|
cmd,
|
||||||
.emit();
|
out,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
match prog {
|
match prog {
|
||||||
|
@ -71,6 +71,7 @@ use std::thread;
|
|||||||
use std::time::{Instant, Duration};
|
use std::time::{Instant, Duration};
|
||||||
|
|
||||||
const TEST_WARN_TIMEOUT_S: u64 = 60;
|
const TEST_WARN_TIMEOUT_S: u64 = 60;
|
||||||
|
const QUIET_MODE_MAX_COLUMN: usize = 100; // insert a '\n' after 100 tests in quiet mode
|
||||||
|
|
||||||
// to be used by rustc to compile tests in libtest
|
// to be used by rustc to compile tests in libtest
|
||||||
pub mod test {
|
pub mod test {
|
||||||
@ -614,7 +615,14 @@ impl<T: Write> ConsoleTestState<T> {
|
|||||||
pub fn write_short_result(&mut self, verbose: &str, quiet: &str, color: term::color::Color)
|
pub fn write_short_result(&mut self, verbose: &str, quiet: &str, color: term::color::Color)
|
||||||
-> io::Result<()> {
|
-> io::Result<()> {
|
||||||
if self.quiet {
|
if self.quiet {
|
||||||
self.write_pretty(quiet, color)
|
self.write_pretty(quiet, color)?;
|
||||||
|
if self.current_test_count() % QUIET_MODE_MAX_COLUMN == QUIET_MODE_MAX_COLUMN - 1 {
|
||||||
|
// we insert a new line every 100 dots in order to flush the
|
||||||
|
// screen when dealing with line-buffered output (e.g. piping to
|
||||||
|
// `stamp` in the rust CI).
|
||||||
|
self.write_plain("\n")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
self.write_pretty(verbose, color)?;
|
self.write_pretty(verbose, color)?;
|
||||||
self.write_plain("\n")
|
self.write_plain("\n")
|
||||||
@ -771,9 +779,12 @@ impl<T: Write> ConsoleTestState<T> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn current_test_count(&self) -> usize {
|
||||||
|
self.passed + self.failed + self.ignored + self.measured + self.allowed_fail
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write_run_finish(&mut self) -> io::Result<bool> {
|
pub fn write_run_finish(&mut self) -> io::Result<bool> {
|
||||||
assert!(self.passed + self.failed + self.ignored + self.measured +
|
assert!(self.current_test_count() == self.total);
|
||||||
self.allowed_fail == self.total);
|
|
||||||
|
|
||||||
if self.options.display_output {
|
if self.options.display_output {
|
||||||
self.write_outputs()?;
|
self.write_outputs()?;
|
||||||
|
@ -18,5 +18,6 @@ extern crate libc as alloc;
|
|||||||
//~^ ERROR E0259
|
//~^ ERROR E0259
|
||||||
//~| NOTE `alloc` reimported here
|
//~| NOTE `alloc` reimported here
|
||||||
//~| NOTE `alloc` must be defined only once in the type namespace of this module
|
//~| NOTE `alloc` must be defined only once in the type namespace of this module
|
||||||
|
//~| NOTE You can use `as` to change the binding name of the import
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -48,8 +48,8 @@ macro_rules! test_c {
|
|||||||
});
|
});
|
||||||
|
|
||||||
($fval:expr, f* -> $ity:ident, $ival:expr) => (
|
($fval:expr, f* -> $ity:ident, $ival:expr) => (
|
||||||
test!($fval, f32 -> $ity, $ival);
|
test_c!($fval, f32 -> $ity, $ival);
|
||||||
test!($fval, f64 -> $ity, $ival);
|
test_c!($fval, f64 -> $ity, $ival);
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
error: unexpected end of macro invocation
|
|
||||||
--> $DIR/assert_eq_trailing_comma.rs:12:20
|
|
||||||
|
|
|
||||||
12 | assert_eq!(1, 1,);
|
|
||||||
| ^
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
|||||||
error: unexpected end of macro invocation
|
|
||||||
--> $DIR/assert_ne_trailing_comma.rs:12:20
|
|
||||||
|
|
|
||||||
12 | assert_ne!(1, 2,);
|
|
||||||
| ^
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
11
src/test/ui/suggestions/auxiliary/m1.rs
Normal file
11
src/test/ui/suggestions/auxiliary/m1.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// 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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
pub fn foo() {}
|
11
src/test/ui/suggestions/auxiliary/m2.rs
Normal file
11
src/test/ui/suggestions/auxiliary/m2.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// 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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
pub fn bar() {}
|
18
src/test/ui/suggestions/extern-crate-rename.rs
Normal file
18
src/test/ui/suggestions/extern-crate-rename.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// 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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// aux-build:m1.rs
|
||||||
|
// aux-build:m2.rs
|
||||||
|
|
||||||
|
|
||||||
|
extern crate m1;
|
||||||
|
extern crate m2 as m1;
|
||||||
|
|
||||||
|
fn main() {}
|
15
src/test/ui/suggestions/extern-crate-rename.stderr
Normal file
15
src/test/ui/suggestions/extern-crate-rename.stderr
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
error[E0259]: the name `m1` is defined multiple times
|
||||||
|
--> $DIR/extern-crate-rename.rs:16:1
|
||||||
|
|
|
||||||
|
15 | extern crate m1;
|
||||||
|
| ---------------- previous import of the extern crate `m1` here
|
||||||
|
16 | extern crate m2 as m1;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| `m1` reimported here
|
||||||
|
| You can use `as` to change the binding name of the import
|
||||||
|
|
|
||||||
|
= note: `m1` must be defined only once in the type namespace of this module
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
@ -11,3 +11,7 @@ getopts = "0.2"
|
|||||||
log = "0.3"
|
log = "0.3"
|
||||||
rustc-serialize = "0.3"
|
rustc-serialize = "0.3"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
|
||||||
|
[target.'cfg(windows)'.dependencies]
|
||||||
|
miow = "0.2"
|
||||||
|
winapi = "0.2"
|
||||||
|
@ -11,10 +11,11 @@
|
|||||||
#![crate_name = "compiletest"]
|
#![crate_name = "compiletest"]
|
||||||
|
|
||||||
#![feature(test)]
|
#![feature(test)]
|
||||||
|
#![feature(slice_rotate)]
|
||||||
|
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
#[cfg(unix)]
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
extern crate test;
|
extern crate test;
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
@ -47,6 +48,7 @@ pub mod runtest;
|
|||||||
pub mod common;
|
pub mod common;
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
mod raise_fd_limit;
|
mod raise_fd_limit;
|
||||||
|
mod read2;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
env_logger::init().unwrap();
|
env_logger::init().unwrap();
|
||||||
|
208
src/tools/compiletest/src/read2.rs
Normal file
208
src/tools/compiletest/src/read2.rs
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
// 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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// FIXME: This is a complete copy of `cargo/src/cargo/util/read2.rs`
|
||||||
|
// Consider unify the read2() in libstd, cargo and this to prevent further code duplication.
|
||||||
|
|
||||||
|
pub use self::imp::read2;
|
||||||
|
|
||||||
|
#[cfg(not(any(unix, windows)))]
|
||||||
|
mod imp {
|
||||||
|
use std::io::{self, Read};
|
||||||
|
use std::process::{ChildStdout, ChildStderr};
|
||||||
|
|
||||||
|
pub fn read2(out_pipe: ChildStdout,
|
||||||
|
err_pipe: ChildStderr,
|
||||||
|
data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
|
||||||
|
let mut buffer = Vec::new();
|
||||||
|
out_pipe.read_to_end(&mut buffer)?;
|
||||||
|
data(true, &mut buffer, true);
|
||||||
|
buffer.clear();
|
||||||
|
err_pipe.read_to_end(&mut buffer)?;
|
||||||
|
data(false, &mut buffer, true);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
mod imp {
|
||||||
|
use std::io::prelude::*;
|
||||||
|
use std::io;
|
||||||
|
use std::mem;
|
||||||
|
use std::os::unix::prelude::*;
|
||||||
|
use std::process::{ChildStdout, ChildStderr};
|
||||||
|
use libc;
|
||||||
|
|
||||||
|
pub fn read2(mut out_pipe: ChildStdout,
|
||||||
|
mut err_pipe: ChildStderr,
|
||||||
|
data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
|
||||||
|
unsafe {
|
||||||
|
libc::fcntl(out_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
|
||||||
|
libc::fcntl(err_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut out_done = false;
|
||||||
|
let mut err_done = false;
|
||||||
|
let mut out = Vec::new();
|
||||||
|
let mut err = Vec::new();
|
||||||
|
|
||||||
|
let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() };
|
||||||
|
fds[0].fd = out_pipe.as_raw_fd();
|
||||||
|
fds[0].events = libc::POLLIN;
|
||||||
|
fds[1].fd = err_pipe.as_raw_fd();
|
||||||
|
fds[1].events = libc::POLLIN;
|
||||||
|
loop {
|
||||||
|
// wait for either pipe to become readable using `select`
|
||||||
|
let r = unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) };
|
||||||
|
if r == -1 {
|
||||||
|
let err = io::Error::last_os_error();
|
||||||
|
if err.kind() == io::ErrorKind::Interrupted {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return Err(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read as much as we can from each pipe, ignoring EWOULDBLOCK or
|
||||||
|
// EAGAIN. If we hit EOF, then this will happen because the underlying
|
||||||
|
// reader will return Ok(0), in which case we'll see `Ok` ourselves. In
|
||||||
|
// this case we flip the other fd back into blocking mode and read
|
||||||
|
// whatever's leftover on that file descriptor.
|
||||||
|
let handle = |res: io::Result<_>| {
|
||||||
|
match res {
|
||||||
|
Ok(_) => Ok(true),
|
||||||
|
Err(e) => {
|
||||||
|
if e.kind() == io::ErrorKind::WouldBlock {
|
||||||
|
Ok(false)
|
||||||
|
} else {
|
||||||
|
Err(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if !out_done && fds[0].revents != 0 && handle(out_pipe.read_to_end(&mut out))? {
|
||||||
|
out_done = true;
|
||||||
|
}
|
||||||
|
data(true, &mut out, out_done);
|
||||||
|
if !err_done && fds[1].revents != 0 && handle(err_pipe.read_to_end(&mut err))? {
|
||||||
|
err_done = true;
|
||||||
|
}
|
||||||
|
data(false, &mut err, err_done);
|
||||||
|
|
||||||
|
if out_done && err_done {
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
mod imp {
|
||||||
|
extern crate miow;
|
||||||
|
extern crate winapi;
|
||||||
|
|
||||||
|
use std::io;
|
||||||
|
use std::os::windows::prelude::*;
|
||||||
|
use std::process::{ChildStdout, ChildStderr};
|
||||||
|
use std::slice;
|
||||||
|
|
||||||
|
use self::miow::iocp::{CompletionPort, CompletionStatus};
|
||||||
|
use self::miow::pipe::NamedPipe;
|
||||||
|
use self::miow::Overlapped;
|
||||||
|
use self::winapi::ERROR_BROKEN_PIPE;
|
||||||
|
|
||||||
|
struct Pipe<'a> {
|
||||||
|
dst: &'a mut Vec<u8>,
|
||||||
|
overlapped: Overlapped,
|
||||||
|
pipe: NamedPipe,
|
||||||
|
done: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read2(out_pipe: ChildStdout,
|
||||||
|
err_pipe: ChildStderr,
|
||||||
|
data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
|
||||||
|
let mut out = Vec::new();
|
||||||
|
let mut err = Vec::new();
|
||||||
|
|
||||||
|
let port = CompletionPort::new(1)?;
|
||||||
|
port.add_handle(0, &out_pipe)?;
|
||||||
|
port.add_handle(1, &err_pipe)?;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let mut out_pipe = Pipe::new(out_pipe, &mut out);
|
||||||
|
let mut err_pipe = Pipe::new(err_pipe, &mut err);
|
||||||
|
|
||||||
|
out_pipe.read()?;
|
||||||
|
err_pipe.read()?;
|
||||||
|
|
||||||
|
let mut status = [CompletionStatus::zero(), CompletionStatus::zero()];
|
||||||
|
|
||||||
|
while !out_pipe.done || !err_pipe.done {
|
||||||
|
for status in port.get_many(&mut status, None)? {
|
||||||
|
if status.token() == 0 {
|
||||||
|
out_pipe.complete(status);
|
||||||
|
data(true, out_pipe.dst, out_pipe.done);
|
||||||
|
out_pipe.read()?;
|
||||||
|
} else {
|
||||||
|
err_pipe.complete(status);
|
||||||
|
data(false, err_pipe.dst, err_pipe.done);
|
||||||
|
err_pipe.read()?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Pipe<'a> {
|
||||||
|
unsafe fn new<P: IntoRawHandle>(p: P, dst: &'a mut Vec<u8>) -> Pipe<'a> {
|
||||||
|
Pipe {
|
||||||
|
dst: dst,
|
||||||
|
pipe: NamedPipe::from_raw_handle(p.into_raw_handle()),
|
||||||
|
overlapped: Overlapped::zero(),
|
||||||
|
done: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn read(&mut self) -> io::Result<()> {
|
||||||
|
let dst = slice_to_end(self.dst);
|
||||||
|
match self.pipe.read_overlapped(dst, self.overlapped.raw()) {
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(e) => {
|
||||||
|
if e.raw_os_error() == Some(ERROR_BROKEN_PIPE as i32) {
|
||||||
|
self.done = true;
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn complete(&mut self, status: &CompletionStatus) {
|
||||||
|
let prev = self.dst.len();
|
||||||
|
self.dst.set_len(prev + status.bytes_transferred() as usize);
|
||||||
|
if status.bytes_transferred() == 0 {
|
||||||
|
self.done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] {
|
||||||
|
if v.capacity() == 0 {
|
||||||
|
v.reserve(16);
|
||||||
|
}
|
||||||
|
if v.capacity() == v.len() {
|
||||||
|
v.reserve(1);
|
||||||
|
}
|
||||||
|
slice::from_raw_parts_mut(v.as_mut_ptr().offset(v.len() as isize),
|
||||||
|
v.capacity() - v.len())
|
||||||
|
}
|
||||||
|
}
|
@ -29,7 +29,7 @@ use std::fmt;
|
|||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::io::{self, BufReader};
|
use std::io::{self, BufReader};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::{Command, Output, ExitStatus, Stdio};
|
use std::process::{Command, Output, ExitStatus, Stdio, Child};
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
use extract_gdb_version;
|
use extract_gdb_version;
|
||||||
@ -1344,12 +1344,14 @@ actual:\n\
|
|||||||
if let Some(input) = input {
|
if let Some(input) = input {
|
||||||
child.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap();
|
child.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap();
|
||||||
}
|
}
|
||||||
let Output { status, stdout, stderr } = child.wait_with_output().unwrap();
|
|
||||||
|
let Output { status, stdout, stderr } = read2_abbreviated(child)
|
||||||
|
.expect("failed to read output");
|
||||||
|
|
||||||
let result = ProcRes {
|
let result = ProcRes {
|
||||||
status,
|
status,
|
||||||
stdout: String::from_utf8(stdout).unwrap(),
|
stdout: String::from_utf8_lossy(&stdout).into_owned(),
|
||||||
stderr: String::from_utf8(stderr).unwrap(),
|
stderr: String::from_utf8_lossy(&stderr).into_owned(),
|
||||||
cmdline,
|
cmdline,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1635,7 +1637,9 @@ actual:\n\
|
|||||||
cmd.arg("-a").arg("-u");
|
cmd.arg("-a").arg("-u");
|
||||||
cmd.arg(filename);
|
cmd.arg(filename);
|
||||||
cmd.arg("-nobanner");
|
cmd.arg("-nobanner");
|
||||||
let output = match cmd.output() {
|
cmd.stdout(Stdio::piped());
|
||||||
|
cmd.stderr(Stdio::piped());
|
||||||
|
let output = match cmd.spawn().and_then(read2_abbreviated) {
|
||||||
Ok(output) => output,
|
Ok(output) => output,
|
||||||
Err(_) => return,
|
Err(_) => return,
|
||||||
};
|
};
|
||||||
@ -2095,6 +2099,8 @@ actual:\n\
|
|||||||
|
|
||||||
let mut cmd = Command::new(make);
|
let mut cmd = Command::new(make);
|
||||||
cmd.current_dir(&self.testpaths.file)
|
cmd.current_dir(&self.testpaths.file)
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.stderr(Stdio::piped())
|
||||||
.env("TARGET", &self.config.target)
|
.env("TARGET", &self.config.target)
|
||||||
.env("PYTHON", &self.config.docck_python)
|
.env("PYTHON", &self.config.docck_python)
|
||||||
.env("S", src_root)
|
.env("S", src_root)
|
||||||
@ -2143,7 +2149,7 @@ actual:\n\
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let output = cmd.output().expect("failed to spawn `make`");
|
let output = cmd.spawn().and_then(read2_abbreviated).expect("failed to spawn `make`");
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
let res = ProcRes {
|
let res = ProcRes {
|
||||||
status: output.status,
|
status: output.status,
|
||||||
@ -2536,3 +2542,76 @@ fn nocomment_mir_line(line: &str) -> &str {
|
|||||||
line
|
line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read2_abbreviated(mut child: Child) -> io::Result<Output> {
|
||||||
|
use std::mem::replace;
|
||||||
|
use read2::read2;
|
||||||
|
|
||||||
|
const HEAD_LEN: usize = 160 * 1024;
|
||||||
|
const TAIL_LEN: usize = 256 * 1024;
|
||||||
|
|
||||||
|
enum ProcOutput {
|
||||||
|
Full(Vec<u8>),
|
||||||
|
Abbreviated {
|
||||||
|
head: Vec<u8>,
|
||||||
|
skipped: usize,
|
||||||
|
tail: Box<[u8]>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProcOutput {
|
||||||
|
fn extend(&mut self, data: &[u8]) {
|
||||||
|
let new_self = match *self {
|
||||||
|
ProcOutput::Full(ref mut bytes) => {
|
||||||
|
bytes.extend_from_slice(data);
|
||||||
|
let new_len = bytes.len();
|
||||||
|
if new_len <= HEAD_LEN + TAIL_LEN {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let tail = bytes.split_off(new_len - TAIL_LEN).into_boxed_slice();
|
||||||
|
let head = replace(bytes, Vec::new());
|
||||||
|
let skipped = new_len - HEAD_LEN - TAIL_LEN;
|
||||||
|
ProcOutput::Abbreviated { head, skipped, tail }
|
||||||
|
}
|
||||||
|
ProcOutput::Abbreviated { ref mut skipped, ref mut tail, .. } => {
|
||||||
|
*skipped += data.len();
|
||||||
|
if data.len() <= TAIL_LEN {
|
||||||
|
tail[..data.len()].copy_from_slice(data);
|
||||||
|
tail.rotate(data.len());
|
||||||
|
} else {
|
||||||
|
tail.copy_from_slice(&data[(data.len() - TAIL_LEN)..]);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
*self = new_self;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_bytes(self) -> Vec<u8> {
|
||||||
|
match self {
|
||||||
|
ProcOutput::Full(bytes) => bytes,
|
||||||
|
ProcOutput::Abbreviated { mut head, skipped, tail } => {
|
||||||
|
write!(&mut head, "\n\n<<<<<< SKIPPED {} BYTES >>>>>>\n\n", skipped).unwrap();
|
||||||
|
head.extend_from_slice(&tail);
|
||||||
|
head
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut stdout = ProcOutput::Full(Vec::new());
|
||||||
|
let mut stderr = ProcOutput::Full(Vec::new());
|
||||||
|
|
||||||
|
drop(child.stdin.take());
|
||||||
|
read2(child.stdout.take().unwrap(), child.stderr.take().unwrap(), &mut |is_stdout, data, _| {
|
||||||
|
if is_stdout { &mut stdout } else { &mut stderr }.extend(data);
|
||||||
|
data.clear();
|
||||||
|
})?;
|
||||||
|
let status = child.wait()?;
|
||||||
|
|
||||||
|
Ok(Output {
|
||||||
|
status,
|
||||||
|
stdout: stdout.into_bytes(),
|
||||||
|
stderr: stderr.into_bytes(),
|
||||||
|
})
|
||||||
|
}
|
@ -31,9 +31,9 @@ pub fn check(path: &Path, bad: &mut bool) {
|
|||||||
if let Ok(mut file) = fs::File::open("/proc/version") {
|
if let Ok(mut file) = fs::File::open("/proc/version") {
|
||||||
let mut contents = String::new();
|
let mut contents = String::new();
|
||||||
file.read_to_string(&mut contents).unwrap();
|
file.read_to_string(&mut contents).unwrap();
|
||||||
// Probably on Windows Linux Subsystem, all files will be marked as
|
// Probably on Windows Linux Subsystem or Docker via VirtualBox,
|
||||||
// executable, so skip checking.
|
// all files will be marked as executable, so skip checking.
|
||||||
if contents.contains("Microsoft") {
|
if contents.contains("Microsoft") || contents.contains("boot2docker") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user