Skip to content

Can't cast self to trait object in default methods #7320

Closed

Description

@Blei

The following code doesn't work (even though I suspect it's correct):

trait Foo {
    fn foo(@self) { bar(self); }
}

fn bar(_b: @Foo) { }

The following error is returned:

<anon>:2:24: 2:29 error: mismatched types: expected `@Foo` but found `@Self` (expected trait Foo but found @-ptr)
<anon>:2     fn foo(@self) { bar(self); }
                                 ^~~~~
error: aborting due to previous error

Activity

  1. Blei commented on Jun 26, 2013

    @Blei
    ContributorAuthor

    Related to (or duplicate of?) #7183

  2. pnkfelix commented on Jun 26, 2013

    @pnkfelix
    Contributor

    @Blei might be related, but I would not call it a duplicate; the type &S in fn<S:Trait>(s:&S) does not use dynamic dispatch (i.e. does not carry a virtual-method table) while @Trait in fn(x:@Trait) does.

    (as in, the use-cases for the two are so different, I'd want to ensure they are addressed, independently if necessary. Though maybe we will be lucky and they will end up having the same root cause.)

  3. pnkfelix commented on Jun 26, 2013

    @pnkfelix
    Contributor

    Regardless of whether this is a dupe of 7183, it is definitely part of #2794.

  4. msullivan commented on Jun 28, 2013

    @msullivan
    Contributor

    The code I think is not correct. It doesn't actually do a cast.

  5. msullivan commented on Jun 28, 2013

    @msullivan
    Contributor

    I feel like the code should be

    trait Foo {
        fn foo(@self) { bar(self as @Foo); }
    }
    
    fn bar(_b: @Foo) { }
    

    This fails with

    ../rust-things/default-self-object.rs:2:24: 2:36 error: cannot pack type `@Self`, which does not fulfill `'static`, as a trait bounded by 'static
    ../rust-things/default-self-object.rs:2     fn foo(@self) { bar(self as @Foo); }
    

    Hm.

  6. Blei commented on Jun 28, 2013

    @Blei
    ContributorAuthor

    Yes, I tried multiple variants, both with and without cast. I meant to paste the one with a cast, but alas.

  7. nikomatsakis commented on Jun 28, 2013

    @nikomatsakis
    Contributor

    Sully's error is legit, in the sense that the type system is operating as expected. The type Self may contain borrowed pointers, and the type @Foo is short for @Foo:'static, which says that the value does NOT contain borrowed pointers. The correct way to implement the example (which I think does not work yet) would be:

    trait Foo : 'static { ... }
    

    which would say that the trait Foo cannot be implemented except by types that do not contain borrowed pointers.

    If we added the rule that @ boxes cannot contain managed pointers, as we have discussed, it is plausible that we could then extend the type system to know that Self has the bound 'static in an @self method (or any method that contains an @Self parameter). I described such a scheme in this blog post about the Sized kind.

  8. pnkfelix commented on Aug 12, 2013

    @pnkfelix
    Contributor

    @nikomatsakis FYI, when I attempted this morning to replicate the issues I was having with syntax::visit @Visitor refactoring, I ran into this problem (I think). Or at least, I could not pass @self to helper methods from the default method implementations in visit.rs. (There are ways to work-around this, such as not using default methods.)

  9. flaper87 commented on Jan 29, 2014

    @flaper87
    Contributor

    The following example works:

    trait Foo {
        fn foo(&self) { bar(self); }
    }
    
    fn bar(_b: &Foo) { }
    
    fn main() {}
    

    Since @ is being deprecated in favor of Gc and Rc and the above example works, I think we can close this issue. @nikomatsakis @pnkfelix thoughts?

  10. huonw commented on Jan 29, 2014

    @huonw
    Contributor

    Does ~self and ~Foo work?

  11. flaper87 commented on Jan 29, 2014

    @flaper87
    Contributor
    trait Foo: Send {
        fn foo(~self) { bar(self as ~Foo); }
    }
    
    fn bar(_b: ~Foo) { }
    
    fn main() {}
    

    Yes, it works!

  12. flaper87 commented on Jan 29, 2014

    @flaper87
    Contributor

    Closing based on the above comments

  13. flaper87 commented on Jan 29, 2014

    @flaper87
    Contributor

    Reopening since the above example requires Send to be explicitly specified

  14. flaper87 commented on Jan 29, 2014

    @flaper87
    Contributor

    To be more specific. The same thing that happens here can be reproduced w/ ~Foo:

    trait Foo {
        fn foo(~self) { bar(self as ~Foo); }
    }
    
    fn bar(_b: ~Foo) { }
    
    fn main() {}
    
    test.rs:2:25: 2:32 error: cannot pack type `~Self`, which does not fulfill `Send`, as a trait bounded by Send
    test.rs:2     fn foo(~self) { bar(self as ~Foo); }
                                      ^~~~~~~
    error: aborting due to previous error
    
  15. huonw commented on Apr 26, 2014

    @huonw
    Contributor

    We no longer have the default bounds on ~ trait objects, but, in any case, the original code has worked for a while using ~Foo: to explicitly override the Send bound, i.e. this issue had been fixed. (The old ~Foo/new ~Foo:Send cast fails because Self isn't known to be Send in that context; if sendability is necessary, writing trait Foo: Send { ... } works).

    Flagging as needstest.

  16. added a commit that references this issue on Apr 28, 2014
    35f295d
  17. added a commit that references this issue on Apr 28, 2014
    7a19a82
  18. added a commit that references this issue on Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions