Skip to content
Permalink
Browse files

Use early unwraps instead of bubbling up errors just to unwrap in the…

… end
  • Loading branch information...
oli-obk committed Feb 16, 2019
1 parent a9da8fc commit 5c0615b89c399ce6a431ba660f9457c24bc69964
@@ -49,36 +49,36 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
constant: Result<ty::Const<'tcx>, ErrorHandled>,
) -> (Bx::Value, Ty<'tcx>) {
constant
.and_then(|c| {
.map(|c| {
let field_ty = c.ty.builtin_index().unwrap();
let fields = match c.ty.sty {
ty::Array(_, n) => n.unwrap_usize(bx.tcx()),
ref other => bug!("invalid simd shuffle type: {}", other),
};
let values: Result<Vec<_>, ErrorHandled> = (0..fields).map(|field| {
let values: Vec<_> = (0..fields).map(|field| {
let field = const_field(
bx.tcx(),
ty::ParamEnv::reveal_all(),
None,
mir::Field::new(field as usize),
c,
)?;
);
if let Some(prim) = field.val.try_to_scalar() {
let layout = bx.layout_of(field_ty);
let scalar = match layout.abi {
layout::Abi::Scalar(ref x) => x,
_ => bug!("from_const: invalid ByVal layout: {:#?}", layout)
};
Ok(bx.scalar_to_backend(
bx.scalar_to_backend(
prim, scalar,
bx.immediate_backend_type(layout),
))
)
} else {
bug!("simd shuffle field {:?}", field)
}
}).collect();
let llval = bx.const_struct(&values?, false);
Ok((llval, c.ty))
let llval = bx.const_struct(&values, false);
(llval, c.ty)
})
.unwrap_or_else(|_| {
bx.tcx().sess.span_err(
@@ -466,45 +466,42 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
}

/// Projects to a field of a (variant of a) const.
// this function uses `unwrap` copiously, because an already validated constant must have valid
// fields and can thus never fail outside of compiler bugs
pub fn const_field<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
variant: Option<VariantIdx>,
field: mir::Field,
value: ty::Const<'tcx>,
) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
) -> ty::Const<'tcx> {
trace!("const_field: {:?}, {:?}", field, value);
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
let result = (|| {
// get the operand again
let op = ecx.const_to_op(value, None)?;
// downcast
let down = match variant {
None => op,
Some(variant) => ecx.operand_downcast(op, variant)?
};
// then project
let field = ecx.operand_field(down, field.index() as u64)?;
// and finally move back to the const world, always normalizing because
// this is not called for statics.
op_to_const(&ecx, field)
})();
result.map_err(|error| {
let err = error_to_const_error(&ecx, error);
err.report_as_error(ecx.tcx, "could not access field of constant");
ErrorHandled::Reported
})
// get the operand again
let op = ecx.const_to_op(value, None).unwrap();
// downcast
let down = match variant {
None => op,
Some(variant) => ecx.operand_downcast(op, variant).unwrap(),
};
// then project
let field = ecx.operand_field(down, field.index() as u64).unwrap();
// and finally move back to the const world, always normalizing because
// this is not called for statics.
op_to_const(&ecx, field).unwrap()
}

// this function uses `unwrap` copiously, because an already validated constant must have valid
// fields and can thus never fail outside of compiler bugs
pub fn const_variant_index<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
val: ty::Const<'tcx>,
) -> EvalResult<'tcx, VariantIdx> {
) -> VariantIdx {
trace!("const_variant_index: {:?}", val);
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
let op = ecx.const_to_op(val, None)?;
Ok(ecx.read_discriminant(op)?.1)
let op = ecx.const_to_op(val, None).unwrap();
ecx.read_discriminant(op).unwrap().1
}

pub fn error_to_const_error<'a, 'mir, 'tcx>(
@@ -440,13 +440,7 @@ impl<'tcx> Constructor<'tcx> {
assert!(!adt.is_enum());
VariantIdx::new(0)
}
&ConstantValue(c) => {
crate::const_eval::const_variant_index(
cx.tcx,
cx.param_env,
c,
).unwrap()
},
&ConstantValue(c) => crate::const_eval::const_variant_index(cx.tcx, cx.param_env, c),
_ => bug!("bad constructor {:?} for adt {:?}", self, adt)
}
}
@@ -937,10 +937,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
debug!("const_to_pat: cv={:#?} id={:?}", cv, id);
let adt_subpattern = |i, variant_opt| {
let field = Field::new(i);
let val = const_field(
self.tcx, self.param_env,
variant_opt, field, cv,
).expect("field access failed");
let val = const_field(self.tcx, self.param_env, variant_opt, field, cv);
self.const_to_pat(instance, val, id, span)
};
let adt_subpatterns = |n, variant_opt| {
@@ -979,9 +976,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
PatternKind::Wild
}
ty::Adt(adt_def, substs) if adt_def.is_enum() => {
let variant_index = const_variant_index(
self.tcx, self.param_env, cv
).expect("const_variant_index failed");
let variant_index = const_variant_index(self.tcx, self.param_env, cv);
let subpatterns = adt_subpatterns(
adt_def.variants[variant_index].fields.len(),
Some(variant_index),

0 comments on commit 5c0615b

Please sign in to comment.
You can’t perform that action at this time.