CloudTasksGapicClient->listTasks frequently throws a cURL timeout

OS: Debian Buster container on Google Cloud Run (us-central1)
PHP version: 7.4
Package name and version: google/cloud-tasks:"^1.6" (currently on v1.9.1)

Steps to reproduce

Simply call listTasks on a CloudTasksClient instance, and frequently (though inconsistently) Guzzle will time out at the 10000 millisecond mark.
I've attempted to override the default 10-second behavior by adding the key/val pair of:

'timeout_millis' => 60000

...to the $options array when creating the instance of CloudTasksClient, but it had no effect.  Timeout still occurred at the 10000 millisecond mark.
Code example
I'm using Laravel8, so know that config('gcp.PROPERTY') will retrieve PROPERTY from the file "gcp.php" under the "config" directory.  The properties referenced here have all been consistently retrieved from the configuration files, so that's very unlikely a factor here.
    /**
     * CountTasks - Iterates through the tasks in the queue and returns a count
     *
     * @param string $namePrefix - Truly this is a suffix... the "project/location/" will be auto-appended
     * @return int
     * @throws ApiException
     * @throws ValidationException
     */
    public function CountTasks(string $namePrefix) : int
    {
        $prj = config('gcp.project');
        $loc = config('gcp.location');

        // Create the task queue client
        $client = new CloudTasksClient([
            'credentials' => config('gcp.cloud_tasks_creds'),
            'timeout_millis' => config('gcp.cloud_tasks_timeout_milliseconds')
        ]);

        $formattedParent = $client->queueName($prj, $loc, $namePrefix);
        $i = 0;

        // Iterate over all pages of elements and count the elements (tasks)
        $pagedResponse = $client->listTasks($formattedParent);
        foreach ($pagedResponse->iterateAllElements() as $foo) {
            $i++;
        }

        return $i;
    }

@dwsupplee do you have thoughts on where this timeout could be coming from?

@grayside @dwsupplee Folks, the stack trace was pointing at Guzzle timing out at 10,000ms while I was iterating through all tasks in a queue.
I tried to modify the timeout by passing a custom config when creating the instance of the CloudTasksClient but it seemed to have been ignored so I've since stripped it back out from my code.  Here's what that attempt looked like in my Laravel project, where the "cloud_tasks_timeout_milliseconds" setting was set to 60000:
$this->client = new CloudTasksClient([
   'credentials' => config('gcp.cloud_tasks_creds'),
   'timeout_millis' => config('gcp.cloud_tasks_timeout_milliseconds')
]);

HTH

The timeout_millis option does not work like that. You'll need to pass an array of RetrySettings into the call you want to make (in this case, listTasks). So it would look something like this:
// create an array of timeout settings using your custom timeout
$timeoutSettings = RetrySettings::logicalTimeout(60000);
// passing this to `retrySettings` will preserve the other defaults for that client method
$pagedResponse = $client->listTasks($formattedParent, ['retrySettings' => $timeoutSettings]);

see the RetrySettings documentation for more info.


Got InstagramRipper working again

Category
This change is exactly one of the following (please change [ ] to [x]) to indicate which:

[x] a bug fix (Fix #718)

Description
I changed AbstractJSONRipper to respect hasASAPRipping and fixed the instagram ripper
Testing
Required verification:

[ ] I've verified that there are no regressions in mvn test (there are no new failures or errors).
[ ] I've verified that this change works as intended.

[ ] Downloads all relevant content.
[ ] Downloads content from multiple pages (as necessary or appropriate).
[ ] Saves content at reasonable file names (e.g. page titles or content IDs) to help easily browse downloaded content.

[ ] I've verified that this change did not break existing functionality (especially in the Ripper I modified).

Optional but recommended:

[ ] I've added a unit test to cover my change.

The failed tests have nothing to do with these changes


Call Custom Function when Accordion Expanded

Is there any method to call function when specific accordion expanded?
Like onClick method:
<AccordionItem uuid="program1">
        <AccordionItemHeading>
                      <AccordionItemButton onClick="this.customFunction">
                               Test
                      </AccordionItemButton>
        </AccordionItemHeading>
</AccordionItem>

I was able to use AccordionItemState to do something similar:
                        <AccordionItemButton>
                            <AccordionItemState>
                                {({ expanded }) => {
                                    const state = expanded ? 'expanded' : 'collapsed';
                                    return (
                                        <button onClick={() => console.log(`hello`)}>
                                            This item is: {state}
                                        </button>
                                    );
                                }}
                            </AccordionItemState>
                        </AccordionItemButton>

@cristianr909090 my understanding is there is no way to call a function from the AccordionItemButton, this is basically a <div role="button"> and can only have one onClick event which controls the toggling of this accordion item.
However, the Accordion component has an onChange prop that is invoked when items are expanded, you could give each AccordionItem  a uuid and check onChange if a certain item is expanded, if so, do something.
Something like:
<Accordion onChange={ (uuids) => { console.log(uuids) }} >
                <AccordionItem uuid={uuid}>
                    <AccordionItemHeading>
                        <AccordionItemButton>
                            Button heading
                        </AccordionItemButton>
                    </AccordionItemHeading>
                    <AccordionItemPanel>Content</AccordionItemPanel>
                </AccordionItem>
</Accordion>

Reference here: https://github.com/springload/react-accessible-accordion#onchange--string--void-optional

Assuming this is dealt with. Please reopen if there is any issue.


Handle tasks which have a goal state of Finished

Any plan when this will be merged? Thanks!

This PR isn't relevant anymore.  #374 handles all this.

So it should already work? I tried with yesterday's master and a YAML plan, but it didn't...


Feature request: more relative motion

I would love to be able to go to the previous (number -1) desk and also to move my windows to the next/previous workspace.
Also the dispatchers name confused me, referring to next as the number+1 but previous as the latest visited and not the number-1. I will suggest to change the prevdesk dispatcher name to something like lastdesk or so.

Hi, can you check the PR https://github.com/levnikmyskin/hyprland-virtual-desktops/pull/14 ?
Code compiles but I haven't tested it yet

Tested and it works!
Just a point, imo will be better for consistency to have something like prevdesk/nextdesk that don't cycles and cyclevdesk/inversecyclevdesk(?) that cycles (like prevdesk in this implementation), or a configuration setting to switch on/off this behaviour.

Thanks for your suggestion. Yes I was already thinking about including something like that. Probably I'll add another config variable, something like backwardcycle

Hi again. I have pushed some changes. I added the backcyclevdesks, which can now be paired with cyclevdesks for backward/forward cycling. Would you have time to test everything works? These days I'm mostly committing from another computer where I don't have hyprland configured

Tested just now, everything works fine.

Thank you very much!


Drop dependency on libcalico-go and improve TestHostEndpoints test

While trying to upgrade Helm dependency to the latest version, we hit
the issue, that libcalico-go is still using old version of
'k8s.io/apimachinery', which prevents us from updating. On Calico slack,
we found, that libcalico-go shouldn't really be imported and used, as
the stability is not guaranteed.
We could upgrade apimachinery in libcalico-go and use the forked version
for the time being, but I think we should avoid that, as implementing
that, getting it merged upstream and released may take a long time.
As TestHostEndpoints test is the only place we use libcalico-go, the
easier way forward is to drop it as a dependency, which will unblock
updating Helm.
This commit changes this test to use Kubernetes REST client, which
mimics 'kubectl get --raw' instead of Calico client, to get HostEndpoint
objects from the cluster.
Also while testing this patch, I found that in my opinion this test is too easy to satisfy,
as any HostEndpoint object with right node name will make it pass, which means,
that if only the HostEndpoint for VPN interface exist, the test will pass, which should not be
the case, as our main concern is bond0 interface, which is exposed to the internet, so this PR
also improves that, so we also check for bond0 interface name.
Signed-off-by: Mateusz Gozdek<EMAIL_ADDRESS>CC @iaguis

This is part of #484 and #545.

Ooops, linter is not happy.


Possible serialization problem?

When running the entire test suite with the option -Dceylon.compile.forceBoxedLocals (see ceylon/ceylon-compiler#1464) I got 2 failing serialization tests: testSerializationRegisterTwice2 and testSerializationRegisterTwice3. You can easily test this yourself with the latest code from master by making the following change to the code (using testSerializationRegisterTwice3 as an example):
shared void testSerializationRegisterTwice3() {
    value sc = serialization();
    variable value id = 0;
    @boxed value instance = 1;
    sc.reference(0, instance);
    sc.reference(1, instance);
}

To see the difference in generated code, this is the original (unboxed):
public static void testSerializationRegisterTwice3() {
    final .ceylon.language.serialization.SerializationContext sc = .ceylon.language.serialization.serialization_.serialization();
    long id = 0L;
    final long instance = 1L;
    sc.<.ceylon.language.Integer>reference(.ceylon.language.Integer.$TypeDescriptor$, .ceylon.language.Integer.instance(0L), .ceylon.language.Integer.instance(instance));
    sc.<.ceylon.language.Integer>reference(.ceylon.language.Integer.$TypeDescriptor$, .ceylon.language.Integer.instance(1L), .ceylon.language.Integer.instance(instance));
}

And this is the version with forced boxing:
public static void testSerializationRegisterTwice3() {
    final .ceylon.language.serialization.SerializationContext sc = .ceylon.language.serialization.serialization_.serialization();
    long id = 0L;
    final .ceylon.language.Integer instance = .ceylon.language.Integer.instance(1L);
    sc.<.ceylon.language.Integer>reference(.ceylon.language.Integer.$TypeDescriptor$, .ceylon.language.Integer.instance(0L), instance);
    sc.<.ceylon.language.Integer>reference(.ceylon.language.Integer.$TypeDescriptor$, .ceylon.language.Integer.instance(1L), instance);
}

The error is just a generic assert:
java.lang.AssertionError: A different instance has already been registered with id 1: "0", "1"

The test now fails with this:
java.lang.AssertionError: The instance "1" has already been registered with id 1: You cannot register "1.0" again with a different id	11:01
at com.redhat.ceylon.compiler.java.runtime.serialization.SerializationContextImpl.reference(SerializationContextImpl.java:73)	11:01
at serialization.testSerializeBasics_.testSerializeBasics(serialization.ceylon:19)	11:01
That's due to #602. Basically I'd like the API to prevent doing broken things like registering the same object multiple times but with different ids (that would be a bug in the serialization library). But because Integer and Float are not identifiable, but also a Float can equal an Integer, I can't tell them apart easily. I suppose I can fix it by having a different map for each of them, that just seems surprisingly complicated.

@tombentley I think there's something a bit heavy-handed here. One thing I tried to do was merge multiple json documents into the same DeserializationContext, but this failed, because there was one object repeated between the two documents. This seems to me a common-enough usage that it needs to be supported.

One thing I tried to do was merge multiple json documents into the same DeserializationContext

You mean you took the output of two different serializations and merged them together?

Yes.

Well there's another excellent reason that won't work: Different instances will be allocated the same ids during serialization.

No, this is deserialization. They already have ids.

Yes, but unless you carefully renumbered stuff they'll both be using id 1 for different instance.

I don't want two instances. I just want to ignore one definition.

You seriously think that's a common enough thing to want to do that we should support it? It seems to me that the chances are slim that the types of things with id x will necessarily be compatible, so we'll likely just throw later during serialization with an IncompatibleTypeException, or something.

It's extremely common in client/server systems.

P.S. See EntityManager.merge() which exists precisely for this reason.

@gavinking I've changed jsonsl to support this, if you want to try it out. We still throw in the case of duplicate ids during serialization though.

@tombentley When I run the language module test suite I get:
[ceylon-run] Exception in thread "main" java.lang.reflect.InvocationTargetException
[ceylon-run] 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ceylon-run] 	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[ceylon-run] 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ceylon-run] 	at java.lang.reflect.Method.invoke(Method.java:483)
[ceylon-run] 	at com.redhat.ceylon.launcher.Launcher.runInJava7Checked(Launcher.java:113)
[ceylon-run] 	at com.redhat.ceylon.launcher.Launcher.run(Launcher.java:40)
[ceylon-run] 	at com.redhat.ceylon.launcher.Launcher.run(Launcher.java:33)
[ceylon-run] 	at com.redhat.ceylon.launcher.Launcher.main(Launcher.java:26)
[ceylon-run] Caused by: ceylon.language.AssertionError "The instance "1" has already been registered with id 1: You cannot register "1.0" again with a different id"
[ceylon-run] 	at com.redhat.ceylon.compiler.java.runtime.serialization.SerializationContextImpl.reference(SerializationContextImpl.java:73)
[ceylon-run] 	at serialization.testSerializeBasics_.testSerializeBasics(serialization.ceylon:19)
[ceylon-run] 	at serialization.run_.run(serialization.ceylon:209)
[ceylon-run] 	at serialization.run_.main(serialization.ceylon)
[ceylon-run] 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ceylon-run] 	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[ceylon-run] 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ceylon-run] 	at java.lang.reflect.Method.invoke(Method.java:483)
[ceylon-run] 	at ceylon.modules.api.runtime.SecurityActions.invokeRunInternal(SecurityActions.java:57)
[ceylon-run] 	at ceylon.modules.api.runtime.SecurityActions.invokeRun(SecurityActions.java:48)
[ceylon-run] 	at ceylon.modules.api.runtime.AbstractRuntime.invokeRun(AbstractRuntime.java:110)
[ceylon-run] 	at ceylon.modules.api.runtime.AbstractRuntime.execute(AbstractRuntime.java:176)
[ceylon-run] 	at ceylon.modules.api.runtime.AbstractRuntime.execute(AbstractRuntime.java:160)
[ceylon-run] 	at ceylon.modules.Main.execute(Main.java:69)
[ceylon-run] 	at ceylon.modules.Main.main(Main.java:42)
[ceylon-run] 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ceylon-run] 	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[ceylon-run] 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ceylon-run] 	at java.lang.reflect.Method.invoke(Method.java:483)
[ceylon-run] 	at org.jboss.modules.Module.run(Module.java:312)
[ceylon-run] 	at org.jboss.modules.Main.main(Main.java:460)
[ceylon-run] 	at ceylon.modules.bootstrap.CeylonRunTool.run(CeylonRunTool.java:215)
[ceylon-run] 	at com.redhat.ceylon.common.tools.CeylonTool.run(CeylonTool.java:409)
[ceylon-run] 	at com.redhat.ceylon.common.tools.CeylonTool.execute(CeylonTool.java:346)

This has been there for way too long, preventing the tests from running. Please either fix this or disable the tests.


rPackages.XML cannot find xml2-config

Issue description
rPackages.XML cannot find xml2-config during compilation
Notes:

xml2-config is part of libxml2
packagesWithNativeBuildInputs contains "XML = [ pkgs.libtool pkgs.libxml2.dev pkgs.xmlsec pkgs.libxslt ]"
see https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/r-modules/default.nix

Steps to reproduce
$ nix-shell -p rPackages.XML
[...]
checking for pkg-config... /nix/store/jklxb0jl7jchv79gkm49bhd9n6zh1a2i-pkg-config-0.29/bin/pkg-config
checking for xml2-config... no
Cannot find xml2-config
ERROR: configuration failed for package 'XML'
removing '/nix/store/gqff0m40s9466y4m4vdyypi2bilnf9p9-r-XML-3.98-1.4/library/XML'
builder for ‘/nix/store/cdgrcrfv7445m4hspvvfwh7mnr0d0bxr-r-XML-3.98-1.4.drv’ failed with exit code 1
error: build of ‘/nix/store/cdgrcrfv7445m4hspvvfwh7mnr0d0bxr-r-XML-3.98-1.4.drv’ failed
/run/current-system/sw/bin/nix-shell: failed to build all dependencies
Technical details

System: 16.09.901.9902430 (Flounder)
Nix version: 1.11.4
Nixpkgs version: "16.09.901.9902430"

I think b2113f78 would need backport to stable, and perhaps other changes. /cc @peti (author of most of late changes there)
There are a couple intriguing points for me:

specifying .dev in *build inputs shouldn't be required – I suppose it's due to some non-standard overriding done;
it seems like native and non-native inputs are switched – the expressions pass .dev etc. inputs as native and pkgconfig etc. as non-native.

For the first point, I expect using the new overrideAttrs instead of overrideDerivation would solve the problem, though that one is not on 16.09 (but IMO it's non-intrusive enough to get backported).

As a note, overriding nativeBuildInputs (or buildInputs) to include pkgs.libxml2 (without .dev) does not help.
myXML = pkgs.stdenv.lib.overrideDerivation pkgs.rPackages.XML (oldAttrs: { nativeBuildInputs = oldAttrs.nativeBuildInputs ++ [ pkgs.libxml2 ]; });

Well, the work-around used in the patch is to have it with .dev.

Oh sorry. However, adding pkgs.libxml2.dev in stable likewise does not help.

No longer an issue for me. Feel free to reopen if it hasn't actually been fixed.


Calling methods on generic parameters of const fns

TLDR: Allow
const fn add<T: Add>(a: T, b: T) -> T::Output {
    a + b
}

and
pub struct Foo<T: Trait>(T);
impl<T: ?const Trait> Foo<T> {
    fn new(t: T) -> Self {
        // not calling methods on `t`, so we opt out of requiring
        // `<T as Trait>` to have const methods via `?const`
        Self(t)
    }
}

cc @Centril @varkor @RalfJung @eddyb
This RFC has gone through an extensive pre-RFC phase in https://github.com/rust-rfcs/const-eval/pull/8
Rendered
Triage: pFCP comment: https://github.com/rust-lang/rfcs/pull/2632#issuecomment-481395091

One alternative syntax design that is not mentioned here is the question of const impl versus impl const.
There are strong arguments that const impl is the more consistent syntax, as it is consistent both with the existing practice of prefixing modifiers to impl (default impl, unsafe impl, etc.) and prefixing const to keywords to indicate const variants (e.g. const fn [and the hypothetical const trait]).
Conversely, as far as I'm aware, impl const is not consistent with any existing syntax in the language or this RFC.

(I don't like to start the discussion with syntax bikeshedding, but as mentioned in the original post, this RFC has already ungone significant design discussion and I'm satisfied it's close to the optimal conservative design.)

How do we want -> impl Trait and arg: dyn Trait to interact with const fn? If you must specify -> impl const Trait, does it also make sense to require arg: dyn const Trait? Both cases feel more existential-y and thus less tied to the function's type parameters, so I kind of lean that way for consistency.

I imagine it makes most sense to use the same (syntactic) rules for impl Trait and dyn Trait as for parameter bounds: that is, in const fn, an impl Trait actually means impl const Trait/const impl Trait (and similarly for dyn) and impl ?const Trait allows opting-out of constness.

I don’t think this has been mentioned before, but putting const before impl would be more consistent with other modifiers like unsafe and pub if we decided to do that.

I'm not sure why const Drop must be recursive on fields.  In my mental model, the body of drop doesn't have calls to the fields' drop impls inserted, but rather, the drop glue in a function body looks like:
Drop::drop(&mut local);
Drop::drop(&mut local.field_1);
Drop::drop(&mut local.field_2);

Requiring const Drop on fields increases churn when library A cannot write const Drop yet due to a non-const Drop in library B.  (so to use A in a const context, changes now need to be made to both library B and A in that order, instead of just B).

I don’t think this has been mentioned before, but putting const before impl would be more consistent with other modifiers like unsafe and pub if we decided to do that.

It has been mentioned before. This was even the original syntax. Reasoning for the change can be found at https://github.com/rust-rfcs/const-eval/pull/8#issuecomment-447560109
cc @scottmcm for consistency (not in semantics, but user expectations) I have slowly come back around to const impl Trait for Type being the best syntax.

Ultimately the location of const is really nothing but the color of the bikeshed.  impl const may be different from the other things, but it is not that hard to remember this "exception" when you have things like T: ?const Trait.
Conceptually, the keyword is attached to the trait.  I.e. it's not an impl const of a Trait, but rather an impl of a const Trait.

Conversely, as far as I'm aware, impl const is not consistent with any existing syntax in the language or this RFC.

I think that's looking at it from the wrong perspective.
It's not that it's (impl const) Trait, but that it's impl (const Trait), the same as you can impl (dyn Trait).  And that's consistent with something like struct Foo<T: const Default>(T); or similar.

But as far as I can tell, the Constness is not a property of the Trait, but of the impl, which is not the same for dyn, right?

It's not that it's (impl const) Trait, but that it's impl (const Trait), the same as you can impl (dyn Trait). And that's consistent with something like struct Foo<T: const Default>(T); or similar.

I agree with this in particular when viewed in light of effect systems. Moreover, impl const Trait also has composability benefits, e.g. arg: impl Add + ?const Clone + const Debug vs. arg: const impl Add + Cone + Debug are probably not the same semantically.

But as far as I can tell, the Constness is not a property of the Trait, but of the impl, which is not the same for dyn, right?

Traits can be seen as logical requirements and implementations are proofs that those requirements are satisfied. In that light, e.g. T: const Foo can be seen as a constraint that T satisfies const Foo and impl const Foo for MyT is a witness for that.

I don’t think this has been mentioned before, but putting const before impl would be more consistent with other modifiers like unsafe and pub if we decided to do that.

There was a huge amount of bikeshedding about this on chat, about a year ago, before work on this RFC even started. I forget the arguments, but perhaps someone can dig them up. (They may already have been mentioned here.)

@alexreg I think it was something along the lines of: const is a modifier on the trait not the impl. This means you could have const traits.
This means that you could have const trait bounds. For example, in the num-traits crate you have the trait Zero.
trait Zero {
    fn zero() -> Self;
}

which could be implemented as such using const traits
impl const Zero for u32 {
    fn zero() -> { 0 }
}

and used
fn test_zero<T: const Zero + PartialEq>(t: T) {
    assert_eq!(t == T::zero());
}

This would mean that T::zero() would be evaluated at compile-time, and inlined, but PartialEq doesn't need to be const, so it doesn't have be computed at compile time.

The RFC doesn't say anything about calling an fn that is const impl'd directly (without going through a generic parameter), as in:
impl const Zero for u32 {
    fn zero() -> { 0 }
}

...
const fn some_const_fn() {
    <u32 as Zero>::zero(); // or do I need to write <u32 as const Zero>?
}

I guess that this will also be supported, right?

Yes. That should definitely be supported. That part is actually very similar to the current inherent impls. I'll add it to the rfc

One thing I notice in this discussion is const impl (or a variant thereof). I have a question: What if I only wanted a subset of methods to be const? const impl wouldn't allow for that ability.

That's not possible with the current design, but certainly a possible addition in the future. With this RFC, if you have control of the trait, you can split up the trait into the "often const" parts and the "never const" parts by creating two traits. Then you can implement one part with impl const Trait1 and the other with impl Trait2
Future designs could simplify this by allowing methods in trait impls to be declared as const instead of declaring the entire impl as such.

Reposting my question from rust-lang/rust#44580, I was told this is a better place to ask.
Can a single function be conditionally const? For example, a function could have 2 signatures like:
const fn foo<A: const T>(x: T)  // `A` const implements `T`
fn foo<A: T>(x: A)              // `A` implements `T` normally

In this case, foo is const iff A: const T; if A does not const implement T, it still satisfies the bound but foo is no longer const. It is also important for the author to be able to specify any generic bound for more complex examples (ex. where A::Output : Bar). A great example of this is even simple arithmetic:
// This only accepts types that const implement `T`
const fn square_const<T: const Mul>(x: T) -> T {
  x*x
}

// This accepts types that implement `T` any way, but it is not const
// This function behaves identically to `square_const`
// But has a different signature and needs a different name
fn square<T: Mul>(x: T) -> T {
  square_const(x)
}

let a: u8 = 5;
let b: FooNumber = FooNumber::new();
square_const(a); // `u8` const implements Mul
square(b); // `FooNumber` implements `Mul` normally, so we need a separate function?

I feel strongly that there should definitely be a way to do this.
(Note: I have not seen this exact problem of conditionally const functions mentioned anywhere before, although it's possible that I missed it)

Note that the syntax you use is invalid per this RFC: const is not required before a trait bound in const fn.
const fn foo<T: Trait>() therefore requires T to const-implement Trait when called at compile-time. When foo is called at run-time, T is only required to implement Trait normally.
(There are suggestions to allow T: const Trait and T: ?const Trait, which allow greater expressivity in the future, but these are not included in the current RFC.)

@varkor

const fn foo<T: Trait>() therefore requires T to const-implement Trait when called at compile-time.

Small clarification on this: The requirement is that T to be substituted by a type U where impl const Trait for U { ... } when foo::<U>() is called in:

a const context,
inside another const fn that does not itself let U be generic in one way or the other.

If you have const call_foo() { foo::<MyType>() } then it is required that impl const Trait for MyType { ... } regardless of whether call_foo() is ultimately called in at compile time itself.

@varkor @Centril Thank you both, that answers my question. IMHO I think this is useful info to add to the "Generic bounds" section of the RFC. Due to the way the section is worded, I had assumed that it only was talking about generic parameters of types; now I see that it applies to functions too. I should have realized that, but I think that this could probably be clarified a bit. Additionally, @Centril's comment about when the type parameters are required to be const might be helpful to clarify. Other than that, I am pretty satisfied with the RFC, especially how it is compatible enough to in theory make everything const/pre-compiled except for nondeterministic functions (random, network, I/O, etc.).
The only thing I am a bit unsure about since now I see that probably a majority of functions can now be made const, is whether there should be some way to disable const evaluation for some edge cases (ex. for very computationally complex tasks or benchmarking). I don't really think there is a way to do that right now except wrapping the const function in a non-const function.

The only thing I am a bit unsure about since now I see that probably a majority of functions can now be made const, is whether there should be some way to disable const evaluation for some edge cases (ex. for very computationally complex tasks or benchmarking).

What reasons do you have for doing this? Note that const functions will not be called implicitly at compile-time, so you still have full control over when they are executed at compile-time.

@varkor

const functions will not be called implicitly at compile-time

I was under the impression that const functions would always be implicitly evaluated at compile-time when given const parameters. Does that only apply to variables declared with const rather than let? What about expressions? For example let result = foo(bar(baz)); where the variable baz and the function bar are both const; would bar(baz) be const or not?

I was under the impression that const functions would always be implicitly evaluated at compile-time when given const parameters.

That is incorrect. They will only be evaluated at compile time when called from a const context. For example, const FOO = foo() will evaluate foo() at compile time, but let bar = foo() will not, no matter how const its arguments are.

@rpjohnst Ok that makes a lot of sense, thank you for clarifying. One final question: if you were to disable all compiler optimizations (ex. -O0 for LLVM), is it guaranteed for future versions of Rust, that Rust will never evaluate const functions at compile-time? (again, this is a very very edge-case scenario, but still important to know).

@Coder-256 I'm hesitant to make such guarantees for all time; but e.g. if a function may panic and we move that to compile time it would be a compile time error which seems like an unlikely change. But we could prove that it will terminate and then execute it at compile-time... Why is the guarantee not to important?

@Centril It's 100% an edge case, so it's not super important for most code, but for example, benchmarking code would be a good place to have that guarantee. Although that may be out of the scope for this RFC since it would not break anything.
Also, sorry for the barrage of questions, but wouldn't this use of the const keyword for variables be a breaking change?:
const fn foo() {
  const result = bar();
  result
}

Here's what the current Rust book says:

constants may be set only to a constant expression, not the result of a function call or any other value that could only be computed at runtime.

However, if foo() is called from outside a const context, then wouldn't that statement be false for const result? Sorry if this is a bad question, I am just finding it difficult to figure this out myself.

In practice, at least for the near to mid-future, any non-const-based compile-time evaluation happens in LLVM, in the form of constant propagation and dead code elimination (and other optimizations).
If you need to guarantee that something happens at runtime (like for benchmarking), you thus cannot rely on anything to do with const or the optimization level. Instead you must rely on something like test::black_box. Work toward stabilizing this is happening in https://github.com/rust-lang/rfcs/pull/2360.

However, if foo() is called from outside a const context, then wouldn't that statement be false for const result? Sorry if this is a bad question, I am just finding it difficult to figure this out myself.

This is why the RFC went with the syntax const fn f<T: Trait> instead of T: const Trait- so that you could write your function foo by using that syntax:
const fn foo<T: const /* <- this is extra, beyond the RFC */ Trait>() {
    const result = T::bar(); // this is now allowed, even when `foo` is called from a non-const context
    result
}

@rpjohnst at what point, if ever, could const things be compile time evaluated even when bound with let instead of const? Because that is a totally non-obvious optimization difference that I'm sure will bite countless programmers.

@Lokathor All the time: https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=e91e27e7996a664fb38290bcc0c78207 (select “ASM” near the “Build” button)

Except that they specifically said in a comment above that such a thing isn't guaranteed. So it might work for any particular simple example, but that's not at all assured.

What exactly are you asking? We interpreted you question as "when is compile-time evaluation allowed in a let binding?" Are you instead asking "when could the language start guaranteeing compile-time evaluation in a let binding?"
If so, I suspect the answer is "never." We have const items for that, and we could potentially add const { .. } blocks, but there's no real need to add an additional guarantee that some_const_fn(some_const_val) is always evaluated at compile time.

Yeah I was asking about the second thing.
If
let a = some_const_fn(some_const_val);

Is ever different from
const c: whatever = some_const_fn(some_const_val);
let a = c;

Then that just seems like a big performance/ergonomics footgun.
The shorter, easier to type version should, all else being equal, always be just as performant as the long winded version. We don't need that guarantee immediately, but we should strive to attain that guarantee eventually.

We don't need that guarantee immediately, but we should strive to attain that guarantee eventually.

No, we should not, for the same reasons that we don't infer const-ness on functions. If you need the performance guarantee, you should request it, otherwise you could lose it without any indication that anything has changed. We should resolve any confusion people have by providing better documentation, not by changing the language in a way that makes programs harder to reason about.
It's also not straightfoward whether compile-time evaluation is always better for performance! The default choice of letting the optimizer decide is probably a safer bet- its heuristics can be improved without modifying program source.

@Ekleog I'm no expert, but I'm pretty sure that's because of optimization. Change Stable to Debug and you'll see what I mean. Optimization and const are different things, the former is automatic by the compiler and the latter is enforced by rust.
@rpjohnst Just to confirm, in my example, const result = bar() would actually produce varying results at runtime? I think this might be a better example:
const fn add_const_test<T: Add>(a: T, b: T) -> T {
  const result = a + b;
  result
}

fn foo() -> u8 {
  add_const_test(generate_random_u8() / 2, 5)
}

Even though we write const result = a + b, wouldn't that not be a compile-time constant when called from foo()? I'm pretty sure that's not allowed currently because declaring a variable with const means it has to be a compile-time constant if I'm not mistaken; but in this case, result cannot be determined at compile-time. Wouldn't that change the statement from the Rust book that I quoted before:

constants may be set only to a constant expression, not the result of a function call or any other value that could only be computed at runtime.

I don't think that it's a breaking change (since it is additive), but it does redefine existing usage of the const keyword for declaring variables. What I mean to say is: I think now we're defining const x to mean that x can only be set to the result of a const fn or some other const value, which is different from the old definition of const x, which I think was mostly meant only for primitives like pi or zero. I could be wrong though.

The question I gave an answer to was “When is the compiler allowed to compile-time-evaluate in non-const contexts?”

Note that that question is entirely off-topic for this RFC. You are discussing compiler optimizations here. The compiler will transform your program in arbitrary ways if it thinks that helps with performance, and it will promise not to change the programs observable behavior in the process.  Rust makes no promise of optimizations happening or not happening.
This RFC is not at all about optimizations. CTFE and const propagation are almost entirely unrelated, at least conceptually. Please let's stick to CTFE here, and discuss const propagation elsewhere.

They had a simple and honest misunderstanding about a question that was about compile-time function evaluation.

And then instead of clearing up the misunderstanding this derailed into more than 10 posts (and counting) discussing whether const propagation is guaranteed to happen or not, whether it can have adverse side-effects, ... all of which are off-topic.
And before this derails into a meta-discussion about this, I'll stop responding on that subject.

@rust-lang/lang 	can we move this to FCP? There has been no (on-topic) discussion that lead to nontrivial changes since a month. All the open questions are documented under the "Unresolved questions" section and should be addressed before stabilization, but should not block implementing the feature unstabily.

One possible syntax for trait default method bodies being const-capable would be const trait Foo { fn bar() { ... } }.

Also, I'm a bit confused about the use of Cell as an example, as it doesn't make sense to me to allow Cell in a const fn. That's not directly an issue with this RFC, though.

If it's a const Cell then there's no reason to disallow it.

@Lokathor This seems like something we should discuss in a separate issue rather than this one; I can easily see how this would balloon into a long discussion.

I removed all mentions of Cell from this RFC. It's not relevant to the RFC and was just chosen as an example.

@rfcbot fcp merge
This RFC has undergone significant development work, first inside a const fn-focused working group and now through the RFC process. It unblocks a significant expansion of const fn which will allow more expressive use of const generics, one of the features cited as a "long-standing feature" to finish in this year's roadmap. The current design has reached a stable point in discussion and is ready for full lang team review.

All the open questions are documented under the "Unresolved questions" section and should be addressed before stabilization, but should not block implementing the feature unstabily.

The final syntax of this feature, as brought up previously, should explicitly be mentioned as an unresolved question and should be revisited before stabilisation.

This might be the wrong place to ask (and sorry if I missed that this has already been discussed somewhere), but how does this RFC affect associated constants? (not to be confused with associated types). It seems that now they would do the exact same thing as const fns, at least in const contexts? Maybe removing/deprecating associated constants should be considered, in favor of const fns via const Trait. For example:
trait Foo {
    const BAR: usize;
}

trait Baz {
    fn qux() -> usize;
}

struct FooStruct {}
impl Foo for FooStruct {
    const BAR: usize = 123;
}

struct BazStruct {}
impl const Baz for BazStruct {
    fn qux() -> usize { 321 }
}

// Now your function can require a generic `Foo` or `const Baz`

The reason I suggest the 2nd syntax (Baz) over the 1st (Foo) is that method bodies are more flexible/readable, but IMO it is worth choosing either one of the two syntaxes because they seem a bit redundant to me. Correct me if I'm wrong about the two styles being redundant.
This also has implications with the question of const trait methods. One possiblilty is phasing out associated constants in favor of const methods; this might be a pretty good use case for const trait methods, or at least something to consider. I do understand the argument against const trait methods (splitting into multiple traits), but I just don't think it took associated constants into consideration. That's not to say that associated const trait methods are per se the best way to handle this (I am still undecided about the best choice with these points in mind), but at least IMO this should be reevaluated with associated constants in mind. Any thoughts?

Associated constants are not redundant,since const fn used outside of a const context (like the value assigned to a const item*) are not guaranteed to be run at compile-time,while const items* have to run at compile-time.
*By const item I mean const IDENT:Type=expr,not including const fn.

Plus, even if we did choose to do all of the language changes needed to make associated consts technically redundant, and even if backwards compatibility weren't a concern, I think we'd still want associated consts as a syntactic sugar rather than requiring everyone to add parenthesis to the many, many associated consts that wouldn't benefit from being functions.

Changing the behavior of parameterless const fn so that they are always evaluated at compile-time,this is a pretty important property of const items.

While we obviously can't change const to mean this now, and the current meaning is a far more practical default, I think I saw someone somewhere propose introducing a separate feature for "always compile-time" stuff with a strawman keyword like constonly. Unfortunately I can't seem to find any trace of it now. Does anyone else remember seeing this?

The main part of this RFC concerns the addition of const modifiers on impls as a prerequisite for allowing you to instantiate generic const fns at const time: I think this is a good idea. One thing we've regretted often is that trait definitions don't declare explicitly that they are object safe, introducing a backwards compatibility hazard. One thing I wish is that we could have something like dyn trait declarations (which also might be a hook for doing some more interesting trait object things too). I think it's the right choice to have explicitly const impls, instead of "inferring" constness and having another backwards compatibility hazard.
I have a few concerns, however.
@rfcbot concern const-position
I think this should be written const impl<T> Trait rather than impl<T> const Trait. I don't agree that the semantics suggest it should be written the way it is in the RFC - an argument could equally well be made that this is a modifier of the entire implementation, and therefore belongs before the impl (conceptually modifying the entire implementation declaration) rather than on the trait, which is only one part of the declaration. I also think users just strongly expect modifiers on items to come at the beginning of the declaration, the way that other modifiers like pub, unsafe, async, and const come there right now. The duality issue is an interesting point, but we've already established a strong precedent to treat both sides of the duality the same by having both unsafe impl and unsafe fn.
@rfcbot concern question-const
This is a deeper concern. I'm not convinced that T: ?const Trait is a well-enough motivated change to the language to include, and I'd prefer to add just const impl without this other addition. (While the justification for this change is included in the RFC, I don't know why it has been put forward now instead of being a future extension like the many extension proposals the RFC mentions).
I want to be clear about my larger position: I am dubious of the benefit of adding a lot of deep annotation heavy integrations between const fn and the generics system. I think this is something that will make people feel an obligation to properly annotate all of their generic parameters so that they propagate constness as permissively as possible, but that this will create too much burden on the community in a variety of ways:

Library authors will have to figure out if they can actually guarantee constness backwards compatibly, which will take their time and attention.
The ecosystem will suffer with version churn when libraries mistakenly mark things const and then need to
We will continue the trend of dumping huge amounts of type information on new users trying to understand the API of their libraries, much of which isn't relevant to them.

In other words, I think its important to remember that const annotations are not a socially zero cost abstraction - there is a global social cost to these extensions - and they should only be added with strong motivation. I think that strong motivation exists for allowing const fns to be generic and use trait methods, but I don't see the strong motivation for adding the syntactically complex ?const bound-modifier for what seems to me like a fairly niche use case (functions that bound generics but never actually use the bounds' items).
In a more concrete fashion, I feel a sense that the design work on constness - like many parts of our type system - is getting pretty far ahead of the real use experience. I'd like to get more a lot more motivating experience from people using const fn that will identify the most significant pain points, then start considering which of these extensions we will add. That is to say, at a high level: I don't expect (or prefer) that we will ever add a full-fledged effect system to Rust, a very pertinent question is how far toward that we will go before we stop, and I think we need more real world experience to feedback into that question.

I'm not convinced that T: ?const Trait is a well-enough motivated change to the language to include, and I'd prefer to add just const impl without this other addition.

On this note: one related issue is what to do (in the long run) about const fn foo(x: fn(T) -> U). This has actually recently come up in the Future discussion (in the RawWaker constructor). As we can clearly see there, the function passed as an argument does not have to be const, and can hence not be called inside the const fn.
This is a very similar situation to calling a trait method, so it might be a good idea to have some symmetry here. However, with this RFC, we do not!  In the syntax this RFC proposed for trait bounds, foo as above would implicitly require a const fn in const context, and if it is a constructor then foo should be written const fn foo(x: ?const fn(T) -> U).  (Maybe) unlike the case for traits, I think this is well-motivated -- but we cannot actually do this due to backwards compatibility.
As the RFC mentions, a function pointer that can actually be called would have to be written const fn foo(x: const fn(T) -> U) (this is listed as a future possibility).  I suppose when called in run-time context, the const requirement is just ignored. (Or maybe not? It is at least conceivable that unsafe code would rely on some function being const. This relates to effect systems.)
The same applies to dyn Trait; const fn foo(x: &dyn Trait) can already be written today and can be called with non-const implementations of Trait; hence foo cannot call x's trait methods.
At the very least, I think this inconsistency between our two mechanisms of "abstracting over code" (statically with traits and dynamically with function pointers/trait objects) should be called out as a drawback.  Ideally, they would be made consistent -- but given the backwards compatibility constraints, the only way to do that seems to be to require const fn foo<T: const Trait>(x: T). This removes the need for ?const, as that would be the default -- but it adds a lot of syntactic overhead, as most trait bounds of const fn will have to explicitly be made const. (And if we want to maintain the option of relying on const as absence of some effects, even this would not be a good choice.)

In the syntax this RFC proposed for trait bounds, foo as above would implicitly require a const fn in const context

I don't think this is the case. fn foo is a function pointer type, not a trait, so it's unaffected by the context in which it appears. If you want to call foo, we need a const fn pointer, as you say.
I don't think there's an issue here with symmetry: there's just a difference between the expressiveness of types and traits with respect to const (the changes here are forwards compatible with expanding the expressiveness of the types later).

the only way to do that seems to be to require const fn foo<T: const Trait>(x: T)

This syntax makes it impossible to distinguish functions foo that require T to const-implement Trait at run-time and those that require it to implement it normally at run-time, so it's not just syntactically awkward — it's overly restrictive.

(Or maybe not? It is at least conceivable that unsafe code would rely on some function being const. This relates to effect systems.)

I don't think there are justifiable use cases to force functions being const. Any state at run-time should be no more restrictive than at compile-time.

I don't think this is the case. fn foo is a function pointer type, not a trait, so it's unaffected by the context in which it appears. If you want to call foo, we need a const fn pointer, as you say.

I was just saying, if the syntax was consistently extended to function pointer types, then this is what would happen.

I don't think there's an issue here with symmetry: there's just a difference between the expressiveness of types and traits with respect to const (the changes here are forwards compatible with expanding the expressiveness of the types later).

There is a symmetry break here: expressing the same thing ("may be called in const context with a non-const-safe instance") is written fn foo<T: ?const Trait>(x: T) once, and fn foo(x: &dyn Trait) the other time.  In on case one has to explicitly request "can be called in const context without restrictions (because item does not get used)" by writing ?const, in the other case that is the default.
How is that not an issue with symmetry?

I don't think there are justifiable use cases to force functions being const. Any state at run-time should be no more restrictive than at compile-time.

Even as someone mostly opposed to adding the complexity of an effect system to Rust, I have to strongly disagree with that statement.  This is a way to restrict what the function can do, and that is always extremely useful when reasoning about higher-order code.
For example, one could write a function fn sort(data: &mut [i32], compare: const fn(i32, i32) -> Ordering) that would be safe to call while relying on the fact that compare will always return the same result when given the same integers.  sort could be UB if compare is inconsistent, but that would be fine because there would be no way to call sort that way (in safe code).
We could decide that making Rust support that kind of reasoning has too high costs elsewhere, but IMO there is no denying the usefulness of this.

I think this should be written const impl Trait rather than impl const Trait.

As I have stated frequently, I don't have a strong opinion there and will essentially choose whatever gets this RFC merged ;)

This is a deeper concern. I'm not convinced that T: ?const Trait is a well-enough motivated change to the language to include

This is actually motivated by two things that I should have mentioned in the RFC, but simplified it to constructors.

Drop impls need to have the same generic bounds that the type declaration has. If you want to have a const Drop implementation, all bounds must be const Trait on the type and the Drop impl, even if the Drop impl does not use said trait bounds.

The standard library is full of cases where you have bounds on a generic type's declaration (e.g. because the Drop impl needs them). Any method (or its impl block) on that generic type will need to repeat those bounds. Repeating those bounds will restrict the impls further than actually required. We don't need const Trait bounds if all we do is store values of the generic argument type in fields of the result type.

I believe that removing ?const will make this RFC significantly less useful to the community than having the full RFC. The point wrt const fn pointers has already been made above. There is no way to stabilize a const fn wrapper around RawWaker::new on stable code without having a way to opt out of the constness of a function pointer in a const fn's argument. The same reasoning applies to trait bounds. E.g. Iterator methods could never become const fn, because F: FnOnce(A) -> B is not a legal bound without restricting F to having to be const fn. Without an opt-out like ?const you are in fact creating both bad churn and fear of constification in the ecosystem, because users have no way to create a const fn with generic arguments without restricting users of that const fn to passing const Trait bounds. This will likely lead to both too-eager application of const fn where the function becomes unusable in many cases and too little application of const fn in more conservative crates where const fn would be ok right now, but "unsure of future changes".

There is a symmetry break here: expressing the same thing ("may be called in const context with a non-const-safe instance") is written fn foo<T: ?const Trait>(x: T) once, and fn foo(x: &dyn Trait) the other time.

Ah, I had skimmed over the part about dyn Trait. I think the point about symmetry here is a good one: one would expect dyn Trait to require the type to const-implement Trait in a const fn (following "any bound in a const fn is treated as const").
I think this is extremely counter-intuitive. Can we make dyn Trait act like a generic trait bound instead (i.e. be const in a const fn)? dyn Trait is unstable in const fn at the moment, isn't it, so we can still make this change?

that would be safe to call while relying on the fact that compare will always return the same result when given the same integers

I don't believe we make this guarantee (i.e. determinism of const fn). I really think we should avoid conflating constness and purity. I agree that hypothetically it may be desirable to enforce purity (in the context of an effect system), but I think this should be viewed as a separate concern.

If you want to have a const Drop implementation, all bounds must be const Trait on the type and the Drop impl, even if the Drop impl does not use said trait bounds.

There are no const Trait bounds... do you mean Trait (implicitly const in const context)?
This is actually why I asked about const Trait bounds, they came up so often in discussion I thought they were a thing, so I was a bit surprised now to see that they are not.

There is no way to stabilize a const fn wrapper around RawWaker::new on stable code without having a way to opt out of the constness of a function pointer in a const fn's argument. The same reasoning applies to trait bounds.

Absolutely. That's why I am arguing that the way to do this should be consistent. For function pointers, the "opt out" is actually the default.

I think this is extremely counter-intuitive. Can we make dyn Trait act like a generic trait bound instead (i.e. be const in a const fn)? dyn Trait is unstable in const fn at the moment, isn't it, so we can still make this change?

That would make it inconsistent with function pointers though, which is just as counter-intuitive.
Also, they are not unstable; this compiles:
const FOO: &dyn std::fmt::Debug = &13;

I don't believe we make this guarantee (i.e. determinism of const fn). I really think we should avoid conflating constness and purity. I agree that hypothetically it may be desirable to enforce purity (in the context of an effect system), but I think this should be viewed as a separate concern.

We do not currently make it, but I can also not conceive of anything we would (want to) let const fn do that would break this guarantee -- hence it seems premature to close this door forever.  I think breaking this guarantee would only be possible if we let const fn mutate global state, and that is inherently incompatible with the idea that a const FOO: Type = foo(); gets evaluated at compile-time but should behave exactly as if the definition was inlined at every use site.

For function pointers, the "opt out" is actually the default.

Right now they are unstable. With this RFC they stay unstable. The future extension suggested in this RFC is ?const fn() as not callable const fn pointer and just fn() as callable const fn pointer

Can we make dyn Trait act like a generic trait bound instead (i.e. be const in a const fn)? dyn Trait is unstable in const fn at the moment, isn't it, so we can still make this change?

That was always my intention, I should add that to the future changes. This RFC does not make any changes to dyn Trait arguments to const fn.

I need to review the changes to Drop more in-depth; until I do so, I'll leave
@rfcbot concern centril-needs-to-review-more-in-depth-again
@withoutboats

I think this should be written const impl<T> Trait rather than impl<T> const Trait. I don't agree that the semantics suggest it should be written the way it is in the RFC - an argument could equally well be made that this is a modifier of the entire implementation, and therefore belongs before the impl (conceptually modifying the entire implementation declaration) rather than on the trait, which is only one part of the declaration.

This does not work well with:
fn foo<T: const Bar>() {}
//        ---------- The bound is a logical unit.

fn foo(arg: impl Bar + const Baz) {}
//               ---   ---------
//  Each of these are different parts of the bound and `const` is a property of `const Baz`.

fn foo() -> impl Send + const Bar {}
//               ----   ---------
// Same here.

Conceptually, impl const Trait communicates that you are implementing a const version of Trait. This fits well with the snippets above, but const impl Trait does not fit well with those snippets.

I also think users just strongly expect modifiers on items to come at the beginning of the declaration, the way that other modifiers like pub, unsafe, async, and const come there right now. The duality issue is an interesting point, but we've already established a strong precedent to treat both sides of the duality the same by having both unsafe impl and unsafe fn.

I expect so too, but the expectation is in my view misleading especially when unsafe impl is considered.
The semantics of unsafe impl are that the documented invariants of the unsafe trait are upheld. This is unlike impl const Trait which enforces that each function within the implementation adhere to the rules of const fn. There is no similar polymorphism or "versions" of the trait; there's just unsafe impl which all implementations of an unsafe trait must use. In other words, you cannot write impl Send .... Writing impl unsafe Trait { ... }  and fn foo<T: unsafe Trait>(...) would be more akin to what impl const Trait { ... } and fn foo<T: const Trait>() would be doing. Here, unsafe Trait would denote a version of the trait with unsafe functions. However, it is not clear that unsafe Trait is useful because of the half-effect nature of unsafe.

This is a deeper concern. I'm not convinced that T: ?const Trait is a well-enough motivated change to the language to include, and I'd prefer to add just const impl without this other addition.

As @RalfJung and @oli-obk noted, the notion of T: ?const Trait is already used by RawWakerVTable::new in the form of #[rustc_allow_const_fn_ptr]. When I agreed to the introduction of this hack attribute, it was because I was under the impression that everyone agreed it was a temporary hack and that we would find a syntax for supporting the semantics of T: ?const Trait in some fashion. I will not agree to having this hack in a permanent fashion without any hope of eventual consistency.

(While the justification for this change is included in the RFC, I don't know why it has been put forward now instead of being a future extension like the many extension proposals the RFC mentions).

Because it is already desired by users, e.g.:

https://github.com/rust-lang/rust/issues/24111#issuecomment-414317077
https://github.com/rust-lang/rust/issues/24111#issuecomment-450766025

Moreover, some of the future work noted in this RFC should be implemented in different feature gates as part of the experimentation to make sure that the future work actually works with the base of this RFC. I discussed this with @oli-obk in Berlin but it never made it into the RFC (I don't recall what parts it was exactly...). Aside: @oli-obk, can you please make a note of this in the RFC?

I want to be clear about my larger position: I am dubious of the benefit of adding a lot of deep annotation heavy integrations between const fn and the generics system. I think this is something that will make people feel an obligation to properly annotate all of their generic parameters so that they propagate constness as permissively as possible, but that this will create too much burden on the community in a variety of ways:

The ecosystem will suffer with version churn when libraries mistakenly mark things const and then need to make a breaking change to unconst them later on.

As far as I know, it is not a breaking change to go from T: Trait to T: ?const Trait. This is a loosening of a restriction. The breaking change would be to go from T: ?const Trait to T: Trait. Having the latter be the shorter one nudges users towards choosing T: Trait which is almost always right. ?const Trait is mostly useful when dealing with marker traits and constructors.

and I think we need more real world experience to feedback into that question.

The best way to retrieve real world experience is to actually test it out on nightly. I intend to treat this RFC quite experimentally.
@oli-obk

The same reasoning applies to trait bounds. E.g. Iterator methods could never become const fn, because F: FnOnce(A) -> B is not a legal bound without restricting F to having to be const fn.

Huh? Surely Iterator's methods, e.g. .map(mapper) needs to be const-polymorphic. Otherwise we'll never be able to pervasively constify libcore and large parts of the ecosystem.
@RalfJung

(Maybe) unlike the case for traits, I think this is well-motivated -- but we cannot actually do this due to backwards compatibility.

The same applies to dyn Trait; const fn foo(x: &dyn Trait) can already be written today and can be called with non-const implementations of Trait; hence foo cannot call x's trait methods.

This is not true. We added restrictions on function pointers, trait objects, and impl Trait so that we could backwards compatibly use const fn foo(x: fn()).
const fn foo(x: fn()) {}
const fn bar(x: &dyn Iterator<Item = u8>) {}

results in:
error[E0723]: function pointers in const fn are unstable (see issue #57563)
error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable (see issue #57563)

Also, they are not unstable; this compiles:
const FOO: &dyn std::fmt::Debug = &13;

You are conflating const items and const fns.
@varkor

I don't think this is the case. fn foo is a function pointer type, not a trait, so it's unaffected by the context in which it appears. If you want to call foo, we need a const fn pointer, as you say.

What is the rationale for having it be unaffected? const is a modifier on the context, and so it stands to reason that it affects traits, trait objects, impl Trait and function pointers in a similar fashion. In my view, it would be wholly inconsistent to have const fn foo<T: Clone>(x: T) and const fn foo(x: const fn() -> u8) together. To be consistent, you'd have const fn foo<T: const Clone>(x: T) and const fn foo(x: const fn() -> u8) which would require a const implementaton rather than be polymorphic.

This syntax makes it impossible to distinguish functions foo that require T to const-implement Trait at run-time and those that require it to implement it normally at run-time, so it's not just syntactically awkward — it's overly restrictive.

I don't think there are justifiable use cases to force functions being const. Any state at run-time should be no more restrictive than at compile-time.

For the same reason you want const fn foo<T: const Add>(...) to force implementations const Add you also want const fn foo(x: const fn() -> u8) to force function pointers to const fns. This is both useful to enforce determinism statically and for being allowed to call x and T::add inside a const context within foo. The latter is important for interacting with const generics.
@RalfJung

We could decide that making Rust support that kind of reasoning has too high costs elsewhere, but IMO there is no denying the usefulness of this.

:100:

I don't believe we make this guarantee (i.e. determinism of const fn). I really think we should avoid conflating constness and purity. I agree that hypothetically it may be desirable to enforce purity (in the context of an effect system), but I think this should be viewed as a separate concern.

I don't think we'll ever guarantee referential transparency for all (only some) const fns due to &mut T but that is something other than determinism which I think we should enforce for all const fns because it is hugely surprising not to.

I was just saying, if the syntax was consistently extended to function pointer types, then this is what would happen.

That would make it inconsistent with function pointers though, which is just as counter-intuitive.

On second thoughts, I agree. Function pointers should be treated in the same way. They're unstable in const fn at the moment too, so hopefully we can change this too?

Also, they are not unstable; this compiles:

This requires the constant to const-implement the trait, though, because it's a const, right? So we should still be able to change this without fallout.

Right now they are unstable. With this RFC they stay unstable. The future extension suggested in this RFC is ?const fn() as not callable const fn pointer and just fn() as callable const fn pointer

They are unstable as function arguments (I didn't know that, good call), but stable as types of const.  You want to interpret these differently?

So I retract what I said about inconsistency with function signatures, I was not aware that this is still unstable (nice foresight!). But then pretty much the same concern arises with const items. It seems really strange that this should not be legal:
const fn foo(x: fn()) {
  // for consistency with trait bounds, this will likely mean x is const-callable.
  x();
}

const X: fn() = /* ... */;
const Y: () = foo(X); // error

X is a constant of type fn() and yet we cannot call a const fn with argument type fn().
This strikes me as somewhat less surprising than if the inconsistency was within the function signature, but still as surprising and something worth calling out in the "Drawbacks" of this RFC -- because this RFC is where we commit to that choice (assuming symmetry for when this gets extended to trait objects and function pointers).

@Centril:

Conceptually, impl const Trait communicates that you are implementing a const version of Trait. This fits well with the snippets above, but const impl Trait does not fit well with those snippets.

I think it depends on whether you take a declarative or imperative reading. Imperatively, const impl Trait says "implement Trait in a const fashion", in which case you should be able to use a const Trait bound. I think the benefits of const impl outweigh the small gain in symmetry for impl/bounds. (I make this point in slightly more detail here.)

You could seemingly disambiguate some concerns @RalfJung noted with some notion of "const lifetime" that clarified the relationships of input constness to output constness, which sounds unacceptable.  I have not understood from the above discussion if this is now known to be overkill, but maybe yes because the const fn should be pure too?
In practice, I'd kinda expect a const fn not to use any pointers passed in, but to pass them into whatever it constructs.  I think means const fn foo(x: ?const fn()) sounds like the intuitive default, and const fn foo(x: const fn()) the exception.

@burdges I am confused. What I said has nothing to do with lifetimes?

Right now they are unstable. With this RFC they stay unstable. The future extension suggested in this RFC is ?const fn() as not callable const fn pointer and just fn() as callable const fn pointer

There are alternative designs that don't involve this syntax:

Allow fn pointers to be passed to const fns but not called. Add const fn pointers which can be called in const contexts.
Allow fn pointers to be cast to const fns but not called and never introduce any syntax for calling fn pointers in a const context.

At a first glance, either of these solutions would seem more preferable to me than ?const fn if the ?const syntax were to have no other uses. That is, you can not draw a clear line from RawWaker to ?const fn to ?const Trait; the connection is not a direct implication.

Allow fn pointers to be passed to const fns but not called. Add const fn pointers which can be called in const contexts.

If you use const fn for this purpose then you have to give up on either of these 2 semantics:

const fn() is an effect polymorphic function pointer wrt. the const restriction (this is what T: Trait means with this RFC, so you give up symmetry, and what fn() is in the future work section).
const fn() must be passed a function pointer to a const fn (this is what T: const Trait and const fn() means in the RFC, https://github.com/oli-obk/rfcs/blob/const_generic_const_fn_bounds/text/0000-const-generic-const-fn-bounds.md#explicit-const-bounds).

The way this RFC is formulated you give up on nothing.

Allow fn pointers to be cast to const fns but not called and never introduce any syntax for calling fn pointers in a const context.

Casting fn pointers to const fns would need to be an unsafe { ... } operation because you can sneak impurity into const fns this way. It seems like a rather strange way to support the use case.

FWIW, I think RawWakerVTable needs zero interaction with this RFC, and that some of this discussion around fn pointers for the sake of RawWakerVTable is an unnecessary waste of everyone's time.
As I wrote in https://github.com/rust-lang/rust/pull/59739#discussion_r272793688, we can have RawWakerVTable::new work at compile-time and allow promotion for it, even if we don't allow fn pointers in const fn nor promote calls to const fns, because we can rely on "callable" pattern aliases instead (https://github.com/rust-rfcs/const-eval/issues/19#issuecomment-472799062).

const fn() must be passed a function pointer to a const fn (this is what T: const Trait and const fn() means in the RFC

Note that this RFC does not suggest supporting const Trait or const fn(). It merely leaves the door open for that being a future extension.

Allow fn pointers to be passed to const fns but not called and never introduce any syntax for calling fn pointers in a const context.

This is actually a workable alternative. Though it would mean that any const fn that is supposed to take a function pointer becomes generic over the function type:
// what would have been
const fn foo(f: fn()) { f() }
// in this RFC, becomes
const fn foo<T: Fn()>(f: T) { f() }

we can rely on "callable" pattern aliases instead (rust-rfcs/const-eval#19 (comment)).

The issue with relying on pattern aliases is that I'd find it very surprising if we had pattern aliases that are not valid const fn.

you can not draw a clear line from RawWaker to ?const fn to ?const Trait; the connection is not a direct implication.

The argument for this connection is symmetry of the features. The alternatives discuss various reasons why explicit T: const Trait are undesirable for this RFC. Ending up with const fn pointers in the future would be very surprising if we go with T: Trait as proposed by this RFC.

I'd like to get more a lot more motivating experience from people using const fn that will identify the most significant pain points, then start considering which of these extensions we will add.

I made it explicit in the RFC that ?const is a separate feature that will be implemented in parallel with trait bounds on const fn, but stabilized separately.

That is to say, at a high level: I don't expect (or prefer) that we will ever add a full-fledged effect system to Rust, a very pertinent question is how far toward that we will go before we stop, and I think we need more real world experience to feedback into that question.

const fns with bounds are in use on nightly since 1.0. The current const_fn feature gate does not allow calling methods on these trait bounds. Stabilizing just the feature that noone uses so far (because it's not implemented) and removing the feature that is in use on nightly (and thus noone complains about loudly) seems slightly odd.

@withoutboats are you ok with splitting the feature gate as per the rationale above? (const_fn feature gate users already having ?const implicitly and changing the impl to implicitly requiring any bounds to have an impl const Trait without an (unstable) fallback would probably be very uncool)

Regarding the Future Work section on const function pointers, it notes they are "illegal before and with this RFC", yet I discovered that the following actually does compile and work as expected with the const_fn feature:
#![feature(const_fn)]

struct Foo<T> {
    x: fn()->T
}

impl<T> Foo<T> {
    const fn new(f: fn()->T) -> Self {
        Foo { x: f }
    }
}

const FOO: Foo<i32> = Foo::new(|| 42);

fn main() {
    assert_eq!((FOO.x)(), 42);
}

Is it a bug that this works currently, or does this represent a reasonable subset of const_fn (something to do with closure coercions to function pointers that never actually get called in a const context?) that isn't actually blocked on waiting for the aforementioned future work? If it is reasonable to stabilize, what would it take and what is it currently blocked on?
(If anyone's curious where I ran across this, it's in my macro-free replacement for the lazy_static crate: https://gist.github.com/bstrie/e05b14f66017bd7560e3cfd2df8750d9)

@bstrie you can't make a const fn() -> T, similarly you cant call those function pointers. Just passing them around is fine, normal function pointers are alao just values.

@KrishnaSannasi The problem is that by removing the feature flag, the code fails to compile with:
Compiling playground v0.0.1 (/playground)
error[E0723]: function pointers in const fn are unstable
 --> src/main.rs:8:18
  |
8 |     const fn new(f: fn()->T) -> Self {
  |                  ^
  |
  = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
  = help: add `#![feature(const_fn)]` to the crate attributes to enable

...while furthermore the linked issue ultimately leads one here. If merely passing around function pointers is supposed to be fine, then what's left to stabilize here that is triggering the feature flag?

I think the main open question there is the concern whether we should also have const fn new(f: const fn() -> T) or maybe const fn new(f: const? fn() -> T).
This is further explained in the proposed RFC.

@RalfJung I don't quite see how that would present a backwards compatibility hazard in this case; even if we were to introduce const fn parameters someday, a const function seemingly doesn't need to care about whether its function pointer parameters are const if those function pointers are never actually invoked in a const context. Am I wrong in that the same check that today rejects fn foo() {} const fn bar() { foo() } would suffice to reject such cases while still allowing const functions to perform other operations on function pointers, such as in this case storing it in a struct? Potentially requiring ?const on such cases would seem inconsistent unless, say, we also wanted to require everyone to change every struct Foo(fn()); that is referenced in a const context to struct Foo(?const fn());, which starts to seem a bit unreasonable (for instance, now structs that aren't defined with const in mind are now accidentally unusable by any const function for no good reason).

Basically design work hasn't been done yet for function pointers (and basically exactly the same concerns apply to dyn Trait as well). Stabilizing before doing the design work seems very risky because it contsrains the design process. Stabilizing little pieces early has the advantage that those little pieces can be used earlier; it has the disadvantage that the end result might look like stitched together from a dozen incoherent pieces because by the time we actually knew what we are doing (by getting a proper overview over all of the involved tradeoffs), a lot of seemingly little decisions have already been made.

To be able to know that a T can be dropped in a const fn, this RFC proposes to make T: Drop be a valid bound for any T, even types which have no Drop impl

Will this affect the resolution of where clauses in blanket impls? If so, it will break this code:
struct NotDrop(String) // has drop glue, but no Drop impl

trait MyTrait {}
impl<T: Drop> MyTrait for T {}
impl MyTrait for NotDrop {}

Currently, this code compiles. In fact the pin-project crate relies on this in order to prevent users from writing an explicit drop impl (drop glue does not matter)

Oh... that would be a breaking change indeed. We could just make that the behaviour in const impls and const fns, though that may be too surprising. Also there's apparently a use case for Drop bounds... so
Back to having a special kinda bound? A Droppable auto trait?

That sounds good to me. While it might be slightly confusing to have Drop and Droppable, I think it's better than giving Drop a different meaning in const contexts.

(drop glue does not matter)

Could you explain why drop glue does not matter ?
Also if the NotDrop type is in your crate, and you don't implement Drop for it, it is a bit unclear to me how users of your crate could implement Drop for it.

@gnzlbg that code is from a macro, so so the type is declared in a user's crate.
Context: https://github.com/taiki-e/pin-project/

I see, damn, then that's clever. AFAICT there are no other ways of actually enforcing such a constraint in Rust (e.g. the module privacy boundary doesn't prevent it, so using the trait system for that seems reasonable).

Potentially relevant prior discussion about Drop bounds on IRLO: Can we deprecate 'T: Drop' trait bounds?, Fixing the Drop trait bound

Is there a blocker on merging this? When the feature finally becomes stable, it would be very helpful for a lot of crypto code that I write/rely on.

I need to come up with a new solution for Drop bounds (or revert to a previous one) and there are a couple of blockers registered in the FCP comment https://github.com/rust-lang/rfcs/pull/2632#issuecomment-481395097
cc @Centril @withoutboats (registered blocks)
cc @scottmcm (unchecked box)

Awesome, thanks for the update!

We discussed this in our meeting today. There weren't that many people in attendance. Nonetheless we felt comfortable concluding a few things:

This design has far-reaching implications and we probably aren't going to be able to work them all out in advance. We probably need to start working through the implementation.
This seems like a great fit for the "const eval" project group, and we should schedule a dedicated meeting to talk over the scope of such a group in more detail.
Similarly, it would be worth scheduling a meeting to talk out this RFC in more detail and make sure the lang team is understanding it well.
We feel comfortable going forward with experimentation on nightly even in advance of this RFC being accepted, as long as that experimentation is gated.

If anyone is interested in tracking the experimental implementation progress, there's a zulip thread in https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/topic/trait.20bounds.20on.20const.20fn and a very high level plan laid out by me at hackmd https://hackmd.io/@oli-obk/generic_trait_bounds_on_const_fn

@oli-obk I'm gonna start on the parsing aspect of this.

Turns out I cannot find the time to review the drop parts more in depth. But in either case, we're proceeding with experimentation right now so this may all become moot anyways. Let's just see what the experimentation results in.
@rfcbot resolve centril-needs-to-review-more-in-depth-again

Am I correct in understanding that this issue being stabilized will resolve this error?
error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable

Perusing the meta tracking issue, it was difficult to understand which specific portion of const_fn I should be following.

Perusing the meta tracking issue, it was difficult to understand which specific portion of const_fn I should be following.

you'll want to follow https://github.com/rust-lang/rust/issues/67792

I'd like to get more a lot more motivating experience from people using const fn that will identify the most significant pain points, then start considering which of these extensions we will add.

If it helps, I just filed rust-lang/const-eval#56 documenting one particular real-world use case, interoperating between Rust traits and an FFI plugin system that asks you to provide a struct with callbacks. Specifically, we need this for writing Rust code that implements Linux kernel files/filesystems/devices/etc., which use "operations structs" that are basically traits in C.
(This looks like it might be the same use case as Tock and possibly also the same use case as the lazy_static proposal above. I know this use case would also be helpful for various userspace plugin systems too - Heimdal comes to mind, and the maintainers are interested in using Rust.)
I think that case might be addressed by ?const, but I'm not totally sure. It does work on nightly currently, but it would be helpful to be able to use stable Rust when proposing to add Rust to the Linux kernel.

Related to const bounds, has thought been given to blanket impls?
e.g. right now in core there is a blanket impl<T, U> Into<U> for T where U: From<T>
Ideally if I implement const From, the blanket Into will also be const. This presumably wouldn't be automatic, but I guess something like this could be written?
impl<T, U> const Into<U> for T where U: const From<T> {...}
impl<T, U> ?const Into<U> for T where U: ?const From<T> {...}

Perhaps there could be some way of condensing this down to one impl, and signifying somehow that the const-ness is sticky? I feel like swapping the prefix/suffix-ness of the ? would probably be confusing, but something like:
impl<T, U> const? Into<U> for T where U: const? From<T> {...}

@illicitonion This section reads to me as "the constness of the impl depends on the constness of the impls for the type parameters":
https://github.com/oli-obk/rfcs/blob/const_generic_const_fn_bounds/text/0000-const-generic-const-fn-bounds.md#runtime-uses-dont-have-const-restrictions

Is anything happening with this?

There was a new PR for the next step just 10 hours ago: https://github.com/rust-lang/rust/pull/79287

@oli-obk Nice, it's even merged already!

How does this RFC work with sub/super traits? I couldn't find anything about it. E.g.:
trait Super {
    fn a();
}

trait Sub: Super {
    fn b();
}

const fn test<T: Sub>() {
    T::b();

    // Is this ok?
    T::a();
    // If it is, how to opt-out implicit `T: const Super` (the `const` part),
    // without breaking `T::b();`?
}

So... the current status of the implementation is that T::a() does not compile and needs its own Super bound on T to work (See this playground for a demo).
That said, I think it's too early to make a decision either way. I think it would be least suprising to also have all the super traits available for const ops and require ?const Super bounds to opt out, but I do see that this may cause a lot of mayhem with bounds. I'd rather end up with as few ?const bounds as possible.

What I would expect is that impl const Trait for Type requires the super-trait-impls to also all be const. That seems most consistent.

Hi - I'm likely missing some important points, but I wanted to bring attention to https://github.com/rust-lang/rust/issues/71971
I agree that it would be quite helpful to have interfaces that are declared const, as you may wish to employ the interface (i.e. trait method) from some const context. Currently, we get: functions in traits cannot be const.

May be you can refer me to better place to ask, but would it be appropriate to consider a case where author of the trait wants to enforce that any reasonable trait implementation would be a const function? So there would be no ambiguity of implementing const trait for type and just implementing a trait for type, and it may be a good starting point that may satisfy 80% of use cases

May be you can refer me to better place to ask, but would it be appropriate to consider a case where author of the trait wants to enforce that any reasonable trait implementation would be a const function? So there would be no ambiguity of implementing const trait for type and just implementing a trait for type, and it may be a good starting point that may satisfy 80% of use cases

That sounds like something that belongs in the "future extensions" section. It sounds like something that may be desirable for guarantees similar to unsafe trait Foo declarations.

A problem came up with the original plan, described in https://github.com/rust-lang/rust/issues/83452 and on Zulip: under some conditions, we currently accept const fn on stable that have trait bounds in scope; if we say that all trait bounds on const fn are implicitly const Trait (as proposed in this RFC), that would be a breaking change for callers of these functions.

@nikomatsakis That might be good if we want to keep our options open -- but @oli-obk has the overview here, I'm just reporting what came up elsewhere. I don't currently have the bandwidth to work on this.
I personally am leaning towards a different design than the one proposed in the RFC, one where there is no implicit "callable in const context" -- that would be more consistent with &dyn Trait and fn() which can already be created in const. That design doesn't mind this accident. But this is a discussion for the RFC.

What's the status of the RFC? FCP was proposed over two years ago, and is currently blocked by @withoutboats. I will note that boats is an alumnus of the lang team. While I am not dismissing their concerns outright, they have had zero public activity on GitHub in over six months. At this point, is it worth cancelling and restarting the checkboxes? This would permit the current lang team to register the same concerns if they still exist.
cc lang team: @joshtriplett @nikomatsakis @cramertj @pnkfelix @scottmcm

I'd assume experimentation going on based upon https://github.com/rust-lang/rfcs/pull/2632#issuecomment-567699174 ?  If I read correctly, there was a rather extensive discussion around boats' third issue, which prompted a desire to experiment.

Yeah, the main reason I asked is because said experimentation had taken place and been on nightly for a while now.

There are currently still a few things that make the experimental feature useless in practice. We don't have the implementation capacity right now to work on it, but I do plan on more things happening here this year.

I talked to @oli-obk today and we agreed that we will close this RFC for now. The content is likely still desired but we want to do more experimentation and will re-open when the design seems closer to settled.

IIUC, this RFC would make trait-associated constants unusable in const contexts if the trait bound is not declared const (possibly implicitly). I think this would be a design mistake - an unnecessary reduction of usability. Conceptually, associated constants should be usable in const contexts always, irrespective of the constness of the trait implementation or the trait bound (setting aside for now the implementation difficulties of proving the equality of different constant expressions). Here's an example that wouldn't compile given the current design:
trait Foo {
    fn foo(value: u8) -> u8;
}

trait Bar {
    const BAR: u8;

    fn bar(value: u8) -> u8;
}

const fn baz<T>() -> u8
where T: Foo + ?const Bar {
    T::foo(T::BAR) // error: `<T as Bar>` used in a const context
}


Review citation code load

The citation code appears briefly as the detail page loads. Javascript then hides until needed. Look into alternate ways of loading to avoid the brief appearance which may be unsettling on slow connections

@Vino-S can you take a look at this?

If it ends up being a big task to change/fix this, let's discuss and it can go back into backlog if needed..

This has been in sprint backlog for a year. Shouldn't we move back


Compilation error RHEL 9.2

On RHEL 9.2 when compiling myself :
src/event/ngx_event_openssl.c: In function ‘ngx_ssl_load_certificate_key’: src/event/ngx_event_openssl.c:729:9: error: ‘ENGINE_by_id’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations]   729 |         engine = ENGINE_by_id((char *) p);       |         ^~~~~~ In file included from src/event/ngx_event_openssl.h:22,                  from src/core/ngx_core.h:84,                  from src/event/ngx_event_openssl.c:9: /usr/include/openssl/engine.h:336:31: note: declared here   336 | OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_by_id(const char *id);       |                               ^~~~~~~~~~~~ src/event/ngx_event_openssl.c:738:9: error: ‘ENGINE_load_private_key’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations]   738 |         pkey = ENGINE_load_private_key(engine, (char *) last, 0, 0);       |         ^~~~ In file included from src/event/ngx_event_openssl.h:22,                  from src/core/ngx_core.h:84,                  from src/event/ngx_event_openssl.c:9: /usr/include/openssl/engine.h:638:11: note: declared here   638 | EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id,       |           ^~~~~~~~~~~~~~~~~~~~~~~ src/event/ngx_event_openssl.c:742:13: error: ‘ENGINE_free’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations]   742 |             ENGINE_free(engine);       |             ^~~~~~~~~~~ In file included from src/event/ngx_event_openssl.h:22,                  from src/core/ngx_core.h:84,                  from src/event/ngx_event_openssl.c:9: /usr/include/openssl/engine.h:493:27: note: declared here   493 | OSSL_DEPRECATEDIN_3_0 int ENGINE_free(ENGINE *e);       |                           ^~~~~~~~~~~ src/event/ngx_event_openssl.c:746:9: error: ‘ENGINE_free’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations]   746 |         ENGINE_free(engine);       |         ^~~~~~~~~~~ In file included from src/event/ngx_event_openssl.h:22,                  from src/core/ngx_core.h:84,                  from src/event/ngx_event_openssl.c:9: /usr/include/openssl/engine.h:493:27: note: declared here   493 | OSSL_DEPRECATEDIN_3_0 int ENGINE_free(ENGINE *e);       |                           ^~~~~~~~~~~ src/event/ngx_event_openssl.c: In function ‘ngx_ssl_dhparam’: src/event/ngx_event_openssl.c:1371:5: error: ‘PEM_read_bio_DHparams’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations]  1371 |     dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);       |     ^~ In file included from /usr/include/openssl/ssl.h:36,                  from src/event/ngx_event_openssl.h:15,                  from src/core/ngx_core.h:84,                  from src/event/ngx_event_openssl.c:9: /usr/include/openssl/pem.h:469:1: note: declared here   469 | DECLARE_PEM_rw_attr(OSSL_DEPRECATEDIN_3_0, DHparams, DH)       | ^~~~~~~~~~~~~~~~~~~ src/event/ngx_event_openssl.c:1381:5: error: ‘DH_free’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations]  1381 |     DH_free(dh);       |     ^~~~~~~ In file included from /usr/include/openssl/dsa.h:51,                  from /usr/include/openssl/x509.h:37,                  from /usr/include/openssl/ssl.h:31,                  from src/event/ngx_event_openssl.h:15,                  from src/core/ngx_core.h:84,                  from src/event/ngx_event_openssl.c:9: /usr/include/openssl/dh.h:200:28: note: declared here   200 | OSSL_DEPRECATEDIN_3_0 void DH_free(DH *dh);       |                            ^~~~~~~ src/event/ngx_event_openssl.c: In function ‘ngx_ssl_error’: src/event/ngx_event_openssl.c:3232:13: error: ‘ERR_peek_error_line_data’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations]  3232 |             n = ERR_peek_error_line_data(NULL, NULL, &data, &flags);       |             ^ In file included from src/event/ngx_event_openssl.h:16,                  from src/core/ngx_core.h:84,                  from src/event/ngx_event_openssl.c:9: /usr/include/openssl/err.h:437:15: note: declared here   437 | unsigned long ERR_peek_error_line_data(const char **file, int *line,       |               ^~~~~~~~~~~~~~~~~~~~~~~~ src/event/ngx_event_openssl.c: In function ‘ngx_ssl_session_ticket_key_callback’: src/event/ngx_event_openssl.c:4140:9: error: ‘HMAC_Init_ex’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations]  4140 |         if (HMAC_Init_ex(hctx, key[0].hmac_key, size, digest, NULL) != 1) {       |         ^~ In file included from /usr/include/openssl/ssl.h:37,                  from src/event/ngx_event_openssl.h:15,                  from src/core/ngx_core.h:84,                  from src/event/ngx_event_openssl.c:9: /usr/include/openssl/hmac.h:43:27: note: declared here    43 | OSSL_DEPRECATEDIN_3_0 int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,       |                           ^~~~~~~~~~~~ src/event/ngx_event_openssl.c:4183:9: error: ‘HMAC_Init_ex’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations]  4183 |         if (HMAC_Init_ex(hctx, key[i].hmac_key, size, digest, NULL) != 1) {       |         ^~ In file included from /usr/include/openssl/ssl.h:37,                  from src/event/ngx_event_openssl.h:15,                  from src/core/ngx_core.h:84,                  from src/event/ngx_event_openssl.c:9: /usr/include/openssl/hmac.h:43:27: note: declared here    43 | OSSL_DEPRECATEDIN_3_0 int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,       |                           ^~~~~~~~~~~~ src/event/ngx_event_openssl.c: In function ‘ngx_openssl_engine’: src/event/ngx_event_openssl.c:5336:5: error: ‘ENGINE_by_id’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations]  5336 |     engine = ENGINE_by_id((char *) value[1].data);       |     ^~~~~~ In file included from src/event/ngx_event_openssl.h:22,                  from src/core/ngx_core.h:84,                  from src/event/ngx_event_openssl.c:9: /usr/include/openssl/engine.h:336:31: note: declared here   336 | OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_by_id(const char *id);       |                               ^~~~~~~~~~~~ src/event/ngx_event_openssl.c:5344:5: error: ‘ENGINE_set_default’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations]  5344 |     if (ENGINE_set_default(engine, ENGINE_METHOD_ALL) == 0) {       |     ^~ In file included from src/event/ngx_event_openssl.h:22,                  from src/core/ngx_core.h:84,                  from src/event/ngx_event_openssl.c:9: /usr/include/openssl/engine.h:708:27: note: declared here   708 | OSSL_DEPRECATEDIN_3_0 int ENGINE_set_default(ENGINE *e, unsigned int flags);       |                           ^~~~~~~~~~~~~~~~~~ src/event/ngx_event_openssl.c:5349:9: error: ‘ENGINE_free’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations]  5349 |         ENGINE_free(engine);       |         ^~~~~~~~~~~ In file included from src/event/ngx_event_openssl.h:22,                  from src/core/ngx_core.h:84,                  from src/event/ngx_event_openssl.c:9: /usr/include/openssl/engine.h:493:27: note: declared here   493 | OSSL_DEPRECATEDIN_3_0 int ENGINE_free(ENGINE *e);       |                           ^~~~~~~~~~~ src/event/ngx_event_openssl.c:5354:5: error: ‘ENGINE_free’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations]  5354 |     ENGINE_free(engine);       |     ^~~~~~~~~~~ In file included from src/event/ngx_event_openssl.h:22,                  from src/core/ngx_core.h:84,                  from src/event/ngx_event_openssl.c:9: /usr/include/openssl/engine.h:493:27: note: declared here   493 | OSSL_DEPRECATEDIN_3_0 int ENGINE_free(ENGINE *e);       |                           ^~~~~~~~~~~ cc1: all warnings being treated as errors make[1]: *** [objs/Makefile:969: objs/src/event/ngx_event_openssl.o] Error 1

Fixed by using nginx 1.22 from upstream .  Now it builds .


IP adress

Hi
It would be great if  we had a fake list of IP adress, is it possible?
Thank you

Yes: https://github.com/fzaninotto/Faker#fakerproviderinternet

thanks