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

Remove default bounds on ~ objects and procs #10296

Closed
nikomatsakis opened this issue Nov 5, 2013 · 10 comments
Closed

Remove default bounds on ~ objects and procs #10296

nikomatsakis opened this issue Nov 5, 2013 · 10 comments

Comments

@nikomatsakis
Copy link
Contributor

Today we do some amount of defaulting to cover two special cases:

~Trait =>  ~Trait:Send
proc   =>  proc:Send

This means that you must write ~Trait: and proc: to bypass these defaults.

I think we should consider removing these defaults and be consistent: no bounds means no bounds.

Arguments in favor of defaults:

  • Less typing for the common case of sendable ~Trait objects and proc

Arguments against:

  • We don't generally default other places in the language

  • proc:Send and ~Trait:Send read quite clearly to me

  • The fact that proc: is even an option is not obvious, leading people to the false conclusion that one cannot e.g. close over borrowed values in a proc

  • There are other use cases for ~Trait and proc that don't involve sending

  • Defaults are somewhat confusing in the face of DST. Consider these types:

    struct Foo<A> { x: ~A }
    struct Bar<A> { x: A }
    

    Wouldn't you think that Foo<Trait> and Bar<~Trait> should be equivalent?
    I would, but they're not.

@orenbenkiki
Copy link

First, +1. I find the current state pretty confusing, perhaps because proc isn't mentioned in the documentation at all. The following fails to compile (obviously):

fn call_once(action: proc() -> T) -> T {
    action()
}

fn consume_owned(_text: ~str) {}
fn used_borrowed(_text: &int) {}

fn lets_try(foo: &int, bar: ~str, baz: &mut_int) {
    mut int qux = 0;
    do call_once {
        used_borrowed(foo);
        consume_owned(bar);
        *baz += 1;
        qux += 1;
    }
}

I'm not sure what you mean by proc: - putting proc: instead of proc in the above doesn't compile. So how is it possible (today) to make the above work?

@pnkfelix
Copy link
Member

pnkfelix commented Nov 5, 2013

cc me

@emberian
Copy link
Member

emberian commented Nov 6, 2013

👍. I had no idea default bounds were a thing, or that ~SomeTrait: was valid syntax.

@alexcrichton
Copy link
Member

@pcwalton ran into something a little related yesterday. All of the runtime's I/O structures are wrappers around some ~Trait object. The idea of these is that they're all sendable across tasks (one can read while the other writes, etc). Specifically, though, the Freeze bound couldn't get inferred for those objects, and having to specify the Send bound everywhere would be a bit of a pain (although entirely plausible).

This may just be a reflection of the runtime's decision to use trait objects instead of generics, but it would make some use cases a little harder. That being said, I'd almost want to lean on the side of consistence and not have any funny bounds inferred for you when you didn't want them.

@nikomatsakis
Copy link
Contributor Author

@alexcrichton yes, some cases get more verbose. Are these many different traits or a single trait? In the latter case, you can certainly make a typedef as well:

trait Callback
type CB = ~Callback:Send;

@alexcrichton
Copy link
Member

Sadly there's a fair number of traits (all in std::rt::rtio), but I also just found out that you can do trait Foo: Send {}, so I don't think that this would be that bad at all (I'm in favor of removing the defaults).

@nikomatsakis
Copy link
Contributor Author

@alexcrichton I was about to suggest that (moving the bound to the trait itself)

@alexcrichton
Copy link
Member

We discussed this in today's meeting, and we decided that these default bounds should go.

@nikomatsakis
Copy link
Contributor Author

In #10553 it was pointed out that a Send bound should imply 'static, just something to keep in mind when implementing this.

@wycats
Copy link
Contributor

wycats commented Mar 8, 2014

Incidentally, this issue caused me a bunch of pain when I was trying to implement a generic trait over objects that contained references (In my case, Matcher<T>).

The error message didn't really explain what I was doing wrong, and there wasn't an easy way to opt out of the Send bound (even Matcher:<T> didn't seem to be possible in all the places I needed to reference the trait and opt-out). It's possible I missed something (an easy opt-out), but the current situation is pretty brittle and the error messages don't send you down the right path.

In any event, I agree that Send should not be the default here.

alexcrichton added a commit to alexcrichton/rust that referenced this issue Mar 12, 2014
This is needed to make progress on rust-lang#10296 as the default bounds will no longer
include Send. I believe that this was the originally intended syntax for procs,
and it just hasn't been necessary up until now.
bors added a commit that referenced this issue Mar 12, 2014

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
This is needed to make progress on #10296 as the default bounds will no longer
include Send. I believe that this was the originally intended syntax for procs,
and it just hasn't been necessary up until now.
bors added a commit that referenced this issue Mar 27, 2014
See #10296 for the rationale, and commits for the implementation.
Jarcho pushed a commit to Jarcho/rust that referenced this issue Feb 26, 2023
manual_let_else: let/else is not divergent by default

The divergent `else` block of a `let`/`else` statement does not make the `let/else` statement itself divergent.

Fixes rust-lang#10296

changelog: [`manual_let_else`]: do not consider `let`/`else` to be divergent by default
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

6 participants