Skip to content

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

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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