Skip to content

Could type inference insert coercions to accommodate box desugaring? #22405

Open
@pnkfelix

Description

@pnkfelix

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-inferenceArea: Type inferenceA-type-systemArea: Type systemC-feature-requestCategory: A feature request, i.e: not implemented / a PR.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions