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

opt-in built-in bounds traits RFC tracker (optin_builtin_traits) #13231

Open
flaper87 opened this Issue Mar 31, 2014 · 21 comments

Comments

@flaper87
Contributor

flaper87 commented Mar 31, 2014

Checklist

Here is a check-list of code to write and tricky scenarios to be sure we handle:

  • forbid conditional negative impls as described here
  • conditional negative impls not properly enforced #23072
  • impl !Pod for .. should not be legal #28475
  • fix feature-gate for impl Foo for .. #23225
  • defaulted traits ought to be have more restrictive coherence rules #22978
  • defaulted traits should have no methods #23080 / #23117
  • Add parser support for impl Foo for ..
  • Port Send/Sync to use new infrastructure internally
  • Add unsafe impl Send for .. / unsafe impl Sync for ..
  • Object types should never match against a defaulted trait (though the object type itself may add a candidate for traits that appear in the object type)
  • When a defaulted trait matches, it should impose any supertrait bounds on the matched type as nested obligations
  • Be wary of type inference -- if we haven't resolved a type yet, we have to be ambiguous
  • Systematic testing for constituent_types
  • Coherence interaction: a defaulted trait can only be implemented for structs/enums
  • Coherence interaction: a trait can only be defaulted in the crate where it is defined
  • Coherence interaction: a trait can only be defaulted once
  • Defaulted impls cannot be generic
  • Fix the interaction with PhantomData. OIBIT should treat PhantomData as if there were an instance of T reachable rather than breaking it down like it would a different struct. #23091
  • Allow negative implementations for traits that have a default implementation (besides Send/Sync).

Original text

This is a tracking issue for the approved RFC opt-in-builtin-traits

Nominating

@flaper87 flaper87 self-assigned this Mar 31, 2014

@flaper87 flaper87 changed the title from opt-in built-in trait bounds RFC tracker to opt-in built-in bounds traits RFC tracker Mar 31, 2014

@pnkfelix

This comment has been minimized.

Member

pnkfelix commented Apr 3, 2014

Marking 1.0, P-backcompat-lang.

@pnkfelix pnkfelix added this to the 1.0 milestone Apr 3, 2014

@nikomatsakis

This comment has been minimized.

Contributor

nikomatsakis commented Apr 15, 2014

cc me

@flaper87

This comment has been minimized.

Contributor

flaper87 commented Apr 22, 2014

I'm actively working on this. Unfortunately, I've moved quite slowly because of other bugs I had to fix. I hope to be able to submit a PR this week.

flaper87 added a commit to flaper87/rust that referenced this issue Apr 28, 2014

flaper87 added a commit to flaper87/rust that referenced this issue Apr 28, 2014

flaper87 added a commit to flaper87/rust that referenced this issue Apr 28, 2014

Lookup trait implementations for type
This commit adds a function in vtable to find the vtables for a trait
implementation on a type.

cc rust-lang#13231

flaper87 added a commit to flaper87/rust that referenced this issue Apr 28, 2014

Add a bounds visitor
The bounds visitor checks looks for built-in traits implementations and
verifies that the type fulfills such trait.

cc rust-lang#13231

flaper87 added a commit to flaper87/rust that referenced this issue Apr 29, 2014

flaper87 added a commit to flaper87/rust that referenced this issue Apr 29, 2014

flaper87 added a commit to flaper87/rust that referenced this issue Apr 29, 2014

flaper87 added a commit to flaper87/rust that referenced this issue Apr 29, 2014

flaper87 added a commit to flaper87/rust that referenced this issue Apr 29, 2014

Lookup trait implementations for type
This commit adds a function in vtable to find the vtables for a trait
implementation on a type.

cc rust-lang#13231

flaper87 added a commit to flaper87/rust that referenced this issue Apr 29, 2014

Add a bounds visitor
The bounds visitor checks looks for built-in traits implementations and
verifies that the type fulfills such trait.

cc rust-lang#13231

flaper87 added a commit to flaper87/rust that referenced this issue Apr 30, 2014

flaper87 added a commit to flaper87/rust that referenced this issue Apr 30, 2014

flaper87 added a commit to flaper87/rust that referenced this issue Apr 30, 2014

flaper87 added a commit to flaper87/rust that referenced this issue Apr 30, 2014

flaper87 added a commit to flaper87/rust that referenced this issue Apr 30, 2014

@nikomatsakis

This comment has been minimized.

Contributor

nikomatsakis commented Aug 26, 2016

@dylanede hmm, sorry I failed to answer your question before. I'm sorry to say this, but your code snippet is not expected to work.

In particular, the way to think about it is that, by adding a negative impl for (T, T), you have suppressed the default impl that would have been provided -- so now there is no positive impl! Therefore, (X, Y): NotSame cannot hold for any tuple. (But, (X, Y): !NotSame, if we ever added negative impls, would only hold if X == Y; otherwise, (X, Y) neither implements NotSame nor !NotSame, a situation which @withoutboats artfully described as (X, Y): ?NotSame.)

Note that the behavior for your example is inconsistent already. For example, while your code compiles, this similar snippet does not.

I had to dig a bit into the code to see why your example worked at all: the answer is that the "first pass" test which tries to unify with various impls fails to unify for types like u32 and i32 -- it will basically succeed "modulo regions". So then later when we check to see if there were any negative impls that applied, we find out that there were not (in the case of u32, i32) but that there are (in the case of &'static u32, &'a u32). If we were properly implementing the RFC the way that I had intended to amend it, we would always find applicable negative impls (in fact, until such time as we add general negative reasoning, I had intended to make the negative impl you wrote illegal -- you would have to write negative impls that are "fully general", much like the rules we enforce for Drop.)

@chriskrycho

This comment has been minimized.

Contributor

chriskrycho commented Dec 30, 2016

This is… beyond me. Someday maybe. 😬

But I'm trying to document all the things, so: can someone take a gander at the reference and the book and give me a reasonable summary of the extent to which this is or isn't documented?

@chriskrycho chriskrycho referenced this issue Dec 30, 2016

Closed

Document all features in the reference #38643

0 of 17 tasks complete

@SimonSapin SimonSapin referenced this issue Feb 19, 2017

Open

Tracking issue for 1.0.0 tracking issues #39954

9 of 28 tasks complete
@Zoxc

This comment has been minimized.

Contributor

Zoxc commented Mar 10, 2017

I just wanted to note that if we add immovable types in it's current form, default traits would have to be declared with trait Send: ?Move {} to avoid having Move as a supertrait (which has soundness bugs).

@chriskrycho chriskrycho referenced this issue Mar 11, 2017

Closed

Document all features #9

18 of 48 tasks complete

@mbrubeck mbrubeck changed the title from opt-in built-in bounds traits RFC tracker to opt-in built-in bounds traits RFC tracker (optin_builtin_traits) May 1, 2017

bors added a commit that referenced this issue Nov 1, 2017

Auto merge of #45247 - leodasvacas:implement-auto-trait-syntax, r=nik…
…omatsakis

[Syntax] Implement auto trait syntax

Implements `auto trait Send {}` as a substitute for `trait Send {} impl Send for .. {}`.

See the [internals thread](https://internals.rust-lang.org/t/pre-rfc-renaming-oibits-and-changing-their-declaration-syntax/3086) for motivation. Part of #13231.

The first commit is just a rename moving from "default trait" to "auto trait". The rest is parser->AST->HIR work and making it the same as the current syntax for everything below HIR. It's under the `optin_builtin_traits` feature gate.

When can we remove the old syntax? Do we need to wait for a new `stage0`? We also need to formally decide for the new form (even if the keyword is not settled yet).

Observations:
- If you `auto trait Auto {}` and then `impl Auto for .. {}` that's accepted even if it's redundant.
- The new syntax is simpler internally which will allow for a net removal of code, for example well-formedness checks are effectively moved to the parser.
- Rustfmt and clippy are broken, need to fix those.
- Rustdoc just ignores it for now.

ping @petrochenkov @nikomatsakis

bors added a commit that referenced this issue Nov 1, 2017

Auto merge of #45247 - leodasvacas:implement-auto-trait-syntax, r=nik…
…omatsakis

[Syntax] Implement auto trait syntax

Implements `auto trait Send {}` as a substitute for `trait Send {} impl Send for .. {}`.

See the [internals thread](https://internals.rust-lang.org/t/pre-rfc-renaming-oibits-and-changing-their-declaration-syntax/3086) for motivation. Part of #13231.

The first commit is just a rename moving from "default trait" to "auto trait". The rest is parser->AST->HIR work and making it the same as the current syntax for everything below HIR. It's under the `optin_builtin_traits` feature gate.

When can we remove the old syntax? Do we need to wait for a new `stage0`? We also need to formally decide for the new form (even if the keyword is not settled yet).

Observations:
- If you `auto trait Auto {}` and then `impl Auto for .. {}` that's accepted even if it's redundant.
- The new syntax is simpler internally which will allow for a net removal of code, for example well-formedness checks are effectively moved to the parser.
- Rustfmt and clippy are broken, need to fix those.
- Rustdoc just ignores it for now.

ping @petrochenkov @nikomatsakis

bors added a commit that referenced this issue Nov 2, 2017

Auto merge of #45247 - leodasvacas:implement-auto-trait-syntax, r=nik…
…omatsakis

[Syntax] Implement auto trait syntax

Implements `auto trait Send {}` as a substitute for `trait Send {} impl Send for .. {}`.

See the [internals thread](https://internals.rust-lang.org/t/pre-rfc-renaming-oibits-and-changing-their-declaration-syntax/3086) for motivation. Part of #13231.

The first commit is just a rename moving from "default trait" to "auto trait". The rest is parser->AST->HIR work and making it the same as the current syntax for everything below HIR. It's under the `optin_builtin_traits` feature gate.

When can we remove the old syntax? Do we need to wait for a new `stage0`? We also need to formally decide for the new form (even if the keyword is not settled yet).

Observations:
- If you `auto trait Auto {}` and then `impl Auto for .. {}` that's accepted even if it's redundant.
- The new syntax is simpler internally which will allow for a net removal of code, for example well-formedness checks are effectively moved to the parser.
- Rustfmt and clippy are broken, need to fix those.
- Rustdoc just ignores it for now.

ping @petrochenkov @nikomatsakis

bors added a commit that referenced this issue Nov 2, 2017

Auto merge of #45247 - leodasvacas:implement-auto-trait-syntax, r=nik…
…omatsakis

[Syntax] Implement auto trait syntax

Implements `auto trait Send {}` as a substitute for `trait Send {} impl Send for .. {}`.

See the [internals thread](https://internals.rust-lang.org/t/pre-rfc-renaming-oibits-and-changing-their-declaration-syntax/3086) for motivation. Part of #13231.

The first commit is just a rename moving from "default trait" to "auto trait". The rest is parser->AST->HIR work and making it the same as the current syntax for everything below HIR. It's under the `optin_builtin_traits` feature gate.

When can we remove the old syntax? Do we need to wait for a new `stage0`? We also need to formally decide for the new form (even if the keyword is not settled yet).

Observations:
- If you `auto trait Auto {}` and then `impl Auto for .. {}` that's accepted even if it's redundant.
- The new syntax is simpler internally which will allow for a net removal of code, for example well-formedness checks are effectively moved to the parser.
- Rustfmt and clippy are broken, need to fix those.
- Rustdoc just ignores it for now.

ping @petrochenkov @nikomatsakis

bors added a commit that referenced this issue Nov 3, 2017

Auto merge of #45247 - leodasvacas:implement-auto-trait-syntax, r=nik…
…omatsakis

[Syntax] Implement auto trait syntax

Implements `auto trait Send {}` as a substitute for `trait Send {} impl Send for .. {}`.

See the [internals thread](https://internals.rust-lang.org/t/pre-rfc-renaming-oibits-and-changing-their-declaration-syntax/3086) for motivation. Part of #13231.

The first commit is just a rename moving from "default trait" to "auto trait". The rest is parser->AST->HIR work and making it the same as the current syntax for everything below HIR. It's under the `optin_builtin_traits` feature gate.

When can we remove the old syntax? Do we need to wait for a new `stage0`? We also need to formally decide for the new form (even if the keyword is not settled yet).

Observations:
- If you `auto trait Auto {}` and then `impl Auto for .. {}` that's accepted even if it's redundant.
- The new syntax is simpler internally which will allow for a net removal of code, for example well-formedness checks are effectively moved to the parser.
- Rustfmt and clippy are broken, need to fix those.
- Rustdoc just ignores it for now.

ping @petrochenkov @nikomatsakis
@bstrie

This comment has been minimized.

Contributor

bstrie commented Nov 7, 2017

Resuming the bikeshed which I had previously missed, not quite sold on the new auto trait syntax as of #45247 (though nevertheless an improvement over the old). Not only is it a new keyword (a heavyweight addition) for a feature that is intended to be incredibly obscure, but it risks confusion for people coming from C++.

In #45247 an alternative of #[autoderive] was floated and seemed to have quite some support. I think it makes sense as a general policy for us to prefer attributes/macros for obscure features, and later offer keywords/operators if anyone demands (which was the trajectory for ?, and the possible trajectory for async/await, and unlikely to ever occur for autotraits IMO).

@clarcharr

This comment has been minimized.

Contributor

clarcharr commented May 27, 2018

Random thing I noticed is that OIBIT (hackily) allows checking for type equality (and hence type inequality):

// sealed for good measure
mod private {
    pub auto trait NotSame {}
    impl<T> !NotSame for (T, T) {}
}
use NotSame;

trait ReqDifferent<T> where (T, Self): NotSame {}
trait ReqSame<T> where (T, Self): !NotSame {}

I assume that this is not desired.

@dylanede

This comment has been minimized.

Contributor

dylanede commented May 27, 2018

No, it's not. This behaviour is a bug, See the responses to #13231 (comment)

@clarcharr

This comment has been minimized.

Contributor

clarcharr commented May 27, 2018

Wow, I completely missed that comment. Appears that this has already been discussed

@mitsuhiko

This comment has been minimized.

Contributor

mitsuhiko commented Jun 14, 2018

I ran into this issue when trying to implement !Sync for a type of mine. I know you can work around this with PhantomData well but it makes for ugly error messages. I wish I could tell my users that my type is not Sync and not that *mut () or something similar contained in my type is not sync.

dlrobertson pushed a commit to dlrobertson/rust that referenced this issue Nov 29, 2018

librustc: Make `Copy` opt-in.
This change makes the compiler no longer infer whether types (structures
and enumerations) implement the `Copy` trait (and thus are implicitly
copyable). Rather, you must implement `Copy` yourself via `impl Copy for
MyType {}`.

A new warning has been added, `missing_copy_implementations`, to warn
you if a non-generic public type has been added that could have
implemented `Copy` but didn't.

For convenience, you may *temporarily* opt out of this behavior by using
`#![feature(opt_out_copy)]`. Note though that this feature gate will never be
accepted and will be removed by the time that 1.0 is released, so you should
transition your code away from using it.

This breaks code like:

    #[deriving(Show)]
    struct Point2D {
        x: int,
        y: int,
    }

    fn main() {
        let mypoint = Point2D {
            x: 1,
            y: 1,
        };
        let otherpoint = mypoint;
        println!("{}{}", mypoint, otherpoint);
    }

Change this code to:

    #[deriving(Show)]
    struct Point2D {
        x: int,
        y: int,
    }

    impl Copy for Point2D {}

    fn main() {
        let mypoint = Point2D {
            x: 1,
            y: 1,
        };
        let otherpoint = mypoint;
        println!("{}{}", mypoint, otherpoint);
    }

This is the backwards-incompatible part of rust-lang#13231.

Part of RFC rust-lang#3.

[breaking-change]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment