Just because Any is a trait doesn't mean it doesn't break parametricity.
Look at this:

http://static.rust-lang.org/doc/master/src/std/home/rustbuild/src/rust-buildbot/slave/doc/build/src/libstd/any.rs.html#37-63

Because we have `impl<T: 'static> Any for T`, it can be used with *any
type* (except borrowed data), including type parameters, whether or not
they declare the `T: Any` bound explicitly (which is essentially redundant
in this situation).

The proper thing would be for the compiler to generate an `impl Any for
MyType` for each individual type separately, rather than a single generic
impl which is valid for all types.

I also think we should guarantee parametricity for safe code and make
`size_of` an unsafe fn. Its legitimate uses in unsafe code (e.g. smart
pointers) are well encapsulated and don't expose parametricity violations,
and I don't believe safe code has a legitimate reason to use it (does it?).


On Sun, Feb 2, 2014 at 3:27 AM, Eric Reed <[email protected]> wrote:

> I'm going to respond to Any and size_of separately because there's a
> significant difference IMO.
>
> It's true that Any and trait bounds on type parameters in general can let
> function behavior depend on the passed type, but only in the specific
> behavior defined by the trait. Everything that's not a trait function is
> still independent of the passed type (contrast this with a setup where this
> wasn't true. `fn foo<A>() -> int' could return 2i for int and spin up a
> tetris game then crash for uint). Any just happens to be powerful enough to
> allow complete variance, which is expected since it's just dynamic typing,
> but there's an important distinction still: behavior variance because of
> Any *is* part of the function because you need to do explicit type tests.
>
> I wasn't aware of mem::size_of before, but I'm rather annoyed to find out
> we've started adding bare A -> B functions since it breaks parametricity.
> I'd much rather put size_of in a trait, at which point it's just a weaker
> version of Any.
> Being able to tell how a function's behavior might vary just from the type
> signature is a very nice property, and I'd like Rust to keep it.
>
> Now, onto monomorphization.
> I agree that distinguishing static and dynamic dispatch is important for
> performance characterization, but static dispatch != monomorphization (or
> if it currently does, then it probably shouldn't) because not all
> statically dispatched code needs to be monomorphizied. Consider a function
> like this:
>
> fn foo<A, B>(ox: Option<~A>, f: |~A| -> ~B) -> Option<~B> {
>     match ox {
>         Some(x) => Some(f(x)),
>         None => None,
>     }
> }
>
> It's quite generic, but AFAIK there's no need to monomorphize it for
> static dispatch. It uses a constant amount of stack space (not counting
> what `f' uses when called) and could run the exact same code for any types
> A or B (check discriminant, potentially call a function pointer, and
> return). I would guess most cases require monomorphization, but I consider
> universal monomorphization a way of implementing static dispatch (as
> opposed to partial monomorphization).
> I agree that understanding monomorphization is important for understanding
> the performance characteristics of code generated by *rustc*, but rustc !=
> Rust.
> Unless universal monomorphization for static dispatch makes its way into
> the Rust language spec, I'm going to consider it an implementation detail
> for rustc.
>
>
>
> On Sat, Feb 1, 2014 at 3:31 PM, Corey Richardson <[email protected]> wrote:
>
>> On Sat, Feb 1, 2014 at 6:24 PM, Eric Reed <[email protected]>
>> wrote:
>> > Responses inlined.
>> >
>> >>
>> >> Hey all,
>> >>
>> >> bjz and I have worked out a nice proposal[0] for a slight syntax
>> >> change, reproduced here. It is a breaking change to the syntax, but it
>> >> is one that I think brings many benefits.
>> >>
>> >> Summary
>> >> =======
>> >>
>> >> Change the following syntax:
>> >>
>> >> ```
>> >> struct Foo<T, U> { ... }
>> >> impl<T, U> Trait<T> for Foo<T, U> { ... }
>> >> fn foo<T, U>(...) { ... }
>> >> ```
>> >>
>> >> to:
>> >>
>> >> ```
>> >> forall<T, U> struct Foo { ... }
>> >> forall<T, U> impl Trait<T> for Foo<T, U> { ... }
>> >> forall<T, U> fn foo(...) { ... }
>> >> ```
>> >>
>> >> The Problem
>> >> ===========
>> >>
>> >> The immediate, and most pragmatic, problem is that in today's Rust one
>> >> cannot
>> >> easily search for implementations of a trait. Why? `grep 'impl Clone'`
>> is
>> >> itself not sufficient, since many types have parametric polymorphism.
>> Now
>> >> I
>> >> need to come up with some sort of regex that can handle this. An easy
>> >> first-attempt is `grep 'impl(<.*?>)? Clone'` but that is quite
>> >> inconvenient to
>> >> type and remember. (Here I ignore the issue of tooling, as I do not
>> find
>> >> the
>> >> argument of "But a tool can do it!" valid in language design.)
>> >
>> >
>> > I think what I've done in the past was just `grep impl | grep Clone'.
>> >
>> >>
>> >> A deeper, more pedagogical problem, is the mismatch between how `struct
>> >> Foo<...> { ... }` is read and how it is actually treated. The
>> >> straightforward,
>> >> left-to-right reading says "There is a struct Foo which, given the
>> types
>> >> ...
>> >> has the members ...". This might lead one to believe that `Foo` is a
>> >> single
>> >> type, but it is not. `Foo<int>` (that is, type `Foo` instantiated with
>> >> type
>> >> `int`) is not the same type as `Foo<unit>` (that is, type `Foo`
>> >> instantiated
>> >> with type `uint`). Of course, with a small amount of experience or a
>> very
>> >> simple explanation, that becomes obvious.
>> >
>> >
>> > I strongly disagree with this reasoning.
>> > There IS only one type Foo. It's a type constructor with kind * -> *
>> (where
>> > * means proper type).
>> > Foo<int> and Foo<uint> are two different applications of Foo and are
>> proper
>> > types (i.e. *) because Foo is * -> * and both int and uint are *.
>> > Regarding people confusing Foo, Foo<int> and Foo<uint>, I think the
>> proposed
>> > forall<T> struct Foo {...} syntax is actually more confusing.
>> > With the current syntax, it's never legal to write Foo without type
>> > parameters, but with the proposed syntax it would be.
>> >
>>
>> I've yet to see a proposal for HKT, but with them that interpretation
>> would be valid and indeed make this proposal's argument weaker.
>>
>> >>
>> >> Something less obvious is the treatment of functions. What does `fn
>> >> foo<...>(...) { ... }` say? "There is a function foo which, given types
>> >> ...
>> >> and arguments ..., does the following computation: ..." is not very
>> >> adequate.
>> >> It leads one to believe there is a *single* function `foo`, whereas
>> there
>> >> is
>> >> actually a single `foo` for every substitution of type parameters! This
>> >> also
>> >> holds for implementations (both of traits and of inherent methods).
>> >
>> >
>> > Again, I strongly disagree here.
>> > There IS only one function foo. Some of it's arguments are types. foo's
>> > behavior *does not change* based on the type parameters because of
>> > parametricity.
>> > That the compiler monomporphizes generic functions is just an
>> implementation
>> > detail and doesn't change the semantics of the function.
>> >
>>
>> It can if it uses Any, size_of, etc. eddyb had "integers in the
>> typesystem" by using size_of and [u8, ..N]. Anything using the
>> "properties" of types or the tydescs *will* change for each
>> instantiation.
>>
>> >>
>> >> Another minor problem is that nicely formatting long lists of type
>> >> parameters
>> >> or type parameters with many bounds is difficult.
>> >
>> >
>> > I'm not sure how this proposal would address this problem. All of your
>> > proposed examples are longer than the current syntax equivalents.
>> >
>>
>> The idea is there is an obvious place to insert a newline (after the
>> forall), though bjz would have to comment more on that.
>>
>
>
> _______________________________________________
> Rust-dev mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/rust-dev
>
>
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to