Uh oh!
There was an error while loading. Please reload this page.
Add associated types support for #[derive(...)] - #21237
Conversation
rust-highfive
commented
Jan 16, 2015
(rust_highfive has picked a reviewer for you, use r? to override) |
a861370 to
46a221eCompareerickt
commented
Jan 16, 2015
Unfortunately this can't land quite yet. It turns out the visibility checker reports that this is exposing a private type: structFoo<T>(T);impl<T>CloneforFoo<T>whereT:Clone{ ... }pubstructBar<T>(Foo<T>);impl<T>CloneforBar<T>whereFoo<T>:Clone{ ... }@nikomatsakis said in #21203 (comment) that the privacy rules are being too strict here and might need to be relaxed. |
alexcrichton
commented
Jan 16, 2015
r? @huonw - you're more familiar with |
nikomatsakis
commented
Jan 16, 2015
I'm not so sure about the privacy thing anymore. |
There was a problem hiding this comment.
I suspect this should check that path.segments has length 1, or maybe the shadowing rules means it doesn't matter? (i.e. is struct Foo<std> { x: std::option::Option<u8> } legal?)
There was a problem hiding this comment.
Drat, you're right, this currently compiles:
modT{pubtypeType = i32;}traitTrait{typeType;}structBaz<T:Trait>{a:T::Type,}I filed #21301 to get that fixed. It'll probably not be that much of an issue in practice though, as you'd have to be crazy to write that :)
huonw
commented
Feb 1, 2015
@erickt what's the status of this? Is
still true? |
erickt
commented
Feb 3, 2015
@huonw: Ack! I was on a business trip this past week and forgot all about wrapping up this PR. I'll try to get it done this week :) |
46a221e to
85ba662Compareerickt
commented
Feb 5, 2015
@huonw: Should work now, and it passes locally. re-r? |
85ba662 to
6311d3bCompareerickt
commented
Feb 7, 2015
huonw
commented
Feb 8, 2015
This approach is definitely an improvement, but it doesn't solve #7671 completely, e.g. #[derive(Debug)]// T: Debug is not insertedstructFoo<T>;#[derive(Debug)]// T: Debug is inserted, but T is still phantomstructBar<T>{x:Foo<T>}Also, I think this may "break" the standard library marker types like That said, I'm not sure that it is necessary to have these restricted implementions. |
goffrie
commented
Feb 8, 2015
I suspect it's not worth trying to solve the general case of #7671. The privacy thing is a real kicker - if a public type |
erickt
commented
Feb 8, 2015
erickt
commented
Feb 9, 2015
After talking to @huonw, I feel like there isn't a great solution that works for phantom/marker types at the same time as working for an edge case of associated types. Say we extend @huonw's phantom type example from before, this time adding an associated type that's not using the trait type: #[derive(Debug)]structFoo<T>;#[derive(Debug)]structBar<T>(Foo<T>);traitTrait{typeType;}#[derive(Debug)]structBaz<T:Trait>(T::Type);We can either generate an impl that constrains all the type parameters, which is our current approach: structFoo<T>;impl<T>DebugforFoo<T>whereT:Debug{ ... }structBar<T>(Foo<T>);impl<T>DebugforBar<T>whereT:Debug{ ... }traitTrait{typeType;}structBaz<T:Trait>(T::Type);impl<T>DebugforBaz<T>whereT:Debug,T::Type:Debug{ ... }Notice that the impl for structFoo<T>;impl<T>DebugforFoo<T>{ ... }structBar<T>(Foo<T>);impl<T>DebugforBar<T>whereT:Debug{ ... }traitTrait{typeType;}structBaz<T:Trait>(T::Type);impl<T>DebugforBaz<T>whereT::Type:Debug{ ... }Notice that for Does anyone have an opinion on which approach to use, or if there are some good heuristics here to decide what to do here? |
There was a problem hiding this comment.
Hm, this will pick up non-generic QPath's too, right? e.g. struct Foo(<Bar as Iterator>::Item);.
(I guess these come up rarely enough that it probably doesn't matter?)
There was a problem hiding this comment.
I'll add a pass through the QPath that checks if it references any of the type parameters. If it does, I'll add it to the types to be constrained. If not, i'll skip it. That should protect against this case.
erickt
commented
Mar 14, 2015
Took a while, but I finally updated the patch to compile on head and address @goffrie's comment. |
There was a problem hiding this comment.
can this be written as
let field_tys = enum_def.variants.flat_map(|variant| {match variant.node.kind{
ast::VariantKind::TupleVariantKind(ref args) => {
args.iter().map(|arg| arg.ty.clone())}
ast::VariantKind::StructVariantKind(ref args) => {
args.fields.iter().map(|field| field.node.ty.clone())}}}).collect();❓
There was a problem hiding this comment.
@tamird: Unfortunately it cannot because those inner iterators are actually two different types.
erickt
commented
Mar 19, 2015
@bors: r+ edb33f2 |
bors
commented
Mar 19, 2015
⌛ Testing commit edb33f2 with merge e989552... |
bors
commented
Mar 19, 2015
💔 Test failed - auto-mac-64-opt |
Manishearth
commented
Mar 20, 2015
|
bors
commented
Mar 24, 2015
⌛ Testing commit 7971f39 with merge 4c3f968... |
bors
commented
Mar 24, 2015
💔 Test failed - auto-linux-64-x-android-t |
erickt
commented
Mar 24, 2015
@bors: retry |
erickt
commented
Mar 25, 2015
@bors: r+ rollup |
bors
commented
Mar 25, 2015
📌 Commit 9cabe27 has been approved by |
bors
commented
Mar 25, 2015
⌛ Testing commit 9cabe27 with merge 72d0695... |
bors
commented
Mar 25, 2015
💔 Test failed - auto-win-32-opt |
erickt
commented
Mar 25, 2015
@bors: retry |
This PR adds support for associated types to the `#[derive(...)]` syntax extension. In order to do this, it switches over to using where predicates to apply the type constraints. So now this:
```rust
type Trait {
type Type;
}
#[derive(Clone)]
struct Foo<A> where A: Trait {
a: A,
b: <A as Trait>::Type,
}
```
Gets expended into this impl:
```rust
impl<A: Clone> Clone for Foo<A> where
A: Trait,
<A as Trait>::Type: Clone,
{
fn clone(&self) -> Foo<T> {
Foo {
a: self.a.clone(),
b: self.b.clone(),
}
}
}
```This PR adds support for associated types to the `#[derive(...)]` syntax extension. In order to do this, it switches over to using where predicates to apply the type constraints. So now this:
```rust
type Trait {
type Type;
}
#[derive(Clone)]
struct Foo<A> where A: Trait {
a: A,
b: <A as Trait>::Type,
}
```
Gets expended into this impl:
```rust
impl<A: Clone> Clone for Foo<A> where
A: Trait,
<A as Trait>::Type: Clone,
{
fn clone(&self) -> Foo<T> {
Foo {
a: self.a.clone(),
b: self.b.clone(),
}
}
}
```This PR adds support for associated types to the `#[derive(...)]` syntax extension. In order to do this, it switches over to using where predicates to apply the type constraints. So now this:
```rust
type Trait {
type Type;
}
#[derive(Clone)]
struct Foo<A> where A: Trait {
a: A,
b: <A as Trait>::Type,
}
```
Gets expended into this impl:
```rust
impl<A: Clone> Clone for Foo<A> where
A: Trait,
<A as Trait>::Type: Clone,
{
fn clone(&self) -> Foo<T> {
Foo {
a: self.a.clone(),
b: self.b.clone(),
}
}
}
```bors
commented
Mar 26, 2015
This PR adds support for associated types to the `#[derive(...)]` syntax extension. In order to do this, it switches over to using where predicates to apply the type constraints. So now this:
```rust
type Trait {
type Type;
}
#[derive(Clone)]
struct Foo<A> where A: Trait {
a: A,
b: <A as Trait>::Type,
}
```
Gets expended into this impl:
```rust
impl<A: Clone> Clone for Foo<A> where
A: Trait,
<A as Trait>::Type: Clone,
{
fn clone(&self) -> Foo<T> {
Foo {
a: self.a.clone(),
b: self.b.clone(),
}
}
}
```bors
commented
Mar 26, 2015
derive applies the necessary trait bounds to derived impl. see rust-lang/rust#21237 for more details
435: derive Eq for other core geo types r=frewsxcv a=michaelkirk Adds `Eq` conformance to other core geo types, building off of #431 > Seems reasonable to me! Yeah +1 to adding the same impl for all the other core geo types Rather than spelling out the impl, I've taken advantage of how `derive` already bounds the generated impl for us. See rust-lang/rust#21237 for more details I wrote a few doc-tests while developing, but I reverted them in fc33f9f since they're pretty verbose, and seem superfluous since they're only asserting rust language semantics rather than anything substantial in this lib. I can un-revert them if you'd prefer. Co-authored-by: Michael Kirk <michael.code@endoftheworl.de>
jendrikw
commented
Jul 18, 2022
I think this is badly documented. A few sentences at https://doc.rust-lang.org/std/clone/trait.Clone.html#derivable would be nice. |
This PR adds support for associated types to the
#[derive(...)]syntax extension. In order to do this, it switches over to using where predicates to apply the type constraints. So now this:Gets expended into this impl: