Merge branch 'master' into master
diff --git a/.travis.yml b/.travis.yml
index c770304..175269a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,24 +1,18 @@
+---
 language: rust
-
-sudo: required
-
 dist: trusty
+sudo: required
+services: docker
+cache: cargo
 
-install:
-  - curl https://static.rust-lang.org/rustup.sh |
-    sh -s -- --add-target=$TARGET --disable-sudo -y --prefix=`rustc --print sysroot`
+before_cache:
+  # Travis can't cache files that are not readable by "others"
+  - chmod -R a+r $HOME/.cargo
 
 script:
   - cargo build
   - cargo build --no-default-features
-  - if [[ $TRAVIS_OS_NAME = "linux" ]]; then
-      sh ci/run-docker.sh $TARGET;
-    else
-      export CARGO_TARGET_DIR=`pwd`/target;
-      sh ci/run.sh $TARGET;
-    fi
-
-cache: cargo
+  - cargo test
 
 matrix:
   include:
@@ -35,21 +29,21 @@
         - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
       script:
         # Ensure that the build works without default features
+        - cargo build
         - cargo build --no-default-features
         - cargo test
         - cargo doc --no-deps
       after_success:
         - travis-cargo doc-upload
-      install:
 
     # Test on latest stable
     - os: linux
       rust: stable
       script:
         # Ensure that the build works without default features
+        - cargo build
         - cargo build --no-default-features
         - cargo test
-      install:
 
     # OS X
     - os: osx
@@ -58,7 +52,6 @@
         # Ensure that the build works without default features
         - cargo build --no-default-features
         - cargo test
-      install:
 
     # iOS
     - os: osx
@@ -68,14 +61,34 @@
       script:
         - cargo build
         - CARGO_TARGET_DIR=`pwd` sh ci/run-ios.sh $TARGET
+      install:
+        - curl https://static.rust-lang.org/rustup.sh |
+          sh -s -- --add-target=$TARGET --disable-sudo -y --prefix=`rustc --print sysroot`
 
     # Android
     - os: linux
       env: TARGET=arm-linux-androideabi
       rust: stable
+      script:
+        - cargo build
+        - cargo build --no-default-features
+        - sh ci/run-docker.sh $TARGET;
+      install:
+        - curl https://static.rust-lang.org/rustup.sh |
+          sh -s -- --add-target=$TARGET --disable-sudo -y --prefix=`rustc --print sysroot`
+
+    # FreeBSD
+    - os: linux
+      env: TARGET=x86_64-unknown-freebsd DISABLE_TESTS=1
+      install:
+        - sh ci/trust/install.sh
+        - source ~/.cargo/env || true
+      script:
+        - bash ci/trust/script.sh
 
 env:
   global:
+    - CRATE_NAME=mio
     - secure: "B/5BSBwUX1r+99YJba421+x7eGgm8J+Cuy7nOAenkRsCP+h5JiOFP4IWyoRgmGQoF1dgGwlHuOLBYvcBj1r8p2i3b8akLk/L83iOBbYNkhub6TpDjltTOZ30brrM++LayazAKHg8mixsTiu72cSJr1BiELQae/ABq9QHTj4v3m4="
 
 notifications:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 728ade3..6544507 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,21 @@
+# 0.6.5 (March 14, 2017)
+
+* Misc improvements to kqueue bindings
+* Add official support for iOS, Android, BSD
+* Reimplement custom readiness queue
+* `Poll` is now `Sync`
+* Officially deprecate non-core functionality (timers, channel, etc...)
+* `Registration` now implements `Evented`
+* Fix bug around error conditions with `connect` on windows.
+* Use iovec crate for scatter / gather operations
+* Only support readable and writable readiness on all platforms
+* Expose additional readiness in a platform specific capacity
+
+# 0.6.4 (January 24, 2017)
+
+* Fix compilation on musl
+* Add `TcpStream::from_stream` which conversts a std TCP stream to Mio.
+
 # 0.6.3 (January 22, 2017)
 
 * Implement readv/writev for `TcpStream`, allowing vectored reads/writes to
diff --git a/Cargo.toml b/Cargo.toml
index d97327a..11b9de6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -27,7 +27,7 @@
 log      = "0.3.1"
 slab     = "0.3.0"
 net2     = "0.2.19"
-iovec    = { git = "https://github.com/carllerche/iovec" }
+iovec    = "0.1.0"
 
 [target.'cfg(unix)'.dependencies]
 libc   = "0.2.19"
diff --git a/ci/docker/aarch64-unknown-linux-gnu/Dockerfile b/ci/docker/aarch64-unknown-linux-gnu/Dockerfile
deleted file mode 100644
index 2ba69e1..0000000
--- a/ci/docker/aarch64-unknown-linux-gnu/Dockerfile
+++ /dev/null
@@ -1,7 +0,0 @@
-FROM ubuntu:16.10
-RUN apt-get update
-RUN apt-get install -y --no-install-recommends \
-  gcc libc6-dev ca-certificates \
-  gcc-aarch64-linux-gnu libc6-dev-arm64-cross qemu-user
-ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \
-    PATH=$PATH:/rust/bin
diff --git a/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile b/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile
deleted file mode 100644
index 3824c04..0000000
--- a/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile
+++ /dev/null
@@ -1,7 +0,0 @@
-FROM ubuntu:16.10
-RUN apt-get update
-RUN apt-get install -y --no-install-recommends \
-  gcc libc6-dev ca-certificates \
-  gcc-arm-linux-gnueabihf libc6-dev-armhf-cross qemu-user
-ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc \
-    PATH=$PATH:/rust/bin
diff --git a/ci/docker/i686-unknown-linux-gnu/Dockerfile b/ci/docker/i686-unknown-linux-gnu/Dockerfile
deleted file mode 100644
index c149d84..0000000
--- a/ci/docker/i686-unknown-linux-gnu/Dockerfile
+++ /dev/null
@@ -1,5 +0,0 @@
-FROM ubuntu:16.10
-RUN apt-get update
-RUN apt-get install -y --no-install-recommends \
-  gcc-multilib libc6-dev ca-certificates
-ENV PATH=$PATH:/rust/bin
diff --git a/ci/docker/i686-unknown-linux-musl/Dockerfile b/ci/docker/i686-unknown-linux-musl/Dockerfile
deleted file mode 100644
index 87459a1..0000000
--- a/ci/docker/i686-unknown-linux-musl/Dockerfile
+++ /dev/null
@@ -1,22 +0,0 @@
-FROM ubuntu:16.10
-
-RUN apt-get update
-RUN apt-get install -y --no-install-recommends \
-  gcc make libc6-dev git curl ca-certificates
-# Below we're cross-compiling musl for i686 using the system compiler on an
-# x86_64 system. This is an awkward thing to be doing and so we have to jump
-# through a couple hoops to get musl to be happy. In particular:
-#
-# * We specifically pass -m32 in CFLAGS and override CC when running ./configure,
-#   since otherwise the script will fail to find a compiler.
-# * We manually unset CROSS_COMPILE when running make; otherwise the makefile
-#   will call the non-existent binary 'i686-ar'.
-RUN curl https://www.musl-libc.org/releases/musl-1.1.15.tar.gz | \
-    tar xzf - && \
-    cd musl-1.1.15 && \
-    CC=gcc CFLAGS=-m32 ./configure --prefix=/musl-i686 --disable-shared --target=i686 && \
-    make CROSS_COMPILE= install -j4 && \
-    cd .. && \
-    rm -rf musl-1.1.15
-ENV PATH=$PATH:/musl-i686/bin:/rust/bin \
-    CC_i686_unknown_linux_musl=musl-gcc
diff --git a/ci/docker/mips-unknown-linux-gnu/Dockerfile b/ci/docker/mips-unknown-linux-gnu/Dockerfile
deleted file mode 100644
index eea1f65..0000000
--- a/ci/docker/mips-unknown-linux-gnu/Dockerfile
+++ /dev/null
@@ -1,10 +0,0 @@
-FROM ubuntu:16.10
-
-RUN apt-get update
-RUN apt-get install -y --no-install-recommends \
-        gcc libc6-dev qemu-user ca-certificates \
-        gcc-mips-linux-gnu libc6-dev-mips-cross \
-        qemu-system-mips
-
-ENV CARGO_TARGET_MIPS_UNKNOWN_LINUX_GNU_LINKER=mips-linux-gnu-gcc \
-    PATH=$PATH:/rust/bin
diff --git a/ci/docker/mips-unknown-linux-musl/Dockerfile b/ci/docker/mips-unknown-linux-musl/Dockerfile
deleted file mode 100644
index cbc41c2..0000000
--- a/ci/docker/mips-unknown-linux-musl/Dockerfile
+++ /dev/null
@@ -1,17 +0,0 @@
-FROM ubuntu:16.10
-
-RUN apt-get update
-RUN apt-get install -y --no-install-recommends \
-        gcc libc6-dev qemu-user ca-certificates qemu-system-mips curl \
-        bzip2
-
-RUN mkdir /toolchain
-
-# Note that this originally came from:
-# https://downloads.openwrt.org/snapshots/trunk/ar71xx/generic/OpenWrt-SDK-ar71xx-generic_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2
-RUN curl -L https://s3.amazonaws.com/rust-lang-ci/libc/OpenWrt-SDK-ar71xx-generic_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2 | \
-      tar xjf - -C /toolchain --strip-components=1
-
-ENV PATH=$PATH:/rust/bin:/toolchain/staging_dir/toolchain-mips_34kc_gcc-5.3.0_musl-1.1.15/bin \
-    CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \
-    CARGO_TARGET_MIPS_UNKNOWN_LINUX_MUSL_LINKER=mips-openwrt-linux-gcc
diff --git a/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile b/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile
deleted file mode 100644
index 2eb5de2..0000000
--- a/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile
+++ /dev/null
@@ -1,11 +0,0 @@
-FROM ubuntu:16.10
-
-RUN apt-get update
-RUN apt-get install -y --no-install-recommends \
-        gcc libc6-dev qemu-user ca-certificates \
-        gcc-mips64-linux-gnuabi64 libc6-dev-mips64-cross \
-        qemu-system-mips64
-
-ENV CARGO_TARGET_MIPS64_UNKNOWN_LINUX_GNUABI64_LINKER=mips64-linux-gnuabi64-gcc \
-    CC_mips64_unknown_linux_gnuabi64=mips64-linux-gnuabi64-gcc \
-    PATH=$PATH:/rust/bin
diff --git a/ci/docker/mipsel-unknown-linux-musl/Dockerfile b/ci/docker/mipsel-unknown-linux-musl/Dockerfile
deleted file mode 100644
index 4c7ee8b..0000000
--- a/ci/docker/mipsel-unknown-linux-musl/Dockerfile
+++ /dev/null
@@ -1,17 +0,0 @@
-FROM ubuntu:16.10
-
-RUN apt-get update
-RUN apt-get install -y --no-install-recommends \
-        gcc libc6-dev qemu-user ca-certificates qemu-system-mips curl \
-        bzip2
-
-RUN mkdir /toolchain
-
-# Note that this originally came from:
-# https://downloads.openwrt.org/snapshots/trunk/malta/generic/OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2
-RUN curl -L https://s3.amazonaws.com/rust-lang-ci/libc/OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2 | \
-      tar xjf - -C /toolchain --strip-components=2
-
-ENV PATH=$PATH:/rust/bin:/toolchain/bin \
-    CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
-    CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_MUSL_LINKER=mipsel-openwrt-linux-gcc
diff --git a/ci/docker/powerpc-unknown-linux-gnu/Dockerfile b/ci/docker/powerpc-unknown-linux-gnu/Dockerfile
deleted file mode 100644
index d9d7db0..0000000
--- a/ci/docker/powerpc-unknown-linux-gnu/Dockerfile
+++ /dev/null
@@ -1,10 +0,0 @@
-FROM ubuntu:16.10
-
-RUN apt-get update
-RUN apt-get install -y --no-install-recommends \
-        gcc libc6-dev qemu-user ca-certificates \
-        gcc-powerpc-linux-gnu libc6-dev-powerpc-cross \
-        qemu-system-ppc
-
-ENV CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_LINKER=powerpc-linux-gnu-gcc \
-    PATH=$PATH:/rust/bin
diff --git a/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile b/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile
deleted file mode 100644
index df0e605..0000000
--- a/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile
+++ /dev/null
@@ -1,11 +0,0 @@
-FROM ubuntu:16.10
-
-RUN apt-get update
-RUN apt-get install -y --no-install-recommends \
-        gcc libc6-dev qemu-user ca-certificates \
-        gcc-powerpc64-linux-gnu libc6-dev-ppc64-cross \
-        qemu-system-ppc
-
-ENV CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_LINKER=powerpc64-linux-gnu-gcc \
-    CC=powerpc64-linux-gnu-gcc \
-    PATH=$PATH:/rust/bin
diff --git a/ci/docker/x86_64-rumprun-netbsd/Dockerfile b/ci/docker/x86_64-rumprun-netbsd/Dockerfile
deleted file mode 100644
index 129771e..0000000
--- a/ci/docker/x86_64-rumprun-netbsd/Dockerfile
+++ /dev/null
@@ -1,6 +0,0 @@
-FROM mato/rumprun-toolchain-hw-x86_64
-USER root
-RUN apt-get update
-RUN apt-get install -y --no-install-recommends \
-  qemu
-ENV PATH=$PATH:/rust/bin
diff --git a/ci/docker/x86_64-unknown-freebsd/Dockerfile b/ci/docker/x86_64-unknown-freebsd/Dockerfile
deleted file mode 100644
index 12b0bdf..0000000
--- a/ci/docker/x86_64-unknown-freebsd/Dockerfile
+++ /dev/null
@@ -1,13 +0,0 @@
-FROM alexcrichton/rust-slave-linux-cross:2016-04-15
-USER root
-
-RUN apt-get update
-RUN apt-get install -y --no-install-recommends \
-  qemu genext2fs
-
-ENTRYPOINT ["sh"]
-
-ENV PATH=$PATH:/rust/bin \
-    QEMU=2016-11-06/freebsd.qcow2.gz \
-    CAN_CROSS=1 \
-    CARGO_TARGET_X86_64_UNKNOWN_FREEBSD_LINKER=x86_64-unknown-freebsd10-gcc
diff --git a/ci/docker/x86_64-unknown-linux-gnu/Dockerfile b/ci/docker/x86_64-unknown-linux-gnu/Dockerfile
deleted file mode 100644
index 4af3f83..0000000
--- a/ci/docker/x86_64-unknown-linux-gnu/Dockerfile
+++ /dev/null
@@ -1,5 +0,0 @@
-FROM ubuntu:16.10
-RUN apt-get update
-RUN apt-get install -y --no-install-recommends \
-  gcc libc6-dev ca-certificates
-ENV PATH=$PATH:/rust/bin
diff --git a/ci/docker/x86_64-unknown-linux-musl/Dockerfile b/ci/docker/x86_64-unknown-linux-musl/Dockerfile
deleted file mode 100644
index 9c24999..0000000
--- a/ci/docker/x86_64-unknown-linux-musl/Dockerfile
+++ /dev/null
@@ -1,13 +0,0 @@
-FROM ubuntu:16.10
-
-RUN apt-get update
-RUN apt-get install -y --no-install-recommends \
-  gcc make libc6-dev git curl ca-certificates
-RUN curl https://www.musl-libc.org/releases/musl-1.1.15.tar.gz | \
-    tar xzf - && \
-    cd musl-1.1.15 && \
-    ./configure --prefix=/musl-x86_64 && \
-    make install -j4 && \
-    cd .. && \
-    rm -rf musl-1.1.15
-ENV PATH=$PATH:/musl-x86_64/bin:/rust/bin
diff --git a/ci/docker/x86_64-unknown-openbsd/Dockerfile b/ci/docker/x86_64-unknown-openbsd/Dockerfile
deleted file mode 100644
index 518baf8..0000000
--- a/ci/docker/x86_64-unknown-openbsd/Dockerfile
+++ /dev/null
@@ -1,8 +0,0 @@
-FROM ubuntu:16.10
-
-RUN apt-get update
-RUN apt-get install -y --no-install-recommends \
-  gcc libc6-dev qemu curl ca-certificates \
-  genext2fs
-ENV PATH=$PATH:/rust/bin \
-    QEMU=2016-11-06/openbsd-6.0-without-pkgs.qcow2
diff --git a/ci/run-qemu.sh b/ci/run-qemu.sh
deleted file mode 100644
index b2f457d..0000000
--- a/ci/run-qemu.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-# Initial script which is run inside of all qemu images. The first argument to
-# this script (as arranged by the qemu image itself) is the path to where the
-# libc crate is mounted.
-#
-# For qemu images we currently need to install Rust manually as this wasn't done
-# by the initial run-travis.sh script
-#
-# FIXME: feels like run-travis.sh should be responsible for downloading the
-#        compiler.
-
-set -ex
-
-ROOT=$1
-cp -r $ROOT/libc /tmp/libc
-cd /tmp/libc
-
-TARGET=$(cat $ROOT/TARGET)
-export CARGO_TARGET_DIR=/tmp
-
-case $TARGET in
-  *-openbsd)
-    pkg_add cargo gcc%4.9 rust
-    export CC=egcc
-    ;;
-
-  *)
-    echo "Unknown target: $TARGET"
-    exit 1
-    ;;
-esac
-
-exec sh ci/run.sh $TARGET
diff --git a/ci/run.sh b/ci/run.sh
index 1a6e92c..122573d 100755
--- a/ci/run.sh
+++ b/ci/run.sh
@@ -7,92 +7,6 @@
 
 TARGET=$1
 
-# If we're going to run tests inside of a qemu image, then we don't need any of
-# the scripts below. Instead, download the image, prepare a filesystem which has
-# the current state of this repository, and then run the image.
-#
-# It's assume that all images, when run with two disks, will run the `run.sh`
-# script from the second which we place inside.
-if [ "$QEMU" != "" ]; then
-  tmpdir=/tmp/qemu-img-creation
-  mkdir -p $tmpdir
-
-  if [ -z "${QEMU#*.gz}" ]; then
-    # image is .gz : download and uncompress it
-    qemufile=$(echo ${QEMU%.gz} | sed 's/\//__/g')
-    if [ ! -f $tmpdir/$qemufile ]; then
-      curl https://s3.amazonaws.com/rust-lang-ci/libc/$QEMU | \
-        gunzip -d > $tmpdir/$qemufile
-    fi
-  else
-    # plain qcow2 image: just download it
-    qemufile=$(echo ${QEMU} | sed 's/\//__/g')
-    if [ ! -f $tmpdir/$qemufile ]; then
-      curl https://s3.amazonaws.com/rust-lang-ci/libc/$QEMU \
-        > $tmpdir/$qemufile
-    fi
-  fi
-
-  # Create a mount a fresh new filesystem image that we'll later pass to QEMU.
-  # This will have a `run.sh` script will which use the artifacts inside to run
-  # on the host.
-  rm -f $tmpdir/libc-test.img
-  mkdir $tmpdir/mount
-
-  # If we have a cross compiler, then we just do the standard rigamarole of
-  # cross-compiling an executable and then the script to run just executes the
-  # binary.
-  #
-  # If we don't have a cross-compiler, however, then we need to do some crazy
-  # acrobatics to get this to work.  Generate all.{c,rs} on the host which will
-  # be compiled inside QEMU. Do this here because compiling syntex_syntax in
-  # QEMU would time out basically everywhere.
-  if [ "$CAN_CROSS" = "1" ]; then
-    cargo build --manifest-path libc-test/Cargo.toml --target $TARGET
-    cp $CARGO_TARGET_DIR/$TARGET/debug/libc-test $tmpdir/mount/
-    echo 'exec $1/libc-test' > $tmpdir/mount/run.sh
-  else
-    rm -rf $tmpdir/generated
-    mkdir -p $tmpdir/generated
-    cargo build --manifest-path libc-test/generate-files/Cargo.toml
-    (cd libc-test && TARGET=$TARGET OUT_DIR=$tmpdir/generated SKIP_COMPILE=1 \
-      $CARGO_TARGET_DIR/debug/generate-files)
-
-    # Copy this folder into the mounted image, the `run.sh` entry point, and
-    # overwrite the standard libc-test Cargo.toml with the overlay one which will
-    # assume the all.{c,rs} test files have already been generated
-    mkdir $tmpdir/mount/libc
-    cp -r Cargo.* libc-test src ci $tmpdir/mount/libc/
-    ln -s libc-test/target $tmpdir/mount/libc/target
-    cp ci/run-qemu.sh $tmpdir/mount/run.sh
-    echo $TARGET | tee -a $tmpdir/mount/TARGET
-    cp $tmpdir/generated/* $tmpdir/mount/libc/libc-test
-    cp libc-test/run-generated-Cargo.toml $tmpdir/mount/libc/libc-test/Cargo.toml
-  fi
-
-  du -sh $tmpdir/mount
-  genext2fs \
-      --root $tmpdir/mount \
-      --size-in-blocks 100000 \
-      $tmpdir/libc-test.img
-
-  # Pass -snapshot to prevent tampering with the disk images, this helps when
-  # running this script in development. The two drives are then passed next,
-  # first is the OS and second is the one we just made. Next the network is
-  # configured to work (I'm not entirely sure how), and then finally we turn off
-  # graphics and redirect the serial console output to out.log.
-  qemu-system-x86_64 \
-    -m 1024 \
-    -snapshot \
-    -drive if=virtio,file=$tmpdir/$qemufile \
-    -drive if=virtio,file=$tmpdir/libc-test.img \
-    -net nic,model=virtio \
-    -net user \
-    -nographic \
-    -vga none 2>&1 | tee $CARGO_TARGET_DIR/out.log
-  exec grep "^PASSED .* tests" $CARGO_TARGET_DIR/out.log
-fi
-
 cargo build --test test --target $TARGET
 
 # Find the file to run
@@ -108,48 +22,7 @@
     grep "^test result.* 0 failed" /tmp/out
     ;;
 
-  arm-unknown-linux-gnueabihf)
-    qemu-arm -L /usr/arm-linux-gnueabihf $CARGO_TARGET_DIR/$TARGET/debug/libc-test
-    ;;
-
-  mips-unknown-linux-gnu)
-    qemu-mips -L /usr/mips-linux-gnu $CARGO_TARGET_DIR/$TARGET/debug/libc-test
-    ;;
-
-  mips64-unknown-linux-gnuabi64)
-    qemu-mips64 -L /usr/mips64-linux-gnuabi64 $CARGO_TARGET_DIR/$TARGET/debug/libc-test
-    ;;
-
-  mips-unknown-linux-musl)
-    qemu-mips -L /toolchain/staging_dir/toolchain-mips_34kc_gcc-5.3.0_musl-1.1.15 \
-              $CARGO_TARGET_DIR/$TARGET/debug/libc-test
-    ;;
-
-  mipsel-unknown-linux-musl)
-      qemu-mipsel -L /toolchain $CARGO_TARGET_DIR/$TARGET/debug/libc-test
-      ;;
-
-  powerpc-unknown-linux-gnu)
-    qemu-ppc -L /usr/powerpc-linux-gnu $CARGO_TARGET_DIR/$TARGET/debug/libc-test
-    ;;
-
-  powerpc64-unknown-linux-gnu)
-    qemu-ppc64 -L /usr/powerpc64-linux-gnu $CARGO_TARGET_DIR/$TARGET/debug/libc-test
-    ;;
-
-  aarch64-unknown-linux-gnu)
-    qemu-aarch64 -L /usr/aarch64-linux-gnu/ $CARGO_TARGET_DIR/$TARGET/debug/libc-test
-    ;;
-
-  *-rumprun-netbsd)
-    rumprun-bake hw_virtio /tmp/libc-test.img $CARGO_TARGET_DIR/$TARGET/debug/libc-test
-    qemu-system-x86_64 -nographic -vga none -m 64 \
-        -kernel /tmp/libc-test.img 2>&1 | tee /tmp/out &
-    sleep 5
-    grep "^PASSED .* tests" /tmp/out
-    ;;
-
   *)
-    $CARGO_TARGET_DIR/$TARGET/debug/libc-test
+    exit 1;
     ;;
 esac
diff --git a/ci/trust/install.sh b/ci/trust/install.sh
new file mode 100644
index 0000000..76bb734
--- /dev/null
+++ b/ci/trust/install.sh
@@ -0,0 +1,31 @@
+set -ex
+
+main() {
+    curl https://sh.rustup.rs -sSf | \
+        sh -s -- -y --default-toolchain $TRAVIS_RUST_VERSION
+
+    local target=
+    if [ $TRAVIS_OS_NAME = linux ]; then
+        target=x86_64-unknown-linux-gnu
+        sort=sort
+    else
+        target=x86_64-apple-darwin
+        sort=gsort  # for `sort --sort-version`, from brew's coreutils.
+    fi
+
+    # This fetches latest stable release
+    local tag=$(git ls-remote --tags --refs --exit-code https://github.com/japaric/cross \
+                       | cut -d/ -f3 \
+                       | grep -E '^v[0-9.]+$' \
+                       | $sort --version-sort \
+                       | tail -n1)
+    echo cross version: $tag
+    curl -LSfs https://japaric.github.io/trust/install.sh | \
+        sh -s -- \
+           --force \
+           --git japaric/cross \
+           --tag $tag \
+           --target $target
+}
+
+main
diff --git a/ci/trust/script.sh b/ci/trust/script.sh
new file mode 100644
index 0000000..473bacb
--- /dev/null
+++ b/ci/trust/script.sh
@@ -0,0 +1,19 @@
+# This script takes care of testing your crate
+
+set -ex
+
+# TODO This is the "test phase", tweak it as you see fit
+main() {
+    cross build --target $TARGET
+
+    if [ ! -z $DISABLE_TESTS ]; then
+        return
+    fi
+
+    cross test --target $TARGET
+}
+
+# we don't run the "test phase" when doing deploys
+if [ -z $TRAVIS_TAG ]; then
+    main
+fi
diff --git a/src/channel.rs b/src/channel.rs
index 30b9d52..b088dde 100644
--- a/src/channel.rs
+++ b/src/channel.rs
@@ -1,6 +1,6 @@
 //! Thread safe communication channel implementing `Evented`
 
-#![allow(unused_imports, deprecated)]
+#![allow(unused_imports, deprecated, missing_debug_implementations)]
 
 use {io, Evented, Ready, Poll, PollOpt, Registration, SetReadiness, Token};
 use lazycell::{LazyCell, AtomicLazyCell};
diff --git a/src/event_imp.rs b/src/event_imp.rs
index fc1b0bb..4eaafc0 100644
--- a/src/event_imp.rs
+++ b/src/event_imp.rs
@@ -266,7 +266,8 @@
         PollOpt(0b0100)
     }
 
-    // TODO: Figure out if this should be deprecated or not
+    #[deprecated(since = "0.6.5", note = "removed")]
+    #[cfg(feature = "with-deprecated")]
     #[doc(hidden)]
     #[inline]
     pub fn urgent() -> PollOpt {
@@ -341,8 +342,10 @@
         self.contains(PollOpt::oneshot())
     }
 
-    // TODO: Should this be deprecated?
+    #[deprecated(since = "0.6.5", note = "removed")]
+    #[cfg(feature = "with-deprecated")]
     #[doc(hidden)]
+    #[allow(deprecated)]
     #[inline]
     pub fn is_urgent(&self) -> bool {
         self.contains(PollOpt::urgent())
@@ -512,10 +515,11 @@
 /// indicates that the associated `Evented` handle is ready to perform a
 /// `read` operation.
 ///
-/// **Note that only readable and writable readiness is guaranteed to be
-/// supported on all platforms**. This means that `error` and `hup` readiness
-/// should be treated as hints. For more details, see [readiness] in the poll
-/// documentation.
+/// This struct only represents portable event kinds. Since only readable and
+/// writable events are guaranteed to be raised on all systems, those are the
+/// only ones available via the `Ready` struct. There are also platform specific
+/// extensions to `Ready`, i.e. `UnixReady`, which provide additional readiness
+/// event kinds only available on unix platforms.
 ///
 /// `Ready` values can be combined together using the various bitwise operators.
 ///
@@ -543,7 +547,6 @@
 const WRITABLE: usize = 0b0010;
 const ERROR: usize    = 0b0100;
 const HUP: usize      = 0b1000;
-const READY_ALL: usize = READABLE | WRITABLE | ERROR | HUP;
 
 impl Ready {
     /// Returns the empty `Ready` set.
@@ -612,56 +615,17 @@
         Ready(WRITABLE)
     }
 
-    /// Returns a `Ready` representing error readiness.
-    ///
-    /// **Note that only readable and writable readiness is guaranteed to be
-    /// supported on all platforms**. This means that `error` readiness
-    /// should be treated as a hint. For more details, see [readiness] in the
-    /// poll documentation.
-    ///
-    /// See [`Poll`] for more documentation on polling.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use mio::Ready;
-    ///
-    /// let ready = Ready::error();
-    ///
-    /// assert!(ready.is_error());
-    /// ```
-    ///
-    /// [`Poll`]: struct.Poll.html
-    /// [readiness]: struct.Poll.html#readiness-operations
+    #[deprecated(since = "0.6.5", note = "use UnixReady instead")]
+    #[cfg(feature = "with-deprecated")]
+    #[doc(hidden)]
     #[inline]
     pub fn error() -> Ready {
         Ready(ERROR)
     }
 
-    /// Returns a `Ready` representing HUP readiness.
-    ///
-    /// A HUP (or hang-up) signifies that a stream socket **peer** closed the
-    /// connection, or shut down the writing half of the connection.
-    ///
-    /// **Note that only readable and writable readiness is guaranteed to be
-    /// supported on all platforms**. This means that `hup` readiness
-    /// should be treated as a hint. For more details, see [readiness] in the
-    /// poll documentation.
-    ///
-    /// See [`Poll`] for more documentation on polling.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use mio::Ready;
-    ///
-    /// let ready = Ready::hup();
-    ///
-    /// assert!(ready.is_hup());
-    /// ```
-    ///
-    /// [`Poll`]: struct.Poll.html
-    /// [readiness]: struct.Poll.html#readiness-operations
+    #[deprecated(since = "0.6.5", note = "use UnixReady instead")]
+    #[cfg(feature = "with-deprecated")]
+    #[doc(hidden)]
     #[inline]
     pub fn hup() -> Ready {
         Ready(HUP)
@@ -741,54 +705,17 @@
         self.contains(Ready::writable())
     }
 
-    /// Returns true if the value includes error readiness
-    ///
-    /// **Note that only readable and writable readiness is guaranteed to be
-    /// supported on all platforms**. This means that `error` readiness should
-    /// be treated as a hint. For more details, see [readiness] in the poll
-    /// documentation.
-    ///
-    /// See [`Poll`] for more documentation on polling.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use mio::Ready;
-    ///
-    /// let ready = Ready::error();
-    ///
-    /// assert!(ready.is_error());
-    /// ```
-    ///
-    /// [`Poll`]: struct.Poll.html
+    #[deprecated(since = "0.6.5", note = "use UnixReady instead")]
+    #[cfg(feature = "with-deprecated")]
+    #[doc(hidden)]
     #[inline]
     pub fn is_error(&self) -> bool {
         self.contains(Ready(ERROR))
     }
 
-    /// Returns true if the value includes HUP readiness
-    ///
-    /// A HUP (or hang-up) signifies that a stream socket **peer** closed the
-    /// connection, or shut down the writing half of the connection.
-    ///
-    /// **Note that only readable and writable readiness is guaranteed to be
-    /// supported on all platforms**. This means that `hup` readiness
-    /// should be treated as a hint. For more details, see [readiness] in the
-    /// poll documentation.
-    ///
-    /// See [`Poll`] for more documentation on polling.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use mio::Ready;
-    ///
-    /// let ready = Ready::hup();
-    ///
-    /// assert!(ready.is_hup());
-    /// ```
-    ///
-    /// [`Poll`]: struct.Poll.html
+    #[deprecated(since = "0.6.5", note = "use UnixReady instead")]
+    #[cfg(feature = "with-deprecated")]
+    #[doc(hidden)]
     #[inline]
     pub fn is_hup(&self) -> bool {
         self.contains(Ready(HUP))
@@ -809,7 +736,8 @@
     /// assert!(readiness.is_readable());
     /// ```
     #[inline]
-    pub fn insert(&mut self, other: Ready) {
+    pub fn insert<T: Into<Self>>(&mut self, other: T) {
+        let other = other.into();
         self.0 |= other.0;
     }
 
@@ -828,7 +756,8 @@
     /// assert!(!readiness.is_readable());
     /// ```
     #[inline]
-    pub fn remove(&mut self, other: Ready) {
+    pub fn remove<T: Into<Self>>(&mut self, other: T) {
+        let other = other.into();
         self.0 &= !other.0;
     }
 
@@ -880,44 +809,45 @@
     ///
     /// [`Poll`]: struct.Poll.html
     #[inline]
-    pub fn contains(&self, other: Ready) -> bool {
+    pub fn contains<T: Into<Self>>(&self, other: T) -> bool {
+        let other = other.into();
         (*self & other) == other
     }
 }
 
-impl ops::BitOr for Ready {
+impl<T: Into<Ready>> ops::BitOr<T> for Ready {
     type Output = Ready;
 
     #[inline]
-    fn bitor(self, other: Ready) -> Ready {
-        Ready(self.0 | other.0)
+    fn bitor(self, other: T) -> Ready {
+        Ready(self.0 | other.into().0)
     }
 }
 
-impl ops::BitXor for Ready {
+impl<T: Into<Ready>> ops::BitXor<T> for Ready {
     type Output = Ready;
 
     #[inline]
-    fn bitxor(self, other: Ready) -> Ready {
-        Ready(self.0 ^ other.0)
+    fn bitxor(self, other: T) -> Ready {
+        Ready(self.0 ^ other.into().0)
     }
 }
 
-impl ops::BitAnd for Ready {
+impl<T: Into<Ready>> ops::BitAnd<T> for Ready {
     type Output = Ready;
 
     #[inline]
-    fn bitand(self, other: Ready) -> Ready {
-        Ready(self.0 & other.0)
+    fn bitand(self, other: T) -> Ready {
+        Ready(self.0 & other.into().0)
     }
 }
 
-impl ops::Sub for Ready {
+impl<T: Into<Ready>> ops::Sub<T> for Ready {
     type Output = Ready;
 
     #[inline]
-    fn sub(self, other: Ready) -> Ready {
-        Ready(self.0 & !other.0)
+    fn sub(self, other: T) -> Ready {
+        Ready(self.0 & !other.into().0)
     }
 }
 
@@ -926,7 +856,7 @@
 
     #[inline]
     fn not(self) -> Ready {
-        Ready(!self.0 & READY_ALL)
+        Ready(!self.0)
     }
 }
 
diff --git a/src/lib.rs b/src/lib.rs
index f84e5a0..ef18a31 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -78,7 +78,7 @@
 #![doc(html_root_url = "https://docs.rs/mio/0.6.1")]
 #![crate_name = "mio"]
 
-#![deny(warnings, missing_docs)]
+#![deny(warnings, missing_docs, missing_debug_implementations)]
 
 extern crate lazycell;
 extern crate net2;
@@ -177,6 +177,7 @@
     pub use sys::{
         EventedFd,
     };
+    pub use sys::unix::UnixReady;
 }
 
 /// Windows-only extensions to the mio crate.
diff --git a/src/poll.rs b/src/poll.rs
index 4e9b09b..9b6707d 100644
--- a/src/poll.rs
+++ b/src/poll.rs
@@ -1185,6 +1185,7 @@
 ///
 /// [`Events`]: struct.Events.html
 /// [`iter`]: struct.Events.html#method.iter
+#[derive(Debug)]
 pub struct Iter<'a> {
     inner: &'a Events,
     pos: usize,
@@ -1321,6 +1322,15 @@
     }
 }
 
+impl fmt::Debug for Events {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("Events")
+            .field("len", &self.len())
+            .field("capacity", &self.capacity())
+            .finish()
+    }
+}
+
 // ===== Accessors for internal usage =====
 
 pub fn selector(poll: &Poll) -> &sys::Selector {
@@ -1586,6 +1596,12 @@
     }
 }
 
+impl fmt::Debug for SetReadiness {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "SetReadiness")
+    }
+}
+
 impl RegistrationInner {
     /// Get the registration's readiness.
     fn readiness(&self) -> Ready {
diff --git a/src/sys/mod.rs b/src/sys/mod.rs
index fb76adc..cff0631 100644
--- a/src/sys/mod.rs
+++ b/src/sys/mod.rs
@@ -17,7 +17,7 @@
 pub use self::unix::UnixSocket;
 
 #[cfg(unix)]
-mod unix;
+pub mod unix;
 
 #[cfg(windows)]
 pub use self::windows::{
diff --git a/src/sys/unix/epoll.rs b/src/sys/unix/epoll.rs
index ba96738..21f4de9 100644
--- a/src/sys/unix/epoll.rs
+++ b/src/sys/unix/epoll.rs
@@ -20,7 +20,7 @@
 
 use {io, Ready, PollOpt, Token};
 use event_imp::Event;
-use sys::unix::cvt;
+use sys::unix::{cvt, UnixReady};
 use sys::unix::io::set_cloexec;
 
 /// Each Selector has a globally unique(ish) ID associated with it. This ID
@@ -139,11 +139,22 @@
     }
 }
 
+#[cfg(feature = "with-deprecated")]
+#[allow(deprecated)]
+fn is_urgent(opts: PollOpt) -> bool {
+    opts.is_urgent()
+}
+
+#[cfg(not(feature = "with-deprecated"))]
+fn is_urgent(_: PollOpt) -> bool {
+    false
+}
+
 fn ioevent_to_epoll(interest: Ready, opts: PollOpt) -> u32 {
     let mut kind = 0;
 
     if interest.is_readable() {
-        if opts.is_urgent() {
+        if is_urgent(opts) {
             kind |= EPOLLPRI;
         } else {
             kind |= EPOLLIN;
@@ -154,7 +165,7 @@
         kind |= EPOLLOUT;
     }
 
-    if interest.is_hup() {
+    if UnixReady::from(interest).is_hup() {
         kind |= EPOLLRDHUP;
     }
 
@@ -223,11 +234,11 @@
 
             // EPOLLHUP - Usually means a socket error happened
             if (epoll & EPOLLERR) != 0 {
-                kind = kind | Ready::error();
+                kind = kind | UnixReady::error();
             }
 
             if (epoll & EPOLLRDHUP) != 0 || (epoll & EPOLLHUP) != 0 {
-                kind = kind | Ready::hup();
+                kind = kind | UnixReady::hup();
             }
 
             let token = self.events[idx].u64;
diff --git a/src/sys/unix/kqueue.rs b/src/sys/unix/kqueue.rs
index c9dbad1..6b8c92b 100644
--- a/src/sys/unix/kqueue.rs
+++ b/src/sys/unix/kqueue.rs
@@ -9,7 +9,7 @@
 
 use {io, Ready, PollOpt, Token};
 use event_imp::{self as event, Event};
-use sys::unix::cvt;
+use sys::unix::{cvt, UnixReady};
 use sys::unix::io::set_cloexec;
 
 /// Each Selector has a globally unique(ish) ID associated with it. This ID
@@ -221,7 +221,7 @@
             }
 
             if e.flags & libc::EV_ERROR != 0 {
-                event::kind_mut(&mut self.events[idx]).insert(Ready::error());
+                event::kind_mut(&mut self.events[idx]).insert(*UnixReady::error());
             }
 
             if e.filter == libc::EVFILT_READ {
@@ -231,12 +231,12 @@
             }
 
             if e.flags & libc::EV_EOF != 0 {
-                event::kind_mut(&mut self.events[idx]).insert(Ready::hup());
+                event::kind_mut(&mut self.events[idx]).insert(UnixReady::hup());
 
                 // When the read end of the socket is closed, EV_EOF is set on
                 // flags, and fflags contains the error if there is one.
                 if e.fflags != 0 {
-                    event::kind_mut(&mut self.events[idx]).insert(Ready::error());
+                    event::kind_mut(&mut self.events[idx]).insert(UnixReady::error());
                 }
             }
         }
diff --git a/src/sys/unix/mod.rs b/src/sys/unix/mod.rs
index 1a1f9aa..65481c3 100644
--- a/src/sys/unix/mod.rs
+++ b/src/sys/unix/mod.rs
@@ -22,6 +22,7 @@
 mod awakener;
 mod eventedfd;
 mod io;
+mod ready;
 mod tcp;
 mod udp;
 
@@ -31,6 +32,7 @@
 pub use self::awakener::Awakener;
 pub use self::eventedfd::EventedFd;
 pub use self::io::{Io, set_nonblock};
+pub use self::ready::UnixReady;
 pub use self::tcp::{TcpStream, TcpListener};
 pub use self::udp::UdpSocket;
 
diff --git a/src/sys/unix/ready.rs b/src/sys/unix/ready.rs
new file mode 100644
index 0000000..2b08c23
--- /dev/null
+++ b/src/sys/unix/ready.rs
@@ -0,0 +1,269 @@
+use event_imp::{Ready, ready_from_usize};
+
+use std::ops;
+
+/// Unix specific extensions to `Ready`
+///
+/// Provides additional readiness event kinds that are available on unix
+/// platforms. Unix platforms are able to provide readiness events for
+/// additional socket events, such as HUP and error.
+///
+/// HUP events occur when the remote end of a socket hangs up. In the TCP case,
+/// this occurs when the remote end of a TCP socket shuts down writes.
+///
+/// Error events occur when the socket enters an error state. In this case, the
+/// socket will also receive a readable or writable event. Reading or writing to
+/// the socket will result in an error.
+///
+/// Conversion traits are implemented between `Ready` and `UnixReady`. See the
+/// examples.
+///
+/// For high level documentation on polling and readiness, see [`Poll`].
+///
+/// # Examples
+///
+/// Most of the time, all that is needed is using bit operations
+///
+/// ```
+/// use mio::Ready;
+/// use mio::unix::UnixReady;
+///
+/// let ready = Ready::readable() | UnixReady::hup();
+///
+/// assert!(ready.is_readable());
+/// assert!(UnixReady::from(ready).is_hup());
+/// ```
+///
+/// Basic conversion between ready types.
+///
+/// ```
+/// use mio::Ready;
+/// use mio::unix::UnixReady;
+///
+/// // Start with a portable ready
+/// let ready = Ready::readable();
+///
+/// // Convert to a unix ready, adding HUP
+/// let mut unix_ready = UnixReady::from(ready) | UnixReady::hup();
+///
+/// unix_ready.insert(UnixReady::error());
+///
+/// // `unix_ready` maintains readable interest
+/// assert!(unix_ready.is_readable());
+/// assert!(unix_ready.is_hup());
+/// assert!(unix_ready.is_error());
+///
+/// // Convert back to `Ready`
+/// let ready = Ready::from(unix_ready);
+///
+/// // Readable is maintained
+/// assert!(ready.is_readable());
+/// ```
+///
+/// Registering readable and error interest on a socket
+///
+/// ```
+/// use mio::{Ready, Poll, PollOpt, Token};
+/// use mio::tcp::TcpStream;
+/// use mio::unix::UnixReady;
+///
+/// let addr = "216.58.193.68:80".parse().unwrap();
+/// let socket = TcpStream::connect(&addr).unwrap();
+///
+/// let poll = Poll::new().unwrap();
+///
+/// poll.register(&socket,
+///               Token(0),
+///               Ready::readable() | UnixReady::error(),
+///               PollOpt::edge()).unwrap();
+///
+/// ```
+///
+/// [`Poll`]: struct.Poll.html
+/// [readiness]: struct.Poll.html#readiness-operations
+#[derive(Debug, Copy, PartialEq, Eq, Clone, PartialOrd, Ord)]
+pub struct UnixReady(Ready);
+
+const ERROR: usize = 0b0100;
+const HUP: usize   = 0b1000;
+
+impl UnixReady {
+    /// Returns a `Ready` representing error readiness.
+    ///
+    /// **Note that only readable and writable readiness is guaranteed to be
+    /// supported on all platforms**. This means that `error` readiness
+    /// should be treated as a hint. For more details, see [readiness] in the
+    /// poll documentation.
+    ///
+    /// See [`Poll`] for more documentation on polling.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use mio::Ready;
+    ///
+    /// let ready = Ready::error();
+    ///
+    /// assert!(ready.is_error());
+    /// ```
+    ///
+    /// [`Poll`]: struct.Poll.html
+    /// [readiness]: struct.Poll.html#readiness-operations
+    #[inline]
+    pub fn error() -> UnixReady {
+        UnixReady(ready_from_usize(ERROR))
+    }
+
+    /// Returns a `Ready` representing HUP readiness.
+    ///
+    /// A HUP (or hang-up) signifies that a stream socket **peer** closed the
+    /// connection, or shut down the writing half of the connection.
+    ///
+    /// **Note that only readable and writable readiness is guaranteed to be
+    /// supported on all platforms**. This means that `hup` readiness
+    /// should be treated as a hint. For more details, see [readiness] in the
+    /// poll documentation.
+    ///
+    /// See [`Poll`] for more documentation on polling.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use mio::Ready;
+    ///
+    /// let ready = Ready::hup();
+    ///
+    /// assert!(ready.is_hup());
+    /// ```
+    ///
+    /// [`Poll`]: struct.Poll.html
+    /// [readiness]: struct.Poll.html#readiness-operations
+    #[inline]
+    pub fn hup() -> UnixReady {
+        UnixReady(ready_from_usize(HUP))
+    }
+
+    /// Returns true if the value includes error readiness
+    ///
+    /// **Note that only readable and writable readiness is guaranteed to be
+    /// supported on all platforms**. This means that `error` readiness should
+    /// be treated as a hint. For more details, see [readiness] in the poll
+    /// documentation.
+    ///
+    /// See [`Poll`] for more documentation on polling.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use mio::Ready;
+    ///
+    /// let ready = Ready::error();
+    ///
+    /// assert!(ready.is_error());
+    /// ```
+    ///
+    /// [`Poll`]: struct.Poll.html
+    #[inline]
+    pub fn is_error(&self) -> bool {
+        self.contains(ready_from_usize(ERROR))
+    }
+
+    /// Returns true if the value includes HUP readiness
+    ///
+    /// A HUP (or hang-up) signifies that a stream socket **peer** closed the
+    /// connection, or shut down the writing half of the connection.
+    ///
+    /// **Note that only readable and writable readiness is guaranteed to be
+    /// supported on all platforms**. This means that `hup` readiness
+    /// should be treated as a hint. For more details, see [readiness] in the
+    /// poll documentation.
+    ///
+    /// See [`Poll`] for more documentation on polling.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use mio::Ready;
+    ///
+    /// let ready = Ready::hup();
+    ///
+    /// assert!(ready.is_hup());
+    /// ```
+    ///
+    /// [`Poll`]: struct.Poll.html
+    #[inline]
+    pub fn is_hup(&self) -> bool {
+        self.contains(ready_from_usize(HUP))
+    }
+}
+
+impl From<Ready> for UnixReady {
+    fn from(src: Ready) -> UnixReady {
+        UnixReady(src)
+    }
+}
+
+impl From<UnixReady> for Ready {
+    fn from(src: UnixReady) -> Ready {
+        src.0
+    }
+}
+
+impl ops::Deref for UnixReady {
+    type Target = Ready;
+
+    fn deref(&self) -> &Ready {
+        &self.0
+    }
+}
+
+impl ops::DerefMut for UnixReady {
+    fn deref_mut(&mut self) -> &mut Ready {
+        &mut self.0
+    }
+}
+
+impl ops::BitOr for UnixReady {
+    type Output = UnixReady;
+
+    #[inline]
+    fn bitor(self, other: UnixReady) -> UnixReady {
+        (self.0 | other.0).into()
+    }
+}
+
+impl ops::BitXor for UnixReady {
+    type Output = UnixReady;
+
+    #[inline]
+    fn bitxor(self, other: UnixReady) -> UnixReady {
+        (self.0 ^ other.0).into()
+    }
+}
+
+impl ops::BitAnd for UnixReady {
+    type Output = UnixReady;
+
+    #[inline]
+    fn bitand(self, other: UnixReady) -> UnixReady {
+        (self.0 & other.0).into()
+    }
+}
+
+impl ops::Sub for UnixReady {
+    type Output = UnixReady;
+
+    #[inline]
+    fn sub(self, other: UnixReady) -> UnixReady {
+        (self.0 & !other.0).into()
+    }
+}
+
+impl ops::Not for UnixReady {
+    type Output = UnixReady;
+
+    #[inline]
+    fn not(self) -> UnixReady {
+        (!self.0).into()
+    }
+}
diff --git a/src/sys/windows/selector.rs b/src/sys/windows/selector.rs
index d3b684b..45d892e 100644
--- a/src/sys/windows/selector.rs
+++ b/src/sys/windows/selector.rs
@@ -1,6 +1,6 @@
 #![allow(deprecated)]
 
-use std::{io, u32};
+use std::{fmt, io, u32};
 use std::cell::UnsafeCell;
 use std::os::windows::prelude::*;
 use std::sync::{Arc, Mutex};
@@ -268,6 +268,12 @@
     }
 }
 
+impl fmt::Debug for Binding {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "Binding")
+    }
+}
+
 /// Helper struct used for TCP and UDP which bundles a `binding` with a
 /// `SetReadiness` handle.
 pub struct ReadyBinding {
@@ -354,13 +360,6 @@
             try!(self.binding.register_socket(socket, token, poll));
         }
 
-        // To keep the same semantics as epoll, if I/O objects are interested in
-        // being readable then they're also interested in listening for hup
-        let events = if events.is_readable() {
-            events | Ready::hup()
-        }  else {
-            events
-        };
         let (r, s) = poll::new_registration(poll, token, events, opts);
         self.readiness = Some(s);
         *registration.lock().unwrap() = Some(r);
@@ -381,13 +380,6 @@
             try!(self.binding.reregister_socket(socket, token, poll));
         }
 
-        // To keep the same semantics as epoll, if I/O objects are interested in
-        // being readable then they're also interested in listening for hup
-        let events = if events.is_readable() {
-            events | Ready::hup()
-        }  else {
-            events
-        };
         registration.lock().unwrap()
                     .as_mut().unwrap()
                     .reregister(poll, token, events, opts)
@@ -523,6 +515,12 @@
     }
 }
 
+impl fmt::Debug for Overlapped {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "Overlapped")
+    }
+}
+
 // Overlapped's APIs are marked as unsafe Overlapped's APIs are marked as
 // unsafe as they must be used with caution to ensure thread safety. The
 // structure itself is safe to send across threads.
diff --git a/src/sys/windows/tcp.rs b/src/sys/windows/tcp.rs
index 2fe0898..12f096a 100644
--- a/src/sys/windows/tcp.rs
+++ b/src/sys/windows/tcp.rs
@@ -395,15 +395,8 @@
                 mem::forget(self.clone());
             }
             Err(e) => {
-                // Like above, be sure to indicate that hup has happened
-                // whenever we get `ECONNRESET`
-                let mut set = Ready::readable();
-                if e.raw_os_error() == Some(WSAECONNRESET as i32) {
-                    trace!("tcp stream at hup: econnreset");
-                    set = set | Ready::hup();
-                }
                 me.read = State::Error(e);
-                self.add_readiness(me, set);
+                self.add_readiness(me, Ready::readable());
             }
         }
     }
diff --git a/src/timer.rs b/src/timer.rs
index 5f096ed..6a8b4b4 100644
--- a/src/timer.rs
+++ b/src/timer.rs
@@ -1,6 +1,6 @@
 //! Timer optimized for I/O related operations
 
-#![allow(deprecated)]
+#![allow(deprecated, missing_debug_implementations)]
 
 use {convert, io, Evented, Ready, Poll, PollOpt, Registration, SetReadiness, Token};
 use lazycell::LazyCell;