servo: Merge #15115 - Introduce the `NoCalcLength` (from Wafflespeanut:lop); r=emilio
authorRavi Shankar <wafflespeanut@gmail.com>
Sat, 28 Jan 2017 14:08:38 -0800
changeset 340678 eee0049755a520cb21e3767ff18f7750400f5c0f
parent 340677 2e5cea5fbfc820d802080f70ecaacc2b149a0e48
child 340679 4a183a7e33ffb5aa67423a1be616d24713e34b56
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
servo: Merge #15115 - Introduce the `NoCalcLength` (from Wafflespeanut:lop); r=emilio <!-- Please describe your changes on the following line: --> I began this for making the `CalcLengthOrPercentage` represent `LengthOrPercentage` (instead of the enum we already have), but only later did I realize that it will make `LengthOrPercentageOrFoo` types fatty (which is the problem we're trying to avoid - #15061) and so, I dropped that attempt. Along the way, I introduced an internal type for `Length`, for representing all its non-calc variants (which are `Copy`). We could still have this type for the `LengthOrPercentageOrFoo` types which don't really need `Length` since they already have their own variants for calc. r? @Manishearth @emilio @SimonSapin or anyone interested --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors <!-- Either: --> - [x] These changes do not require tests because it's a refactor <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: cd0a6b98f4a9073e9ac98409c2fa917643552181
servo/components/script/dom/element.rs
servo/components/style/gecko/media_queries.rs
servo/components/style/properties/longhand/box.mako.rs
servo/components/style/properties/longhand/effects.mako.rs
servo/components/style/properties/longhand/font.mako.rs
servo/components/style/properties/longhand/inherited_text.mako.rs
servo/components/style/properties/shorthand/inherited_text.mako.rs
servo/components/style/properties/shorthand/position.mako.rs
servo/components/style/values/computed/length.rs
servo/components/style/values/computed/mod.rs
servo/components/style/values/specified/basic_shape.rs
servo/components/style/values/specified/length.rs
servo/components/style/values/specified/mod.rs
servo/components/style/viewport.rs
servo/tests/unit/style/media_queries.rs
servo/tests/unit/style/properties/serialization.rs
servo/tests/unit/style/properties/viewport.rs
servo/tests/unit/style/value.rs
servo/tests/unit/style/viewport.rs
--- a/servo/components/script/dom/element.rs
+++ b/servo/components/script/dom/element.rs
@@ -1,15 +1,14 @@
 /* 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/. */
 
 //! Element nodes.
 
-use app_units::Au;
 use cssparser::Color;
 use devtools_traits::AttrInfo;
 use dom::activation::Activatable;
 use dom::attr::{Attr, AttrHelpersForLayout};
 use dom::bindings::cell::DOMRefCell;
 use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
 use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
 use dom::bindings::codegen::Bindings::ElementBinding;
@@ -450,38 +449,33 @@ impl LayoutElementHelpers for LayoutJS<E
             hints.push(from_declaration(
                 PropertyDeclaration::FontFamily(
                     DeclaredValue::Value(
                         font_family::computed_value::T(vec![
                             font_family::computed_value::FontFamily::from_atom(
                                 font_family)])))));
         }
 
-        let font_size = if let Some(this) = self.downcast::<HTMLFontElement>() {
-            this.get_size()
-        } else {
-            None
-        };
+        let font_size = self.downcast::<HTMLFontElement>().and_then(|this| this.get_size());
 
         if let Some(font_size) = font_size {
             hints.push(from_declaration(
                 PropertyDeclaration::FontSize(
                     DeclaredValue::Value(
-                        font_size::SpecifiedValue(
-                            LengthOrPercentage::Length(font_size))))))
+                        font_size::SpecifiedValue(font_size.into())))))
         }
 
         let cellspacing = if let Some(this) = self.downcast::<HTMLTableElement>() {
             this.get_cellspacing()
         } else {
             None
         };
 
         if let Some(cellspacing) = cellspacing {
-            let width_value = specified::Length::Absolute(Au::from_px(cellspacing as i32));
+            let width_value = specified::Length::from_px(cellspacing as f32);
             hints.push(from_declaration(
                 PropertyDeclaration::BorderSpacing(DeclaredValue::Value(
                     border_spacing::SpecifiedValue {
                         horizontal: width_value.clone(),
                         vertical: width_value,
                     }))));
         }
 
@@ -504,23 +498,22 @@ impl LayoutElementHelpers for LayoutJS<E
                     }
                 },
             }
         } else {
             None
         };
 
         if let Some(size) = size {
-            let value = specified::Length::ServoCharacterWidth(specified::CharacterWidth(size));
+            let value = specified::NoCalcLength::ServoCharacterWidth(specified::CharacterWidth(size));
             hints.push(from_declaration(
                 PropertyDeclaration::Width(DeclaredValue::Value(
                     specified::LengthOrPercentageOrAuto::Length(value)))));
         }
 
-
         let width = if let Some(this) = self.downcast::<HTMLIFrameElement>() {
             this.get_width()
         } else if let Some(this) = self.downcast::<HTMLImageElement>() {
             this.get_width()
         } else if let Some(this) = self.downcast::<HTMLTableElement>() {
             this.get_width()
         } else if let Some(this) = self.downcast::<HTMLTableCellElement>() {
             this.get_width()
@@ -536,17 +529,17 @@ impl LayoutElementHelpers for LayoutJS<E
             LengthOrPercentageOrAuto::Percentage(percentage) => {
                 let width_value =
                     specified::LengthOrPercentageOrAuto::Percentage(specified::Percentage(percentage));
                 hints.push(from_declaration(
                     PropertyDeclaration::Width(DeclaredValue::Value(width_value))));
             }
             LengthOrPercentageOrAuto::Length(length) => {
                 let width_value = specified::LengthOrPercentageOrAuto::Length(
-                    specified::Length::Absolute(length));
+                    specified::NoCalcLength::Absolute(length));
                 hints.push(from_declaration(
                     PropertyDeclaration::Width(DeclaredValue::Value(width_value))));
             }
         }
 
 
         let height = if let Some(this) = self.downcast::<HTMLIFrameElement>() {
             this.get_height()
@@ -561,17 +554,17 @@ impl LayoutElementHelpers for LayoutJS<E
             LengthOrPercentageOrAuto::Percentage(percentage) => {
                 let height_value =
                     specified::LengthOrPercentageOrAuto::Percentage(specified::Percentage(percentage));
                 hints.push(from_declaration(
                     PropertyDeclaration::Height(DeclaredValue::Value(height_value))));
             }
             LengthOrPercentageOrAuto::Length(length) => {
                 let height_value = specified::LengthOrPercentageOrAuto::Length(
-                    specified::Length::Absolute(length));
+                    specified::NoCalcLength::Absolute(length));
                 hints.push(from_declaration(
                     PropertyDeclaration::Height(DeclaredValue::Value(height_value))));
             }
         }
 
 
         let cols = if let Some(this) = self.downcast::<HTMLTextAreaElement>() {
             match this.get_cols() {
@@ -583,52 +576,50 @@ impl LayoutElementHelpers for LayoutJS<E
         };
 
         if let Some(cols) = cols {
             // TODO(mttr) ServoCharacterWidth uses the size math for <input type="text">, but
             // the math for <textarea> is a little different since we need to take
             // scrollbar size into consideration (but we don't have a scrollbar yet!)
             //
             // https://html.spec.whatwg.org/multipage/#textarea-effective-width
-            let value = specified::Length::ServoCharacterWidth(specified::CharacterWidth(cols));
+            let value = specified::NoCalcLength::ServoCharacterWidth(specified::CharacterWidth(cols));
             hints.push(from_declaration(
                 PropertyDeclaration::Width(DeclaredValue::Value(
                     specified::LengthOrPercentageOrAuto::Length(value)))));
         }
 
-
         let rows = if let Some(this) = self.downcast::<HTMLTextAreaElement>() {
             match this.get_rows() {
                 0 => None,
                 r => Some(r as i32),
             }
         } else {
             None
         };
 
         if let Some(rows) = rows {
             // TODO(mttr) This should take scrollbar size into consideration.
             //
             // https://html.spec.whatwg.org/multipage/#textarea-effective-height
-            let value = specified::Length::FontRelative(specified::FontRelativeLength::Em(rows as CSSFloat));
+            let value = specified::NoCalcLength::FontRelative(specified::FontRelativeLength::Em(rows as CSSFloat));
             hints.push(from_declaration(
                 PropertyDeclaration::Height(DeclaredValue::Value(
                         specified::LengthOrPercentageOrAuto::Length(value)))));
         }
 
 
         let border = if let Some(this) = self.downcast::<HTMLTableElement>() {
             this.get_border()
         } else {
             None
         };
 
         if let Some(border) = border {
-            let width_value = specified::BorderWidth::from_length(
-                specified::Length::Absolute(Au::from_px(border as i32)));
+            let width_value = specified::BorderWidth::from_length(specified::Length::from_px(border as f32));
             hints.push(from_declaration(
                 PropertyDeclaration::BorderTopWidth(DeclaredValue::Value(width_value.clone()))));
             hints.push(from_declaration(
                 PropertyDeclaration::BorderLeftWidth(DeclaredValue::Value(width_value.clone()))));
             hints.push(from_declaration(
                 PropertyDeclaration::BorderBottomWidth(DeclaredValue::Value(width_value.clone()))));
             hints.push(from_declaration(
                 PropertyDeclaration::BorderRightWidth(DeclaredValue::Value(width_value))));
--- a/servo/components/style/gecko/media_queries.rs
+++ b/servo/components/style/gecko/media_queries.rs
@@ -231,18 +231,17 @@ impl MediaExpressionValue {
         if css_value.mUnit == nsCSSUnit::eCSSUnit_Null {
             return None;
         }
 
         match for_expr.feature.mValueType {
             nsMediaFeature_ValueType::eLength => {
                 debug_assert!(css_value.mUnit == nsCSSUnit::eCSSUnit_Pixel);
                 let pixels = css_value.float_unchecked();
-                Some(MediaExpressionValue::Length(
-                        specified::Length::Absolute(Au::from_f32_px(pixels))))
+                Some(MediaExpressionValue::Length(specified::Length::from_px(pixels)))
             }
             nsMediaFeature_ValueType::eInteger => {
                 let i = css_value.integer_unchecked();
                 debug_assert!(i >= 0);
                 Some(MediaExpressionValue::Integer(i as u32))
             }
             nsMediaFeature_ValueType::eFloat => {
                 debug_assert!(css_value.mUnit == nsCSSUnit::eCSSUnit_Number);
--- a/servo/components/style/properties/longhand/box.mako.rs
+++ b/servo/components/style/properties/longhand/box.mako.rs
@@ -1323,39 +1323,39 @@
                     }))
                 },
                 "translate" => {
                     try!(input.parse_nested_block(|input| {
                         let (tx, ty) = try!(parse_two_lengths_or_percentages(context, input));
                         result.push(SpecifiedOperation::Translate(TranslateKind::Translate,
                                                                   tx,
                                                                   ty,
-                                                                  specified::Length::Absolute(Au(0))));
+                                                                  specified::Length::zero()));
                         Ok(())
                     }))
                 },
                 "translatex" => {
                     try!(input.parse_nested_block(|input| {
                         let tx = try!(specified::LengthOrPercentage::parse(context, input));
                         result.push(SpecifiedOperation::Translate(
                             TranslateKind::TranslateX,
                             tx,
                             specified::LengthOrPercentage::zero(),
-                            specified::Length::Absolute(Au(0))));
+                            specified::Length::zero()));
                         Ok(())
                     }))
                 },
                 "translatey" => {
                     try!(input.parse_nested_block(|input| {
                         let ty = try!(specified::LengthOrPercentage::parse(context, input));
                         result.push(SpecifiedOperation::Translate(
                             TranslateKind::TranslateY,
                             specified::LengthOrPercentage::zero(),
                             ty,
-                            specified::Length::Absolute(Au(0))));
+                            specified::Length::zero()));
                         Ok(())
                     }))
                 },
                 "translatez" => {
                     try!(input.parse_nested_block(|input| {
                         let tz = try!(specified::Length::parse(context, input));
                         result.push(SpecifiedOperation::Translate(
                             TranslateKind::TranslateZ,
@@ -1756,17 +1756,17 @@
                          animatable=False)}
 
 <%helpers:longhand name="transform-origin" animatable="True" extra_prefixes="moz webkit"
                    spec="https://drafts.csswg.org/css-transforms/#transform-origin-property">
     use app_units::Au;
     use std::fmt;
     use style_traits::ToCss;
     use values::HasViewportPercentage;
-    use values::specified::{Length, LengthOrPercentage, Percentage};
+    use values::specified::{NoCalcLength, LengthOrPercentage, Percentage};
 
     pub mod computed_value {
         use properties::animated_properties::Interpolate;
         use values::computed::{Length, LengthOrPercentage};
 
         #[derive(Clone, Copy, Debug, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub struct T {
@@ -1794,17 +1794,17 @@
         }
     }
 
     #[derive(Clone, Debug, PartialEq)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
     pub struct SpecifiedValue {
         horizontal: LengthOrPercentage,
         vertical: LengthOrPercentage,
-        depth: Length,
+        depth: NoCalcLength,
     }
 
     impl ToCss for computed_value::T {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             try!(self.horizontal.to_css(dest));
             try!(dest.write_str(" "));
             try!(self.vertical.to_css(dest));
             try!(dest.write_str(" "));
@@ -1831,17 +1831,17 @@
         }
     }
 
     pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
         let result = try!(super::parse_origin(context, input));
         Ok(SpecifiedValue {
             horizontal: result.horizontal.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
             vertical: result.vertical.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
-            depth: result.depth.unwrap_or(Length::Absolute(Au(0))),
+            depth: result.depth.unwrap_or(NoCalcLength::zero()),
         })
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
         fn to_computed_value(&self, context: &Context) -> computed_value::T {
--- a/servo/components/style/properties/longhand/effects.mako.rs
+++ b/servo/components/style/properties/longhand/effects.mako.rs
@@ -275,20 +275,20 @@
                 try!(input.expect_comma());
                 left = try!(parse_argument(context, input));
             } else {
                 right = try!(parse_argument(context, input));
                 bottom = try!(parse_argument(context, input));
                 left = try!(parse_argument(context, input));
             }
             Ok(SpecifiedValue(Some(SpecifiedClipRect {
-                top: top.unwrap_or(Length::Absolute(Au(0))),
+                top: top.unwrap_or(Length::zero()),
                 right: right,
                 bottom: bottom,
-                left: left.unwrap_or(Length::Absolute(Au(0))),
+                left: left.unwrap_or(Length::zero()),
             })))
         })
     }
 </%helpers:longhand>
 
 // FIXME: This prop should be animatable
 <%helpers:longhand name="filter" animatable="False" extra_prefixes="webkit"
                    spec="https://drafts.fxtf.org/filters/#propdef-filter">
@@ -608,17 +608,17 @@
             }).collect())
         }
     }
 </%helpers:longhand>
 
 pub struct OriginParseResult {
     pub horizontal: Option<specified::LengthOrPercentage>,
     pub vertical: Option<specified::LengthOrPercentage>,
-    pub depth: Option<specified::Length>
+    pub depth: Option<specified::NoCalcLength>
 }
 
 pub fn parse_origin(context: &ParserContext, input: &mut Parser) -> Result<OriginParseResult,()> {
     use values::specified::{LengthOrPercentage, Percentage};
     let (mut horizontal, mut vertical, mut depth) = (None, None, None);
     loop {
         if let Err(_) = input.try(|input| {
             let token = try!(input.expect_ident());
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.mako.rs
@@ -324,17 +324,17 @@
 </%helpers:longhand>
 
 <%helpers:longhand name="font-size" need_clone="True" animatable="True"
                    spec="https://drafts.csswg.org/css-fonts/#propdef-font-size">
     use app_units::Au;
     use std::fmt;
     use style_traits::ToCss;
     use values::{FONT_MEDIUM_PX, HasViewportPercentage};
-    use values::specified::{LengthOrPercentage, Length, Percentage};
+    use values::specified::{LengthOrPercentage, Length, NoCalcLength, Percentage};
 
     impl ToCss for SpecifiedValue {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             self.0.to_css(dest)
         }
     }
 
     impl HasViewportPercentage for SpecifiedValue {
@@ -358,20 +358,20 @@
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
         fn to_computed_value(&self, context: &Context) -> computed_value::T {
             match self.0 {
-                LengthOrPercentage::Length(Length::FontRelative(value)) => {
+                LengthOrPercentage::Length(NoCalcLength::FontRelative(value)) => {
                     value.to_computed_value(context, /* use inherited */ true)
                 }
-                LengthOrPercentage::Length(Length::ServoCharacterWidth(value)) => {
+                LengthOrPercentage::Length(NoCalcLength::ServoCharacterWidth(value)) => {
                     value.to_computed_value(context.inherited_style().get_font().clone_font_size())
                 }
                 LengthOrPercentage::Length(ref l) => {
                     l.to_computed_value(context)
                 }
                 LengthOrPercentage::Percentage(Percentage(value)) => {
                     context.inherited_style().get_font().clone_font_size().scale_by(value)
                 }
@@ -392,21 +392,20 @@
     }
     /// <length> | <percentage> | <absolute-size> | <relative-size>
     pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
         use values::specified::{Length, LengthOrPercentage};
 
         input.try(specified::LengthOrPercentage::parse_non_negative)
         .or_else(|()| {
             let ident = try!(input.expect_ident());
-            specified::Length::from_str(&ident as &str)
-                .ok_or(())
-                .map(specified::LengthOrPercentage::Length)
-        })
-        .map(SpecifiedValue)
+            NoCalcLength::from_str(&ident as &str)
+                         .ok_or(())
+                         .map(specified::LengthOrPercentage::Length)
+        }).map(SpecifiedValue)
     }
 </%helpers:longhand>
 
 <%helpers:longhand products="gecko" name="font-size-adjust" animatable="True"
                    spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust">
     use values::NoViewportPercentage;
     use values::computed::ComputedValueAsSpecified;
     use values::specified::Number;
--- a/servo/components/style/properties/longhand/inherited_text.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_text.mako.rs
@@ -108,23 +108,24 @@
                     SpecifiedValue::MozBlockHeight => computed_value::T::MozBlockHeight,
                 % endif
                 SpecifiedValue::Number(value) => computed_value::T::Number(value),
                 SpecifiedValue::LengthOrPercentage(ref value) => {
                     match *value {
                         specified::LengthOrPercentage::Length(ref value) =>
                             computed_value::T::Length(value.to_computed_value(context)),
                         specified::LengthOrPercentage::Percentage(specified::Percentage(value)) => {
-                            let fr = specified::Length::FontRelative(specified::FontRelativeLength::Em(value));
+                            let fr = specified::Length::NoCalc(specified::NoCalcLength::FontRelative(
+                                specified::FontRelativeLength::Em(value)));
                             computed_value::T::Length(fr.to_computed_value(context))
                         },
                         specified::LengthOrPercentage::Calc(ref calc) => {
                             let calc = calc.to_computed_value(context);
                             let fr = specified::FontRelativeLength::Em(calc.percentage());
-                            let fr = specified::Length::FontRelative(fr);
+                            let fr = specified::Length::NoCalc(specified::NoCalcLength::FontRelative(fr));
                             computed_value::T::Length(calc.length() + fr.to_computed_value(context))
                         }
                     }
                 }
             }
         }
 
         #[inline]
@@ -676,19 +677,17 @@
             Ok(SpecifiedValue(Vec::new()))
         } else {
             input.parse_comma_separated(|i| parse_one_text_shadow(context, i)).map(SpecifiedValue)
         }
     }
 
     fn parse_one_text_shadow(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedTextShadow,()> {
         use app_units::Au;
-        let mut lengths = [specified::Length::Absolute(Au(0)),
-                           specified::Length::Absolute(Au(0)),
-                           specified::Length::Absolute(Au(0))];
+        let mut lengths = [specified::Length::zero(), specified::Length::zero(), specified::Length::zero()];
         let mut lengths_parsed = false;
         let mut color = None;
 
         loop {
             if !lengths_parsed {
                 if let Ok(value) = input.try(|i| specified::Length::parse(context, i)) {
                     lengths[0] = value;
                     let mut length_parsed_count = 1;
--- a/servo/components/style/properties/shorthand/inherited_text.mako.rs
+++ b/servo/components/style/properties/shorthand/inherited_text.mako.rs
@@ -69,17 +69,16 @@
                     products="gecko"
                     spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke">
     use cssparser::Color as CSSParserColor;
     use properties::longhands::{_webkit_text_stroke_color, _webkit_text_stroke_width};
     use values::specified::CSSColor;
 
     pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
         use values::specified::{BorderWidth, Length};
-        use app_units::Au;
 
         let mut color = None;
         let mut width = None;
         loop {
             if color.is_none() {
                 if let Ok(value) = input.try(|input| _webkit_text_stroke_color::parse(context, input)) {
                     color = Some(value);
                     continue
@@ -94,17 +93,17 @@
             }
             break
         }
 
         if color.is_some() || width.is_some() {
             Ok(Longhands {
                 _webkit_text_stroke_color: color.or(Some(CSSColor { parsed: CSSParserColor::CurrentColor,
                     authored: None })),
-                _webkit_text_stroke_width: width.or(Some(BorderWidth::from_length(Length::Absolute(Au::from_px(0))))),
+                _webkit_text_stroke_width: width.or(Some(BorderWidth::from_length(Length::zero()))),
             })
         } else {
             Err(())
         }
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
--- a/servo/components/style/properties/shorthand/position.mako.rs
+++ b/servo/components/style/properties/shorthand/position.mako.rs
@@ -52,18 +52,17 @@
             }
         }
     }
 </%helpers:shorthand>
 
 <%helpers:shorthand name="flex" sub_properties="flex-grow flex-shrink flex-basis" extra_prefixes="webkit"
                     spec="https://drafts.csswg.org/css-flexbox/#flex-property">
     use parser::Parse;
-    use app_units::Au;
-    use values::specified::{Number, Length, LengthOrPercentageOrAutoOrContent};
+    use values::specified::{Number, NoCalcLength, LengthOrPercentageOrAutoOrContent};
 
     pub fn parse_flexibility(input: &mut Parser)
                              -> Result<(Number, Option<Number>),()> {
         let grow = try!(Number::parse_non_negative(input));
         let shrink = input.try(Number::parse_non_negative).ok();
         Ok((grow, shrink))
     }
 
@@ -97,17 +96,17 @@
         }
 
         if grow.is_none() && basis.is_none() {
             return Err(())
         }
         Ok(Longhands {
             flex_grow: grow.or(Some(Number(1.0))),
             flex_shrink: shrink.or(Some(Number(1.0))),
-            flex_basis: basis.or(Some(LengthOrPercentageOrAutoOrContent::Length(Length::Absolute(Au(0)))))
+            flex_basis: basis.or(Some(LengthOrPercentageOrAutoOrContent::Length(NoCalcLength::zero())))
         })
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             try!(self.flex_grow.to_css(dest));
             try!(write!(dest, " "));
 
--- a/servo/components/style/values/computed/length.rs
+++ b/servo/components/style/values/computed/length.rs
@@ -12,16 +12,55 @@ use super::{Number, ToComputedValue, Con
 use values::{Auto, CSSFloat, Either, None_, Normal, specified};
 use values::specified::length::{FontRelativeLength, ViewportPercentageLength};
 
 pub use cssparser::Color as CSSColor;
 pub use super::image::{EndingShape as GradientShape, Gradient, GradientKind, Image};
 pub use super::image::{LengthOrKeyword, LengthOrPercentageOrKeyword};
 pub use values::specified::{Angle, BorderStyle, Time, UrlOrNone};
 
+impl ToComputedValue for specified::NoCalcLength {
+    type ComputedValue = Au;
+
+    #[inline]
+    fn to_computed_value(&self, context: &Context) -> Au {
+        match *self {
+            specified::NoCalcLength::Absolute(length) => length,
+            specified::NoCalcLength::FontRelative(length) =>
+                length.to_computed_value(context, /* use inherited */ false),
+            specified::NoCalcLength::ViewportPercentage(length) =>
+                length.to_computed_value(context.viewport_size()),
+            specified::NoCalcLength::ServoCharacterWidth(length) =>
+                length.to_computed_value(context.style().get_font().clone_font_size())
+        }
+    }
+
+    #[inline]
+    fn from_computed_value(computed: &Au) -> Self {
+        specified::NoCalcLength::Absolute(*computed)
+    }
+}
+
+impl ToComputedValue for specified::Length {
+    type ComputedValue = Au;
+
+    #[inline]
+    fn to_computed_value(&self, context: &Context) -> Au {
+        match *self {
+            specified::Length::NoCalc(l) => l.to_computed_value(context),
+            specified::Length::Calc(ref calc, range) => range.clamp(calc.to_computed_value(context).length()),
+        }
+    }
+
+    #[inline]
+    fn from_computed_value(computed: &Au) -> Self {
+        specified::Length::NoCalc(specified::NoCalcLength::from_computed_value(computed))
+    }
+}
+
 #[derive(Clone, PartialEq, Copy, Debug)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 #[allow(missing_docs)]
 pub struct CalcLengthOrPercentage {
     pub length: Au,
     pub percentage: Option<CSSFloat>,
 }
 
--- a/servo/components/style/values/computed/mod.rs
+++ b/servo/components/style/values/computed/mod.rs
@@ -116,40 +116,16 @@ impl ToComputedValue for specified::CSSC
             parsed: *computed,
             authored: None,
         }
     }
 }
 
 impl ComputedValueAsSpecified for specified::BorderStyle {}
 
-impl ToComputedValue for specified::Length {
-    type ComputedValue = Au;
-
-    #[inline]
-    fn to_computed_value(&self, context: &Context) -> Au {
-        match *self {
-            specified::Length::Absolute(length) => length,
-            specified::Length::Calc(ref calc, range) => range.clamp(calc.to_computed_value(context).length()),
-            specified::Length::FontRelative(length) =>
-                length.to_computed_value(context, /* use inherited */ false),
-            specified::Length::ViewportPercentage(length) =>
-                length.to_computed_value(context.viewport_size()),
-            specified::Length::ServoCharacterWidth(length) =>
-                length.to_computed_value(context.style().get_font().clone_font_size())
-        }
-    }
-
-    #[inline]
-    fn from_computed_value(computed: &Au) -> Self {
-        specified::Length::Absolute(*computed)
-    }
-}
-
-
 #[derive(Debug, PartialEq, Clone, Copy)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 #[allow(missing_docs)]
 pub struct BorderRadiusSize(pub Size2D<LengthOrPercentage>);
 
 impl BorderRadiusSize {
     #[allow(missing_docs)]
     pub fn zero() -> BorderRadiusSize {
--- a/servo/components/style/values/specified/basic_shape.rs
+++ b/servo/components/style/values/specified/basic_shape.rs
@@ -294,17 +294,16 @@ impl ToComputedValue for InsetRect {
 /// https://drafts.csswg.org/css-shapes/#basic-shape-serialization
 ///
 /// Positions get serialized differently with basic shapes. Keywords
 /// are converted to percentages where possible. Only the two or four
 /// value forms are used. In case of two keyword-percentage pairs,
 /// the keywords are folded into the percentages
 fn serialize_basicshape_position<W>(position: &Position, dest: &mut W)
     -> fmt::Result where W: fmt::Write {
-        use values::specified::Length;
         use values::specified::position::Keyword;
 
         // keyword-percentage pairs can be folded into a single percentage
         fn fold_keyword(keyword: Option<Keyword>, length: Option<LengthOrPercentage>)
             -> Option<LengthOrPercentage> {
             let none = length.is_none();
             let pc = match length.map(replace_with_percent) {
                 None => Percentage(0.0), // unspecified length = 0%
@@ -322,17 +321,17 @@ fn serialize_basicshape_position<W>(posi
                 _ => return None,
             };
             Some(LengthOrPercentage::Percentage(percent))
         }
 
         // 0 length should be replaced with 0%
         fn replace_with_percent(input: LengthOrPercentage) -> LengthOrPercentage {
             match input {
-                LengthOrPercentage::Length(Length::Absolute(au)) if au.0 == 0 => {
+                LengthOrPercentage::Length(ref l) if l.is_zero() => {
                     LengthOrPercentage::Percentage(Percentage(0.0))
                 }
                 _ => {
                     input
                 }
             }
         }
 
--- a/servo/components/style/values/specified/length.rs
+++ b/servo/components/style/values/specified/length.rs
@@ -19,16 +19,24 @@ use style_traits::values::specified::All
 use super::{Angle, Number, SimplifiedValueNode, SimplifiedSumNode, Time};
 use values::{Auto, CSSFloat, Either, FONT_MEDIUM_PX, HasViewportPercentage, None_, Normal};
 use values::computed::Context;
 
 pub use super::image::{AngleOrCorner, ColorStop, EndingShape as GradientEndingShape, Gradient};
 pub use super::image::{GradientKind, HorizontalDirection, Image, LengthOrKeyword, LengthOrPercentageOrKeyword};
 pub use super::image::{SizeKeyword, VerticalDirection};
 
+const AU_PER_PX: CSSFloat = 60.;
+const AU_PER_IN: CSSFloat = AU_PER_PX * 96.;
+const AU_PER_CM: CSSFloat = AU_PER_IN / 2.54;
+const AU_PER_MM: CSSFloat = AU_PER_IN / 25.4;
+const AU_PER_Q: CSSFloat = AU_PER_MM / 4.;
+const AU_PER_PT: CSSFloat = AU_PER_IN / 72.;
+const AU_PER_PC: CSSFloat = AU_PER_PT * 12.;
+
 #[derive(Clone, PartialEq, Copy, Debug)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 /// A font relative length.
 pub enum FontRelativeLength {
     /// A "em" value: https://drafts.csswg.org/css-values/#em
     Em(CSSFloat),
     /// A "ex" value: https://drafts.csswg.org/css-values/#ex
     Ex(CSSFloat),
@@ -200,22 +208,22 @@ impl CharacterWidth {
         //
         // TODO(pcwalton): Find these from the font.
         let average_advance = reference_font_size.scale_by(0.5);
         let max_advance = reference_font_size;
         average_advance.scale_by(self.0 as CSSFloat - 1.0) + max_advance
     }
 }
 
-/// A length.
+/// A `<length>` without taking `calc` expressions into account
 ///
 /// https://drafts.csswg.org/css-values/#lengths
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Clone, PartialEq, Copy, Debug)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub enum Length {
+pub enum NoCalcLength {
     /// An absolute length: https://drafts.csswg.org/css-values/#absolute-length
     Absolute(Au),  // application units
 
     /// A font-relative length:
     ///
     /// https://drafts.csswg.org/css-values/#font-relative-lengths
     FontRelative(FontRelativeLength),
 
@@ -224,60 +232,159 @@ pub enum Length {
     /// https://drafts.csswg.org/css-values/#viewport-relative-lengths
     ViewportPercentage(ViewportPercentageLength),
 
     /// HTML5 "character width", as defined in HTML5 ยง 14.5.4.
     ///
     /// This cannot be specified by the user directly and is only generated by
     /// `Stylist::synthesize_rules_for_legacy_attributes()`.
     ServoCharacterWidth(CharacterWidth),
+}
 
+impl HasViewportPercentage for NoCalcLength {
+    fn has_viewport_percentage(&self) -> bool {
+        match *self {
+            NoCalcLength::ViewportPercentage(_) => true,
+            _ => false,
+        }
+    }
+}
+
+impl ToCss for NoCalcLength {
+    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+        match *self {
+            NoCalcLength::Absolute(length) => write!(dest, "{}px", length.to_f32_px()),
+            NoCalcLength::FontRelative(length) => length.to_css(dest),
+            NoCalcLength::ViewportPercentage(length) => length.to_css(dest),
+            /* This should only be reached from style dumping code */
+            NoCalcLength::ServoCharacterWidth(CharacterWidth(i)) => write!(dest, "CharWidth({})", i),
+        }
+    }
+}
+
+impl Mul<CSSFloat> for NoCalcLength {
+    type Output = NoCalcLength;
+
+    #[inline]
+    fn mul(self, scalar: CSSFloat) -> NoCalcLength {
+        match self {
+            NoCalcLength::Absolute(Au(v)) => NoCalcLength::Absolute(Au(((v as f32) * scalar) as i32)),
+            NoCalcLength::FontRelative(v) => NoCalcLength::FontRelative(v * scalar),
+            NoCalcLength::ViewportPercentage(v) => NoCalcLength::ViewportPercentage(v * scalar),
+            NoCalcLength::ServoCharacterWidth(_) => panic!("Can't multiply ServoCharacterWidth!"),
+        }
+    }
+}
+
+impl NoCalcLength {
+    /// https://drafts.csswg.org/css-fonts-3/#font-size-prop
+    pub fn from_str(s: &str) -> Option<NoCalcLength> {
+        Some(match_ignore_ascii_case! { s,
+            "xx-small" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX) * 3 / 5),
+            "x-small" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX) * 3 / 4),
+            "small" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX) * 8 / 9),
+            "medium" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX)),
+            "large" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX) * 6 / 5),
+            "x-large" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX) * 3 / 2),
+            "xx-large" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX) * 2),
+
+            // https://github.com/servo/servo/issues/3423#issuecomment-56321664
+            "smaller" => NoCalcLength::FontRelative(FontRelativeLength::Em(0.85)),
+            "larger" => NoCalcLength::FontRelative(FontRelativeLength::Em(1.2)),
+            _ => return None
+        })
+    }
+
+    /// Parse a given absolute or relative dimension.
+    pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<NoCalcLength, ()> {
+        match_ignore_ascii_case! { unit,
+            "px" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_PX) as i32))),
+            "in" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_IN) as i32))),
+            "cm" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_CM) as i32))),
+            "mm" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_MM) as i32))),
+            "q" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_Q) as i32))),
+            "pt" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_PT) as i32))),
+            "pc" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_PC) as i32))),
+            // font-relative
+            "em" => Ok(NoCalcLength::FontRelative(FontRelativeLength::Em(value))),
+            "ex" => Ok(NoCalcLength::FontRelative(FontRelativeLength::Ex(value))),
+            "ch" => Ok(NoCalcLength::FontRelative(FontRelativeLength::Ch(value))),
+            "rem" => Ok(NoCalcLength::FontRelative(FontRelativeLength::Rem(value))),
+            // viewport percentages
+            "vw" => Ok(NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vw(value))),
+            "vh" => Ok(NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vh(value))),
+            "vmin" => Ok(NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vmin(value))),
+            "vmax" => Ok(NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vmax(value))),
+            _ => Err(())
+        }
+    }
+
+    #[inline]
+    /// Returns a `zero` length.
+    pub fn zero() -> NoCalcLength {
+        NoCalcLength::Absolute(Au(0))
+    }
+
+    #[inline]
+    /// Checks whether the length value is zero.
+    pub fn is_zero(&self) -> bool {
+        *self == NoCalcLength::Absolute(Au(0))
+    }
+
+    /// Get an absolute length from a px value.
+    #[inline]
+    pub fn from_px(px_value: CSSFloat) -> NoCalcLength {
+        NoCalcLength::Absolute(Au((px_value * AU_PER_PX) as i32))
+    }
+}
+
+/// An extension to `NoCalcLength` to parse `calc` expressions.
+/// This is commonly used for the `<length>` values.
+///
+/// https://drafts.csswg.org/css-values/#lengths
+#[derive(Clone, PartialEq, Debug)]
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+pub enum Length {
+    /// The internal length type that cannot parse `calc`
+    NoCalc(NoCalcLength),
     /// A calc expression.
     ///
     /// https://drafts.csswg.org/css-values/#calc-notation
     ///
     /// TODO(emilio): We have more `Calc` variants around, we should only use
     /// one.
     Calc(Box<CalcLengthOrPercentage>, AllowedNumericType),
 }
 
 impl HasViewportPercentage for Length {
     fn has_viewport_percentage(&self) -> bool {
         match *self {
-            Length::ViewportPercentage(_) => true,
+            Length::NoCalc(ref inner) => inner.has_viewport_percentage(),
             Length::Calc(ref calc, _) => calc.has_viewport_percentage(),
-            _ => false
         }
     }
 }
 
 impl ToCss for Length {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         match *self {
-            Length::Absolute(length) => write!(dest, "{}px", length.to_f32_px()),
-            Length::FontRelative(length) => length.to_css(dest),
-            Length::ViewportPercentage(length) => length.to_css(dest),
+            Length::NoCalc(ref inner) => inner.to_css(dest),
             Length::Calc(ref calc, _) => calc.to_css(dest),
-            /* This should only be reached from style dumping code */
-            Length::ServoCharacterWidth(CharacterWidth(i)) => write!(dest, "CharWidth({})", i),
         }
     }
 }
 
 impl Mul<CSSFloat> for Length {
     type Output = Length;
 
     #[inline]
     fn mul(self, scalar: CSSFloat) -> Length {
         match self {
-            Length::Absolute(Au(v)) => Length::Absolute(Au(((v as f32) * scalar) as i32)),
-            Length::FontRelative(v) => Length::FontRelative(v * scalar),
-            Length::ViewportPercentage(v) => Length::ViewportPercentage(v * scalar),
+            Length::NoCalc(inner) => Length::NoCalc(inner * scalar),
             Length::Calc(..) => panic!("Can't multiply Calc!"),
-            Length::ServoCharacterWidth(_) => panic!("Can't multiply ServoCharacterWidth!"),
         }
     }
 }
 
 impl Mul<CSSFloat> for FontRelativeLength {
     type Output = FontRelativeLength;
 
     #[inline]
@@ -300,100 +407,64 @@ impl Mul<CSSFloat> for ViewportPercentag
             ViewportPercentageLength::Vw(v) => ViewportPercentageLength::Vw(v * scalar),
             ViewportPercentageLength::Vh(v) => ViewportPercentageLength::Vh(v * scalar),
             ViewportPercentageLength::Vmin(v) => ViewportPercentageLength::Vmin(v * scalar),
             ViewportPercentageLength::Vmax(v) => ViewportPercentageLength::Vmax(v * scalar),
         }
     }
 }
 
-const AU_PER_PX: CSSFloat = 60.;
-const AU_PER_IN: CSSFloat = AU_PER_PX * 96.;
-const AU_PER_CM: CSSFloat = AU_PER_IN / 2.54;
-const AU_PER_MM: CSSFloat = AU_PER_IN / 25.4;
-const AU_PER_Q: CSSFloat = AU_PER_MM / 4.;
-const AU_PER_PT: CSSFloat = AU_PER_IN / 72.;
-const AU_PER_PC: CSSFloat = AU_PER_PT * 12.;
+impl Length {
+    #[inline]
+    /// Returns a `zero` length.
+    pub fn zero() -> Length {
+        Length::NoCalc(NoCalcLength::zero())
+    }
 
-impl Length {
     /// https://drafts.csswg.org/css-fonts-3/#font-size-prop
     pub fn from_str(s: &str) -> Option<Length> {
-        Some(match_ignore_ascii_case! { s,
-            "xx-small" => Length::Absolute(Au::from_px(FONT_MEDIUM_PX) * 3 / 5),
-            "x-small" => Length::Absolute(Au::from_px(FONT_MEDIUM_PX) * 3 / 4),
-            "small" => Length::Absolute(Au::from_px(FONT_MEDIUM_PX) * 8 / 9),
-            "medium" => Length::Absolute(Au::from_px(FONT_MEDIUM_PX)),
-            "large" => Length::Absolute(Au::from_px(FONT_MEDIUM_PX) * 6 / 5),
-            "x-large" => Length::Absolute(Au::from_px(FONT_MEDIUM_PX) * 3 / 2),
-            "xx-large" => Length::Absolute(Au::from_px(FONT_MEDIUM_PX) * 2),
+        NoCalcLength::from_str(s).map(Length::NoCalc)
+    }
 
-            // https://github.com/servo/servo/issues/3423#issuecomment-56321664
-            "smaller" => Length::FontRelative(FontRelativeLength::Em(0.85)),
-            "larger" => Length::FontRelative(FontRelativeLength::Em(1.2)),
-            _ => return None
-        })
+    /// Parse a given absolute or relative dimension.
+    pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Length, ()> {
+        NoCalcLength::parse_dimension(value, unit).map(Length::NoCalc)
     }
 
     #[inline]
     fn parse_internal(input: &mut Parser, context: AllowedNumericType) -> Result<Length, ()> {
         match try!(input.next()) {
             Token::Dimension(ref value, ref unit) if context.is_ok(value.value) =>
                 Length::parse_dimension(value.value, unit),
-            Token::Number(ref value) if value.value == 0. =>
-                Ok(Length::Absolute(Au(0))),
+            Token::Number(ref value) if value.value == 0. => Ok(Length::zero()),
             Token::Function(ref name) if name.eq_ignore_ascii_case("calc") =>
                 input.parse_nested_block(|input| {
                     CalcLengthOrPercentage::parse_length(input, context)
                 }),
             _ => Err(())
         }
     }
 
     /// Parse a non-negative length
     pub fn parse_non_negative(input: &mut Parser) -> Result<Length, ()> {
         Length::parse_internal(input, AllowedNumericType::NonNegative)
     }
 
-    /// Parse a given absolute or relative dimension.
-    pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Length, ()> {
-        match_ignore_ascii_case! { unit,
-            "px" => Ok(Length::from_px(value)),
-            "in" => Ok(Length::Absolute(Au((value * AU_PER_IN) as i32))),
-            "cm" => Ok(Length::Absolute(Au((value * AU_PER_CM) as i32))),
-            "mm" => Ok(Length::Absolute(Au((value * AU_PER_MM) as i32))),
-            "q" => Ok(Length::Absolute(Au((value * AU_PER_Q) as i32))),
-            "pt" => Ok(Length::Absolute(Au((value * AU_PER_PT) as i32))),
-            "pc" => Ok(Length::Absolute(Au((value * AU_PER_PC) as i32))),
-            // font-relative
-            "em" => Ok(Length::FontRelative(FontRelativeLength::Em(value))),
-            "ex" => Ok(Length::FontRelative(FontRelativeLength::Ex(value))),
-            "ch" => Ok(Length::FontRelative(FontRelativeLength::Ch(value))),
-            "rem" => Ok(Length::FontRelative(FontRelativeLength::Rem(value))),
-            // viewport percentages
-            "vw" => Ok(Length::ViewportPercentage(ViewportPercentageLength::Vw(value))),
-            "vh" => Ok(Length::ViewportPercentage(ViewportPercentageLength::Vh(value))),
-            "vmin" => Ok(Length::ViewportPercentage(ViewportPercentageLength::Vmin(value))),
-            "vmax" => Ok(Length::ViewportPercentage(ViewportPercentageLength::Vmax(value))),
-            _ => Err(())
-        }
-    }
-
-    /// Get an absolute length from a px values.
+    /// Get an absolute length from a px value.
     #[inline]
     pub fn from_px(px_value: CSSFloat) -> Length {
-        Length::Absolute(Au((px_value * AU_PER_PX) as i32))
+        Length::NoCalc(NoCalcLength::from_px(px_value))
     }
 
     /// Extract inner length without a clone, replacing it with a 0 Au
     ///
     /// Use when you need to move out of a length array without cloning
     #[inline]
     pub fn take(&mut self) -> Self {
-        let new = Length::Absolute(Au(0));
-        mem::replace(self, new)
+        mem::replace(self, Length::zero())
     }
 }
 
 impl Parse for Length {
     fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
         Length::parse_internal(input, AllowedNumericType::All)
     }
 }
@@ -419,17 +490,17 @@ pub struct CalcProductNode {
     /// The values inside this product node.
     values: Vec<CalcValueNode>
 }
 
 /// A value inside a `Calc` expression.
 #[derive(Clone, Debug)]
 #[allow(missing_docs)]
 pub enum CalcValueNode {
-    Length(Length),
+    Length(NoCalcLength),
     Angle(Angle),
     Time(Time),
     Percentage(CSSFloat),
     Number(CSSFloat),
     Sum(Box<CalcSumNode>),
 }
 
 #[derive(Clone, Copy, PartialEq)]
@@ -512,17 +583,17 @@ impl CalcLengthOrPercentage {
         Ok(CalcProductNode { values: values })
     }
 
     fn parse_value(input: &mut Parser, expected_unit: CalcUnit) -> Result<CalcValueNode, ()> {
         match (try!(input.next()), expected_unit) {
             (Token::Number(ref value), _) => Ok(CalcValueNode::Number(value.value)),
             (Token::Dimension(ref value, ref unit), CalcUnit::Length) |
             (Token::Dimension(ref value, ref unit), CalcUnit::LengthOrPercentage) => {
-                Length::parse_dimension(value.value, unit).map(CalcValueNode::Length)
+                NoCalcLength::parse_dimension(value.value, unit).map(CalcValueNode::Length)
             }
             (Token::Dimension(ref value, ref unit), CalcUnit::Angle) => {
                 Angle::parse_dimension(value.value, unit).map(CalcValueNode::Angle)
             }
             (Token::Dimension(ref value, ref unit), CalcUnit::Time) => {
                 Time::parse_dimension(value.value, unit).map(CalcValueNode::Time)
             }
             (Token::Percentage(ref value), CalcUnit::LengthOrPercentage) =>
@@ -643,30 +714,30 @@ impl CalcLengthOrPercentage {
         let mut ch = None;
         let mut rem = None;
         let mut percentage = None;
 
         for value in simplified {
             match value {
                 SimplifiedValueNode::Percentage(p) =>
                     percentage = Some(percentage.unwrap_or(0.) + p),
-                SimplifiedValueNode::Length(Length::Absolute(Au(au))) =>
+                SimplifiedValueNode::Length(NoCalcLength::Absolute(Au(au))) =>
                     absolute = Some(absolute.unwrap_or(0) + au),
-                SimplifiedValueNode::Length(Length::ViewportPercentage(v)) =>
+                SimplifiedValueNode::Length(NoCalcLength::ViewportPercentage(v)) =>
                     match v {
                         ViewportPercentageLength::Vw(val) =>
                             vw = Some(vw.unwrap_or(0.) + val),
                         ViewportPercentageLength::Vh(val) =>
                             vh = Some(vh.unwrap_or(0.) + val),
                         ViewportPercentageLength::Vmin(val) =>
                             vmin = Some(vmin.unwrap_or(0.) + val),
                         ViewportPercentageLength::Vmax(val) =>
                             vmax = Some(vmax.unwrap_or(0.) + val),
                     },
-                SimplifiedValueNode::Length(Length::FontRelative(f)) =>
+                SimplifiedValueNode::Length(NoCalcLength::FontRelative(f)) =>
                     match f {
                         FontRelativeLength::Em(val) =>
                             em = Some(em.unwrap_or(0.) + val),
                         FontRelativeLength::Ex(val) =>
                             ex = Some(ex.unwrap_or(0.) + val),
                         FontRelativeLength::Ch(val) =>
                             ch = Some(ch.unwrap_or(0.) + val),
                         FontRelativeLength::Rem(val) =>
@@ -828,21 +899,30 @@ impl Parse for Percentage {
 
 /// A length or a percentage value.
 ///
 /// TODO(emilio): Does this make any sense vs. CalcLengthOrPercentage?
 #[derive(Clone, PartialEq, Debug)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 #[allow(missing_docs)]
 pub enum LengthOrPercentage {
-    Length(Length),
+    Length(NoCalcLength),
     Percentage(Percentage),
     Calc(Box<CalcLengthOrPercentage>),
 }
 
+impl From<Length> for LengthOrPercentage {
+    fn from(len: Length) -> LengthOrPercentage {
+        match len {
+            Length::NoCalc(l) => LengthOrPercentage::Length(l),
+            Length::Calc(l, _) => LengthOrPercentage::Calc(l),
+        }
+    }
+}
+
 impl HasViewportPercentage for LengthOrPercentage {
     fn has_viewport_percentage(&self) -> bool {
         match *self {
             LengthOrPercentage::Length(ref length) => length.has_viewport_percentage(),
             LengthOrPercentage::Calc(ref calc) => calc.has_viewport_percentage(),
             _ => false
         }
     }
@@ -855,29 +935,29 @@ impl ToCss for LengthOrPercentage {
             LengthOrPercentage::Percentage(percentage) => percentage.to_css(dest),
             LengthOrPercentage::Calc(ref calc) => calc.to_css(dest),
         }
     }
 }
 impl LengthOrPercentage {
     /// Returns a `zero` length.
     pub fn zero() -> LengthOrPercentage {
-        LengthOrPercentage::Length(Length::Absolute(Au(0)))
+        LengthOrPercentage::Length(NoCalcLength::zero())
     }
 
     fn parse_internal(input: &mut Parser, context: AllowedNumericType)
                       -> Result<LengthOrPercentage, ()>
     {
         match try!(input.next()) {
             Token::Dimension(ref value, ref unit) if context.is_ok(value.value) =>
-                Length::parse_dimension(value.value, unit).map(LengthOrPercentage::Length),
+                NoCalcLength::parse_dimension(value.value, unit).map(LengthOrPercentage::Length),
             Token::Percentage(ref value) if context.is_ok(value.unit_value) =>
                 Ok(LengthOrPercentage::Percentage(Percentage(value.unit_value))),
             Token::Number(ref value) if value.value == 0. =>
-                Ok(LengthOrPercentage::Length(Length::Absolute(Au(0)))),
+                Ok(LengthOrPercentage::zero()),
             Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
                 let calc = try!(input.parse_nested_block(CalcLengthOrPercentage::parse_length_or_percentage));
                 Ok(LengthOrPercentage::Calc(Box::new(calc)))
             },
             _ => Err(())
         }
     }
 
@@ -887,35 +967,34 @@ impl LengthOrPercentage {
         LengthOrPercentage::parse_internal(input, AllowedNumericType::NonNegative)
     }
 
     /// Extract value from ref without a clone, replacing it with a 0 Au
     ///
     /// Use when you need to move out of a length array without cloning
     #[inline]
     pub fn take(&mut self) -> Self {
-        let new = LengthOrPercentage::Length(Length::Absolute(Au(0)));
-        mem::replace(self, new)
+        mem::replace(self, LengthOrPercentage::zero())
     }
 }
 
 impl Parse for LengthOrPercentage {
     #[inline]
     fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
         LengthOrPercentage::parse_internal(input, AllowedNumericType::All)
     }
 }
 
 /// TODO(emilio): Do the Length and Percentage variants make any sense with
 /// CalcLengthOrPercentage?
 #[derive(Clone, PartialEq, Debug)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 #[allow(missing_docs)]
 pub enum LengthOrPercentageOrAuto {
-    Length(Length),
+    Length(NoCalcLength),
     Percentage(Percentage),
     Auto,
     Calc(Box<CalcLengthOrPercentage>),
 }
 
 impl HasViewportPercentage for LengthOrPercentageOrAuto {
     fn has_viewport_percentage(&self) -> bool {
         match *self {
@@ -938,21 +1017,21 @@ impl ToCss for LengthOrPercentageOrAuto 
 }
 
 impl LengthOrPercentageOrAuto {
     fn parse_internal(input: &mut Parser, context: AllowedNumericType)
                       -> Result<LengthOrPercentageOrAuto, ()>
     {
         match try!(input.next()) {
             Token::Dimension(ref value, ref unit) if context.is_ok(value.value) =>
-                Length::parse_dimension(value.value, unit).map(LengthOrPercentageOrAuto::Length),
+                NoCalcLength::parse_dimension(value.value, unit).map(LengthOrPercentageOrAuto::Length),
             Token::Percentage(ref value) if context.is_ok(value.unit_value) =>
                 Ok(LengthOrPercentageOrAuto::Percentage(Percentage(value.unit_value))),
             Token::Number(ref value) if value.value == 0. =>
-                Ok(LengthOrPercentageOrAuto::Length(Length::Absolute(Au(0)))),
+                Ok(LengthOrPercentageOrAuto::Length(NoCalcLength::zero())),
             Token::Ident(ref value) if value.eq_ignore_ascii_case("auto") =>
                 Ok(LengthOrPercentageOrAuto::Auto),
             Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
                 let calc = try!(input.parse_nested_block(CalcLengthOrPercentage::parse_length_or_percentage));
                 Ok(LengthOrPercentageOrAuto::Calc(Box::new(calc)))
             },
             _ => Err(())
         }
@@ -973,17 +1052,17 @@ impl Parse for LengthOrPercentageOrAuto 
 }
 
 /// TODO(emilio): Do the Length and Percentage variants make any sense with
 /// CalcLengthOrPercentage?
 #[derive(Clone, PartialEq, Debug)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 #[allow(missing_docs)]
 pub enum LengthOrPercentageOrNone {
-    Length(Length),
+    Length(NoCalcLength),
     Percentage(Percentage),
     Calc(Box<CalcLengthOrPercentage>),
     None,
 }
 
 impl HasViewportPercentage for LengthOrPercentageOrNone {
     fn has_viewport_percentage(&self) -> bool {
         match *self {
@@ -1005,21 +1084,21 @@ impl ToCss for LengthOrPercentageOrNone 
     }
 }
 impl LengthOrPercentageOrNone {
     fn parse_internal(input: &mut Parser, context: AllowedNumericType)
                       -> Result<LengthOrPercentageOrNone, ()>
     {
         match try!(input.next()) {
             Token::Dimension(ref value, ref unit) if context.is_ok(value.value) =>
-                Length::parse_dimension(value.value, unit).map(LengthOrPercentageOrNone::Length),
+                NoCalcLength::parse_dimension(value.value, unit).map(LengthOrPercentageOrNone::Length),
             Token::Percentage(ref value) if context.is_ok(value.unit_value) =>
                 Ok(LengthOrPercentageOrNone::Percentage(Percentage(value.unit_value))),
             Token::Number(ref value) if value.value == 0. =>
-                Ok(LengthOrPercentageOrNone::Length(Length::Absolute(Au(0)))),
+                Ok(LengthOrPercentageOrNone::Length(NoCalcLength::zero())),
             Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
                 let calc = try!(input.parse_nested_block(CalcLengthOrPercentage::parse_length_or_percentage));
                 Ok(LengthOrPercentageOrNone::Calc(Box::new(calc)))
             },
             Token::Ident(ref value) if value.eq_ignore_ascii_case("none") =>
                 Ok(LengthOrPercentageOrNone::None),
             _ => Err(())
         }
@@ -1050,17 +1129,17 @@ pub type LengthOrAuto = Either<Length, A
 /// Either a `<length>` or a `<percentage>` or the `auto` keyword or the
 /// `content` keyword.
 ///
 /// TODO(emilio): Do the Length and Percentage variants make any sense with
 #[derive(Clone, PartialEq, Debug)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 pub enum LengthOrPercentageOrAutoOrContent {
     /// A `<length>`.
-    Length(Length),
+    Length(NoCalcLength),
     /// A percentage.
     Percentage(Percentage),
     /// A `calc` node.
     Calc(Box<CalcLengthOrPercentage>),
     /// The `auto` keyword.
     Auto,
     /// The `content` keyword.
     Content
@@ -1088,21 +1167,21 @@ impl ToCss for LengthOrPercentageOrAutoO
     }
 }
 
 impl Parse for LengthOrPercentageOrAutoOrContent {
     fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
         let context = AllowedNumericType::NonNegative;
         match try!(input.next()) {
             Token::Dimension(ref value, ref unit) if context.is_ok(value.value) =>
-                Length::parse_dimension(value.value, unit).map(LengthOrPercentageOrAutoOrContent::Length),
+                NoCalcLength::parse_dimension(value.value, unit).map(LengthOrPercentageOrAutoOrContent::Length),
             Token::Percentage(ref value) if context.is_ok(value.unit_value) =>
                 Ok(LengthOrPercentageOrAutoOrContent::Percentage(Percentage(value.unit_value))),
             Token::Number(ref value) if value.value == 0. =>
-                Ok(LengthOrPercentageOrAutoOrContent::Length(Length::Absolute(Au(0)))),
+                Ok(LengthOrPercentageOrAutoOrContent::Length(NoCalcLength::zero())),
             Token::Ident(ref value) if value.eq_ignore_ascii_case("auto") =>
                 Ok(LengthOrPercentageOrAutoOrContent::Auto),
             Token::Ident(ref value) if value.eq_ignore_ascii_case("content") =>
                 Ok(LengthOrPercentageOrAutoOrContent::Content),
             Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
                 let calc = try!(input.parse_nested_block(CalcLengthOrPercentage::parse_length_or_percentage));
                 Ok(LengthOrPercentageOrAutoOrContent::Calc(Box::new(calc)))
             },
--- a/servo/components/style/values/specified/mod.rs
+++ b/servo/components/style/values/specified/mod.rs
@@ -21,17 +21,17 @@ use super::computed::{ComputedValueAsSpe
 use super::computed::Shadow as ComputedShadow;
 
 pub use self::grid::GridLine;
 pub use self::image::{AngleOrCorner, ColorStop, EndingShape as GradientEndingShape, Gradient};
 pub use self::image::{GradientKind, HorizontalDirection, Image, LengthOrKeyword, LengthOrPercentageOrKeyword};
 pub use self::image::{SizeKeyword, VerticalDirection};
 pub use self::length::{FontRelativeLength, ViewportPercentageLength, CharacterWidth, Length, CalcLengthOrPercentage};
 pub use self::length::{Percentage, LengthOrNone, LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrAuto};
-pub use self::length::{LengthOrPercentageOrNone, LengthOrPercentageOrAutoOrContent, CalcUnit};
+pub use self::length::{LengthOrPercentageOrNone, LengthOrPercentageOrAutoOrContent, NoCalcLength, CalcUnit};
 
 pub mod basic_shape;
 pub mod grid;
 pub mod image;
 pub mod length;
 pub mod position;
 pub mod url;
 
@@ -104,23 +104,24 @@ impl<'a> Mul<CSSFloat> for &'a Simplifie
             values: self.values.iter().map(|p| p * scalar).collect()
         }
     }
 }
 
 #[derive(Clone, Debug)]
 #[allow(missing_docs)]
 pub enum SimplifiedValueNode {
-    Length(Length),
+    Length(NoCalcLength),
     Angle(Angle),
     Time(Time),
     Percentage(CSSFloat),
     Number(CSSFloat),
     Sum(Box<SimplifiedSumNode>),
 }
+
 impl<'a> Mul<CSSFloat> for &'a SimplifiedValueNode {
     type Output = SimplifiedValueNode;
 
     #[inline]
     fn mul(self, scalar: CSSFloat) -> SimplifiedValueNode {
         match *self {
             SimplifiedValueNode::Length(ref l) => SimplifiedValueNode::Length(l.clone() * scalar),
             SimplifiedValueNode::Percentage(p) => SimplifiedValueNode::Percentage(p * scalar),
@@ -192,18 +193,18 @@ pub fn parse_number(input: &mut Parser) 
 #[allow(missing_docs)]
 pub struct BorderRadiusSize(pub Size2D<LengthOrPercentage>);
 
 impl NoViewportPercentage for BorderRadiusSize {}
 
 impl BorderRadiusSize {
     #[allow(missing_docs)]
     pub fn zero() -> BorderRadiusSize {
-        let zero = LengthOrPercentage::Length(Length::Absolute(Au(0)));
-            BorderRadiusSize(Size2D::new(zero.clone(), zero))
+        let zero = LengthOrPercentage::Length(NoCalcLength::zero());
+        BorderRadiusSize(Size2D::new(zero.clone(), zero))
     }
 
     #[allow(missing_docs)]
     pub fn new(width: LengthOrPercentage, height: LengthOrPercentage) -> BorderRadiusSize {
         BorderRadiusSize(Size2D::new(width, height))
     }
 
     #[allow(missing_docs)]
@@ -286,21 +287,21 @@ impl Angle {
     }
 }
 
 #[allow(missing_docs)]
 pub fn parse_border_radius(context: &ParserContext, input: &mut Parser) -> Result<BorderRadiusSize, ()> {
     input.try(|i| BorderRadiusSize::parse(context, i)).or_else(|_| {
         match_ignore_ascii_case! { try!(input.expect_ident()),
             "thin" => Ok(BorderRadiusSize::circle(
-                             LengthOrPercentage::Length(Length::from_px(1.)))),
+                             LengthOrPercentage::Length(NoCalcLength::from_px(1.)))),
             "medium" => Ok(BorderRadiusSize::circle(
-                               LengthOrPercentage::Length(Length::from_px(3.)))),
+                               LengthOrPercentage::Length(NoCalcLength::from_px(3.)))),
             "thick" => Ok(BorderRadiusSize::circle(
-                              LengthOrPercentage::Length(Length::from_px(5.)))),
+                              LengthOrPercentage::Length(NoCalcLength::from_px(5.)))),
             _ => Err(())
         }
     })
 }
 
 #[allow(missing_docs)]
 pub fn parse_border_width(input: &mut Parser) -> Result<Length, ()> {
     input.try(Length::parse_non_negative).or_else(|()| {
@@ -599,22 +600,18 @@ impl ToComputedValue for Shadow {
         }
     }
 }
 
 impl Shadow {
     // disable_spread_and_inset is for filter: drop-shadow(...)
     #[allow(missing_docs)]
     pub fn parse(context:  &ParserContext, input: &mut Parser, disable_spread_and_inset: bool) -> Result<Shadow, ()> {
-        use app_units::Au;
         let length_count = if disable_spread_and_inset { 3 } else { 4 };
-        let mut lengths = [Length::Absolute(Au(0)),
-                           Length::Absolute(Au(0)),
-                           Length::Absolute(Au(0)),
-                           Length::Absolute(Au(0))];
+        let mut lengths = [Length::zero(), Length::zero(), Length::zero(), Length::zero()];
         let mut lengths_parsed = false;
         let mut color = None;
         let mut inset = false;
 
         loop {
             if !inset && !disable_spread_and_inset {
                 if input.try(|input| input.expect_ident_matching("inset")).is_ok() {
                     inset = true;
@@ -656,14 +653,14 @@ impl Shadow {
         if !lengths_parsed {
             return Err(())
         }
 
         Ok(Shadow {
             offset_x: lengths[0].take(),
             offset_y: lengths[1].take(),
             blur_radius: lengths[2].take(),
-            spread_radius: if disable_spread_and_inset { Length::Absolute(Au(0)) } else { lengths[3].take() },
+            spread_radius: if disable_spread_and_inset { Length::zero() } else { lengths[3].take() },
             color: color,
             inset: inset,
         })
     }
 }
--- a/servo/components/style/viewport.rs
+++ b/servo/components/style/viewport.rs
@@ -20,17 +20,17 @@ use std::ascii::AsciiExt;
 use std::borrow::Cow;
 use std::fmt;
 use std::iter::Enumerate;
 use std::str::Chars;
 use style_traits::ToCss;
 use style_traits::viewport::{Orientation, UserZoom, ViewportConstraints, Zoom};
 use stylesheets::{Stylesheet, Origin};
 use values::computed::{Context, ToComputedValue};
-use values::specified::{Length, LengthOrPercentageOrAuto, ViewportPercentageLength};
+use values::specified::{NoCalcLength, LengthOrPercentageOrAuto, ViewportPercentageLength};
 
 macro_rules! declare_viewport_descriptor {
     ( $( $variant_name: expr => $variant: ident($data: ident), )+ ) => {
          declare_viewport_descriptor_inner!([] [ $( $variant_name => $variant($data), )+ ] 0);
     };
 }
 
 macro_rules! declare_viewport_descriptor_inner {
@@ -145,24 +145,24 @@ impl FromMeta for ViewportLength {
         macro_rules! specified {
             ($value:expr) => {
                 ViewportLength::Specified(LengthOrPercentageOrAuto::Length($value))
             }
         }
 
         Some(match value {
             v if v.eq_ignore_ascii_case("device-width") =>
-                specified!(Length::ViewportPercentage(ViewportPercentageLength::Vw(100.))),
+                specified!(NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vw(100.))),
             v if v.eq_ignore_ascii_case("device-height") =>
-                specified!(Length::ViewportPercentage(ViewportPercentageLength::Vh(100.))),
+                specified!(NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vh(100.))),
             _ => {
                 match value.parse::<f32>() {
-                    Ok(n) if n >= 0. => specified!(Length::from_px(n.max(1.).min(10000.))),
+                    Ok(n) if n >= 0. => specified!(NoCalcLength::from_px(n.max(1.).min(10000.))),
                     Ok(_) => return None,
-                    Err(_) => specified!(Length::from_px(1.))
+                    Err(_) => specified!(NoCalcLength::from_px(1.))
                 }
             }
         })
     }
 }
 
 impl ViewportLength {
     fn parse(input: &mut Parser) -> Result<ViewportLength, ()> {
--- a/servo/tests/unit/style/media_queries.rs
+++ b/servo/tests/unit/style/media_queries.rs
@@ -1,13 +1,12 @@
 /* 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/. */
 
-use app_units::Au;
 use cssparser::{Parser, SourcePosition};
 use euclid::size::TypedSize2D;
 use servo_url::ServoUrl;
 use std::borrow::ToOwned;
 use style::Atom;
 use style::error_reporting::ParseErrorReporter;
 use style::media_queries::*;
 use style::parser::ParserContextExtraData;
@@ -202,80 +201,80 @@ fn test_mq_or() {
 fn test_mq_default_expressions() {
     test_media_rule("@media (min-width: 100px) { }", |list, css| {
         assert!(list.media_queries.len() == 1, css.to_owned());
         let q = &list.media_queries[0];
         assert!(q.qualifier == None, css.to_owned());
         assert!(q.media_type == MediaQueryType::All, css.to_owned());
         assert!(q.expressions.len() == 1, css.to_owned());
         match *q.expressions[0].kind_for_testing() {
-            ExpressionKind::Width(Range::Min(ref w)) => assert!(*w == specified::Length::Absolute(Au::from_px(100))),
+            ExpressionKind::Width(Range::Min(ref w)) => assert!(*w == specified::Length::from_px(100.)),
             _ => panic!("wrong expression type"),
         }
     });
 
     test_media_rule("@media (max-width: 43px) { }", |list, css| {
         assert!(list.media_queries.len() == 1, css.to_owned());
         let q = &list.media_queries[0];
         assert!(q.qualifier == None, css.to_owned());
         assert!(q.media_type == MediaQueryType::All, css.to_owned());
         assert!(q.expressions.len() == 1, css.to_owned());
         match *q.expressions[0].kind_for_testing() {
-            ExpressionKind::Width(Range::Max(ref w)) => assert!(*w == specified::Length::Absolute(Au::from_px(43))),
+            ExpressionKind::Width(Range::Max(ref w)) => assert!(*w == specified::Length::from_px(43.)),
             _ => panic!("wrong expression type"),
         }
     });
 }
 
 #[test]
 fn test_mq_expressions() {
     test_media_rule("@media screen and (min-width: 100px) { }", |list, css| {
         assert!(list.media_queries.len() == 1, css.to_owned());
         let q = &list.media_queries[0];
         assert!(q.qualifier == None, css.to_owned());
         assert!(q.media_type == MediaQueryType::Known(MediaType::Screen), css.to_owned());
         assert!(q.expressions.len() == 1, css.to_owned());
         match *q.expressions[0].kind_for_testing() {
-            ExpressionKind::Width(Range::Min(ref w)) => assert!(*w == specified::Length::Absolute(Au::from_px(100))),
+            ExpressionKind::Width(Range::Min(ref w)) => assert!(*w == specified::Length::from_px(100.)),
             _ => panic!("wrong expression type"),
         }
     });
 
     test_media_rule("@media print and (max-width: 43px) { }", |list, css| {
         assert!(list.media_queries.len() == 1, css.to_owned());
         let q = &list.media_queries[0];
         assert!(q.qualifier == None, css.to_owned());
         assert!(q.media_type == MediaQueryType::Known(MediaType::Print), css.to_owned());
         assert!(q.expressions.len() == 1, css.to_owned());
         match *q.expressions[0].kind_for_testing() {
-            ExpressionKind::Width(Range::Max(ref w)) => assert!(*w == specified::Length::Absolute(Au::from_px(43))),
+            ExpressionKind::Width(Range::Max(ref w)) => assert!(*w == specified::Length::from_px(43.)),
             _ => panic!("wrong expression type"),
         }
     });
 
     test_media_rule("@media print and (width: 43px) { }", |list, css| {
         assert!(list.media_queries.len() == 1, css.to_owned());
         let q = &list.media_queries[0];
         assert!(q.qualifier == None, css.to_owned());
         assert!(q.media_type == MediaQueryType::Known(MediaType::Print), css.to_owned());
         assert!(q.expressions.len() == 1, css.to_owned());
         match *q.expressions[0].kind_for_testing() {
-            ExpressionKind::Width(Range::Eq(ref w)) => assert!(*w == specified::Length::Absolute(Au::from_px(43))),
+            ExpressionKind::Width(Range::Eq(ref w)) => assert!(*w == specified::Length::from_px(43.)),
             _ => panic!("wrong expression type"),
         }
     });
 
     test_media_rule("@media fridge and (max-width: 52px) { }", |list, css| {
         assert!(list.media_queries.len() == 1, css.to_owned());
         let q = &list.media_queries[0];
         assert!(q.qualifier == None, css.to_owned());
         assert!(q.media_type == MediaQueryType::Unknown(Atom::from("fridge")), css.to_owned());
         assert!(q.expressions.len() == 1, css.to_owned());
         match *q.expressions[0].kind_for_testing() {
-            ExpressionKind::Width(Range::Max(ref w)) => assert!(*w == specified::Length::Absolute(Au::from_px(52))),
+            ExpressionKind::Width(Range::Max(ref w)) => assert!(*w == specified::Length::from_px(52.)),
             _ => panic!("wrong expression type"),
         }
     });
 }
 
 #[test]
 fn test_to_css() {
   test_media_rule("@media print and (width: 43px) { }", |list, _| {
@@ -290,37 +289,37 @@ fn test_to_css() {
 fn test_mq_multiple_expressions() {
     test_media_rule("@media (min-width: 100px) and (max-width: 200px) { }", |list, css| {
         assert!(list.media_queries.len() == 1, css.to_owned());
         let q = &list.media_queries[0];
         assert!(q.qualifier == None, css.to_owned());
         assert!(q.media_type == MediaQueryType::All, css.to_owned());
         assert!(q.expressions.len() == 2, css.to_owned());
         match *q.expressions[0].kind_for_testing() {
-            ExpressionKind::Width(Range::Min(ref w)) => assert!(*w == specified::Length::Absolute(Au::from_px(100))),
+            ExpressionKind::Width(Range::Min(ref w)) => assert!(*w == specified::Length::from_px(100.)),
             _ => panic!("wrong expression type"),
         }
         match *q.expressions[1].kind_for_testing() {
-            ExpressionKind::Width(Range::Max(ref w)) => assert!(*w == specified::Length::Absolute(Au::from_px(200))),
+            ExpressionKind::Width(Range::Max(ref w)) => assert!(*w == specified::Length::from_px(200.)),
             _ => panic!("wrong expression type"),
         }
     });
 
     test_media_rule("@media not screen and (min-width: 100px) and (max-width: 200px) { }", |list, css| {
         assert!(list.media_queries.len() == 1, css.to_owned());
         let q = &list.media_queries[0];
         assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
         assert!(q.media_type == MediaQueryType::Known(MediaType::Screen), css.to_owned());
         assert!(q.expressions.len() == 2, css.to_owned());
         match *q.expressions[0].kind_for_testing() {
-            ExpressionKind::Width(Range::Min(ref w)) => assert!(*w == specified::Length::Absolute(Au::from_px(100))),
+            ExpressionKind::Width(Range::Min(ref w)) => assert!(*w == specified::Length::from_px(100.)),
             _ => panic!("wrong expression type"),
         }
         match *q.expressions[1].kind_for_testing() {
-            ExpressionKind::Width(Range::Max(ref w)) => assert!(*w == specified::Length::Absolute(Au::from_px(200))),
+            ExpressionKind::Width(Range::Max(ref w)) => assert!(*w == specified::Length::from_px(200.)),
             _ => panic!("wrong expression type"),
         }
     });
 }
 
 #[test]
 fn test_mq_malformed_expressions() {
     fn check_malformed_expr(list: &MediaList, css: &str) {
--- a/servo/tests/unit/style/properties/serialization.rs
+++ b/servo/tests/unit/style/properties/serialization.rs
@@ -1,38 +1,38 @@
 /* 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/. */
 
 pub use std::sync::Arc;
 pub use style::computed_values::display::T::inline_block;
 pub use style::properties::{DeclaredValue, PropertyDeclaration, PropertyDeclarationBlock, Importance, PropertyId};
-pub use style::values::specified::{BorderStyle, BorderWidth, CSSColor, Length};
+pub use style::values::specified::{BorderStyle, BorderWidth, CSSColor, Length, NoCalcLength};
 pub use style::values::specified::{LengthOrPercentage, LengthOrPercentageOrAuto, LengthOrPercentageOrAutoOrContent};
 pub use style::properties::longhands::outline_color::computed_value::T as ComputedColor;
 pub use style::values::RGBA;
 pub use style::values::specified::url::{UrlExtraData, SpecifiedUrl};
 pub use style_traits::ToCss;
 
 #[test]
 fn property_declaration_block_should_serialize_correctly() {
     use style::properties::longhands::overflow_x::SpecifiedValue as OverflowXValue;
     use style::properties::longhands::overflow_y::SpecifiedValue as OverflowYContainer;
 
     let declarations = vec![
         (PropertyDeclaration::Width(
-            DeclaredValue::Value(LengthOrPercentageOrAuto::Length(Length::from_px(70f32)))),
+            DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(70f32)))),
          Importance::Normal),
 
         (PropertyDeclaration::MinHeight(
-            DeclaredValue::Value(LengthOrPercentage::Length(Length::from_px(20f32)))),
+            DeclaredValue::Value(LengthOrPercentage::Length(NoCalcLength::from_px(20f32)))),
          Importance::Normal),
 
         (PropertyDeclaration::Height(
-            DeclaredValue::Value(LengthOrPercentageOrAuto::Length(Length::from_px(20f32)))),
+            DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(20f32)))),
          Importance::Important),
 
         (PropertyDeclaration::Display(
             DeclaredValue::Value(inline_block)),
          Importance::Normal),
 
         (PropertyDeclaration::OverflowX(
             DeclaredValue::Value(OverflowXValue::auto)),
@@ -108,83 +108,83 @@ mod shorthand_serialization {
         pub use super::*;
 
         // we can use margin as a base to test out the different combinations
         // but afterwards, we only need to to one test per "four sides shorthand"
         #[test]
         fn all_equal_properties_should_serialize_to_one_value() {
             let mut properties = Vec::new();
 
-            let px_70 = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(Length::from_px(70f32)));
+            let px_70 = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(70f32)));
             properties.push(PropertyDeclaration::MarginTop(px_70.clone()));
             properties.push(PropertyDeclaration::MarginRight(px_70.clone()));
             properties.push(PropertyDeclaration::MarginBottom(px_70.clone()));
             properties.push(PropertyDeclaration::MarginLeft(px_70));
 
             let serialization = shorthand_properties_to_string(properties);
             assert_eq!(serialization, "margin: 70px;");
         }
 
         #[test]
         fn equal_vertical_and_equal_horizontal_properties_should_serialize_to_two_value() {
             let mut properties = Vec::new();
 
-            let vertical_px = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(Length::from_px(10f32)));
-            let horizontal_px = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(Length::from_px(5f32)));
+            let vertical_px = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(10f32)));
+            let horizontal_px = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(5f32)));
 
             properties.push(PropertyDeclaration::MarginTop(vertical_px.clone()));
             properties.push(PropertyDeclaration::MarginRight(horizontal_px.clone()));
             properties.push(PropertyDeclaration::MarginBottom(vertical_px));
             properties.push(PropertyDeclaration::MarginLeft(horizontal_px));
 
             let serialization = shorthand_properties_to_string(properties);
             assert_eq!(serialization, "margin: 10px 5px;");
         }
 
         #[test]
         fn different_vertical_and_equal_horizontal_properties_should_serialize_to_three_values() {
             let mut properties = Vec::new();
 
-            let top_px = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(Length::from_px(8f32)));
-            let bottom_px = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(Length::from_px(10f32)));
-            let horizontal_px = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(Length::from_px(5f32)));
+            let top_px = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(8f32)));
+            let bottom_px = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(10f32)));
+            let horizontal_px = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(5f32)));
 
             properties.push(PropertyDeclaration::MarginTop(top_px));
             properties.push(PropertyDeclaration::MarginRight(horizontal_px.clone()));
             properties.push(PropertyDeclaration::MarginBottom(bottom_px));
             properties.push(PropertyDeclaration::MarginLeft(horizontal_px));
 
             let serialization = shorthand_properties_to_string(properties);
             assert_eq!(serialization, "margin: 8px 5px 10px;");
         }
 
         #[test]
         fn different_properties_should_serialize_to_four_values() {
             let mut properties = Vec::new();
 
-            let top_px = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(Length::from_px(8f32)));
-            let right_px = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(Length::from_px(12f32)));
-            let bottom_px = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(Length::from_px(10f32)));
-            let left_px = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(Length::from_px(14f32)));
+            let top_px = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(8f32)));
+            let right_px = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(12f32)));
+            let bottom_px = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(10f32)));
+            let left_px = DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(14f32)));
 
             properties.push(PropertyDeclaration::MarginTop(top_px));
             properties.push(PropertyDeclaration::MarginRight(right_px));
             properties.push(PropertyDeclaration::MarginBottom(bottom_px));
             properties.push(PropertyDeclaration::MarginLeft(left_px));
 
             let serialization = shorthand_properties_to_string(properties);
             assert_eq!(serialization, "margin: 8px 12px 10px 14px;");
         }
 
         #[test]
         fn padding_should_serialize_correctly() {
             let mut properties = Vec::new();
 
-            let px_10 = DeclaredValue::Value(LengthOrPercentage::Length(Length::from_px(10f32)));
-            let px_15 = DeclaredValue::Value(LengthOrPercentage::Length(Length::from_px(15f32)));
+            let px_10 = DeclaredValue::Value(LengthOrPercentage::Length(NoCalcLength::from_px(10f32)));
+            let px_15 = DeclaredValue::Value(LengthOrPercentage::Length(NoCalcLength::from_px(15f32)));
             properties.push(PropertyDeclaration::PaddingTop(px_10.clone()));
             properties.push(PropertyDeclaration::PaddingRight(px_15.clone()));
             properties.push(PropertyDeclaration::PaddingBottom(px_10));
             properties.push(PropertyDeclaration::PaddingLeft(px_15));
 
             let serialization = shorthand_properties_to_string(properties);
             assert_eq!(serialization, "padding: 10px 15px;");
         }
@@ -632,17 +632,17 @@ mod shorthand_serialization {
                 FamilyContainer(vec![FontFamily::Generic(atom!("serif"))])
             );
 
 
             let font_style = DeclaredValue::Value(FontStyle::italic);
             let font_variant = DeclaredValue::Value(FontVariant::normal);
             let font_weight = DeclaredValue::Value(FontWeight::Bolder);
             let font_size = DeclaredValue::Value(FontSizeContainer(
-                LengthOrPercentage::Length(Length::from_px(4f32)))
+                LengthOrPercentage::Length(NoCalcLength::from_px(4f32)))
             );
             let font_stretch = DeclaredValue::Value(FontStretch::expanded);
             let line_height = DeclaredValue::Value(LineHeight::Number(3f32));
 
             properties.push(PropertyDeclaration::FontFamily(font_family));
             properties.push(PropertyDeclaration::FontStyle(font_style));
             properties.push(PropertyDeclaration::FontVariant(font_variant));
             properties.push(PropertyDeclaration::FontWeight(font_weight));
@@ -713,38 +713,38 @@ mod shorthand_serialization {
             let color = DeclaredValue::Value(CSSColor {
                 parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }),
                 authored: None
             });
 
             let position_x = single_vec_value_typedef!(position_x,
                 HorizontalPosition {
                     keyword: None,
-                    position: Some(LengthOrPercentage::Length(Length::from_px(7f32))),
+                    position: Some(LengthOrPercentage::Length(NoCalcLength::from_px(7f32))),
                 }
             );
 
             let position_y = single_vec_value_typedef!(position_y,
                 VerticalPosition {
                     keyword: None,
-                    position: Some(LengthOrPercentage::Length(Length::from_px(4f32))),
+                    position: Some(LengthOrPercentage::Length(NoCalcLength::from_px(4f32))),
                 }
             );
 
             let repeat = single_vec_keyword_value!(repeat, repeat_x);
             let attachment = single_vec_keyword_value!(attachment, scroll);
 
             let image = single_vec_value!(image,
                 Some(Image::Url(SpecifiedUrl::new_for_testing("http://servo/test.png"))));
 
             let size = single_vec_variant_value!(size,
                 size::single_value::SpecifiedValue::Explicit(
                     size::single_value::ExplicitSize {
-                        width: LengthOrPercentageOrAuto::Length(Length::from_px(70f32)),
-                        height: LengthOrPercentageOrAuto::Length(Length::from_px(50f32))
+                        width: LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(70f32)),
+                        height: LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(50f32))
                     }
                 )
             );
 
             let origin = single_vec_keyword_value!(origin, border_box);
             let clip = single_vec_keyword_value!(clip, padding_box);
 
             properties.push(PropertyDeclaration::BackgroundColor(color));
@@ -773,38 +773,38 @@ mod shorthand_serialization {
             let color = DeclaredValue::Value(CSSColor {
                 parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }),
                 authored: None
             });
 
             let position_x = single_vec_value_typedef!(position_x,
                 HorizontalPosition {
                     keyword: None,
-                    position: Some(LengthOrPercentage::Length(Length::from_px(7f32))),
+                    position: Some(LengthOrPercentage::Length(NoCalcLength::from_px(7f32))),
                 }
             );
 
             let position_y = single_vec_value_typedef!(position_y,
                 VerticalPosition {
                     keyword: None,
-                    position: Some(LengthOrPercentage::Length(Length::from_px(4f32))),
+                    position: Some(LengthOrPercentage::Length(NoCalcLength::from_px(4f32))),
                 }
             );
 
             let repeat = single_vec_keyword_value!(repeat, repeat_x);
             let attachment = single_vec_keyword_value!(attachment, scroll);
 
             let image = single_vec_value!(image,
                         Some(Image::Url(SpecifiedUrl::new_for_testing("http://servo/test.png"))));
 
             let size = single_vec_variant_value!(size,
                 size::single_value::SpecifiedValue::Explicit(
                     size::single_value::ExplicitSize {
-                        width: LengthOrPercentageOrAuto::Length(Length::from_px(70f32)),
-                        height: LengthOrPercentageOrAuto::Length(Length::from_px(50f32))
+                        width: LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(70f32)),
+                        height: LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(50f32))
                     }
                 )
             );
 
             let origin = single_vec_keyword_value!(origin, padding_box);
             let clip = single_vec_keyword_value!(clip, padding_box);
 
             properties.push(PropertyDeclaration::BackgroundColor(color));
@@ -832,24 +832,24 @@ mod shorthand_serialization {
             let color = DeclaredValue::Value(CSSColor {
                 parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }),
                 authored: None
             });
 
             let position_x = single_vec_value_typedef!(position_x,
                 HorizontalPosition {
                     keyword: None,
-                    position: Some(LengthOrPercentage::Length(Length::from_px(0f32))),
+                    position: Some(LengthOrPercentage::Length(NoCalcLength::from_px(0f32))),
                 }
             );
 
             let position_y = single_vec_value_typedef!(position_y,
                 VerticalPosition {
                     keyword: None,
-                    position: Some(LengthOrPercentage::Length(Length::from_px(0f32))),
+                    position: Some(LengthOrPercentage::Length(NoCalcLength::from_px(0f32))),
                 }
             );
 
             let repeat = single_vec_keyword_value!(repeat, repeat_x);
             let attachment = single_vec_keyword_value!(attachment, scroll);
 
             let image = single_vec_value!(image, None);
 
@@ -917,30 +917,30 @@ mod shorthand_serialization {
                     Image::Url(SpecifiedUrl::new_for_testing("http://servo/test.png"))));
 
             let mode = single_vec_keyword_value!(mode, luminance);
 
             let position = single_vec_value_typedef!(position,
                 Position {
                     horizontal: HorizontalPosition {
                         keyword: None,
-                        position: Some(LengthOrPercentage::Length(Length::from_px(7f32))),
+                        position: Some(LengthOrPercentage::Length(NoCalcLength::from_px(7f32))),
                     },
                     vertical: VerticalPosition {
                         keyword: None,
-                        position: Some(LengthOrPercentage::Length(Length::from_px(4f32))),
+                        position: Some(LengthOrPercentage::Length(NoCalcLength::from_px(4f32))),
                     },
                 }
             );
 
             let size = single_vec_variant_value!(size,
                 size::single_value::SpecifiedValue::Explicit(
                     size::single_value::ExplicitSize {
-                        width: LengthOrPercentageOrAuto::Length(Length::from_px(70f32)),
-                        height: LengthOrPercentageOrAuto::Length(Length::from_px(50f32))
+                        width: LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(70f32)),
+                        height: LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(50f32))
                     }
                 )
             );
 
             let repeat = single_vec_keyword_value!(repeat, repeat_x);
             let origin = single_vec_keyword_value!(origin, padding_box);
             let clip = single_vec_keyword_value!(clip, border_box);
             let composite = single_vec_keyword_value!(composite, subtract);
@@ -971,30 +971,30 @@ mod shorthand_serialization {
                     Image::Url(SpecifiedUrl::new_for_testing("http://servo/test.png"))));
 
             let mode = single_vec_keyword_value!(mode, luminance);
 
             let position = single_vec_value_typedef!(position,
                 Position {
                     horizontal: HorizontalPosition {
                         keyword: None,
-                        position: Some(LengthOrPercentage::Length(Length::from_px(7f32))),
+                        position: Some(LengthOrPercentage::Length(NoCalcLength::from_px(7f32))),
                     },
                     vertical: VerticalPosition {
                         keyword: None,
-                        position: Some(LengthOrPercentage::Length(Length::from_px(4f32))),
+                        position: Some(LengthOrPercentage::Length(NoCalcLength::from_px(4f32))),
                     },
                 }
             );
 
             let size = single_vec_variant_value!(size,
                 size::single_value::SpecifiedValue::Explicit(
                     size::single_value::ExplicitSize {
-                        width: LengthOrPercentageOrAuto::Length(Length::from_px(70f32)),
-                        height: LengthOrPercentageOrAuto::Length(Length::from_px(50f32))
+                        width: LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(70f32)),
+                        height: LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(50f32))
                     }
                 )
             );
 
             let repeat = single_vec_keyword_value!(repeat, repeat_x);
             let origin = single_vec_keyword_value!(origin, padding_box);
             let clip = single_vec_keyword_value!(clip, padding_box);
             let composite = single_vec_keyword_value!(composite, subtract);
--- a/servo/tests/unit/style/properties/viewport.rs
+++ b/servo/tests/unit/style/properties/viewport.rs
@@ -1,27 +1,27 @@
 /* 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/. */
 
 use app_units::Au;
 use style::properties::{DeclaredValue, PropertyDeclaration};
 use style::properties::longhands::border_top_width;
 use style::values::HasViewportPercentage;
-use style::values::specified::{Length, ViewportPercentageLength};
+use style::values::specified::{Length, NoCalcLength, ViewportPercentageLength};
 
 #[test]
 fn has_viewport_percentage_for_specified_value() {
     //TODO: test all specified value with a HasViewportPercentage impl
     let pvw = PropertyDeclaration::BorderTopWidth(
         DeclaredValue::Value(border_top_width::SpecifiedValue::from_length(
-            Length::ViewportPercentage(ViewportPercentageLength::Vw(100.))
+            Length::NoCalc(NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vw(100.)))
         ))
     );
     assert!(pvw.has_viewport_percentage());
 
     let pabs = PropertyDeclaration::BorderTopWidth(
         DeclaredValue::Value(border_top_width::SpecifiedValue::from_length(
-            Length::Absolute(Au(100))
+            Length::NoCalc(NoCalcLength::Absolute(Au(100)))
         ))
     );
     assert!(!pabs.has_viewport_percentage());
 }
--- a/servo/tests/unit/style/value.rs
+++ b/servo/tests/unit/style/value.rs
@@ -1,23 +1,23 @@
 /* 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/. */
 
 use app_units::Au;
 use cssparser::Parser;
 use style::values::HasViewportPercentage;
-use style::values::specified::{ViewportPercentageLength, Length};
+use style::values::specified::{ViewportPercentageLength, NoCalcLength};
 use style::values::specified::length::{CalcLengthOrPercentage, CalcUnit};
 
 #[test]
 fn length_has_viewport_percentage() {
-    let l = Length::ViewportPercentage(ViewportPercentageLength::Vw(100.));
+    let l = NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vw(100.));
     assert!(l.has_viewport_percentage());
-    let l = Length::Absolute(Au(100));
+    let l = NoCalcLength::Absolute(Au(100));
     assert!(!l.has_viewport_percentage());
 }
 
 #[test]
 fn calc_top_level_number_with_unit() {
     fn parse(text: &str, unit: CalcUnit) -> Result<CalcLengthOrPercentage, ()> {
         let mut parser = Parser::new(text);
         CalcLengthOrPercentage::parse(&mut parser, unit)
--- a/servo/tests/unit/style/viewport.rs
+++ b/servo/tests/unit/style/viewport.rs
@@ -7,18 +7,18 @@ use euclid::scale_factor::ScaleFactor;
 use euclid::size::TypedSize2D;
 use media_queries::CSSErrorReporterTest;
 use servo_config::prefs::{PREFS, PrefValue};
 use servo_url::ServoUrl;
 use style::error_reporting::ParseErrorReporter;
 use style::media_queries::{Device, MediaType};
 use style::parser::{ParserContext, ParserContextExtraData};
 use style::stylesheets::{Stylesheet, Origin};
-use style::values::specified::Length::{self, ViewportPercentage};
 use style::values::specified::LengthOrPercentageOrAuto::{self, Auto};
+use style::values::specified::NoCalcLength::{self, ViewportPercentage};
 use style::values::specified::ViewportPercentageLength::Vw;
 use style::viewport::*;
 use style_traits::viewport::*;
 
 macro_rules! stylesheet {
     ($css:expr, $origin:ident, $error_reporter:expr) => {
         Box::new(Stylesheet::from_str(
             $css,
@@ -75,17 +75,17 @@ macro_rules! assert_decl_len {
         assert!($declarations.len() == $len,
                 "expected {} declarations; have {}: {:?})",
                 $len, $declarations.len(), $declarations)
     }
 }
 
 macro_rules! viewport_length {
     ($value:expr, px) => {
-        ViewportLength::Specified(LengthOrPercentageOrAuto::Length(Length::from_px($value)))
+        ViewportLength::Specified(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px($value)))
     };
     ($value:expr, vw) => {
         ViewportLength::Specified(LengthOrPercentageOrAuto::Length(ViewportPercentage(Vw($value))))
     }
 }
 
 #[test]
 fn empty_viewport_rule() {