about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/ty/util.rs40
-rw-r--r--src/librustc_mir/transform/check_consts/qualifs.rs25
-rw-r--r--src/test/run-make-fulldeps/min-global-align/min_global_align.rs10
3 files changed, 52 insertions, 23 deletions
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index f3c3d04931a..cb43f7475b8 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -697,7 +697,7 @@ impl<'tcx> ty::TyS<'tcx> {
     /// strange rules like `<T as Foo<'static>>::Bar: Sized` that
     /// actually carry lifetime requirements.
     pub fn is_sized(&'tcx self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
-        tcx_at.is_sized_raw(param_env.and(self))
+        self.is_trivially_sized(tcx_at.tcx) || tcx_at.is_sized_raw(param_env.and(self))
     }
 
     /// Checks whether values of this type `T` implement the `Freeze`
@@ -713,7 +713,43 @@ impl<'tcx> ty::TyS<'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         span: Span,
     ) -> bool {
-        tcx.at(span).is_freeze_raw(param_env.and(self))
+        self.is_trivially_freeze() || tcx.at(span).is_freeze_raw(param_env.and(self))
+    }
+
+    /// Fast path helper for testing if a type is `Freeze`.
+    ///
+    /// Returning true means the type is known to be `Freeze`. Returning
+    /// `false` means nothing -- could be `Freeze`, might not be.
+    fn is_trivially_freeze(&self) -> bool {
+        match self.kind {
+            ty::Int(_)
+            | ty::Uint(_)
+            | ty::Float(_)
+            | ty::Bool
+            | ty::Char
+            | ty::Str
+            | ty::Never
+            | ty::Ref(..)
+            | ty::RawPtr(_)
+            | ty::FnDef(..)
+            | ty::Error
+            | ty::FnPtr(_) => true,
+            ty::Tuple(_) => self.tuple_fields().all(Self::is_trivially_freeze),
+            ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_freeze(),
+            ty::Adt(..)
+            | ty::Bound(..)
+            | ty::Closure(..)
+            | ty::Dynamic(..)
+            | ty::Foreign(_)
+            | ty::Generator(..)
+            | ty::GeneratorWitness(_)
+            | ty::Infer(_)
+            | ty::Opaque(..)
+            | ty::Param(_)
+            | ty::Placeholder(_)
+            | ty::Projection(_)
+            | ty::UnnormalizedProjection(_) => false,
+        }
     }
 
     /// If `ty.needs_drop(...)` returns `true`, then `ty` is definitely
diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs
index e509e8267cc..215496e4d03 100644
--- a/src/librustc_mir/transform/check_consts/qualifs.rs
+++ b/src/librustc_mir/transform/check_consts/qualifs.rs
@@ -94,32 +94,23 @@ pub trait Qualif {
             }
 
             Operand::Constant(ref constant) => {
-                if constant.check_static_ptr(cx.tcx).is_some() {
-                    // `mir_const_qualif` does return the qualifs in the final value of a `static`,
-                    // so we could use value-based qualification here, but we shouldn't do this
-                    // without a good reason.
-                    //
-                    // Note: this uses `constant.literal.ty` which is a reference or pointer to the
-                    // type of the actual `static` item.
-                    Self::in_any_value_of_ty(cx, constant.literal.ty)
-                } else if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val
-                {
+                // Check the qualifs of the value of `const` items.
+                if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val {
                     assert!(promoted.is_none());
                     // Don't peek inside trait associated constants.
-                    if cx.tcx.trait_of_item(def_id).is_some() {
-                        Self::in_any_value_of_ty(cx, constant.literal.ty)
-                    } else {
+                    if cx.tcx.trait_of_item(def_id).is_none() {
                         let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def_id);
-                        let qualif = Self::in_qualifs(&qualifs);
+                        if !Self::in_qualifs(&qualifs) {
+                            return false;
+                        }
 
                         // Just in case the type is more specific than
                         // the definition, e.g., impl associated const
                         // with type parameters, take it into account.
-                        qualif && Self::in_any_value_of_ty(cx, constant.literal.ty)
                     }
-                } else {
-                    false
                 }
+                // Otherwise use the qualifs of the type.
+                Self::in_any_value_of_ty(cx, constant.literal.ty)
             }
         }
     }
diff --git a/src/test/run-make-fulldeps/min-global-align/min_global_align.rs b/src/test/run-make-fulldeps/min-global-align/min_global_align.rs
index ce86d202c62..d9851a2f794 100644
--- a/src/test/run-make-fulldeps/min-global-align/min_global_align.rs
+++ b/src/test/run-make-fulldeps/min-global-align/min_global_align.rs
@@ -1,5 +1,5 @@
 #![feature(no_core, lang_items)]
-#![crate_type="rlib"]
+#![crate_type = "rlib"]
 #![no_core]
 
 pub static STATIC_BOOL: bool = true;
@@ -9,7 +9,6 @@ pub static mut STATIC_MUT_BOOL: bool = true;
 const CONST_BOOL: bool = true;
 pub static CONST_BOOL_REF: &'static bool = &CONST_BOOL;
 
-
 #[lang = "sized"]
 trait Sized {}
 
@@ -19,10 +18,13 @@ trait Copy {}
 #[lang = "freeze"]
 trait Freeze {}
 
+// No `UnsafeCell`, so everything is `Freeze`.
+impl<T: ?Sized> Freeze for T {}
+
 #[lang = "sync"]
 trait Sync {}
 impl Sync for bool {}
 impl Sync for &'static bool {}
 
-#[lang="drop_in_place"]
-pub unsafe fn drop_in_place<T: ?Sized>(_: *mut T) { }
+#[lang = "drop_in_place"]
+pub unsafe fn drop_in_place<T: ?Sized>(_: *mut T) {}