Support IAM Roles for Service Accounts

Amazon recently released support for assigning IAM roles to Service Accounts (https://aws.amazon.com/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/).
In order to take advantage of this, the AWS SDK needs to be upgraded (The Go SDK needs to be a minimum of version 1.23.13), and we need a way to indicate the IAM role to be used, so it can be added as an annotation to the service account(s) used by the operator.
Assigning IAM roles through this method is easier and more secure than keeping long-running IAM users around, which have fixed credentials and [ideally] need them rotated periodically.

This seems reasonable. Sounds like we just need to upgrade the dependency then. I can take a look at this for next week.

I started taking at look a this myself, and ended up down the rabbit hole. Upgrading the aws sdk reference for operator-metering itself was straightforward, and I started things up using the custom docker image I built with that. It wasn't clear from the documentation exactly which pods needed access to AWS resources, but the hive-server seemed to be one of them, as its logs reported access denied trying to access the s3 bucket.
Looking at the code to Hive, it appears to leverage Hadoop's s3a plugin to connect to s3, and doesn't itself actually have the AWS SDK as a dependency. So I looked at the source to s3a, and it appears to just grab the latest AWS SDK when it is built with the rest of Hadoop, which is great. Unfortunately, it seems like operator-metering uses a really ancient fork of Hive (https://github.com/operator-framework/hive) 3804 commits behind mainline, and its Hadoop dependency is years old and by extension, so is its AWS SDK.
Does that all sound about right? I'm really eager to try this project, but because our corporate security policy doesn't allow IAM users (only assumed IAM roles and instance profiles) I'm not able to.

So there's a few things that will talk to AWS. Reporting-operator, Presto, and Hive (both metastore and server).
Hive has multiple versions, and version 3 hasn't been "stable" that long, and most distributions of Hive are based on Hive 2.3.x which is still maintained. We're not that far behind on that either, we're at 2.3.3 and latest is 2.3.6, and we follow the releases if there are fixes critical to our project. Presto, until recently hasn't worked with Hive 3.x at all really so we've been stuck on Hive 2.3.x.
S3A comes from the core hadoop-common libraries which come from the hadoop installation which isn't part of Hive. Similarly, most are using Hadoop 2.x, and we're actually on hadoop 3.1.1 https://github.com/operator-framework/hadoop.
I would expect all of these libraries to behave similarly to all AWS credentials chains, trying to use whichever credentials are available. My only thought it that we may be setting the AWS_* environment variables unconditionally, perhaps to empty values which might be an issue if that's the case. I know quite a bit in the past in our earlier days people had success with the kube2iam project, so I know these things work to some degree, but the service account stuff is new so we may need to upgrade some more things.

For what it's worth, the version of the AWS java SDK is here: https://github.com/operator-framework/hadoop/blob/master/hadoop-project/pom.xml#L137

<aws-java-sdk.version>1.11.271</aws-java-sdk.version>

Thanks for clarifying which services need to be targeted. For the java1 sdk, 1.11.623 is the minimum to support the new authentication mechanism. I started by making a simple docker image like this:
FROM quay.io/openshift/origin-metering-hive:latest
RUN rm /opt/hive/lib/aws-java-sdk-bundle-*
COPY aws-java-sdk-bundle-1.11.651.jar /opt/hive/lib/

Hoping I could get lucky and there wouldn't be any breaking changes. It didn't actually explode, but s3 is still unable to authenticate. I am currently working on rebuilding the hive image with debug logging turned on for s3a (it didn't look like there was any easier way to do that, but please let me know if there is).
It's interesting that you say there has been success with kube2iam - we do actually use that, though we are trying to retire it in favor of the new service account mechanism. In order to get the project to deploy at all, I had to remove secretName as a required field from the s3 storage configuration, Once it deploys, I annotated the hive serviceaccount and deleted the hive-server-0 pod. I confirmed that when it came back up, the expected env var and volume mount was present, but I'll double check that there aren't any empty vars throwing things off.

The files in /opt/hive/lib/ are symlinks, though I don't even think the symlinks are necessary anymore. The files are actually in ${HADOOP_HOME}/share/hadoop/tools/lib/, among many others. Perhaps:
FROM quay.io/openshift/origin-metering-hive:latest
RUN rm ${HADOOP_HOME}/share/hadoop/tools/lib/aws-java-sdk-bundle-*
COPY aws-java-sdk-bundle-1.11.651.jar ${HADOOP_HOME}/share/hadoop/tools/lib/

Ok, I've put the new jar there (as well as in /opt/hive/lib just to be sure, since the symlink gets broken when I remove the file, I guess) and confirmed that it's on the classpath (according to the log that's printed at the start). I also confirmed that there are no empty or otherwise conflicting env vars that might throw off the AWS SDK. Unfortunately, it still isn't authenticating and I can't think of a way to figure out which creds (if any) it is trying to use, without the app itself logging that.
I'm struggling to get the hive docker image with debug logging built, probably as a consequence of trying to do it on Windows. First I ran into this:
The system is out of resources.
Consult the following stack trace for details.
java.lang.OutOfMemoryError: GC overhead limit exceeded

So I threw in ENV MAVEN_OPTS=-Xmx768m -XX:MaxPermSize=256m  and it got further, but now just seems to be hanging with the last log output being [INFO] --- maven-site-plugin:3.3:attach-descriptor (attach-descriptor) @ hive-llap-ext-client ---. I'll let it run over night and hope it finds its way through.

You might be able to just set the logging you need in the log4j
configuration files as well.
On Mon, Oct 14, 2019 at 12:26 PM Noah Potash<EMAIL_ADDRESS>wrote:

Ok, I've put the new jar there (as well as in /opt/hive/lib just to be
sure, since the symlink gets broken when I remove the file, I guess) and
confirmed that it's on the classpath (according to the log that's printed
at the start). I also confirmed that there are no empty or otherwise
conflicting env vars that might throw off the AWS SDK. Unfortunately, it
still isn't authenticating and I can't think of a way to figure out which
creds (if any) it is trying to use, without the app itself logging that.
I'm struggling to get the hive docker image with debug logging built,
probably as a consequence of trying to do it on Windows. First I ran into
this:
The system is out of resources.
Consult the following stack trace for details.
java.lang.OutOfMemoryError: GC overhead limit exceeded
So I threw in ENV MAVEN_OPTS=-Xmx768m -XX:MaxPermSize=256m and it got
further, but now just seems to be hanging with the last log output being [INFO]
--- maven-site-plugin:3.3:attach-descriptor (attach-descriptor) @
hive-llap-ext-client ---. I'll let it run over night and hope it finds
its way through.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/operator-framework/operator-metering/issues/947?email_source=notifications&email_token=AAKV4UNQ2CX4LEAL7OE7WALQOTBWZA5CNFSM4IY2Z6EKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEBGFEAA#issuecomment-541872640,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAKV4UOSAMCGNIOXOKVFPILQOTBWZANCNFSM4IY2Z6EA
.

I figured out what's going on here.
First, I rebuilt the ansible-operator image using a modified hive-configmap.yaml that enabled the debug logging for s3a. This confirmed that s3a was using only the BasicAWSCredentialsProvider, EnvironmentVariableCredentialsProvider, and InstanceProfileCredentialsProvider - not the new WebIdentityTokenCredentialsProvider.
Then I edited _hadoop_config_helpers.tpl to force the use of the new provider, by setting
  <property>
      <name>fs.s3a.aws.credentials.provider</name>
      <value>com.amazonaws.auth.WebIdentityTokenCredentialsProvider</value>
  </property>

which then caused it to throw the following stack trace:
Caused by: java.io.IOException: com.amazonaws.auth.WebIdentityTokenCredentialsProvider constructor exception.  A class specified in fs.s3a.aws.credentials.provider must provide a public constructor accepting Configuration, or a public factory method named getInstance that accepts no arguments, or a public default constructor.
        at org.apache.hadoop.fs.s3a.S3AUtils.createAWSCredentialProvider(S3AUtils.java:661) ~[hadoop-aws-3.1.1.jar:?]
        at org.apache.hadoop.fs.s3a.S3AUtils.createAWSCredentialProviderSet(S3AUtils.java:566) ~[hadoop-aws-3.1.1.jar:?]

And sure enough, WebIdentityTokenCredentialsProvider offers neither of those things. Looking at how it's used in the AWS SDK (https://github.com/aws/aws-sdk-java/blob/53683b836dec55226f45060dd5af3f00259650c3/aws-java-sdk-core/src/main/java/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.java) you can see that it uses .create() rather than .getInstance()
So I guess that puts me back to editing the Hadoop fork to use the new provider from the new SDK.

Looking from it, the default provider chain should make it so that WebIdentityTokenCredentialsProvider is used when the creds aren't specified in the env, java system properties, aws creds file. The fact that the web identity creds provider uses create makes it not work for passing to fs.s3a.aws.credentials.provider, but DefaultAWSCredentialsProviderChain does implement getInstance(), and it does have WebIdentityTokenCredentialsProvider in it as part of the chain.
So if you leave fs.s3a.aws.credentials.provider unspecified, or set to com.amazonaws.auth.DefaultAWSCredentialsProviderChain it should go through the list, and eventually land on the WebIdentityTokenCredentialsProvider. Perhaps the env vars are being used if set, even when empty preventing it from going to the next provider.
Either way, WebIdentityTokenCredentialsProvider should probably also have getInstance() in it so you can specify it directly.

DefaultAWSCredentialsProviderChain does indeed fall back to WebIdentityTokenCredentialsProvider, but Hadoop/s3a doesn't use DefaultAWSCredentialsProviderChain . It uses its own ( https://github.com/operator-framework/hadoop/blob/master/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/AWSCredentialProviderList.java ) and populates it here: https://github.com/operator-framework/hadoop/blob/master/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AUtils.java#L558
I'm working on rebuilding with credentials.add(WebIdentityTokenCredentialsProvider.create()); added in there.

Ah I see. I can look at making a PR to add a default constructor to this type in the aws-java-sdk since it seems reasonably simple and easy.

https://github.com/aws/aws-sdk-java/pull/2121 with this, if we updated the AWS SDK to use these changes I think that WebIdentityTokenCredentialsProvider should just work if specified in fs.s3a.aws.credentials.provider

Cool. Yeah that ought to work, though since we would still need to rebuild Hadoop to pick up the new SDK it probably makes sense to put it in the default AWSCredentialProviderList anyway (ideally that would happen in the upstream Hadoop repo and backported, of course).

You shouldn't need to rebuild hadoop, you should just be able to update the AWS SDK jar.

Right - patching over the docker image like I've been doing.

I managed to get everything working! Here's what I did:

Hadoop
○ Rebuilt with the latest SDK and added credentials.add(WebIdentityTokenCredentialsProvider.create()); to S3AUtils.java (should be avoidable when aws/aws-sdk-java#2121 is accepted and released, with configuration in metering-ansible-operator)
Hive
○ Rebuilt with the new Hadoop (should be avoidable when aws/aws-sdk-java#2121 is accepted and released, with configuration in metering-ansible-operator)
Metering-ansible-operator
○ Modified templates for hive, presto, and reporting-operator serviceAccounts to have the IAM annotation (long term should be configurable from the main repo, maybe in metering-custom.yaml)
○ Modified presto-common-config.yaml to set hive.s3.use-instance-credentials=false
Presto
○ Rebuilt presto-hive plugin with latest SDK and added WebIdentityTokenCredentialsProvider.create(); to PrestoS3ClientFactory.java and PrestoS3FileSystem.java  (should be avoidable if https://github.com/prestosql/presto/pull/741/files got pulled downstream)
○ Modified PrestoS3FileSystem.java to not verify that the IAM role or useInstanceCredentials must be set.
○ Patched the docker image to remove the old AWS SDK and presto-hive plugin, replacing it with the one I built (docker build seems to just download the plugins from maven, rather than build the ones in the repo?)
Reporting-operator
○ Rebuilt the reporting operator using the latest SDK (dep ensure -update github.com/aws/aws-sdk-go)

With all that in place, I was able to generate the sample namespace-cpu-request report from the documentation.
Thanks for your help with this, I'm looking forward to "proper" support for the new creds so I don't have to run with custom docker images, but this is good enough for now.

○ Modified templates for hive, presto, and reporting-operator serviceAccounts to have the IAM annotation (long term should be configurable from the main repo, maybe in metering-custom.yaml)
we already support annotations on every component that I'm aware of.

○ Modified presto-common-config.yaml to set hive.s3.use-instance-credentials=false
we can add this as an option you can set in the MeteringConfig probably

https://github.com/prestosql/presto/pull/741/
this was in Presto 316 and we'll be updating to a newer Presto pretty soon, we're on 311 now.

○ Rebuilt the reporting operator using the latest SDK (dep ensure -update github.com/aws/aws-sdk-go)

I can take a look at getting this done too.
Overall seems reasonsable. I think once the aws-java-sdk change is merged we'll need to bump the version in our pom.xml files of each to get the latest, but I could be wrong, as I'm not sure if they've just got constraints or if they're pinned.

Could you show me an example for how to add an annotation at "deployment" time? The only avenue for customization I saw was metering-custom.yaml, and it wasn't obvious to me how I would put an annotation in there that would get applied to a ServiceAccount.
I've had to do one more thing for the reporting operator, which I didn't realize until I tried to use the aws billing support: I needed to add fsGroup: 3001 to its securityContext because the projected token is by default only accessible to root, but the container runs as a different user (see https://github.com/kubernetes-incubator/external-dns/pull/1185 for discussion)

Hmm we don't yet support annotations on serviceAccounts, but we could add that. What do you need it for and what would be an example annotation?

The service account is bound to the IAM role via annotation, and it is from there that the token gets projected into the pod.
The full technical details are in the link I included in the first post of this issue, but in short, when a pod is created it gets intercepted by a mutating webhook (https://github.com/aws/amazon-eks-pod-identity-webhook) which inspects the eks.amazonaws.com/role-arn annotation on the Service Account to which the pod is bound. It runs off and does security token things, and mounts a token as a volume in the pod, along with adding two environment variables.
Here's an example annotation applied to a ServiceAccount-
 annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/eksctl-irptest-addon-iamsa-default-my-serviceaccount-Role1-UCGG6NDYZ3UE


Missing dependencies for qwen-vl describer

python bqva.py -m qwen-vl describe returns the following error:
  File "/scratch/users/k1217897/kdl-vqa/describer/qwen-vl.py", line 5, in <module>
    from transformers import Qwen2VLForConditionalGeneration, AutoTokenizer, AutoProcessor
  File "/scratch/users/k1217897/kdl-vqa/venv/lib/python3.11/site-packages/transformers/__init__.py", line 26, in <module>
    from . import dependency_versions_check
  File "/scratch/users/k1217897/kdl-vqa/venv/lib/python3.11/site-packages/transformers/dependency_versions_check.py", line 16, in <module>
    from .utils.versions import require_version, require_version_core
  File "/scratch/users/k1217897/kdl-vqa/venv/lib/python3.11/site-packages/transformers/utils/__init__.py", line 27, in <module>
    from .chat_template_utils import DocstringParsingException, TypeHintParsingException, get_json_schema
  File "/scratch/users/k1217897/kdl-vqa/venv/lib/python3.11/site-packages/transformers/utils/chat_template_utils.py", line 39, in <module>
    from torch import Tensor
ImportError: cannot import name 'Tensor' from 'torch' (unknown location)

Installed dependencies (see build/requirements-qwen-vl.txt)
git+https://github.com/huggingface/transformers
qwen-vl-utils
torch
torchvision
accelerate
optimum
git+https://github.com/huggingface/transformers
auto-gptq

worked by uninstall torch then re-installing all torch packages. Not sure why. Need to retest.

Retested again and it worked just well after installing requirements-qwen-vl.txt


Joystick not working on some phones

Check in with Steven, running iPhone X iOS 13.1.3, happens on both safari/chrome

fixed with #60


Added CBCS sentence under Server 4.4

Added CBCS sentence under Server 4.4

Docs Build status updates of commit d701b1d:
:warning: Validation status: warnings

File
Status
Preview URL
Details

Docs/Overview/client-server-compatibility.md
:warning:Warning

Details

Docs/Overview/what-is-new/what-is-new-4-4.md
:white_check_mark:Succeeded

Docs/Overview/client-server-compatibility.md

Line 20: [Warning-bookmark-not-found] Cannot find bookmark '#_Toc508706691' in 'Overview/client-server-compatibility.md'
Line 21: [Warning-bookmark-not-found] Cannot find bookmark '#_Toc508706692' in 'Overview/client-server-compatibility.md'
Line 22: [Warning-bookmark-not-found] Cannot find bookmark '#_Toc508706693' in 'Overview/client-server-compatibility.md'
Line 23: [Warning-bookmark-not-found] Cannot find bookmark '#_Toc508706694' in 'Overview/client-server-compatibility.md'
Line 24: [Warning-bookmark-not-found] Cannot find bookmark '#_Toc508706695' in 'Overview/client-server-compatibility.md'
Line 25: [Warning-bookmark-not-found] Cannot find bookmark '#_Toc508706696' in 'Overview/client-server-compatibility.md'
Line 26: [Warning-bookmark-not-found] Cannot find bookmark '#_Toc508706697' in 'Overview/client-server-compatibility.md'
Line 27: [Warning-bookmark-not-found] Cannot find bookmark '#_Toc508706698' in 'Overview/client-server-compatibility.md'
Line 28: [Warning-bookmark-not-found] Cannot find bookmark '#_Toc508706699' in 'Overview/client-server-compatibility.md'
Line 29: [Warning-bookmark-not-found] Cannot find bookmark '#_Toc508706700' in 'Overview/client-server-compatibility.md'
Line 30: [Warning-bookmark-not-found] Cannot find bookmark '#_Toc508706701' in 'Overview/client-server-compatibility.md'
Line 31: [Warning-bookmark-not-found] Cannot find bookmark '#_Toc508706702' in 'Overview/client-server-compatibility.md'
Line 32: [Warning-bookmark-not-found] Cannot find bookmark '#_Toc508706703' in 'Overview/client-server-compatibility.md'
Line 33: [Warning-bookmark-not-found] Cannot find bookmark '#_Toc508706704' in 'Overview/client-server-compatibility.md'
Line 34: [Warning-bookmark-not-found] Cannot find bookmark '#_Toc508706705' in 'Overview/client-server-compatibility.md'
Line 35: [Warning-bookmark-not-found] Cannot find bookmark '#_Toc508706706' in 'Overview/client-server-compatibility.md'
Line 36: [Warning-bookmark-not-found] Cannot find bookmark '#_Toc508706707' in 'Overview/client-server-compatibility.md'
Line 119: [Warning-multiple-h1s] Multiple H1s are not allowed. You can only have one top-level heading.
Line 259: [Warning-multiple-h1s] Multiple H1s are not allowed. You can only have one top-level heading.

For more details, please refer to the build report.
Note: Broken links written as relative paths are included in the above build report. For broken links written as absolute paths or external URLs, see the broken link report.
Note: Your PR may contain errors or warnings unrelated to the files you changed. This happens when external dependencies like GitHub alias, Microsoft alias, cross repo links are updated. Please use these instructions to resolve them.
For any questions, please:Try searching in the Docs contributor and Admin GuideSee the frequently asked questionsPost your question in the Docs support channel

#sign-off

#sign-off

Docs Build status updates of commit 6cbda16:
:white_check_mark: Validation status: passed

File
Status
Preview URL
Details

Docs/Overview/what-is-new/what-is-new-4-4.md
:bulb:Suggestion

Details

Docs/Overview/what-is-new/what-is-new-4-4.md

Line 2, Column 8: [Suggestion-duplicate-titles] Title 'What's New - PlayReady' is duplicated in: 'Overview/what-is-new.md(2,8), Overview/what-is-new/what-is-new-4-2.md(2,8), Overview/what-is-new/what-is-new-4-3.md(2,8), Overview/what-is-new/what-is-new-4-4.md(2,8)'. Titles must be unique within a docset.
Line 55, Column 1: [Suggestion-code-block-indented] Indented code blocks aren't allowed. Use a Markdown code block surrounded by triple backticks (```).

For more details, please refer to the build report.
Note: Broken links written as relative paths are included in the above build report. For broken links written as absolute paths or external URLs, see the broken link report.
For any questions, please:Try searching in the Docs contributor and Admin GuideSee the frequently asked questionsPost your question in the Docs support channel


App Doesn't Load

Application doesn't load at all, it's just a blank page. Console error is as follows:
In Firefox Nightly (Today's)
None of the "sha512" hashes in the integrity attribute match the content of the subresource.
In Chrome 47.0.2526.106 m
Failed to find a valid digest in the 'integrity' attribute for resource 'http://www.blazeboy.me/devtools/assets/devtools-dbd1b6be46db16eb5d3270d709c9174b.js' with computed SHA-256 integrity '2qXoHfZSfB9ceWJu5I1MjnrRdLXs89gKSjAcT6MtPJ0='. The resource has been blocked.
Side note: I think it would be useful to test the deployment with clear cache or private browser mode.

will investigate noe

There's another error in the console, but it's not related
The resource at "http://www.google-analytics.com/analytics.js" was blocked because tracking protection is enabled.[Learn More] devtools
I have 'Do Not Track' turned on

aha it's irrelevant

I'm also currently facing this issue.

It's not fixed for me either. Tried clearing the cache, private mode, and different browser. Still there on Firefox and Chrome.

This maybe relevant : https://github.com/ember-cli/ember-cli/issues/5040

Weird, it's loading correctly on my firefox, i'll investigate further

@AmrEldib @MohamedBassem can we check if this solved the bug?

It did, but seems like this is a temporary fix, if you found the commit that introduced this thing maybe we can find a better way to fix it

Sure, i'll dig nore after finishing this tool #25

Cool, good luck!

Seems resolved now. Thanks!

Ok, the ember-cli main developer said that adding integrity to script tags is the solution not a work around, it's just ember-cli blueprint didn't add it by default and the new versions will.

@blazeeboy was the integrity failing on the testem script out of interest? (just seen this)

I didn't get that error, neither when running tests not the app itself, but @AmrEldib had it on firefox with the main app.
couldn't regenerate the issue on my machine.

I found the problem while trying to use the app. You can find a description of the error above.


fix(stream): fix the minput's indicies when it's for distinct call

I hereby agree to the terms of the RisingWave Labs, Inc. Contributor License Agreement.
What's changed and what's your intention?
fix https://github.com/risingwavelabs/risingwave/issues/12140
Checklist

[ ] I have written necessary rustdoc comments
[x] I have added necessary unit tests and integration tests
[ ] I have added fuzzing tests or opened an issue to track them. (Optional, recommended for new SQL features #7934).
[ ] My PR contains breaking changes. (If it deprecates some features, please create a tracking issue to remove them in the future).
[x] All checks passed in ./risedev check (or alias, ./risedev c)
[ ] My PR changes performance-critical code. (Please run macro/micro-benchmarks and show the results.)

[ ] My PR contains critical fixes that are necessary to be merged into the latest release. (Please check out the details)

Documentation

[ ] My PR needs documentation updates. (Please use the Release note section below to summarize the impact on users)

Release note
If this PR includes changes that directly affect users or other significant modifications relevant to the community, kindly draft a release note to provide a concise summary of these changes. Please prioritize highlighting the impact these changes will have on users.

The implementation LGTM, but keeping backward compatibility needs extra care. Please take a look at the discussion thread in team-engineer channel. (Thanks for @st1page brining this up)

Please be caution when force pushing. 534cbba seems to be lost. 😕


Add file-svg

Describe the requested icon
Like file-pdf, an icon with the text SVG.

Added file-svg in v2.0.0


bug:  Cannot pass data to popover with componentProps

Bug Report
Ionic version:
Ionic:
Ionic CLI                     : 5.4.6 (/Users/brooks.forsyth/.nvm/versions/node/v12.13.0/lib/node_modules/ionic)
Ionic Framework               : @ionic/angular 4.11.5
@angular-devkit/build-angular : 0.801.3
@angular-devkit/schematics    : 8.1.3
@angular/cli                  : 8.1.3
@ionic/angular-toolkit        : 2.1.1
Utility:
cordova-res : not installed
native-run  : not installed
System:
NodeJS : v12.13.0 (/Users/brooks.forsyth/.nvm/versions/node/v12.13.0/bin/node)
npm    : 6.12.0
OS     : macOS Mojave

[x] 4.x
Current behavior:

There is no data being passed through the componentProps using the popover controller
Expected behavior:

Data to be passed
Steps to reproduce:

click pop button in example project and not console.log.
https://github.com/Bforsyth1234/popoverionic4
Related code:

  async presentPopover() {
    const popover = await this.popoverController.create({
      component: PopovercomponentComponent,
      componentProps: {
        test: 'test'
      },
      translucent: true
    });
    return await popover.present();
  }

Other information:

Ionic info:

insert the output from ionic info here

Thanks for the issue. I am going to close this as this is not a bug in Ionic Framework.
When using componentProps in Ionic Angular, each key in the object becomes an input. In your example app, you pass in the following:
componentProps: {
  test: 'test'
}

To access this data in your popover component, you would need to access @Input() test;. However, in your example repo you have @Input() data;. Changing this to be @Input() test; resolves the issue.


Initial pipeline rfc

Rendered
Hey guys, wanted to introduce my view on having pipeline (or pipes?) implemented in Rust language.
Open to discuss, open to close :)
P.S. I have seen some old RFC and it did not cover all the thoughts I put into my RFC.

One thought off the top of my head - rather than adding a new syntax for method calls in a pipeline (_.to_string), it might make more sense to use a method reference (ToString::to_string), since that's already something you can do in Rust:
let a = "string".to_string();
let b = ToString::to_string("string");
assert_eq!(a, b);

Also, a couple of thoughts on the syntax:

I'm not sure about using _ for the placeholder - everywhere else in Rust, a _ means 'this value doesn't matter' or 'this value isn't used', so seeing it being used as a parameter placeholder feels a bit strange to me.
Most other languages I've seen with this feature use |> for piping and =>/-> for lambdas - is there any reason for Rust to not use |> too?

One thought off the top of my head - rather than adding a new syntax for method calls in a pipeline (_.to_string), it might make more sense to use a method reference (ToString::to_string), since that's already something you can do in Rust:
let a = "string".to_string();
let b = ToString::to_string("string");
assert_eq!(a, b);

Well, there is no difference between:
let a = "a";
let b = a.to_string();

And the proposed syntax with _ for intermediate value - in both these cases we already know the type we want to call method on. Also, if you suddenly decide to change the trait name, you will need also to change it there. But anyway, this is not a big difference.

Also, a couple of thoughts on the syntax:
* I'm not sure about using `_` for the placeholder - everywhere else in Rust, a `_` means 'this value doesn't matter' or 'this value isn't used', so seeing it being used as a parameter placeholder feels a bit strange to me.

* Most other languages I've seen with this feature use `|>` for piping and `=>`/`->` for lambdas - is there any reason for Rust to not use `|>` too?

Both of these questions were mentioned in the RFC. I picked _ as it is a placeholder for unused value, using that part that it is a placeholder just in another context (not for unused value, but for intermediate one). And => I picked because it is slightly easier to write then |> personally for me, also, because people are already familiar with it and it looks quite understandable in the code as it looks similar to an arrow while |> does not. Also, in clojure, ==> is used for piping IIRC. These were my thoughts, I am open to discuss this, of course, I don't say that we must use exactly these tokens, we may change it if we find better ones.

I hack on a language that uses ^ for composition and _ for lambda shorthand (in exactly the manner proposed by this RFC). I'm a big fan of both of these features.
However, it seems to me like there are two distinct features here: a pipe operator and a lambda shorthand. Since both of these are going to be subject to endless bikeshedding, perhaps these should be separate RFCs? They're also independently useful. I often use placeholder syntax in map and filter calls; e.g.: iter.filter(_ > 5). I use pipelining less often, especially when method chaining is available.
@17cupsofcoffee I don't find using _ in the single-argument case that compelling, either. I think where it really shines is when you have something that takes multiple arguments and you want to fill in some, but not all, of the blanks (as in the filter example above).
FWIW, I think _ is actually a great choice of symbol for lambda shorthand. In both the name context (where it can already be used) and expression context, it refers to something that is filled in with a value, but cannot be referred to by name.

Since both of these are going to be subject to endless bikeshedding, perhaps these should be separate RFCs? They're also independently useful.

Yes, I also thought so. Just I elaborated on meaning of my _ in the end of writing the RFC :) It may be so that it could be better if there were written separate RFCs for the pipeline and the placeholder.

I use pipelining less often, especially when method chaining is available.

I'd also pick methods but then we have to do a lot of work with types and objects (I tried making something similar to std::iter::Iter trait myself) and it was not so quick as if I used functions. Also, if we call mutable methods of an object in a chain, the object shares state while pipelines are almost always stateless. This is just another view onto the solving of a problem. We may offer it for more general use :) Also, not everyone prefers objects in Rust, since Rust is multi-paradigm language, even though many things in the standard library (and crates) are object-like. As I have already said in the RFC, I do not tell people that we must write the code in this way, we can just provide this way, but the end user decides how and what he will use in his project.

FWIW, I think _ is actually a great choice of symbol for lambda shorthand. In both the name context (where it can already be used) and expression context, it refers to something that is filled in with a value, but cannot be referred to by name.

These were also my thoughts.

Point-free programming is related to De Bruijn indexes:
I'd rather we use #0 instead of _ for the 'hole', so that when a function is defined itself as a pipeline there is no ambiguity as to which variable is referred to by _ :
let subber = |x, y| x - y;
40 => (20 => subber(_, _)); // ???

// Whereas
40 => (20 => subber(#1, #0)); // is not ambiguous, since
(20 => subber(#1, #0))
  = subber(#0, 20)
  = |x| subber(x, 20);

This shows that point-free programming, although an interesting topic to explore in Rust, should be dealt with in another RFC.
Pipelining is already a feature interesting enough on its own.
The biggest issue with all this is currying, which is far from trivial given Rust's ownership rules (move closures vs. non-move ones); I think we need existential -> impl Trait in return position in trait methods to fully enable currying in Rust.

Taking your example:
let is_printed = 1 => adder(3) => multiplier(2) => _.to_string => printer(); // is_printed == true

Equivalent valid rust code could be:
let a = 1;
let a = adder(3, a);
let a = multiplier(2, a);
let a = ToString::to_string(a);
let a = printer(a);
a

This looks to me like something a macro could semi-trivially accomplish.
In my opinion, if this feature were desired then it could easily be accomplished by a crate. Therefore it should not be added to the core rust syntax. If such a crate became so massively popular and was such a huge ergonomics improvement that it was widely used, then maybe it could be added.

My main problem with this RFCs is that I get a strong C++ or Perl "More than one way to do it. Declare your preferred dialect in your CONTRIBUTING.md." feel from it and Rust takes a fair bit of inspiration from Python's "There should be one-- and preferably only one --obvious way to do it."
(Or, to put it another way, I just don't see the existing options as having enough shortcomings to justify adding another syntax for function/method composition.)

You also might be interested in my pre-RFC and its discussion thread for similar syntax:
// Reusing your example:

fn perform_action(vendor_id: u64, model_id: u64, action: &str) -> Option<String> {
    Some(vendor_id
        .[find_vendor_id_in_database(this)?]
        .get_model_name(model_id)?
        .[do_action_with_model_name(this, action)]
        .[parse_action_result(this)]
    ])
}

This looks to me like something a macro could semi-trivially accomplish.

There is prior art for implementing this as a macro: https://github.com/johannhof/pipeline.rs

I see an unresolved problem: how compiler should treat the function invocation in every single case.
In OCaml and F# all the pipeline process is enabled by currying.
In Rust there is no currying and the partial arguments application leads to error.
So it's unclear to me from your proposal, what should be the expected results in Rust for each of the following statements, and how it should be implemented in language:
/// assume we have some functions
fn binary(arg1: u8, arg2: u8) -> u8 { ... }
fn binary_ho(arg1: u8, arg2: u8) -> dyn Fn(u8, u8) -> u8 { ... }

/// and now we call:
binary();
binary(1);
let x = binary(1);
binary(1, 2);
binary(1, 2) => ();
binary(1, 2) => binary();
binary(1, 2) => (binary(1, 2) => binary());
binary(1, 2) => binary(1, 2);
binary(1, 2) => binary_ho(1, 2);
1 => (binary(1, 2) => binary_ho(1, 2));
1 => (2 => binary(1, 2) => binary_ho(1, 2));

Where would be an error and where would be a result, and what result?
I still see only currying as a solution giving a consistent and meaningful behavior in all this examples, but there is not a word about it in the proposal, so may be I got your idea wrong.

/// assume we have some functions
fn binary(arg1: u8, arg2: u8) -> u8 { 5u8 }
fn binary_ho(arg1: u8, arg2: u8) -> dyn Fn(u8, u8) -> u8 { ... }

fn main() {
    /// and now we call:
    binary(); // no arguments, usual rust error
    binary(1); // not enough arguments, usual rust error
    let x = binary(1); // not enough arguments, usual rust error
    binary(1, 2); // the returne value is ignored, no error

    // The line below is incorrect - there is nothing to call, for example, we can't
    // call a number, the same error as it would be for `let a = 5u8();`.
    binary(1, 2) => ();
    // not enough arguments, we passed `_` as arg1 into `binary`.
    binary(1, 2) => binary();
    // Multiple errors:
    // 1. Not enough arguments for passing in pipeline inside pipeline:
    //     `binary(1, 2)` evaluates to some value and we pass it to `binary`
    //     so there is no enough arguments again, as in previous example.
    // 2. After that, the first pipeline (outermost) is invalid: we can't
    //    pass a non-callable value to another non-callable value, like
    //    `5u8 => 6u8`, also `6u8` is non-callable, the syntax is incorrect.
    binary(1, 2) => (binary(1, 2) => binary());
    // Again, 2. from previous example.
    binary(1, 2) => binary(1, 2);
    // The result of this pipeline is incorrect: the pipeline assumes
    // one more argument in `binary_ho`, the third one, as it always
    // put intermediate value there implicitly as a last argument,
    // so it could be written explicitly like this:
    // `binary(1, 2) => binary_ho(1, 2, _)` which is incorrect.
    // If `binary_ho` had third argument, it returned a function which
    // we did not use.
    binary(1, 2) => binary_ho(1, 2);
    // Multiple errors:
    // 1. The same problem as above with `binary_ho` and not passing enough
    //    arguments to it.
    // 2. If 1. was solved by making `binary_ho` accept 3 parameters,
    //    it returned a function of two arguments and so we could not simply
    //    pass one argument with value of `1` (in the beginning) to it, as
    //    this returned function accepts two arguments.
    1 => (binary(1, 2) => binary_ho(1, 2));
    // Multiple errors:
    // 1. Incorrect invocation in `2 => binary(1, 2)`, as `binary` accepts 2 arguments,
    //    while we pass `2` to it as a third one.
    // 2. The same for `binary_ho`.
    // 3. The same for returned value of `binary_ho`.
    1 => (2 => binary(1, 2) => binary_ho(1, 2));
}

Please note, that I am still in doubt about having pipelines inside pipelines, I think it will reduce readability and understandability, but this is only my personal opinion.

Point-free programming is related to De Bruijn indexes:
I'd rather we use #0 instead of _ for the 'hole', so that when a function is defined itself as a pipeline there is no ambiguity as to which variable is referred to by _ :
let subber = |x, y| x - y;
40 => (20 => subber(_, _)); // ???

// Whereas
40 => (20 => subber(#1, #0)); // is not ambiguous, since
(20 => subber(#1, #0))
  = subber(#0, 20)
  = |x| subber(x, 20);

This shows that point-free programming, although an interesting topic to explore in Rust, should be dealt with in another RFC.
Pipelining is already a feature interesting enough on its own.
The biggest issue with all this is currying, which is far from trivial given Rust's ownership rules (move closures vs. non-move ones); I think we need existential -> impl Trait in return position in trait methods to fully enable currying in Rust.

This is much more complex thing to have, and it is much more functional than rust is now, we also will have to make a lot of changes, it really requires another RFC. I also thought about this while making my RFC, but decided to give it another time. Also, seeing people not so acceptable about pipelines in the language now, I think this will never land.
About passing _ multiple times into one pipeline item, like subber(_, _), that is why I did not provide this example in the RFC: I think we should use Rust semantics of move by default and so use it here: if it can be moved (or copied), this is available, if there are two mutable references, this would be impossible. I was just thinking of it as a usual function call, I do not want to make Rust really another LISP or haskell, even though I love LISP. So I stick with existing rust rules about passing a value to a function by now.

Taking your example:
let is_printed = 1 => adder(3) => multiplier(2) => _.to_string => printer(); // is_printed == true

Equivalent valid rust code could be:
let is_printed = {
  let a = 1;
  let a = adder(3, a);
  let a = multiplier(2, a);
  let a = ToString::to_string(a);
  let a = printer(a);
  a
};

This looks to me like something a macro could semi-trivially accomplish.
In my opinion, if this feature were desired then it could easily be accomplished by a crate. Therefore it should not be added to the core rust syntax. If such a crate became so massively popular and was such a huge ergonomics improvement that it was widely used, then maybe it could be added.

I also take your opinion and understand your concerns about having a language with wide features. But why did we move from try! to ? then? Because of ergonomics, better integration with the language itself, because it is too common in Rust to unpack Result and Option types. In functional language it is also common to have pipelines (I even did it in C++) where you see your execution path step by step, as you deal with functions most (if not all) of time. As Rust is also multi-paradigm language, and considering its advantages of static checks (borrowing and others), it would be really nice to provide pipeline inside the language itself, easy integratable and requiring no more work like requiring and using a 3rd-party crate for this. Did we use try! as a separate crate?
Also, macros are not well-integrated into the language. Considering existing pipeline crate which I mentioned in the RFC, don't you find this not really ergonomic?

let num = pipe!(
  4
  => (times(10))
  => {|i: u32| i * 2}
  => (times(4))
);

Here you:

Can't pass intermediate value in arbitrary position as I mentioned in the RFC, it is always the last one.

You need braces all the time (what for, why?).

You can't really understand what is [len] is called on, as it is not a usual syntax, it is not so understandable as in my RFC:
let num = "abcd" => _.len;
let num2 = "abcd" => str::len();

Here you can clearly see that it is a method call. This is somewhat subjective of course, but I find this a little bit more clear.

You need that pipe! all the time, or even pipe_res!, pipe_opt!and they can't be integrated into each other, you must use them separately, you can't use?` inside a pipeline, you are very limited using this, you need separate macros, you need braces, you need more efforts for this. My proposal simply eliminates all of this restrictions and provides a single, ergonomic way of making a pipeline. For example, this fails:
#[macro_use]
extern crate pipeline;

fn times_opt(a: u32, b: u32) -> Option<u32> {
    Some(a * b)
}

fn main() {
    let length = pipe!(
        "abcd"
        => [len]
        => (as u32)
        => (times_opt(2)?)
        => [to_string]
    );

    println!("Values: {}, {}", num, length);
}

because of ? not being accepted by macro_rules!, so the author had to make two separate macros which accept only functions which return Option or Result.

My main problem with this RFC is that I get a strong C++ or Perl "More than one way to do it. Declare your preferred dialect in your CONTRIBUTING.md." feel from it and Rust takes a fair bit of inspiration from Python's "There should be one-- and preferably only one --obvious way to do it."

There is no other way to do a pipeline using Rust, chained method call. As I have already told, rust is multi-paradigm language, but so it looks more object-oriented than functional actually. If we can do method chaining, why can't we do function chaining? I mean, in more or less normal way? There are also more than one ways of making loops over items in a collection, using iter or manual for, or for each (which is actually an iter), or even a while loop?

(Or, to put it another way, I just don't see the existing options as having enough shortcomings to justify adding another syntax for function/method composition.)

I did not provide a replacement. My RFC states, that if we do this, then there will also be another way of method chaining, as a side-effect. This is not my main goal - to duplicate existing functionality just because I want that. And again, we can't create a function chain but only method chain. This is what it all about, - function chaining.

You also might be interested in my pre-RFC and its discussion thread for similar syntax:
// Reusing your example:

fn perform_action(vendor_id: u64, model_id: u64, action: &str) -> Option<String> {
    Some(vendor_id
        .[find_vendor_id_in_database(this)?]
        .get_model_name(model_id)?
        .[do_action_with_model_name(this, action)]
        .[parse_action_result(this)]
    ])
}

Yes, this looks quite similar to mine. Your way just looks a bit more complicated to me, I don't personally like all these {}, (), [] without a reason (so I like rust rule about unnecessary parenthesis inside if :)). I find your way a bit more difficult to write than mine but of course this is just my personal subjective opinion, but it seems we are pursuing almost the same (if not the same) goal.

There is no other way to do a pipeline using Rust and functions, we can only make chained method calls.

It's having pipelines in Rust that hasn't been sufficiently justified for me. Chaining up non-methods like that looks quite alien and I have yet to see an example of code which is made so much better by having them that it convinces me of their worth.
(To be honest, in a language without currying, guaranteed tail call optimization, and at least a preference for recursion over iteration, they evoke an "Oh, no. Not another CoffeeScript" reaction from me.)

As I have already told, rust is multi-paradigm language, but so it looks more object-oriented than functional actually.

"X is a multi-paradigm language" isn't a license to pile on features, willy-nilly, to allow the language to fit every person's preferred way of writing code. That way lies C++.
For example, Python is also a multi-paradigm language, it's where that "There should be one-- and preferably only one --obvious way to do it." line I quoted comes from, and, unless they slipped into one of the recent 3.x releases that I've been neglecting to keep up on, it gets along just fine without pipelines.

If we can do method chaining, why can't we do function chaining? I mean, in more or less normal way? There are also more than one ways of making loops over items in a collection, using iter or manual for, or for each (which is actually an iter), or even a while loop?

That argument reminds me of some of the discussion on the structural records RFC.
I'll quote @graydon on this

The fact that there's an un-filled box in a particular table enumerating aspects of types does not at all warrant filling every such box in. Consistency should not be considered an design criterion that exceeds thrift.

You don't seem to be making exactly the same argument, but I feel like the same concerns and value for thrift apply.
One important element of deciding whether an RFC gets accepted is whether the benefit from adding it outweighs what it adds to the pile of things a newcomer must learn to become proficient.

My main problem with this RFC is that I get a strong C++ or Perl "More than one way to do it. Declare your preferred dialect in your CONTRIBUTING.md." feel from it and Rust takes a fair bit of inspiration from Python's "There should be one-- and preferably only one --obvious way to do it."
(Or, to put it another way, I just don't see the existing options as having enough shortcomings to justify adding another syntax for function/method composition.)

I feel exactly the same way. Having multiple ways of achieving the same thing gives way to people having different styles and thus making it harder for different people to collaborate. You will be more proficient at reading and writing code in your preferred style. Obviously this is not a huge problem but, what does it actually give us? The given examples are fairly artificial but I would like to see examples of piping being applied pieces of code from (not using) popular crates, code that actually does something.
This example is given in the RFC to motivate it:
fn find_by_name(document: &select::Document) -> Option<&str> {
    Some(document.find(select::predicate::Class("name"))
         .next()?
         .text())
}

fn trimmed_and_owned(s: &str) -> Option<String> {
    s.trim().to_owned()
}

fn parse_name(html: &str) -> Option<String> {
    select::document::Document::from(html)
        => find_by_name()?
        => trimmed_and_owned()
}

However, is it really better than this (nothing new, this possibility is stated)?
trait DocumentExt {
    fn find_by_name(&self) -> Option<&str>;
}

impl DocumentExt for select::document::Document {
    fn find_by_name(&self) -> Option<&str> {
        self.find(select::predicate::Class("name")).next().map(select::Node::text)
    }
}

fn parse_name(html: &str) -> Option<String> {
    select::document::Document::from(html).find_by_name().trim().to_owned()
}

I expect that in most cases, we can get very far with what is already possible. I do not think that introducing more syntax into the language so that we can write code a little more concise will be an improvement. In fact I think it is hurtful because of the increased complexity in parsing (for both people and computers) and the therefore increased maintenance burden and perhaps decreased compiler performance in rust and the entire ecosystem.

@vityafx
From the explanation you gave I assume you are solving just one simple chaining case and you probably don't have enough understanding what underlying theory should be the ground for pipeline.
For example, currently I see the conflict between the explanation you gave for my example statements and your own question:

If we can do method chaining, why can't we do function chaining?

Basically method chaining has the underlying idea that every step of the chain is a valid value that has type and so on, so the whole chain can be considered step by step, it can be broken apart and any partial subject could be assigned to a variable. Your explanation above forbids this, so the chain must be parsed and evaluated only as a whole. Hence it gives us no further concepts, possibilities or features beyond the simple straightforward case considered, it is only a piece of syntactic sugar. So I must agree with @vitiral, this is a job for macros, not the language-level grammar construction.

I'm not sure about using _ for the placeholder - everywhere else in Rust, a _ means 'this value doesn't matter' or 'this value isn't used', so seeing it being used as a parameter placeholder feels a bit strange to me.

FWIW, I think _ is actually a great choice of symbol for lambda shorthand. In both the name context (where it can already be used) and expression context, it refers to something that is filled in with a value, but cannot be referred to by name.

@jswrenn I agree wholeheartedly with @17cupsofcoffee here. _ means "please infer" or more generally "I don't care" in Rust. This applies to two cases: type placeholders (which are inference type variables) and pattern matching _ => .... For consistency (and because I don't want to look for another syntax...), in expression contexts, _ should act exactly like it does in type contexts, that is, _ should stand for an inference value variable. For example, if you write let x: [u8; { _ }] = [1, 2]; then _ should infer to 2. This clashes with _ for lambdas and so I think lambdas will need to find a different syntax.

Most other languages I've seen with this feature use |> for piping and =>/-> for lambdas - is there any reason for Rust to not use |> too?

(Haskell uses $)
@danielhenrymantilla

The biggest issue with all this is currying, which is far from trivial given Rust's ownership rules (move closures vs. non-move ones); I think we need existential -> impl Trait in return position in trait methods to fully enable currying in Rust.

Currying / partial application is probably not that complicated. Save for one piece of information (the number of formal parameters a function has), it can be achieved in a syntax-directed manner. For example:
fn foo(x: u8, y: u8, u8) { ... }

let x = foo(1); // desugars to:
let x = { let _0 = 1; |_1, _2| foo(_0, _1, _2) };

let x = move foo(1); // desugars to:
let x = { let _0 = 1; move |_0, _1, _2| foo(_0, _1, _2) };

The compiler knows how many arguments foo has and so it knows how many extra parameters the lambda needs. This should also extend to methods as well.
@ssokolow

"X is a multi-paradigm language" isn't a license to pile on features, willy-nilly, to allow the language to fit every person's preferred way of writing code. That way lies C++.

I think everyone agrees that we shouldn't pile on features willy-nilly. I think the disagreement here is one of "is this willy-nilly?".

For example, Python is also a multi-paradigm language, it's where that "There should be one-- and preferably only one --obvious way to do it." line I quoted comes from, and, unless they slipped into one of the recent 3.x releases that I've been neglecting to keep up on, it gets along just fine without pipelines.

Python is good at not listening to it's own advice... ;) The language team is not philosophically opposed to having several ways to do things under certain conditions.

The fact that there's an un-filled box in a particular table enumerating aspects of types does not at all warrant filling every such box in. Consistency should not be considered an design criterion that exceeds thrift.

You don't seem to be making exactly the same argument, but I feel like the same concerns and value for thrift apply.

Irrespective of this RFC, I feel I must address Graydon's sentiment with respect to frugality over consistency. First, I think this is an unqualified blanket statement that is too unnuanced to serve as a good design guideline for us. I also disagree with the sentiment overall. If one is unwilling to let consistency (and composability in particular) exceed frugality, then I believe the likely outcome of the language design is a hard-to-learn and uncomposable patchwork. I think language design shines when things can be frugal, powerfully expressive, minimalistic, composable, consistent, and learnable all at the same time. That's of course easier said than done, but sometimes it is possible and it is a goal worthy of being our north star.
@mickvangelderen

In fact I think it is hurtful because of the increased complexity in parsing (for both people and computers) and the therefore increased maintenance burden and perhaps decreased compiler performance in rust and the entire ecosystem.

Decreased compiler performance is probably a non-issue as little time is spent in the parser. This proposal requires from what I can tell no backtracking so performance impacts should be negligible. The only noteworthy complexity is likely only for people.

I think this design space is interesting and I think there's something that should be done here. However, there are many alternatives to consider and the current proposal is likely not exactly the right fit for Rust. The RFC is also likely to be contentious and the language team does not have the bandwidth to give this proposal serious and sustained thought. Moreover, the proposal is unlikely to fit with our roadmap goals for 2019. Therefore, I propose that we:
@rfcbot postpone
this proposal.
Having said that, we may want to do something long-term. Thus, further investigation in a working group for ergonomics may be fruitful. For those interested you may consider forming such a group. This can include a balance of views including those who have expressed doubts in this RFC.

The language team is not philosophically opposed to having several ways to do things under certain conditions.

The line you were quoting continues "as long as the technique is applied only to cases that are common or particularly painful."
My argument is that this hasn't been demonstrated to meet the "common or particularly painful" requirement sufficiently.

If one is unwilling to let consistency (and composability in particular) exceed frugality, then I believe the likely outcome of the language design is a hard-to-learn and uncomposable patchwork.

Fair enough... but I also don't see this as being one of those cases.
This feels very inconsistent with the design philosophy of the rest of the language to me.
That's why I qualified one of my previous comments with "in a language without currying, guaranteed tail call optimization, and at least a preference for recursion over iteration".

@ssokolow To clarify, my points were meant as general notes as opposed to directly tied to this RFC. :) IOW, I'm not saying one way or the other that this RFC as proposed fits "common" or "particularly painful" or that the benefits outweigh the costs. There are probably many different designs that try to satisfy the same needs here that have different cost/benefit calculus. A working group would likely be the right place to collect and discuss alternatives.

Hi @Centril,

Having said that, we may want to do something long-term. Thus, further investigation in a working group for ergonomics may be fruitful. For those interested you may consider forming such a group. This can include a balance of views including those who have expressed doubts in this RFC.

How can I form one? By making a pull request to lang-team repository?

How can I form one? By making a pull request to lang-team repository?

Well... uhmm... we are sorta in the midst of revamping our processes as a language team after the all hands so this question doesn't exactly have a clear answer... so... cc @nikomatsakis :) I'd probably reach out to interested people first since a working-group needs more than one person. Ideally there would also be one language team member in such a group.

How can I form one? By making a pull request to lang-team repository?

Well... uhmm... we are sorta in the midst of revamping our processes as a language team after the all hands so this question doesn't exactly have a clear answer... so... cc @nikomatsakis :) I'd probably reach out to interested people first since a working-group needs more than one person.

Sure! Just I don't know where and whom to list people who is interested (or where they can say they are interested themselves).

Ideally there would also be one language team member in such a group.

This would be really awesome.

The attempt to create a new WG to abrogate the ratified decision of another is an obvious attack on process and should be treated as such if the project is to survive its own increasing popularity.

@bele: I'm not aware of any pre-existing official decision from any Rust team or WG on the subject of a pipeline operator. What are you referring to?

I love both currying and the operators like . and $ in Haskell.  Yet, I'm weakly against adding them to Rust like this RFC proposes because they mostly just create noise without actual currying.
Instead, I'd prefer if someone developed an entire functional "overlay" language that compiles down to Rust, and interacts nicely with Rust's type, traits, etc., but uses a Haskell or ML like syntax for function arguments and evaluation, and solves currying using Rust's newer features, like ATCs.  Doge lang attempted this for Python.  I think such an overlay language would provide a much more ergonomic REPL and drive real improvements in Rust itself around iterators, generators, lenses, etc.

There are captured dysfunctional standards bodies like W3C in which "working group" means "the group blessed to make some decisions" @bele but actually the term has different meanings elsewhere.
I'd expect based on https://github.com/steveklabnik/rfcs/blob/2019-roadmap/text/0000-roadmap-2019.md#language and http://smallcultfollowing.com/babysteps/blog/2019/02/22/rust-lang-team-working-groups/#initial-set-of-active-working-groups that any such "soft" WG for Rust would largely act as a filter for the larger language team, with the de facto power to reject RFCs, but they'd only bring cases to the larger language team, not bless RFCs.  I suppose "hard" WGs for things like unsafe code might often come up with more irrefutable answers, but that's fine.
That said, I believe "ergonomics" is a very poor name for a WG.  Instead, I'd suggest a "Readability" WG with the express purpose of making Rust code more readable.  Almost anything good that falls under "ergonomics" improves readability anyways.
In this light, there is no real improvement in readability in going from |x| foo(x,y) to foo(#0,y) while say improving #[derive(..)] helps enormously.  I think the name "Readability" would help the WG spend it's time more wisely.

@bele

The charter of an "ergonomics" WG could only possibly be to override the language group, or else to merely be an advisory body and thereby be a non-entity. As it's unlikely that well-meaning leadership would ever force a standing WG to be a non-entity, we can conclude that an "ergonomics" WG if created would have the power to override the language group. Hopefully the implicit decision to support WG creation can be reevaluated in that light.

I disagree that creating working groups to focus on assembling information, gathering consensus, and advising the language team on design issues makes them "non-entities." Ultimately the language team has the power to decide whether or not a feature is added, but working groups still have an extremely valuable role to play here.

I'm coming across this now as I've been toying with SeaQL which requires a lot of nested function calls to construct a query. Looking at some of their examples illustrates the sizeable chunks of nested calls you can create for even small and simple queries. Having played with it myself, I was reminded of the pipeline operator proposal for JavaScript, which has been mentioned in a similar RFC here.
I'm definitely not too fond of the => or -> approach so I would advocate for |>. I agree with what was said earlier in this conversation about piping:

If we can do method chaining, why can't we do function chaining?

In addition to this, I'm personally not too fond of the crazy lengths you can nest values via the new type pattern. Below is an extremely contrived example of what I'm trying to explain, in which ideally one could simplify the nested function calls with the pipe operator.
use std::sync::{Arc, Mutex}

struct Foo<A>(A);

struct Bar<B>(B);

struct Baz<C>(C);

// Each struct is given something like...
// impl X {
//   fn new() -> Self {
//     Self(...)
//   }
// }

fn main() {
  let value = Arc::new(Mutex::new(Foo::new(Bar::new(Baz::new(...)))));
}

Using this example, it would be arguably more readable using the pipe operator.
// ... snip ...

fn main() {
  let value = Baz::new
    |> Bar::new
    |> Foo::new
    |> Mutex::new
    |> Arc::new;
}

The examples above should be seen as the most basic form of what kind of code would gain readable value with the pipe operator. I would like to refer back to SeaQL as a better example, where it's very likely that you'll end up with a massive chunk of nested function calls. Obviously one could also argue that their implementation of a query builder is questionable, perhaps there's a more ergonomic way for them to do it. SeaQL is also just one example that I found literally this morning, so it's also possible that it's a poor example to begin with. The bottom line I'm trying to get to here is that personally, I would find it useful. I reckon I would use it enough to justify it as a language change. The JavaScript proposal is a feature I've been keenly waiting on for years now, although perhaps pipe operators simply can't translate to Rust.
It's been a couple of years since any activity was seen on this issue so I don't think there's much of a push for it, I just wanted to post my two cents on the matter.


can receive new elements from another list

Would it be possible to define in a list whether or not it can receive new elements from another list?
I have a use case where I have 18 lists that allow a single element or no elements.
And another with several elements.
I need to be able to drag the elements of these 18 lists between them, however, without allowing two items to be in the same list.
The onMove method returning false does not solve this problem.
The application is vue 2.7
Furthermore, are you interested in implementing documentation in PT? I can help with that

Only the same groups can drag each other. If the group names are the same, they can accept dragging elements from each other. If they are different, they cannot.

Furthermore, are you interested in implementing documentation in PT? I can help with that

I don't quite understand what you mean. Can you elaborate? Thanks.

I have 18 lists, all of them allow dragging. I can drag between lists. However, I need to validate that the list to receive the new item is empty, if there is already another item in the list, it should not allow it. Is this possible somehow?
Furthermore, I noticed that the documentation only has translations in English and Mandarin. If you are interested, I can try to help with the translation into Portuguese

I have 18 lists, all of them allow dragging. I can drag between lists. However, I need to validate that the list to receive the new item is empty, if there is already another item in the list, it should not allow it. Is this possible somehow?

When a list is not empty, you should either use the option/pause method to pause it, or set its group so that it can or cannot interact with other lists.

Furthermore, I noticed that the documentation only has translations in English and Mandarin. If you are interested, I can try to help with the translation into Portuguese

Maintaining documentation for multiple versions increases our workload and complicates our documentation. It means that every time we add a new feature, we have to maintain documentation for multiple versions, which can be a very painful task. Of course, you can create a repository to manage documentation for respective versions, and we would greatly appreciate it if you do so.

I'm going to re-open this issue because it's still ongoing.
I have a list and within the list can be a group with another list.
Something like this structure:

Item A
Item B
Group A

Item AA
Item AB

Group B

Item BA
Item BB

What I am trying to do is prevent someone from dragging Group A into Group B, or vice verse. But, I still want Item A and Item B to be able to be dragged into either group. Just not a group into another group. Therefore, all 3 draggable instances (top level, Group A, and Group B) need to have the same group.
Sortablejs had the @move handler that you could optionally return false to prevent a certain move. This functionality does not seem to exist in this library at the present time.

OK, I finally got this working after some trial and error. First I had to change my implementation from component to useDraggable. This was fairly simple.
Next, for each list item that you are iterating over via a v-for=field in fields, add a data attribute. In my case I used this:
:data-draggable-group="isGroupModel(field)"
This either equates to true or false. We are going to use this data attribute to check if we're dragging into an invalid group. In my case (as shown in my previous comment), I want to prevent dragging a group into another group. But either way, the next part is where you can add whichever logic you need to make sure the user can indeed drop into the current list.
In the onMove event, this is the logic I have:
const onMove = (event: MoveEvent): boolean => {
  // if you try and move a group into another group, prevent the drag operation
  const from = event.dragged.dataset.draggableGroup
  const to = event.to.parentElement?.parentElement?.dataset.draggableGroup
  if (from && to) {
    draggableElement.pause() // draggableElement is the return value from `useDraggable()`
    return false
  }
  return true
}

This will pause dragging completely and prevent the drop.
Lastly, in the onEnd handler, simply put draggableElement.resume().
In the case of @luisrossi , you can change this onMove handler to instead check the length of the current list and make sure it's 0. Otherwise, pause the dragging and return false.


DocsArchive-<IP_ADDRESS>Auto archive content

Please don't merge this PR until target archive repo PR https://github.com/OPS-E2E-PPE/docs-yml-archive-non-versioning-archive/pull/25 is merged into live branch.
Auto archive content to https://github.com/VSC-Service-Account/docs-yml-archive-non-versioning-archive.git

Docs Build status updates of commit 386f9da:
:white_check_mark: Validation status: passed

File
Status
Preview URL
Details

.openpublishing.redirection.json
:white_check_mark:Succeeded

docs/TOC.yml
:white_check_mark:Succeeded
View

docs/to-be-archive/level1/article3-1-1.md
:white_check_mark:Succeeded
View

docs/to-be-archive/level1/article3-1-2.md
:white_check_mark:Succeeded
View

docs/to-be-archive/level1/article3-1-3.yml
:white_check_mark:Succeeded
View

docs/to-be-archive/level2/article3-2-1.md
:white_check_mark:Succeeded
View

docs/to-be-archive/level2/article3-2-2.md
:white_check_mark:Succeeded
View

docs/to-be-archive/level2/article3-2-3.yml
:white_check_mark:Succeeded
View

For more details, please refer to the build report.
Note: Broken links written as relative paths are included in the above build report. For broken links written as absolute paths or external URLs, see the broken link report.
For any questions, please:Try searching in the Docs contributor and Admin GuideSee the frequently asked questionsPost your question in the Docs support channel


TypeScript template literal support (const camel: "fooBar" = camelCase("foo_bar"))

Currently the functions output simple TypeScript strings. Template literals were introduced not too long ago, so now the following is possible:

const camel: 'fooBar' = camelCase('foo_bar')

That is, the exact string literal is derived from the input string literal.
Here's an article on how to achieve this: https://dev.to/svehla/typescript-transform-case-strings-450b
And another library already implements this (MIT license as well):
https://github.com/madonoharu/literal-case/blob/8d190d865cdcaf65ed639bdc40447410202f97a8/src/types.ts
Would be cool to see it at, least for some of the functions of this library.

I took a look but it's honestly too complex for me to consider maintaining for the marginal benefit it provides. You're welcome to type and maintain them here though if you'd like, but I'd probably consider keeping them separate from the main package due to the type complexity and potential build perf issues.


missing declared dependency (for pnpm compatibility)

Hi,
I'm using pnpm as package manager, and installing nsecure (0.9.1) with it leads to a failure
internal/process/esm_loader.js:74
    internalBinding('errors').triggerUncaughtException(
                              ^
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'timers' imported from /usr/pnpm-global/5/node_modules/.pnpm/@nodesecure+scanner<EMAIL_ADDRESS>
I guess that timers is missing in scanner dependencies (it works on npm and yarn because of flat dependencies tree, because timers should be a dependency of a scanner dependency).

timers is core Node.js dependencies.https://nodejs.org/dist/latest-v16.x/docs/api/timers.html

There are probably problems with pnpm anyway. I am not very familiar with it so I would have to look into it.

Ok, I'm running node 14 (because our production servers are running this version), which contains timers but not timers/promise required by @nodesecure/scanner
So it should be a bug in pnpm because it doesn't complain on installing nsecure (and "node": ">=16.1.0" is mentioned in nsecure package.json).
Sorry for the noise, thanks for the quick answer.

@dcaillibaud No problems 👌.


MinProtocol can only be used for TLS or DTLS, not both.

In openssl 1.1.1, only one value can be set to MinProtocol (https://www.openssl.org/docs/man1.1.1/man3/SSL_CONF_cmd.html)
If MinProtocol is set to "TLSv1.2", it is not possible for an application to use "DTLSv1.2".
To restrict the used protocol versions to the currently support ones >=1.2, you have to use the deprecated "Protocol" command:
# MinProtocol = TLSv1.2
Protocol = -SSLv3, -TLSv1, -TLSv1.1, TLSv1.2, TLSv1.3, -DTLSv1, DTLSv1.2

It should be possible, to set a minimal version for TLS and DTLS.
This issue (and possible solutions) have already been discussed on the openssl-users mailinglist<EMAIL_ADDRESS>

Thanks for opening the issue.  Before we get to implementation pull requests, any thoughts about whether my proposed solution of two new "CONF" parameters for DTLS min/max protocol is the way forward?

@mattcaswell Any feedback on my proposed way forward? Can you think of anyone else we should encourage to comment?

@mattcaswell Any feedback on my proposed way forward?

Your proposal seems the best route ahead.

@mattcaswell Any feedback on my proposed way forward?

Your proposal seems the best route ahead.

I started an implementation, and discovered that a small change of plan may be in order.  Specifically, while TLS version bounds would still apply only to TLS-based contexts and DTLS bounds only to DTLS-based contexts, it turns out much simpler to use a single configuration option name for both—MxxProtocol in config files and mxx-protocol in command-line options—and just specify the config file setting or command-line option twice, with an appropriate value for each protocol:
MinProtocol = TLSv1.2
MinProtocol = DTLSv1.2

With a modest documentation change, and a simple filter than applies the bound only to contexts of the right type this is by far the least disruptive implementation strategy, and in retrospect I think also makes for a reasonable interface.
Any objections?

On closer inspection, the requisite code was written (by me, of all people) back in 2015, but needs better docs and a couple of minor tweaks to be more forgiving when the bounds and SSL_CTX protocol don't match up.
@treibholz Please reply to the openssl-users post when you get a chance.

Unless the underlying problem is not what we expected, #12472 should address this issue.


Update Functions.swift

Fix buildServerURL to not include default port 8081 when running in localhost or <IP_ADDRESS>

Hi,
In ParseServerConfiguration the port 8081 is set as default and I didn't think touching all of that was way to go.
How do I " If there’s no port, you can make it not specify a default" ? as 8081 is set as the port by this point if there's no port set in ENV.
What do you think is best way to achieve this?  I'll be happy to fix it to work better in a general sense.

Would love to hear your thoughts on this and maybe get it a fix in pulled.

You have merged changes from your other branches into here. All of those changes need to be removed

Closing this, feel free to open another PR if you have a different fix.

thanks for the fix!


[FIX] fix doc (#6197)

Pull request opened by the merge tool on behalf of #6197

Merged into branches iso6 in b1ac06cba9857fc609ed00bb4f97f9aae7bc4cd6


Fixed reset phone email data error and removed dom API from ResetModal.js

Fixed:

reset phone email data error
send code button background color error
remoted dom api from ResetModal.js

Deployed at: https://door.chromium.link/
admin 123456

:tada: This PR is included in version 1.0.0 :tada:
The release is available on GitHub release
Your semantic-release bot :package::rocket: