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

(Re-)Implement impl_trait_in_bindings #134185

Merged
merged 2 commits into from
Dec 14, 2024

Conversation

compiler-errors
Copy link
Member

@compiler-errors compiler-errors commented Dec 11, 2024

This reimplements the impl_trait_in_bindings feature for local bindings.

"impl Trait in bindings" serve as a form of trait ascription, where the type basically functions as an infer var but additionally registering the impl Trait's trait bounds for the infer type. These trait bounds can be used to enforce that predicates hold, and can guide inference (e.g. for closure signature inference):

let _: impl Fn(&u8) -> &u8 = |x| x;

They are implemented as an additional set of bounds that are registered when the type is lowered during typeck, and then these bounds are tied to a given CanonicalUserTypeAscription for borrowck. We enforce these CanonicalUserTypeAscription bounds during borrowck to make sure that the impl Trait types are sensitive to lifetimes:

trait Static: 'static {}
impl<T> Static for T where T: 'static {}

let local = 1;
let x: impl Static = &local;
//~^ ERROR `local` does not live long enough

r? oli-obk

cc #63065


Why can't we just use TAIT inference or something? Well, TAITs in bodies have the problem that they cannot reference lifetimes local to a body. For example:

type TAIT = impl Display;
let local = 0;
let x: TAIT = &local;
//~^ ERROR `local` does not live long enough

That's because TAITs requires us to do opaque type inference which is pretty strict, since we need to remap all of the lifetimes of the hidden type to universal regions. This is simply not possible here.


I consider this part of the "impl trait everywhere" experiment. I'm not certain if this needs yet another lang team experiment.

@compiler-errors
Copy link
Member Author

@bors try @rust-timer queue

@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-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. labels Dec 11, 2024
@rustbot
Copy link
Collaborator

rustbot commented Dec 11, 2024

Some changes occurred in match lowering

cc @Nadrieril

Some changes occurred in src/tools/clippy

cc @rust-lang/clippy

HIR ty lowering was modified

cc @fmease

@rust-timer

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Dec 11, 2024
@bors
Copy link
Contributor

bors commented Dec 11, 2024

⌛ Trying commit f84b2f6 with merge 917c884...

bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 11, 2024
…gs, r=<try>

(Re-)Implement `impl_trait_in_bindings`

This reimplements the `impl_trait_in_bindings` feature for local bindings.

"`impl Trait` in bindings" serve as a form of *trait* ascription, where the type basically functions as an infer var but additionally registering the `impl Trait`'s trait bounds for the infer type. These trait bounds can be used to enforce that predicates hold, and can guide inference (e.g. for closure signature inference):

```rust
let _: impl Fn(&u8) -> &u8 = |x| x;
```

They are implemented as an additional set of bounds that are registered when the type is lowered during typeck, and then these bounds are tied to a given `CanonicalUserTypeAscription` for borrowck. We enforce these `CanonicalUserTypeAscription` bounds during borrowck to make sure that the `impl Trait` types are sensitive to lifetimes:

```rust
trait Static: 'static {}
impl<T> Static for T where T: 'static {}

let local = 1;
let x: impl Static = &local;
//~^ ERROR `local` does not live long enough
```

r? oli-obk

cc rust-lang#63065

---

Why can't we just use TAIT inference or something? Well, TAITs in bodies have the problem that they cannot reference lifetimes local to a body. For example:

```rust
type TAIT = impl Display;
let local = 0;
let x: TAIT = &local;
//~^ ERROR `local` does not live long enough
```

That's because TAITs requires us to do *opaque type inference* which is pretty strict, since we need to remap all of the lifetimes of the hidden type to universal regions. This is simply not possible here.

---

I consider this part of the "impl trait everywhere" experiment. I'm not certain if this needs yet another lang team experiment.
@compiler-errors
Copy link
Member Author

@rust-timer build 917c884

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (917c884): comparison URL.

Overall result: no relevant changes - no action needed

Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR may lead to changes in compiler perf.

@bors rollup=never
@rustbot label: -S-waiting-on-perf -perf-regression

Instruction count

This benchmark run did not return any relevant results for this metric.

Max RSS (memory usage)

Results (primary 0.4%, secondary -4.6%)

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
2.1% [2.1%, 2.1%] 1
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-1.3% [-1.3%, -1.3%] 1
Improvements ✅
(secondary)
-4.6% [-5.1%, -4.2%] 2
All ❌✅ (primary) 0.4% [-1.3%, 2.1%] 2

Cycles

This benchmark run did not return any relevant results for this metric.

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 771.021s -> 769.24s (-0.23%)
Artifact size: 330.96 MiB -> 331.03 MiB (0.02%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Dec 12, 2024
Copy link
Contributor

@oli-obk oli-obk left a comment

Choose a reason for hiding this comment

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

A difference to APIT is that impl Trait<impl Debug> is allowed. r=me with a test for that added

@compiler-errors
Copy link
Member Author

We should definitely not allow that, ill check and add test and maybe fix it

@compiler-errors
Copy link
Member Author

Added a test which confirms that we deny impl Trait<impl Trait>.

@compiler-errors
Copy link
Member Author

@bors r=oli-obk

@bors
Copy link
Contributor

bors commented Dec 12, 2024

📌 Commit 3bbdc9e has been approved by oli-obk

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 12, 2024
@bors
Copy link
Contributor

bors commented Dec 14, 2024

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

@bors bors 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-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Dec 14, 2024
@compiler-errors
Copy link
Member Author

@bors r=oli-obk

@bors
Copy link
Contributor

bors commented Dec 14, 2024

📌 Commit d714a22 has been approved by oli-obk

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Dec 14, 2024
@bors
Copy link
Contributor

bors commented Dec 14, 2024

⌛ Testing commit d714a22 with merge f5079d0...

@bors
Copy link
Contributor

bors commented Dec 14, 2024

☀️ Test successful - checks-actions
Approved by: oli-obk
Pushing f5079d0 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Dec 14, 2024
@bors bors merged commit f5079d0 into rust-lang:master Dec 14, 2024
7 checks passed
@rustbot rustbot added this to the 1.85.0 milestone Dec 14, 2024
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (f5079d0): comparison URL.

Overall result: no relevant changes - no action needed

@rustbot label: -perf-regression

Instruction count

This benchmark run did not return any relevant results for this metric.

Max RSS (memory usage)

Results (primary -1.8%, secondary -2.1%)

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-1.8% [-2.0%, -1.7%] 2
Improvements ✅
(secondary)
-2.1% [-2.1%, -2.1%] 1
All ❌✅ (primary) -1.8% [-2.0%, -1.7%] 2

Cycles

This benchmark run did not return any relevant results for this metric.

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 768.74s -> 769.535s (0.10%)
Artifact size: 333.05 MiB -> 333.08 MiB (0.01%)

flip1995 pushed a commit to flip1995/rust that referenced this pull request Dec 15, 2024
…gs, r=oli-obk

(Re-)Implement `impl_trait_in_bindings`

This reimplements the `impl_trait_in_bindings` feature for local bindings.

"`impl Trait` in bindings" serve as a form of *trait* ascription, where the type basically functions as an infer var but additionally registering the `impl Trait`'s trait bounds for the infer type. These trait bounds can be used to enforce that predicates hold, and can guide inference (e.g. for closure signature inference):

```rust
let _: impl Fn(&u8) -> &u8 = |x| x;
```

They are implemented as an additional set of bounds that are registered when the type is lowered during typeck, and then these bounds are tied to a given `CanonicalUserTypeAscription` for borrowck. We enforce these `CanonicalUserTypeAscription` bounds during borrowck to make sure that the `impl Trait` types are sensitive to lifetimes:

```rust
trait Static: 'static {}
impl<T> Static for T where T: 'static {}

let local = 1;
let x: impl Static = &local;
//~^ ERROR `local` does not live long enough
```

r? oli-obk

cc rust-lang#63065

---

Why can't we just use TAIT inference or something? Well, TAITs in bodies have the problem that they cannot reference lifetimes local to a body. For example:

```rust
type TAIT = impl Display;
let local = 0;
let x: TAIT = &local;
//~^ ERROR `local` does not live long enough
```

That's because TAITs requires us to do *opaque type inference* which is pretty strict, since we need to remap all of the lifetimes of the hidden type to universal regions. This is simply not possible here.

---

I consider this part of the "impl trait everywhere" experiment. I'm not certain if this needs yet another lang team experiment.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants