servo: Merge #17820 - Update cssparser to 0.18 (from servo:token-cache); r=emilio
authorSimon Sapin <simon.sapin@exyr.org>
Mon, 24 Jul 2017 06:27:00 -0700
changeset 419326 e5aad4922fba8855a4bfc979adf4e56c44d6db8c
parent 419325 2badbccc0c6e34cbdf542379a3c31db34dbb1cae
child 419327 a16685e70549796c816432868f0f5ac07869dafa
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
milestone56.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
servo: Merge #17820 - Update cssparser to 0.18 (from servo:token-cache); r=emilio Do not merge yet, depends on https://github.com/servo/rust-cssparser/pull/171. Source-Repo: https://github.com/servo/servo Source-Revision: 4f0821192c112943bb53b4fb04303c1afdde06e6
servo/Cargo.lock
servo/components/canvas/Cargo.toml
servo/components/canvas_traits/Cargo.toml
servo/components/script/Cargo.toml
servo/components/script/dom/bindings/str.rs
servo/components/script/dom/csskeyframesrule.rs
servo/components/script_layout_interface/Cargo.toml
servo/components/selectors/Cargo.toml
servo/components/selectors/parser.rs
servo/components/style/Cargo.toml
servo/components/style/counter_style/mod.rs
servo/components/style/custom_properties.rs
servo/components/style/font_face.rs
servo/components/style/gecko/media_queries.rs
servo/components/style/gecko/selector_parser.rs
servo/components/style/gecko_string_cache/namespace.rs
servo/components/style/macros.rs
servo/components/style/media_queries.rs
servo/components/style/properties/declaration_block.rs
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/helpers/animated_properties.mako.rs
servo/components/style/properties/longhand/background.mako.rs
servo/components/style/properties/longhand/box.mako.rs
servo/components/style/properties/longhand/color.mako.rs
servo/components/style/properties/longhand/counters.mako.rs
servo/components/style/properties/longhand/font.mako.rs
servo/components/style/properties/longhand/inherited_text.mako.rs
servo/components/style/properties/longhand/list.mako.rs
servo/components/style/properties/longhand/pointing.mako.rs
servo/components/style/properties/longhand/position.mako.rs
servo/components/style/properties/longhand/text.mako.rs
servo/components/style/properties/properties.mako.rs
servo/components/style/properties/shorthand/position.mako.rs
servo/components/style/servo/media_queries.rs
servo/components/style/servo/selector_parser.rs
servo/components/style/stylesheets/document_rule.rs
servo/components/style/stylesheets/keyframes_rule.rs
servo/components/style/stylesheets/rule_parser.rs
servo/components/style/stylesheets/supports_rule.rs
servo/components/style/stylesheets/viewport_rule.rs
servo/components/style/values/generics/grid.rs
servo/components/style/values/generics/mod.rs
servo/components/style/values/mod.rs
servo/components/style/values/specified/align.rs
servo/components/style/values/specified/background.rs
servo/components/style/values/specified/basic_shape.rs
servo/components/style/values/specified/calc.rs
servo/components/style/values/specified/color.rs
servo/components/style/values/specified/effects.rs
servo/components/style/values/specified/grid.rs
servo/components/style/values/specified/image.rs
servo/components/style/values/specified/length.rs
servo/components/style/values/specified/mod.rs
servo/components/style/values/specified/text.rs
servo/components/style/values/specified/transform.rs
servo/components/style_traits/Cargo.toml
servo/components/style_traits/lib.rs
servo/components/style_traits/values.rs
servo/components/style_traits/viewport.rs
servo/ports/geckolib/Cargo.toml
servo/ports/geckolib/error_reporter.rs
servo/tests/unit/gfx/Cargo.toml
servo/tests/unit/style/Cargo.toml
servo/tests/unit/stylo/Cargo.toml
--- a/servo/Cargo.lock
+++ b/servo/Cargo.lock
@@ -320,32 +320,32 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "canvas"
 version = "0.0.1"
 dependencies = [
  "azure 0.20.0 (git+https://github.com/servo/rust-azure)",
  "canvas_traits 0.0.1",
- "cssparser 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
  "offscreen_gl_context 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_config 0.0.1",
  "webrender_api 0.48.0 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "canvas_traits"
 version = "0.0.1"
 dependencies = [
- "cssparser 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender_api 0.48.0 (git+https://github.com/servo/webrender)",
 ]
 
@@ -581,17 +581,17 @@ source = "registry+https://github.com/ru
 dependencies = [
  "core-foundation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cssparser"
-version = "0.17.0"
+version = "0.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1013,17 +1013,17 @@ dependencies = [
  "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "geckoservo"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "nsstring_vendor 0.1.0",
  "parking_lot 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "servo_arc 0.0.1",
  "style 0.0.1",
@@ -1081,17 +1081,17 @@ dependencies = [
  "xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "xml5ever 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "gfx_tests"
 version = "0.0.1"
 dependencies = [
- "cssparser 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gfx 0.0.1",
  "ipc-channel 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
 ]
 
 [[package]]
 name = "gfx_traits"
 version = "0.0.1"
@@ -2453,17 +2453,17 @@ dependencies = [
  "base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bluetooth_traits 0.0.1",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "canvas_traits 0.0.1",
  "caseless 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "cookie 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "deny_public_fields 0.0.1",
  "devtools_traits 0.0.1",
  "dom_struct 0.0.1",
  "domobject_derive 0.0.1",
  "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2526,17 +2526,17 @@ dependencies = [
 
 [[package]]
 name = "script_layout_interface"
 version = "0.0.1"
 dependencies = [
  "app_units 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "canvas_traits 0.0.1",
- "cssparser 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "gfx_traits 0.0.1",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "html5ever 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2600,17 +2600,17 @@ dependencies = [
  "webvr_traits 0.0.1",
 ]
 
 [[package]]
 name = "selectors"
 version = "0.19.0"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_arc 0.0.1",
  "size_of_test 0.0.1",
@@ -2999,17 +2999,17 @@ dependencies = [
  "arraydeque 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "arrayvec 0.3.23 (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.26.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.0.0 (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.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "html5ever 0.18.0 (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)",
@@ -3053,17 +3053,17 @@ dependencies = [
 ]
 
 [[package]]
 name = "style_tests"
 version = "0.0.1"
 dependencies = [
  "app_units 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "html5ever 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "servo_arc 0.0.1",
  "servo_atoms 0.0.1",
@@ -3075,30 +3075,30 @@ dependencies = [
 ]
 
 [[package]]
 name = "style_traits"
 version = "0.0.1"
 dependencies = [
  "app_units 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cssparser 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[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.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "geckoservo 0.0.1",
  "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "size_of_test 0.0.1",
  "style 0.0.1",
@@ -3676,17 +3676,17 @@ dependencies = [
 "checksum cocoa 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4047fed6536f40cc2ae5e7834fb38e382c788270191c4cd69196f89686d076ce"
 "checksum color_quant 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a475fc4af42d83d28adf72968d9bcfaf035a1a9381642d8e85d8a04957767b0d"
 "checksum compiletest_rs 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "617b23d0ed4f57b3bcff6b5fe0a78f0010f1efb636298317665a960b6dbc0533"
 "checksum cookie 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30b3493e12a550c2f96be785088d1da8d93189e7237c8a8d0d871bc9070334c3"
 "checksum core-foundation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f51ce3b8ebe311c56de14231eb57572c15abebd2d32b3bcb99bcdb9c101f5ac3"
 "checksum core-foundation-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "41115a6aa5d3e1e5ef98148373f25971d1fad53818553f216495f9e67e90a624"
 "checksum core-graphics 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a9f841e9637adec70838c537cae52cb4c751cc6514ad05669b51d107c2021c79"
 "checksum core-text 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16ce16d9ed00181016c11ff48e561314bec92bfbce9fe48f319366618d4e5de6"
-"checksum cssparser 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7063452c60432cb306ed54d538178c20792d47fa960c240ce6c083239ee55ec"
+"checksum cssparser 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7cf65dc20c985b085db316cf6e824fbccd4fa2c4641b57b8f42e06b0edb1052d"
 "checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"
 "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
 "checksum dbus 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4aee01fb76ada3e5e7ca642ea6664ebf7308a810739ca2aca44909a1191ac254"
 "checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
 "checksum deflate 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebb02aaf4b775afc96684b8402510a338086974e38570a1f65bea8c202eb77a7"
 "checksum device 0.0.1 (git+https://github.com/servo/devices)" = "<none>"
 "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
 "checksum dwmapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07c4c7cc7b396419bc0a4d90371d0cee16cb5053b53647d287c0b728000c41fe"
--- a/servo/components/canvas/Cargo.toml
+++ b/servo/components/canvas/Cargo.toml
@@ -7,17 +7,17 @@ publish = false
 
 [lib]
 name = "canvas"
 path = "lib.rs"
 
 [dependencies]
 azure = {git = "https://github.com/servo/rust-azure"}
 canvas_traits = {path = "../canvas_traits"}
-cssparser = "0.17.0"
+cssparser = "0.18"
 euclid = "0.15"
 gleam = "0.4"
 ipc-channel = "0.8"
 log = "0.3.5"
 num-traits = "0.1.32"
 offscreen_gl_context = { version = "0.11", features = ["serde"] }
 servo_config = {path = "../config"}
 webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
--- a/servo/components/canvas_traits/Cargo.toml
+++ b/servo/components/canvas_traits/Cargo.toml
@@ -5,15 +5,15 @@ authors = ["The Servo Project Developers
 license = "MPL-2.0"
 publish = false
 
 [lib]
 name = "canvas_traits"
 path = "lib.rs"
 
 [dependencies]
-cssparser = "0.17.0"
+cssparser = "0.18"
 euclid = "0.15"
 heapsize = "0.4"
 heapsize_derive = "0.1"
 ipc-channel = "0.8"
 serde = "1.0"
 webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
--- a/servo/components/script/Cargo.toml
+++ b/servo/components/script/Cargo.toml
@@ -29,17 +29,17 @@ app_units = "0.5"
 audio-video-metadata = "0.1.2"
 base64 = "0.5.2"
 bitflags = "0.7"
 bluetooth_traits = {path = "../bluetooth_traits"}
 byteorder = "1.0"
 canvas_traits = {path = "../canvas_traits"}
 caseless = "0.1.0"
 cookie = "0.6"
-cssparser = "0.17.0"
+cssparser = "0.18"
 deny_public_fields = {path = "../deny_public_fields"}
 devtools_traits = {path = "../devtools_traits"}
 dom_struct = {path = "../dom_struct"}
 domobject_derive = {path = "../domobject_derive"}
 encoding = "0.2"
 euclid = "0.15"
 fnv = "1.0"
 gleam = "0.4"
--- a/servo/components/script/dom/bindings/str.rs
+++ b/servo/components/script/dom/bindings/str.rs
@@ -1,15 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! The `ByteString` struct.
 
-use cssparser::CompactCowStr;
+use cssparser::CowRcStr;
 use html5ever::{LocalName, Namespace};
 use servo_atoms::Atom;
 use std::ascii::AsciiExt;
 use std::borrow::{Borrow, Cow, ToOwned};
 use std::fmt;
 use std::hash::{Hash, Hasher};
 use std::marker::PhantomData;
 use std::ops;
@@ -293,18 +293,18 @@ impl Into<Vec<u8>> for DOMString {
 }
 
 impl<'a> Into<Cow<'a, str>> for DOMString {
     fn into(self) -> Cow<'a, str> {
         self.0.into()
     }
 }
 
-impl<'a> Into<CompactCowStr<'a>> for DOMString {
-    fn into(self) -> CompactCowStr<'a> {
+impl<'a> Into<CowRcStr<'a>> for DOMString {
+    fn into(self) -> CowRcStr<'a> {
         self.0.into()
     }
 }
 
 impl Extend<char> for DOMString {
     fn extend<I>(&mut self, iterable: I) where I: IntoIterator<Item=char> {
         self.0.extend(iterable)
     }
--- a/servo/components/script/dom/csskeyframesrule.rs
+++ b/servo/components/script/dom/csskeyframesrule.rs
@@ -116,17 +116,17 @@ impl CSSKeyframesRuleMethods for CSSKeyf
         DOMString::from(&**self.keyframesrule.read_with(&guard).name.as_atom())
     }
 
     // https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-name
     fn SetName(&self, value: DOMString) -> ErrorResult {
         // Spec deviation: https://github.com/w3c/csswg-drafts/issues/801
         // Setting this property to a CSS-wide keyword or `none` does not throw,
         // it stores a value that serializes as a quoted string.
-        let name = KeyframesName::from_ident(value.into());
+        let name = KeyframesName::from_ident(&value);
         let mut guard = self.cssrule.shared_lock().write();
         self.keyframesrule.write_with(&mut guard).name = name;
         Ok(())
     }
 }
 
 impl SpecificCSSRule for CSSKeyframesRule {
     fn ty(&self) -> u16 {
--- a/servo/components/script_layout_interface/Cargo.toml
+++ b/servo/components/script_layout_interface/Cargo.toml
@@ -8,17 +8,17 @@ publish = false
 [lib]
 name = "script_layout_interface"
 path = "lib.rs"
 
 [dependencies]
 app_units = "0.5"
 atomic_refcell = "0.1"
 canvas_traits = {path = "../canvas_traits"}
-cssparser = "0.17.0"
+cssparser = "0.18"
 euclid = "0.15"
 gfx_traits = {path = "../gfx_traits"}
 heapsize = "0.4"
 heapsize_derive = "0.1"
 html5ever = "0.18"
 ipc-channel = "0.8"
 libc = "0.2"
 log = "0.3.5"
--- a/servo/components/selectors/Cargo.toml
+++ b/servo/components/selectors/Cargo.toml
@@ -20,17 +20,17 @@ doctest = false
 
 [features]
 gecko_like_types = []
 unstable = []
 
 [dependencies]
 bitflags = "0.7"
 matches = "0.1"
-cssparser = "0.17.0"
+cssparser = "0.18"
 log = "0.3"
 fnv = "1.0"
 phf = "0.7.18"
 precomputed-hash = "0.1"
 servo_arc = { path = "../servo_arc" }
 smallvec = "0.4"
 
 [dev-dependencies]
--- a/servo/components/selectors/parser.rs
+++ b/servo/components/selectors/parser.rs
@@ -2,17 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use attr::{AttrSelectorWithNamespace, ParsedAttrSelectorOperation, AttrSelectorOperator};
 use attr::{ParsedCaseSensitivity, SELECTOR_WHITESPACE, NamespaceConstraint};
 use bloom::BLOOM_HASH_MASK;
 use builder::{SelectorBuilder, SpecificityAndFlags};
 use context::QuirksMode;
-use cssparser::{ParseError, BasicParseError, CompactCowStr};
+use cssparser::{ParseError, BasicParseError, CowRcStr};
 use cssparser::{Token, Parser as CssParser, parse_nth, ToCss, serialize_identifier, CssStringWriter};
 use precomputed_hash::PrecomputedHash;
 use servo_arc::ThinArc;
 use sink::Push;
 use smallvec::SmallVec;
 use std::ascii::AsciiExt;
 use std::borrow::{Borrow, Cow};
 use std::fmt::{self, Display, Debug, Write};
@@ -54,40 +54,33 @@ pub enum SelectorParseError<'i, T> {
     NegationSelectorComponentNotNamespace,
     NegationSelectorComponentNotLocalName,
     EmptySelector,
     NonSimpleSelectorInNegation,
     UnexpectedTokenInAttributeSelector,
     PseudoElementExpectedColon,
     PseudoElementExpectedIdent,
     UnsupportedPseudoClass,
-    UnexpectedIdent(CompactCowStr<'i>),
-    ExpectedNamespace(CompactCowStr<'i>),
+    UnexpectedIdent(CowRcStr<'i>),
+    ExpectedNamespace(CowRcStr<'i>),
     Custom(T),
 }
 
 impl<'a, T> Into<ParseError<'a, SelectorParseError<'a, T>>> for SelectorParseError<'a, T> {
     fn into(self) -> ParseError<'a, SelectorParseError<'a, T>> {
         ParseError::Custom(self)
     }
 }
 
 macro_rules! with_all_bounds {
     (
         [ $( $InSelector: tt )* ]
         [ $( $CommonBounds: tt )* ]
         [ $( $FromStr: tt )* ]
     ) => {
-        fn from_cow_str<T>(cow: Cow<str>) -> T where T: $($FromStr)* {
-            match cow {
-                Cow::Borrowed(s) => T::from(s),
-                Cow::Owned(s) => T::from(s),
-            }
-        }
-
         /// This trait allows to define the parser implementation in regards
         /// of pseudo-classes/elements
         ///
         /// NB: We need Clone so that we can derive(Clone) on struct with that
         /// are parameterized on SelectorImpl. See
         /// https://github.com/rust-lang/rust/issues/26925
         pub trait SelectorImpl: Clone + Sized + 'static {
             type AttrValue: $($InSelector)*;
@@ -120,53 +113,53 @@ macro_rules! with_bounds {
             [$($CommonBounds)*]
             [$($FromStr)*]
         }
     }
 }
 
 with_bounds! {
     [Clone + Eq]
-    [From<String> + for<'a> From<&'a str>]
+    [for<'a> From<&'a str>]
 }
 
 pub trait Parser<'i> {
     type Impl: SelectorImpl;
     type Error: 'i;
 
     /// Whether the name is a pseudo-element that can be specified with
     /// the single colon syntax in addition to the double-colon syntax.
-    fn is_pseudo_element_allows_single_colon(name: &CompactCowStr<'i>) -> bool {
+    fn is_pseudo_element_allows_single_colon(name: &CowRcStr<'i>) -> bool {
         is_css2_pseudo_element(name)
     }
 
     /// This function can return an "Err" pseudo-element in order to support CSS2.1
     /// pseudo-elements.
-    fn parse_non_ts_pseudo_class(&self, name: CompactCowStr<'i>)
+    fn parse_non_ts_pseudo_class(&self, name: CowRcStr<'i>)
                                  -> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass,
                                            ParseError<'i, SelectorParseError<'i, Self::Error>>> {
         Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name)))
     }
 
     fn parse_non_ts_functional_pseudo_class<'t>
-        (&self, name: CompactCowStr<'i>, _arguments: &mut CssParser<'i, 't>)
+        (&self, name: CowRcStr<'i>, _arguments: &mut CssParser<'i, 't>)
          -> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass,
                    ParseError<'i, SelectorParseError<'i, Self::Error>>>
     {
         Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name)))
     }
 
-    fn parse_pseudo_element(&self, name: CompactCowStr<'i>)
+    fn parse_pseudo_element(&self, name: CowRcStr<'i>)
                             -> Result<<Self::Impl as SelectorImpl>::PseudoElement,
                                       ParseError<'i, SelectorParseError<'i, Self::Error>>> {
         Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name)))
     }
 
     fn parse_functional_pseudo_element<'t>
-        (&self, name: CompactCowStr<'i>, _arguments: &mut CssParser<'i, 't>)
+        (&self, name: CowRcStr<'i>, _arguments: &mut CssParser<'i, 't>)
          -> Result<<Self::Impl as SelectorImpl>::PseudoElement,
                    ParseError<'i, SelectorParseError<'i, Self::Error>>> {
         Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name)))
     }
 
     fn default_namespace(&self) -> Option<<Self::Impl as SelectorImpl>::NamespaceUrl> {
         None
     }
@@ -1055,26 +1048,26 @@ fn parse_selector<'i, 't, P, E, Impl>(
 
         // Parse a combinator.
         let combinator;
         let mut any_whitespace = false;
         loop {
             let position = input.position();
             match input.next_including_whitespace() {
                 Err(_e) => break 'outer_loop,
-                Ok(Token::WhiteSpace(_)) => any_whitespace = true,
-                Ok(Token::Delim('>')) => {
+                Ok(&Token::WhiteSpace(_)) => any_whitespace = true,
+                Ok(&Token::Delim('>')) => {
                     combinator = Combinator::Child;
                     break
                 }
-                Ok(Token::Delim('+')) => {
+                Ok(&Token::Delim('+')) => {
                     combinator = Combinator::NextSibling;
                     break
                 }
-                Ok(Token::Delim('~')) => {
+                Ok(&Token::Delim('~')) => {
                     combinator = Combinator::LaterSibling;
                     break
                 }
                 Ok(_) => {
                     input.reset(position);
                     if any_whitespace {
                         combinator = Combinator::Descendant;
                         break
@@ -1149,18 +1142,18 @@ fn parse_type_selector<'i, 't, P, E, Imp
                 }
                 QNamePrefix::ImplicitNoNamespace => {
                     unreachable!()  // Not returned with in_attr_selector = false
                 }
             }
             match local_name {
                 Some(name) => {
                     sink.push(Component::LocalName(LocalName {
-                        lower_name: from_cow_str(to_ascii_lowercase(&name)),
-                        name: from_cow_str(name.into()),
+                        lower_name: to_ascii_lowercase(&name).as_ref().into(),
+                        name: name.as_ref().into(),
                     }))
                 }
                 None => {
                     sink.push(Component::ExplicitUniversalType)
                 }
             }
             Ok(true)
         }
@@ -1184,75 +1177,77 @@ enum QNamePrefix<Impl: SelectorImpl> {
 }
 
 /// * `Err(())`: Invalid selector, abort
 /// * `Ok(None)`: Not a simple selector, could be something else. `input` was not consumed.
 /// * `Ok(Some((namespace, local_name)))`: `None` for the local name means a `*` universal selector
 fn parse_qualified_name<'i, 't, P, E, Impl>
                        (parser: &P, input: &mut CssParser<'i, 't>,
                         in_attr_selector: bool)
-                        -> Result<Option<(QNamePrefix<Impl>, Option<CompactCowStr<'i>>)>,
+                        -> Result<Option<(QNamePrefix<Impl>, Option<CowRcStr<'i>>)>,
                                   ParseError<'i, SelectorParseError<'i, E>>>
     where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
 {
     let default_namespace = |local_name| {
         let namespace = match parser.default_namespace() {
             Some(url) => QNamePrefix::ImplicitDefaultNamespace(url),
             None => QNamePrefix::ImplicitAnyNamespace,
         };
         Ok(Some((namespace, local_name)))
     };
 
     let explicit_namespace = |input: &mut CssParser<'i, 't>, namespace| {
         match input.next_including_whitespace() {
-            Ok(Token::Delim('*')) if !in_attr_selector => {
+            Ok(&Token::Delim('*')) if !in_attr_selector => {
                 Ok(Some((namespace, None)))
             },
-            Ok(Token::Ident(local_name)) => {
-                Ok(Some((namespace, Some(local_name))))
+            Ok(&Token::Ident(ref local_name)) => {
+                Ok(Some((namespace, Some(local_name.clone()))))
             },
-            Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
+            Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t.clone()))),
             Err(e) => Err(ParseError::Basic(e)),
         }
     };
 
     let position = input.position();
-    match input.next_including_whitespace() {
+    // FIXME: remove clone() when lifetimes are non-lexical
+    match input.next_including_whitespace().map(|t| t.clone()) {
         Ok(Token::Ident(value)) => {
             let position = input.position();
             match input.next_including_whitespace() {
-                Ok(Token::Delim('|')) => {
-                    let prefix = from_cow_str(value.clone().into());
+                Ok(&Token::Delim('|')) => {
+                    let prefix = value.as_ref().into();
                     let result = parser.namespace_for_prefix(&prefix);
                     let url = result.ok_or(ParseError::Custom(
-                        SelectorParseError::ExpectedNamespace(value.into())))?;
+                        SelectorParseError::ExpectedNamespace(value)))?;
                     explicit_namespace(input, QNamePrefix::ExplicitNamespace(prefix, url))
                 },
                 _ => {
                     input.reset(position);
                     if in_attr_selector {
                         Ok(Some((QNamePrefix::ImplicitNoNamespace, Some(value))))
                     } else {
                         default_namespace(Some(value))
                     }
                 }
             }
         },
         Ok(Token::Delim('*')) => {
             let position = input.position();
-            match input.next_including_whitespace() {
+            // FIXME: remove clone() when lifetimes are non-lexical
+            match input.next_including_whitespace().map(|t| t.clone()) {
                 Ok(Token::Delim('|')) => {
                     explicit_namespace(input, QNamePrefix::ExplicitAnyNamespace)
                 }
                 result => {
                     input.reset(position);
                     if in_attr_selector {
                         match result {
                             Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
-                             Err(e) => Err(ParseError::Basic(e)),
+                            Err(e) => Err(ParseError::Basic(e)),
                         }
                     } else {
                         default_namespace(None)
                     }
                 },
             }
         },
         Ok(Token::Delim('|')) => {
@@ -1298,18 +1293,18 @@ fn parse_attribute_selector<'i, 't, P, E
     }
 
     let operator;
     let value;
     let never_matches;
     match input.next() {
         // [foo]
         Err(_) => {
-            let local_name_lower = from_cow_str(to_ascii_lowercase(&local_name));
-            let local_name = from_cow_str(local_name.into());
+            let local_name_lower = to_ascii_lowercase(&local_name).as_ref().into();
+            let local_name = local_name.as_ref().into();
             if let Some(namespace) = namespace {
                 return Ok(Component::AttributeOther(Box::new(AttrSelectorWithNamespace {
                     namespace: namespace,
                     local_name: local_name,
                     local_name_lower: local_name_lower,
                     operation: ParsedAttrSelectorOperation::Exists,
                     never_matches: false,
                 })))
@@ -1317,72 +1312,72 @@ fn parse_attribute_selector<'i, 't, P, E
                 return Ok(Component::AttributeInNoNamespaceExists {
                     local_name: local_name,
                     local_name_lower: local_name_lower,
                 })
             }
         }
 
         // [foo=bar]
-        Ok(Token::Delim('=')) => {
-            value = input.expect_ident_or_string()?;
+        Ok(&Token::Delim('=')) => {
+            value = input.expect_ident_or_string()?.clone();
             never_matches = false;
             operator = AttrSelectorOperator::Equal;
         }
         // [foo~=bar]
-        Ok(Token::IncludeMatch) => {
-            value = input.expect_ident_or_string()?;
+        Ok(&Token::IncludeMatch) => {
+            value = input.expect_ident_or_string()?.clone();
             never_matches = value.is_empty() || value.contains(SELECTOR_WHITESPACE);
             operator = AttrSelectorOperator::Includes;
         }
         // [foo|=bar]
-        Ok(Token::DashMatch) => {
-            value = input.expect_ident_or_string()?;
+        Ok(&Token::DashMatch) => {
+            value = input.expect_ident_or_string()?.clone();
             never_matches = false;
             operator = AttrSelectorOperator::DashMatch;
         }
         // [foo^=bar]
-        Ok(Token::PrefixMatch) => {
-            value = input.expect_ident_or_string()?;
+        Ok(&Token::PrefixMatch) => {
+            value = input.expect_ident_or_string()?.clone();
             never_matches = value.is_empty();
             operator = AttrSelectorOperator::Prefix;
         }
         // [foo*=bar]
-        Ok(Token::SubstringMatch) => {
-            value = input.expect_ident_or_string()?;
+        Ok(&Token::SubstringMatch) => {
+            value = input.expect_ident_or_string()?.clone();
             never_matches = value.is_empty();
             operator = AttrSelectorOperator::Substring;
         }
         // [foo$=bar]
-        Ok(Token::SuffixMatch) => {
-            value = input.expect_ident_or_string()?;
+        Ok(&Token::SuffixMatch) => {
+            value = input.expect_ident_or_string()?.clone();
             never_matches = value.is_empty();
             operator = AttrSelectorOperator::Suffix;
         }
         _ => return Err(SelectorParseError::UnexpectedTokenInAttributeSelector.into())
     }
 
     let mut case_sensitivity = parse_attribute_flags(input)?;
 
-    let value = from_cow_str(value.into());
+    let value = value.as_ref().into();
     let local_name_lower;
     {
         let local_name_lower_cow = to_ascii_lowercase(&local_name);
         if let ParsedCaseSensitivity::CaseSensitive = case_sensitivity {
             if namespace.is_none() &&
                 include!(concat!(env!("OUT_DIR"), "/ascii_case_insensitive_html_attributes.rs"))
                 .contains(&*local_name_lower_cow)
             {
                 case_sensitivity =
                     ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument
             }
         }
-        local_name_lower = from_cow_str(local_name_lower_cow.into());
+        local_name_lower = local_name_lower_cow.as_ref().into();
     }
-    let local_name = from_cow_str(local_name.into());
+    let local_name = local_name.as_ref().into();
     if let Some(namespace) = namespace {
         Ok(Component::AttributeOther(Box::new(AttrSelectorWithNamespace {
             namespace: namespace,
             local_name: local_name,
             local_name_lower: local_name_lower,
             never_matches: never_matches,
             operation: ParsedAttrSelectorOperation::WithValue {
                 operator: operator,
@@ -1406,20 +1401,20 @@ fn parse_attribute_selector<'i, 't, P, E
 fn parse_attribute_flags<'i, 't, E>(input: &mut CssParser<'i, 't>)
                                     -> Result<ParsedCaseSensitivity,
                                               ParseError<'i, SelectorParseError<'i, E>>> {
     match input.next() {
         Err(_) => {
             // Selectors spec says language-defined, but HTML says sensitive.
             Ok(ParsedCaseSensitivity::CaseSensitive)
         }
-        Ok(Token::Ident(ref value)) if value.eq_ignore_ascii_case("i") => {
+        Ok(&Token::Ident(ref value)) if value.eq_ignore_ascii_case("i") => {
             Ok(ParsedCaseSensitivity::AsciiCaseInsensitive)
         }
-        Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t)))
+        Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t.clone())))
     }
 }
 
 
 /// Level 3: Parse **one** simple_selector.  (Though we might insert a second
 /// implied "<defaultns>|*" type selector.)
 fn parse_negation<'i, 't, P, E, Impl>(parser: &P,
                                       input: &mut CssParser<'i, 't>)
@@ -1428,17 +1423,17 @@ fn parse_negation<'i, 't, P, E, Impl>(pa
     where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
 {
     // We use a sequence because a type selector may be represented as two Components.
     let mut sequence = SmallVec::<[Component<Impl>; 2]>::new();
 
     // Consume any leading whitespace.
     loop {
         let position = input.position();
-        if !matches!(input.next_including_whitespace(), Ok(Token::WhiteSpace(_))) {
+        if !matches!(input.next_including_whitespace(), Ok(&Token::WhiteSpace(_))) {
             input.reset(position);
             break
         }
     }
 
     // Get exactly one simple selector. The parse logic in the caller will verify
     // that there are no trailing tokens after we're done.
     if !parse_type_selector(parser, input, &mut sequence)? {
@@ -1471,17 +1466,17 @@ fn parse_compound_selector<'i, 't, P, E,
     input: &mut CssParser<'i, 't>,
     mut builder: &mut SelectorBuilder<Impl>)
     -> Result<bool, ParseError<'i, SelectorParseError<'i, E>>>
     where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
 {
     // Consume any leading whitespace.
     loop {
         let position = input.position();
-        if !matches!(input.next_including_whitespace(), Ok(Token::WhiteSpace(_))) {
+        if !matches!(input.next_including_whitespace(), Ok(&Token::WhiteSpace(_))) {
             input.reset(position);
             break
         }
     }
     let mut empty = true;
     if !parse_type_selector(parser, input, builder)? {
         if let Some(url) = parser.default_namespace() {
             // If there was no explicit type selector, but there is a
@@ -1503,25 +1498,25 @@ fn parse_compound_selector<'i, 't, P, E,
             }
             Some(SimpleSelectorParseResult::PseudoElement(p)) => {
                 // Try to parse state to its right. There are only 3 allowable
                 // state selectors that can go on pseudo-elements.
                 let mut state_selectors = SmallVec::<[Component<Impl>; 3]>::new();
 
                 loop {
                     match input.next_including_whitespace() {
-                        Ok(Token::Colon) => {},
-                        Ok(Token::WhiteSpace(_)) | Err(_) => break,
+                        Ok(&Token::Colon) => {},
+                        Ok(&Token::WhiteSpace(_)) | Err(_) => break,
                         _ => return Err(SelectorParseError::PseudoElementExpectedColon.into()),
                     }
 
                     // TODO(emilio): Functional pseudo-classes too?
                     // We don't need it for now.
                     let name = match input.next_including_whitespace() {
-                        Ok(Token::Ident(name)) => name,
+                        Ok(&Token::Ident(ref name)) => name.clone(),
                         _ => return Err(SelectorParseError::PseudoElementExpectedIdent.into()),
                     };
 
                     let pseudo_class =
                         P::parse_non_ts_pseudo_class(parser, name)?;
                     if !p.supports_pseudo_class(&pseudo_class) {
                         return Err(SelectorParseError::UnsupportedPseudoClass.into());
                     }
@@ -1548,17 +1543,17 @@ fn parse_compound_selector<'i, 't, P, E,
         Err(ParseError::Custom(SelectorParseError::EmptySelector))
     } else {
         Ok(pseudo)
     }
 }
 
 fn parse_functional_pseudo_class<'i, 't, P, E, Impl>(parser: &P,
                                                      input: &mut CssParser<'i, 't>,
-                                                     name: CompactCowStr<'i>,
+                                                     name: CowRcStr<'i>,
                                                      inside_negation: bool)
                                                      -> Result<Component<Impl>,
                                                                ParseError<'i, SelectorParseError<'i, E>>>
     where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
 {
     match_ignore_ascii_case! { &name,
         "nth-child" => return parse_nth_pseudo_class(input, Component::NthChild),
         "nth-of-type" => return parse_nth_pseudo_class(input, Component::NthOfType),
@@ -1584,17 +1579,17 @@ where Impl: SelectorImpl, F: FnOnce(i32,
     let (a, b) = parse_nth(input)?;
     Ok(selector(a, b))
 }
 
 
 /// Returns whether the name corresponds to a CSS2 pseudo-element that
 /// can be specified with the single colon syntax (in addition to the
 /// double-colon syntax, which can be used for all pseudo-elements).
-pub fn is_css2_pseudo_element<'i>(name: &CompactCowStr<'i>) -> bool {
+pub fn is_css2_pseudo_element<'i>(name: &CowRcStr<'i>) -> bool {
     // ** Do not add to this list! **
     return name.eq_ignore_ascii_case("before") ||
            name.eq_ignore_ascii_case("after") ||
            name.eq_ignore_ascii_case("first-line") ||
            name.eq_ignore_ascii_case("first-letter");
 }
 
 /// Parse a simple selector other than a type selector.
@@ -1605,37 +1600,38 @@ pub fn is_css2_pseudo_element<'i>(name: 
 fn parse_one_simple_selector<'i, 't, P, E, Impl>(parser: &P,
                                                  input: &mut CssParser<'i, 't>,
                                                  inside_negation: bool)
                                                  -> Result<Option<SimpleSelectorParseResult<Impl>>,
                                                            ParseError<'i, SelectorParseError<'i, E>>>
     where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
 {
     let start_position = input.position();
-    match input.next_including_whitespace() {
+    // FIXME: remove clone() when lifetimes are non-lexical
+    match input.next_including_whitespace().map(|t| t.clone()) {
         Ok(Token::IDHash(id)) => {
-            let id = Component::ID(from_cow_str(id.into()));
+            let id = Component::ID(id.as_ref().into());
             Ok(Some(SimpleSelectorParseResult::SimpleSelector(id)))
         }
         Ok(Token::Delim('.')) => {
-            match input.next_including_whitespace()? {
-                Token::Ident(class) => {
-                    let class = Component::Class(from_cow_str(class.into()));
+            match *input.next_including_whitespace()? {
+                Token::Ident(ref class) => {
+                    let class = Component::Class(class.as_ref().into());
                     Ok(Some(SimpleSelectorParseResult::SimpleSelector(class)))
                 }
-                t => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
+                ref t => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t.clone()))),
             }
         }
         Ok(Token::SquareBracketBlock) => {
             let attr = input.parse_nested_block(|input| parse_attribute_selector(parser, input))?;
             Ok(Some(SimpleSelectorParseResult::SimpleSelector(attr)))
         }
         Ok(Token::Colon) => {
-            let (is_single_colon, next_token) = match input.next_including_whitespace()? {
-                Token::Colon => (false, input.next_including_whitespace()?),
+            let (is_single_colon, next_token) = match input.next_including_whitespace()?.clone() {
+                Token::Colon => (false, input.next_including_whitespace()?.clone()),
                 t => (true, t),
             };
             let (name, is_functional) = match next_token {
                 Token::Ident(name) => (name, false),
                 Token::Function(name) => (name, true),
                 t => return Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
             };
             let is_pseudo_element = !is_single_colon ||
@@ -1662,17 +1658,17 @@ fn parse_one_simple_selector<'i, 't, P, 
         }
         _ => {
             input.reset(start_position);
             Ok(None)
         }
     }
 }
 
-fn parse_simple_pseudo_class<'i, P, E, Impl>(parser: &P, name: CompactCowStr<'i>)
+fn parse_simple_pseudo_class<'i, P, E, Impl>(parser: &P, name: CowRcStr<'i>)
                                              -> Result<Component<Impl>,
                                                        ParseError<'i, SelectorParseError<'i, E>>>
     where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
 {
     (match_ignore_ascii_case! { &name,
         "first-child" => Ok(Component::FirstChild),
         "last-child"  => Ok(Component::LastChild),
         "only-child"  => Ok(Component::OnlyChild),
@@ -1816,37 +1812,37 @@ pub mod tests {
             return 0
         }
     }
 
     impl<'i> Parser<'i> for DummyParser {
         type Impl = DummySelectorImpl;
         type Error = ();
 
-        fn parse_non_ts_pseudo_class(&self, name: CompactCowStr<'i>)
+        fn parse_non_ts_pseudo_class(&self, name: CowRcStr<'i>)
                                      -> Result<PseudoClass,
                                                ParseError<'i, SelectorParseError<'i, ()>>> {
             match_ignore_ascii_case! { &name,
                 "hover" => Ok(PseudoClass::Hover),
                 "active" => Ok(PseudoClass::Active),
                 _ => Err(SelectorParseError::Custom(()).into())
             }
         }
 
-        fn parse_non_ts_functional_pseudo_class<'t>(&self, name: CompactCowStr<'i>,
+        fn parse_non_ts_functional_pseudo_class<'t>(&self, name: CowRcStr<'i>,
                                                     parser: &mut CssParser<'i, 't>)
                                                     -> Result<PseudoClass,
                                                               ParseError<'i, SelectorParseError<'i, ()>>> {
             match_ignore_ascii_case! { &name,
-                "lang" => Ok(PseudoClass::Lang(parser.expect_ident_or_string()?.into_owned())),
+                "lang" => Ok(PseudoClass::Lang(parser.expect_ident_or_string()?.as_ref().to_owned())),
                 _ => Err(SelectorParseError::Custom(()).into())
             }
         }
 
-        fn parse_pseudo_element(&self, name: CompactCowStr<'i>)
+        fn parse_pseudo_element(&self, name: CowRcStr<'i>)
                                 -> Result<PseudoElement,
                                           ParseError<'i, SelectorParseError<'i, ()>>> {
             match_ignore_ascii_case! { &name,
                 "before" => Ok(PseudoElement::Before),
                 "after" => Ok(PseudoElement::After),
                 _ => Err(SelectorParseError::Custom(()).into())
             }
         }
--- a/servo/components/style/Cargo.toml
+++ b/servo/components/style/Cargo.toml
@@ -33,17 +33,17 @@ gecko_debug = ["nsstring_vendor/gecko_de
 app_units = "0.5"
 arrayvec = "0.3.20"
 arraydeque = "0.2.3"
 atomic_refcell = "0.1"
 bitflags = "0.7"
 bit-vec = "0.4.3"
 byteorder = "1.0"
 cfg-if = "0.1.0"
-cssparser = "0.17.0"
+cssparser = "0.18"
 encoding = {version = "0.2", optional = true}
 euclid = "0.15"
 fnv = "1.0"
 heapsize = {version = "0.4", optional = true}
 heapsize_derive = {version = "0.1", optional = true}
 itoa = "0.3"
 html5ever = {version = "0.18", optional = true}
 lazy_static = "0.2"
--- a/servo/components/style/counter_style/mod.rs
+++ b/servo/components/style/counter_style/mod.rs
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! The [`@counter-style`][counter-style] at-rule.
 //!
 //! [counter-style]: https://drafts.csswg.org/css-counter-styles/
 
 use Atom;
 use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser};
-use cssparser::{Parser, Token, serialize_identifier, BasicParseError, CompactCowStr};
+use cssparser::{Parser, Token, serialize_identifier, BasicParseError, CowRcStr};
 use error_reporting::ContextualParseError;
 #[cfg(feature = "gecko")] use gecko::rules::CounterStyleDescriptors;
 #[cfg(feature = "gecko")] use gecko_bindings::structs::nsCSSCounterDesc;
 use parser::{ParserContext, log_css_error, Parse};
 use selectors::parser::SelectorParseError;
 use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
 use std::ascii::AsciiExt;
 use std::borrow::Cow;
@@ -179,17 +179,17 @@ macro_rules! counter_style_descriptors {
                 )*
             }
         }
 
         impl<'a, 'b, 'i> DeclarationParser<'i> for CounterStyleRuleParser<'a, 'b> {
             type Declaration = ();
             type Error = SelectorParseError<'i, StyleParseError<'i>>;
 
-            fn parse_value<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>)
+            fn parse_value<'t>(&mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't>)
                                -> Result<(), ParseError<'i>> {
                 match_ignore_ascii_case! { &*name,
                     $(
                         $name => {
                             // DeclarationParser also calls parse_entirely
                             // so we’d normally not need to,
                             // but in this case we do because we set the value as a side effect
                             // rather than returning it.
@@ -290,17 +290,17 @@ pub enum System {
         first_symbol_value: Option<i32>
     },
     /// 'extends <counter-style-name>'
     Extends(CustomIdent),
 }
 
 impl Parse for System {
     fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
-        try_match_ident_ignore_ascii_case! { input.expect_ident()?,
+        try_match_ident_ignore_ascii_case! { input.expect_ident_cloned()?,
             "cyclic" => Ok(System::Cyclic),
             "numeric" => Ok(System::Numeric),
             "alphabetic" => Ok(System::Alphabetic),
             "symbolic" => Ok(System::Symbolic),
             "additive" => Ok(System::Additive),
             "fixed" => {
                 let first_symbol_value = input.try(|i| i.expect_integer()).ok();
                 Ok(System::Fixed { first_symbol_value: first_symbol_value })
@@ -346,19 +346,19 @@ pub enum Symbol {
     // Not implemented:
     // /// <image>
     // Image(Image),
 }
 
 impl Parse for Symbol {
     fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         match input.next() {
-            Ok(Token::QuotedString(s)) => Ok(Symbol::String(s.into_owned())),
-            Ok(Token::Ident(s)) => Ok(Symbol::Ident(s.into_owned())),
-            Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
+            Ok(&Token::QuotedString(ref s)) => Ok(Symbol::String(s.as_ref().to_owned())),
+            Ok(&Token::Ident(ref s)) => Ok(Symbol::Ident(s.as_ref().to_owned())),
+            Ok(t) => Err(BasicParseError::UnexpectedToken(t.clone()).into()),
             Err(e) => Err(e.into()),
         }
     }
 }
 
 impl ToCss for Symbol {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         match *self {
@@ -414,19 +414,19 @@ impl Parse for Ranges {
                 Ok(opt_start..opt_end)
             }).map(Ranges)
         }
     }
 }
 
 fn parse_bound<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Option<i32>, ParseError<'i>> {
     match input.next() {
-        Ok(Token::Number { int_value: Some(v), .. }) => Ok(Some(v)),
-        Ok(Token::Ident(ref ident)) if ident.eq_ignore_ascii_case("infinite") => Ok(None),
-        Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
+        Ok(&Token::Number { int_value: Some(v), .. }) => Ok(Some(v)),
+        Ok(&Token::Ident(ref ident)) if ident.eq_ignore_ascii_case("infinite") => Ok(None),
+        Ok(t) => Err(BasicParseError::UnexpectedToken(t.clone()).into()),
         Err(e) => Err(e.into()),
     }
 }
 
 impl ToCss for Ranges {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         let mut iter = self.0.iter();
         if let Some(first) = iter.next() {
--- a/servo/components/style/custom_properties.rs
+++ b/servo/components/style/custom_properties.rs
@@ -247,17 +247,18 @@ fn parse_declaration_value<'i, 't>
 fn parse_declaration_value_block<'i, 't>
                                 (input: &mut Parser<'i, 't>,
                                  references: &mut Option<HashSet<Name>>,
                                  missing_closing_characters: &mut String)
                                  -> Result<(TokenSerializationType, TokenSerializationType),
                                            ParseError<'i>> {
     let mut token_start = input.position();
     let mut token = match input.next_including_whitespace_and_comments() {
-        Ok(token) => token,
+        // FIXME: remove clone() when borrows are non-lexical
+        Ok(token) => token.clone(),
         Err(_) => return Ok((TokenSerializationType::nothing(), TokenSerializationType::nothing()))
     };
     let first_token_type = token.serialization_type();
     loop {
         macro_rules! nested {
             () => {
                 input.parse_nested_block(|input| {
                     parse_declaration_value_block(input, references, missing_closing_characters)
@@ -346,27 +347,28 @@ fn parse_declaration_value_block<'i, 't>
             }
             _ => {
                 token.serialization_type()
             }
         };
 
         token_start = input.position();
         token = match input.next_including_whitespace_and_comments() {
-            Ok(token) => token,
+            // FIXME: remove clone() when borrows are non-lexical
+            Ok(token) => token.clone(),
             Err(..) => return Ok((first_token_type, last_token_type)),
         };
     }
 }
 
 // If the var function is valid, return Ok((custom_property_name, fallback))
 fn parse_var_function<'i, 't>(input: &mut Parser<'i, 't>,
                               references: &mut Option<HashSet<Name>>)
                               -> Result<(), ParseError<'i>> {
-    let name = input.expect_ident()?;
+    let name = input.expect_ident_cloned()?;
     let name: Result<_, ParseError> =
         parse_name(&name)
         .map_err(|()| SelectorParseError::UnexpectedIdent(name.clone()).into());
     let name = name?;
     if input.try(|input| input.expect_comma()).is_ok() {
         // Exclude `!` and `;` at the top level
         // https://drafts.csswg.org/css-syntax/#typedef-declaration-value
         input.parse_until_before(Delimiter::Bang | Delimiter::Semicolon, |input| {
@@ -592,17 +594,18 @@ fn substitute_block<'i, 't, F>(input: &m
                                partial_computed_value: &mut ComputedValue,
                                substitute_one: &mut F)
                                -> Result<TokenSerializationType, ParseError<'i>>
                        where F: FnMut(&Name, &mut ComputedValue) -> Result<TokenSerializationType, ()> {
     let mut last_token_type = TokenSerializationType::nothing();
     let mut set_position_at_next_iteration = false;
     loop {
         let before_this_token = input.position();
-        let next = input.next_including_whitespace_and_comments();
+        // FIXME: remove clone() when borrows are non-lexical
+        let next = input.next_including_whitespace_and_comments().map(|t| t.clone());
         if set_position_at_next_iteration {
             *position = (before_this_token, match next {
                 Ok(ref token) => token.serialization_type(),
                 Err(_) => TokenSerializationType::nothing(),
             });
             set_position_at_next_iteration = false;
         }
         let token = match next {
@@ -610,17 +613,17 @@ fn substitute_block<'i, 't, F>(input: &m
             Err(..) => break,
         };
         match token {
             Token::Function(ref name) if name.eq_ignore_ascii_case("var") => {
                 partial_computed_value.push(
                     input.slice(position.0..before_this_token), position.1, last_token_type);
                 input.parse_nested_block(|input| {
                     // parse_var_function() ensures neither .unwrap() will fail.
-                    let name = input.expect_ident().unwrap();
+                    let name = input.expect_ident_cloned().unwrap();
                     let name = Atom::from(parse_name(&name).unwrap());
 
                     if let Ok(last) = substitute_one(&name, partial_computed_value) {
                         last_token_type = last;
                         // Skip over the fallback, as `parse_nested_block` would return `Err`
                         // if we don’t consume all of `input`.
                         // FIXME: Add a specialized method to cssparser to do this with less work.
                         while let Ok(_) = input.next() {}
--- a/servo/components/style/font_face.rs
+++ b/servo/components/style/font_face.rs
@@ -7,17 +7,17 @@
 //! [ff]: https://drafts.csswg.org/css-fonts/#at-font-face-rule
 
 #![deny(missing_docs)]
 
 #[cfg(feature = "gecko")]
 use computed_values::{font_feature_settings, font_stretch, font_style, font_weight};
 use computed_values::font_family::FamilyName;
 use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
-use cssparser::{SourceLocation, CompactCowStr};
+use cssparser::{SourceLocation, CowRcStr};
 use error_reporting::ContextualParseError;
 #[cfg(feature = "gecko")] use gecko_bindings::structs::CSSFontFaceDescriptors;
 #[cfg(feature = "gecko")] use cssparser::UnicodeRange;
 use parser::{ParserContext, log_css_error, Parse};
 #[cfg(feature = "gecko")]
 use properties::longhands::font_language_override;
 use selectors::parser::SelectorParseError;
 use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
@@ -192,17 +192,17 @@ impl Parse for Source {
         }
 
         let url = SpecifiedUrl::parse(context, input)?;
 
         // Parsing optional format()
         let format_hints = if input.try(|input| input.expect_function_matching("format")).is_ok() {
             input.parse_nested_block(|input| {
                 input.parse_comma_separated(|input| {
-                    Ok(input.expect_string()?.into_owned())
+                    Ok(input.expect_string()?.as_ref().to_owned())
                 })
             })?
         } else {
             vec![]
         };
 
         Ok(Source::Url(UrlSource {
             url: url,
@@ -270,17 +270,17 @@ macro_rules! font_face_descriptors_commo
                 dest.write_str("}")
             }
         }
 
        impl<'a, 'b, 'i> DeclarationParser<'i> for FontFaceRuleParser<'a, 'b> {
            type Declaration = ();
            type Error = SelectorParseError<'i, StyleParseError<'i>>;
 
-           fn parse_value<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>)
+           fn parse_value<'t>(&mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't>)
                               -> Result<(), ParseError<'i>> {
                 match_ignore_ascii_case! { &*name,
                     $(
                         $name => {
                             // DeclarationParser also calls parse_entirely
                             // so we’d normally not need to,
                             // but in this case we do because we set the value as a side effect
                             // rather than returning it.
--- a/servo/components/style/gecko/media_queries.rs
+++ b/servo/components/style/gecko/media_queries.rs
@@ -235,33 +235,33 @@ impl Resolution {
         match *self {
             Resolution::Dpi(f) => f,
             Resolution::Dppx(f) => f * 96.0,
             Resolution::Dpcm(f) => f * 2.54,
         }
     }
 
     fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
-        let (value, unit) = match input.next()? {
-            Token::Dimension { value, unit, .. } => {
+        let (value, unit) = match *input.next()? {
+            Token::Dimension { value, ref unit, .. } => {
                 (value, unit)
             },
-            t => return Err(BasicParseError::UnexpectedToken(t).into()),
+            ref t => return Err(BasicParseError::UnexpectedToken(t.clone()).into()),
         };
 
         if value <= 0. {
             return Err(StyleParseError::UnspecifiedError.into())
         }
 
         (match_ignore_ascii_case! { &unit,
             "dpi" => Ok(Resolution::Dpi(value)),
             "dppx" => Ok(Resolution::Dppx(value)),
             "dpcm" => Ok(Resolution::Dpcm(value)),
             _ => Err(())
-        }).map_err(|()| StyleParseError::UnexpectedDimension(unit).into())
+        }).map_err(|()| StyleParseError::UnexpectedDimension(unit.clone()).into())
     }
 }
 
 impl ToCss for Resolution {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result
         where W: fmt::Write,
     {
         match *self {
@@ -469,57 +469,65 @@ impl Expression {
     ///
     /// ```
     /// (media-feature: media-value)
     /// ```
     pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<Self, ParseError<'i>> {
         input.expect_parenthesis_block()?;
         input.parse_nested_block(|input| {
-            let ident = input.expect_ident()?;
+            // FIXME: remove extra indented block when lifetimes are non-lexical
+            let feature;
+            let range;
+            {
+                let ident = input.expect_ident()?;
+
+                let mut flags = 0;
+                let result = {
+                    let mut feature_name = &**ident;
+
+                    // TODO(emilio): this is under a pref in Gecko.
+                    if starts_with_ignore_ascii_case(feature_name, "-webkit-") {
+                        feature_name = &feature_name[8..];
+                        flags |= nsMediaFeature_RequirementFlags::eHasWebkitPrefix as u8;
+                    }
 
-            let mut flags = 0;
-            let result = {
-                let mut feature_name = &*ident;
+                    let range = if starts_with_ignore_ascii_case(feature_name, "min-") {
+                        feature_name = &feature_name[4..];
+                        nsMediaExpression_Range::eMin
+                    } else if starts_with_ignore_ascii_case(feature_name, "max-") {
+                        feature_name = &feature_name[4..];
+                        nsMediaExpression_Range::eMax
+                    } else {
+                        nsMediaExpression_Range::eEqual
+                    };
 
-                // TODO(emilio): this is under a pref in Gecko.
-                if starts_with_ignore_ascii_case(feature_name, "-webkit-") {
-                    feature_name = &feature_name[8..];
-                    flags |= nsMediaFeature_RequirementFlags::eHasWebkitPrefix as u8;
+                    let atom = Atom::from(feature_name);
+                    match find_feature(|f| atom.as_ptr() == unsafe { *f.mName }) {
+                        Some(f) => Ok((f, range)),
+                        None => Err(()),
+                    }
+                };
+
+                match result {
+                    Ok((f, r)) => {
+                        feature = f;
+                        range = r;
+                    }
+                    Err(()) => return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()),
                 }
 
-                let range = if starts_with_ignore_ascii_case(feature_name, "min-") {
-                    feature_name = &feature_name[4..];
-                    nsMediaExpression_Range::eMin
-                } else if starts_with_ignore_ascii_case(feature_name, "max-") {
-                    feature_name = &feature_name[4..];
-                    nsMediaExpression_Range::eMax
-                } else {
-                    nsMediaExpression_Range::eEqual
-                };
-
-                let atom = Atom::from(feature_name);
-                match find_feature(|f| atom.as_ptr() == unsafe { *f.mName }) {
-                    Some(f) => Ok((f, range)),
-                    None => Err(()),
+                if (feature.mReqFlags & !flags) != 0 {
+                    return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into());
                 }
-            };
 
-            let (feature, range) = match result {
-                Ok((feature, range)) => (feature, range),
-                Err(()) => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
-            };
-
-            if (feature.mReqFlags & !flags) != 0 {
-                return Err(SelectorParseError::UnexpectedIdent(ident).into());
-            }
-
-            if range != nsMediaExpression_Range::eEqual &&
-                feature.mRangeType != nsMediaFeature_RangeType::eMinMaxAllowed {
-                return Err(SelectorParseError::UnexpectedIdent(ident).into());
+                if range != nsMediaExpression_Range::eEqual &&
+                    feature.mRangeType != nsMediaFeature_RangeType::eMinMaxAllowed {
+                    return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into());
+                }
             }
 
             // If there's no colon, this is a media query of the form
             // '(<feature>)', that is, there's no value specified.
             //
             // Gecko doesn't allow ranged expressions without a value, so just
             // reject them here too.
             if input.try(|i| i.expect_colon()).is_err() {
@@ -585,17 +593,17 @@ impl Expression {
                                 value
                             }
                             None => return Err(StyleParseError::UnspecifiedError.into()),
                         };
 
                     MediaExpressionValue::Enumerated(value)
                 }
                 nsMediaFeature_ValueType::eIdent => {
-                    MediaExpressionValue::Ident(input.expect_ident()?.into_owned())
+                    MediaExpressionValue::Ident(input.expect_ident()?.as_ref().to_owned())
                 }
             };
 
             Ok(Expression::new(feature, Some(value), range))
         })
     }
 
     /// Returns whether this media query evaluates to true for the given device.
--- a/servo/components/style/gecko/selector_parser.rs
+++ b/servo/components/style/gecko/selector_parser.rs
@@ -1,15 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Gecko-specific bits for selector-parsing.
 
-use cssparser::{BasicParseError, Parser, ToCss, Token, CompactCowStr};
+use cssparser::{BasicParseError, Parser, ToCss, Token, CowRcStr};
 use element_state::ElementState;
 use gecko_bindings::structs::CSSPseudoClassType;
 use selector_parser::{SelectorParser, PseudoElementCascadeType};
 use selectors::parser::{Selector, SelectorMethods, SelectorParseError};
 use selectors::visitor::SelectorVisitor;
 use std::fmt;
 use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
 use style_traits::{ParseError, StyleParseError};
@@ -262,22 +262,22 @@ impl ::selectors::SelectorImpl for Selec
                                 NonTSPseudoClass::Hover)
     }
 }
 
 impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
     type Impl = SelectorImpl;
     type Error = StyleParseError<'i>;
 
-    fn is_pseudo_element_allows_single_colon(name: &CompactCowStr<'i>) -> bool {
+    fn is_pseudo_element_allows_single_colon(name: &CowRcStr<'i>) -> bool {
         ::selectors::parser::is_css2_pseudo_element(name) ||
             name.starts_with("-moz-tree-") // tree pseudo-elements
     }
 
-    fn parse_non_ts_pseudo_class(&self, name: CompactCowStr<'i>)
+    fn parse_non_ts_pseudo_class(&self, name: CowRcStr<'i>)
                                  -> Result<NonTSPseudoClass, ParseError<'i>> {
         macro_rules! pseudo_class_parse {
             (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
              string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*],
              keyword: [$(($k_css:expr, $k_name:ident, $k_gecko_type:tt, $k_state:tt, $k_flags:tt),)*]) => {
                 match_ignore_ascii_case! { &name,
                     $($css => NonTSPseudoClass::$name,)*
                     _ => return Err(::selectors::parser::SelectorParseError::UnexpectedIdent(
@@ -289,17 +289,17 @@ impl<'a, 'i> ::selectors::Parser<'i> for
         if !pseudo_class.is_internal() || self.in_user_agent_stylesheet() {
             Ok(pseudo_class)
         } else {
             Err(SelectorParseError::UnexpectedIdent(name).into())
         }
     }
 
     fn parse_non_ts_functional_pseudo_class<'t>(&self,
-                                                name: CompactCowStr<'i>,
+                                                name: CowRcStr<'i>,
                                                 parser: &mut Parser<'i, 't>)
                                                 -> Result<NonTSPseudoClass, ParseError<'i>> {
         macro_rules! pseudo_class_string_parse {
             (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
              string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*],
              keyword: [$(($k_css:expr, $k_name:ident, $k_gecko_type:tt, $k_state:tt, $k_flags:tt),)*]) => {
                 match_ignore_ascii_case! { &name,
                     $($s_css => {
@@ -333,33 +333,33 @@ impl<'a, 'i> ::selectors::Parser<'i> for
         let pseudo_class = apply_non_ts_list!(pseudo_class_string_parse);
         if !pseudo_class.is_internal() || self.in_user_agent_stylesheet() {
             Ok(pseudo_class)
         } else {
             Err(SelectorParseError::UnexpectedIdent(name).into())
         }
     }
 
-    fn parse_pseudo_element(&self, name: CompactCowStr<'i>) -> Result<PseudoElement, ParseError<'i>> {
+    fn parse_pseudo_element(&self, name: CowRcStr<'i>) -> Result<PseudoElement, ParseError<'i>> {
         PseudoElement::from_slice(&name, self.in_user_agent_stylesheet())
             .ok_or(SelectorParseError::UnexpectedIdent(name.clone()).into())
     }
 
-    fn parse_functional_pseudo_element<'t>(&self, name: CompactCowStr<'i>,
+    fn parse_functional_pseudo_element<'t>(&self, name: CowRcStr<'i>,
                                            parser: &mut Parser<'i, 't>)
                                            -> Result<PseudoElement, ParseError<'i>> {
         if name.starts_with("-moz-tree-") {
             // Tree pseudo-elements can have zero or more arguments,
             // separated by either comma or space.
             let mut args = Vec::new();
             loop {
                 match parser.next() {
-                    Ok(Token::Ident(ident)) => args.push(ident.into_owned()),
-                    Ok(Token::Comma) => {},
-                    Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()),
+                    Ok(&Token::Ident(ref ident)) => args.push(ident.as_ref().to_owned()),
+                    Ok(&Token::Comma) => {},
+                    Ok(t) => return Err(BasicParseError::UnexpectedToken(t.clone()).into()),
                     Err(BasicParseError::EndOfInput) => break,
                     _ => unreachable!("Parser::next() shouldn't return any other error"),
                 }
             }
             let args = args.into_boxed_slice();
             if let Some(pseudo) = PseudoElement::tree_pseudo_element(&name, args) {
                 return Ok(pseudo);
             }
--- a/servo/components/style/gecko_string_cache/namespace.rs
+++ b/servo/components/style/gecko_string_cache/namespace.rs
@@ -1,17 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! A type to represent a namespace.
 
 use gecko_bindings::structs::nsIAtom;
 use precomputed_hash::PrecomputedHash;
-use std::borrow::{Borrow, Cow};
+use std::borrow::Borrow;
 use std::fmt;
 use std::ops::Deref;
 use string_cache::{Atom, WeakAtom};
 
 #[macro_export]
 macro_rules! ns {
     () => { $crate::string_cache::Namespace(atom!("")) };
     ($s: tt) => { $crate::string_cache::Namespace(atom!($s)) };
@@ -49,18 +49,18 @@ impl Deref for Namespace {
     fn deref(&self) -> &WeakNamespace {
         let weak: *const WeakAtom = &*self.0;
         unsafe {
             &*(weak as *const WeakNamespace)
         }
     }
 }
 
-impl<'a> From<Cow<'a, str>> for Namespace {
-    fn from(s: Cow<'a, str>) -> Self {
+impl<'a> From<&'a str> for Namespace {
+    fn from(s: &'a str) -> Self {
         Namespace(Atom::from(s))
     }
 }
 
 impl fmt::Display for Namespace {
     fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
         self.0.fmt(w)
     }
--- a/servo/components/style/macros.rs
+++ b/servo/components/style/macros.rs
@@ -12,17 +12,17 @@
 macro_rules! try_match_ident_ignore_ascii_case {
     ($ident:expr, $( $match_body:tt )*) => {
         let __ident = $ident;
         (match_ignore_ascii_case! { &*__ident,
             $( $match_body )*
             _ => Err(()),
         })
         .map_err(|()| {
-            ::selectors::parser::SelectorParseError::UnexpectedIdent(__ident).into()
+            ::selectors::parser::SelectorParseError::UnexpectedIdent(__ident.clone()).into()
         })
     }
 }
 
 macro_rules! define_numbered_css_keyword_enum {
     ($name: ident: $( $css: expr => $variant: ident = $value: expr ),+,) => {
         define_numbered_css_keyword_enum!($name: $( $css => $variant = $value ),+);
     };
--- a/servo/components/style/media_queries.rs
+++ b/servo/components/style/media_queries.rs
@@ -206,20 +206,20 @@ impl MediaQuery {
         let qualifier = if input.try(|input| input.expect_ident_matching("only")).is_ok() {
             Some(Qualifier::Only)
         } else if input.try(|input| input.expect_ident_matching("not")).is_ok() {
             Some(Qualifier::Not)
         } else {
             None
         };
 
-        let media_type = match input.try(|input| input.expect_ident()) {
+        let media_type = match input.try(|i| i.expect_ident_cloned()) {
             Ok(ident) => {
                 let result: Result<_, ParseError> = MediaQueryType::parse(&*ident)
-                    .map_err(|()| SelectorParseError::UnexpectedIdent(ident).into());
+                    .map_err(|()| SelectorParseError::UnexpectedIdent(ident.clone()).into());
                 result?
             }
             Err(_) => {
                 // Media type is only optional if qualifier is not specified.
                 if qualifier.is_some() {
                     return Err(StyleParseError::UnspecifiedError.into())
                 }
 
@@ -258,17 +258,17 @@ pub fn parse_media_query_list(context: &
                 media_queries.push(mq);
             },
             Err(..) => {
                 media_queries.push(MediaQuery::never_matching());
             },
         }
 
         match input.next() {
-            Ok(Token::Comma) => {},
+            Ok(&Token::Comma) => {},
             Ok(_) => unreachable!(),
             Err(_) => break,
         }
     }
 
     MediaList {
         media_queries: media_queries,
     }
--- a/servo/components/style/properties/declaration_block.rs
+++ b/servo/components/style/properties/declaration_block.rs
@@ -2,17 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! A property declaration block.
 
 #![deny(missing_docs)]
 
 use context::QuirksMode;
-use cssparser::{DeclarationListParser, parse_important, ParserInput, CompactCowStr};
+use cssparser::{DeclarationListParser, parse_important, ParserInput, CowRcStr};
 use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter, ParseError as CssParseError};
 use error_reporting::{ParseErrorReporter, ContextualParseError};
 use parser::{ParserContext, log_css_error};
 use properties::animated_properties::AnimationValue;
 use selectors::parser::SelectorParseError;
 use shared_lock::Locked;
 use smallvec::SmallVec;
 use std::fmt;
@@ -940,17 +940,17 @@ fn is_non_mozilla_vendor_identifier(name
     (name.starts_with("-") && !name.starts_with("-moz-")) ||
         name.starts_with("_")
 }
 
 impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b> {
     type Declaration = Importance;
     type Error = SelectorParseError<'i, StyleParseError<'i>>;
 
-    fn parse_value<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>)
+    fn parse_value<'t>(&mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't>)
                        -> Result<Importance, ParseError<'i>> {
         let id = match PropertyId::parse(&name) {
             Ok(id) => id,
             Err(()) => {
                 return Err(if is_non_mozilla_vendor_identifier(&name) {
                     PropertyDeclarationParseError::UnknownVendorProperty
                 } else {
                     PropertyDeclarationParseError::UnknownProperty(name)
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -2803,17 +2803,17 @@ fn static_assert() {
     pub fn animation_name_at(&self, index: usize)
         -> longhands::animation_name::computed_value::SingleComputedValue {
         use properties::longhands::animation_name::single_value::SpecifiedValue as AnimationName;
         // XXX: Is there any effective ways?
         let atom = &self.gecko.mAnimations[index].mName;
         if atom.is_empty() {
             AnimationName(None)
         } else {
-            AnimationName(Some(KeyframesName::from_ident(atom.to_string())))
+            AnimationName(Some(KeyframesName::from_ident(&atom.to_string())))
         }
     }
     pub fn copy_animation_name_from(&mut self, other: &Self) {
         unsafe { self.gecko.mAnimations.ensure_len(other.gecko.mAnimations.len()) };
 
         let count = other.gecko.mAnimationNameCount;
         self.gecko.mAnimationNameCount = count;
 
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -281,17 +281,17 @@ impl TransitionProperty {
             % endfor
             "none" => Err(()),
             _ => Ok(None),
         };
 
         match supported {
             Ok(Some(property)) => Ok(property),
             Ok(None) => CustomIdent::from_ident(ident, &[]).map(TransitionProperty::Unsupported),
-            Err(()) => Err(SelectorParseError::UnexpectedIdent(ident).into()),
+            Err(()) => Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()),
         }
     }
 
     /// Return transitionable longhands of this shorthand TransitionProperty, except for "all".
     pub fn longhands(&self) -> &'static [TransitionProperty] {
         % for prop in data.shorthands_except_all():
             % if prop.transitionable:
                 static ${prop.ident.upper()}: &'static [TransitionProperty] = &[
--- a/servo/components/style/properties/longhand/background.mako.rs
+++ b/servo/components/style/properties/longhand/background.mako.rs
@@ -117,24 +117,24 @@
                 (RepeatKeyword::NoRepeat, RepeatKeyword::Repeat) => SpecifiedValue::RepeatY,
                 (horizontal, vertical) => SpecifiedValue::Other(horizontal, Some(vertical)),
             }
         }
     }
 
     pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<SpecifiedValue, ParseError<'i>> {
-        let ident = input.expect_ident()?;
+        let ident = input.expect_ident_cloned()?;
         (match_ignore_ascii_case! { &ident,
             "repeat-x" => Ok(SpecifiedValue::RepeatX),
             "repeat-y" => Ok(SpecifiedValue::RepeatY),
             _ => Err(()),
         }).or_else(|()| {
             let horizontal: Result<_, ParseError> = RepeatKeyword::from_ident(&ident)
-                .map_err(|()| SelectorParseError::UnexpectedIdent(ident).into());
+                .map_err(|()| SelectorParseError::UnexpectedIdent(ident.clone()).into());
             let horizontal = horizontal?;
             let vertical = input.try(RepeatKeyword::parse).ok();
             Ok(SpecifiedValue::Other(horizontal, vertical))
         })
     }
 </%helpers:vector_longhand>
 
 ${helpers.single_keyword("background-attachment",
--- a/servo/components/style/properties/longhand/box.mako.rs
+++ b/servo/components/style/properties/longhand/box.mako.rs
@@ -1020,17 +1020,17 @@
     ) -> Result<SpecifiedValue,ParseError<'i>> {
         use style_traits::{Separator, Space};
 
         if input.try(|input| input.expect_ident_matching("none")).is_ok() {
             return Ok(SpecifiedValue(Vec::new()))
         }
 
         Ok(SpecifiedValue(Space::parse(input, |input| {
-            let function = input.expect_function()?;
+            let function = input.expect_function()?.clone();
             input.parse_nested_block(|input| {
                 let result = match_ignore_ascii_case! { &function,
                     "matrix" => {
                         let a = specified::parse_number(context, input)?;
                         input.expect_comma()?;
                         let b = specified::parse_number(context, input)?;
                         input.expect_comma()?;
                         let c = specified::parse_number(context, input)?;
@@ -1212,17 +1212,17 @@
                     },
                     "perspective" => {
                         let d = specified::Length::parse_non_negative(context, input)?;
                         Ok(SpecifiedOperation::Perspective(d))
                     },
                     _ => Err(()),
                 };
                 result
-                    .map_err(|()| StyleParseError::UnexpectedFunction(function).into())
+                    .map_err(|()| StyleParseError::UnexpectedFunction(function.clone()).into())
             })
         })?))
     }
 
     /// Parses `transform` property.
     #[inline]
     pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<SpecifiedValue,ParseError<'i>> {
@@ -1759,26 +1759,26 @@
         if input.try(|input| input.expect_ident_matching("none")).is_ok() {
             return Ok(result)
         }
         if input.try(|input| input.expect_ident_matching("strict")).is_ok() {
             result.insert(STRICT | STRICT_BITS);
             return Ok(result)
         }
 
-        while let Ok(name) = input.try(|input| input.expect_ident()) {
+        while let Ok(name) = input.try(|i| i.expect_ident_cloned()) {
             let flag = match_ignore_ascii_case! { &name,
                 "layout" => Some(LAYOUT),
                 "style" => Some(STYLE),
                 "paint" => Some(PAINT),
                 _ => None
             };
             let flag = match flag {
                 Some(flag) if !result.contains(flag) => flag,
-                _ => return Err(SelectorParseError::UnexpectedIdent(name).into())
+                _ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
             };
             result.insert(flag);
         }
 
         if !result.is_empty() {
             Ok(result)
         } else {
             Err(StyleParseError::UnspecifiedError.into())
@@ -1955,17 +1955,18 @@
 
     #[inline]
     pub fn get_initial_value() -> computed_value::T {
         TOUCH_ACTION_AUTO
     }
 
     pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<SpecifiedValue, ParseError<'i>> {
-        try_match_ident_ignore_ascii_case! { input.expect_ident()?,
+        // FIXME: remove clone() when lifetimes are non-lexical
+        try_match_ident_ignore_ascii_case! { input.expect_ident()?.clone(),
             "auto" => Ok(TOUCH_ACTION_AUTO),
             "none" => Ok(TOUCH_ACTION_NONE),
             "manipulation" => Ok(TOUCH_ACTION_MANIPULATION),
             "pan-x" => {
                 if input.try(|i| i.expect_ident_matching("pan-y")).is_ok() {
                     Ok(TOUCH_ACTION_PAN_X | TOUCH_ACTION_PAN_Y)
                 } else {
                     Ok(TOUCH_ACTION_PAN_X)
--- a/servo/components/style/properties/longhand/color.mako.rs
+++ b/servo/components/style/properties/longhand/color.mako.rs
@@ -129,14 +129,14 @@
                         % endfor
                     }
                 }
 
                 let ident = input.expect_ident()?;
                 if let Some(color) = color_name(&ident) {
                     Ok(*color)
                 } else {
-                    Err(SelectorParseError::UnexpectedIdent(ident).into())
+                    Err(SelectorParseError::UnexpectedIdent(ident.clone()).into())
                 }
             }
         }
     % endif
 </%helpers:longhand>
--- a/servo/components/style/properties/longhand/counters.mako.rs
+++ b/servo/components/style/properties/longhand/counters.mako.rs
@@ -174,57 +174,58 @@
         loop {
             % if product == "gecko":
                 if let Ok(mut url) = input.try(|i| SpecifiedUrl::parse(context, i)) {
                     url.build_image_value();
                     content.push(ContentItem::Url(url));
                     continue;
                 }
             % endif
-            match input.next() {
-                Ok(Token::QuotedString(value)) => {
-                    content.push(ContentItem::String(value.into_owned()))
+            // FIXME: remove clone() when lifetimes are non-lexical
+            match input.next().map(|t| t.clone()) {
+                Ok(Token::QuotedString(ref value)) => {
+                    content.push(ContentItem::String(value.as_ref().to_owned()))
                 }
-                Ok(Token::Function(name)) => {
+                Ok(Token::Function(ref name)) => {
                     let result = match_ignore_ascii_case! { &name,
                         "counter" => Some(input.parse_nested_block(|input| {
-                            let name = input.expect_ident()?.into_owned();
+                            let name = input.expect_ident()?.as_ref().to_owned();
                             let style = parse_counter_style(context, input);
                             Ok(ContentItem::Counter(name, style))
                         })),
                         "counters" => Some(input.parse_nested_block(|input| {
-                            let name = input.expect_ident()?.into_owned();
+                            let name = input.expect_ident()?.as_ref().to_owned();
                             input.expect_comma()?;
-                            let separator = input.expect_string()?.into_owned();
+                            let separator = input.expect_string()?.as_ref().to_owned();
                             let style = parse_counter_style(context, input);
                             Ok(ContentItem::Counters(name, separator, style))
                         })),
                         % if product == "gecko":
                             "attr" => Some(input.parse_nested_block(|input| {
                                 Ok(ContentItem::Attr(Attr::parse_function(context, input)?))
                             })),
                         % endif
                         _ => None
                     };
                     match result {
                         Some(result) => content.push(result?),
-                        None => return Err(StyleParseError::UnexpectedFunction(name).into())
+                        None => return Err(StyleParseError::UnexpectedFunction(name.clone()).into())
                     }
                 }
-                Ok(Token::Ident(ident)) => {
+                Ok(Token::Ident(ref ident)) => {
                     let valid = match_ignore_ascii_case! { &ident,
                         "open-quote" => { content.push(ContentItem::OpenQuote); true },
                         "close-quote" => { content.push(ContentItem::CloseQuote); true },
                         "no-open-quote" => { content.push(ContentItem::NoOpenQuote); true },
                         "no-close-quote" => { content.push(ContentItem::NoCloseQuote); true },
 
                         _ => false,
                     };
                     if !valid {
-                        return Err(SelectorParseError::UnexpectedIdent(ident).into())
+                        return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into())
                     }
                 }
                 Err(_) => break,
                 Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into())
             }
         }
         if content.is_empty() {
             return Err(StyleParseError::UnspecifiedError.into());
@@ -328,18 +329,18 @@
                                 -> Result<SpecifiedValue, ParseError<'i>> {
         if input.try(|input| input.expect_ident_matching("none")).is_ok() {
             return Ok(SpecifiedValue(Vec::new()))
         }
 
         let mut counters = Vec::new();
         loop {
             let counter_name = match input.next() {
-                Ok(Token::Ident(ident)) => CustomIdent::from_ident(ident, &["none"])?,
-                Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()),
+                Ok(&Token::Ident(ref ident)) => CustomIdent::from_ident(ident, &["none"])?,
+                Ok(t) => return Err(BasicParseError::UnexpectedToken(t.clone()).into()),
                 Err(_) => break,
             };
             let counter_delta = input.try(|input| specified::parse_integer(context, input))
                                      .unwrap_or(specified::Integer::new(default_value));
             counters.push((counter_name, counter_delta))
         }
 
         if !counters.is_empty() {
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.mako.rs
@@ -140,23 +140,23 @@ macro_rules! impl_gecko_keyword_conversi
                 FontFamily::FamilyName(FamilyName {
                     name: input,
                     quoted: true,
                 })
             }
 
             /// Parse a font-family value
             pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
-                if let Ok(value) = input.try(|input| input.expect_string()) {
+                if let Ok(value) = input.try(|i| i.expect_string_cloned()) {
                     return Ok(FontFamily::FamilyName(FamilyName {
                         name: Atom::from(&*value),
                         quoted: true,
                     }))
                 }
-                let first_ident = input.expect_ident()?;
+                let first_ident = input.expect_ident()?.clone();
 
                 // FIXME(bholley): The fast thing to do here would be to look up the
                 // string (as lowercase) in the static atoms table. We don't have an
                 // API to do that yet though, so we do the simple thing for now.
                 let mut css_wide_keyword = false;
                 match_ignore_ascii_case! { &first_ident,
                     "serif" => return Ok(FontFamily::Generic(atom!("serif"))),
                     "sans-serif" => return Ok(FontFamily::Generic(atom!("sans-serif"))),
@@ -176,25 +176,25 @@ macro_rules! impl_gecko_keyword_conversi
                     //  UAs must not consider these keywords as matching the <family-name> type."
                     "inherit" => css_wide_keyword = true,
                     "initial" => css_wide_keyword = true,
                     "unset" => css_wide_keyword = true,
                     "default" => css_wide_keyword = true,
                     _ => {}
                 }
 
-                let mut value = first_ident.into_owned();
+                let mut value = first_ident.as_ref().to_owned();
                 // These keywords are not allowed by themselves.
                 // The only way this value can be valid with with another keyword.
                 if css_wide_keyword {
                     let ident = input.expect_ident()?;
                     value.push_str(" ");
                     value.push_str(&ident);
                 }
-                while let Ok(ident) = input.try(|input| input.expect_ident()) {
+                while let Ok(ident) = input.try(|i| i.expect_ident_cloned()) {
                     value.push_str(" ");
                     value.push_str(&ident);
                 }
                 Ok(FontFamily::FamilyName(FamilyName {
                     name: Atom::from(value),
                     quoted: false,
                 }))
             }
@@ -1184,17 +1184,18 @@ macro_rules! impl_gecko_keyword_conversi
     #[inline]
     pub fn get_initial_value() -> computed_value::T {
         SpecifiedValue { weight: true, style: true }
     }
 
     pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<SpecifiedValue, ParseError<'i>> {
         let mut result = SpecifiedValue { weight: false, style: false };
-        try_match_ident_ignore_ascii_case! { input.expect_ident()?,
+        // FIXME: remove clone() when lifetimes are non-lexical
+        try_match_ident_ignore_ascii_case! { input.expect_ident()?.clone(),
             "none" => Ok(result),
             "weight" => {
                 result.weight = true;
                 if input.try(|input| input.expect_ident_matching("style")).is_ok() {
                     result.style = true;
                 }
                 Ok(result)
             },
@@ -1406,27 +1407,28 @@ macro_rules! impl_gecko_keyword_conversi
             ($flag:ident) => (
                 if parsed_alternates.contains($flag) {
                     return Err(StyleParseError::UnspecifiedError.into())
                 }
                 parsed_alternates |= $flag;
             )
         );
         while let Ok(_) = input.try(|input| {
-            match input.next()? {
-                Token::Ident(ident) => {
-                    if ident == "historical-forms" {
+            // FIXME: remove clone() when lifetimes are non-lexical
+            match input.next()?.clone() {
+                Token::Ident(ref ident) => {
+                    if *ident == "historical-forms" {
                         check_if_parsed!(HISTORICAL_FORMS);
                         alternates.push(VariantAlternates::HistoricalForms);
                         Ok(())
                     } else {
                         return Err(StyleParseError::UnspecifiedError.into());
                     }
                 },
-                Token::Function(name) => {
+                Token::Function(ref name) => {
                     input.parse_nested_block(|i| {
                         match_ignore_ascii_case! { &name,
                             % for value in "swash stylistic ornaments annotation".split():
                             "${value}" => {
                                 check_if_parsed!(${value.upper()});
                                 let ident = CustomIdent::from_ident(i.expect_ident()?, &[])?;
                                 alternates.push(VariantAlternates::${to_camel_case(value)}(ident));
                                 Ok(())
@@ -2131,18 +2133,18 @@ https://drafts.csswg.org/css-fonts-4/#lo
     }
 
     /// normal | <string>
     pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<SpecifiedValue, ParseError<'i>> {
         if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
             Ok(SpecifiedValue::Normal)
         } else {
-            input.expect_string().map(|cow| {
-                SpecifiedValue::Override(cow.into_owned())
+            input.expect_string().map(|s| {
+                SpecifiedValue::Override(s.as_ref().to_owned())
             }).map_err(|e| e.into())
         }
     }
 
     /// Used in @font-face.
     impl Parse for SpecifiedValue {
         fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<Self, ParseError<'i>> {
--- a/servo/components/style/properties/longhand/inherited_text.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_text.mako.rs
@@ -585,19 +585,19 @@
     }
 
     pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<SpecifiedValue, ParseError<'i>> {
         if input.try(|input| input.expect_ident_matching("none")).is_ok() {
             return Ok(SpecifiedValue::None);
         }
 
-        if let Ok(s) = input.try(|input| input.expect_string()) {
+        if let Ok(s) = input.try(|i| i.expect_string().map(|s| s.as_ref().to_owned())) {
             // Handle <string>
-            return Ok(SpecifiedValue::String(s.into_owned()));
+            return Ok(SpecifiedValue::String(s));
         }
 
         // Handle a pair of keywords
         let mut shape = input.try(ShapeKeyword::parse);
         let fill = if input.try(|input| input.expect_ident_matching("filled")).is_ok() {
             Some(true)
         } else if input.try(|input| input.expect_ident_matching("open")).is_ok() {
             Some(false)
--- a/servo/components/style/properties/longhand/list.mako.rs
+++ b/servo/components/style/properties/longhand/list.mako.rs
@@ -89,17 +89,17 @@
             SpecifiedValue::CounterStyle(CounterStyleOrNone::disc())
         }
 
         pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                              -> Result<SpecifiedValue, ParseError<'i>> {
             Ok(if let Ok(style) = input.try(|i| CounterStyleOrNone::parse(context, i)) {
                 SpecifiedValue::CounterStyle(style)
             } else {
-                SpecifiedValue::String(input.expect_string()?.into_owned())
+                SpecifiedValue::String(input.expect_string()?.as_ref().to_owned())
             })
         }
     </%helpers:longhand>
 % endif
 
 <%helpers:longhand name="list-style-image" animation_value_type="discrete"
                    boxed="${product == 'gecko'}"
                    spec="https://drafts.csswg.org/css-lists/#propdef-list-style-image">
@@ -192,23 +192,23 @@
                          -> Result<SpecifiedValue,ParseError<'i>> {
         if input.try(|input| input.expect_ident_matching("none")).is_ok() {
             return Ok(SpecifiedValue(Vec::new()))
         }
 
         let mut quotes = Vec::new();
         loop {
             let first = match input.next() {
-                Ok(Token::QuotedString(value)) => value.into_owned(),
-                Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()),
+                Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned(),
+                Ok(t) => return Err(BasicParseError::UnexpectedToken(t.clone()).into()),
                 Err(_) => break,
             };
             let second = match input.next() {
-                Ok(Token::QuotedString(value)) => value.into_owned(),
-                Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()),
+                Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned(),
+                Ok(t) => return Err(BasicParseError::UnexpectedToken(t.clone()).into()),
                 Err(e) => return Err(e.into()),
             };
             quotes.push((first, second))
         }
         if !quotes.is_empty() {
             Ok(SpecifiedValue(quotes))
         } else {
             Err(StyleParseError::UnspecifiedError.into())
--- a/servo/components/style/properties/longhand/pointing.mako.rs
+++ b/servo/components/style/properties/longhand/pointing.mako.rs
@@ -96,17 +96,17 @@
             use std::ascii::AsciiExt;
             use style_traits::cursor::Cursor;
             let ident = input.expect_ident()?;
             if ident.eq_ignore_ascii_case("auto") {
                 Ok(computed_value::Keyword::Auto)
             } else {
                 Cursor::from_css_keyword(&ident)
                     .map(computed_value::Keyword::Cursor)
-                    .map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+                    .map_err(|()| SelectorParseError::UnexpectedIdent(ident.clone()).into())
             }
         }
     }
 
     #[cfg(feature = "gecko")]
     fn parse_image<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                            -> Result<computed_value::Image, ParseError<'i>> {
         Ok(computed_value::Image {
--- a/servo/components/style/properties/longhand/position.mako.rs
+++ b/servo/components/style/properties/longhand/position.mako.rs
@@ -356,17 +356,17 @@ macro_rules! impl_align_conversions {
                 },
                 "dense" if !dense => {
                     dense = true;
                     true
                 },
                 _ => false
             };
             if !success {
-                return Err(SelectorParseError::UnexpectedIdent(ident).into());
+                return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into());
             }
         }
 
         if value.is_some() || dense {
             Ok(computed_value::T {
                 autoflow: value.unwrap_or(AutoFlow::Row),
                 dense: dense,
             })
@@ -458,18 +458,18 @@ macro_rules! impl_align_conversions {
 
     no_viewport_percentage!(TemplateAreas);
     impl ComputedValueAsSpecified for TemplateAreas {}
 
     impl Parse for TemplateAreas {
         fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<Self, ParseError<'i>> {
             let mut strings = vec![];
-            while let Ok(string) = input.try(Parser::expect_string) {
-                strings.push(string.into_owned().into_boxed_str());
+            while let Ok(string) = input.try(|i| i.expect_string().map(|s| s.as_ref().into())) {
+                strings.push(string);
             }
 
             TemplateAreas::from_vec(strings)
                 .map_err(|()| StyleParseError::UnspecifiedError.into())
         }
     }
 
     impl TemplateAreas {
--- a/servo/components/style/properties/longhand/text.mako.rs
+++ b/servo/components/style/properties/longhand/text.mako.rs
@@ -112,27 +112,27 @@
         Ok(SpecifiedValue {
             first: first,
             second: second,
         })
     }
     impl Parse for Side {
         fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<Side, ParseError<'i>> {
-            match input.next()? {
-                Token::Ident(ident) => {
+            match *input.next()? {
+                Token::Ident(ref ident) => {
                     try_match_ident_ignore_ascii_case! { ident,
                         "clip" => Ok(Side::Clip),
                         "ellipsis" => Ok(Side::Ellipsis),
                     }
                 }
-                Token::QuotedString(v) => {
-                    Ok(Side::String(v.into_owned().into_boxed_str()))
+                Token::QuotedString(ref v) => {
+                    Ok(Side::String(v.as_ref().to_owned().into_boxed_str()))
                 }
-                other => Err(BasicParseError::UnexpectedToken(other).into()),
+                ref t => Err(BasicParseError::UnexpectedToken(t.clone()).into()),
             }
         }
     }
 </%helpers:longhand>
 
 ${helpers.single_keyword("unicode-bidi",
                          "normal embed isolate bidi-override isolate-override plaintext",
                          animation_value_type="discrete",
@@ -231,17 +231,17 @@
                                            else { empty = false; result.insert(UNDERLINE); Ok(()) },
                             "overline" => if result.contains(OVERLINE) { Err(()) }
                                           else { empty = false; result.insert(OVERLINE); Ok(()) },
                             "line-through" => if result.contains(LINE_THROUGH) { Err(()) }
                                               else { empty = false; result.insert(LINE_THROUGH); Ok(()) },
                             "blink" => if result.contains(BLINK) { Err(()) }
                                        else { empty = false; result.insert(BLINK); Ok(()) },
                             _ => Err(())
-                        }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+                        }).map_err(|()| SelectorParseError::UnexpectedIdent(ident.clone()).into())
                     }
                     Err(e) => return Err(e.into())
                 }
             });
             if result.is_err() {
                 break;
             }
         }
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -417,17 +417,17 @@ impl CSSWideKeyword {
             "unset" => Some(CSSWideKeyword::Unset),
             _ => None
         }
     }
 }
 
 impl Parse for CSSWideKeyword {
     fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
-        let ident = input.expect_ident()?;
+        let ident = input.expect_ident()?.clone();
         input.expect_exhausted()?;
         CSSWideKeyword::from_ident(&ident)
             .ok_or(SelectorParseError::UnexpectedIdent(ident).into())
     }
 }
 
 bitflags! {
     /// A set of flags for properties.
--- a/servo/components/style/properties/shorthand/position.mako.rs
+++ b/servo/components/style/properties/shorthand/position.mako.rs
@@ -273,34 +273,33 @@
                 }
                 Err(())
             }) {
                 return Ok(x);
             }
         % endfor
 
         let first_line_names = input.try(parse_line_names).unwrap_or(vec![].into_boxed_slice());
-        if let Ok(s) = input.try(Parser::expect_string) {
+        if let Ok(mut string) = input.try(|i| i.expect_string().map(|s| s.as_ref().into())) {
             let mut strings = vec![];
             let mut values = vec![];
             let mut line_names = vec![];
             let mut names = first_line_names.into_vec();
-            let mut string = s.into_owned().into_boxed_str();
             loop {
                 line_names.push(names.into_boxed_slice());
                 strings.push(string);
                 let size = input.try(|i| TrackSize::parse(context, i)).unwrap_or_default();
                 values.push(size);
                 names = input.try(parse_line_names).unwrap_or(vec![].into_boxed_slice()).into_vec();
                 if let Ok(v) = input.try(parse_line_names) {
                     names.extend(v.into_vec());
                 }
 
-                string = match input.try(Parser::expect_string) {
-                    Ok(s) => s.into_owned().into_boxed_str(),
+                string = match input.try(|i| i.expect_string().map(|s| s.as_ref().into())) {
+                    Ok(s) => s,
                     _ => {      // only the named area determines whether we should bail out
                         line_names.push(names.into_boxed_slice());
                         break
                     },
                 };
             }
 
             if line_names.len() == values.len() {
--- a/servo/components/style/servo/media_queries.rs
+++ b/servo/components/style/servo/media_queries.rs
@@ -160,17 +160,17 @@ impl Expression {
     /// (media-feature: media-value)
     /// ```
     ///
     /// Only supports width and width ranges for now.
     pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<Self, ParseError<'i>> {
         input.expect_parenthesis_block()?;
         input.parse_nested_block(|input| {
-            let name = input.expect_ident()?;
+            let name = input.expect_ident_cloned()?;
             input.expect_colon()?;
             // TODO: Handle other media features
             Ok(Expression(match_ignore_ascii_case! { &name,
                 "min-width" => {
                     ExpressionKind::Width(Range::Min(specified::Length::parse_non_negative(context, input)?))
                 },
                 "max-width" => {
                     ExpressionKind::Width(Range::Max(specified::Length::parse_non_negative(context, input)?))
--- a/servo/components/style/servo/selector_parser.rs
+++ b/servo/components/style/servo/selector_parser.rs
@@ -3,29 +3,28 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #![deny(missing_docs)]
 
 //! Servo's selector parser.
 
 use {Atom, Prefix, Namespace, LocalName, CaseSensitivityExt};
 use attr::{AttrIdentifier, AttrValue};
-use cssparser::{Parser as CssParser, ToCss, serialize_identifier, CompactCowStr};
+use cssparser::{Parser as CssParser, ToCss, serialize_identifier, CowRcStr};
 use dom::{OpaqueNode, TElement, TNode};
 use element_state::ElementState;
 use fnv::FnvHashMap;
 use invalidation::element::element_wrapper::ElementSnapshot;
 use properties::PropertyFlags;
 use selector_parser::{AttrValue as SelectorAttrValue, ElementExt, PseudoElementCascadeType, SelectorParser};
 use selectors::Element;
 use selectors::attr::{AttrSelectorOperation, NamespaceConstraint, CaseSensitivity};
 use selectors::parser::{SelectorMethods, SelectorParseError};
 use selectors::visitor::SelectorVisitor;
 use std::ascii::AsciiExt;
-use std::borrow::Cow;
 use std::fmt;
 use std::fmt::Debug;
 use std::mem;
 use std::ops::{Deref, DerefMut};
 use style_traits::{ParseError, StyleParseError};
 
 /// A pseudo-element, both public and private.
 ///
@@ -329,17 +328,17 @@ impl ::selectors::SelectorImpl for Selec
                                 NonTSPseudoClass::Hover)
     }
 }
 
 impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
     type Impl = SelectorImpl;
     type Error = StyleParseError<'i>;
 
-    fn parse_non_ts_pseudo_class(&self, name: CompactCowStr<'i>)
+    fn parse_non_ts_pseudo_class(&self, name: CowRcStr<'i>)
                                  -> Result<NonTSPseudoClass, ParseError<'i>> {
         use self::NonTSPseudoClass::*;
         let pseudo_class = match_ignore_ascii_case! { &name,
             "active" => Active,
             "any-link" => AnyLink,
             "checked" => Checked,
             "disabled" => Disabled,
             "enabled" => Enabled,
@@ -362,37 +361,37 @@ impl<'a, 'i> ::selectors::Parser<'i> for
             },
             _ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into()),
         };
 
         Ok(pseudo_class)
     }
 
     fn parse_non_ts_functional_pseudo_class<'t>(&self,
-                                                name: CompactCowStr<'i>,
+                                                name: CowRcStr<'i>,
                                                 parser: &mut CssParser<'i, 't>)
                                                 -> Result<NonTSPseudoClass, ParseError<'i>> {
         use self::NonTSPseudoClass::*;
         let pseudo_class = match_ignore_ascii_case!{ &name,
             "lang" => {
-                Lang(parser.expect_ident_or_string()?.into_owned().into_boxed_str())
+                Lang(parser.expect_ident_or_string()?.as_ref().into())
             }
             "-servo-case-sensitive-type-attr" => {
                 if !self.in_user_agent_stylesheet() {
                     return Err(SelectorParseError::UnexpectedIdent(name.clone()).into());
                 }
-                ServoCaseSensitiveTypeAttr(Atom::from(Cow::from(parser.expect_ident()?)))
+                ServoCaseSensitiveTypeAttr(Atom::from(parser.expect_ident()?.as_ref()))
             }
             _ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
         };
 
         Ok(pseudo_class)
     }
 
-    fn parse_pseudo_element(&self, name: CompactCowStr<'i>) -> Result<PseudoElement, ParseError<'i>> {
+    fn parse_pseudo_element(&self, name: CowRcStr<'i>) -> Result<PseudoElement, ParseError<'i>> {
         use self::PseudoElement::*;
         let pseudo_element = match_ignore_ascii_case! { &name,
             "before" => Before,
             "after" => After,
             "selection" => Selection,
             "-servo-details-summary" => {
                 if !self.in_user_agent_stylesheet() {
                     return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
--- a/servo/components/style/stylesheets/document_rule.rs
+++ b/servo/components/style/stylesheets/document_rule.rs
@@ -84,19 +84,19 @@ pub enum UrlMatchingFunction {
 }
 
 macro_rules! parse_quoted_or_unquoted_string {
     ($input:ident, $url_matching_function:expr) => {
         $input.parse_nested_block(|input| {
             let start = input.position();
             input.parse_entirely(|input| {
                 match input.next() {
-                    Ok(Token::QuotedString(value)) =>
-                        Ok($url_matching_function(value.into_owned())),
-                    Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
+                    Ok(&Token::QuotedString(ref value)) =>
+                        Ok($url_matching_function(value.as_ref().to_owned())),
+                    Ok(t) => Err(BasicParseError::UnexpectedToken(t.clone()).into()),
                     Err(e) => Err(e.into()),
                 }
             }).or_else(|_: ParseError| {
                 while let Ok(_) = input.next() {}
                 Ok($url_matching_function(input.slice_from(start).to_string()))
             })
         })
     }
@@ -107,17 +107,17 @@ impl UrlMatchingFunction {
     pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
         -> Result<UrlMatchingFunction, ParseError<'i>> {
         if input.try(|input| input.expect_function_matching("url-prefix")).is_ok() {
             parse_quoted_or_unquoted_string!(input, UrlMatchingFunction::UrlPrefix)
         } else if input.try(|input| input.expect_function_matching("domain")).is_ok() {
             parse_quoted_or_unquoted_string!(input, UrlMatchingFunction::Domain)
         } else if input.try(|input| input.expect_function_matching("regexp")).is_ok() {
             input.parse_nested_block(|input| {
-                Ok(UrlMatchingFunction::RegExp(input.expect_string()?.into_owned()))
+                Ok(UrlMatchingFunction::RegExp(input.expect_string()?.as_ref().to_owned()))
             })
         } else if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
             Ok(UrlMatchingFunction::Url(url))
         } else {
             Err(StyleParseError::UnspecifiedError.into())
         }
     }
 
--- a/servo/components/style/stylesheets/keyframes_rule.rs
+++ b/servo/components/style/stylesheets/keyframes_rule.rs
@@ -1,15 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Keyframes: https://drafts.csswg.org/css-animations/#keyframes
 
-use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser, ParserInput, CompactCowStr};
+use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser, ParserInput, CowRcStr};
 use cssparser::{DeclarationListParser, DeclarationParser, parse_one_rule, SourceLocation};
 use error_reporting::{NullReporter, ContextualParseError};
 use parser::{ParserContext, log_css_error};
 use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock, PropertyId};
 use properties::{PropertyDeclarationId, LonghandId, SourcePropertyDeclaration};
 use properties::LonghandIdSet;
 use properties::animated_properties::AnimatableLonghand;
 use properties::longhands::transition_timing_function::single_value::SpecifiedValue as SpecifiedTimingFunction;
@@ -526,17 +526,17 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for Ke
     type AtRule = ();
     type Error = SelectorParseError<'i, StyleParseError<'i>>;
 }
 
 impl<'a, 'b, 'i> DeclarationParser<'i> for KeyframeDeclarationParser<'a, 'b> {
     type Declaration = ();
     type Error = SelectorParseError<'i, StyleParseError<'i>>;
 
-    fn parse_value<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>)
+    fn parse_value<'t>(&mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't>)
                        -> Result<(), ParseError<'i>> {
         let id = PropertyId::parse(&name)
             .map_err(|()| PropertyDeclarationParseError::UnknownProperty(name))?;
         match PropertyDeclaration::parse_into(self.declarations, id, self.context, input) {
             Ok(()) => {
                 // In case there is still unparsed text in the declaration, we should roll back.
                 input.expect_exhausted().map_err(|e| e.into())
             }
--- a/servo/components/style/stylesheets/rule_parser.rs
+++ b/servo/components/style/stylesheets/rule_parser.rs
@@ -2,28 +2,27 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Parsing of the stylesheet contents.
 
 use {Namespace, Prefix};
 use counter_style::{parse_counter_style_body, parse_counter_style_name};
 use cssparser::{AtRuleParser, AtRuleType, Parser, QualifiedRuleParser, RuleListParser};
-use cssparser::{CompactCowStr, SourceLocation, BasicParseError};
+use cssparser::{CowRcStr, SourceLocation, BasicParseError};
 use error_reporting::ContextualParseError;
 use font_face::parse_font_face_block;
 use media_queries::{parse_media_query_list, MediaList};
 use parser::{Parse, ParserContext, log_css_error};
 use properties::parse_property_declaration_list;
 use selector_parser::{SelectorImpl, SelectorParser};
 use selectors::SelectorList;
 use selectors::parser::SelectorParseError;
 use servo_arc::Arc;
 use shared_lock::{Locked, SharedRwLock};
-use std::borrow::Cow;
 use str::starts_with_ignore_ascii_case;
 use style_traits::{StyleParseError, ParseError};
 use stylesheets::{CssRule, CssRules, CssRuleType, Origin, StylesheetLoader};
 use stylesheets::{DocumentRule, KeyframesRule, MediaRule, NamespaceRule, PageRule};
 use stylesheets::{StyleRule, SupportsRule, ViewportRule};
 use stylesheets::document_rule::DocumentCondition;
 use stylesheets::keyframes_rule::parse_keyframe_list;
 use stylesheets::stylesheet::Namespaces;
@@ -137,31 +136,31 @@ fn register_namespace(_: &Namespace) -> 
 
 impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> {
     type Prelude = AtRulePrelude;
     type AtRule = CssRule;
     type Error = SelectorParseError<'i, StyleParseError<'i>>;
 
     fn parse_prelude<'t>(
         &mut self,
-        name: CompactCowStr<'i>,
+        name: CowRcStr<'i>,
         input: &mut Parser<'i, 't>
     ) -> Result<AtRuleType<AtRulePrelude, CssRule>, ParseError<'i>> {
         let location = get_location_with_offset(input.current_source_location(),
                                                 self.context.line_number_offset);
         match_ignore_ascii_case! { &*name,
             "import" => {
                 if self.state > State::Imports {
                     self.state = State::Invalid;
                     // "@import must be before any rule but @charset"
                     return Err(StyleParseError::UnexpectedImportRule.into())
                 }
 
                 self.state = State::Imports;
-                let url_string = input.expect_url_or_string()?.into_owned();
+                let url_string = input.expect_url_or_string()?.as_ref().to_owned();
                 let specified_url = SpecifiedUrl::parse_from_string(url_string, &self.context)?;
 
                 let media = parse_media_query_list(&self.context, input);
                 let media = Arc::new(self.shared_lock.wrap(media));
 
                 let loader =
                     self.loader.expect("Expected a stylesheet loader for @import");
 
@@ -178,32 +177,32 @@ impl<'a, 'i> AtRuleParser<'i> for TopLev
             "namespace" => {
                 if self.state > State::Namespaces {
                     self.state = State::Invalid;
                     // "@namespace must be before any rule but @charset and @import"
                     return Err(StyleParseError::UnexpectedNamespaceRule.into())
                 }
                 self.state = State::Namespaces;
 
-                let prefix_result = input.try(|input| input.expect_ident());
+                let prefix_result = input.try(|i| i.expect_ident_cloned());
                 let maybe_namespace = match input.expect_url_or_string() {
                     Ok(url_or_string) => url_or_string,
                     Err(BasicParseError::UnexpectedToken(t)) =>
                         return Err(StyleParseError::UnexpectedTokenWithinNamespace(t).into()),
                     Err(e) => return Err(e.into()),
                 };
-                let url = Namespace::from(Cow::from(maybe_namespace));
+                let url = Namespace::from(maybe_namespace.as_ref());
 
                 let id = register_namespace(&url)
                     .map_err(|()| StyleParseError::UnspecifiedError)?;
 
                 let mut namespaces = self.namespaces.as_mut().unwrap();
 
                 let opt_prefix = if let Ok(prefix) = prefix_result {
-                    let prefix = Prefix::from(Cow::from(prefix));
+                    let prefix = Prefix::from(prefix.as_ref());
                     namespaces
                         .prefixes
                         .insert(prefix.clone(), (url.clone(), id));
                     Some(prefix)
                 } else {
                     namespaces.default = Some((url.clone(), id));
                     None
                 };
@@ -319,17 +318,17 @@ impl<'a, 'b> NestedRuleParser<'a, 'b> {
 
 impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> {
     type Prelude = AtRulePrelude;
     type AtRule = CssRule;
     type Error = SelectorParseError<'i, StyleParseError<'i>>;
 
     fn parse_prelude<'t>(
         &mut self,
-        name: CompactCowStr<'i>,
+        name: CowRcStr<'i>,
         input: &mut Parser<'i, 't>
     ) -> Result<AtRuleType<AtRulePrelude, CssRule>, ParseError<'i>> {
         let location =
             get_location_with_offset(
                 input.current_source_location(),
                 self.context.line_number_offset
             );
 
--- a/servo/components/style/stylesheets/supports_rule.rs
+++ b/servo/components/style/stylesheets/supports_rule.rs
@@ -92,24 +92,24 @@ impl SupportsCondition {
 
         let in_parens = SupportsCondition::parse_in_parens(input)?;
 
         let (keyword, wrapper) = match input.next() {
             Err(_) => {
                 // End of input
                 return Ok(in_parens)
             }
-            Ok(Token::Ident(ident)) => {
+            Ok(&Token::Ident(ref ident)) => {
                 match_ignore_ascii_case! { &ident,
                     "and" => ("and", SupportsCondition::And as fn(_) -> _),
                     "or" => ("or", SupportsCondition::Or as fn(_) -> _),
                     _ => return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into())
                 }
             }
-            Ok(t) => return Err(CssParseError::Basic(BasicParseError::UnexpectedToken(t)))
+            Ok(t) => return Err(CssParseError::Basic(BasicParseError::UnexpectedToken(t.clone())))
         };
 
         let mut conditions = Vec::with_capacity(2);
         conditions.push(in_parens);
         loop {
             conditions.push(SupportsCondition::parse_in_parens(input)?);
             if input.try(|input| input.expect_ident_matching(keyword)).is_err() {
                 // Did not find the expected keyword.
@@ -121,17 +121,18 @@ impl SupportsCondition {
     }
 
     /// https://drafts.csswg.org/css-conditional-3/#supports_condition_in_parens
     fn parse_in_parens<'i, 't>(input: &mut Parser<'i, 't>) -> Result<SupportsCondition, ParseError<'i>> {
         // Whitespace is normally taken care of in `Parser::next`,
         // but we want to not include it in `pos` for the SupportsCondition::FutureSyntax cases.
         while input.try(Parser::expect_whitespace).is_ok() {}
         let pos = input.position();
-        match input.next()? {
+        // FIXME: remove clone() when lifetimes are non-lexical
+        match input.next()?.clone() {
             Token::ParenthesisBlock => {
                 let nested = input.try(|input| {
                     input.parse_nested_block(|i| parse_condition_or_declaration(i))
                 });
                 if nested.is_ok() {
                     return nested;
                 }
             }
@@ -239,17 +240,17 @@ impl Declaration {
 
     /// Determine if a declaration parses
     ///
     /// https://drafts.csswg.org/css-conditional-3/#support-definition
     pub fn eval(&self, cx: &ParserContext) -> bool {
         let mut input = ParserInput::new(&self.0);
         let mut input = Parser::new(&mut input);
         input.parse_entirely(|input| {
-            let prop = input.expect_ident().unwrap();
+            let prop = input.expect_ident().unwrap().as_ref().to_owned();
             input.expect_colon().unwrap();
             let id = PropertyId::parse(&prop)
                 .map_err(|_| StyleParseError::UnspecifiedError)?;
             let mut declarations = SourcePropertyDeclaration::new();
             let context = ParserContext::new_with_rule_type(cx, Some(CssRuleType::Style));
             input.parse_until_before(Delimiter::Bang, |input| {
                 PropertyDeclaration::parse_into(&mut declarations, id, &context, input)
                     .map_err(|e| StyleParseError::PropertyDeclaration(e).into())
--- a/servo/components/style/stylesheets/viewport_rule.rs
+++ b/servo/components/style/stylesheets/viewport_rule.rs
@@ -5,17 +5,17 @@
 //! The [`@viewport`][at] at-rule and [`meta`][meta] element.
 //!
 //! [at]: https://drafts.csswg.org/css-device-adapt/#atviewport-rule
 //! [meta]: https://drafts.csswg.org/css-device-adapt/#viewport-meta
 
 use app_units::Au;
 use context::QuirksMode;
 use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser, parse_important};
-use cssparser::{CompactCowStr, ToCss as ParserToCss};
+use cssparser::{CowRcStr, ToCss as ParserToCss};
 use error_reporting::ContextualParseError;
 use euclid::TypedSize2D;
 use font_metrics::get_metrics_provider_for_product;
 use media_queries::Device;
 use parser::{Parse, ParserContext, log_css_error};
 use properties::StyleBuilder;
 use selectors::parser::SelectorParseError;
 use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
@@ -275,17 +275,17 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for Vi
     type AtRule = Vec<ViewportDescriptorDeclaration>;
     type Error = SelectorParseError<'i, StyleParseError<'i>>;
 }
 
 impl<'a, 'b, 'i> DeclarationParser<'i> for ViewportRuleParser<'a, 'b> {
     type Declaration = Vec<ViewportDescriptorDeclaration>;
     type Error = SelectorParseError<'i, StyleParseError<'i>>;
 
-    fn parse_value<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>)
+    fn parse_value<'t>(&mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't>)
                        -> Result<Vec<ViewportDescriptorDeclaration>, ParseError<'i>> {
         macro_rules! declaration {
             ($declaration:ident($parse:expr)) => {
                 declaration!($declaration(value: try!($parse(input)),
                                           important: input.try(parse_important).is_ok()))
             };
             ($declaration:ident(value: $value:expr, important: $important:expr)) => {
                 ViewportDescriptorDeclaration::new(
--- a/servo/components/style/values/generics/grid.rs
+++ b/servo/components/style/values/generics/grid.rs
@@ -95,21 +95,21 @@ impl Parse for GridLine {
 
                 grid_line.is_span = true;
             } else if let Ok(i) = input.try(|i| Integer::parse(context, i)) {
                 if i.value() == 0 || val_before_span || grid_line.line_num.is_some() {
                     return Err(StyleParseError::UnspecifiedError.into())
                 }
 
                 grid_line.line_num = Some(i);
-            } else if let Ok(name) = input.try(|i| i.expect_ident()) {
+            } else if let Ok(name) = input.try(|i| i.expect_ident_cloned()) {
                 if val_before_span || grid_line.ident.is_some() {
                     return Err(StyleParseError::UnspecifiedError.into());
                 }
-                grid_line.ident = Some(CustomIdent::from_ident(name, &[])?);
+                grid_line.ident = Some(CustomIdent::from_ident(&name, &[])?);
             } else {
                 break
             }
         }
 
         if grid_line.is_auto() {
             return Err(StyleParseError::UnspecifiedError.into())
         }
--- a/servo/components/style/values/generics/mod.rs
+++ b/servo/components/style/values/generics/mod.rs
@@ -146,27 +146,30 @@ impl<T: Parse> Parse for FontSettingTag<
     /// https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-
     /// settings-control-the-font-variation-settings-property
     /// <string> [ on | off | <integer> ]
     /// <string> <number>
     fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         use byteorder::{ReadBytesExt, BigEndian};
         use std::io::Cursor;
 
-        let tag = input.expect_string()?;
-
-        // allowed strings of length 4 containing chars: <U+20, U+7E>
-        if tag.len() != 4 ||
-           tag.chars().any(|c| c < ' ' || c > '~')
+        let u_tag;
         {
-            return Err(StyleParseError::UnspecifiedError.into())
-        }
+            let tag = input.expect_string()?;
 
-        let mut raw = Cursor::new(tag.as_bytes());
-        let u_tag = raw.read_u32::<BigEndian>().unwrap();
+            // allowed strings of length 4 containing chars: <U+20, U+7E>
+            if tag.len() != 4 ||
+               tag.chars().any(|c| c < ' ' || c > '~')
+            {
+                return Err(StyleParseError::UnspecifiedError.into())
+            }
+
+            let mut raw = Cursor::new(tag.as_bytes());
+            u_tag = raw.read_u32::<BigEndian>().unwrap();
+        }
 
         Ok(FontSettingTag { tag: u_tag, value: T::parse(context, input)? })
     }
 }
 
 
 /// A font settings value for font-variation-settings or font-feature-settings
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
--- a/servo/components/style/values/mod.rs
+++ b/servo/components/style/values/mod.rs
@@ -4,21 +4,20 @@
 
 //! Common [values][values] used in CSS.
 //!
 //! [values]: https://drafts.csswg.org/css-values/
 
 #![deny(missing_docs)]
 
 use Atom;
-pub use cssparser::{RGBA, Token, Parser, serialize_identifier, BasicParseError, CompactCowStr};
+pub use cssparser::{RGBA, Token, Parser, serialize_identifier, BasicParseError, CowRcStr};
 use parser::{Parse, ParserContext};
 use selectors::parser::SelectorParseError;
 use std::ascii::AsciiExt;
-use std::borrow::Cow;
 use std::fmt::{self, Debug};
 use std::hash;
 use style_traits::{ToCss, ParseError, StyleParseError};
 
 pub mod animated;
 pub mod computed;
 pub mod generics;
 pub mod specified;
@@ -82,28 +81,28 @@ impl<A: Parse, B: Parse> Parse for Eithe
 
 /// https://drafts.csswg.org/css-values-4/#custom-idents
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 pub struct CustomIdent(pub Atom);
 
 impl CustomIdent {
     /// Parse an already-tokenizer identifier
-    pub fn from_ident<'i>(ident: CompactCowStr<'i>, excluding: &[&str]) -> Result<Self, ParseError<'i>> {
-        let valid = match_ignore_ascii_case! { &ident,
+    pub fn from_ident<'i>(ident: &CowRcStr<'i>, excluding: &[&str]) -> Result<Self, ParseError<'i>> {
+        let valid = match_ignore_ascii_case! { ident,
             "initial" | "inherit" | "unset" | "default" => false,
             _ => true
         };
         if !valid {
-            return Err(SelectorParseError::UnexpectedIdent(ident).into());
+            return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into());
         }
         if excluding.iter().any(|s| ident.eq_ignore_ascii_case(s)) {
             Err(StyleParseError::UnspecifiedError.into())
         } else {
-            Ok(CustomIdent(Atom::from(Cow::from(ident))))
+            Ok(CustomIdent(Atom::from(ident.as_ref())))
         }
     }
 }
 
 impl ToCss for CustomIdent {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         serialize_identifier(&self.0.to_string(), dest)
     }
@@ -116,18 +115,18 @@ pub enum KeyframesName {
     /// <custom-ident>
     Ident(CustomIdent),
     /// <string>
     QuotedString(Atom),
 }
 
 impl KeyframesName {
     /// https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-name
-    pub fn from_ident(value: String) -> Self {
-        let custom_ident = CustomIdent::from_ident((&*value).into(), &["none"]).ok();
+    pub fn from_ident(value: &str) -> Self {
+        let custom_ident = CustomIdent::from_ident(&value.into(), &["none"]).ok();
         match custom_ident {
             Some(ident) => KeyframesName::Ident(ident),
             None => KeyframesName::QuotedString(value.into()),
         }
     }
 
     /// The name as an Atom
     pub fn as_atom(&self) -> &Atom {
@@ -150,19 +149,19 @@ impl hash::Hash for KeyframesName {
     fn hash<H>(&self, state: &mut H) where H: hash::Hasher {
         self.as_atom().hash(state)
     }
 }
 
 impl Parse for KeyframesName {
     fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         match input.next() {
-            Ok(Token::Ident(s)) => Ok(KeyframesName::Ident(CustomIdent::from_ident(s, &["none"])?)),
-            Ok(Token::QuotedString(s)) => Ok(KeyframesName::QuotedString(Atom::from(Cow::from(s)))),
-            Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
+            Ok(&Token::Ident(ref s)) => Ok(KeyframesName::Ident(CustomIdent::from_ident(s, &["none"])?)),
+            Ok(&Token::QuotedString(ref s)) => Ok(KeyframesName::QuotedString(Atom::from(s.as_ref()))),
+            Ok(t) => Err(BasicParseError::UnexpectedToken(t.clone()).into()),
             Err(e) => Err(e.into()),
         }
     }
 }
 
 impl ToCss for KeyframesName {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         match *self {
--- a/servo/components/style/values/specified/align.rs
+++ b/servo/components/style/values/specified/align.rs
@@ -369,17 +369,18 @@ fn parse_normal_or_baseline<'i, 't>(inpu
     }
 
     input.expect_ident_matching("normal")?;
     Ok(ALIGN_NORMAL)
 }
 
 // <baseline-position>
 fn parse_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
-    try_match_ident_ignore_ascii_case! { input.expect_ident()?,
+    // FIXME: remove clone() when lifetimes are non-lexical
+    try_match_ident_ignore_ascii_case! { input.expect_ident()?.clone(),
         "baseline" => Ok(ALIGN_BASELINE),
         "first" => {
             input.expect_ident_matching("baseline")?;
             Ok(ALIGN_BASELINE)
         }
         "last" => {
             input.expect_ident_matching("baseline")?;
             Ok(ALIGN_LAST_BASELINE)
@@ -466,25 +467,25 @@ fn parse_self_position<'i, 't>(input: &m
         "right" => Ok(ALIGN_RIGHT),
         "self-start" => Ok(ALIGN_SELF_START),
         "self-end" => Ok(ALIGN_SELF_END),
     }
 }
 
 // [ legacy && [ left | right | center ] ]
 fn parse_legacy<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
-    let a = input.expect_ident()?;
+    let a = input.expect_ident()?.clone();
     let b = input.expect_ident()?;
     if a.eq_ignore_ascii_case("legacy") {
         (match_ignore_ascii_case! { &b,
             "left" => Ok(ALIGN_LEGACY | ALIGN_LEFT),
             "right" => Ok(ALIGN_LEGACY | ALIGN_RIGHT),
             "center" => Ok(ALIGN_LEGACY | ALIGN_CENTER),
             _ => Err(())
-        }).map_err(|()| SelectorParseError::UnexpectedIdent(b).into())
+        }).map_err(|()| SelectorParseError::UnexpectedIdent(b.clone()).into())
     } else if b.eq_ignore_ascii_case("legacy") {
         (match_ignore_ascii_case! { &a,
             "left" => Ok(ALIGN_LEGACY | ALIGN_LEFT),
             "right" => Ok(ALIGN_LEGACY | ALIGN_RIGHT),
             "center" => Ok(ALIGN_LEGACY | ALIGN_CENTER),
             _ => Err(())
         }).map_err(|()| SelectorParseError::UnexpectedIdent(a).into())
     } else {
--- a/servo/components/style/values/specified/background.rs
+++ b/servo/components/style/values/specified/background.rs
@@ -22,11 +22,11 @@ impl Parse for BackgroundSize {
                 .unwrap_or(LengthOrPercentageOrAuto::Auto);
             return Ok(GenericBackgroundSize::Explicit { width: width, height: height });
         }
         let ident = input.expect_ident()?;
         (match_ignore_ascii_case! { &ident,
             "cover" => Ok(GenericBackgroundSize::Cover),
             "contain" => Ok(GenericBackgroundSize::Contain),
             _ => Err(()),
-        }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+        }).map_err(|()| SelectorParseError::UnexpectedIdent(ident.clone()).into())
     }
 }
--- a/servo/components/style/values/specified/basic_shape.rs
+++ b/servo/components/style/values/specified/basic_shape.rs
@@ -96,25 +96,25 @@ impl Parse for GeometryBox {
             "stroke-box" => Ok(GeometryBox::StrokeBox),
             "view-box" => Ok(GeometryBox::ViewBox),
         }
     }
 }
 
 impl Parse for BasicShape {
     fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
-        let function = input.expect_function()?;
+        let function = input.expect_function()?.clone();
         input.parse_nested_block(move |i| {
             (match_ignore_ascii_case! { &function,
                 "inset" => return InsetRect::parse_function_arguments(context, i).map(GenericBasicShape::Inset),
                 "circle" => return Circle::parse_function_arguments(context, i).map(GenericBasicShape::Circle),
                 "ellipse" => return Ellipse::parse_function_arguments(context, i).map(GenericBasicShape::Ellipse),
                 "polygon" => return Polygon::parse_function_arguments(context, i).map(GenericBasicShape::Polygon),
                 _ => Err(())
-            }).map_err(|()| StyleParseError::UnexpectedFunction(function).into())
+            }).map_err(|()| StyleParseError::UnexpectedFunction(function.clone()).into())
         })
     }
 }
 
 impl Parse for InsetRect {
     fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         input.expect_function_matching("inset")?;
         input.parse_nested_block(|i| Self::parse_function_arguments(context, i))
--- a/servo/components/style/values/specified/calc.rs
+++ b/servo/components/style/values/specified/calc.rs
@@ -145,71 +145,68 @@ impl CalcNode {
     ///
     /// May return a "complex" `CalcNode`, in the presence of a parenthesized
     /// expression, for example.
     fn parse_one<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
         expected_unit: CalcUnit
     ) -> Result<Self, ParseError<'i>> {
+        // FIXME: remove early returns when lifetimes are non-lexical
         match (input.next()?, expected_unit) {
-            (Token::Number { value, .. }, _) => Ok(CalcNode::Number(value)),
-            (Token::Dimension { value, ref unit, .. }, CalcUnit::Length) |
-            (Token::Dimension { value, ref unit, .. }, CalcUnit::LengthOrPercentage) => {
-                NoCalcLength::parse_dimension(context, value, unit)
+            (&Token::Number { value, .. }, _) => return Ok(CalcNode::Number(value)),
+            (&Token::Dimension { value, ref unit, .. }, CalcUnit::Length) |
+            (&Token::Dimension { value, ref unit, .. }, CalcUnit::LengthOrPercentage) => {
+                return NoCalcLength::parse_dimension(context, value, unit)
                     .map(CalcNode::Length)
                     .map_err(|()| StyleParseError::UnspecifiedError.into())
             }
-            (Token::Dimension { value, ref unit, .. }, CalcUnit::Angle) => {
-                Angle::parse_dimension(value, unit, /* from_calc = */ true)
+            (&Token::Dimension { value, ref unit, .. }, CalcUnit::Angle) => {
+                return Angle::parse_dimension(value, unit, /* from_calc = */ true)
                     .map(CalcNode::Angle)
                     .map_err(|()| StyleParseError::UnspecifiedError.into())
             }
-            (Token::Dimension { value, ref unit, .. }, CalcUnit::Time) => {
-                Time::parse_dimension(value, unit, /* from_calc = */ true)
+            (&Token::Dimension { value, ref unit, .. }, CalcUnit::Time) => {
+                return Time::parse_dimension(value, unit, /* from_calc = */ true)
                     .map(CalcNode::Time)
                     .map_err(|()| StyleParseError::UnspecifiedError.into())
             }
-            (Token::Percentage { unit_value, .. }, CalcUnit::LengthOrPercentage) |
-            (Token::Percentage { unit_value, .. }, CalcUnit::Percentage) => {
-                Ok(CalcNode::Percentage(unit_value))
+            (&Token::Percentage { unit_value, .. }, CalcUnit::LengthOrPercentage) |
+            (&Token::Percentage { unit_value, .. }, CalcUnit::Percentage) => {
+                return Ok(CalcNode::Percentage(unit_value))
             }
-            (Token::ParenthesisBlock, _) => {
-                input.parse_nested_block(|i| {
-                    CalcNode::parse(context, i, expected_unit)
-                })
-            }
-            (Token::Function(ref name), _) if name.eq_ignore_ascii_case("calc") => {
-                input.parse_nested_block(|i| {
-                    CalcNode::parse(context, i, expected_unit)
-                })
-            }
-            (t, _) => Err(BasicParseError::UnexpectedToken(t).into())
+            (&Token::ParenthesisBlock, _) => {}
+            (&Token::Function(ref name), _) if name.eq_ignore_ascii_case("calc") => {}
+            (t, _) => return Err(BasicParseError::UnexpectedToken(t.clone()).into())
         }
+        input.parse_nested_block(|i| {
+            CalcNode::parse(context, i, expected_unit)
+        })
     }
 
     /// Parse a top-level `calc` expression, with all nested sub-expressions.
     ///
     /// This is in charge of parsing, for example, `2 + 3 * 100%`.
     fn parse<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
         expected_unit: CalcUnit)
         -> Result<Self, ParseError<'i>>
     {
         let mut root = Self::parse_product(context, input, expected_unit)?;
 
         loop {
             let position = input.position();
             match input.next_including_whitespace() {
-                Ok(Token::WhiteSpace(_)) => {
+                Ok(&Token::WhiteSpace(_)) => {
                     if input.is_exhausted() {
                         break; // allow trailing whitespace
                     }
-                    match input.next()? {
+                    // FIXME: remove clone() when lifetimes are non-lexical
+                    match input.next()?.clone() {
                         Token::Delim('+') => {
                             let rhs =
                                 Self::parse_product(context, input, expected_unit)?;
                             let new_root =
                                 CalcNode::Sum(Box::new(root), Box::new(rhs));
                             root = new_root;
                         }
                         Token::Delim('-') => {
@@ -247,23 +244,23 @@ impl CalcNode {
         expected_unit: CalcUnit)
         -> Result<Self, ParseError<'i>>
     {
         let mut root = Self::parse_one(context, input, expected_unit)?;
 
         loop {
             let position = input.position();
             match input.next() {
-                Ok(Token::Delim('*')) => {
+                Ok(&Token::Delim('*')) => {
                     let rhs = Self::parse_one(context, input, expected_unit)?;
                     let new_root = CalcNode::Mul(Box::new(root), Box::new(rhs));
                     root = new_root;
                 }
                 // TODO(emilio): Figure out why the `Integer` check.
-                Ok(Token::Delim('/')) if expected_unit != CalcUnit::Integer => {
+                Ok(&Token::Delim('/')) if expected_unit != CalcUnit::Integer => {
                     let rhs = Self::parse_one(context, input, expected_unit)?;
                     let new_root = CalcNode::Div(Box::new(root), Box::new(rhs));
                     root = new_root;
                 }
                 _ => {
                     input.reset(position);
                     break
                 }
--- a/servo/components/style/values/specified/color.rs
+++ b/servo/components/style/values/specified/color.rs
@@ -67,17 +67,17 @@ impl From<RGBA> for Color {
 
 impl Parse for Color {
     fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         // Currently we only store authored value for color keywords,
         // because all browsers serialize those values as keywords for
         // specified value.
         let start_position = input.position();
         let authored = match input.next() {
-            Ok(Token::Ident(s)) => Some(s.to_lowercase().into_boxed_str()),
+            Ok(&Token::Ident(ref s)) => Some(s.to_lowercase().into_boxed_str()),
             _ => None,
         };
         input.reset(start_position);
         if let Ok(value) = input.try(CSSParserColor::parse) {
             Ok(match value {
                 CSSParserColor::CurrentColor => Color::CurrentColor,
                 CSSParserColor::RGBA(rgba) => Color::Numeric {
                     parsed: rgba,
@@ -168,32 +168,32 @@ impl Color {
             Color::parse_quirky_color(input).map(|rgba| Color::rgba(rgba))
         })
     }
 
     /// Parse a <quirky-color> value.
     ///
     /// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk
     fn parse_quirky_color<'i, 't>(input: &mut Parser<'i, 't>) -> Result<RGBA, ParseError<'i>> {
-        let (value, unit) = match input.next()? {
+        let (value, unit) = match *input.next()? {
             Token::Number { int_value: Some(integer), .. } => {
                 (integer, None)
             },
-            Token::Dimension { int_value: Some(integer), unit, .. } => {
+            Token::Dimension { int_value: Some(integer), ref unit, .. } => {
                 (integer, Some(unit))
             },
-            Token::Ident(ident) => {
+            Token::Ident(ref ident) => {
                 if ident.len() != 3 && ident.len() != 6 {
                     return Err(StyleParseError::UnspecifiedError.into());
                 }
                 return parse_hash_color(ident.as_bytes())
                     .map_err(|()| StyleParseError::UnspecifiedError.into());
             }
-            t => {
-                return Err(BasicParseError::UnexpectedToken(t).into());
+            ref t => {
+                return Err(BasicParseError::UnexpectedToken(t.clone()).into());
             },
         };
         if value < 0 {
             return Err(StyleParseError::UnspecifiedError.into());
         }
         let length = if value <= 9 {
             1
         } else if value <= 99 {
--- a/servo/components/style/values/specified/effects.rs
+++ b/servo/components/style/values/specified/effects.rs
@@ -154,17 +154,17 @@ impl Parse for Filter {
         input: &mut Parser<'i, 't>
     ) -> Result<Self, ParseError<'i>> {
         #[cfg(feature = "gecko")]
         {
             if let Ok(url) = input.try(|i| SpecifiedUrl::parse(context, i)) {
                 return Ok(GenericFilter::Url(url));
             }
         }
-        let function = input.expect_function()?;
+        let function = input.expect_function()?.clone();
         input.parse_nested_block(|i| {
             try_match_ident_ignore_ascii_case! { function,
                 "blur" => Ok(GenericFilter::Blur(Length::parse_non_negative(context, i)?)),
                 "brightness" => Ok(GenericFilter::Brightness(Factor::parse(context, i)?)),
                 "contrast" => Ok(GenericFilter::Contrast(Factor::parse(context, i)?)),
                 "grayscale" => Ok(GenericFilter::Grayscale(Factor::parse(context, i)?)),
                 "hue-rotate" => Ok(GenericFilter::HueRotate(Angle::parse(context, i)?)),
                 "invert" => Ok(GenericFilter::Invert(Factor::parse(context, i)?)),
--- a/servo/components/style/values/specified/grid.rs
+++ b/servo/components/style/values/specified/grid.rs
@@ -13,20 +13,20 @@ use style_traits::{HasViewportPercentage
 use values::{CSSFloat, CustomIdent};
 use values::computed::{self, Context, ToComputedValue};
 use values::generics::grid::{GridTemplateComponent, RepeatCount, TrackBreadth, TrackKeyword, TrackRepeat};
 use values::generics::grid::{LineNameList, TrackSize, TrackList, TrackListType};
 use values::specified::LengthOrPercentage;
 
 /// Parse a single flexible length.
 pub fn parse_flex<'i, 't>(input: &mut Parser<'i, 't>) -> Result<CSSFloat, ParseError<'i>> {
-    match input.next()? {
+    match *input.next()? {
         Token::Dimension { value, ref unit, .. } if unit.eq_ignore_ascii_case("fr") && value.is_sign_positive()
             => Ok(value),
-        t => Err(BasicParseError::UnexpectedToken(t).into()),
+        ref t => Err(BasicParseError::UnexpectedToken(t.clone()).into()),
     }
 }
 
 impl Parse for TrackBreadth<LengthOrPercentage> {
     fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
             return Ok(TrackBreadth::Breadth(lop))
         }
@@ -80,18 +80,18 @@ impl Parse for TrackSize<LengthOrPercent
 
 /// Parse the grid line names into a vector of owned strings.
 ///
 /// https://drafts.csswg.org/css-grid/#typedef-line-names
 pub fn parse_line_names<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Box<[CustomIdent]>, ParseError<'i>> {
     input.expect_square_bracket_block()?;
     input.parse_nested_block(|input| {
         let mut values = vec![];
-        while let Ok(ident) = input.try(|i| i.expect_ident()) {
-            let ident = CustomIdent::from_ident(ident, &["span"])?;
+        while let Ok(ident) = input.try(|i| i.expect_ident_cloned()) {
+            let ident = CustomIdent::from_ident(&ident, &["span"])?;
             values.push(ident);
         }
 
         Ok(values.into_boxed_slice())
     })
 }
 
 /// The type of `repeat` function (only used in parsing).
--- a/servo/components/style/values/specified/image.rs
+++ b/servo/components/style/values/specified/image.rs
@@ -8,17 +8,16 @@
 //! [image]: https://drafts.csswg.org/css-images/#image-values
 
 use Atom;
 use cssparser::{Parser, Token, BasicParseError};
 use parser::{Parse, ParserContext};
 use selectors::parser::SelectorParseError;
 #[cfg(feature = "servo")]
 use servo_url::ServoUrl;
-use std::borrow::Cow;
 use std::cmp::Ordering;
 use std::f32::consts::PI;
 use std::fmt;
 use style_traits::{ToCss, ParseError, StyleParseError};
 use values::{Either, None_};
 #[cfg(feature = "gecko")]
 use values::computed::{Context, Position as ComputedPosition, ToComputedValue};
 use values::generics::image::{Circle, CompatMode, Ellipse, ColorStop as GenericColorStop};
@@ -164,32 +163,33 @@ impl Image {
     pub fn for_cascade(url: ServoUrl) -> Self {
         GenericImage::Url(SpecifiedUrl::for_cascade(url))
     }
 
     /// Parses a `-moz-element(# <element-id>)`.
     fn parse_element<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Atom, ParseError<'i>> {
         input.try(|i| i.expect_function_matching("-moz-element"))?;
         input.parse_nested_block(|i| {
-            match i.next()? {
-                Token::IDHash(id) => Ok(Atom::from(Cow::from(id))),
-                t => Err(BasicParseError::UnexpectedToken(t).into()),
+            match *i.next()? {
+                Token::IDHash(ref id) => Ok(Atom::from(id.as_ref())),
+                ref t => Err(BasicParseError::UnexpectedToken(t.clone()).into()),
             }
         })
     }
 }
 
 impl Parse for Gradient {
     fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         enum Shape {
             Linear,
             Radial,
         }
 
-        let func = input.expect_function()?;
+        // FIXME: remove clone() when lifetimes are non-lexical
+        let func = input.expect_function()?.clone();
         let result = match_ignore_ascii_case! { &func,
             "linear-gradient" => {
                 Some((Shape::Linear, false, CompatMode::Modern))
             },
             "-webkit-linear-gradient" => {
                 Some((Shape::Linear, false, CompatMode::WebKit))
             },
             #[cfg(feature = "gecko")]
@@ -229,17 +229,17 @@ impl Parse for Gradient {
             "-webkit-gradient" => {
                 return input.parse_nested_block(|i| Self::parse_webkit_gradient_argument(context, i));
             },
             _ => None,
         };
 
         let (shape, repeating, mut compat_mode) = match result {
             Some(result) => result,
-            None => return Err(StyleParseError::UnexpectedFunction(func).into()),
+            None => return Err(StyleParseError::UnexpectedFunction(func.clone()).into()),
         };
 
         let (kind, items) = input.parse_nested_block(|i| {
             let shape = match shape {
                 Shape::Linear => GradientKind::parse_linear(context, i, &mut compat_mode)?,
                 Shape::Radial => GradientKind::parse_radial(context, i, &mut compat_mode)?,
             };
             let items = GradientItem::parse_comma_separated(context, i)?;
@@ -384,17 +384,17 @@ impl Gradient {
                 if let Ok(number) = input.try(|i| NumberOrPercentage::parse(context, i)) {
                     return Ok(Component::Number(number));
                 }
                 input.try(|i| i.expect_ident_matching("center"))?;
                 Ok(Component::Center)
             }
         }
 
-        let ident = input.expect_ident()?;
+        let ident = input.expect_ident_cloned()?;
         input.expect_comma()?;
 
         let (kind, reverse_stops) = match_ignore_ascii_case! { &ident,
             "linear" => {
                 let first = Point::parse(context, input)?;
                 input.expect_comma()?;
                 let second = Point::parse(context, input)?;
 
@@ -434,17 +434,17 @@ impl Gradient {
                 }
             },
             _ => return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()),
         };
 
         let mut items = input.try(|i| {
             i.expect_comma()?;
             i.parse_comma_separated(|i| {
-                let function = i.expect_function()?;
+                let function = i.expect_function()?.clone();
                 let (color, mut p) = i.parse_nested_block(|i| {
                     let p = match_ignore_ascii_case! { &function,
                         "color-stop" => {
                             let p = match NumberOrPercentage::parse(context, i)? {
                                 NumberOrPercentage::Number(number) => Percentage::new(number.value),
                                 NumberOrPercentage::Percentage(p) => p,
                             };
                             i.expect_comma()?;
@@ -874,28 +874,28 @@ impl Parse for ColorStop {
 }
 
 impl Parse for PaintWorklet {
     fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         input.expect_function_matching("paint")?;
         input.parse_nested_block(|i| {
             let name = i.expect_ident()?;
             Ok(PaintWorklet {
-                name: Atom::from(Cow::from(name)),
+                name: Atom::from(name.as_ref()),
             })
         })
     }
 }
 
 impl Parse for MozImageRect {
     fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         input.try(|i| i.expect_function_matching("-moz-image-rect"))?;
         input.parse_nested_block(|i| {
             let string = i.expect_url_or_string()?;
-            let url = SpecifiedUrl::parse_from_string(string.into_owned(), context)?;
+            let url = SpecifiedUrl::parse_from_string(string.as_ref().to_owned(), context)?;
             i.expect_comma()?;
             let top = NumberOrPercentage::parse_non_negative(context, i)?;
             i.expect_comma()?;
             let right = NumberOrPercentage::parse_non_negative(context, i)?;
             i.expect_comma()?;
             let bottom = NumberOrPercentage::parse_non_negative(context, i)?;
             i.expect_comma()?;
             let left = NumberOrPercentage::parse_non_negative(context, i)?;
--- a/servo/components/style/values/specified/length.rs
+++ b/servo/components/style/values/specified/length.rs
@@ -614,36 +614,39 @@ impl Length {
     }
 
     #[inline]
     fn parse_internal<'i, 't>(context: &ParserContext,
                               input: &mut Parser<'i, 't>,
                               num_context: AllowedLengthType,
                               allow_quirks: AllowQuirks)
                               -> Result<Length, ParseError<'i>> {
-        let token = input.next()?;
-        match token {
-            Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => {
-                Length::parse_dimension(context, value, unit)
+        // FIXME: remove early returns when lifetimes are non-lexical
+        {
+            let token = input.next()?;
+            match *token {
+                Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => {
+                    return Length::parse_dimension(context, value, unit)
+                        .map_err(|()| BasicParseError::UnexpectedToken(token.clone()).into())
+                }
+                Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => {
+                    if value != 0. &&
+                       !context.parsing_mode.allows_unitless_lengths() &&
+                       !allow_quirks.allowed(context.quirks_mode) {
+                        return Err(StyleParseError::UnspecifiedError.into())
+                    }
+                    return Ok(Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(value))))
+                },
+                Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {}
+                ref token => return Err(BasicParseError::UnexpectedToken(token.clone()).into())
             }
-            Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => {
-                if value != 0. &&
-                   !context.parsing_mode.allows_unitless_lengths() &&
-                   !allow_quirks.allowed(context.quirks_mode) {
-                    return Err(StyleParseError::UnspecifiedError.into())
-                }
-                Ok(Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(value))))
-            },
-            Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
-                return input.parse_nested_block(|input| {
-                    CalcNode::parse_length(context, input, num_context).map(|calc| Length::Calc(Box::new(calc)))
-                })
-            }
-            _ => Err(())
-        }.map_err(|()| BasicParseError::UnexpectedToken(token).into())
+        }
+        input.parse_nested_block(|input| {
+            CalcNode::parse_length(context, input, num_context).map(|calc| Length::Calc(Box::new(calc)))
+        })
     }
 
     /// Parse a non-negative length
     #[inline]
     pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                                       -> Result<Length, ParseError<'i>> {
         Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
     }
@@ -756,34 +759,35 @@ impl Percentage {
 
 
     /// Parse a specific kind of percentage.
     pub fn parse_with_clamping_mode<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
         num_context: AllowedNumericType,
     ) -> Result<Self, ParseError<'i>> {
-        match input.next()? {
+        // FIXME: remove early returns when lifetimes are non-lexical
+        match *input.next()? {
             Token::Percentage { unit_value, .. } if num_context.is_ok(context.parsing_mode, unit_value) => {
-                Ok(Percentage::new(unit_value))
+                return Ok(Percentage::new(unit_value))
             }
-            Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
-                let result = input.parse_nested_block(|i| {
-                    CalcNode::parse_percentage(context, i)
-                })?;
+            Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {}
+            ref t => return Err(BasicParseError::UnexpectedToken(t.clone()).into())
+        }
 
-                // TODO(emilio): -moz-image-rect is the only thing that uses
-                // the clamping mode... I guess we could disallow it...
-                Ok(Percentage {
-                    value: result,
-                    calc_clamping_mode: Some(num_context),
-                })
-            }
-            t => Err(BasicParseError::UnexpectedToken(t).into())
-        }
+        let result = input.parse_nested_block(|i| {
+            CalcNode::parse_percentage(context, i)
+        })?;
+
+        // TODO(emilio): -moz-image-rect is the only thing that uses
+        // the clamping mode... I guess we could disallow it...
+        Ok(Percentage {
+            value: result,
+            calc_clamping_mode: Some(num_context),
+        })
     }
 
     /// Parses a percentage token, but rejects it if it's negative.
     pub fn parse_non_negative<'i, 't>(context: &ParserContext,
                                       input: &mut Parser<'i, 't>)
                                       -> Result<Self, ParseError<'i>> {
         Self::parse_with_clamping_mode(context, input, AllowedNumericType::NonNegative)
     }
@@ -872,41 +876,46 @@ impl LengthOrPercentage {
     }
 
     fn parse_internal<'i, 't>(context: &ParserContext,
                               input: &mut Parser<'i, 't>,
                               num_context: AllowedLengthType,
                               allow_quirks: AllowQuirks)
                               -> Result<LengthOrPercentage, ParseError<'i>>
     {
-        let token = input.next()?;
-        match token {
-            Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => {
-                NoCalcLength::parse_dimension(context, value, unit).map(LengthOrPercentage::Length)
-            }
-            Token::Percentage { unit_value, .. } if num_context.is_ok(context.parsing_mode, unit_value) => {
-                return Ok(LengthOrPercentage::Percentage(computed::Percentage(unit_value)))
+        // FIXME: remove early returns when lifetimes are non-lexical
+        {
+            let token = input.next()?;
+            match *token {
+                Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => {
+                    return NoCalcLength::parse_dimension(context, value, unit)
+                        .map(LengthOrPercentage::Length)
+                        .map_err(|()| BasicParseError::UnexpectedToken(token.clone()).into())
+                }
+                Token::Percentage { unit_value, .. } if num_context.is_ok(context.parsing_mode, unit_value) => {
+                    return Ok(LengthOrPercentage::Percentage(computed::Percentage(unit_value)))
+                }
+                Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => {
+                    if value != 0. &&
+                       !context.parsing_mode.allows_unitless_lengths() &&
+                       !allow_quirks.allowed(context.quirks_mode) {
+                        return Err(BasicParseError::UnexpectedToken(token.clone()).into())
+                    } else {
+                        return Ok(LengthOrPercentage::Length(NoCalcLength::from_px(value)))
+                    }
+                }
+                Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {}
+                _ => return Err(BasicParseError::UnexpectedToken(token.clone()).into())
             }
-            Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => {
-                if value != 0. &&
-                   !context.parsing_mode.allows_unitless_lengths() &&
-                   !allow_quirks.allowed(context.quirks_mode) {
-                    Err(())
-                } else {
-                    return Ok(LengthOrPercentage::Length(NoCalcLength::from_px(value)))
-                }
-            }
-            Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
-                let calc = input.parse_nested_block(|i| {
-                    CalcNode::parse_length_or_percentage(context, i, num_context)
-                })?;
-                return Ok(LengthOrPercentage::Calc(Box::new(calc)))
-            }
-            _ => Err(())
-        }.map_err(|()| BasicParseError::UnexpectedToken(token).into())
+        }
+
+        let calc = input.parse_nested_block(|i| {
+            CalcNode::parse_length_or_percentage(context, i, num_context)
+        })?;
+        Ok(LengthOrPercentage::Calc(Box::new(calc)))
     }
 
     /// Parse a non-negative length.
     #[inline]
     pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                                       -> Result<LengthOrPercentage, ParseError<'i>> {
         Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
     }
@@ -1008,45 +1017,50 @@ impl From<computed::Percentage> for Leng
 }
 
 impl LengthOrPercentageOrAuto {
     fn parse_internal<'i, 't>(context: &ParserContext,
                               input: &mut Parser<'i, 't>,
                               num_context: AllowedLengthType,
                               allow_quirks: AllowQuirks)
                               -> Result<Self, ParseError<'i>> {
-        let token = input.next()?;
-        match token {
-            Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => {
-                NoCalcLength::parse_dimension(context, value, unit).map(LengthOrPercentageOrAuto::Length)
-            }
-            Token::Percentage { unit_value, .. } if num_context.is_ok(context.parsing_mode, unit_value) => {
-                Ok(LengthOrPercentageOrAuto::Percentage(computed::Percentage(unit_value)))
-            }
-            Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => {
-                if value != 0. &&
-                   !context.parsing_mode.allows_unitless_lengths() &&
-                   !allow_quirks.allowed(context.quirks_mode) {
-                    return Err(StyleParseError::UnspecifiedError.into())
+        // FIXME: remove early returns when lifetimes are non-lexical
+        {
+            let token = input.next()?;
+            match *token {
+                Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => {
+                    return NoCalcLength::parse_dimension(context, value, unit)
+                        .map(LengthOrPercentageOrAuto::Length)
+                        .map_err(|()| BasicParseError::UnexpectedToken(token.clone()).into())
+                }
+                Token::Percentage { unit_value, .. } if num_context.is_ok(context.parsing_mode, unit_value) => {
+                    return Ok(LengthOrPercentageOrAuto::Percentage(computed::Percentage(unit_value)))
                 }
-                Ok(LengthOrPercentageOrAuto::Length(
-                    NoCalcLength::Absolute(AbsoluteLength::Px(value))
-                ))
-            }
-            Token::Ident(ref value) if value.eq_ignore_ascii_case("auto") => {
-                Ok(LengthOrPercentageOrAuto::Auto)
+                Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => {
+                    if value != 0. &&
+                       !context.parsing_mode.allows_unitless_lengths() &&
+                       !allow_quirks.allowed(context.quirks_mode) {
+                        return Err(StyleParseError::UnspecifiedError.into())
+                    }
+                    return Ok(LengthOrPercentageOrAuto::Length(
+                        NoCalcLength::Absolute(AbsoluteLength::Px(value))
+                    ))
+                }
+                Token::Ident(ref value) if value.eq_ignore_ascii_case("auto") => {
+                    return Ok(LengthOrPercentageOrAuto::Auto)
+                }
+                Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {}
+                _ => return Err(BasicParseError::UnexpectedToken(token.clone()).into())
             }
-            Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
-                let calc = input.parse_nested_block(|i| {
-                    CalcNode::parse_length_or_percentage(context, i, num_context)
-                })?;
-                Ok(LengthOrPercentageOrAuto::Calc(Box::new(calc)))
-            }
-            _ => Err(())
-        }.map_err(|()| BasicParseError::UnexpectedToken(token).into())
+        }
+
+        let calc = input.parse_nested_block(|i| {
+            CalcNode::parse_length_or_percentage(context, i, num_context)
+        })?;
+        Ok(LengthOrPercentageOrAuto::Calc(Box::new(calc)))
     }
 
     /// Parse a non-negative length, percentage, or auto.
     #[inline]
     pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                                       -> Result<LengthOrPercentageOrAuto, ParseError<'i>> {
         Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
     }
@@ -1107,43 +1121,49 @@ pub enum LengthOrPercentageOrNone {
 
 impl LengthOrPercentageOrNone {
     fn parse_internal<'i, 't>(context: &ParserContext,
                               input: &mut Parser<'i, 't>,
                               num_context: AllowedLengthType,
                               allow_quirks: AllowQuirks)
                               -> Result<LengthOrPercentageOrNone, ParseError<'i>>
     {
-        let token = input.next()?;
-        match token {
-            Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => {
-                NoCalcLength::parse_dimension(context, value, unit).map(LengthOrPercentageOrNone::Length)
-            }
-            Token::Percentage { unit_value, .. } if num_context.is_ok(context.parsing_mode, unit_value) => {
-                Ok(LengthOrPercentageOrNone::Percentage(computed::Percentage(unit_value)))
-            }
-            Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => {
-                if value != 0. && !context.parsing_mode.allows_unitless_lengths() &&
-                   !allow_quirks.allowed(context.quirks_mode) {
-                    return Err(StyleParseError::UnspecifiedError.into())
+        // FIXME: remove early returns when lifetimes are non-lexical
+        {
+            let token = input.next()?;
+            match *token {
+                Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => {
+                    return NoCalcLength::parse_dimension(context, value, unit)
+                        .map(LengthOrPercentageOrNone::Length)
+                        .map_err(|()| BasicParseError::UnexpectedToken(token.clone()).into())
+                }
+                Token::Percentage { unit_value, .. } if num_context.is_ok(context.parsing_mode, unit_value) => {
+                    return Ok(LengthOrPercentageOrNone::Percentage(computed::Percentage(unit_value)))
                 }
-                Ok(LengthOrPercentageOrNone::Length(
-                    NoCalcLength::Absolute(AbsoluteLength::Px(value))
-                ))
+                Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => {
+                    if value != 0. && !context.parsing_mode.allows_unitless_lengths() &&
+                       !allow_quirks.allowed(context.quirks_mode) {
+                        return Err(StyleParseError::UnspecifiedError.into())
+                    }
+                    return Ok(LengthOrPercentageOrNone::Length(
+                        NoCalcLength::Absolute(AbsoluteLength::Px(value))
+                    ))
+                }
+                Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {}
+                Token::Ident(ref value) if value.eq_ignore_ascii_case("none") => {
+                    return Ok(LengthOrPercentageOrNone::None)
+                }
+                _ => return Err(BasicParseError::UnexpectedToken(token.clone()).into())
             }
-            Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
-                let calc = input.parse_nested_block(|i| {
-                    CalcNode::parse_length_or_percentage(context, i, num_context)
-                })?;
-                Ok(LengthOrPercentageOrNone::Calc(Box::new(calc)))
-            }
-            Token::Ident(ref value) if value.eq_ignore_ascii_case("none") =>
-                Ok(LengthOrPercentageOrNone::None),
-            _ => Err(())
-        }.map_err(|()| BasicParseError::UnexpectedToken(token).into())
+        }
+
+        let calc = input.parse_nested_block(|i| {
+            CalcNode::parse_length_or_percentage(context, i, num_context)
+        })?;
+        Ok(LengthOrPercentageOrNone::Calc(Box::new(calc)))
     }
 
     /// Parse a non-negative LengthOrPercentageOrNone.
     #[inline]
     pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                                       -> Result<Self, ParseError<'i>> {
         Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
     }
--- a/servo/components/style/values/specified/mod.rs
+++ b/servo/components/style/values/specified/mod.rs
@@ -7,17 +7,16 @@
 //! TODO(emilio): Enhance docs.
 
 use Namespace;
 use context::QuirksMode;
 use cssparser::{Parser, Token, serialize_identifier, BasicParseError};
 use parser::{ParserContext, Parse};
 use self::url::SpecifiedUrl;
 use std::ascii::AsciiExt;
-use std::borrow::Cow;
 use std::f32;
 use std::fmt;
 use style_traits::{ToCss, ParseError, StyleParseError};
 use style_traits::values::specified::AllowedNumericType;
 use super::{Auto, CSSFloat, CSSInteger, Either, None_};
 use super::computed::{self, Context, ToComputedValue};
 use super::generics::grid::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize};
 use super::generics::grid::TrackList as GenericTrackList;
@@ -78,75 +77,77 @@ use values::computed::ComputedValueAsSpe
 #[cfg(feature = "servo")]
 pub use ::servo::url::*;
 #[cfg(feature = "gecko")]
 pub use ::gecko::url::*;
 
 impl Parse for SpecifiedUrl {
     fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         let url = input.expect_url()?;
-        Self::parse_from_string(url.into_owned(), context)
+        Self::parse_from_string(url.as_ref().to_owned(), context)
     }
 }
 
 impl Eq for SpecifiedUrl {}
 
 // TODO(emilio): Maybe consider ComputedUrl to save a word in style structs?
 impl ComputedValueAsSpecified for SpecifiedUrl {}
 
 no_viewport_percentage!(SpecifiedUrl);
 }
 
 /// Parse an `<integer>` value, handling `calc()` correctly.
 pub fn parse_integer<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                              -> Result<Integer, ParseError<'i>> {
-    match input.next()? {
-        Token::Number { int_value: Some(v), .. } => Ok(Integer::new(v)),
-        Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
-            let result = input.parse_nested_block(|i| {
-                CalcNode::parse_integer(context, i)
-            })?;
+    // FIXME: remove early returns when lifetimes are non-lexical
+    match *input.next()? {
+        Token::Number { int_value: Some(v), .. } => return Ok(Integer::new(v)),
+        Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {}
+        ref t => return Err(BasicParseError::UnexpectedToken(t.clone()).into())
+    }
 
-            Ok(Integer::from_calc(result))
-        }
-        t => Err(BasicParseError::UnexpectedToken(t).into())
-    }
+    let result = input.parse_nested_block(|i| {
+        CalcNode::parse_integer(context, i)
+    })?;
+
+    Ok(Integer::from_calc(result))
 }
 
 /// Parse a `<number>` value, handling `calc()` correctly, and without length
 /// limitations.
 pub fn parse_number<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                             -> Result<Number, ParseError<'i>> {
     parse_number_with_clamping_mode(context, input, AllowedNumericType::All)
 }
 
 /// Parse a `<number>` value, with a given clamping mode.
 pub fn parse_number_with_clamping_mode<'i, 't>(context: &ParserContext,
                                                input: &mut Parser<'i, 't>,
                                                clamping_mode: AllowedNumericType)
                                                -> Result<Number, ParseError<'i>> {
-    match input.next()? {
+    // FIXME: remove early returns when lifetimes are non-lexical
+    match *input.next()? {
         Token::Number { value, .. } if clamping_mode.is_ok(context.parsing_mode, value) => {
-            Ok(Number {
+            return Ok(Number {
                 value: value.min(f32::MAX).max(f32::MIN),
                 calc_clamping_mode: None,
             })
-        },
-        Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
-            let result = input.parse_nested_block(|i| {
-                CalcNode::parse_number(context, i)
-            })?;
+        }
+        Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {}
+        ref t => return Err(BasicParseError::UnexpectedToken(t.clone()).into())
+    }
 
-            Ok(Number {
-                value: result.min(f32::MAX).max(f32::MIN),
-                calc_clamping_mode: Some(clamping_mode),
-            })
-        }
-        t => Err(BasicParseError::UnexpectedToken(t).into())
-    }
+    let result = input.parse_nested_block(|i| {
+        CalcNode::parse_number(context, i)
+    })?;
+
+    Ok(Number {
+        value: result.min(f32::MAX).max(f32::MIN),
+        calc_clamping_mode: Some(clamping_mode),
+    })
 }
 
 #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
 /// An angle consisting of a value and a unit.
 ///
 /// Computed Angle is essentially same as specified angle except calc
 /// value serialization. Therefore we are using computed Angle enum
@@ -223,26 +224,27 @@ impl Angle {
             was_calc: true,
         }
     }
 }
 
 impl Parse for Angle {
     /// Parses an angle according to CSS-VALUES § 6.1.
     fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
-        let token = input.next()?;
+        // FIXME: remove clone() when lifetimes are non-lexical
+        let token = input.next()?.clone();
         match token {
             Token::Dimension { value, ref unit, .. } => {
                 Angle::parse_dimension(value, unit, /* from_calc = */ false)
             }
             Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
                 return input.parse_nested_block(|i| CalcNode::parse_angle(context, i))
             }
             _ => Err(())
-        }.map_err(|()| BasicParseError::UnexpectedToken(token).into())
+        }.map_err(|()| BasicParseError::UnexpectedToken(token.clone()).into())
     }
 }
 
 impl Angle {
     /// Parse an `<angle>` value given a value and an unit.
     pub fn parse_dimension(
         value: CSSFloat,
         unit: &str,
@@ -263,27 +265,28 @@ impl Angle {
     /// Note that numbers without any AngleUnit, including unitless 0 angle,
     /// should be invalid. However, some properties still accept unitless 0
     /// angle and stores it as '0deg'.
     ///
     /// We can remove this and get back to the unified version Angle::parse once
     /// https://github.com/w3c/csswg-drafts/issues/1162 is resolved.
     pub fn parse_with_unitless<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                                        -> Result<Self, ParseError<'i>> {
-        let token = input.next()?;
+        // FIXME: remove clone() when lifetimes are non-lexical
+        let token = input.next()?.clone();
         match token {
             Token::Dimension { value, ref unit, .. } => {
                 Angle::parse_dimension(value, unit, /* from_calc = */ false)
             }
             Token::Number { value, .. } if value == 0. => Ok(Angle::zero()),
             Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
                 return input.parse_nested_block(|i| CalcNode::parse_angle(context, i))
             }
             _ => Err(())
-        }.map_err(|()| BasicParseError::UnexpectedToken(token).into())
+        }.map_err(|()| BasicParseError::UnexpectedToken(token.clone()).into())
     }
 }
 
 // The integer values here correspond to the border conflict resolution rules in CSS 2.1 §
 // 17.6.2.1. Higher values override lower values.
 define_numbered_css_keyword_enum! { BorderStyle:
     "none" => none = -1,
     "solid" => solid = 6,
@@ -361,34 +364,34 @@ impl Time {
     }
 
     fn parse_with_clamping_mode<'i, 't>(context: &ParserContext,
                                         input: &mut Parser<'i, 't>,
                                         clamping_mode: AllowedNumericType)
                                         -> Result<Self, ParseError<'i>> {
         use style_traits::PARSING_MODE_DEFAULT;
 
+        // FIXME: remove early returns when lifetimes are non-lexical
         match input.next() {
             // Note that we generally pass ParserContext to is_ok() to check
             // that the ParserMode of the ParserContext allows all numeric
             // values for SMIL regardless of clamping_mode, but in this Time
             // value case, the value does not animate for SMIL at all, so we use
             // PARSING_MODE_DEFAULT directly.
-            Ok(Token::Dimension { value, ref unit, .. }) if clamping_mode.is_ok(PARSING_MODE_DEFAULT, value) => {
-                Time::parse_dimension(value, unit, /* from_calc = */ false)
+            Ok(&Token::Dimension { value, ref unit, .. }) if clamping_mode.is_ok(PARSING_MODE_DEFAULT, value) => {
+                return Time::parse_dimension(value, unit, /* from_calc = */ false)
                     .map_err(|()| StyleParseError::UnspecifiedError.into())
             }
-            Ok(Token::Function(ref name)) if name.eq_ignore_ascii_case("calc") => {
-                match input.parse_nested_block(|i| CalcNode::parse_time(context, i)) {
-                    Ok(time) if clamping_mode.is_ok(PARSING_MODE_DEFAULT, time.seconds) => Ok(time),
-                    _ => Err(StyleParseError::UnspecifiedError.into()),
-                }
-            }
-            Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
-            Err(e) => Err(e.into())
+            Ok(&Token::Function(ref name)) if name.eq_ignore_ascii_case("calc") => {}
+            Ok(t) => return Err(BasicParseError::UnexpectedToken(t.clone()).into()),
+            Err(e) => return Err(e.into())
+        }
+        match input.parse_nested_block(|i| CalcNode::parse_time(context, i)) {
+            Ok(time) if clamping_mode.is_ok(PARSING_MODE_DEFAULT, time.seconds) => Ok(time),
+            _ => Err(StyleParseError::UnspecifiedError.into()),
         }
     }
 
     /// Parse <time> that values are non-negative.
     pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                                       -> Result<Self, ParseError<'i>> {
         Self::parse_with_clamping_mode(context, input, AllowedNumericType::NonNegative)
     }
@@ -809,20 +812,17 @@ impl ClipRect {
                                   allow_quirks: AllowQuirks) -> Result<Option<Length>, ParseError<'i>> {
             if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
                 Ok(None)
             } else {
                 Length::parse_quirky(context, input, allow_quirks).map(Some)
             }
         }
 
-        let func = input.expect_function()?;
-        if !func.eq_ignore_ascii_case("rect") {
-            return Err(StyleParseError::UnexpectedFunction(func).into())
-        }
+        input.expect_function_matching("rect")?;
 
         input.parse_nested_block(|input| {
             let top = parse_argument(context, input, allow_quirks)?;
             let right;
             let bottom;
             let left;
 
             if input.try(|input| input.expect_comma()).is_ok() {
@@ -934,47 +934,47 @@ fn get_id_for_namespace(_: &Namespace, _
 
 impl Attr {
     /// Parse contents of attr() assuming we have already parsed `attr` and are
     /// within a parse_nested_block()
     pub fn parse_function<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                                   -> Result<Attr, ParseError<'i>> {
         // Syntax is `[namespace? `|`]? ident`
         // no spaces allowed
-        let first = input.try(|i| i.expect_ident()).ok();
-        if let Ok(token) = input.try(|i| i.next_including_whitespace()) {
+        let first = input.try(|i| i.expect_ident_cloned()).ok();
+        if let Ok(token) = input.try(|i| i.next_including_whitespace().map(|t| t.clone())) {
             match token {
                 Token::Delim('|') => {}
-                t => return Err(BasicParseError::UnexpectedToken(t).into()),
+                ref t => return Err(BasicParseError::UnexpectedToken(t.clone()).into()),
             }
             // must be followed by an ident
-            let second_token = match input.next_including_whitespace()? {
-                Token::Ident(second) => second,
-                t => return Err(BasicParseError::UnexpectedToken(t).into()),
+            let second_token = match *input.next_including_whitespace()? {
+                Token::Ident(ref second) => second,
+                ref t => return Err(BasicParseError::UnexpectedToken(t.clone()).into()),
             };
 
             let ns_with_id = if let Some(ns) = first {
-                let ns = Namespace::from(Cow::from(ns));
+                let ns = Namespace::from(ns.as_ref());
                 let id: Result<_, ParseError> =
                     get_id_for_namespace(&ns, context)
                     .map_err(|()| StyleParseError::UnspecifiedError.into());
                 Some((ns, id?))
             } else {
                 None
             };
             return Ok(Attr {
                 namespace: ns_with_id,
-                attribute: second_token.into_owned(),
+                attribute: second_token.as_ref().to_owned(),
             })
         }
 
         if let Some(first) = first {
             Ok(Attr {
                 namespace: None,
-                attribute: first.into_owned(),
+                attribute: first.as_ref().to_owned(),
             })
         } else {
             Err(StyleParseError::UnspecifiedError.into())
         }
     }
 }
 
 impl ToCss for Attr {
--- a/servo/components/style/values/specified/text.rs
+++ b/servo/components/style/values/specified/text.rs
@@ -68,17 +68,17 @@ impl Parse for LineHeight {
         match ident {
             ref ident if ident.eq_ignore_ascii_case("normal") => {
                 Ok(GenericLineHeight::Normal)
             },
             #[cfg(feature = "gecko")]
             ref ident if ident.eq_ignore_ascii_case("-moz-block-height") => {
                 Ok(GenericLineHeight::MozBlockHeight)
             },
-            ident => Err(SelectorParseError::UnexpectedIdent(ident).into()),
+            ident => Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()),
         }
     }
 }
 
 impl ToComputedValue for LineHeight {
     type ComputedValue = ComputedLineHeight;
 
     #[inline]
--- a/servo/components/style/values/specified/transform.rs
+++ b/servo/components/style/values/specified/transform.rs
@@ -142,25 +142,25 @@ fn allow_frames_timing() -> bool {
 #[inline]
 fn allow_frames_timing() -> bool { true }
 
 impl Parse for TimingFunction {
     fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         if let Ok(keyword) = input.try(TimingKeyword::parse) {
             return Ok(GenericTimingFunction::Keyword(keyword));
         }
-        if let Ok(ident) = input.try(|i| i.expect_ident()) {
+        if let Ok(ident) = input.try(|i| i.expect_ident_cloned()) {
             let position = match_ignore_ascii_case! { &ident,
                 "step-start" => StepPosition::Start,
                 "step-end" => StepPosition::End,
                 _ => return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()),
             };
             return Ok(GenericTimingFunction::Steps(Integer::new(1), position));
         }
-        let function = input.expect_function()?;
+        let function = input.expect_function()?.clone();
         input.parse_nested_block(move |i| {
             (match_ignore_ascii_case! { &function,
                 "cubic-bezier" => {
                     let x1 = Number::parse(context, i)?;
                     i.expect_comma()?;
                     let y1 = Number::parse(context, i)?;
                     i.expect_comma()?;
                     let x2 = Number::parse(context, i)?;
@@ -185,17 +185,17 @@ impl Parse for TimingFunction {
                     if allow_frames_timing() {
                         let frames = Integer::parse_with_minimum(context, i, 2)?;
                         Ok(GenericTimingFunction::Frames(frames))
                     } else {
                         Err(())
                     }
                 },
                 _ => Err(()),
-            }).map_err(|()| StyleParseError::UnexpectedFunction(function).into())
+            }).map_err(|()| StyleParseError::UnexpectedFunction(function.clone()).into())
         })
     }
 }
 
 impl ToComputedValue for TimingFunction {
     type ComputedValue = ComputedTimingFunction;
 
     #[inline]
--- a/servo/components/style_traits/Cargo.toml
+++ b/servo/components/style_traits/Cargo.toml
@@ -11,14 +11,14 @@ path = "lib.rs"
 
 [features]
 servo = ["heapsize", "heapsize_derive", "serde", "cssparser/heapsize", "cssparser/serde"]
 gecko = []
 
 [dependencies]
 app_units = "0.5"
 bitflags = "0.7"
-cssparser = "0.17.0"
+cssparser = "0.18"
 euclid = "0.15"
 heapsize = {version = "0.4", optional = true}
 heapsize_derive = {version = "0.1", optional = true}
 selectors = { path = "../selectors" }
 serde = {version = "1.0", optional = true}
--- a/servo/components/style_traits/lib.rs
+++ b/servo/components/style_traits/lib.rs
@@ -17,17 +17,17 @@ extern crate app_units;
 #[macro_use] extern crate bitflags;
 #[macro_use] extern crate cssparser;
 extern crate euclid;
 #[cfg(feature = "servo")] extern crate heapsize;
 #[cfg(feature = "servo")] #[macro_use] extern crate heapsize_derive;
 extern crate selectors;
 #[cfg(feature = "servo")] #[macro_use] extern crate serde;
 
-use cssparser::{CompactCowStr, Token};
+use cssparser::{CowRcStr, Token};
 use selectors::parser::SelectorParseError;
 
 /// Opaque type stored in type-unsafe work queues for parallel layout.
 /// Must be transmutable to and from `TNode`.
 pub type UnsafeNode = (usize, usize);
 
 /// Represents a mobile style pinch zoom factor.
 /// TODO(gw): Once WR supports pinch zoom, use a type directly from webrender_api.
@@ -82,60 +82,60 @@ pub use viewport::HasViewportPercentage;
 
 /// The error type for all CSS parsing routines.
 pub type ParseError<'i> = cssparser::ParseError<'i, SelectorParseError<'i, StyleParseError<'i>>>;
 
 #[derive(Clone, Debug, PartialEq)]
 /// Errors that can be encountered while parsing CSS values.
 pub enum StyleParseError<'i> {
     /// A bad URL token in a DVB.
-    BadUrlInDeclarationValueBlock(CompactCowStr<'i>),
+    BadUrlInDeclarationValueBlock(CowRcStr<'i>),
     /// A bad string token in a DVB.
-    BadStringInDeclarationValueBlock(CompactCowStr<'i>),
+    BadStringInDeclarationValueBlock(CowRcStr<'i>),
     /// Unexpected closing parenthesis in a DVB.
     UnbalancedCloseParenthesisInDeclarationValueBlock,
     /// Unexpected closing bracket in a DVB.
     UnbalancedCloseSquareBracketInDeclarationValueBlock,
     /// Unexpected closing curly bracket in a DVB.
     UnbalancedCloseCurlyBracketInDeclarationValueBlock,
     /// A property declaration parsing error.
     PropertyDeclaration(PropertyDeclarationParseError<'i>),
     /// A property declaration value had input remaining after successfully parsing.
     PropertyDeclarationValueNotExhausted,
     /// An unexpected dimension token was encountered.
-    UnexpectedDimension(CompactCowStr<'i>),
+    UnexpectedDimension(CowRcStr<'i>),
     /// A media query using a ranged expression with no value was encountered.
     RangedExpressionWithNoValue,
     /// A function was encountered that was not expected.
-    UnexpectedFunction(CompactCowStr<'i>),
+    UnexpectedFunction(CowRcStr<'i>),
     /// @namespace must be before any rule but @charset and @import
     UnexpectedNamespaceRule,
     /// @import must be before any rule but @charset
     UnexpectedImportRule,
     /// Unexpected @charset rule encountered.
     UnexpectedCharsetRule,
     /// Unsupported @ rule
-    UnsupportedAtRule(CompactCowStr<'i>),
+    UnsupportedAtRule(CowRcStr<'i>),
     /// A placeholder for many sources of errors that require more specific variants.
     UnspecifiedError,
     /// An unexpected token was found within a namespace rule.
     UnexpectedTokenWithinNamespace(Token<'i>),
 }
 
 /// The result of parsing a property declaration.
 #[derive(Eq, PartialEq, Clone, Debug)]
 pub enum PropertyDeclarationParseError<'i> {
     /// The property declaration was for an unknown property.
-    UnknownProperty(CompactCowStr<'i>),
+    UnknownProperty(CowRcStr<'i>),
     /// An unknown vendor-specific identifier was encountered.
     UnknownVendorProperty,
     /// The property declaration was for a disabled experimental property.
     ExperimentalProperty,
     /// The property declaration contained an invalid value.
-    InvalidValue(CompactCowStr<'i>),
+    InvalidValue(CowRcStr<'i>),
     /// The declaration contained an animation property, and we were parsing
     /// this as a keyframe block (so that property should be ignored).
     ///
     /// See: https://drafts.csswg.org/css-animations/#keyframes
     AnimationPropertyInKeyframeBlock,
     /// The property is not allowed within a page rule.
     NotAllowedInPageRule,
 }
--- a/servo/components/style_traits/values.rs
+++ b/servo/components/style_traits/values.rs
@@ -404,17 +404,17 @@ macro_rules! __define_css_keyword_enum__
         impl $name {
             /// Parse this property from a CSS input stream.
             pub fn parse<'i, 't>(input: &mut ::cssparser::Parser<'i, 't>)
                                  -> Result<$name, $crate::ParseError<'i>> {
                 let ident = input.expect_ident()?;
                 Self::from_ident(&ident)
                     .map_err(|()| ::cssparser::ParseError::Basic(
                         ::cssparser::BasicParseError::UnexpectedToken(
-                            ::cssparser::Token::Ident(ident))))
+                            ::cssparser::Token::Ident(ident.clone()))))
             }
 
             /// Parse this property from an already-tokenized identifier.
             pub fn from_ident(ident: &str) -> Result<$name, ()> {
                 match_ignore_ascii_case! { ident,
                                            $( $css => Ok($name::$variant), )+
                                            $( $alias => Ok($name::$alias_variant), )*
                                            _ => Err(())
--- a/servo/components/style_traits/viewport.rs
+++ b/servo/components/style_traits/viewport.rs
@@ -149,31 +149,31 @@ impl Zoom {
     /// Parse a zoom value per:
     ///
     /// https://drafts.csswg.org/css-device-adapt/#descdef-viewport-zoom
     pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Zoom, ParseError<'i>> {
         use PARSING_MODE_DEFAULT;
         use cssparser::Token;
         use values::specified::AllowedLengthType::NonNegative;
 
-        match input.next()? {
+        match *input.next()? {
             // TODO: This parse() method should take ParserContext as an
             // argument, and pass ParsingMode owned by the ParserContext to
             // is_ok() instead of using PARSING_MODE_DEFAULT directly.
             // In order to do so, we might want to move these stuff into style::stylesheets::viewport_rule.
             Token::Percentage { unit_value, .. } if NonNegative.is_ok(PARSING_MODE_DEFAULT, unit_value) => {
                 Ok(Zoom::Percentage(unit_value))
             }
             Token::Number { value, .. } if NonNegative.is_ok(PARSING_MODE_DEFAULT, value) => {
                 Ok(Zoom::Number(value))
             }
             Token::Ident(ref value) if value.eq_ignore_ascii_case("auto") => {
                 Ok(Zoom::Auto)
             }
-            t => Err(CssParseError::Basic(BasicParseError::UnexpectedToken(t)))
+            ref t => Err(CssParseError::Basic(BasicParseError::UnexpectedToken(t.clone())))
         }
     }
 
     /// Get this zoom value as a float value. Returns `None` if the value is the
     /// `auto` keyword.
     #[inline]
     pub fn to_f32(&self) -> Option<f32> {
         match *self {
--- a/servo/ports/geckolib/Cargo.toml
+++ b/servo/ports/geckolib/Cargo.toml
@@ -11,17 +11,17 @@ crate-type = ["staticlib", "rlib"]
 
 [features]
 bindgen = ["style/use_bindgen"]
 testing = ["style/testing"]
 gecko_debug = ["style/gecko_debug"]
 
 [dependencies]
 atomic_refcell = "0.1"
-cssparser = "0.17.0"
+cssparser = "0.18"
 env_logger = {version = "0.4", default-features = false} # disable `regex` to reduce code size
 libc = "0.2"
 log = {version = "0.3.5", features = ["release_max_level_info"]}
 nsstring_vendor = {path = "../../components/style/gecko_bindings/nsstring_vendor"}
 parking_lot = "0.4"
 selectors = {path = "../../components/selectors"}
 servo_arc = {path = "../../components/servo_arc"}
 style = {path = "../../components/style", features = ["gecko"]}
--- a/servo/ports/geckolib/error_reporter.rs
+++ b/servo/ports/geckolib/error_reporter.rs
@@ -2,17 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Wrapper around Gecko's CSS error reporting mechanism.
 
 #![allow(unsafe_code)]
 
 use cssparser::{Parser, SourcePosition, ParseError as CssParseError, Token, BasicParseError};
-use cssparser::CompactCowStr;
+use cssparser::CowRcStr;
 use selectors::parser::SelectorParseError;
 use style::error_reporting::{ParseErrorReporter, ContextualParseError};
 use style::gecko_bindings::bindings::{Gecko_CreateCSSErrorReporter, Gecko_DestroyCSSErrorReporter};
 use style::gecko_bindings::bindings::Gecko_ReportUnexpectedCSSError;
 use style::gecko_bindings::structs::{Loader, ServoStyleSheet, nsIURI};
 use style::gecko_bindings::structs::ErrorReporter as GeckoErrorReporter;
 use style::gecko_bindings::structs::URLExtraData as RawUrlExtraData;
 use style::gecko_bindings::sugar::refptr::RefPtr;
@@ -38,25 +38,25 @@ impl Drop for ErrorReporter {
     fn drop(&mut self) {
         unsafe {
             Gecko_DestroyCSSErrorReporter(self.0);
         }
     }
 }
 
 enum ErrorString<'a> {
-    Snippet(CompactCowStr<'a>),
-    Ident(CompactCowStr<'a>),
+    Snippet(CowRcStr<'a>),
+    Ident(CowRcStr<'a>),
     UnexpectedToken(Token<'a>),
 }
 
 impl<'a> ErrorString<'a> {
     fn into_str(self) -> String {
         match self {
-            ErrorString::Snippet(s) => s.into_owned(),
+            ErrorString::Snippet(s) => s.as_ref().to_owned(),
             ErrorString::Ident(i) => escape_css_ident(&i),
             ErrorString::UnexpectedToken(t) => token_to_str(t),
         }
     }
 }
 
 // This is identical to the behaviour of cssparser::serialize_identifier, except that
 // it uses numerical escapes for a larger set of characters.
@@ -181,23 +181,23 @@ fn token_to_str<'a>(t: Token<'a>) -> Str
         Token::BadString(s) => format!("'{}", escape_css_string(&s)).into(),
         Token::CloseParenthesis => "unmatched close parenthesis".into(),
         Token::CloseSquareBracket => "unmatched close square bracket".into(),
         Token::CloseCurlyBracket => "unmatched close curly bracket".into(),
     }
 }
 
 trait ErrorHelpers<'a> {
-    fn error_data(self) -> (CompactCowStr<'a>, ParseError<'a>);
+    fn error_data(self) -> (CowRcStr<'a>, ParseError<'a>);
     fn error_param(self) -> ErrorString<'a>;
     fn to_gecko_message(&self) -> &'static [u8];
 }
 
 impl<'a> ErrorHelpers<'a> for ContextualParseError<'a> {
-    fn error_data(self) -> (CompactCowStr<'a>, ParseError<'a>) {
+    fn error_data(self) -> (CowRcStr<'a>, ParseError<'a>) {
         match self {
             ContextualParseError::UnsupportedPropertyDeclaration(s, err) |
             ContextualParseError::UnsupportedFontFaceDescriptor(s, err) |
             ContextualParseError::InvalidKeyframeRule(s, err) |
             ContextualParseError::UnsupportedKeyframePropertyDeclaration(s, err) |
             ContextualParseError::InvalidRule(s, err) |
             ContextualParseError::UnsupportedRule(s, err) |
             ContextualParseError::UnsupportedViewportDescriptorDeclaration(s, err) |
--- a/servo/tests/unit/gfx/Cargo.toml
+++ b/servo/tests/unit/gfx/Cargo.toml
@@ -5,12 +5,12 @@ authors = ["The Servo Project Developers
 license = "MPL-2.0"
 
 [lib]
 name = "gfx_tests"
 path = "lib.rs"
 doctest = false
 
 [dependencies]
-cssparser = "0.17.0"
+cssparser = "0.18"
 gfx = {path = "../../../components/gfx"}
 ipc-channel = "0.8"
 style = {path = "../../../components/style"}
--- a/servo/tests/unit/style/Cargo.toml
+++ b/servo/tests/unit/style/Cargo.toml
@@ -10,17 +10,17 @@ path = "lib.rs"
 doctest = false
 
 [features]
 testing = ["style/testing"]
 
 [dependencies]
 byteorder = "1.0"
 app_units = "0.5"
-cssparser = "0.17.0"
+cssparser = "0.18"
 euclid = "0.15"
 html5ever = "0.18"
 parking_lot = "0.4"
 rayon = "0.8"
 rustc-serialize = "0.3"
 selectors = {path = "../../../components/selectors"}
 servo_arc = {path = "../../../components/servo_arc"}
 servo_atoms = {path = "../../../components/atoms"}
--- a/servo/tests/unit/stylo/Cargo.toml
+++ b/servo/tests/unit/stylo/Cargo.toml
@@ -11,17 +11,17 @@ name = "stylo_tests"
 path = "lib.rs"
 doctest = false
 
 [features]
 testing = ["style/testing"]
 
 [dependencies]
 atomic_refcell = "0.1"
-cssparser = "0.17.0"
+cssparser = "0.18"
 env_logger = "0.4"
 euclid = "0.15"
 geckoservo = {path = "../../../ports/geckolib"}
 libc = "0.2"
 log = {version = "0.3.5", features = ["release_max_level_info"]}
 selectors = {path = "../../../components/selectors", features = ["gecko_like_types"]}
 size_of_test = {path = "../../../components/size_of_test"}
 style_traits = {path = "../../../components/style_traits"}