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

ability to opt out of auto-rolling of reflexive From #42861

Closed
dobkeratops opened this issue Jun 23, 2017 · 7 comments
Closed

ability to opt out of auto-rolling of reflexive From #42861

dobkeratops opened this issue Jun 23, 2017 · 7 comments

Comments

@dobkeratops
Copy link

dobkeratops commented Jun 23, 2017

In order to facilitate impl'ing From for collections/wrapped types, would it be possible to amend the library (within the existing language features) to allow the user to opt out of 'core's' generation of reflexive T:From<T>
this was my scenario,
https://www.reddit.com/r/rust/comments/6ieagx/from_generic_impl_conflict_vector_maths/

To summarise impl From<Vec3<B>> for Vec3<A> where A:From<B> seemed to clash with core's reflexive impl of 'From' (i.e. From<Vec3> for Vec2

my workaround was to manually impl for specific types but this is messy,

Do the "negative trait bounds" offer a solution? - e.g. could there be a NotReflexiveFrom helper-trait which when impld for a type (in my case, Vec3<T>) would suppress the library reflexive-from.

The reverse - an opt-in sounds easier r.e. the existing language features, but that would be a breaking library change, right?

I think the clearest solution to my situation would be a not equal type-bound e.g. where A!=B ?
impl From<Vec3<B>> for Vec3<A> where A:From<B>, A!=B
I tried to hack a manual A:IsNot<B> but once again I seemed to need to roll this for specific types so I was back to square one.

https://users.rust-lang.org/t/not-equal-type-bound-e-g-where-t-y/11442

Could an automatic A:IsNot<B> be done through a "procedural macro" ?

For reference, equivalent C++ situation - the behaviour I'm trying to get close to in Rust
Here is is possible using 'conversion operators' or constructors, because a type can respond to casting to itself automatically already, and you can go ahead and write a templated conversion.

template<typename T>
struct Vec3 {
	T x; T y; T z;
	Vec3(){}
    // component wise conversion between vectors of different types
	template<typename B>
	explicit Vec3(const Vec3<B>& src) :x(src.x),y(src.y),z(src.z){} 
};

int main(int argc, const char** argv){
   // try instantiating a vector, assignment, casting
	Vec3<int> v0; Vec3<short> v1; auto v2 = (Vec3<short>) v1;  auto v3= (Vec3<int>) v1;

I am ok with the fact rust conversions are 'explicit' by default ('write .into()' giving a clear point where conversions occur), but I still want to be able to request conversions between anything that makes sense (in this example, many possible formats of vector data)

@Mark-Simulacrum
Copy link
Member

I think what you really want is specialization, which is currently primarily waiting on Chalk; opting out of impls isn't quite what you want -- rather, you want to specialize core's impl for your types. As such, I'm going to go ahead and close -- see #31844 and rust-lang/rust-roadmap-2017#8.

@dobkeratops
Copy link
Author

dobkeratops commented Jun 23, 2017

Does the where A!=B idea have any merit; would it have utility in other situations ? - it's possible to roll things where 'A==B' by re-using a parameter , e.g. where A:Add .
I'll read about the other issue aswell, thanks.

@Mark-Simulacrum
Copy link
Member

A != B introduces problems IIRC; I don't recall what they are though. Feel free to ask on internals.rust-lang.org or users.rust-lang.org, though.

@Ixrec
Copy link
Contributor

Ixrec commented Jun 24, 2017

I'd guess the big problem is either contexts where you don't know yet if two type parameters are equal or unequal, or cases where you can't know if they will always stay equal/unequal after the library adds new impls or the app adds new call sites. But an A!=B bound on an impl should always be equivalent to adding a specializing impl for the A==B case (unless you don't want an impl to exist at all if A==B, which afaik is not something anyone ever wants), so I'd just focus on specialization.

@dobkeratops
Copy link
Author

dobkeratops commented Jun 29, 2017

A != B introduces problems IIRC; I don't recall what they are though.

hmmm , so it has been considered and found to be problematic ... are those problems 'permanent',or just potential opinions (e.g. library generality)
tangentially I also remembered sometimes it would seem nice to be able to access items of a tuple or union? .. Either https://hackage.haskell.org/package/base-4.9.1.0/docs/Data-Either.html) by the name of the types, e.g. imagine .get<FOO>(), .get<BAR>() accessors for an Either<A,B:B!=A> or whatever. I do find myself wanting this with tuple-structs (e.g. I find i'm using those because naming the elements can sometimes seem extraneous in the case where the type is enough to identify the contextual purpose); if it was possible to constrain A!=B, the idea of 'access by type' would make more sense (it should fail if A==B, right?)

@Mark-Simulacrum
Copy link
Member

Accessing from some structure by type "name" can be done with https://docs.rs/typemap/. I can't find anything on != right now, but if you ask on internals it's likely someone will be able to explain better than I can.

@dobkeratops
Copy link
Author

type map looks interesting, thanks , (i'm not sure i understand fully.. i'll have to check what UnsafeAny does) - but it's far more general than the case I had in mind which would be implementing a .get<A>() / .get<B>() for fixed size parameterised tuples/tuplestructs (i'm not even sure if thats possible.. maybe it's another thing Specailization will allow)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants