Skip to content

Commit e4b23b8

Browse files
committed
allow the use of tuple struct constructors as functions
1 parent 0a79304 commit e4b23b8

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

src/terminator/mod.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,34 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
229229
(def_id, substs, Vec::new())
230230
};
231231

232+
// FIXME(eddyb) Detect ADT constructors more efficiently.
233+
if let Some(adt_def) = fn_ty.sig.skip_binder().output().ty_adt_def() {
234+
if let Some(v) = adt_def.variants.iter().find(|v| resolved_def_id == v.did) {
235+
// technically they can diverge, but only if one of their arguments diverges, so it doesn't matter
236+
let (lvalue, target) = destination.expect("tuple struct constructors can't diverge");
237+
let dest_ty = self.tcx.item_type(adt_def.did);
238+
let dest_layout = self.type_layout(dest_ty)?;
239+
match *dest_layout {
240+
Layout::Univariant { ref variant, .. } => {
241+
assert_eq!(v.disr_val.to_u64_unchecked(), 0);
242+
let offsets = variant.offsets.iter().map(|s| s.bytes());
243+
244+
// FIXME: don't allocate for single or dual field structs
245+
let dest = self.force_allocation(lvalue)?.to_ptr();
246+
247+
for (offset, (value, value_ty)) in offsets.into_iter().zip(args) {
248+
let field_dest = dest.offset(offset);
249+
self.write_value_to_ptr(value, field_dest, value_ty)?;
250+
}
251+
},
252+
// FIXME: enum variant constructors
253+
_ => bug!("bad layout for tuple struct constructor: {:?}", dest_layout),
254+
}
255+
self.goto_block(target);
256+
return Ok(());
257+
}
258+
}
259+
232260
let mir = self.load_mir(resolved_def_id)?;
233261
let (return_lvalue, return_to_block) = match destination {
234262
Some((lvalue, block)) => (lvalue, StackPopCleanup::Goto(block)),
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
fn main() {
2+
#[derive(PartialEq, Eq, Debug)]
3+
struct A(i32);
4+
assert_eq!(Some(42).map(A), Some(A(42)));
5+
}

0 commit comments

Comments
 (0)