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

Allow const iterator implementations #102225

Closed
wants to merge 4 commits into from

Conversation

fee1-dead
Copy link
Member

@fee1-dead fee1-dead commented Sep 24, 2022

Based on #102224

@rust-highfive
Copy link
Collaborator

r? @thomcc

(rust-highfive has picked a reviewer for you, use r? to override)

@rustbot rustbot added 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. labels Sep 24, 2022
@rustbot
Copy link
Collaborator

rustbot commented Sep 24, 2022

Hey! It looks like you've submitted a new PR for the library teams!

If this PR contains changes to any rust-lang/rust public library APIs then please comment with @rustbot label +T-libs-api -T-libs to tag it appropriately. If this PR contains changes to any unstable APIs please edit the PR description to add a link to the relevant API Change Proposal or create one if you haven't already. If you're unsure where your change falls no worries, just leave it as is and the reviewer will take a look and make a decision to forward on if necessary.

Examples of T-libs-api changes:

  • Stabilizing library features
  • Introducing insta-stable changes such as new implementations of existing stable traits on existing stable types
  • Introducing new or changing existing unstable library APIs (excluding permanently unstable features / features without a tracking issue)
  • Changing public documentation in ways that create new stability guarantees
  • Changing observable runtime behavior of library APIs

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 24, 2022
@fee1-dead
Copy link
Member Author

cc @rust-lang/wg-const-eval

@bors
Copy link
Contributor

bors commented Sep 24, 2022

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

@thomcc
Copy link
Member

thomcc commented Sep 25, 2022

I could review the impl changes (so feel free to reassign to me if you'd prefer), but I think I'm not the best here. I know @scottmcm has done considerable work on the iterator implementations, and is also t-lang, so they seem like a more natural fit for this.

r? @scottmcm

@rust-highfive rust-highfive assigned scottmcm and unassigned thomcc Sep 25, 2022
@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented Sep 25, 2022

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

@onestacked
Copy link
Contributor

onestacked commented Sep 25, 2022

Once this lands I can take on const Iterator for Ranges, Slices and maybe some other types if you want.

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.

The drop in place change could go into a separate PR, seems good on its own

On the rest of the PR: quite a few annoyingly big bootstrap diffs, not sure how I feel about them. But I also don't want to block this for a month

// SAFETY: slice contains initialized objects
unsafe { crate::ptr::drop_in_place(x) }
}
crate::intrinsics::const_eval_select((to_drop,), drop_ct, drop_rt);
Copy link
Contributor

Choose a reason for hiding this comment

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

This will be needed more often, maybe move into drop_in_place

Copy link
Member Author

Choose a reason for hiding this comment

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

I can extract this into a separate function, but not to drop_in_place as drop_in_place is for all unsized types and this is only for slices.

@scottmcm
Copy link
Member

Hmm, this is really dependent on the change from 2 days ago, I take it? My instinct was also that it would be nice to wait for the bootstrap bump, but if it's 6 weeks that's not amazing.

Certainly a bunch of this -- like constifying the adaptor constructors -- is an easy "sure", though.

@onestacked
Copy link
Contributor

Once this lands I can take on const Iterator for Ranges, Slices and maybe some other types if you want.

Im not sure its actually possible to do const Iterator for slices, since those rely on many pointer operations that are not sound in const context.

pub struct Iter<'a, T: 'a> {
    ptr: NonNull<T>,
    end: *const T, // If T is a ZST, this is actually ptr+len.  This encoding is picked so that
    // ptr == end is a quick test for the Iterator being empty, that works
    // for both ZST and non-ZST.
    _marker: PhantomData<&'a T>,
}

library/core/src/slice/iter/macros.rs: has the is_empty and len macros, other then those I have implemented const Iterator for slices.

@fee1-dead
Copy link
Member Author

Certainly a bunch of this -- like constifying the adaptor constructors -- is an easy "sure", though.

We recently moved to attributes on the entire trait instead of marking individual functions as const. As a result of this, we can't simply constify adaptors separately..

@fee1-dead fee1-dead force-pushed the const_iterator branch 2 times, most recently from efd3979 to 8240186 Compare September 27, 2022 14:34
@the8472
Copy link
Member

the8472 commented Sep 27, 2022

Could this maybe be reduced in scope by only making next const so iterators work in for-each loops?

@onestacked
Copy link
Contributor

Could this maybe be reduced in scope by only making next const so iterators work in for-each loops?

No as @fee1-dead said above there was a recent change that disabled partially const Traits. (only allow const implementations for traits with the #[const_trait] attribute)
So it is no longer possible to only implement const next().

Partially const Traits were removed, since a ~const Trait bound would not actually mean that the concrete type used actually has the const functions needed.

@thomcc
Copy link
Member

thomcc commented Sep 27, 2022

This seems unfortunate, since it also means that we're effectively saying that t-libs-api is only allowed to make const iterator methods (or else Rust users can't use iterators in const).

That might be reasonable, but it's a big restriction that seems worth considering.

@onestacked
Copy link
Contributor

Keyword generics might allow syntax like this to allow non const functions in traits:

const<C> Trait {
    const<C> fn const_fn() { ...}
    fn non_const_fn() {...}
}

But otherwise I don't know how to make some trait functions never const. (Other than adding some kind of #[never_const] attribute which would be very weird in my opinion)

@the8472
Copy link
Member

the8472 commented Sep 28, 2022

This seems unfortunate, since it also means that we're effectively saying that t-libs-api is only allowed to make const iterator methods (or else Rust users can't use iterators in const).

That should make this a libs-api concern

@the8472 the8472 added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. and removed T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Sep 28, 2022
@fee1-dead fee1-dead marked this pull request as ready for review November 14, 2022 13:51
@fee1-dead
Copy link
Member Author

fee1-dead commented Nov 15, 2022

Re-requesting review, since this now uses derive_const. Partially const traits have serious design concerns, and I don't see how we will ever need a method body that cannot be const, and even if we might need it we can still just leave it unimplemented using const_eval_select. So I don't think having a language feature to allow partially const traits would be the biggest blocker right now.

@the8472
Copy link
Member

the8472 commented Nov 16, 2022

Partially const traits have serious design concerns

Even if we don't have stable partially const traits enabling that unstably would still bring the benefit of reducing the amount of API surface we need to constify, which is one of the issues with this type of "experimenting with const syntax" PR.

and I don't see how we will ever need a method body that cannot be const

If core and std get unified then it could easily do something that does IO or allocate. Or it could involve concrete types that aren't const.

and even if we might need it we can still just leave it unimplemented using const_eval_select.

It's be quite the hack to explicitly declare the whole thing is const and then go "oops, you can't actually call this in const contexts". That's exactly the time where you'd need a partially const trait to make this explicit.

Comment on lines 1939 to 1947
const fn collect<
'a,
T: ~const Iterator,
R,
O: ~const FromIterator<<<T as Iterator>::Item as Try>::Output>,
>(
x: GenericShunt<'a, T, R>,
) -> O
where
T::Item: ~const Try<Residual = R>,
R: ~const Destruct,
{
x.collect()
}
Copy link
Member

Choose a reason for hiding this comment

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

this looks terrible, can the generic constraints be moved to where bounds?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

move |(), (t, u)| {
a.extend_one(t);
b.extend_one(u);
pub struct ExtendFold<'a, EA, EB>(&'a mut EA, &'a mut EB);
Copy link
Member

Choose a reason for hiding this comment

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

Is this a temporary thing to be removed later? If so it could use a FIXME(#issuenumber) for the feature needed to solve it.

If this isn't meant to be temporary I have additional concerns.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, this is temporary. This could be improved and made to look better using ConstFnMutClosure, but in the long run we plan to replace these with const closures.

Copy link
Member Author

Choose a reason for hiding this comment

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

I've improved it.

library/core/src/iter/adapters/zip.rs Outdated Show resolved Hide resolved
library/core/src/iter/adapters/mod.rs Show resolved Hide resolved
library/core/src/array/mod.rs Show resolved Hide resolved
@the8472
Copy link
Member

the8472 commented Nov 16, 2022

There's some ongoing work for namable function items. Would it be possible to have conditionally-const Iterator::next impls and then make const for _ in iter depend on where I: Iterator, I::fn::next: ~const or something like that?

@fee1-dead
Copy link
Member Author

fee1-dead commented Nov 17, 2022

Partially const traits have serious design concerns

Even if we don't have stable partially const traits enabling that unstably would still bring the benefit of reducing the amount of API surface we need to constify, which is one of the issues with this type of "experimenting with const syntax" PR.

The serious design concerns make the described language feature perma-unstable if they cannot be resolved.

It's be quite the hack to explicitly declare the whole thing is const and then go "oops, you can't actually call this in const contexts". That's exactly the time where you'd need a partially const trait to make this explicit.

We are not panicking at runtime, though? This would only result in compile errors when called. I would consider adding a perma-unstable language feature for this to be a hack as well.

There's some ongoing work for namable function items. Would it be possible to have conditionally-const Iterator::next impls and then make const for _ in iter depend on where I: Iterator, I::fn::next: ~const or something like that?

I guess. It will certainly need more compiler work in addition to namable function item types to make this happen. I was hoping that we could make comparisons between two slices possible in compile time. Its current default implementation uses iterator combinators. (see)

The thing is that all of these are doable and look way better than the one I did a year ago (#92433) It is a real concern in terms of readability since not many people understand what ~const is right now, and those are valid points. Perhaps you would want const_closure to be implemented (after ~1yr or more of implementation work) first, such that readability of these closures are not impacted at all?

@bors

This comment was marked as resolved.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer
Copy link
Collaborator

The job mingw-check failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
   Compiling memchr v2.5.0
   Compiling std v0.0.0 (/checkout/library/std)
   Compiling compiler_builtins v0.1.84
   Compiling unwind v0.0.0 (/checkout/library/unwind)
error[E0277]: the trait bound `alignment::Alignment: ~const cmp::Eq` is not satisfied
    |
174 | impl const cmp::Ord for Alignment {
174 | impl const cmp::Ord for Alignment {
    |            ^^^^^^^^ the trait `~const cmp::Eq` is not implemented for `alignment::Alignment`
    |
note: the trait `cmp::Eq` is implemented for `alignment::Alignment`, but that implementation is not `const`
    |
174 | impl const cmp::Ord for Alignment {
    |            ^^^^^^^^
note: required by a bound in `cmp::Ord`
note: required by a bound in `cmp::Ord`
   --> library/core/src/cmp.rs:767:16
    |
767 | pub trait Ord: ~const Eq + ~const PartialOrd<Self> {
    |                ^^^^^^^^^ required by this bound in `cmp::Ord`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `core` due to previous error
Build completed unsuccessfully in 0:02:04

@bors
Copy link
Contributor

bors commented Dec 10, 2022

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

@TiagoCavalcante

This comment was marked as off-topic.

@apiraino
Copy link
Contributor

apiraino commented Jan 5, 2023

I'll tentatively remove T-compiler from the review queue as the code in this patch seems now to be all under ./library/core. Let me know if it's ok!

@rustbot label -T-compiler

@rustbot rustbot removed the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Jan 5, 2023
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request Feb 23, 2023
…o, r=thomcc

implement const iterator using `rustc_do_not_const_check`

Previous experiment: rust-lang#102225.

Explanation: rather than making all default methods work under `const` all at once, this uses `rustc_do_not_const_check` as a workaround to "trick" the compiler to not run any checks on those other default methods. Any const implementations are only required to implement the `next` method. Any actual calls to the trait methods other than `next` will either error in compile time (at CTFE runs), or run the methods correctly if they do not have any non-const operations. This is extremely easy to maintain, remove, or improve.
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request Feb 24, 2023
…o, r=thomcc

implement const iterator using `rustc_do_not_const_check`

Previous experiment: rust-lang#102225.

Explanation: rather than making all default methods work under `const` all at once, this uses `rustc_do_not_const_check` as a workaround to "trick" the compiler to not run any checks on those other default methods. Any const implementations are only required to implement the `next` method. Any actual calls to the trait methods other than `next` will either error in compile time (at CTFE runs), or run the methods correctly if they do not have any non-const operations. This is extremely easy to maintain, remove, or improve.
@fee1-dead fee1-dead closed this Feb 25, 2023
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request Mar 19, 2023
…r=the8472,fee1-dead

Allow using `Range` as an `Iterator` in const contexts.

~~based on rust-lang#102225 by `@fee1-dead~~`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.