From 7c486416cb68efcefcf216037d1bcaab60e88133 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 12 Jan 2017 08:52:22 +0100 Subject: [PATCH] allow the use of tuple struct constructors as functions --- src/terminator/mod.rs | 28 +++++++++++++++++++ .../run-pass/tuple_like_struct_constructor.rs | 5 ++++ 2 files changed, 33 insertions(+) create mode 100644 tests/run-pass/tuple_like_struct_constructor.rs diff --git a/src/terminator/mod.rs b/src/terminator/mod.rs index 6959da650b42..1b5ff9da9d73 100644 --- a/src/terminator/mod.rs +++ b/src/terminator/mod.rs @@ -229,6 +229,34 @@ fn eval_fn_call( (def_id, substs, Vec::new()) }; + // FIXME(eddyb) Detect ADT constructors more efficiently. + if let Some(adt_def) = fn_ty.sig.skip_binder().output().ty_adt_def() { + if let Some(v) = adt_def.variants.iter().find(|v| resolved_def_id == v.did) { + // technically they can diverge, but only if one of their arguments diverges, so it doesn't matter + let (lvalue, target) = destination.expect("tuple struct constructors can't diverge"); + let dest_ty = self.tcx.item_type(adt_def.did); + let dest_layout = self.type_layout(dest_ty)?; + match *dest_layout { + Layout::Univariant { ref variant, .. } => { + assert_eq!(v.disr_val.to_u128_unchecked(), 0); + let offsets = variant.offsets.iter().map(|s| s.bytes()); + + // FIXME: don't allocate for single or dual field structs + let dest = self.force_allocation(lvalue)?.to_ptr(); + + for (offset, (value, value_ty)) in offsets.into_iter().zip(args) { + let field_dest = dest.offset(offset); + self.write_value_to_ptr(value, field_dest, value_ty)?; + } + }, + // FIXME: enum variant constructors + _ => bug!("bad layout for tuple struct constructor: {:?}", dest_layout), + } + self.goto_block(target); + return Ok(()); + } + } + let mir = self.load_mir(resolved_def_id)?; let (return_lvalue, return_to_block) = match destination { Some((lvalue, block)) => (lvalue, StackPopCleanup::Goto(block)), diff --git a/tests/run-pass/tuple_like_struct_constructor.rs b/tests/run-pass/tuple_like_struct_constructor.rs new file mode 100644 index 000000000000..05e8893de178 --- /dev/null +++ b/tests/run-pass/tuple_like_struct_constructor.rs @@ -0,0 +1,5 @@ +fn main() { + #[derive(PartialEq, Eq, Debug)] + struct A(i32); + assert_eq!(Some(42).map(A), Some(A(42))); +}