diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index f3c3d04931ac3..cb43f7475b89a 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 `>::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 e509e8267cc1a..215496e4d03cb 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 ce86d202c62d3..d9851a2f79422 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 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(_: *mut T) { } +#[lang = "drop_in_place"] +pub unsafe fn drop_in_place(_: *mut T) {}