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

Initial support for auto traits with default bounds #120706

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Bryanskiy
Copy link
Contributor

@Bryanskiy Bryanskiy commented Feb 6, 2024

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) labels Feb 6, 2024
@Bryanskiy
Copy link
Contributor Author

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 6, 2024
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rustbot rustbot added A-testsuite Area: The testsuite used to check the correctness of rustc T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) labels Feb 8, 2024
@petrochenkov
Copy link
Contributor

petrochenkov commented Feb 8, 2024

So, what are the goals here:

  • We want to have a possibility to add new auto traits that are added to all bound lists by default on the current edition. The examples of such traits could be Leak, Move, SyncDrop or something else, it doesn't matter much right now. The desired behavior is similar to the current Sized trait. Such behavior is required for introducing !Leak or !SyncDrop types in a backward compatible way. (Both Leak and SyncDrop are likely necessary for properly supporting libraries for scoped async tasks and structured concurrency.)
  • It's not clear whether it can be done backward compatibly and without significant perf regressions, but that's exactly what we want to find out. Right now we encounter some cycle errors and exponential blow ups in the trait solver, but there's a chance that they are fixable with the new solver.
  • Then we want to land the change into rustc under an option, so it becomes available in bootstrap compiler. Then we'll be able to do standard library experiments with the aforementioned traits without adding hundreds of #[cfg(not(bootstrap))]s.
  • Based on the experiments, we can come up with some scheme for the next edition, in which such bounds are added more conservatively.
  • Relevant blog posts - https://without.boats/blog/changing-the-rules-of-rust/, https://without.boats/blog/follow-up-to-changing-the-rules-of-rust/ and https://without.boats/blog/generic-trait-methods-and-new-auto-traits/, https://without.boats/blog/the-scoped-task-trilemma/
  • Larger compiler team MCP including this feature - MCP: Low level components for async drop compiler-team#727, it gives some more context

@petrochenkov
Copy link
Contributor

The issue right now is that there are regressions, some previously passing code now fails due to cycles in trait solver or something similar, @Bryanskiy has been trying to investigate it, but without success.

@lcnr, this is the work I've been talking about today.
(Maybe it makes sense to ping some other types team members as well?)

@rust-log-analyzer

This comment has been minimized.

@petrochenkov petrochenkov added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 8, 2024
@petrochenkov petrochenkov assigned lcnr and unassigned petrochenkov Feb 8, 2024
@Bryanskiy
Copy link
Contributor Author

Bryanskiy commented Feb 8, 2024

I want to reproduce regressions in CI

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 8, 2024
@lcnr
Copy link
Contributor

lcnr commented Feb 8, 2024

it would be good to get an MVCE for the new cycles, otherwise debugging this without fully going through the PR is hard

@apiraino apiraino added the S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). label Jun 20, 2024
| ty::Char => ty::Binder::dummy(Vec::new()),

// Used for proving `DispatchFromDyn` for default auto traits.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe this is necessary, nor is it sound I think. You should be able to register $DUMMY_PARAM: Auto trait bounds in a param-env.

Copy link
Contributor Author

@Bryanskiy Bryanskiy Jul 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem I was trying to solve here is that we have to prove Receiver: DefaultAutoTrait due to implicit T: DefaultAutoTrait in DispatchFromDyn<T>. It is provable if $DUMMY_PARAM: DefaultAutoTrait. I have now registered this predicate in the param_env, but not sure if this is correct solution.

}
// Used for proving `DispatchFromDyn` for default auto traits.
// See `receiver_is_dispatchable`.
ty::Param(param) if param == ty::ParamTy::dummy() => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not totally sure why this is necessary, and especially why this is sound.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

@@ -737,8 +736,7 @@ fn receiver_is_dispatchable<'tcx>(
// use a bogus type parameter to mimic a forall(U) query using u32::MAX for now.
// FIXME(mikeyhew) this is a total hack. Once object_safe_for_dispatch is stabilized, we can
// replace this with `dyn Trait`
let unsized_self_ty: Ty<'tcx> =
Ty::new_param(tcx, u32::MAX, Symbol::intern("RustaceansAreAwesome"));
let unsized_self_ty: Ty<'tcx> = Ty::new(tcx, ty::Param(ty::ParamTy::dummy()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ty::ParamTy::dummy() now automatically implements all Auto traits, as I noted below, right? I'm suspicious that receiver_is_dispatchable is now subtly unsound.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

@lcnr
Copy link
Contributor

lcnr commented Jul 18, 2024

one question wrt to https://github.com/Bryanskiy/posts/blob/master/default%20auto%20traits.md

what happens if we exclusively add these bounds to methods, but for all type parameters in scope?

i.e. do "In this PR for optimization purposes instead of adding default supertraits, bounds are added to the associated items" not as an optimization, but simply as the desired behavior?

pub trait Trait<Rhs = Self> {}
pub trait Trait1 : Trait {} 

that example would continue to work in this case, as there is no implicit DefaultAutoTrait bound on Rhs. Same for the Trait2<T> : Trait<Type = T> example.

I am likely missing something, but where are these bounds required outside of function bodies?

edit: I was missing struct Foo<T>(T::Assoc); which would not implement Leak unless T::Assoc has a default bound

@traviscross
Copy link
Contributor

@rustbot labels -I-lang-nominated

In our meeting on 2024-07-17, we decided to accept this as a lang experiment. Thanks to @Bryanskiy, @zetanumbers, and @petrochenkov for the ongoing work here.

@rustbot rustbot removed the I-lang-nominated Nominated for discussion during a lang team meeting. label Jul 24, 2024
@oli-obk oli-obk removed their assignment Jul 25, 2024
@rust-log-analyzer

This comment has been minimized.

@Bryanskiy
Copy link
Contributor Author

Bryanskiy commented Jul 25, 2024

I am likely missing something, but where are these bounds required outside of function bodies?

It is not enough to add these bounds only for functions. An example of a backward compatibility violation if they are not added to associated types:

trait Trait {
  type Item: Sized;
  fn get_item(&self) -> Self::Item;
}

// impilict `T: DefaultAutoTrait` here
fn foo<T>(_: T) {}

fn bar<T: Trait>(x: T) {
  foo(x.get_item());
  //~^ ERROR the trait bound `<T as Trait>::Item: DefaultAutoTrait` is not satisfied
}

or for constants:

// impilict `T: DefaultAutoTrait` here
pub const fn size_of<T>() -> usize {...}
...
pub trait Trait: Sized {
   const SOME_CONST: usize = size_of::<Self>();
   // the trait bound `Self: DefaultAutoTrait` is not satisfied
}

@Bryanskiy
Copy link
Contributor Author

@rustbot ready

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 25, 2024
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jul 25, 2024
Support ?Trait bounds in supertraits and dyn Trait under a feature gate

This patch allows `maybe` polarity bounds under a feature gate. The only language change here is that corresponding hard errors are replaced by feature gates. Example:
```rust
#![feature(allow_maybe_polarity)]
...
trait Trait1 : ?Trait { ... } // ok
fn foo(_: Box<(dyn Trait2 + ?Trait)>) {} // ok
fn bar<T: ?Sized + ?Trait>(_: &T) {} // ok
```
Maybe bounds still don't do anything (except for `Sized` trait), however this patch will allow us to [experiment with default auto traits](rust-lang#120706 (comment)).

This is a part of the [MCP: Low level components for async drop](rust-lang/compiler-team#727)
@@ -3,36 +3,54 @@ error[E0203]: type parameter has more than one relaxed default bound, only one i
|
LL | fn foo2<T: ?Sized + ?Sized>(a: T) {}
| ^^^^^^ ^^^^^^
|
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be allowed, even w/ the feature gate.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fn foo<T: Clone + Clone>() {} is supported though, it doesn't even warn.

Comment on lines +417 to +422
// Experimental lang items for `MCP: Low level components for async drop`(https://github.com/rust-lang/compiler-team/issues/727)
DefaultTrait4, sym::default_trait4, default_trait4_trait, Target::Trait, GenericRequirement::None;
DefaultTrait3, sym::default_trait3, default_trait3_trait, Target::Trait, GenericRequirement::None;
DefaultTrait2, sym::default_trait2, default_trait2_trait, Target::Trait, GenericRequirement::None;
DefaultTrait1, sym::default_trait1, default_trait1_trait, Target::Trait, GenericRequirement::None;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not make it so that the compiler collects these traits on-demand, rather than having to be hard-coded in the compiler? Having 4 dummy lang items is kinda annoying, and it seems like something that can be an attr on a trait.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can. This would require partially copying the logic for lang items collection, as new traits can be defined in another crate. Using lang items is just easier.

@bors
Copy link
Contributor

bors commented Jul 26, 2024

☔ The latest upstream changes (presumably #128213) made this pull request unmergeable. Please resolve the merge conflicts.

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jul 26, 2024
Support ?Trait bounds in supertraits and dyn Trait under a feature gate

This patch allows `maybe` polarity bounds under a feature gate. The only language change here is that corresponding hard errors are replaced by feature gates. Example:
```rust
#![feature(allow_maybe_polarity)]
...
trait Trait1 : ?Trait { ... } // ok
fn foo(_: Box<(dyn Trait2 + ?Trait)>) {} // ok
fn bar<T: ?Sized + ?Trait>(_: &T) {} // ok
```
Maybe bounds still don't do anything (except for `Sized` trait), however this patch will allow us to [experiment with default auto traits](rust-lang#120706 (comment)).

This is a part of the [MCP: Low level components for async drop](rust-lang/compiler-team#727)
tgross35 added a commit to tgross35/rust that referenced this pull request Jul 26, 2024
Support ?Trait bounds in supertraits and dyn Trait under a feature gate

This patch allows `maybe` polarity bounds under a feature gate. The only language change here is that corresponding hard errors are replaced by feature gates. Example:
```rust
#![feature(allow_maybe_polarity)]
...
trait Trait1 : ?Trait { ... } // ok
fn foo(_: Box<(dyn Trait2 + ?Trait)>) {} // ok
fn bar<T: ?Sized + ?Trait>(_: &T) {} // ok
```
Maybe bounds still don't do anything (except for `Sized` trait), however this patch will allow us to [experiment with default auto traits](rust-lang#120706 (comment)).

This is a part of the [MCP: Low level components for async drop](rust-lang/compiler-team#727)
bors added a commit to rust-lang-ci/rust that referenced this pull request Jul 26, 2024
Support ?Trait bounds in supertraits and dyn Trait under a feature gate

This patch allows `maybe` polarity bounds under a feature gate. The only language change here is that corresponding hard errors are replaced by feature gates. Example:
```rust
#![feature(allow_maybe_polarity)]
...
trait Trait1 : ?Trait { ... } // ok
fn foo(_: Box<(dyn Trait2 + ?Trait)>) {} // ok
fn bar<T: ?Sized + ?Trait>(_: &T) {} // ok
```
Maybe bounds still don't do anything (except for `Sized` trait), however this patch will allow us to [experiment with default auto traits](rust-lang#120706 (comment)).

This is a part of the [MCP: Low level components for async drop](rust-lang/compiler-team#727)
github-actions bot pushed a commit to rust-lang/miri that referenced this pull request Jul 27, 2024
Support ?Trait bounds in supertraits and dyn Trait under a feature gate

This patch allows `maybe` polarity bounds under a feature gate. The only language change here is that corresponding hard errors are replaced by feature gates. Example:
```rust
#![feature(allow_maybe_polarity)]
...
trait Trait1 : ?Trait { ... } // ok
fn foo(_: Box<(dyn Trait2 + ?Trait)>) {} // ok
fn bar<T: ?Sized + ?Trait>(_: &T) {} // ok
```
Maybe bounds still don't do anything (except for `Sized` trait), however this patch will allow us to [experiment with default auto traits](rust-lang/rust#120706 (comment)).

This is a part of the [MCP: Low level components for async drop](rust-lang/compiler-team#727)
@Dylan-DPC Dylan-DPC added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 7, 2024
flip1995 pushed a commit to flip1995/rust-clippy that referenced this pull request Aug 8, 2024
Support ?Trait bounds in supertraits and dyn Trait under a feature gate

This patch allows `maybe` polarity bounds under a feature gate. The only language change here is that corresponding hard errors are replaced by feature gates. Example:
```rust
#![feature(allow_maybe_polarity)]
...
trait Trait1 : ?Trait { ... } // ok
fn foo(_: Box<(dyn Trait2 + ?Trait)>) {} // ok
fn bar<T: ?Sized + ?Trait>(_: &T) {} // ok
```
Maybe bounds still don't do anything (except for `Sized` trait), however this patch will allow us to [experiment with default auto traits](rust-lang/rust#120706 (comment)).

This is a part of the [MCP: Low level components for async drop](rust-lang/compiler-team#727)
@Bryanskiy
Copy link
Contributor Author

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Aug 20, 2024
@bors
Copy link
Contributor

bors commented Aug 27, 2024

☔ The latest upstream changes (presumably #129665) made this pull request unmergeable. Please resolve the merge conflicts.

@apiraino apiraino removed the S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). label Aug 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-async-await Area: Async & Await A-testsuite Area: The testsuite used to check the correctness of rustc AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. perf-regression Performance regression. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. WG-async Working group: Async & await WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)
Projects
None yet
Development

Successfully merging this pull request may close these issues.