Open
Description
The problem here was previously documented as a drawback in rust-lang/rfcs#809 (with similar details provided in Appendix B).
Demonstration code:
#![feature(box_syntax)]
// NOTE: Scroll down to "START HERE"
fn main() { }
macro_rules! box_ {
($value:expr) => { {
let mut place = ::BoxPlace::make();
let raw_place = ::Place::pointer(&mut place);
let value = $value;
unsafe { ::std::ptr::write(raw_place, value); ::Boxed::fin(place) }
} }
}
pub trait BoxPlace<Data> : Place<Data> { fn make() -> Self; }
pub trait Place<Data: ?Sized> { fn pointer(&mut self) -> *mut Data; }
pub trait Boxed<CoercedFrom> { type Place; fn fin(filled: Self::Place) -> Self; }
struct BP<T: ?Sized> { _fake_box: Option<Box<T>> }
impl<T> BoxPlace<T> for BP<T> {
fn make() -> BP<T> { make_pl() }
}
impl<T: ?Sized> Place<T> for BP<T> {
fn pointer(&mut self) -> *mut T { pointer(self) }
}
impl<T> Boxed<T> for Box<T> {
type Place = BP<T>;
fn fin(x: BP<T>) -> Self { finaliz(x) }
}
fn make_pl<T>() -> BP<T> { loop { } }
fn finaliz<T: ?Sized, CoercedFrom>(mut _filled: BP<CoercedFrom>) -> Box<T> { loop { } }
fn pointer<T: ?Sized>(_p: &mut BP<T>) -> *mut T { loop { } }
// START HERE
trait D1 { fn duh() -> Self; }
trait D2 { fn duh() -> Self; }
trait D3 { fn duh() -> Self; }
trait D4 { fn duh() -> Self; }
trait D5 { fn duh() -> Self; }
trait D6 { fn duh() -> Self; }
trait D7 { fn duh() -> Self; }
// THIS WORKS TODAY (pre box desugaring).
impl<T> D1 for Box<[T]> { fn duh() -> Box<[T]> { box [] } }
// D2/D3/D4/D5 WORK TOMORROW (they accommodate the box desugaring).
impl<T> D2 for Box<[T]> {
fn duh() -> Box<[T]> { let b: Box<[_; 0]> = box_!( [] ); b }
}
impl<T> D3 for Box<[T]> {
fn duh() -> Box<[T]> { (|b| -> Box<[_; 0]> { b })(box_!( [] )) }
}
impl<T> D4 for Box<[T]> {
fn duh() -> Box<[T]> { (|b: Box<[_; 0]>| { b })(box_!( [] )) }
}
fn the<X>(x:X) -> X { x }
impl<T> D5 for Box<[T]> {
fn duh() -> Box<[T]> { the::<Box<[_; 0]>>(box_!( [] )) }
}
// BUT: D6 and D7 do not work.
impl<T> D6 for Box<[T]> { fn duh() -> Box<[T]> { box_!([]) } }
impl<T> D7 for Box<[T]> {
// fn duh() -> Box<[T]> { box_!( [] ) }
//
// desugars to:
fn duh() -> Box<[T]> {
let mut place = ::BoxPlace::make();
let raw_place = ::Place::pointer(&mut place);
let value = [];
unsafe { ::std::ptr::write(raw_place, value);
::Boxed::fin(place) }
}
}
The question posed by this issue is: Could we enhance the type inference and/or the design of this protocol so that, by tracking the sized-ness of the type unification variables, we could determine where coercions need to be inserted.