diff options
Diffstat (limited to 'compiler/rustc_const_eval/src/util')
-rw-r--r-- | compiler/rustc_const_eval/src/util/aggregate.rs | 77 | ||||
-rw-r--r-- | compiler/rustc_const_eval/src/util/call_kind.rs | 3 | ||||
-rw-r--r-- | compiler/rustc_const_eval/src/util/check_validity_requirement.rs (renamed from compiler/rustc_const_eval/src/util/might_permit_raw_init.rs) | 65 | ||||
-rw-r--r-- | compiler/rustc_const_eval/src/util/mod.rs | 6 | ||||
-rw-r--r-- | compiler/rustc_const_eval/src/util/type_name.rs | 1 |
5 files changed, 44 insertions, 108 deletions
diff --git a/compiler/rustc_const_eval/src/util/aggregate.rs b/compiler/rustc_const_eval/src/util/aggregate.rs deleted file mode 100644 index 10783c5ed..000000000 --- a/compiler/rustc_const_eval/src/util/aggregate.rs +++ /dev/null @@ -1,77 +0,0 @@ -use rustc_index::vec::Idx; -use rustc_middle::mir::*; -use rustc_middle::ty::{Ty, TyCtxt}; -use rustc_target::abi::VariantIdx; - -use std::iter::TrustedLen; - -/// Expand `lhs = Rvalue::Aggregate(kind, operands)` into assignments to the fields. -/// -/// Produces something like -/// ```ignore (ilustrative) -/// (lhs as Variant).field0 = arg0; // We only have a downcast if this is an enum -/// (lhs as Variant).field1 = arg1; -/// discriminant(lhs) = variant_index; // If lhs is an enum or generator. -/// ``` -pub fn expand_aggregate<'tcx>( - orig_lhs: Place<'tcx>, - operands: impl Iterator<Item = (Operand<'tcx>, Ty<'tcx>)> + TrustedLen, - kind: AggregateKind<'tcx>, - source_info: SourceInfo, - tcx: TyCtxt<'tcx>, -) -> impl Iterator<Item = Statement<'tcx>> + TrustedLen { - let mut lhs = orig_lhs; - let mut set_discriminant = None; - let active_field_index = match kind { - AggregateKind::Adt(adt_did, variant_index, _, _, active_field_index) => { - let adt_def = tcx.adt_def(adt_did); - if adt_def.is_enum() { - set_discriminant = Some(Statement { - kind: StatementKind::SetDiscriminant { - place: Box::new(orig_lhs), - variant_index, - }, - source_info, - }); - lhs = tcx.mk_place_downcast(orig_lhs, adt_def, variant_index); - } - active_field_index - } - AggregateKind::Generator(..) => { - // Right now we only support initializing generators to - // variant 0 (Unresumed). - let variant_index = VariantIdx::new(0); - set_discriminant = Some(Statement { - kind: StatementKind::SetDiscriminant { place: Box::new(orig_lhs), variant_index }, - source_info, - }); - - // Operands are upvars stored on the base place, so no - // downcast is necessary. - - None - } - _ => None, - }; - - let operands = operands.enumerate().map(move |(i, (op, ty))| { - let lhs_field = if let AggregateKind::Array(_) = kind { - let offset = u64::try_from(i).unwrap(); - tcx.mk_place_elem( - lhs, - ProjectionElem::ConstantIndex { offset, min_length: offset + 1, from_end: false }, - ) - } else { - let field = Field::new(active_field_index.unwrap_or(i)); - tcx.mk_place_field(lhs, field, ty) - }; - Statement { - source_info, - kind: StatementKind::Assign(Box::new((lhs_field, Rvalue::Use(op)))), - } - }); - [Statement { source_info, kind: StatementKind::Deinit(Box::new(orig_lhs)) }] - .into_iter() - .chain(operands) - .chain(set_discriminant) -} diff --git a/compiler/rustc_const_eval/src/util/call_kind.rs b/compiler/rustc_const_eval/src/util/call_kind.rs index 38d9b0449..995363c0e 100644 --- a/compiler/rustc_const_eval/src/util/call_kind.rs +++ b/compiler/rustc_const_eval/src/util/call_kind.rs @@ -40,6 +40,7 @@ pub enum CallKind<'tcx> { self_arg: Option<Ident>, desugaring: Option<(CallDesugaringKind, Ty<'tcx>)>, method_did: DefId, + method_substs: SubstsRef<'tcx>, }, /// A call to `Fn(..)::call(..)`, desugared from `my_closure(a, b, c)` FnCall { fn_trait_id: DefId, self_ty: Ty<'tcx> }, @@ -131,6 +132,6 @@ pub fn call_kind<'tcx>( } else { None }; - CallKind::Normal { self_arg, desugaring, method_did } + CallKind::Normal { self_arg, desugaring, method_did, method_substs } }) } diff --git a/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index 4ce107ea6..23fcd22c5 100644 --- a/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -1,7 +1,7 @@ -use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout}; -use rustc_middle::ty::{ParamEnv, TyCtxt}; +use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement}; +use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt}; use rustc_session::Limit; -use rustc_target::abi::{Abi, FieldsShape, InitKind, Scalar, Variants}; +use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants}; use crate::const_eval::{CheckAlignment, CompileTimeInterpreter}; use crate::interpret::{InterpCx, MemoryKind, OpTy}; @@ -18,16 +18,23 @@ use crate::interpret::{InterpCx, MemoryKind, OpTy}; /// Rust UB as long as there is no risk of miscompilations. The `strict_init_checks` can be set to /// do a full check against Rust UB instead (in which case we will also ignore the 0x01-filling and /// to the full uninit check). -pub fn might_permit_raw_init<'tcx>( +pub fn check_validity_requirement<'tcx>( tcx: TyCtxt<'tcx>, - ty: TyAndLayout<'tcx>, - kind: InitKind, -) -> bool { - if tcx.sess.opts.unstable_opts.strict_init_checks { - might_permit_raw_init_strict(ty, tcx, kind) + kind: ValidityRequirement, + param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>, +) -> Result<bool, LayoutError<'tcx>> { + let layout = tcx.layout_of(param_env_and_ty)?; + + // There is nothing strict or lax about inhabitedness. + if kind == ValidityRequirement::Inhabited { + return Ok(!layout.abi.is_uninhabited()); + } + + if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks { + might_permit_raw_init_strict(layout, tcx, kind) } else { - let layout_cx = LayoutCx { tcx, param_env: ParamEnv::reveal_all() }; - might_permit_raw_init_lax(ty, &layout_cx, kind) + let layout_cx = LayoutCx { tcx, param_env: param_env_and_ty.param_env }; + might_permit_raw_init_lax(layout, &layout_cx, kind) } } @@ -36,8 +43,8 @@ pub fn might_permit_raw_init<'tcx>( fn might_permit_raw_init_strict<'tcx>( ty: TyAndLayout<'tcx>, tcx: TyCtxt<'tcx>, - kind: InitKind, -) -> bool { + kind: ValidityRequirement, +) -> Result<bool, LayoutError<'tcx>> { let machine = CompileTimeInterpreter::new( Limit::new(0), /*can_access_statics:*/ false, @@ -50,7 +57,7 @@ fn might_permit_raw_init_strict<'tcx>( .allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap)) .expect("OOM: failed to allocate for uninit check"); - if kind == InitKind::Zero { + if kind == ValidityRequirement::Zero { cx.write_bytes_ptr( allocated.ptr, std::iter::repeat(0_u8).take(ty.layout.size().bytes_usize()), @@ -64,7 +71,7 @@ fn might_permit_raw_init_strict<'tcx>( // This does *not* actually check that references are dereferenceable, but since all types that // require dereferenceability also require non-null, we don't actually get any false negatives // due to this. - cx.validate_operand(&ot).is_ok() + Ok(cx.validate_operand(&ot).is_ok()) } /// Implements the 'lax' (default) version of the `might_permit_raw_init` checks; see that function for @@ -72,15 +79,18 @@ fn might_permit_raw_init_strict<'tcx>( fn might_permit_raw_init_lax<'tcx>( this: TyAndLayout<'tcx>, cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, - init_kind: InitKind, -) -> bool { + init_kind: ValidityRequirement, +) -> Result<bool, LayoutError<'tcx>> { let scalar_allows_raw_init = move |s: Scalar| -> bool { match init_kind { - InitKind::Zero => { + ValidityRequirement::Inhabited => { + bug!("ValidityRequirement::Inhabited should have been handled above") + } + ValidityRequirement::Zero => { // The range must contain 0. s.valid_range(cx).contains(0) } - InitKind::UninitMitigated0x01Fill => { + ValidityRequirement::UninitMitigated0x01Fill => { // The range must include an 0x01-filled buffer. let mut val: u128 = 0x01; for _ in 1..s.size(cx).bytes() { @@ -89,6 +99,9 @@ fn might_permit_raw_init_lax<'tcx>( } s.valid_range(cx).contains(val) } + ValidityRequirement::Uninit => { + bug!("ValidityRequirement::Uninit should have been handled above") + } } }; @@ -102,20 +115,20 @@ fn might_permit_raw_init_lax<'tcx>( }; if !valid { // This is definitely not okay. - return false; + return Ok(false); } // Special magic check for references and boxes (i.e., special pointer types). if let Some(pointee) = this.ty.builtin_deref(false) { - let pointee = cx.layout_of(pointee.ty).expect("need to be able to compute layouts"); + let pointee = cx.layout_of(pointee.ty)?; // We need to ensure that the LLVM attributes `aligned` and `dereferenceable(size)` are satisfied. if pointee.align.abi.bytes() > 1 { // 0x01-filling is not aligned. - return false; + return Ok(false); } if pointee.size.bytes() > 0 { // A 'fake' integer pointer is not sufficiently dereferenceable. - return false; + return Ok(false); } } @@ -128,9 +141,9 @@ fn might_permit_raw_init_lax<'tcx>( } FieldsShape::Arbitrary { offsets, .. } => { for idx in 0..offsets.len() { - if !might_permit_raw_init_lax(this.field(cx, idx), cx, init_kind) { + if !might_permit_raw_init_lax(this.field(cx, idx), cx, init_kind)? { // We found a field that is unhappy with this kind of initialization. - return false; + return Ok(false); } } } @@ -147,5 +160,5 @@ fn might_permit_raw_init_lax<'tcx>( } } - true + Ok(true) } diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs index 76ea5a24e..c0aabd77c 100644 --- a/compiler/rustc_const_eval/src/util/mod.rs +++ b/compiler/rustc_const_eval/src/util/mod.rs @@ -1,16 +1,14 @@ -pub mod aggregate; mod alignment; mod call_kind; +mod check_validity_requirement; pub mod collect_writes; mod compare_types; mod find_self_call; -mod might_permit_raw_init; mod type_name; -pub use self::aggregate::expand_aggregate; pub use self::alignment::is_disaligned; pub use self::call_kind::{call_kind, CallDesugaringKind, CallKind}; +pub use self::check_validity_requirement::check_validity_requirement; pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype}; pub use self::find_self_call::find_self_call; -pub use self::might_permit_raw_init::might_permit_raw_init; pub use self::type_name::type_name; diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index c4122f664..4e80a2851 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -64,6 +64,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { ty::Foreign(def_id) => self.print_def_path(def_id, &[]), ty::GeneratorWitness(_) => bug!("type_name: unexpected `GeneratorWitness`"), + ty::GeneratorWitnessMIR(..) => bug!("type_name: unexpected `GeneratorWitnessMIR`"), } } |