Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move the 'static bound of Any to the methods. #2280

Closed
crlf0710 opened this issue Jan 6, 2018 · 6 comments
Closed

Move the 'static bound of Any to the methods. #2280

crlf0710 opened this issue Jan 6, 2018 · 6 comments
Labels
breaking-change The RFC proposes a breaking change. T-libs-api Relevant to the library API team, which will review and decide on the RFC.

Comments

@crlf0710
Copy link
Member

crlf0710 commented Jan 6, 2018

In principle the trait Any works just like a 'top type' trait. However there's the unnecessary bound of 'static involved by the restrictions of downcast method. So i propose that the 'static bound move to the methods, so Any can act as a real 'top type' trait.

Use case: When i want to erase the type of a value and just make sure it is alive until a certain point, currently there's no good way to do so. However, with the changes above, i can just put it into a Box<Any + 'a>.

@Centril Centril added the T-libs-api Relevant to the library API team, which will review and decide on the RFC. label Jan 6, 2018
@sfackler
Copy link
Member

sfackler commented Jan 6, 2018

This is a breaking change.

@burdges
Copy link

burdges commented Jan 6, 2018

I think anything like this requires ATC tricks according to #1849

@ExpHP
Copy link

ExpHP commented Jan 7, 2018

Use case: When i want to erase the type of a value and just make sure it is alive until a certain point, currently there's no good way to do so. However, with the changes above, i can just put it into a Box<Any + 'a>.

Is there anything wrong with the two line replacement

pub trait MyAny { }
impl<T: ?Sized> MyAny for T { }

(I mean, other than the obvious it's not in the standard lib?)

@crlf0710
Copy link
Member Author

crlf0710 commented Jan 7, 2018

@ExpHP yes, it's enough for the use case. However for it to act as a 'top type' here, if there're more ?Trait coming up, i guess the impl has to be changed to pick up all of those negative reasoning bounds. I don't think it can be well maintained within user land, since different rustc version might have a different list...

@KamilaBorowska
Copy link
Contributor

KamilaBorowska commented May 14, 2019

This would help with Error trait. While Any cannot be feasibly changed (it would be a breaking change), there is an option of deprecating Any and creating a new trait. With a hypothetical name of Unknown (although I'm pretty sure there is a better name, maybe referring to RTTI provided by a trait), there could be an implementation like this.

use std::any::TypeId;
use std::fmt;

pub trait Unknown {
    fn type_id(&self) -> TypeId
    where
        Self: 'static;
}

impl<T: ?Sized> Unknown for T {
    fn type_id(&self) -> TypeId
    where
        T: 'static,
    {
        TypeId::of::<T>()
    }
}

macro_rules! imp {
    ($bound:ty) => {
        // Not providing `+ '_` to possibly allow TypeId debug information
        impl fmt::Debug for $bound {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                f.pad("Unknown")
            }
        }
        
        impl $bound {
            pub fn is<T: 'static>(&self) -> bool {
                let t = TypeId::of::<T>();
                let concrete = self.type_id();
                t == concrete
            }
        
            pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
                if self.is::<T>() {
                    unsafe { Some(&*(self as *const dyn Unknown as *const T)) }
                } else {
                    None
                }
            }
        
            pub fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T> {
                if self.is::<T>() {
                    unsafe { Some(&mut *(self as *mut dyn Unknown as *mut T)) }
                } else {
                    None
                }
            }
        }
    };
}

imp!(dyn Unknown);
imp!(dyn Unknown + Send);
imp!(dyn Unknown + Send + Sync);

@dtolnay
Copy link
Member

dtolnay commented Sep 20, 2023

Let's continue this in the form of an API Change Proposal in https://github.com/rust-lang/libs-team if someone is up for owning a concrete proposed path forward.

@dtolnay dtolnay closed this as completed Sep 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking-change The RFC proposes a breaking change. T-libs-api Relevant to the library API team, which will review and decide on the RFC.
Projects
None yet
Development

No branches or pull requests

7 participants