From dee35d97fd2208b7f0ae5f5aeb2cee071fb7bf3c Mon Sep 17 00:00:00 2001 From: ticki Date: Sun, 1 May 2016 10:33:16 +0200 Subject: [PATCH 1/3] `dyn` keyword --- text/0000-dyn-keyword.md | 76 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 text/0000-dyn-keyword.md diff --git a/text/0000-dyn-keyword.md b/text/0000-dyn-keyword.md new file mode 100644 index 00000000000..f9b3a9b44bf --- /dev/null +++ b/text/0000-dyn-keyword.md @@ -0,0 +1,76 @@ +- Feature Name: dyn-keyword +- Start Date: 2016-05-01 +- RFC PR: (leave this empty) +- Rust Issue: (leave this empty) + +# Summary +[summary]: #summary + +Introduce a keyword, `dyn`, for denoting dynamic dispatch, with the motivation +of avoid "accidental overhead" and making the costs more explicit, along with +deprecation of the old syntax. + +# Motivation +[motivation]: #motivation + +The current syntax for dynamic dispatch, making use of traits as unsized types, +does not align very well with the Rust philosophy for two reasons: + +1. It hides the overhead: One would think that `Box` simply carried the + overhead of the allocation and indirection, but, in fact, the major overhead + stems from dynamic dispatch. This expense is rather implicit, in that there + is denotation nor sigil to signify this overhead. +2. It is prone to subtle mistakes and unnecessary dynamic dispatch due to + `Trait` appearing like a unsized type. + +Furthermore, it is worth noting that `Trait` is not a type, despite it may seem +so. + +# Detailed design +[design]: #detailed-design + +To overcome these hurdles, we introduce a new syntax: `dyn Trait`. + +`dyn Trait` is an unsized type, which is the dynamically dispatched form of +`Trait`. Two things are essential to the semantics: + +1. `∀T.[dyn T]∊T`: namely that `dyn Trait` satisfy the bound `: Trait`. +2. `∀t∊T.[c (dyn T) <: c t]`: meaning that `T` where `T: Trait` can coerce into + `dyn Trait`. This rule is similar to the current trait object coercion rule. + +It is worth mentioning that `dyn` is not, and can not be, a type constructor. +Traits are classes of types, not types them self. + +Secondly, we add a deprecation lint against the current syntax, where traits +are treated like types. + +# Examples + +```rust +let vec: Box = box 4; +``` + +will now be + +```rust +let vec: Box = box 4; +``` + +# Drawbacks +[drawbacks]: #drawbacks + +This won't cause breakage, but deprecation is certainly a drawback. + +# Alternatives +[alternatives]: #alternatives + +## Have a "magic" type constructor, `Object`. + +Acting as a dynamic dispatcher for `Trait`. + +## Leave it as is. + +# Unresolved questions +[unresolved]: #unresolved-questions + +None. From 7d976ce824958e105e5337be3992b9ff47151d60 Mon Sep 17 00:00:00 2001 From: ticki Date: Sun, 1 May 2016 10:50:25 +0200 Subject: [PATCH 2/3] Add note on parsing --- text/0000-dyn-keyword.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/text/0000-dyn-keyword.md b/text/0000-dyn-keyword.md index f9b3a9b44bf..1ac242a5de9 100644 --- a/text/0000-dyn-keyword.md +++ b/text/0000-dyn-keyword.md @@ -44,6 +44,8 @@ Traits are classes of types, not types them self. Secondly, we add a deprecation lint against the current syntax, where traits are treated like types. +The parsing is done in a context-specific manner (alike #1444 and #243). + # Examples ```rust From 39768382aae585bb566f05d164e7ca1ef13b3837 Mon Sep 17 00:00:00 2001 From: ticki Date: Fri, 1 Jul 2016 20:31:52 +0200 Subject: [PATCH 3/3] Update with extensional motivation --- text/0000-dyn-keyword.md | 91 +++++++++++++++++++++++++++++++++------- 1 file changed, 77 insertions(+), 14 deletions(-) diff --git a/text/0000-dyn-keyword.md b/text/0000-dyn-keyword.md index 1ac242a5de9..c14d6126a34 100644 --- a/text/0000-dyn-keyword.md +++ b/text/0000-dyn-keyword.md @@ -14,17 +14,82 @@ deprecation of the old syntax. [motivation]: #motivation The current syntax for dynamic dispatch, making use of traits as unsized types, -does not align very well with the Rust philosophy for two reasons: +does not align very well with the Rust philosophy for multiple reasons: -1. It hides the overhead: One would think that `Box` simply carried the - overhead of the allocation and indirection, but, in fact, the major overhead - stems from dynamic dispatch. This expense is rather implicit, in that there - is denotation nor sigil to signify this overhead. -2. It is prone to subtle mistakes and unnecessary dynamic dispatch due to - `Trait` appearing like a unsized type. +## Hidden overhead -Furthermore, it is worth noting that `Trait` is not a type, despite it may seem -so. +The current syntax hides the overhead: One would think that `Box` simply +carried the overhead of the allocation and indirection, but, in fact, the major +overhead stems from dynamic dispatch. This expense is rather implicit, in that +there is denotation nor sigil to signify this overhead. + +Dynamic dispatch is not bad per se, but the user must carefully evaluate the +choice. + +## Reducing mistakes + +It is prone to subtle mistakes and unnecessary dynamic dispatch due to +`Trait` appearing like a unsized type. + +At first, it might not be obvious that `&Num` fundamentally behaves differently +from, say, `&u32`. + +## Obviousness + +Between new beginners, there are often questions and confusions about trait +objects and their syntax. A common misconception is that traits are types, +which is directly implied by the current syntax. + +## Grep-ability + +Being able to grep for some string in large codebases is critical to +maintainability. As it stands now, one cannot search for dynamically dispatched +types. + +## `impl` syntax + +Abstract unboxed types are, in a sense, "simpler" than dynamically dispatched +types. Thus, concerns have been raised about syntactically favoring dynamically +dispatched types over abstract unboxed return types. + +One cannot use the syntax, `-> Trait`, for these, due to collision with the +trait object syntax, in a consistent manner. Using `dyn` allows this syntax to +stand free. + +## Non-locality + +An important property well-designed language features must hold is the ability +to reason locally. With the current syntax, one needs non-local information for +determining its behavior. + +## Formal correctness + +`Trait` is, type theoretically speaking, not a type. It might seem so because +they share same syntax. In particular, every dynamically dispatchable trait has +a sister type representing its dynamic counterpart. + +This is rather confusing, since it is not obvious at first, that the meaning +depends on the context. + +## Self-documenting + +Adding `dyn` makes it largely self-documenting. + +## Function pointers + +The difference between + +```rust +&Fn(A) -> B +``` + +and + +```rust +fn(A) -> B +``` + +is a subtle one, despite there being a 10-20% performance improvement. # Detailed design [design]: #detailed-design @@ -32,11 +97,7 @@ so. To overcome these hurdles, we introduce a new syntax: `dyn Trait`. `dyn Trait` is an unsized type, which is the dynamically dispatched form of -`Trait`. Two things are essential to the semantics: - -1. `∀T.[dyn T]∊T`: namely that `dyn Trait` satisfy the bound `: Trait`. -2. `∀t∊T.[c (dyn T) <: c t]`: meaning that `T` where `T: Trait` can coerce into - `dyn Trait`. This rule is similar to the current trait object coercion rule. +`Trait`. It is worth mentioning that `dyn` is not, and can not be, a type constructor. Traits are classes of types, not types them self. @@ -63,6 +124,8 @@ let vec: Box = box 4; This won't cause breakage, but deprecation is certainly a drawback. +Concerns have been raised about `&dyn` looking like a seperate pointer. + # Alternatives [alternatives]: #alternatives