Bug 1467277 - Bump euclid to 0.18 for style, style_traits, malloc_size_of, and tests. r=emilio
authorBoris Chiou <boris.chiou@gmail.com>
Mon, 09 Jul 2018 12:10:50 -0700
changeset 483411 a57f16821e08889c73060a7b598f3c06f5ad271b
parent 483410 3ffd10f22f12e0e99bfdce0c57adbce45eb8ee6b
child 483412 e42f62ecacfe93353c64b8ed0cd3e30cc771bb19
push id1815
push userffxbld-merge
push dateMon, 15 Oct 2018 10:40:45 +0000
treeherdermozilla-release@18d4c09e9378 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
bugs1467277
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1467277 - Bump euclid to 0.18 for style, style_traits, malloc_size_of, and tests. r=emilio In order to drop old euclid version, we still need to bump euclid for plane-split and gfx/*. However, it needs more update and is not related to this bug, so let's do that in other place. Here, we bump euclid to 0.18.1, and update style/values/generics/transform.rs for it. MozReview-Commit-ID: JfNAxkR8wgs
Cargo.lock
servo/components/malloc_size_of/Cargo.toml
servo/components/style/Cargo.toml
servo/components/style/values/generics/transform.rs
servo/components/style_traits/Cargo.toml
servo/ports/geckolib/tests/Cargo.toml
servo/tests/unit/style/Cargo.toml
third_party/rust/euclid-0.17.3/.cargo-checksum.json
third_party/rust/euclid-0.17.3/.travis.yml
third_party/rust/euclid-0.17.3/COPYRIGHT
third_party/rust/euclid-0.17.3/Cargo.toml
third_party/rust/euclid-0.17.3/LICENSE-APACHE
third_party/rust/euclid-0.17.3/LICENSE-MIT
third_party/rust/euclid-0.17.3/README.md
third_party/rust/euclid-0.17.3/src/approxeq.rs
third_party/rust/euclid-0.17.3/src/homogen.rs
third_party/rust/euclid-0.17.3/src/length.rs
third_party/rust/euclid-0.17.3/src/lib.rs
third_party/rust/euclid-0.17.3/src/macros.rs
third_party/rust/euclid-0.17.3/src/num.rs
third_party/rust/euclid-0.17.3/src/point.rs
third_party/rust/euclid-0.17.3/src/rect.rs
third_party/rust/euclid-0.17.3/src/rotation.rs
third_party/rust/euclid-0.17.3/src/scale.rs
third_party/rust/euclid-0.17.3/src/side_offsets.rs
third_party/rust/euclid-0.17.3/src/size.rs
third_party/rust/euclid-0.17.3/src/transform2d.rs
third_party/rust/euclid-0.17.3/src/transform3d.rs
third_party/rust/euclid-0.17.3/src/trig.rs
third_party/rust/euclid-0.17.3/src/vector.rs
third_party/rust/euclid/.cargo-checksum.json
third_party/rust/euclid/Cargo.toml
third_party/rust/euclid/src/homogen.rs
third_party/rust/euclid/src/length.rs
third_party/rust/euclid/src/lib.rs
third_party/rust/euclid/src/macros.rs
third_party/rust/euclid/src/point.rs
third_party/rust/euclid/src/rect.rs
third_party/rust/euclid/src/rotation.rs
third_party/rust/euclid/src/scale.rs
third_party/rust/euclid/src/side_offsets.rs
third_party/rust/euclid/src/size.rs
third_party/rust/euclid/src/transform2d.rs
third_party/rust/euclid/src/transform3d.rs
third_party/rust/euclid/src/trig.rs
third_party/rust/euclid/src/vector.rs
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -674,16 +674,24 @@ name = "euclid"
 version = "0.17.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "euclid"
+version = "0.18.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "fallible"
 version = "0.0.1"
 dependencies = [
  "hashglobe 0.1.0",
  "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1137,17 +1145,17 @@ dependencies = [
 ]
 
 [[package]]
 name = "malloc_size_of"
 version = "0.0.1"
 dependencies = [
  "app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
  "selectors 0.19.0",
  "servo_arc 0.1.1",
  "smallbitvec 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1937,17 +1945,17 @@ dependencies = [
  "app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bindgen 0.37.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "fallible 0.0.1",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
  "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1992,32 +2000,32 @@ dependencies = [
 
 [[package]]
 name = "style_traits"
 version = "0.0.1"
 dependencies = [
  "app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "malloc_size_of_derive 0.0.1",
  "selectors 0.19.0",
  "servo_arc 0.1.1",
 ]
 
 [[package]]
 name = "stylo_tests"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "geckoservo 0.0.1",
  "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "size_of_test 0.0.1",
  "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2586,16 +2594,17 @@ dependencies = [
 "checksum dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b26e30aaa6bf31ec830db15fec14ed04f0f2ecfcc486ecfce88c55d3389b237f"
 "checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a"
 "checksum ena 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cabe5a5078ac8c506d3e4430763b1ba9b609b1286913e7d08e581d1c2de9b7e5"
 "checksum encoding_c 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "769ecb8b33323998e482b218c0d13cd64c267609023b4b7ec3ee740714c318ee"
 "checksum encoding_rs 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88a1b66a0d28af4b03a8c8278c6dcb90e6e600d89c14500a9e7a02e64b9ee3ac"
 "checksum env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0561146661ae44c579e993456bc76d11ce1e0c7d745e57b2fa7146b6e49fa2ad"
 "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
 "checksum euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c95fd0d455f114291a3109286bd387bd423770058474a2d3f38b712cd661df60"
+"checksum euclid 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "47d5eb6310c8dd3e79f973952ddcb180bf6a98c01d341add49126a094b5598cc"
 "checksum fixedbitset 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "85cb8fec437468d86dc7c83ca7cfc933341d561873275f22dd5eedefa63a6478"
 "checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909"
 "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
 "checksum foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ebc04f19019fff1f2d627b5581574ead502f80c48c88900575a46e0840fe5d0"
 "checksum freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b659e75b7a7338fe75afd7f909fc2b71937845cffb6ebe54ba2e50f13d8e903d"
 "checksum fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab76cfd2aaa59b7bf6688ad9ba15bbae64bff97f04ea02144cfd3443e5c2866"
 "checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"
 "checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"
--- a/servo/components/malloc_size_of/Cargo.toml
+++ b/servo/components/malloc_size_of/Cargo.toml
@@ -20,17 +20,17 @@ servo = [
     "url",
     "webrender_api",
     "xml5ever",
 ]
 
 [dependencies]
 app_units = "0.6"
 cssparser = "0.24.0"
-euclid = "0.17"
+euclid = "0.18"
 hashglobe = { path = "../hashglobe" }
 hyper = { version = "0.10", optional = true }
 hyper_serde = { version = "0.8", optional = true }
 mozjs = { version = "0.7.1", features = ["promises"], optional = true }
 selectors = { path = "../selectors" }
 serde = { version = "1.0.27", optional = true }
 serde_bytes = { version = "0.10", optional = true }
 servo_arc = { path = "../servo_arc" }
--- a/servo/components/style/Cargo.toml
+++ b/servo/components/style/Cargo.toml
@@ -29,17 +29,17 @@ app_units = "0.6"
 arrayvec = "0.4.6"
 atomic_refcell = "0.1"
 bitflags = "1.0"
 byteorder = "1.0"
 cfg-if = "0.1.0"
 cssparser = "0.24.0"
 new_debug_unreachable = "1.0"
 encoding_rs = {version = "0.7", optional = true}
-euclid = "0.17"
+euclid = "0.18"
 fallible = { path = "../fallible" }
 fnv = "1.0"
 hashglobe = { path = "../hashglobe" }
 html5ever = {version = "0.22", optional = true}
 itertools = "0.7.6"
 itoa = "0.3"
 lazy_static = "1"
 log = "0.4"
--- a/servo/components/style/values/generics/transform.rs
+++ b/servo/components/style/values/generics/transform.rs
@@ -431,17 +431,16 @@ where
             },
             RotateZ(theta) | Rotate(theta) => {
                 let theta = euclid::Angle::radians(TWO_PI - theta.as_ref().radians64());
                 Transform3D::create_rotation(0., 0., 1., theta)
             },
             Perspective(ref d) => {
                 let m = create_perspective_matrix(d.to_pixel_length(None)?);
                 m.cast()
-                    .expect("Casting from f32 to f64 should be successful")
             },
             Scale3D(sx, sy, sz) => Transform3D::create_scale(sx.into(), sy.into(), sz.into()),
             Scale(sx, sy) => Transform3D::create_scale(sx.into(), sy.unwrap_or(sx).into(), 1.),
             ScaleX(s) => Transform3D::create_scale(s.into(), 1., 1.),
             ScaleY(s) => Transform3D::create_scale(1., s.into(), 1.),
             ScaleZ(s) => Transform3D::create_scale(1., 1., s.into()),
             Translate3D(ref tx, ref ty, ref tz) => {
                 let tx = tx.to_pixel_length(reference_width)? as f64;
--- a/servo/components/style_traits/Cargo.toml
+++ b/servo/components/style_traits/Cargo.toml
@@ -12,17 +12,17 @@ path = "lib.rs"
 [features]
 servo = ["serde", "servo_atoms", "cssparser/serde", "webrender_api", "servo_url"]
 gecko = []
 
 [dependencies]
 app_units = "0.6"
 cssparser = "0.24.0"
 bitflags = "1.0"
-euclid = "0.17"
+euclid = "0.18"
 malloc_size_of = { path = "../malloc_size_of" }
 malloc_size_of_derive = { path = "../malloc_size_of_derive" }
 selectors = { path = "../selectors" }
 serde = {version = "1.0", optional = true}
 webrender_api = {git = "https://github.com/servo/webrender", optional = true}
 servo_atoms = {path = "../atoms", optional = true}
 servo_arc = { path = "../servo_arc" }
 servo_url = { path = "../url", optional = true }
--- a/servo/ports/geckolib/tests/Cargo.toml
+++ b/servo/ports/geckolib/tests/Cargo.toml
@@ -11,17 +11,17 @@ name = "stylo_tests"
 path = "lib.rs"
 doctest = false
 
 [dependencies]
 atomic_refcell = "0.1"
 cssparser = "0.24.0"
 cstr = "0.1.2"
 env_logger = { version = "0.5", default-features = false }
-euclid = "0.17"
+euclid = "0.18"
 geckoservo = {path = "../../../ports/geckolib"}
 libc = "0.2"
 log = {version = "0.4", features = ["release_max_level_info"]}
 malloc_size_of = {path = "../../../components/malloc_size_of"}
 selectors = {path = "../../../components/selectors"}
 size_of_test = {path = "../../../components/size_of_test"}
 smallvec = "0.6"
 style_traits = {path = "../../../components/style_traits"}
--- a/servo/tests/unit/style/Cargo.toml
+++ b/servo/tests/unit/style/Cargo.toml
@@ -8,17 +8,17 @@ license = "MPL-2.0"
 name = "style_tests"
 path = "lib.rs"
 doctest = false
 
 [dependencies]
 byteorder = "1.0"
 app_units = "0.6"
 cssparser = "0.24.0"
-euclid = "0.17"
+euclid = "0.18"
 html5ever = "0.22"
 parking_lot = "0.5"
 rayon = "1"
 serde_json = "1.0"
 selectors = {path = "../../../components/selectors"}
 servo_arc = {path = "../../../components/servo_arc"}
 servo_atoms = {path = "../../../components/atoms"}
 servo_config = {path = "../../../components/config"}
copy from third_party/rust/euclid/.cargo-checksum.json
copy to third_party/rust/euclid-0.17.3/.cargo-checksum.json
new file mode 100644
--- /dev/null
+++ b/third_party/rust/euclid-0.17.3/.travis.yml
@@ -0,0 +1,25 @@
+language: rust
+
+notifications:
+  webhooks: http://build.servo.org:54856/travis
+
+rust:
+  - 1.23.0
+  - stable
+  - beta
+  - nightly
+
+env:
+  - FEATURES=""
+  - FEATURES="--features serde"
+
+matrix:
+  include:
+    - rust: nightly
+      env: FEATURES="--features unstable"
+    - rust: nightly
+      env: FEATURES="--features unstable,serde"
+
+script:
+  - cargo build $FEATURES
+  - cargo test --verbose $FEATURES
new file mode 100644
--- /dev/null
+++ b/third_party/rust/euclid-0.17.3/COPYRIGHT
@@ -0,0 +1,5 @@
+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. All files in the project carrying such notice may not be
+copied, modified, or distributed except according to those terms.
copy from third_party/rust/euclid/Cargo.toml
copy to third_party/rust/euclid-0.17.3/Cargo.toml
new file mode 100644
--- /dev/null
+++ b/third_party/rust/euclid-0.17.3/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/euclid-0.17.3/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2012-2013 Mozilla Foundation
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/euclid-0.17.3/README.md
@@ -0,0 +1,8 @@
+# euclid
+
+This is a small library for geometric types with a focus on 2d graphics and
+layout.
+
+* [Documentation](https://docs.rs/euclid/)
+* [Release notes](https://github.com/servo/euclid/releases)
+* [crates.io](https://crates.io/crates/euclid)
new file mode 100644
--- /dev/null
+++ b/third_party/rust/euclid-0.17.3/src/approxeq.rs
@@ -0,0 +1,35 @@
+// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// 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.
+
+/// Trait for testing approximate equality
+pub trait ApproxEq<Eps> {
+    fn approx_epsilon() -> Eps;
+    fn approx_eq(&self, other: &Self) -> bool;
+    fn approx_eq_eps(&self, other: &Self, approx_epsilon: &Eps) -> bool;
+}
+
+macro_rules! approx_eq {
+    ($ty:ty, $eps:expr) => (
+        impl ApproxEq<$ty> for $ty {
+            #[inline]
+            fn approx_epsilon() -> $ty { $eps }
+            #[inline]
+            fn approx_eq(&self, other: &$ty) -> bool {
+                self.approx_eq_eps(other, &$eps)
+            }
+            #[inline]
+            fn approx_eq_eps(&self, other: &$ty, approx_epsilon: &$ty) -> bool {
+                (*self - *other).abs() < *approx_epsilon
+            }
+        }
+    )
+}
+
+approx_eq!(f32, 1.0e-6);
+approx_eq!(f64, 1.0e-6);
copy from third_party/rust/euclid/src/homogen.rs
copy to third_party/rust/euclid-0.17.3/src/homogen.rs
copy from third_party/rust/euclid/src/length.rs
copy to third_party/rust/euclid-0.17.3/src/length.rs
copy from third_party/rust/euclid/src/lib.rs
copy to third_party/rust/euclid-0.17.3/src/lib.rs
copy from third_party/rust/euclid/src/macros.rs
copy to third_party/rust/euclid-0.17.3/src/macros.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/euclid-0.17.3/src/num.rs
@@ -0,0 +1,85 @@
+// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// 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.
+//! A one-dimensional length, tagged with its units.
+
+use num_traits;
+
+pub trait Zero {
+    fn zero() -> Self;
+}
+
+impl<T: num_traits::Zero> Zero for T {
+    fn zero() -> T {
+        num_traits::Zero::zero()
+    }
+}
+
+pub trait One {
+    fn one() -> Self;
+}
+
+impl<T: num_traits::One> One for T {
+    fn one() -> T {
+        num_traits::One::one()
+    }
+}
+
+pub trait Round: Copy {
+    fn round(self) -> Self;
+}
+pub trait Floor: Copy {
+    fn floor(self) -> Self;
+}
+pub trait Ceil: Copy {
+    fn ceil(self) -> Self;
+}
+
+macro_rules! num_int {
+    ($ty:ty) => (
+        impl Round for $ty {
+            #[inline]
+            fn round(self) -> $ty { self }
+        }
+        impl Floor for $ty {
+            #[inline]
+            fn floor(self) -> $ty { self }
+        }
+        impl Ceil for $ty {
+            #[inline]
+            fn ceil(self) -> $ty { self }
+        }
+    )
+}
+macro_rules! num_float {
+    ($ty:ty) => (
+        impl Round for $ty {
+            #[inline]
+            fn round(self) -> $ty { self.round() }
+        }
+        impl Floor for $ty {
+            #[inline]
+            fn floor(self) -> $ty { self.floor() }
+        }
+        impl Ceil for $ty {
+            #[inline]
+            fn ceil(self) -> $ty { self.ceil() }
+        }
+    )
+}
+
+num_int!(i16);
+num_int!(u16);
+num_int!(i32);
+num_int!(u32);
+num_int!(i64);
+num_int!(u64);
+num_int!(isize);
+num_int!(usize);
+num_float!(f32);
+num_float!(f64);
copy from third_party/rust/euclid/src/point.rs
copy to third_party/rust/euclid-0.17.3/src/point.rs
copy from third_party/rust/euclid/src/rect.rs
copy to third_party/rust/euclid-0.17.3/src/rect.rs
copy from third_party/rust/euclid/src/rotation.rs
copy to third_party/rust/euclid-0.17.3/src/rotation.rs
copy from third_party/rust/euclid/src/scale.rs
copy to third_party/rust/euclid-0.17.3/src/scale.rs
copy from third_party/rust/euclid/src/side_offsets.rs
copy to third_party/rust/euclid-0.17.3/src/side_offsets.rs
copy from third_party/rust/euclid/src/size.rs
copy to third_party/rust/euclid-0.17.3/src/size.rs
copy from third_party/rust/euclid/src/transform2d.rs
copy to third_party/rust/euclid-0.17.3/src/transform2d.rs
copy from third_party/rust/euclid/src/transform3d.rs
copy to third_party/rust/euclid-0.17.3/src/transform3d.rs
copy from third_party/rust/euclid/src/trig.rs
copy to third_party/rust/euclid-0.17.3/src/trig.rs
copy from third_party/rust/euclid/src/vector.rs
copy to third_party/rust/euclid-0.17.3/src/vector.rs
--- a/third_party/rust/euclid/.cargo-checksum.json
+++ b/third_party/rust/euclid/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".travis.yml":"301590735ff27f124c03cef8598aa5397c88c59aba3d058edf0bde532965c346","COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"2d7ade90b1883e9ec1e718b52a7c1785adf7d8f482a3d2a2813079ad15de906b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"625bec69c76ce5423fdd05cfe46922b2680ec517f97c5854ce34798d1d8a9541","src/approxeq.rs":"6594377e8f6c20f88f628520d8de9b9a59c5892a0ee9a6ccd13c8400c1499911","src/homogen.rs":"df6bdb87aee7422c19cf8ce633c70656ebea789b96f6fcc396baecc4c3ef6ab3","src/length.rs":"5c0784bccb1840f1bc86f45c80094584ca2f60b6a644797a5e760341c15c6e50","src/lib.rs":"ef31060a582a8a133750aeaa7244cc6bbb709a0aec7d964a76b54643bb9f7134","src/macros.rs":"ccb9aeb942f571ec4207334b87c87f59a9a4d666039d143d7673372679c42347","src/num.rs":"4439479fad5729073e0bfe0b96b547672a237430d48e564519759b9550baa033","src/point.rs":"50ccf38962b2aee2b0b2e7c516f24e54908286953cb7cf97b5a6b9fb7bdfc91b","src/rect.rs":"b96f267123972d7d924d08d8b93bea9333d71654febe20063c532a11f7c7ae30","src/rotation.rs":"2686d8624671f48e9c657a98c9ac3345f3c4028e65ee3ef588d407ffd020fb86","src/scale.rs":"80c96c99cc916cac155fc898cd34a771a64ab46a60340cb7de876d224f0c7cb1","src/side_offsets.rs":"604e104616777515e0e0e68262110c55fe9c0ce4deeb6d022e5b4984df11e29f","src/size.rs":"ee722964a6e6654eacd8f321f5c3f62452237316d9d2dac8a98753f6227c4fce","src/transform2d.rs":"edf9b82411a25d8f6b2a867a5b579c15316b3fd112eb463f6589012039670be3","src/transform3d.rs":"797c445c99edace0a6e51e166cdbeb667620c6fd98cbc0249742bbd09588dc7f","src/trig.rs":"78b8fb26d2fded11c4b8aa47935e80c474696aee1999c688642534b667e005d9","src/vector.rs":"37215522068612107acca427c83159f4bca79ae41a2f54d9c7d0feb4b28b2348"},"package":"c95fd0d455f114291a3109286bd387bd423770058474a2d3f38b712cd661df60"}
\ No newline at end of file
+{"files":{".travis.yml":"301590735ff27f124c03cef8598aa5397c88c59aba3d058edf0bde532965c346","COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"d67b137d287c8debd8811e4deb3c2973eb9ee1ea11b31fcdd8217591482021f6","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"625bec69c76ce5423fdd05cfe46922b2680ec517f97c5854ce34798d1d8a9541","src/approxeq.rs":"6594377e8f6c20f88f628520d8de9b9a59c5892a0ee9a6ccd13c8400c1499911","src/homogen.rs":"cb26346ad1ea2797bdc1cac7f532872becabf28a1f9c60792f86ad4a655582f9","src/length.rs":"3171315822707728b1bfbdd04a4190ffb7206b4bfc59e9dd072bb2caa05ff292","src/lib.rs":"b3c2303ab06ce972784c2ec4faa09ecdaa8e0706316f427c8a2009445a52f6e9","src/macros.rs":"877b4bd62b63ea120e568803281e7169f33fb811fe1c1515e56bfc44a74c34a2","src/num.rs":"4439479fad5729073e0bfe0b96b547672a237430d48e564519759b9550baa033","src/point.rs":"d18046853e19012e649a01991d45fdb1ba8f51eb55e52273e68f567cd7df932a","src/rect.rs":"1a4fbcf482e447218894c6a31753cb9b5a6c3e5377447ba7b5bceae7941a0772","src/rotation.rs":"982aaca640215bacc5d2dc60a8949bb2510d5b6d492975b8b6946a7c8f69b496","src/scale.rs":"fc07bcf47f3a1215023c830059f0d270e570cbd37fe8c367ef4a47b191f4ae3e","src/side_offsets.rs":"f114cb881256bbeff2ee2aa305d363e2dea65aa8535140f104f6fa9364bd02f5","src/size.rs":"f6a4f12fc50cc54220af089339cb7fde37f22c6dfcc4c2c676d24caab07b1790","src/transform2d.rs":"137344a16162f5cd1dc4a2ae87b8ea3fdde7597874835582378945f55e45513e","src/transform3d.rs":"efd971ba35e8a9ab59b0c4062b2625532147af0e57bf96b8cd09117524cf23ed","src/trig.rs":"97a263c4f178b0332501659ca8143f9f637a0755aca189dd31ac551bcd4cb73c","src/vector.rs":"d84103384907174d2b2206acd60d6b3261edb3ac971ec5e121ae22ce6bcca5d9"},"package":"47d5eb6310c8dd3e79f973952ddcb180bf6a98c01d341add49126a094b5598cc"}
\ No newline at end of file
--- a/third_party/rust/euclid/Cargo.toml
+++ b/third_party/rust/euclid/Cargo.toml
@@ -7,17 +7,17 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "euclid"
-version = "0.17.3"
+version = "0.18.1"
 authors = ["The Servo Project Developers"]
 description = "Geometry primitives"
 documentation = "https://docs.rs/euclid/"
 keywords = ["matrix", "vector", "linear-algebra", "geometry"]
 categories = ["science"]
 license = "MIT / Apache-2.0"
 repository = "https://github.com/servo/euclid"
 [dependencies.num-traits]
--- a/third_party/rust/euclid/src/homogen.rs
+++ b/third_party/rust/euclid/src/homogen.rs
@@ -7,19 +7,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
 use point::{TypedPoint2D, TypedPoint3D};
 use vector::{TypedVector2D, TypedVector3D};
 
 use num::{One, Zero};
 
-use std::fmt;
-use std::marker::PhantomData;
-use std::ops::Div;
+use core::fmt;
+use core::marker::PhantomData;
+use core::ops::Div;
 
 
 define_matrix! {
     /// Homogeneous vector in 3D space.
     pub struct HomogeneousVector<T, U> {
         pub x: T,
         pub y: T,
         pub z: T,
@@ -32,31 +32,39 @@ impl<T, U> HomogeneousVector<T, U> {
     /// Constructor taking scalar values directly.
     #[inline]
     pub fn new(x: T, y: T, z: T, w: T) -> Self {
         HomogeneousVector { x, y, z, w, _unit: PhantomData }
     }
 }
 
 
-impl<T: Copy + Div<T, Output=T>, U> HomogeneousVector<T, U> {
+impl<T: Copy + Div<T, Output=T> + Zero + PartialOrd, U> HomogeneousVector<T, U> {
     /// Convert into Cartesian 2D point.
     ///
-    /// Note: possible division by zero.
+    /// Returns None if the point is on or behind the W=0 hemisphere.
     #[inline]
-    pub fn to_point2d(&self) -> TypedPoint2D<T, U> {
-        TypedPoint2D::new(self.x / self.w, self.y / self.w)
+    pub fn to_point2d(&self) -> Option<TypedPoint2D<T, U>> {
+        if self.w > T::zero() {
+            Some(TypedPoint2D::new(self.x / self.w, self.y / self.w))
+        } else {
+            None
+        }
     }
 
     /// Convert into Cartesian 3D point.
     ///
-    /// Note: possible division by zero.
+    /// Returns None if the point is on or behind the W=0 hemisphere.
     #[inline]
-    pub fn to_point3d(&self) -> TypedPoint3D<T, U> {
-        TypedPoint3D::new(self.x / self.w, self.y / self.w, self.z / self.w)
+    pub fn to_point3d(&self) -> Option<TypedPoint3D<T, U>> {
+        if self.w > T::zero() {
+            Some(TypedPoint3D::new(self.x / self.w, self.y / self.w, self.z / self.w))
+        } else {
+            None
+        }
     }
 }
 
 impl<T: Zero, U> From<TypedVector2D<T, U>> for HomogeneousVector<T, U> {
     #[inline]
     fn from(v: TypedVector2D<T, U>) -> Self {
         HomogeneousVector::new(v.x, v.y, T::zero(), T::zero())
     }
@@ -98,12 +106,18 @@ impl<T: fmt::Display, U> fmt::Display fo
 
 #[cfg(test)]
 mod homogeneous {
     use super::HomogeneousVector;
     use point::{Point2D, Point3D};
 
     #[test]
     fn roundtrip() {
-        assert_eq!(Point2D::new(1.0, 2.0), HomogeneousVector::from(Point2D::new(1.0, 2.0)).to_point2d());
-        assert_eq!(Point3D::new(1.0, -2.0, 0.1), HomogeneousVector::from(Point3D::new(1.0, -2.0, 0.1)).to_point3d());
+        assert_eq!(Some(Point2D::new(1.0, 2.0)), HomogeneousVector::from(Point2D::new(1.0, 2.0)).to_point2d());
+        assert_eq!(Some(Point3D::new(1.0, -2.0, 0.1)), HomogeneousVector::from(Point3D::new(1.0, -2.0, 0.1)).to_point3d());
+    }
+
+    #[test]
+    fn negative() {
+        assert_eq!(None, HomogeneousVector::<f32, ()>::new(1.0, 2.0, 3.0, 0.0).to_point2d());
+        assert_eq!(None, HomogeneousVector::<f32, ()>::new(1.0, -2.0, -3.0, -2.0).to_point3d());
     }
 }
--- a/third_party/rust/euclid/src/length.rs
+++ b/third_party/rust/euclid/src/length.rs
@@ -10,37 +10,37 @@
 
 use scale::TypedScale;
 use num::Zero;
 
 use num_traits::{NumCast, Saturating};
 use num::One;
 #[cfg(feature = "serde")]
 use serde::{Deserialize, Deserializer, Serialize, Serializer};
-use std::cmp::Ordering;
-use std::ops::{Add, Div, Mul, Neg, Sub};
-use std::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
-use std::marker::PhantomData;
-use std::fmt;
+use core::cmp::Ordering;
+use core::ops::{Add, Div, Mul, Neg, Sub};
+use core::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
+use core::marker::PhantomData;
+use core::fmt;
 
 /// A one-dimensional distance, with value represented by `T` and unit of measurement `Unit`.
 ///
 /// `T` can be any numeric type, for example a primitive type like `u64` or `f32`.
 ///
 /// `Unit` is not used in the representation of a `Length` value. It is used only at compile time
 /// to ensure that a `Length` stored with one unit is converted explicitly before being used in an
 /// expression that requires a different unit.  It may be a type without values, such as an empty
 /// enum.
 ///
 /// You can multiply a `Length` by a `scale::TypedScale` to convert it from one unit to
 /// another. See the [`TypedScale`] docs for an example.
 ///
 /// [`TypedScale`]: struct.TypedScale.html
 #[repr(C)]
-pub struct Length<T, Unit>(pub T, PhantomData<Unit>);
+pub struct Length<T, Unit>(pub T, #[doc(hidden)] pub PhantomData<Unit>);
 
 impl<T: Clone, Unit> Clone for Length<T, Unit> {
     fn clone(&self) -> Self {
         Length(self.0.clone(), PhantomData)
     }
 }
 
 impl<T: Copy, Unit> Copy for Length<T, Unit> {}
@@ -206,17 +206,22 @@ impl<U, T: Clone + Neg<Output = T>> Neg 
     #[inline]
     fn neg(self) -> Length<T, U> {
         Length::new(-self.get())
     }
 }
 
 impl<Unit, T0: NumCast + Clone> Length<T0, Unit> {
     /// Cast from one numeric representation to another, preserving the units.
-    pub fn cast<T1: NumCast + Clone>(&self) -> Option<Length<T1, Unit>> {
+    pub fn cast<T1: NumCast + Clone>(&self) -> Length<T1, Unit> {
+        self.try_cast().unwrap()
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    pub fn try_cast<T1: NumCast + Clone>(&self) -> Option<Length<T1, Unit>> {
         NumCast::from(self.get()).map(Length::new)
     }
 }
 
 impl<Unit, T: Clone + PartialEq> PartialEq for Length<T, Unit> {
     fn eq(&self, other: &Self) -> bool {
         self.get().eq(&other.get())
     }
@@ -258,17 +263,17 @@ where
 
 #[cfg(test)]
 mod tests {
     use super::Length;
     use num::Zero;
 
     use num_traits::Saturating;
     use scale::TypedScale;
-    use std::f32::INFINITY;
+    use core::f32::INFINITY;
 
     enum Inch {}
     enum Mm {}
     enum Cm {}
     enum Second {}
 
     #[cfg(feature = "serde")]
     mod serde {
@@ -456,17 +461,17 @@ mod tests {
         let expected: Length<f32, Cm> = Length::new(-5.0);
         assert_eq!(result, expected);
     }
 
     #[test]
     fn test_cast() {
         let length_as_i32: Length<i32, Cm> = Length::new(5);
 
-        let result: Length<f32, Cm> = length_as_i32.cast().unwrap();
+        let result: Length<f32, Cm> = length_as_i32.cast();
 
         let length_as_f32: Length<f32, Cm> = Length::new(5.0);
         assert_eq!(result, length_as_f32);
     }
 
     #[test]
     fn test_equality() {
         let length_5_point_0: Length<f32, Cm> = Length::new(5.0);
--- a/third_party/rust/euclid/src/lib.rs
+++ b/third_party/rust/euclid/src/lib.rs
@@ -3,16 +3,17 @@
 //
 // 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.
 
 #![cfg_attr(feature = "unstable", feature(fn_must_use))]
+#![cfg_attr(not(test), no_std)]
 
 //! A collection of strongly typed math tools for computer graphics with an inclination
 //! towards 2d graphics and layout.
 //!
 //! All types are generic over the scalar type of their component (`f32`, `i32`, etc.),
 //! and tagged with a generic Unit parameter which is useful to prevent mixing
 //! values from different spaces. For example it should not be legal to translate
 //! a screen-space position by a world-space vector and this can be expressed using
@@ -58,16 +59,19 @@
 #[cfg(feature = "serde")]
 #[macro_use]
 extern crate serde;
 
 extern crate num_traits;
 #[cfg(test)]
 extern crate rand;
 
+#[cfg(test)]
+use std as core;
+
 pub use length::Length;
 pub use scale::TypedScale;
 pub use transform2d::{Transform2D, TypedTransform2D};
 pub use transform3d::{Transform3D, TypedTransform3D};
 pub use point::{Point2D, Point3D, TypedPoint2D, TypedPoint3D, point2, point3};
 pub use vector::{TypedVector2D, TypedVector3D, Vector2D, Vector3D, vec2, vec3};
 pub use vector::{BoolVector2D, BoolVector3D, bvec2, bvec3};
 pub use homogen::HomogeneousVector;
@@ -118,9 +122,8 @@ pub type TypedMatrix4D<T, Src, Dst> = Ty
 
 /// Temporary alias to facilitate the transition to the new naming scheme
 #[deprecated]
 pub type ScaleFactor<T, Src, Dst> = TypedScale<T, Src, Dst>;
 
 /// Temporary alias to facilitate the transition to the new naming scheme
 #[deprecated]
 pub use Angle as Radians;
-
--- a/third_party/rust/euclid/src/macros.rs
+++ b/third_party/rust/euclid/src/macros.rs
@@ -13,17 +13,22 @@ macro_rules! define_matrix {
         pub struct $name:ident<T, $($phantom:ident),+> {
             $(pub $field:ident: T,)+
         }
     ) => (
         #[repr(C)]
         $(#[$attr])*
         pub struct $name<T, $($phantom),+> {
             $(pub $field: T,)+
-            _unit: PhantomData<($($phantom),+)>
+
+            // Keep this (secretly) public for the few cases where we would like to
+            // create static constants which currently can't be initialized with a
+            // function.
+            #[doc(hidden)]
+            pub _unit: PhantomData<($($phantom),+)>
         }
 
         impl<T: Clone, $($phantom),+> Clone for $name<T, $($phantom),+> {
             fn clone(&self) -> Self {
                 $name {
                     $($field: self.$field.clone(),)+
                     _unit: PhantomData,
                 }
@@ -54,28 +59,28 @@ macro_rules! define_matrix {
         {
             fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
                 where S: ::serde::Serializer
             {
                 ($(&self.$field,)+).serialize(serializer)
             }
         }
 
-        impl<T, $($phantom),+> ::std::cmp::Eq for $name<T, $($phantom),+>
-            where T: ::std::cmp::Eq {}
+        impl<T, $($phantom),+> ::core::cmp::Eq for $name<T, $($phantom),+>
+            where T: ::core::cmp::Eq {}
 
-        impl<T, $($phantom),+> ::std::cmp::PartialEq for $name<T, $($phantom),+>
-            where T: ::std::cmp::PartialEq
+        impl<T, $($phantom),+> ::core::cmp::PartialEq for $name<T, $($phantom),+>
+            where T: ::core::cmp::PartialEq
         {
             fn eq(&self, other: &Self) -> bool {
                 true $(&& self.$field == other.$field)+
             }
         }
 
-        impl<T, $($phantom),+> ::std::hash::Hash for $name<T, $($phantom),+>
-            where T: ::std::hash::Hash
+        impl<T, $($phantom),+> ::core::hash::Hash for $name<T, $($phantom),+>
+            where T: ::core::hash::Hash
         {
-            fn hash<H: ::std::hash::Hasher>(&self, h: &mut H) {
+            fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
                 $(self.$field.hash(h);)+
             }
         }
     )
 }
--- a/third_party/rust/euclid/src/point.rs
+++ b/third_party/rust/euclid/src/point.rs
@@ -10,19 +10,19 @@
 use super::UnknownUnit;
 use approxeq::ApproxEq;
 use length::Length;
 use scale::TypedScale;
 use size::TypedSize2D;
 use num::*;
 use num_traits::{Float, NumCast};
 use vector::{TypedVector2D, TypedVector3D, vec2, vec3};
-use std::fmt;
-use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
-use std::marker::PhantomData;
+use core::fmt;
+use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
+use core::marker::PhantomData;
 
 define_matrix! {
     /// A 2d Point tagged with a unit.
     pub struct TypedPoint2D<T, U> {
         pub x: T,
         pub y: T,
     }
 }
@@ -63,18 +63,18 @@ impl<T: fmt::Display, U> fmt::Display fo
     }
 }
 
 impl<T, U> TypedPoint2D<T, U> {
     /// Constructor taking scalar values directly.
     #[inline]
     pub fn new(x: T, y: T) -> Self {
         TypedPoint2D {
-            x: x,
-            y: y,
+            x,
+            y,
             _unit: PhantomData,
         }
     }
 }
 
 impl<T: Copy, U> TypedPoint2D<T, U> {
     /// Constructor taking properly typed Lengths instead of scalar values.
     #[inline]
@@ -281,75 +281,84 @@ impl<T: Floor, U> TypedPoint2D<T, U> {
 
 impl<T: NumCast + Copy, U> TypedPoint2D<T, U> {
     /// Cast from one numeric representation to another, preserving the units.
     ///
     /// When casting from floating point to integer coordinates, the decimals are truncated
     /// as one would expect from a simple cast, but this behavior does not always make sense
     /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
     #[inline]
-    pub fn cast<NewT: NumCast + Copy>(&self) -> Option<TypedPoint2D<NewT, U>> {
+    pub fn cast<NewT: NumCast + Copy>(&self) -> TypedPoint2D<NewT, U> {
+        self.try_cast().unwrap()
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    ///
+    /// When casting from floating point to integer coordinates, the decimals are truncated
+    /// as one would expect from a simple cast, but this behavior does not always make sense
+    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
+    pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<TypedPoint2D<NewT, U>> {
         match (NumCast::from(self.x), NumCast::from(self.y)) {
             (Some(x), Some(y)) => Some(point2(x, y)),
             _ => None,
         }
     }
 
     // Convenience functions for common casts
 
     /// Cast into an `f32` point.
     #[inline]
     pub fn to_f32(&self) -> TypedPoint2D<f32, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `f64` point.
     #[inline]
     pub fn to_f64(&self) -> TypedPoint2D<f64, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `usize` point, truncating decimals if any.
     ///
     /// When casting from floating point points, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     #[inline]
     pub fn to_usize(&self) -> TypedPoint2D<usize, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `u32` point, truncating decimals if any.
     ///
     /// When casting from floating point points, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     #[inline]
     pub fn to_u32(&self) -> TypedPoint2D<u32, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an i32 point, truncating decimals if any.
     ///
     /// When casting from floating point points, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     #[inline]
     pub fn to_i32(&self) -> TypedPoint2D<i32, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an i64 point, truncating decimals if any.
     ///
     /// When casting from floating point points, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     #[inline]
     pub fn to_i64(&self) -> TypedPoint2D<i64, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 }
 
 impl<T, U> TypedPoint2D<T, U>
 where
     T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
 {
     /// Linearly interpolate between this point and another point.
@@ -450,19 +459,19 @@ impl<T: fmt::Display, U> fmt::Display fo
     }
 }
 
 impl<T: Copy, U> TypedPoint3D<T, U> {
     /// Constructor taking scalar values directly.
     #[inline]
     pub fn new(x: T, y: T, z: T) -> Self {
         TypedPoint3D {
-            x: x,
-            y: y,
-            z: z,
+            x,
+            y,
+            z,
             _unit: PhantomData,
         }
     }
 
     /// Constructor taking properly typed Lengths instead of scalar values.
     #[inline]
     pub fn from_lengths(x: Length<T, U>, y: Length<T, U>, z: Length<T, U>) -> Self {
         point3(x.0, y.0, z.0)
@@ -645,79 +654,89 @@ impl<T: Floor, U> TypedPoint3D<T, U> {
 
 impl<T: NumCast + Copy, U> TypedPoint3D<T, U> {
     /// Cast from one numeric representation to another, preserving the units.
     ///
     /// When casting from floating point to integer coordinates, the decimals are truncated
     /// as one would expect from a simple cast, but this behavior does not always make sense
     /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
     #[inline]
-    pub fn cast<NewT: NumCast + Copy>(&self) -> Option<TypedPoint3D<NewT, U>> {
+    pub fn cast<NewT: NumCast + Copy>(&self) -> TypedPoint3D<NewT, U> {
+        self.try_cast().unwrap()
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    ///
+    /// When casting from floating point to integer coordinates, the decimals are truncated
+    /// as one would expect from a simple cast, but this behavior does not always make sense
+    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
+    #[inline]
+    pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<TypedPoint3D<NewT, U>> {
         match (
             NumCast::from(self.x),
             NumCast::from(self.y),
             NumCast::from(self.z),
         ) {
             (Some(x), Some(y), Some(z)) => Some(point3(x, y, z)),
             _ => None,
         }
     }
 
     // Convenience functions for common casts
 
     /// Cast into an `f32` point.
     #[inline]
     pub fn to_f32(&self) -> TypedPoint3D<f32, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `f64` point.
     #[inline]
     pub fn to_f64(&self) -> TypedPoint3D<f64, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `usize` point, truncating decimals if any.
     ///
     /// When casting from floating point points, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     #[inline]
     pub fn to_usize(&self) -> TypedPoint3D<usize, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `u32` point, truncating decimals if any.
     ///
     /// When casting from floating point points, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     #[inline]
     pub fn to_u32(&self) -> TypedPoint3D<u32, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `i32` point, truncating decimals if any.
     ///
     /// When casting from floating point points, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     #[inline]
     pub fn to_i32(&self) -> TypedPoint3D<i32, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `i64` point, truncating decimals if any.
     ///
     /// When casting from floating point points, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     #[inline]
     pub fn to_i64(&self) -> TypedPoint3D<i64, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 }
 
 impl<T: Copy + ApproxEq<T>, U> ApproxEq<TypedPoint3D<T, U>> for TypedPoint3D<T, U> {
     #[inline]
     fn approx_epsilon() -> Self {
         point3(
             T::approx_epsilon(),
--- a/third_party/rust/euclid/src/rect.rs
+++ b/third_party/rust/euclid/src/rect.rs
@@ -15,21 +15,21 @@ use point::TypedPoint2D;
 use vector::TypedVector2D;
 use side_offsets::TypedSideOffsets2D;
 use size::TypedSize2D;
 
 use num_traits::NumCast;
 #[cfg(feature = "serde")]
 use serde::{Deserialize, Deserializer, Serialize, Serializer};
 
-use std::borrow::Borrow;
-use std::cmp::PartialOrd;
-use std::fmt;
-use std::hash::{Hash, Hasher};
-use std::ops::{Add, Div, Mul, Sub};
+use core::borrow::Borrow;
+use core::cmp::PartialOrd;
+use core::fmt;
+use core::hash::{Hash, Hasher};
+use core::ops::{Add, Div, Mul, Sub};
 
 
 /// A 2d Rectangle optionally tagged with a unit.
 #[repr(C)]
 pub struct TypedRect<T, U = UnknownUnit> {
     pub origin: TypedPoint2D<T, U>,
     pub size: TypedSize2D<T, U>,
 }
@@ -92,18 +92,31 @@ impl<T: fmt::Display, U> fmt::Display fo
         write!(formatter, "Rect({} at {})", self.size, self.origin)
     }
 }
 
 impl<T, U> TypedRect<T, U> {
     /// Constructor.
     pub fn new(origin: TypedPoint2D<T, U>, size: TypedSize2D<T, U>) -> Self {
         TypedRect {
-            origin: origin,
-            size: size,
+            origin,
+            size,
+        }
+    }
+}
+
+impl<T, U> TypedRect<T, U>
+where
+    T: Copy + Zero
+{
+    /// Creates a rect of the given size, at offset zero.
+    pub fn from_size(size: TypedSize2D<T, U>) -> Self {
+        TypedRect {
+            origin: TypedPoint2D::zero(),
+            size,
         }
     }
 }
 
 impl<T, U> TypedRect<T, U>
 where
     T: Copy + Clone + Zero + PartialOrd + PartialEq + Add<T, Output = T> + Sub<T, Output = T>,
 {
@@ -452,18 +465,30 @@ impl<T: Copy, Unit> TypedRect<T, Unit> {
 }
 
 impl<T0: NumCast + Copy, Unit> TypedRect<T0, Unit> {
     /// Cast from one numeric representation to another, preserving the units.
     ///
     /// When casting from floating point to integer coordinates, the decimals are truncated
     /// as one would expect from a simple cast, but this behavior does not always make sense
     /// geometrically. Consider using round(), round_in or round_out() before casting.
-    pub fn cast<T1: NumCast + Copy>(&self) -> Option<TypedRect<T1, Unit>> {
-        match (self.origin.cast(), self.size.cast()) {
+    pub fn cast<T1: NumCast + Copy>(&self) -> TypedRect<T1, Unit> {
+        TypedRect::new(
+            self.origin.cast(),
+            self.size.cast(),
+        )
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    ///
+    /// When casting from floating point to integer coordinates, the decimals are truncated
+    /// as one would expect from a simple cast, but this behavior does not always make sense
+    /// geometrically. Consider using round(), round_in or round_out() before casting.
+    pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<TypedRect<T1, Unit>> {
+        match (self.origin.try_cast(), self.size.try_cast()) {
             (Some(origin), Some(size)) => Some(TypedRect::new(origin, size)),
             _ => None,
         }
     }
 }
 
 impl<T: Floor + Ceil + Round + Add<T, Output = T> + Sub<T, Output = T>, U> TypedRect<T, U> {
     /// Return a rectangle with edges rounded to integer coordinates, such that
@@ -500,58 +525,66 @@ impl<T: Floor + Ceil + Round + Add<T, Ou
         TypedRect::new(origin, TypedSize2D::new(size.x, size.y))
     }
 }
 
 // Convenience functions for common casts
 impl<T: NumCast + Copy, Unit> TypedRect<T, Unit> {
     /// Cast into an `f32` rectangle.
     pub fn to_f32(&self) -> TypedRect<f32, Unit> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `f64` rectangle.
     pub fn to_f64(&self) -> TypedRect<f64, Unit> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `usize` rectangle, truncating decimals if any.
     ///
     /// When casting from floating point rectangles, it is worth considering whether
     /// to `round()`, `round_in()` or `round_out()` before the cast in order to
     /// obtain the desired conversion behavior.
     pub fn to_usize(&self) -> TypedRect<usize, Unit> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `u32` rectangle, truncating decimals if any.
     ///
     /// When casting from floating point rectangles, it is worth considering whether
     /// to `round()`, `round_in()` or `round_out()` before the cast in order to
     /// obtain the desired conversion behavior.
     pub fn to_u32(&self) -> TypedRect<u32, Unit> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `i32` rectangle, truncating decimals if any.
     ///
     /// When casting from floating point rectangles, it is worth considering whether
     /// to `round()`, `round_in()` or `round_out()` before the cast in order to
     /// obtain the desired conversion behavior.
     pub fn to_i32(&self) -> TypedRect<i32, Unit> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `i64` rectangle, truncating decimals if any.
     ///
     /// When casting from floating point rectangles, it is worth considering whether
     /// to `round()`, `round_in()` or `round_out()` before the cast in order to
     /// obtain the desired conversion behavior.
     pub fn to_i64(&self) -> TypedRect<i64, Unit> {
-        self.cast().unwrap()
+        self.cast()
+    }
+}
+
+impl<T, U> From<TypedSize2D<T, U>> for TypedRect<T, U>
+where T: Copy + Zero
+{
+    fn from(size: TypedSize2D<T, U>) -> Self {
+        Self::from_size(size)
     }
 }
 
 /// Shorthand for `TypedRect::new(TypedPoint2D::new(x, y), TypedSize2D::new(w, h))`.
 pub fn rect<T: Copy, U>(x: T, y: T, w: T, h: T) -> TypedRect<T, U> {
     TypedRect::new(TypedPoint2D::new(x, y), TypedSize2D::new(w, h))
 }
 
--- a/third_party/rust/euclid/src/rotation.rs
+++ b/third_party/rust/euclid/src/rotation.rs
@@ -4,19 +4,19 @@
 // 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.
 
 use approxeq::ApproxEq;
 use num_traits::{Float, FloatConst, One, Zero};
-use std::fmt;
-use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, SubAssign};
-use std::marker::PhantomData;
+use core::fmt;
+use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, SubAssign};
+use core::marker::PhantomData;
 use trig::Trig;
 use {TypedPoint2D, TypedPoint3D, TypedVector2D, TypedVector3D, Vector3D, point2, point3, vec3};
 use {TypedTransform2D, TypedTransform3D, UnknownUnit};
 
 /// An angle in radians
 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Hash)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 pub struct Angle<T> {
@@ -735,17 +735,17 @@ where
             || (self.i.approx_eq_eps(&-other.i, eps) && self.j.approx_eq_eps(&-other.j, eps)
                 && self.k.approx_eq_eps(&-other.k, eps)
                 && self.r.approx_eq_eps(&-other.r, eps))
     }
 }
 
 #[test]
 fn simple_rotation_2d() {
-    use std::f32::consts::{FRAC_PI_2, PI};
+    use core::f32::consts::{FRAC_PI_2, PI};
     let ri = Rotation2D::identity();
     let r90 = Rotation2D::radians(FRAC_PI_2);
     let rm90 = Rotation2D::radians(-FRAC_PI_2);
     let r180 = Rotation2D::radians(PI);
 
     assert!(
         ri.transform_point(&point2(1.0, 2.0))
             .approx_eq(&point2(1.0, 2.0))
@@ -768,17 +768,17 @@ fn simple_rotation_2d() {
             .inverse()
             .transform_point(&point2(1.0, 2.0))
             .approx_eq(&r90.transform_point(&point2(1.0, 2.0)))
     );
 }
 
 #[test]
 fn simple_rotation_3d_in_2d() {
-    use std::f32::consts::{FRAC_PI_2, PI};
+    use core::f32::consts::{FRAC_PI_2, PI};
     let ri = Rotation3D::identity();
     let r90 = Rotation3D::around_z(Angle::radians(FRAC_PI_2));
     let rm90 = Rotation3D::around_z(Angle::radians(-FRAC_PI_2));
     let r180 = Rotation3D::around_z(Angle::radians(PI));
 
     assert!(
         ri.rotate_point2d(&point2(1.0, 2.0))
             .approx_eq(&point2(1.0, 2.0))
@@ -801,42 +801,42 @@ fn simple_rotation_3d_in_2d() {
             .inverse()
             .rotate_point2d(&point2(1.0, 2.0))
             .approx_eq(&r90.rotate_point2d(&point2(1.0, 2.0)))
     );
 }
 
 #[test]
 fn pre_post() {
-    use std::f32::consts::FRAC_PI_2;
+    use core::f32::consts::FRAC_PI_2;
     let r1 = Rotation3D::around_x(Angle::radians(FRAC_PI_2));
     let r2 = Rotation3D::around_y(Angle::radians(FRAC_PI_2));
     let r3 = Rotation3D::around_z(Angle::radians(FRAC_PI_2));
 
     let t1 = r1.to_transform();
     let t2 = r2.to_transform();
     let t3 = r3.to_transform();
 
     let p = point3(1.0, 2.0, 3.0);
 
     // Check that the order of transformations is correct (corresponds to what
     // we do in Transform3D).
     let p1 = r1.post_rotate(&r2).post_rotate(&r3).rotate_point3d(&p);
     let p2 = t1.post_mul(&t2).post_mul(&t3).transform_point3d(&p);
 
-    assert!(p1.approx_eq(&p2));
+    assert!(p1.approx_eq(&p2.unwrap()));
 
     // Check that changing the order indeed matters.
     let p3 = t3.post_mul(&t1).post_mul(&t2).transform_point3d(&p);
-    assert!(!p1.approx_eq(&p3));
+    assert!(!p1.approx_eq(&p3.unwrap()));
 }
 
 #[test]
 fn to_transform3d() {
-    use std::f32::consts::{FRAC_PI_2, PI};
+    use core::f32::consts::{FRAC_PI_2, PI};
     let rotations = [
         Rotation3D::identity(),
         Rotation3D::around_x(Angle::radians(FRAC_PI_2)),
         Rotation3D::around_x(Angle::radians(-FRAC_PI_2)),
         Rotation3D::around_x(Angle::radians(PI)),
         Rotation3D::around_y(Angle::radians(FRAC_PI_2)),
         Rotation3D::around_y(Angle::radians(-FRAC_PI_2)),
         Rotation3D::around_y(Angle::radians(PI)),
@@ -851,17 +851,17 @@ fn to_transform3d() {
         point3(-5.0, 3.0, -1.0),
         point3(-0.5, -1.0, 1.5),
     ];
 
     for rotation in &rotations {
         for point in &points {
             let p1 = rotation.rotate_point3d(point);
             let p2 = rotation.to_transform().transform_point3d(point);
-            assert!(p1.approx_eq(&p2));
+            assert!(p1.approx_eq(&p2.unwrap()));
         }
     }
 }
 
 #[test]
 fn slerp() {
     let q1 = Rotation3D::quaternion(1.0, 0.0, 0.0, 0.0);
     let q2 = Rotation3D::quaternion(0.0, 1.0, 0.0, 0.0);
@@ -926,17 +926,17 @@ fn slerp() {
         -0.951056516295154,
         0.0
     )));
     assert!(q1.slerp(&q3, 1.0).approx_eq(&q3));
 }
 
 #[test]
 fn around_axis() {
-    use std::f32::consts::{FRAC_PI_2, PI};
+    use core::f32::consts::{FRAC_PI_2, PI};
 
     // Two sort of trivial cases:
     let r1 = Rotation3D::around_axis(vec3(1.0, 1.0, 0.0), Angle::radians(PI));
     let r2 = Rotation3D::around_axis(vec3(1.0, 1.0, 0.0), Angle::radians(FRAC_PI_2));
     assert!(
         r1.rotate_point3d(&point3(1.0, 2.0, 0.0))
             .approx_eq(&point3(2.0, 1.0, 0.0))
     );
@@ -951,17 +951,17 @@ fn around_axis() {
         -0.58071821,
         0.81401868,
         -0.01182979
     )));
 }
 
 #[test]
 fn from_euler() {
-    use std::f32::consts::FRAC_PI_2;
+    use core::f32::consts::FRAC_PI_2;
 
     // First test simple separate yaw pitch and roll rotations, because it is easy to come
     // up with the corresponding quaternion.
     // Since several quaternions can represent the same transformation we compare the result
     // of transforming a point rather than the values of each quaternions.
     let p = point3(1.0, 2.0, 3.0);
 
     let angle = Angle::radians(FRAC_PI_2);
@@ -996,17 +996,17 @@ fn from_euler() {
     let ypr_pe = ypr_e.rotate_point3d(&p);
     let ypr_pq = ypr_q.rotate_point3d(&p);
 
     assert!(ypr_pe.approx_eq(&ypr_pq));
 }
 
 #[test]
 fn wrap_angles() {
-    use std::f32::consts::{FRAC_PI_2, PI};
+    use core::f32::consts::{FRAC_PI_2, PI};
     assert!(Angle::radians(0.0).positive().radians.approx_eq(&0.0));
     assert!(
         Angle::radians(FRAC_PI_2)
             .positive()
             .radians
             .approx_eq(&FRAC_PI_2)
     );
     assert!(
--- a/third_party/rust/euclid/src/scale.rs
+++ b/third_party/rust/euclid/src/scale.rs
@@ -8,19 +8,19 @@
 // except according to those terms.
 //! A type-checked scaling factor between units.
 
 use num::One;
 
 use num_traits::NumCast;
 #[cfg(feature = "serde")]
 use serde::{Deserialize, Deserializer, Serialize, Serializer};
-use std::fmt;
-use std::ops::{Add, Div, Mul, Neg, Sub};
-use std::marker::PhantomData;
+use core::fmt;
+use core::ops::{Add, Div, Mul, Neg, Sub};
+use core::marker::PhantomData;
 use {TypedPoint2D, TypedRect, TypedSize2D, TypedVector2D};
 
 /// A scaling factor between two different units of measurement.
 ///
 /// This is effectively a type-safe float, intended to be used in combination with other types like
 /// `length::Length` to enforce conversion between systems of measurement at compile time.
 ///
 /// `Src` and `Dst` represent the units before and after multiplying a value by a `TypedScale`. They
@@ -33,17 +33,17 @@ use {TypedPoint2D, TypedRect, TypedSize2
 /// enum Inch {};
 ///
 /// let mm_per_inch: TypedScale<f32, Inch, Mm> = TypedScale::new(25.4);
 ///
 /// let one_foot: Length<f32, Inch> = Length::new(12.0);
 /// let one_foot_in_mm: Length<f32, Mm> = one_foot * mm_per_inch;
 /// ```
 #[repr(C)]
-pub struct TypedScale<T, Src, Dst>(pub T, PhantomData<(Src, Dst)>);
+pub struct TypedScale<T, Src, Dst>(pub T, #[doc(hidden)] pub PhantomData<(Src, Dst)>);
 
 #[cfg(feature = "serde")]
 impl<'de, T, Src, Dst> Deserialize<'de> for TypedScale<T, Src, Dst>
 where
     T: Deserialize<'de>,
 {
     fn deserialize<D>(deserializer: D) -> Result<TypedScale<T, Src, Dst>, D::Error>
     where
@@ -118,17 +118,22 @@ impl<T: Clone + Sub<T, Output = T>, Src,
     #[inline]
     fn sub(self, other: TypedScale<T, Src, Dst>) -> TypedScale<T, Src, Dst> {
         TypedScale::new(self.get() - other.get())
     }
 }
 
 impl<T: NumCast + Clone, Src, Dst0> TypedScale<T, Src, Dst0> {
     /// Cast from one numeric representation to another, preserving the units.
-    pub fn cast<T1: NumCast + Clone>(&self) -> Option<TypedScale<T1, Src, Dst0>> {
+    pub fn cast<T1: NumCast + Clone>(&self) -> TypedScale<T1, Src, Dst0> {
+        self.try_cast().unwrap()
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    pub fn try_cast<T1: NumCast + Clone>(&self) -> Option<TypedScale<T1, Src, Dst0>> {
         NumCast::from(self.get()).map(TypedScale::new)
     }
 }
 
 impl<T, Src, Dst> TypedScale<T, Src, Dst>
 where
     T: Copy + Clone + Mul<T, Output = T> + Neg<Output = T> + PartialEq + One,
 {
--- a/third_party/rust/euclid/src/side_offsets.rs
+++ b/third_party/rust/euclid/src/side_offsets.rs
@@ -8,19 +8,19 @@
 // except according to those terms.
 
 //! A group of side offsets, which correspond to top/left/bottom/right for borders, padding,
 //! and margins in CSS.
 
 use super::UnknownUnit;
 use length::Length;
 use num::Zero;
-use std::fmt;
-use std::ops::Add;
-use std::marker::PhantomData;
+use core::fmt;
+use core::ops::Add;
+use core::marker::PhantomData;
 
 /// A group of side offsets, which correspond to top/left/bottom/right for borders, padding,
 /// and margins in CSS, optionally tagged with a unit.
 define_matrix! {
     pub struct TypedSideOffsets2D<T, U> {
         pub top: T,
         pub right: T,
         pub bottom: T,
@@ -40,20 +40,20 @@ impl<T: fmt::Debug, U> fmt::Debug for Ty
 
 /// The default side offset type with no unit.
 pub type SideOffsets2D<T> = TypedSideOffsets2D<T, UnknownUnit>;
 
 impl<T: Copy, U> TypedSideOffsets2D<T, U> {
     /// Constructor taking a scalar for each side.
     pub fn new(top: T, right: T, bottom: T, left: T) -> Self {
         TypedSideOffsets2D {
-            top: top,
-            right: right,
-            bottom: bottom,
-            left: left,
+            top,
+            right,
+            bottom,
+            left,
             _unit: PhantomData,
         }
     }
 
     /// Constructor taking a typed Length for each side.
     pub fn from_lengths(
         top: Length<T, U>,
         right: Length<T, U>,
--- a/third_party/rust/euclid/src/size.rs
+++ b/third_party/rust/euclid/src/size.rs
@@ -9,19 +9,19 @@
 
 use super::UnknownUnit;
 use length::Length;
 use scale::TypedScale;
 use vector::{TypedVector2D, vec2, BoolVector2D};
 use num::*;
 
 use num_traits::{NumCast, Signed};
-use std::fmt;
-use std::ops::{Add, Div, Mul, Sub};
-use std::marker::PhantomData;
+use core::fmt;
+use core::ops::{Add, Div, Mul, Sub};
+use core::marker::PhantomData;
 
 /// A 2d size tagged with a unit.
 define_matrix! {
     pub struct TypedSize2D<T, U> {
         pub width: T,
         pub height: T,
     }
 }
@@ -42,18 +42,18 @@ impl<T: fmt::Display, U> fmt::Display fo
         write!(formatter, "({}x{})", self.width, self.height)
     }
 }
 
 impl<T, U> TypedSize2D<T, U> {
     /// Constructor taking scalar values.
     pub fn new(width: T, height: T) -> Self {
         TypedSize2D {
-            width: width,
-            height: height,
+            width,
+            height,
             _unit: PhantomData,
         }
     }
 }
 
 impl<T: Clone, U> TypedSize2D<T, U> {
     /// Constructor taking scalar strongly typed lengths.
     pub fn from_lengths(width: Length<T, U>, height: Length<T, U>) -> Self {
@@ -211,69 +211,78 @@ impl<T: Copy, U> TypedSize2D<T, U> {
 }
 
 impl<T: NumCast + Copy, Unit> TypedSize2D<T, Unit> {
     /// Cast from one numeric representation to another, preserving the units.
     ///
     /// When casting from floating point to integer coordinates, the decimals are truncated
     /// as one would expect from a simple cast, but this behavior does not always make sense
     /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
-    pub fn cast<NewT: NumCast + Copy>(&self) -> Option<TypedSize2D<NewT, Unit>> {
+    pub fn cast<NewT: NumCast + Copy>(&self) -> TypedSize2D<NewT, Unit> {
+        self.try_cast().unwrap()
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    ///
+    /// When casting from floating point to integer coordinates, the decimals are truncated
+    /// as one would expect from a simple cast, but this behavior does not always make sense
+    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
+    pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<TypedSize2D<NewT, Unit>> {
         match (NumCast::from(self.width), NumCast::from(self.height)) {
             (Some(w), Some(h)) => Some(TypedSize2D::new(w, h)),
             _ => None,
         }
     }
 
     // Convenience functions for common casts
 
     /// Cast into an `f32` size.
     pub fn to_f32(&self) -> TypedSize2D<f32, Unit> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `f64` size.
     pub fn to_f64(&self) -> TypedSize2D<f64, Unit> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `uint` size, truncating decimals if any.
     ///
     /// When casting from floating point sizes, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     pub fn to_usize(&self) -> TypedSize2D<usize, Unit> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `u32` size, truncating decimals if any.
     ///
     /// When casting from floating point sizes, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     pub fn to_u32(&self) -> TypedSize2D<u32, Unit> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `i32` size, truncating decimals if any.
     ///
     /// When casting from floating point sizes, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     pub fn to_i32(&self) -> TypedSize2D<i32, Unit> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `i64` size, truncating decimals if any.
     ///
     /// When casting from floating point sizes, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     pub fn to_i64(&self) -> TypedSize2D<i64, Unit> {
-        self.cast().unwrap()
+        self.cast()
     }
 }
 
 impl<T, U> TypedSize2D<T, U>
 where
     T: Signed,
 {
     pub fn abs(&self) -> Self {
--- a/third_party/rust/euclid/src/transform2d.rs
+++ b/third_party/rust/euclid/src/transform2d.rs
@@ -2,27 +2,29 @@
 // file at the top-level directory of this distribution.
 //
 // 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.
 
+#![cfg_attr(feature = "cargo-clippy", allow(just_underscores_and_digits))]
+
 use super::{UnknownUnit, Angle};
 use num::{One, Zero};
 use point::TypedPoint2D;
 use vector::{TypedVector2D, vec2};
 use rect::TypedRect;
 use transform3d::TypedTransform3D;
-use std::ops::{Add, Mul, Div, Sub, Neg};
-use std::marker::PhantomData;
+use core::ops::{Add, Mul, Div, Sub, Neg};
+use core::marker::PhantomData;
 use approxeq::ApproxEq;
 use trig::Trig;
-use std::fmt;
+use core::fmt;
 use num_traits::NumCast;
 
 define_matrix! {
     /// A 2d transform stored as a 3 by 2 matrix in row-major order in memory.
     ///
     /// Transforms can be parametrized over the source and destination units, to describe a
     /// transformation from a space to another.
     /// For example, `TypedTransform2D<f32, WorldSpace, ScreenSpace>::transform_point4d`
@@ -41,29 +43,29 @@ define_matrix! {
 
 /// The default 2d transform type with no units.
 pub type Transform2D<T> = TypedTransform2D<T, UnknownUnit, UnknownUnit>;
 
 impl<T: Copy, Src, Dst> TypedTransform2D<T, Src, Dst> {
     /// Create a transform specifying its matrix elements in row-major order.
     pub fn row_major(m11: T, m12: T, m21: T, m22: T, m31: T, m32: T) -> Self {
         TypedTransform2D {
-            m11: m11, m12: m12,
-            m21: m21, m22: m22,
-            m31: m31, m32: m32,
+            m11, m12,
+            m21, m22,
+            m31, m32,
             _unit: PhantomData,
         }
     }
 
     /// Create a transform specifying its matrix elements in column-major order.
     pub fn column_major(m11: T, m21: T, m31: T, m12: T, m22: T, m32: T) -> Self {
         TypedTransform2D {
-            m11: m11, m12: m12,
-            m21: m21, m22: m22,
-            m31: m31, m32: m32,
+            m11, m12,
+            m21, m22,
+            m31, m32,
             _unit: PhantomData,
         }
     }
 
     /// Returns an array containing this transform's terms in row-major order (the order
     /// in which the transform is actually laid out in memory).
     pub fn to_row_major_array(&self) -> [T; 6] {
         [
@@ -127,26 +129,33 @@ impl<T: Copy, Src, Dst> TypedTransform2D
             p.m21, p.m22,
             p.m31, p.m32
         )
     }
 }
 
 impl<T0: NumCast + Copy, Src, Dst> TypedTransform2D<T0, Src, Dst> {
     /// Cast from one numeric representation to another, preserving the units.
-    pub fn cast<T1: NumCast + Copy>(&self) -> Option<TypedTransform2D<T1, Src, Dst>> {
+    pub fn cast<T1: NumCast + Copy>(&self) -> TypedTransform2D<T1, Src, Dst> {
+        self.try_cast().unwrap()
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<TypedTransform2D<T1, Src, Dst>> {
         match (NumCast::from(self.m11), NumCast::from(self.m12),
                NumCast::from(self.m21), NumCast::from(self.m22),
                NumCast::from(self.m31), NumCast::from(self.m32)) {
             (Some(m11), Some(m12),
              Some(m21), Some(m22),
              Some(m31), Some(m32)) => {
-                Some(TypedTransform2D::row_major(m11, m12,
-                                                 m21, m22,
-                                                 m31, m32))
+                Some(TypedTransform2D::row_major(
+                    m11, m12,
+                    m21, m22,
+                    m31, m32
+                ))
             },
             _ => None
         }
     }
 }
 
 impl<T, Src, Dst> TypedTransform2D<T, Src, Dst>
 where T: Copy +
@@ -342,17 +351,17 @@ where T: Copy + Clone +
     /// Returns the same transform with a different source unit.
     #[inline]
     pub fn with_source<NewSrc>(&self) -> TypedTransform2D<T, NewSrc, Dst> {
         TypedTransform2D::row_major(
             self.m11, self.m12,
             self.m21, self.m22,
             self.m31, self.m32,
         )
-    }   
+    }
 }
 
 impl <T, Src, Dst> TypedTransform2D<T, Src, Dst>
 where T: Copy + Clone +
          Add<T, Output=T> +
          Sub<T, Output=T> +
          Mul<T, Output=T> +
          Div<T, Output=T> +
@@ -362,16 +371,24 @@ where T: Copy + Clone +
          One + Zero {
     /// Create a 3D transform from the current transform
     pub fn to_3d(&self) -> TypedTransform3D<T, Src, Dst> {
         TypedTransform3D::row_major_2d(self.m11, self.m12, self.m21, self.m22, self.m31, self.m32)
     }
 
 }
 
+impl <T, Src, Dst> Default for TypedTransform2D<T, Src, Dst>
+    where T: Copy + PartialEq + One + Zero
+{
+    fn default() -> Self {
+        Self::identity()
+    }
+}
+
 impl<T: ApproxEq<T>, Src, Dst> TypedTransform2D<T, Src, Dst> {
     pub fn approx_eq(&self, other: &Self) -> bool {
         self.m11.approx_eq(&other.m11) && self.m12.approx_eq(&other.m12) &&
         self.m21.approx_eq(&other.m21) && self.m22.approx_eq(&other.m22) &&
         self.m31.approx_eq(&other.m31) && self.m32.approx_eq(&other.m32)
     }
 }
 
@@ -390,17 +407,17 @@ where T: Copy + fmt::Debug +
 
 #[cfg(test)]
 mod test {
     use super::*;
     use approxeq::ApproxEq;
     use point::Point2D;
     use Angle;
 
-    use std::f32::consts::FRAC_PI_2;
+    use core::f32::consts::FRAC_PI_2;
 
     type Mat = Transform2D<f32>;
 
     fn rad(v: f32) -> Angle<f32> { Angle::radians(v) }
 
     #[test]
     pub fn test_translation() {
         let t1 = Mat::create_translation(1.0, 2.0);
@@ -497,17 +514,17 @@ mod test {
 
         assert!(r.pre_mul(&t).transform_point(&a).approx_eq(&Point2D::new(4.0, -3.0)));
         assert!(t.pre_mul(&r).transform_point(&a).approx_eq(&Point2D::new(3.0, 2.0)));
         assert!(t.pre_mul(&r).transform_point(&a).approx_eq(&t.transform_point(&r.transform_point(&a))));
     }
 
     #[test]
     fn test_size_of() {
-        use std::mem::size_of;
+        use core::mem::size_of;
         assert_eq!(size_of::<Transform2D<f32>>(), 6*size_of::<f32>());
         assert_eq!(size_of::<Transform2D<f64>>(), 6*size_of::<f64>());
     }
 
     #[test]
     pub fn test_is_identity() {
         let m1 = Transform2D::identity();
         assert!(m1.is_identity());
--- a/third_party/rust/euclid/src/transform3d.rs
+++ b/third_party/rust/euclid/src/transform3d.rs
@@ -2,29 +2,31 @@
 // file at the top-level directory of this distribution.
 //
 // 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.
 
+#![cfg_attr(feature = "cargo-clippy", allow(just_underscores_and_digits))]
+
 use super::{UnknownUnit, Angle};
 use approxeq::ApproxEq;
 use homogen::HomogeneousVector;
 use trig::Trig;
 use point::{TypedPoint2D, TypedPoint3D};
 use vector::{TypedVector2D, TypedVector3D, vec2, vec3};
 use rect::TypedRect;
 use transform2d::TypedTransform2D;
 use scale::TypedScale;
 use num::{One, Zero};
-use std::ops::{Add, Mul, Sub, Div, Neg};
-use std::marker::PhantomData;
-use std::fmt;
+use core::ops::{Add, Mul, Sub, Div, Neg};
+use core::marker::PhantomData;
+use core::fmt;
 use num_traits::NumCast;
 
 define_matrix! {
     /// A 3d transform stored as a 4 by 4 matrix in row-major order in memory.
     ///
     /// Transforms can be parametrized over the source and destination units, to describe a
     /// transformation from a space to another.
     /// For example, `TypedTransform3D<f32, WorldSpace, ScreenSpace>::transform_point3d`
@@ -46,47 +48,49 @@ define_matrix! {
 pub type Transform3D<T> = TypedTransform3D<T, UnknownUnit, UnknownUnit>;
 
 impl<T, Src, Dst> TypedTransform3D<T, Src, Dst> {
     /// Create a transform specifying its components in row-major order.
     ///
     /// For example, the translation terms m41, m42, m43 on the last row with the
     /// row-major convention) are the 13rd, 14th and 15th parameters.
     #[inline]
+    #[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
     pub fn row_major(
             m11: T, m12: T, m13: T, m14: T,
             m21: T, m22: T, m23: T, m24: T,
             m31: T, m32: T, m33: T, m34: T,
             m41: T, m42: T, m43: T, m44: T)
          -> Self {
         TypedTransform3D {
-            m11: m11, m12: m12, m13: m13, m14: m14,
-            m21: m21, m22: m22, m23: m23, m24: m24,
-            m31: m31, m32: m32, m33: m33, m34: m34,
-            m41: m41, m42: m42, m43: m43, m44: m44,
+            m11, m12, m13, m14,
+            m21, m22, m23, m24,
+            m31, m32, m33, m34,
+            m41, m42, m43, m44,
             _unit: PhantomData,
         }
     }
 
     /// Create a transform specifying its components in column-major order.
     ///
     /// For example, the translation terms m41, m42, m43 on the last column with the
     /// column-major convention) are the 4th, 8th and 12nd parameters.
     #[inline]
+    #[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
     pub fn column_major(
             m11: T, m21: T, m31: T, m41: T,
             m12: T, m22: T, m32: T, m42: T,
             m13: T, m23: T, m33: T, m43: T,
             m14: T, m24: T, m34: T, m44: T)
          -> Self {
         TypedTransform3D {
-            m11: m11, m12: m12, m13: m13, m14: m14,
-            m21: m21, m22: m22, m23: m23, m24: m24,
-            m31: m31, m32: m32, m33: m33, m34: m34,
-            m41: m41, m42: m42, m43: m43, m44: m44,
+            m11, m12, m13, m14,
+            m21, m22, m23, m24,
+            m31, m32, m33, m34,
+            m41, m42, m43, m44,
             _unit: PhantomData,
         }
     }
 }
 
 impl <T, Src, Dst> TypedTransform3D<T, Src, Dst>
 where T: Copy + Clone +
          PartialEq +
@@ -409,29 +413,33 @@ where T: Copy + Clone +
         let x = p.x * self.m11 + p.y * self.m21 + self.m41;
         let y = p.x * self.m12 + p.y * self.m22 + self.m42;
         let z = p.x * self.m13 + p.y * self.m23 + self.m43;
         let w = p.x * self.m14 + p.y * self.m24 + self.m44;
 
         HomogeneousVector::new(x, y, z, w)
     }
 
-    /// Returns the given 2d point transformed by this transform.
+    /// Returns the given 2d point transformed by this transform, if the transform makes sense,
+    /// or `None` otherwise.
     ///
     /// The input point must be use the unit Src, and the returned point has the unit Dst.
+    ///
     #[inline]
-    pub fn transform_point2d(&self, p: &TypedPoint2D<T, Src>) -> TypedPoint2D<T, Dst> {
+    pub fn transform_point2d(&self, p: &TypedPoint2D<T, Src>) -> Option<TypedPoint2D<T, Dst>> {
         //Note: could use `transform_point2d_homogeneous()` but it would waste the calculus of `z`
+        let w = p.x * self.m14 + p.y * self.m24 + self.m44;
+        if w > T::zero() {
+            let x = p.x * self.m11 + p.y * self.m21 + self.m41;
+            let y = p.x * self.m12 + p.y * self.m22 + self.m42;
 
-        let x = p.x * self.m11 + p.y * self.m21 + self.m41;
-        let y = p.x * self.m12 + p.y * self.m22 + self.m42;
-        let w = p.x * self.m14 + p.y * self.m24 + self.m44;
-
-
-        TypedPoint2D::new(x / w, y / w)
+            Some(TypedPoint2D::new(x / w, y / w))
+        } else {
+            None
+        }
     }
 
     /// Returns the given 2d vector transformed by this matrix.
     ///
     /// The input point must be use the unit Src, and the returned point has the unit Dst.
     #[inline]
     pub fn transform_vector2d(&self, v: &TypedVector2D<T, Src>) -> TypedVector2D<T, Dst> {
         vec2(
@@ -450,45 +458,46 @@ where T: Copy + Clone +
         let x = p.x * self.m11 + p.y * self.m21 + p.z * self.m31 + self.m41;
         let y = p.x * self.m12 + p.y * self.m22 + p.z * self.m32 + self.m42;
         let z = p.x * self.m13 + p.y * self.m23 + p.z * self.m33 + self.m43;
         let w = p.x * self.m14 + p.y * self.m24 + p.z * self.m34 + self.m44;
 
         HomogeneousVector::new(x, y, z, w)
     }
 
-    /// Returns the given 3d point transformed by this transform.
+    /// Returns the given 3d point transformed by this transform, if the transform makes sense,
+    /// or `None` otherwise.
     ///
     /// The input point must be use the unit Src, and the returned point has the unit Dst.
     #[inline]
-    pub fn transform_point3d(&self, p: &TypedPoint3D<T, Src>) -> TypedPoint3D<T, Dst> {
+    pub fn transform_point3d(&self, p: &TypedPoint3D<T, Src>) -> Option<TypedPoint3D<T, Dst>> {
         self.transform_point3d_homogeneous(p).to_point3d()
     }
 
     /// Returns the given 3d vector transformed by this matrix.
     ///
     /// The input point must be use the unit Src, and the returned point has the unit Dst.
     #[inline]
     pub fn transform_vector3d(&self, v: &TypedVector3D<T, Src>) -> TypedVector3D<T, Dst> {
         vec3(
             v.x * self.m11 + v.y * self.m21 + v.z * self.m31,
             v.x * self.m12 + v.y * self.m22 + v.z * self.m32,
             v.x * self.m13 + v.y * self.m23 + v.z * self.m33,
         )
     }
 
     /// Returns a rectangle that encompasses the result of transforming the given rectangle by this
-    /// transform.
-    pub fn transform_rect(&self, rect: &TypedRect<T, Src>) -> TypedRect<T, Dst> {
-        TypedRect::from_points(&[
-            self.transform_point2d(&rect.origin),
-            self.transform_point2d(&rect.top_right()),
-            self.transform_point2d(&rect.bottom_left()),
-            self.transform_point2d(&rect.bottom_right()),
-        ])
+    /// transform, if the transform makes sense for it, or `None` otherwise.
+    pub fn transform_rect(&self, rect: &TypedRect<T, Src>) -> Option<TypedRect<T, Dst>> {
+        Some(TypedRect::from_points(&[
+            self.transform_point2d(&rect.origin)?,
+            self.transform_point2d(&rect.top_right())?,
+            self.transform_point2d(&rect.bottom_left())?,
+            self.transform_point2d(&rect.bottom_right())?,
+        ]))
     }
 
     /// Create a 3d translation transform
     pub fn create_translation(x: T, y: T, z: T) -> Self {
         let (_0, _1): (T, T) = (Zero::zero(), One::one());
         TypedTransform3D::row_major(
             _1, _0, _0, _0,
             _0, _1, _0, _0,
@@ -678,17 +687,22 @@ impl<T: Copy, Src, Dst> TypedTransform3D
             array[2][0], array[2][1], array[2][2], array[2][3],
             array[3][0], array[3][1], array[3][2], array[3][3],
         )
     }
 }
 
 impl<T0: NumCast + Copy, Src, Dst> TypedTransform3D<T0, Src, Dst> {
     /// Cast from one numeric representation to another, preserving the units.
-    pub fn cast<T1: NumCast + Copy>(&self) -> Option<TypedTransform3D<T1, Src, Dst>> {
+    pub fn cast<T1: NumCast + Copy>(&self) -> TypedTransform3D<T1, Src, Dst> {
+        self.try_cast().unwrap()
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<TypedTransform3D<T1, Src, Dst>> {
         match (NumCast::from(self.m11), NumCast::from(self.m12),
                NumCast::from(self.m13), NumCast::from(self.m14),
                NumCast::from(self.m21), NumCast::from(self.m22),
                NumCast::from(self.m23), NumCast::from(self.m24),
                NumCast::from(self.m31), NumCast::from(self.m32),
                NumCast::from(self.m33), NumCast::from(self.m34),
                NumCast::from(self.m41), NumCast::from(self.m42),
                NumCast::from(self.m43), NumCast::from(self.m44)) {
@@ -701,16 +715,24 @@ impl<T0: NumCast + Copy, Src, Dst> Typed
                                                  m31, m32, m33, m34,
                                                  m41, m42, m43, m44))
             },
             _ => None
         }
     }
 }
 
+impl <T, Src, Dst> Default for TypedTransform3D<T, Src, Dst>
+    where T: Copy + PartialEq + One + Zero
+{
+    fn default() -> Self {
+        Self::identity()
+    }
+}
+
 impl<T, Src, Dst> fmt::Debug for TypedTransform3D<T, Src, Dst>
 where T: Copy + fmt::Debug +
          PartialEq +
          One + Zero {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         if self.is_identity() {
             write!(f, "[I]")
         } else {
@@ -722,67 +744,67 @@ where T: Copy + fmt::Debug +
 #[cfg(test)]
 mod tests {
     use approxeq::ApproxEq;
     use transform2d::Transform2D;
     use point::{point2, point3};
     use Angle;
     use super::*;
 
-    use std::f32::consts::{FRAC_PI_2, PI};
+    use core::f32::consts::{FRAC_PI_2, PI};
 
     type Mf32 = Transform3D<f32>;
 
     // For convenience.
     fn rad(v: f32) -> Angle<f32> { Angle::radians(v) }
 
     #[test]
     pub fn test_translation() {
         let t1 = Mf32::create_translation(1.0, 2.0, 3.0);
         let t2 = Mf32::identity().pre_translate(vec3(1.0, 2.0, 3.0));
         let t3 = Mf32::identity().post_translate(vec3(1.0, 2.0, 3.0));
         assert_eq!(t1, t2);
         assert_eq!(t1, t3);
 
-        assert_eq!(t1.transform_point3d(&point3(1.0, 1.0, 1.0)), point3(2.0, 3.0, 4.0));
-        assert_eq!(t1.transform_point2d(&point2(1.0, 1.0)), point2(2.0, 3.0));
+        assert_eq!(t1.transform_point3d(&point3(1.0, 1.0, 1.0)), Some(point3(2.0, 3.0, 4.0)));
+        assert_eq!(t1.transform_point2d(&point2(1.0, 1.0)), Some(point2(2.0, 3.0)));
 
         assert_eq!(t1.post_mul(&t1), Mf32::create_translation(2.0, 4.0, 6.0));
 
         assert!(!t1.is_2d());
         assert_eq!(Mf32::create_translation(1.0, 2.0, 3.0).to_2d(), Transform2D::create_translation(1.0, 2.0));
     }
 
     #[test]
     pub fn test_rotation() {
         let r1 = Mf32::create_rotation(0.0, 0.0, 1.0, rad(FRAC_PI_2));
         let r2 = Mf32::identity().pre_rotate(0.0, 0.0, 1.0, rad(FRAC_PI_2));
         let r3 = Mf32::identity().post_rotate(0.0, 0.0, 1.0, rad(FRAC_PI_2));
         assert_eq!(r1, r2);
         assert_eq!(r1, r3);
 
-        assert!(r1.transform_point3d(&point3(1.0, 2.0, 3.0)).approx_eq(&point3(2.0, -1.0, 3.0)));
-        assert!(r1.transform_point2d(&point2(1.0, 2.0)).approx_eq(&point2(2.0, -1.0)));
+        assert!(r1.transform_point3d(&point3(1.0, 2.0, 3.0)).unwrap().approx_eq(&point3(2.0, -1.0, 3.0)));
+        assert!(r1.transform_point2d(&point2(1.0, 2.0)).unwrap().approx_eq(&point2(2.0, -1.0)));
 
         assert!(r1.post_mul(&r1).approx_eq(&Mf32::create_rotation(0.0, 0.0, 1.0, rad(FRAC_PI_2*2.0))));
 
         assert!(r1.is_2d());
         assert!(r1.to_2d().approx_eq(&Transform2D::create_rotation(rad(FRAC_PI_2))));
     }
 
     #[test]
     pub fn test_scale() {
         let s1 = Mf32::create_scale(2.0, 3.0, 4.0);
         let s2 = Mf32::identity().pre_scale(2.0, 3.0, 4.0);
         let s3 = Mf32::identity().post_scale(2.0, 3.0, 4.0);
         assert_eq!(s1, s2);
         assert_eq!(s1, s3);
 
-        assert!(s1.transform_point3d(&point3(2.0, 2.0, 2.0)).approx_eq(&point3(4.0, 6.0, 8.0)));
-        assert!(s1.transform_point2d(&point2(2.0, 2.0)).approx_eq(&point2(4.0, 6.0)));
+        assert!(s1.transform_point3d(&point3(2.0, 2.0, 2.0)).unwrap().approx_eq(&point3(4.0, 6.0, 8.0)));
+        assert!(s1.transform_point2d(&point2(2.0, 2.0)).unwrap().approx_eq(&point2(4.0, 6.0)));
 
         assert_eq!(s1.post_mul(&s1), Mf32::create_scale(4.0, 9.0, 16.0));
 
         assert!(!s1.is_2d());
         assert_eq!(Mf32::create_scale(2.0, 3.0, 0.0).to_2d(), Transform2D::create_scale(2.0, 3.0));
     }
 
     #[test]
@@ -867,20 +889,20 @@ mod tests {
     #[test]
     pub fn test_inverse_transform_point_2d() {
         let m1 = Mf32::create_translation(100.0, 200.0, 0.0);
         let m2 = m1.inverse().unwrap();
         assert!(m1.pre_mul(&m2).approx_eq(&Mf32::identity()));
 
         let p1 = point2(1000.0, 2000.0);
         let p2 = m1.transform_point2d(&p1);
-        assert!(p2.eq(&point2(1100.0, 2200.0)));
+        assert_eq!(p2, Some(point2(1100.0, 2200.0)));
 
-        let p3 = m2.transform_point2d(&p2);
-        assert!(p3.eq(&p1));
+        let p3 = m2.transform_point2d(&p2.unwrap());
+        assert_eq!(p3, Some(p1));
     }
 
     #[test]
     fn test_inverse_none() {
         assert!(Mf32::create_scale(2.0, 0.0, 2.0).inverse().is_none());
         assert!(Mf32::create_scale(2.0, 2.0, 2.0).inverse().is_some());
     }
 
@@ -890,46 +912,46 @@ mod tests {
         let m2 = Transform3D::identity().pre_translate(vec3(1.0, 2.0, 3.0)).pre_scale(1.0, 2.0, 3.0);
         assert!(m1.approx_eq(&m2));
 
         let r = Mf32::create_rotation(0.0, 0.0, 1.0, rad(FRAC_PI_2));
         let t = Mf32::create_translation(2.0, 3.0, 0.0);
 
         let a = point3(1.0, 1.0, 1.0);
 
-        assert!(r.post_mul(&t).transform_point3d(&a).approx_eq(&point3(3.0, 2.0, 1.0)));
-        assert!(t.post_mul(&r).transform_point3d(&a).approx_eq(&point3(4.0, -3.0, 1.0)));
-        assert!(t.post_mul(&r).transform_point3d(&a).approx_eq(&r.transform_point3d(&t.transform_point3d(&a))));
+        assert!(r.post_mul(&t).transform_point3d(&a).unwrap().approx_eq(&point3(3.0, 2.0, 1.0)));
+        assert!(t.post_mul(&r).transform_point3d(&a).unwrap().approx_eq(&point3(4.0, -3.0, 1.0)));
+        assert!(t.post_mul(&r).transform_point3d(&a).unwrap().approx_eq(&r.transform_point3d(&t.transform_point3d(&a).unwrap()).unwrap()));
 
-        assert!(r.pre_mul(&t).transform_point3d(&a).approx_eq(&point3(4.0, -3.0, 1.0)));
-        assert!(t.pre_mul(&r).transform_point3d(&a).approx_eq(&point3(3.0, 2.0, 1.0)));
-        assert!(t.pre_mul(&r).transform_point3d(&a).approx_eq(&t.transform_point3d(&r.transform_point3d(&a))));
+        assert!(r.pre_mul(&t).transform_point3d(&a).unwrap().approx_eq(&point3(4.0, -3.0, 1.0)));
+        assert!(t.pre_mul(&r).transform_point3d(&a).unwrap().approx_eq(&point3(3.0, 2.0, 1.0)));
+        assert!(t.pre_mul(&r).transform_point3d(&a).unwrap().approx_eq(&t.transform_point3d(&r.transform_point3d(&a).unwrap()).unwrap()));
     }
 
     #[test]
     fn test_size_of() {
-        use std::mem::size_of;
+        use core::mem::size_of;
         assert_eq!(size_of::<Transform3D<f32>>(), 16*size_of::<f32>());
         assert_eq!(size_of::<Transform3D<f64>>(), 16*size_of::<f64>());
     }
 
     #[test]
     pub fn test_transform_associativity() {
         let m1 = Mf32::row_major(3.0, 2.0, 1.5, 1.0,
                                  0.0, 4.5, -1.0, -4.0,
                                  0.0, 3.5, 2.5, 40.0,
                                  0.0, 3.0, 0.0, 1.0);
         let m2 = Mf32::row_major(1.0, -1.0, 3.0, 0.0,
                                  -1.0, 0.5, 0.0, 2.0,
                                  1.5, -2.0, 6.0, 0.0,
                                  -2.5, 6.0, 1.0, 1.0);
 
         let p = point3(1.0, 3.0, 5.0);
-        let p1 = m2.pre_mul(&m1).transform_point3d(&p);
-        let p2 = m2.transform_point3d(&m1.transform_point3d(&p));
+        let p1 = m2.pre_mul(&m1).transform_point3d(&p).unwrap();
+        let p2 = m2.transform_point3d(&m1.transform_point3d(&p).unwrap()).unwrap();
         assert!(p1.approx_eq(&p2));
     }
 
     #[test]
     pub fn test_is_identity() {
         let m1 = Transform3D::identity();
         assert!(m1.is_identity());
         let m2 = m1.post_translate(vec3(0.1, 0.0, 0.0));
@@ -938,22 +960,22 @@ mod tests {
 
     #[test]
     pub fn test_transform_vector() {
         // Translation does not apply to vectors.
         let m = Mf32::create_translation(1.0, 2.0, 3.0);
         let v1 = vec3(10.0, -10.0, 3.0);
         assert_eq!(v1, m.transform_vector3d(&v1));
         // While it does apply to points.
-        assert!(v1.to_point() != m.transform_point3d(&v1.to_point()));
+        assert_ne!(Some(v1.to_point()), m.transform_point3d(&v1.to_point()));
 
         // same thing with 2d vectors/points
         let v2 = vec2(10.0, -5.0);
         assert_eq!(v2, m.transform_vector2d(&v2));
-        assert!(v2.to_point() != m.transform_point2d(&v2.to_point()));
+        assert_ne!(Some(v2.to_point()), m.transform_point2d(&v2.to_point()));
     }
 
     #[test]
     pub fn test_is_backface_visible() {
         // backface is not visible for rotate-x 0 degree.
         let r1 = Mf32::create_rotation(1.0, 0.0, 0.0, rad(0.0));
         assert!(!r1.is_backface_visible());
         // backface is not visible for rotate-x 45 degree.
@@ -982,9 +1004,21 @@ mod tests {
             m.transform_point2d_homogeneous(&point2(1.0, 2.0)),
             HomogeneousVector::new(6.0, 11.0, 0.0, 19.0),
         );
         assert_eq!(
             m.transform_point3d_homogeneous(&point3(1.0, 2.0, 4.0)),
             HomogeneousVector::new(8.0, 7.0, 4.0, 15.0),
         );
     }
+
+    #[test]
+    pub fn test_perspective_division() {
+        let p = point2(1.0, 2.0);
+        let mut m = Mf32::identity();
+        assert!(m.transform_point2d(&p).is_some());
+        m.m44 = 0.0;
+        assert_eq!(None, m.transform_point2d(&p));
+        m.m44 = 1.0;
+        m.m24 = -1.0;
+        assert_eq!(None, m.transform_point2d(&p));
+    }
 }
--- a/third_party/rust/euclid/src/trig.rs
+++ b/third_party/rust/euclid/src/trig.rs
@@ -27,23 +27,27 @@ macro_rules! trig {
             #[inline]
             fn tan(self) -> $ty { self.tan() }
 
             /// A slightly faster approximation of `atan2`.
             ///
             /// Note that it does not deal with the case where both x and y are 0.
             #[inline]
             fn fast_atan2(y: $ty, x: $ty) -> $ty {
+                // This macro is used with f32 and f64 and clippy warns about the extra
+                // precision with f32.
+                #![cfg_attr(feature = "cargo-clippy", allow(excessive_precision))]
+
                 // See https://math.stackexchange.com/questions/1098487/atan2-faster-approximation#1105038
-                use std::$ty::consts;
+                use core::$ty::consts;
                 let x_abs = x.abs();
                 let y_abs = y.abs();
                 let a = x_abs.min(y_abs) / x_abs.max(y_abs);
                 let s = a * a;
-                let mut result = ((-0.0464964749 * s + 0.15931422) * s - 0.327622764) * s * a + a;
+                let mut result = ((-0.046_496_474_9 * s + 0.159_314_22) * s - 0.327_622_764) * s * a + a;
                 if y_abs > x_abs {
                     result = consts::FRAC_PI_2 - result;
                 }
                 if x < 0.0 {
                     result = consts::PI - result
                 }
                 if y < 0.0 {
                     result = -result
--- a/third_party/rust/euclid/src/vector.rs
+++ b/third_party/rust/euclid/src/vector.rs
@@ -12,19 +12,19 @@ use approxeq::ApproxEq;
 use length::Length;
 use point::{TypedPoint2D, TypedPoint3D, point2, point3};
 use size::{TypedSize2D, size2};
 use scale::TypedScale;
 use trig::Trig;
 use Angle;
 use num::*;
 use num_traits::{Float, NumCast, Signed};
-use std::fmt;
-use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
-use std::marker::PhantomData;
+use core::fmt;
+use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
+use core::marker::PhantomData;
 
 define_matrix! {
     /// A 2d Vector tagged with a unit.
     pub struct TypedVector2D<T, U> {
         pub x: T,
         pub y: T,
     }
 }
@@ -60,18 +60,18 @@ impl<T: fmt::Display, U> fmt::Display fo
     }
 }
 
 impl<T, U> TypedVector2D<T, U> {
     /// Constructor taking scalar values directly.
     #[inline]
     pub fn new(x: T, y: T) -> Self {
         TypedVector2D {
-            x: x,
-            y: y,
+            x,
+            y,
             _unit: PhantomData,
         }
     }
 }
 
 impl<T: Copy, U> TypedVector2D<T, U> {
     /// Constructor taking properly typed Lengths instead of scalar values.
     #[inline]
@@ -164,16 +164,31 @@ where
     #[inline]
     pub fn normalize(self) -> Self
     where
         T: Float,
     {
         self / self.length()
     }
 
+    /// Return the normalized vector even if the length is larger than the max value of Float.
+    #[inline]
+    pub fn robust_normalize(self) -> Self
+    where
+        T: Float,
+    {
+        let length = self.length();
+        if length.is_infinite() {
+            let scaled = self / T::max_value();
+            scaled / scaled.length()
+        } else {
+            self / length
+        }
+    }
+
     #[inline]
     pub fn square_length(&self) -> T {
         self.x * self.x + self.y * self.y
     }
 
     #[inline]
     pub fn length(&self) -> T
     where
@@ -330,75 +345,85 @@ impl<T: Floor, U> TypedVector2D<T, U> {
 
 impl<T: NumCast + Copy, U> TypedVector2D<T, U> {
     /// Cast from one numeric representation to another, preserving the units.
     ///
     /// When casting from floating vector to integer coordinates, the decimals are truncated
     /// as one would expect from a simple cast, but this behavior does not always make sense
     /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
     #[inline]
-    pub fn cast<NewT: NumCast + Copy>(&self) -> Option<TypedVector2D<NewT, U>> {
+    pub fn cast<NewT: NumCast + Copy>(&self) -> TypedVector2D<NewT, U> {
+        self.try_cast().unwrap()
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    ///
+    /// When casting from floating vector to integer coordinates, the decimals are truncated
+    /// as one would expect from a simple cast, but this behavior does not always make sense
+    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
+    #[inline]
+    pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<TypedVector2D<NewT, U>> {
         match (NumCast::from(self.x), NumCast::from(self.y)) {
             (Some(x), Some(y)) => Some(TypedVector2D::new(x, y)),
             _ => None,
         }
     }
 
     // Convenience functions for common casts
 
     /// Cast into an `f32` vector.
     #[inline]
     pub fn to_f32(&self) -> TypedVector2D<f32, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `f64` vector.
     #[inline]
     pub fn to_f64(&self) -> TypedVector2D<f64, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `usize` vector, truncating decimals if any.
     ///
     /// When casting from floating vector vectors, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     #[inline]
     pub fn to_usize(&self) -> TypedVector2D<usize, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `u32` vector, truncating decimals if any.
     ///
     /// When casting from floating vector vectors, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     #[inline]
     pub fn to_u32(&self) -> TypedVector2D<u32, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an i32 vector, truncating decimals if any.
     ///
     /// When casting from floating vector vectors, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     #[inline]
     pub fn to_i32(&self) -> TypedVector2D<i32, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an i64 vector, truncating decimals if any.
     ///
     /// When casting from floating vector vectors, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     #[inline]
     pub fn to_i64(&self) -> TypedVector2D<i64, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 }
 
 impl<T: Copy + ApproxEq<T>, U> ApproxEq<TypedVector2D<T, U>> for TypedVector2D<T, U> {
     #[inline]
     fn approx_epsilon() -> Self {
         vec2(T::approx_epsilon(), T::approx_epsilon())
     }
@@ -474,19 +499,19 @@ impl<T: fmt::Display, U> fmt::Display fo
     }
 }
 
 impl<T, U> TypedVector3D<T, U> {
     /// Constructor taking scalar values directly.
     #[inline]
     pub fn new(x: T, y: T, z: T) -> Self {
         TypedVector3D {
-            x: x,
-            y: y,
-            z: z,
+            x,
+            y,
+            z,
             _unit: PhantomData,
         }
     }
 }
 
 impl<T: Copy, U> TypedVector3D<T, U> {
     /// Constructor taking properly typed Lengths instead of scalar values.
     #[inline]
@@ -583,16 +608,31 @@ impl<T: Mul<T, Output = T> + Add<T, Outp
     #[inline]
     pub fn normalize(self) -> Self
     where
         T: Float,
     {
         self / self.length()
     }
 
+    /// Return the normalized vector even if the length is larger than the max value of Float.
+    #[inline]
+    pub fn robust_normalize(self) -> Self
+    where
+        T: Float,
+    {
+        let length = self.length();
+        if length.is_infinite() {
+            let scaled = self / T::max_value();
+            scaled / scaled.length()
+        } else {
+            self / length
+        }
+    }
+
     #[inline]
     pub fn square_length(&self) -> T {
         self.x * self.x + self.y * self.y + self.z * self.z
     }
 
     #[inline]
     pub fn length(&self) -> T
     where
@@ -755,79 +795,89 @@ impl<T: Floor, U> TypedVector3D<T, U> {
 
 impl<T: NumCast + Copy, U> TypedVector3D<T, U> {
     /// Cast from one numeric representation to another, preserving the units.
     ///
     /// When casting from floating vector to integer coordinates, the decimals are truncated
     /// as one would expect from a simple cast, but this behavior does not always make sense
     /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
     #[inline]
-    pub fn cast<NewT: NumCast + Copy>(&self) -> Option<TypedVector3D<NewT, U>> {
+    pub fn cast<NewT: NumCast + Copy>(&self) -> TypedVector3D<NewT, U> {
+        self.try_cast().unwrap()
+    }
+
+    /// Fallible cast from one numeric representation to another, preserving the units.
+    ///
+    /// When casting from floating vector to integer coordinates, the decimals are truncated
+    /// as one would expect from a simple cast, but this behavior does not always make sense
+    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
+    #[inline]
+    pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<TypedVector3D<NewT, U>> {
         match (
             NumCast::from(self.x),
             NumCast::from(self.y),
             NumCast::from(self.z),
         ) {
             (Some(x), Some(y), Some(z)) => Some(vec3(x, y, z)),
             _ => None,
         }
     }
 
     // Convenience functions for common casts
 
     /// Cast into an `f32` vector.
     #[inline]
     pub fn to_f32(&self) -> TypedVector3D<f32, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `f64` vector.
     #[inline]
     pub fn to_f64(&self) -> TypedVector3D<f64, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `usize` vector, truncating decimals if any.
     ///
     /// When casting from floating vector vectors, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     #[inline]
     pub fn to_usize(&self) -> TypedVector3D<usize, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `u32` vector, truncating decimals if any.
     ///
     /// When casting from floating vector vectors, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     #[inline]
     pub fn to_u32(&self) -> TypedVector3D<u32, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `i32` vector, truncating decimals if any.
     ///
     /// When casting from floating vector vectors, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     #[inline]
     pub fn to_i32(&self) -> TypedVector3D<i32, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 
     /// Cast into an `i64` vector, truncating decimals if any.
     ///
     /// When casting from floating vector vectors, it is worth considering whether
     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
     /// the desired conversion behavior.
     #[inline]
     pub fn to_i64(&self) -> TypedVector3D<i64, U> {
-        self.cast().unwrap()
+        self.cast()
     }
 }
 
 impl<T: Copy + ApproxEq<T>, U> ApproxEq<TypedVector3D<T, U>> for TypedVector3D<T, U> {
     #[inline]
     fn approx_epsilon() -> Self {
         vec3(
             T::approx_epsilon(),
@@ -1159,16 +1209,20 @@ mod vector2d {
     #[test]
     pub fn test_normalize() {
         let p0: Vec2 = Vec2::zero();
         let p1: Vec2 = vec2(4.0, 0.0);
         let p2: Vec2 = vec2(3.0, -4.0);
         assert!(p0.normalize().x.is_nan() && p0.normalize().y.is_nan());
         assert_eq!(p1.normalize(), vec2(1.0, 0.0));
         assert_eq!(p2.normalize(), vec2(0.6, -0.8));
+
+        let p3: Vec2 = vec2(::std::f32::MAX, ::std::f32::MAX);
+        assert_ne!(p3.normalize(), vec2(1.0 / 2.0f32.sqrt(), 1.0 / 2.0f32.sqrt()));
+        assert_eq!(p3.robust_normalize(), vec2(1.0 / 2.0f32.sqrt(), 1.0 / 2.0f32.sqrt()));
     }
 
     #[test]
     pub fn test_min() {
         let p1: Vec2 = vec2(1.0, 3.0);
         let p2: Vec2 = vec2(2.0, 2.0);
 
         let result = p1.min(p2);
@@ -1183,17 +1237,17 @@ mod vector2d {
 
         let result = p1.max(p2);
 
         assert_eq!(result, vec2(2.0, 3.0));
     }
 
     #[test]
     pub fn test_angle_from_x_axis() {
-        use std::f32::consts::FRAC_PI_2;
+        use core::f32::consts::FRAC_PI_2;
         use approxeq::ApproxEq;
 
         let right: Vec2 = vec2(10.0, 0.0);
         let down: Vec2 = vec2(0.0, 4.0);
         let up: Vec2 = vec2(0.0, -1.0);
 
         assert!(right.angle_from_x_axis().get().approx_eq(&0.0));
         assert!(down.angle_from_x_axis().get().approx_eq(&FRAC_PI_2));
@@ -1274,16 +1328,20 @@ mod vector3d {
         let p0: Vec3 = Vec3::zero();
         let p1: Vec3 = vec3(0.0, -6.0, 0.0);
         let p2: Vec3 = vec3(1.0, 2.0, -2.0);
         assert!(
             p0.normalize().x.is_nan() && p0.normalize().y.is_nan() && p0.normalize().z.is_nan()
         );
         assert_eq!(p1.normalize(), vec3(0.0, -1.0, 0.0));
         assert_eq!(p2.normalize(), vec3(1.0 / 3.0, 2.0 / 3.0, -2.0 / 3.0));
+
+        let p3: Vec3 = vec3(::std::f32::MAX, ::std::f32::MAX, 0.0);
+        assert_ne!(p3.normalize(), vec3(1.0 / 2.0f32.sqrt(), 1.0 / 2.0f32.sqrt(), 0.0));
+        assert_eq!(p3.robust_normalize(), vec3(1.0 / 2.0f32.sqrt(), 1.0 / 2.0f32.sqrt(), 0.0));
     }
 
     #[test]
     pub fn test_min() {
         let p1: Vec3 = vec3(1.0, 3.0, 5.0);
         let p2: Vec3 = vec3(2.0, 2.0, -1.0);
 
         let result = p1.min(p2);
@@ -1318,16 +1376,17 @@ mod vector3d {
     pub fn test_swizzling() {
         let p: Vector3D<i32> = vec3(1, 2, 3);
         assert_eq!(p.xy(), vec2(1, 2));
         assert_eq!(p.xz(), vec2(1, 3));
         assert_eq!(p.yz(), vec2(2, 3));
     }
 }
 
+#[cfg(test)]
 mod bool_vector {
     use super::*;
     type Vec2 = Vector2D<f32>;
     type Vec3 = Vector3D<f32>;
 
     #[test]
     fn test_bvec2() {
 
@@ -1409,9 +1468,9 @@ mod bool_vector {
         assert_eq!(bvec3(true, false, false).or(bvec3(true, true, false)), bvec3(true, true, false));
 
         assert_eq!(
             bvec3(true, false, true).select_vector(&Vec3::new(1.0, 2.0, 3.0), &Vec3::new(4.0, 5.0, 6.0)),
             Vec3::new(1.0, 5.0, 3.0),
         );
     }
 
-}
\ No newline at end of file
+}