odo service create should add operator CR to the devfile

/kind user-story
User Story
As a developer working with odo, when I add a new service to the application (like DB), I want to be able to easily share service definitions with my team so they can start the application with the service in the same way as me.
Acceptance Criteria

[ ] odo service create should not create any services on cluster
[ ] odo service create should store service definition in devfile as kubernetes component (ServiceInstance for SericeCatalog or CR for operator backed service)
[ ] odo service delete should delete the service from devfile (remove appropriate kubernetes component). Deletion from the cluster will happen once odo push is executed (similar to how we handle URLs).
[ ] odo service list should list services and their status. Important is to differentiate between statues like DeletedLocally, DeletedRemotely etc... (Similarly to what odo does for URLs)
[ ] odo link should add Service Binding information to devfile.yaml and odo unlink should remove it from the file. Subsequent odo push should create/delete the actual link (a Service Binding).

Links

Feature Request: https://github.com/openshift/odo/issues/4159
Related issue:

/kind user-story

It seems the Uri holds a link to the yaml or we can provide the yaml as a string in Inlined. both seem mutually exclusive.

I'm not sure what purpose does having both Inlined and Uri serve. When I read this, I think of Inlined as a string representation of the CRD used to spin up a CR. It would be the same as what we have right now when doing odo service create <operator-name>/<cr-name> --dry-run. Then what is Uri/reference in this case?
What is odo supposed to do with name? At the moment, we have odo service create etcdoperator.v0.9.4/EtcdCluster newetcd which creates a new service from the CR EtcdCluster provided by the Operator etcdoperator.v0.9.4 and names it as newetcd. Should odo use the value in name for the newly created service?

devfile/api#36

This is a proposal, IIUC. Do we have to implement things based on this proposal? Or do we use Kubernetes/OpenShift lingo instead? If we should be using Kubernetes/OpenShift based on current devfile schema, what happens when this change goes in? We make changes to work with the new terminology?
Few other questions (more along the lines of "thinking out loud"):

What's the timeline for this? It seems more like an epic than a user story to me.
What about Service Catalog backed services? Are we planning to support those in the new approach?
What about the combination of "s2i components" + "Service Catalog services"? Are we planning to support that using existing tooling using if..else that we had for experimental mode?
How does this play with devfile parser that's being moved out to a separate project? What parts are supposed to be handled by devfile parser and what is to be handled by odo?

Then what is Uri/reference in this case?

I think inline and Uri/reference are mutually exclusive. i.e. if you provide inline then you then the uri would be ignored.

What's the timeline for this? It seems more like an epic than a user story to me.

well I was hoping for this to be done in this sprint?

What about Service Catalog backed services? Are we planning to support those in the new approach?

Yeah that is something I was thinking alot about and right now I would say no - because you need to consider the problem of have an s2i component with
Some more thinking on what kind of combination we are looking ait

[ ] devfile component + operator backed service - scoped in this issue

[ ] devfile component + service catalog services - we could store the service template in the devfile directly

[ ] s2i component + operator backed service - we dont have a devfile for s2i component so we might need to add the CR in the config.yaml. So imagine an interface ServiceStorageProvider that can be implemented by a config.yaml and the devfile?

[ ] s2i component + service catalog service - again store the service template in the config.yaml

I bet there is a newer service catalog CR someone would have implemented to move the service catalog into an operator but I haven't searched about it.

I think we might need to consider deprecating s2i components

Sorry about writing an essay. I have a lot of questions around this and I couldn't find a better way to put it.

I think inline and Uri/reference are mutually exclusive. i.e. if you provide inline then you then the uri would be ignored.

OK. And what would be a valid value for URI in this case? What would we like to store as URI?
About storing the CRD in devfile. Currently, we don't support passing parameters for odo service create when the user wants to spin up an Operator backed service. I think, storing CRD in devfile would be a lot more valuable when we have this support.
Then there's also this notion of keeping the information in devfile compatible with what Che might need.

well I was hoping for this to be done in this sprint? only the devfile + operator backed service and that too just adding the CR into the devfile and still do that original work so we dont break operator backed services. Essentially do what odo service create does and also store the CR in the devfile for now.

If we put the CRD (the definition used to bring up the CR, a.k.a. service, provided by an Operator) in the devfile when doing odo service create, and if odo push fails to bring up the service for some reason, what do we do about the info that's gone into devfile? Should we delete it. What if this happens when user2 is cloning the code provided by user1 and odo push fails to spin up the service because the required Operator doesn't exist on their environment? Deleting the CRD from devfile might be a bad idea in that case. Also, does thinking of failure scenarios from odo watch's perspective add any other challenges?
Also, if I understand correctly, you mean to only add the CRD into devfile as Step 1 and not changing the flow to create the service when doing odo push. Sounds doable.

Yeah that is something I was thinking alot about and right now I would say no.

OK. So what would be our approach to handle it? Separate code (as is the case right now)? Do we want to provide different UX to the users when they spin up a service using Operators vs. Service Catalog? By different approach, I mean that if we store CRD info in devfile, we eventually want to provide the ability to create a component+service in one odo push when, say, user2 clones the repo on their system. But this wouldn't hold true for Service Catalog based services.
From k8s point of view, I don't think we will/should be deprecating support for Service Catalog in a rush. OTOH, we could also deprecate it since it's no longer available on OCP and focus solely on Operators. This reduces the scope of bugs in odo code. IMO, we should think this hard because supporting both requires considering a lot of permutations and combinations.
This piece is confusing and I'd prefer we think of reaching a conclusion sooner rather than later.

[ ]  devfile component + operator backed service - scoped in this issue

This means storing the CRD in the devfile. It doesn't mean actually spinning up a service when doing odo push after odo service create stores the info in devfile. Should we add a few unambiguous acceptance criteria to this issue?

[ ]  devfile component + service catalog services - we could store the service template in the devfile directly

At the moment, this scenario is not supported. I think I need to come up with a matrix about all the possibilities and their support status. Otherwise, this is quickly going to become insane.

[ ] s2i component + operator backed service - we dont have a devfile for s2i component so we might need to add the CR in the config.yaml. So imagine an interface ServiceStorageProvider that can be implemented by a config.yaml and the devfile?
[ ] s2i component + service catalog service - again store the service template in the config.yaml ( many other things are possible so think about this point )

We discussed under the hood conversion of s2i components to devfile on the Cabal. So I think this needs a rethink?

I bet there is a newer service catalog CR someone would have implemented to move the service catalog into an operator but I haven't searched about it.

I'm not so sure about the CR/Operator for Service Catalog. But I think we can give a try to the steps mentioned here on a minikube setup. But again, I'd prefer we discuss how long we intend to support it. And I am seeking this info only because OCP doesn't support it anymore.

Sorry about writing an essay. I have a lot of questions around this and I couldn't find a better way to put it.

I think inline and Uri/reference are mutually exclusive. i.e. if you provide inline then you then the uri would be ignored.

OK. And what would be a valid value for URI in this case? What would we like to store as URI?

It would be a public link to a kubernetes manifest and when there is something inline then the uri would be blank.
reference: https://.../mongo.yaml

About storing the CRD in devfile. Currently, we don't support passing parameters for odo service create when the user wants to spin up an Operator backed service. I think, storing CRD in devfile would be a lot more valuable when we have this support.

Agreed but for now lets not add the functionality of passing parameters - first step is simple and that is store the CRD in the devfile then maybe we can think about this

Then there's also this notion of keeping the information in devfile compatible with what Che might need.

well I was hoping for this to be done in this sprint? only the devfile + operator backed service and that too just adding the CR into the devfile and still do that original work so we dont break operator backed services. Essentially do what odo service create does and also store the CR in the devfile for now.

If we put the CRD (the definition used to bring up the CR, a.k.a. service, provided by an Operator) in the devfile when doing odo service create, and if odo push fails to bring up the service for some reason, what do we do about the info that's gone into devfile? Should we delete it. What if this happens when user2 is cloning the code provided by user1 and odo push fails to spin up the service because the required Operator doesn't exist on their environment? Deleting the CRD from devfile might be a bad idea in that case. Also, does thinking of failure scenarios from odo watch's perspective add any other challenges?

I asked the same question to tomas and he mentioned that the person who added the service operator in the devfile knows that their application wont function correctly without it so the person cloning the application should have the operator present and if not - its a good thing that push fails. We need to provide good error messages here though

Also, if I understand correctly, you mean to only add the CRD into devfile as Step 1 and not changing the flow to create the service when doing odo push. Sounds doable.

Yes as this flow of storing the CRD in the devfile is still a smaller part of the whole puzzle we need to keep the original work intact until the new flow is completely implemented

Yeah that is something I was thinking alot about and right now I would say no.

OK. So what would be our approach to handle it? Separate code (as is the case right now)? Do we want to provide different UX to the users when they spin up a service using Operators vs. Service Catalog? By different approach, I mean that if we store CRD info in devfile, we eventually want to provide the ability to create a component+service in one odo push when, say, user2 clones the repo on their system. But this wouldn't hold true for Service Catalog based services.
From k8s point of view, I don't think we will/should be deprecating support for Service Catalog in a rush. OTOH, we could also deprecate it since it's no longer available on OCP and focus solely on Operators. This reduces the scope of bugs in odo code. IMO, we should think this hard because supporting both requires considering a lot of permutations and combinations.
This piece is confusing and I'd prefer we think of reaching a conclusion sooner rather than later.

[ ]   devfile component + operator backed service - scoped in this issue

This means storing the CRD in the devfile. It doesn't mean actually spinning up a service when doing odo push after odo service create stores the info in devfile. Should we add a few unambiguous acceptance criteria to this issue?

[ ]   devfile component + service catalog services - we could store the service template in the devfile directly

At the moment, this scenario is not supported. I think I need to come up with a matrix about all the possibilities and their support status. Otherwise, this is quickly going to become insane.

[ ]  s2i component + operator backed service - we dont have a devfile for s2i component so we might need to add the CR in the config.yaml. So imagine an interface ServiceStorageProvider that can be implemented by a config.yaml and the devfile?
[ ]  s2i component + service catalog service - again store the service template in the config.yaml ( many other things are possible so think about this point )

We discussed under the hood conversion of s2i components to devfile on the Cabal. So I think this needs a rethink?

I bet there is a newer service catalog CR someone would have implemented to move the service catalog into an operator but I haven't searched about it.

I'm not so sure about the CR/Operator for Service Catalog. But I think we can give a try to the steps mentioned here on a minikube setup. But again, I'd prefer we discuss how long we intend to support it. And I am seeking this info only because OCP doesn't support it anymore.

OK. And what would be a valid value for URI in this case? What would we like to store as URI?

It would be a public link to a kubernetes manifest and when there is something inline then the uri would be blank.
reference: https://.../mongo.yaml

:+1: makes sense.

About storing the CRD in devfile. Currently, we don't support passing parameters for odo service create when the user wants to spin up an Operator backed service. I think, storing CRD in devfile would be a lot more valuable when we have this support.

Agreed but for now lets not add the functionality of passing parameters - first step is simple and that is store the CRD in the devfile then maybe we can think about this

Ah, I didn't mean to stall this till we have parameters support. Totally agree about adding CRD info into devfile as a first step.

If we put the CRD (the definition used to bring up the CR, a.k.a. service, provided by an Operator) in the devfile when doing odo service create, and if odo push fails to bring up the service for some reason, what do we do about the info that's gone into devfile? Should we delete it. What if this happens when user2 is cloning the code provided by user1 and odo push fails to spin up the service because the required Operator doesn't exist on their environment? Deleting the CRD from devfile might be a bad idea in that case. Also, does thinking of failure scenarios from odo watch's perspective add any other challenges?

I asked the same question to tomas and he mentioned that the person who added the service operator in the devfile knows that their application wont function correctly without it so the person cloning the application should have the operator present and if not - its a good thing that push fails. We need to provide good error messages here though

OK. So if the push fails for user2, what do we want the state of the component to be? Only the service creation on the cluster fails for them or does the entire push become invalid? I get it that this is not a part of the first step we just agreed on above, but this is going to be the next step, IIUC.
Other questions remain unanswered. Can we discuss this as well because there are a lot of possible scenarios that we need to think of? cc @kadel
In the meantime, I'll start looking into adding just the CRD to the devfile.

The first thing that needs to be addressed is https://github.com/openshift/odo/issues/4159
Otherwise, services stored in Devfile can't be created.
Once we have that odo service create should be quite simple.
Instead of creating Kubernetes resources in cluster it will save it into devfile as inlined kubernetes component
For example command odo service create mongodb-enterprise.v1.8.0/MongoDB mymongo will add a new component into Devfile that looks like this:
components:
  - name: mymongo
    kubernetes:
      inlined: >
        apiVersion: mongodb.com/v1
        kind: MongoDB
        metadata:
          name: mymongo
        spec:
          credentials: my-credentials
          members: 3
          opsManager:
            configMapRef:
              name: my-project
          persistent: true
          type: ReplicaSet
          version: 4.4.0-ent
        status:
          phase: Running
          type: ReplicaSet

odo service create etcdoperator.v0.9.4-clusterwide/EtcdCluster myetcd --dry-run > myetcd.yaml
odo service create --from-file myetcd.yaml

Will save the content of myetcd.yaml as a new kubernetes component in Devfile
components:
  - name: myetcd
    kubernetes:
      inlined: >
        apiVersion: etcd.database.coreos.com/v1beta2
        kind: EtcdCluster
        metadata:
          annotations:
            etcd.database.coreos.com/scope: clusterwide
          name: myetcd
        spec:
          size: 3
          version: 3.2.13

Similarly with service catalog
odo service create mariadb --plan 10-3-22 --parameters  param-1=value-1 --parameters  param-2=value-2
should result in adding the following kubernetes component into the devfile
components:
  - name: mymaria
    kubernetes:
      inlined: >
        apiVersion: servicecatalog.k8s.io/v1beta1
        kind: ServiceInstance
        metadata:
          name: mymaria
          namespace: tkral-test
        spec:
          clusterServiceClassExternalName: mariadb
          clusterServicePlanExternalName: 10-3-22
          parameters:
            param-1: value-1
            param-2: value-2

But again, before we tackle this we need to make sure that odo understands kubernetes  components
https://github.com/openshift/odo/issues/4159. This needs to be the first step.

odo service create etcdoperator.v0.9.4-clusterwide/EtcdCluster myetcd --dry-run > myetcd.yaml
odo service create --from-file myetcd.yaml

We can get rid of the --dry-run and --from-file entirely because odo service create will store the CR in the devfile so a user can open the devfile and edit it before doing a odo push if they want to. And --from-file makes no sense either once we start storing the CRD in devfile.
But how/where do we want to store link related information?

But how/where do we want to store link related information?

We need to create a separate issue for this.
The link will come as next after we have https://github.com/openshift/odo/issues/4159 and this one.
It will work similarly as odo service create. odo link will store ServiceBinding CR in devfile as a kubernetes component. And then it will be created later by running odo push.

This will not be possible to do before #4159 which is in turn dependent on https://github.com/devfile/api/issues/216.

Scope of this issue for Sprint 197
Focussing on second acceptance criteria -  odo service create should store service definition in devfile as kubernetes component (ServiceInstance for SericeCatalog or CR for operator backed service)

Store alm example of a CR into devfile.
Store ServiceInstance info into devfile (still not sure about how to fetch this.)
Involves updating dependency to devfile v2. (#4346)

Function signature has changed for GetComponents which is used at various places in odo code. Will have to update related unit tests as well.

Add unit tests and integration tests.

what about odo service create --from-file? CR defined in the file should also be saved in Devfile

Store ServiceInstance info into devfile (still not sure about how to fetch this.)

Managed to figure this out. For a devfile based component, when the user tries to create a Service Catalog backed service, the info gets added to devfile.yaml:
$ odo service create dh-postgresql-apb psql --plan dev -p postgresql_user=luke -p postgresql_password=secret -p postgresql_database=my_data -p postgresql_version=9.6
Deploying service "psql" of type: "dh-postgresql-apb"
 ✓  Service "psql" was created

Progress of the provisioning will not be reported and might take a long time
You can see the current status by executing 'odo service list'
Optionally, link "dh-postgresql-apb" to your component by running: 'odo link <component-name>'

$ cat devfile.yaml
commands:
- exec:
    commandLine: npm install
    component: runtime
    group:
      isDefault: true
      kind: build
    workingDir: /project
  id: install
- exec:
    commandLine: npm start
    component: runtime
    group:
      isDefault: true
      kind: run
    workingDir: /project
  id: run
- exec:
    commandLine: npm run debug
    component: runtime
    group:
      isDefault: true
      kind: debug
    workingDir: /project
  id: debug
- exec:
    commandLine: npm test
    component: runtime
    group:
      isDefault: true
      kind: test
    workingDir: /project
  id: test
components:
- container:
    endpoints:
    - name: http-3000
      targetPort: 3000
    image: registry.access.redhat.com/ubi8/nodejs-14:latest
    memoryLimit: 1024Mi
    mountSources: true
    sourceMapping: /project
  name: runtime
- kubernetes:
    inlined: |
      apiVersion: servicecatalog.k8s.io/v1beta1
      kind: ServiceInstance
      metadata:
        creationTimestamp: null
        labels:
          app: app
          app.kubernetes.io/instance: psql
          app.kubernetes.io/managed-by: odo
          app.kubernetes.io/managed-by-version: v2.0.5
          app.kubernetes.io/name: dh-postgresql-apb
          app.kubernetes.io/part-of: app
        name: psql
        namespace: myproject
      spec:
        clusterServiceClassExternalName: dh-postgresql-apb
        clusterServicePlanExternalName: dev
        externalID: ""
        parameters:
          postgresql_database: my_data
          postgresql_password: secret
          postgresql_user: luke
          postgresql_version: "9.6"
        updateRequests: 0
      status:
        asyncOpInProgress: false
        conditions: null
        deprovisionStatus: ""
        observedGeneration: 0
        orphanMitigationInProgress: false
        provisionStatus: ""
        reconciledGeneration: 0
  name: psql
metadata:
  name: nodejs
  version: 2.0.0
schemaVersion: 2.0.0
starterProjects:
- git:
    remotes:
      origin: https://github.com/odo-devfiles/nodejs-ex.git
  name: nodejs-starter

However, for an s2i based component, this won't work till we have addressed #4281 so that a devfile.yaml is created for odo create --s2i.

odo service delete should delete the entry from devfile for both Operators & Service Catalog.

This is currently blocked on https://github.com/devfile/api/issues/306.

What's done so far (#4465):

odo service create adds CRD (Operators) and ServiceInstance (Service Catalog) yaml into devfile.yaml.
Library has been updated from v1 to v2 by Mrinal

What's pending (scope of this issue for Sprint 198):

[ ] Remove CRD and ServiceInstance yaml from devfile.yaml when user does odo service delete. This can be done only after https://github.com/devfile/library/pull/65 is merged
[ ] Tests.

@kadel PR #4465 implements the items discussed in https://github.com/openshift/odo/issues/4160#issuecomment-790577742 and https://github.com/openshift/odo/issues/4160#issuecomment-775838428. It's in review and I need to make a few changes to it for it to get merged.
But overall, this issue has wider scope. For Sprint 199, what would you think we should cover in the scope?
There's one question that I mentioned on a few calls - how would odo know which service to delete when odo service delete removes the service info from devfile.yaml? You mentioned that we don't want to store service related info in env.yaml. Then how do you suggest we show status information to the user when they do odo service delete (one of the acceptance criteria)?
I've added odo link/unlink to acceptance criteria as well because odo link is creating an Operand of the Service Binding Operator.

A complete picture of how this should work at the end.

odo service create - adds Operator Backed Service CR to devfile.yaml as a kubernetes component.
odo push reads the content of the devfile and creates its representation on the cluster. Every Kubernetes resource created from the devfile needs to be labeled at least with the following labels: app.kubernetes.io/instance, app.kubernetes.io/managed-by, app.kubernetes.io/name

Those labels are odo implementation-specific. They should not appear in devfile.yaml.

odo push needs to be able to detect differences between the cluster and local state (devfile.yaml). For example, somewhere early in the process, it needs to list all CRs in a given namespace with matching app.kubernetes.io/instance, app.kubernetes.io/managed-by, app.kubernetes.io/name labels and compare that list with kuberentes components in devfile.

If resource matching the labels is present in the cluster and it is not present in devfile, that is an indication that it was previously deleted from devfile using odo service delete and it should be removed from the cluster.

odo service list should have additional fields to let the user know if the service is managed by odo or not.▶ odo service list
NAME                      MANAGED BY          STATE
EtcdCluster/example          odo            Locally Deleted
PostgresSQLCluster/example   odo            Not Pushed
PostgresSQLCluster/example2  odo            Pushed
Someting/else
Someting/else2               other-tool

The information for MANAGED BY column is taken from app.kubernetes.io/managed-by label. Services managed by odo are listed first.
STATE column indicates the differences between the cluster and devfile. It makes sense only for services managed by odo.
Locally Deleted - present on the cluster but not in the devfile (next odo push will delete it from the cluster)
Not Pushed - present in the devfile but not on the cluster (next odo push will create it in the cluster)
Pushed -  present in both places (next odo push will do nothing or update the existing CR if is is not the same as in devfile)

odo service delete - deletes the service from devfile. This means that executing it on a service that is not managed by odo will fail.

Locally Deleted - present on the cluster but not in the devfile (next odo push will delete it from the cluster)

So odo push should be smart to check for this states and do relevant actions every time, right? Now consider this scenario:

I have two components having their own component directories. Let's call them c1 and c2.
I created a service called s1 from c1's dir. odo makes an entry in devfile. Subsequent odo push from c1's dir creates the service s1 on cluster.
Now I need to do something with c2. I cd into its component directory. Now let's say I only modified something related to code. And I do odo push.
But odo push is smart, and it checks that a service s1 on the cluster is not present in devfile and deletes service s1.

What is the right thing to do? How do you suggest odo do the right thing?

But odo push is smart, and it checks that a service s1 on the cluster is not present in devfile and deletes service s1.

no it won't. If you did odo push from c2 dir won't touch s1 service, because that belongs to c1, odo know that from labels.

odo service list should have additional fields to let the user know if the service is managed by odo or not.

Considering the same example that I gave in https://github.com/openshift/odo/issues/4160#issuecomment-805817724, should odo service list show all services across all components in the namespace or should it only list the services matching the label of a component?
If we go with the former, we could keep odo service list runnable from any directory on the system. Also, should odo link allow linking between services managed by different components in this case? As in, if service s1 was started from component c1's context, should component c2 be able to link to service s1 since it can see the service s1 in the output of odo service list?
If we go with the latter, we need to make sure that odo service list is executed from a valid component directory only.

▶ odo service list
NAME                      MANAGED BY          STATE
EtcdCluster/example          odo            Locally Deleted
PostgresSQLCluster/example   odo            Not Pushed
PostgresSQLCluster/example2  odo            Pushed
Someting/else
Someting/else2               other-tool

When we show other-tool in above output to the user, should we figure out what tool is managing it? If yes, how do we ensure that other tools will use the same label as odo does? If no, should we just put hardcoded string other-tool to indicate that it's not managed by odo? Can we instead change the column name to MANAGED BY ODO and print a tick or a cross indicating true or false? (thinking out loud)

Well that's a lot of questions :). Let me give answering them a try:

odo service list should have additional fields to let the user know if the service is managed by odo or not.

Considering the same example that I gave in #4160 (comment), should odo service list show all services across all components in the namespace or should it only list the services matching the label of a component?

All, because you might want to link to a service you just created within the component, or you might want to link to an 'external' service or one that already exists on the cluster.

If we go with the former, we could keep odo service list runnable from any directory on the system.

I think that's a very good goal that we should try to keep. The labels should still tell us if some of them are part of a component, and we can show that, we just won't know if that component is local, on someone else's machine, or whatever.

Also, should odo link allow linking between services managed by different components in this case? As in, if service s1 was started from component c1's context, should component c2 be able to link to service s1 since it can see the service s1 in the output of odo service list?

I don't know if that's a frequent case, but yes, I think it should be possible. To c2 it's just another service and doesn't particularly care how it got there.

If we go with the latter, we need to make sure that odo service list is executed from a valid component directory only.

I don't follow that. If you're outside wouldn't it still know that s1 came from c1?

▶ odo service list
NAME                      MANAGED BY          STATE
EtcdCluster/example          odo            Locally Deleted
PostgresSQLCluster/example   odo            Not Pushed
PostgresSQLCluster/example2  odo            Pushed
Someting/else
Someting/else2               other-tool

When we show other-tool in above output to the user, should we figure out what tool is managing it? If yes, how do we ensure that other tools will use the same label as odo does? If no, should we just put hardcoded string other-tool to indicate that it's not managed by odo? Can we instead change the column name to MANAGED BY ODO and print a tick or a cross indicating true or false? (thinking out loud)

We should use labels that are as standard as we can find, but I agree not every tool will use them, and so we won't know anything about those services. If you were in c2's folder I thought the output might look something like this:

▶ odo service list
NAME                      MANAGED BY          STATE
EtcdCluster/example          c1
PostgresSQLCluster/example   c2            Not Pushed
PostgresSQLCluster/example2  c2            Pushed
Someting/else                app7
Someting/else2               unknown

c1 was pushed by odo (maybe we could indicate this as well), but since we don't know where it came from we don't know the status. We're in c2 so we can output the status of those. app7 came from a different tool, but since it used labels we can at least fill the 'managed by' in, and the last service didn't have any labels.

If we go with the latter, we need to make sure that odo service list is executed from a valid component directory only.

I don't follow that. If you're outside wouldn't it still know that s1 came from c1?

If we add the MANAGED BY column to odo service list, I think it'll be possible to know from anywhere that s1 belongs to component c1.
I'm assuming that MANAGED BY indicates an odo component here and not a tool (odo/ODC/CRW.) That's different from what @kadel suggested in MANAGED BY (more around which tool manages it rather than which odo component.)

If you were in c2's folder I thought the output might look something like this:
▶ odo service list
NAME                      MANAGED BY          STATE
EtcdCluster/example          c1
PostgresSQLCluster/example   c2            Not Pushed
PostgresSQLCluster/example2  c2            Pushed
Someting/else                app7
Someting/else2               unknown

c1 was pushed by odo (maybe we could indicate this as well), but since we don't know where it came from we don't know the status. We're in c2 so we can output the status of those. app7 came from a different tool, but since it used labels we can at least fill the 'managed by' in, and the last service didn't have any labels.

Makes sene. We'll need to make docs clearly say that STATE can be expected only when working from a component dir.
I'll try to jot down the scope based on what we discussed on this issue. Thanks for your inputs @kadel & @deboer-tim

Scope for next pass on this issue:

[ ] Get #4465 merged!
[ ] odo push should invisibly set labels to the component - "invisibly" means label info won't be stored in devfile because same devfile can be used by other tools (ODC/CRW) and each tool should assign labels of their own.
[ ] odo push should create the service on the cluster instead of odo service create doing it right now.

[ ] Operators
[ ] Service Catalog

[ ] odo push should delete the service from the cluster instead of odo service delete doing it right now.

[ ] Operators
[ ] Service Catalog

odo push should create the service on the cluster instead of odo service create doing it right now.

I'm considering adding the code to create service right before https://github.com/openshift/odo/blob/16946d4068f30f1e51cecc64877e535338b043b2/pkg/devfile/adapters/kubernetes/component/adapter.go#L175-L178
Thinking along these lines because there's a call to the function WaitForDeploymentRollout. And I'm taking it literally as a function that will wait for something to complete.
@kadel @mik-dass @girishramnani @valaparthvi if you have a differing opinion/suggestion, let me know.

Scope of this issue for Sprint 201:

[ ] odo service list should show output like below from the component directory of component-1:$ odo service list
NAME                       MANAGED BY ODO    STATE
EtcdCluster/etcd-1         component-1       Pushed
EtcdCluster/etcd-2         component-2       Pushed
EtcdCluster/etcd-3         component-1       Not Pushed
EtcdCluster/etcd-4         component-1       Deleted Locally

[ ] odo service delete should delete the service only from devfile.yaml; odo push should delete the service from the cluster.
[ ] Tests

I'll defer documentation till we have properly defined structure via #4664.

  ```shell
  $ odo service list
  NAME                       MANAGED BY ODO    STATE
  EtcdCluster/etcd-1         component-1       Pushed
  EtcdCluster/etcd-2         component-2       Pushed
  EtcdCluster/etcd-3         component-1       Not Pushed
  EtcdCluster/etcd-4         component-1       Deleted Locally
  ```

@feloy I noticed that the state doesn't show up when running this command outside of a component directory. I don't think I have a question here, just an fyi, or is this expected for now and we'll be iterating over it?
➜  odo git:(pr/4819) odo service list
NAME               MANAGED BY ODO     STATE     AGE
Database/bkddb     Yes (bkd)                    15m22s


Test OBS scripts with mock

What type of PR is this?
/kind ci
What this PR does / why we need it:
Be able to test the OBS scripts with a mock flag.
Which issue(s) this PR fixes:

None
Special notes for your reviewer:
None
Does this PR introduce a user-facing change?

None

This does not work, a OSC checkout is not possible unauthenticated.


Generate Password contain double quotes (") and backslash ()

In most of the case password not accept double-quotes (") and backslash () but Generate password function generate these symbols.
Need to remove these from generate.go.

You can customize the list of letters, symbols, numbers, etc. Create a new generator object and alter the list of symbols to be a string of the allowed symbols (e.g. "!@#$%^&*()") and it will only generate from those symbols.
gen, err := password.NewGenerator(&password.NewGeneratorInput{
  Symbols: "PUT YOUR LIST OF SYMBOLS HERE AS A SINGLE STRING",
})
if err != nil {
  # ...
}

gen.Generate(...)

Sorry, my bad...
I used your example from README.
Just for a suggestion, you can add these in README it will be more helpful.


Solves #34

the following video contains preview of the functioning of the code. If u find it appropriate please merge it.
https://user-images.githubusercontent.com/102437896/196825210-e30bfb9e-4827-4d7d-9725-1cb18b21c031.mp4

Your code will delete cases like:
<textarea><!-- is not a comment --></textarea>

also will delete cases like:
 <!-- is not a comment -->


unable to test the learnt model because customed_goal_sampler is not loaded

Hi, when I was running run_goal_conditioned_policy.py, an error occurred saying custom_goal_sampler is None. And I checked that VAEWrappedEnv.__getstate__ ignored its _custom_goal_sampler. Then there is no data load while the object is loaded from .pkl file.
Is there any method to make the goal sampling work while testing the trained model?

Good catch. You'd have to set the custom_goal_sampler after creating the environment. If you search for how it's set during training, you'll see how to do it (look in the launcher.py file). A PR to add this to the run_goal_conditioned_policy.py file would be welcomed!

Something confused me. During training, it seems the VAEWrapperedEnv object's __goal_sampling_mode has never been to 'custom_goal_sampler', why it suddenly changed into 'custom_goal_sampler' during loading?
BTW, I'm running using sawyer_door.py.

Yes, so in that experiment, during autonomous exploration, we sample goals from the replay buffer since the policy doesn't have access to any oracle sampler. However, for testing you might want to have some "oracle goal sampler" and you can implement that using the custom goal sampler.

So, there are some 'software engineering' problems. If I'm going to implement an "oracle goal sampler", what is the required output in order to match the repository interface?

Good question! Yeah, this part of the code is a bit "untyped"/undocumented. Based on VAEWrappedEnv.samples_goals, the signature should be
def goal_sampler_function(batch_size):
  return dict_of_goals

where dict_of_goals is something like:
{
  'desired_goals': NUMPY_ARRAY # shape (batch_size x latent_dim),
  'other_desired_goal: NUMPY_ARRAY # shape (batch_size x feature_dim),
}


Add flag to exit with 1 if no results found

The --fail-if-no-results-found flag exit with status code 1 if no
search results found during helm search repo and helm search hub
commands.  This is useful for automation scripts.
closes #7197
Signed-off-by: Baiju Muthukadan<EMAIL_ADDRESS>
What this PR does / why we need it:
Special notes for your reviewer:
If applicable:

[ ] this PR contains documentation
[x] this PR contains unit tests
[x] this PR has been tested for backwards compatibility

@baijum This is failing CI. Can you take a look?


Generic parameters constrained to unions of tuples are not inferred correctly in rest parameter positions

TypeScript Version:  3.1.0-dev.20180813
Search Terms:
Tuple rest generic union
Code
declare function hmm<A extends [] | [number, string]>(...args: A): void;
hmm(); // okay, A = []
hmm(1, "s"); // okay, A = [1, "s"]
hmm("what"); // no error?  A = [] | [number, string] ?

Expected behavior:
Error on hmm("what").  A should be inferred as [string], which does not extend [] | [number, string].
Actual behavior:
No error on hmm("what").  Apparently A is inferred as the constraint type [] | [number, string] despite that not matching the actual argument type.
Playground Link:
Link
Related Issues:
#24897: introduction of tuples into rest/spread expressions
#26110: similar issue with bad or weird inference behavior on rest arguments

@ahejlsberg I'm probably missing something here but this seems bad


Error: parent directory is world writable but not sticky

when install composer,have this error
brew install josegonzalez/php/composer
...
Error: parent directory is world writable but not sticky
Installing composer from josegonzalez/php
==> Installing dependencies for josegonzalez/php/composer: libpng, freety
==> Installing josegonzalez/php/composer dependency: libpng
==> Downloading https://homebrew.bintray.com/bottles/libpng-1.6.23.yosemite.bott
######################################################################## 100.0%
==> Pouring libpng-1.6.23.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/libpng/1.6.23: 25 files, 1.2M
==> Installing josegonzalez/php/composer dependency: freetype
==> Downloading https://homebrew.bintray.com/bottles/freetype-2.6.3.yosemite.bot
######################################################################## 100.0%
==> Pouring freetype-2.6.3.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/freetype/2.6.3: 61 files, 2.5M
==> Installing josegonzalez/php/composer dependency: gettext
==> Downloading https://homebrew.bintray.com/bottles/gettext-<IP_ADDRESS>.yosemite.b
#######                                                                   10.7%
curl: (56) SSLRead() return error -9806
Error: Failed to download resource "gettext"
Download failed: https://homebrew.bintray.com/bottles/gettext-<IP_ADDRESS>.yosemite.bottle.tar.gz
Warning: Bottle installation failed: building from source.
==> Downloading https://ftpmirror.gnu.org/gettext/gettext-<IP_ADDRESS>.tar.xz
==> Downloading from http://mirrors.ustc.edu.cn/gnu/gettext/gettext-<IP_ADDRESS>.tar
######################################################################## 100.0%
==> ./configure --disable-silent-rules --prefix=/usr/local/Cellar/gettext/0.19.8
==> make
==> make install
Error: parent directory is world writable but not sticky
Please report this bug:
    https://git.io/brew-troubleshooting
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/tmpdir.rb:92:in `mktmpdir'
/usr/local/Library/Homebrew/utils/fork.rb:6:in `safe_fork'
/usr/local/Library/Homebrew/formula_installer.rb:574:in `build'
/usr/local/Library/Homebrew/formula_installer.rb:236:in `install'
/usr/local/Library/Homebrew/formula_installer.rb:436:in `install_dependency'
/usr/local/Library/Homebrew/formula_installer.rb:387:in `block in install_dependencies'
/usr/local/Library/Homebrew/formula_installer.rb:387:in `each'
/usr/local/Library/Homebrew/formula_installer.rb:387:in `install_dependencies'
/usr/local/Library/Homebrew/formula_installer.rb:188:in `install'
/usr/local/Library/Homebrew/cmd/install.rb:269:in `install_formula'
/usr/local/Library/Homebrew/cmd/install.rb:149:in `block in install'
/usr/local/Library/Homebrew/cmd/install.rb:149:in `each'
/usr/local/Library/Homebrew/cmd/install.rb:149:in `install'
/usr/local/Library/brew.rb:87:in `<main>'

Yikes, I haven't seen this crop up for a while.
brew doctor contains fix instructions, but if you can't execute brew doctor for some reason the answer is sudo chmod +t /tmp unless you've manually set a different HOMEBREW_TEMP.

Thank you very much for helping me resolve this issue. After use brew doctor,l also find other problem,  /usr/bin occurs before /usr/local/binand l found how to resolve it in http://stackoverflow.com/,but l can't find the page now,it say rewrite etc/paths,and list how to rewrite, l just copy it and didn't see if l have the directory. so when lsource ~/.bash_profile`, many commands l can't use , l found the problem is in the file etc/paths have one path is wrong.l modified this file,and restart computer or restart apache,or source etc/paths,source ~/.bash_profile, it isn't work. The wrong path also in the terminal.
-bash: /usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin: No such file or directory
-bash: /usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin: No such file or directory
-bash: /usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin: No such file or directory

/usr/local/sbin  this one
In etc/paths already not exists,l don't understand why still load it when open terminal.
l'm sorry for my poor english, could you give me some suggestions?
@DomT4

echo $PATH
/usr/local/bin:/usr/local/mysql/bin:.

the first is set by  etc/profile
the second  is  set by ~/.bash_profile
so all  in the etc/paths isn't work
etc/paths
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin

l know how to resolve it! my bash_profile is wrong too,open it in terminal is different from open in the l don't know how to call it ,the txt editor,maybe.
thank you again.~


The error message for CURL accessing SSL certificate expiration on MAC OS is: No such file or directory

I did this
I used curl to access an HTTPS website, but due to the SSL certificate of the website expiring, the error message from curl made it difficult for me to understand

curl https://<IP_ADDRESS>:8000/
His error is like this
curl: (35) OpenSSL/3.3.1: error:80000002:system library::No such file or directory
use curl -v https://<IP_ADDRESS>:8000/
His suggestion is

Host <IP_ADDRESS>:8000。was resolved.
IPv6: (none)
IPv4: <IP_ADDRESS>
Trying <IP_ADDRESS>:8000 .....
Connected to <IP_ADDRESS> port 8000
ALPN: curl offers h2,http/1.1
TLSv1.3 (OUT), TLS handshake, Client hello (1):
TLSv1.3 (IN), TLS handshake, Server hello (2):
TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
TLSv1.3 (IN), TLS handshake, Certificate (11):
TLSv1.3 (OUT), TLS alert, certificate expired (557):
OpenSSL/3.3.1: error:80000002:system library::No such file or directory
closing connection #0
curl: (35) OpenSSL/3.3.1: error:80000002:system library::No such file or directory
I expected the following
Prompt SSL certificate is invalid
curl/libcurl version
curl 8.9.1 (x86_64-apple-darwin21.6.0) libcurl/8.9.1 OpenSSL/3.3.1 (SecureTransport) zlib/1.2.11 brotli/1.1.0 zstd/1.5.6 libidn2/2.3.7 libssh2/1.11.0 nghttp2/1.61.0 librtmp/2.3
Release-Date: 2024-07-31
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns ldap ldaps mqtt pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS brotli GSS-API HSTS HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz MultiSSL NTLM SPNEGO SSL threadsafe TLS-SRP UnixSockets zstd
operating system
Darwin bogon 21.6.0 Darwin Kernel Version 21.6.0: Mon Jun 24 00:56:10 PDT 2024; root:xnu-8<IP_ADDRESS>9.2~1/RELEASE_X86_64 x86_64

The feedback from the curl team is an issue with OpenSSL。
https://github.com/curl/curl/issues/14498

But you do get an error indicating the certificate is invalid:
ALPN: curl offers h2,http/1.1
TLSv1.3 (OUT), TLS handshake, Client hello (1):
TLSv1.3 (IN), TLS handshake, Server hello (2):
TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
TLSv1.3 (IN), TLS handshake, Certificate (11):
TLSv1.3 (OUT), TLS alert, certificate expired (557):   <======= HERE
OpenSSL/3.3.1: error:80000002:system library::No such file or directory

This error:
curl: (35) OpenSSL/3.3.1: error:80000002:system library::No such file or directory

Is typically indicative of a problem in which homebrew has a library versioning problem, see https://github.com/openssl/openssl/discussions/25172

this seems to be rather a discussion.


dependencies: Update the way to get C-Thread-Pool

To use frankenphp as a golib, we need to get C-Thread-Pool as a dependency. As it's not a go dependencies, we need to version it to avoid this error :
$ go build
# github.com/dunglas/frankenphp
frankenphp.c:16:10: fatal error: 'C-Thread-Pool/thpool.h' file not found

We init it using go generate.

Thanks!


Add package-lock.json to the repository

After cloning this repository, I ran npm install, which created package-lock.json and modified package.json with the latest versions of some dependencies.
I think including package-lock.json will ensure npm doesn't change package.json for me.

:+1:


bump gatsby version

What kind of change does this PR introduce?

Does this PR introduce a breaking change?

What needs to be documented once your changes are merged?

/retitle fix(deps): bump gatsby version


I deleted all my files

>mkdir desktop
>mv * desktop
>dir
rom

Heh. Well I'm not really maintaining Mimic anymore, so I'm not too sure why you'd bother reporting this. Thanks anyway.

RIP Mimic :disappointed:


Pt 155784885 aws deployment

Ref infrastructure PR https://github.com/aeternity/infrastructure/pull/29
Test build: https://circleci.com/gh/aeternity/epoch/4482
pivotal: https://www.pivotaltracker.com/story/show/155784885

@acidsennui Please rebase and fix the config file.

@acidsennui Please also add reference+link (repo) to the exact version of deployment/ansible/inventory/ec2.py in the file as comment

@acidsennui Please update your PR title/description with more meaningful information about the changes:

references to the infra repo with related changes
reference the PT ticket
reference to successful test build

Tags for aws env are here: https://github.com/aeternity/infrastructure/blob/bafbcdbfd383705481d7a1a8dbb33078fcd7736c/aws/ae-environment.yml#L81 it should not affect current deployment, just add new env in aws.

@lucafavatella This PR adds support to AWS dynamic inventory. As @acidsennui pointed (in addition to your finds) the AWS nodes will have a group tag_env_uat thus the current deployment should work as is, and deploy to the AWS nodes on tag.

@lucafavatella Once this and other infrastructure PR's for adding new nodes are merged, I'll do manual UAT (only AWS) deployment to ensure it works as expected and take the AWS UAT nodes in the testnet.


Relicensing as BSD 3

I'm having slight difficulties landing this in the Firefox tree because of licensing issues. BSD 3 has been approved by our legal, while BSD 2 hasn't yet – I know that the difference between both is trivial, I don't know how much time it will take them to realize.
So, here is a PR relicensing as BSD 3. I don't know if you have the will and/or authorization to do so, but if you do, this will save me a little headache :) It's ok if you don't, I'm sure that legal will find time to look at this in a not-too-distant future.

Never mind, I got approval for BSD 2 :)


Fix issue 47. Actually use all the files....

This one was embarrassing. I suspect I broke it during the grand refactoring a while back.
Here is the original issue:
https://github.com/Bachmann1234/diff-cover/issues/47
I am going to look at issue48 before merging this. Maybe combine them as one release.

Coverage decreased (-0.3%) to 98.749% when pulling decbf17faf2f4ae73561385cbe3747414c59e3c2 on issue-47 into 0c593e8b704a5f97b89e34161d78fff804be0bce on master.

Coverage decreased (-0.2%) to 98.797% when pulling 85a734908f1c4cbaa13fe0d70dc8d5e39d439254 on issue-47 into 0c593e8b704a5f97b89e34161d78fff804be0bce on master.

Coverage decreased (-0.3%) to 98.763% when pulling 552bfe4cc2b979c93330d206d69edaedc71f1d2b on issue-47 into 0c593e8b704a5f97b89e34161d78fff804be0bce on master.

Hi Matt,
Same comment, new version of diff-cover does fix the issue I was seeing in our repo, so looks good to me. Thanks for the fix!


Add Iter::ascending() and Iter::descending()

Depends on:

[ ] #326

the diff is so large that it needs significant amount of work to make it alive. note we are going to provide some sugars like this  for i in 0..= 10 { .. }


proposal: spec: permit referring to a field shared by all elements of a type set

What version of Go are you using (go version)?

$ go version
/tmp/golang-tip/bin/go version
go version devel go1.18-986f8ea6b4 Tue Sep 21 00:59:42 2021 +0000 linux/amd64

Does this issue reproduce with the latest release?
No, it is a generics issue, therefore tested with a recent tip only.
What operating system and processor architecture are you using (go env)?
linux/amd64

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/me/.cache/go-build"
GOENV="/home/me/.config/go/env"
GOEXE=""                                                                                GOEXPERIMENT=""                                                                                GOFLAGS=""                                                                                GOHOSTARCH="amd64"                                                                                GOHOSTOS="linux"                                                                                GOINSECURE=""                                                                                GOMODCACHE="/home/me/src/go/pkg/mod"                                                                                GONOPROXY="k8s.io/*"
GONOSUMDB=""                                                                                GOOS="linux"                                                                                GOPATH="/home/me/src/go"                                                                                GOPRIVATE=""                                                                                GOPROXY=""
GOROOT="/tmp/golang-tip"                                                                                GOSUMDB="off"                                                                                GOTMPDIR=""                                                                                GOTOOLDIR="/tmp/golang-tip/pkg/tool/linux_amd64"                                                                                GOVCS=""                                                                                GOVERSION="devel go1.18-986f8ea6b4 Tue Sep 21 00:59:42 2021 +0000"                                                                                GCCGO="gccgo"
GOAMD64="v1"                                                                                AR="ar"
CC="gcc"                                                                                CXX="g++"                                                                                CGO_ENABLED="1"                                                                                GOMOD="/home/me/src/gocrtp/go.mod"                                                                                CGO_CFLAGS="-g -O2"                                                                                CGO_CPPFLAGS=""                                                                                CGO_CXXFLAGS="-g -O2"                                                                                CGO_FFLAGS="-g -O2"                                                                                CGO_LDFLAGS="-g -O2"                                                                                PKG_CONFIG="pkg-config"                                                                                GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build1474680903=/tmp/go-build -gno-record-gcc-switches"

What did you do?
I tried to compile this  program (crtp.go) with generics:
package main

import "fmt"

type Point struct {
	X, Y int
}

type Rect struct {
	X, Y, W, H int
}

type Elli struct {
	X, Y, W, H int
}

func GetX[P interface { Point | Rect | Elli }] (p P) int {
	return p.X
}

func main() {
	p := Point { 1, 2}
	r := Rect {2, 3, 7, 8}
	e := Elli {4, 5, 9, 10}
	fmt.Printf("X: %d %d %d\n", GetX(p), GetX(r), GetX(e))
}

with tmp/golang-tip/bin/go build
What did you expect to see?
Program compiles, runs and outputs X: 1 2 4
What did you see instead?
./crtp.go:19:11: p.X undefined (type bound for P has no method X)
All three structs in the type bound have an identical X /field/, so I think this is wrong. Of course there is no method but I don't think that matters here. I feel I should be able to use the public field X of p since p can only be one of the three Point, Rect, or Elli.

@gopherbot, please add label generics

@griesemer
Reading "Composite types in constraints" in  https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md I get the impression that this ought to work; the example there says "this doesn't work because the field types for X don't all match" which implies that if the field types did match, as they do here, then it would work.
package main

import "fmt"

type hasX interface {
	struct {
		X, Y int
	} | struct {
		X, Y, H int
	} | struct {
		X, Y, W, H int
	}
}

func GetX[P hasX](p *P) int {
	return p.X
}

func main() {
	p := struct {
		X, Y int
	}{1, 2}
	r := struct {
		X, Y, H int
	}{2, 3, 8}
	e := struct {
		X, Y, W, H int
	}{4, 5, 9, 10}
	fmt.Printf("X: %d %d %d\n", GetX(&p), GetX(&r), GetX(&e))
}

We don't currently support field accesses of this kind even though the proposal says that this should/could work. We may not support this for Go1.18 as it doesn't seem like an essential feature. There's a trivial work-around that uses a method:
package main

import "fmt"

type Point struct {
	X, Y int
}

func (p Point) GetX() int { return p.X }

type Rect struct {
	X, Y, W, H int
}

func (r Rect) GetX() int { return r.X }

type Elli struct {
	X, Y, W, H int
}

func (e Elli) GetX() int { return e.X }

func GetX[P interface { Point | Rect | Elli; GetX() int }] (p P) int {
	return p.GetX()
}

func main() {
	p := Point { 1, 2}
	r := Rect {2, 3, 7, 8}
	e := Elli {4, 5, 9, 10}
	fmt.Printf("X: %d %d %d\n", GetX(p), GetX(r), GetX(e))
}

Of course, then you don't need generic code in the first place because you could just use dynamic method dispatch. And maybe you should.

The reason I tried this out is for #48499, wherr the OP directly wants to get fields or pointers to fields from a struct. In that use case, the overhead of an accessor function and dynamic method dispatch would be not acceptable.
So while it may not be essential, #48499, which is for use with Go language databases, goes to show that it is not academic, but actually would be very useful for existing code,  in stead of the feature proposed in that issue. Furthermore it is more consistent and easier to learn to also allow it.
If there is not enough time left to implement this for 1.18, then please consider this for 1.19.

Open question here.
I feel this is a bit restrictive because we have to explicitly say which struct statisfy the constraint. Like for the interface we may want something that will allow us to tell what is the constraint not who can pass. For example :
package main

import "fmt"

type Point struct {
	X, Y int
}

type Rect struct {
	X, Y, W, H int
}

type Elli struct {
	X, Y, W, H int
}

func GetX[P struct { X int }] (p P) int {
        // here p is known to have only the field X anything more
	return p.X
}

func main() {
	p := Point { 1, 2}
	r := Rect {2, 3, 7, 8}
	e := Elli {4, 5, 9, 10}
	fmt.Printf("X: %d %d %d\n", GetX(p), GetX(r), GetX(e))
}

With this example we can pass any struct that has an int  field name X, our function is not coupled with some defined type.

func GetX[P struct { X int }] (p P) int {

Just stopping by to say that this is exactly something that I was looking for. Basically, how can I avoid the explicitly defining the accessors, especially in the case when I fully intend on allowing both Get & Set to occur.
I feel that gymnastics are a totally reasonable expectation when I either want only 1 of Get/Set, OR if the Get/Set needs extra explicit handling. In that case, an interface makes sense. Otherwise, it's just boilerplate.

I believe that this kind of generic structural typing would be extremely useful, and necessary for systems that have performance requirements that dynamic dispatch cannot handle.
That being said the above suggestions for type sets with struct members only being structural seems to be against the grain of the type set. If I were to write the follow:
type Named interface {
  string |  struct { Name string }
}

I expect the set of types to be the set that consists of string and the struct literal that Has a Name property of type string.
Not the set of string and any struct with property Name. Adding the ~ operator does help express perhaps that we want structural typing for the struct, but it is inconsistent with what came before in 1.18 where the meaning of the ~ operator is to mean any type's who's underlying type is what follows the operator.
Therefore, and this might be extremely unpopular, would it not make more sense to extend the constraint/interface syntax to allow for struct members?
type Xer interface {
  X int
}

In the same way that type XGetter interface{ GetX() int } represents the set of types that implement the method GetX, Xer would be the set of types that have an accessor X ?
This way we don't need to touch what the tilde operator means, or how to interpret type unions? Otherwise I think we would be taking two steps backwards in regards to eventually supporting sum types (if ever).

Many interesting ideas here. But, if the use case of my original examples could work somehow, I don't mind the implementation details.

I have a real scenario where i'm working on a ETL jobs that work nicely with generics.
I remove the necessity to do type checking with switch.
The only thing that prevent it to working is assigning a value of a Field to the struct. And since there is a lot of struct object and each has a lot of properties, adding setter / getter for each struct seems to defeat the whole purpose.

It is strange that if all the structs have the same underlying type, then the code works.
package main

import "fmt"

type Point struct {
	X, Y, W, H int
}

type Rect struct {
	X, Y, W, H int
}

type Elli struct {
	X, Y, W, H int
}

func GetX[P interface { Point | Rect | Elli }] (p P) int {
	return p.X
}

func main() {
	p := Point { 1, 2, 0, 0}
	r := Rect {2, 3, 7, 8}
	e := Elli {4, 5, 9, 10}
	fmt.Printf("X: %d %d %d\n", GetX(p), GetX(r), GetX(e))
}

However, I didn't find the ~ sign in the code.

Promoted fields also work (if their underlying types are the same):
package main

import "fmt"

type Base struct {
	X, Y, W, H int
}

type Point struct {
	Base
}

type Rect struct {
	Base
}

type Elli struct {
	Base
}

func GetX[P interface { Point | Rect | Elli }] (p P) int {
	return p.X // okay
}

func main() {
	p := Point {}
	r := Rect {}
	e := Elli {}
	fmt.Printf("X: %d %d %d\n", GetX(p), GetX(r), GetX(e))
}

But hybrid promoted and direct fields don't work:
package main

import "fmt"

type Point struct {
	X, Y, W, H int
}

type Rect struct {
	Point
}

type Elli struct {
	Point
}

func GetX[P interface { Point | Rect | Elli }] (p P) int {
	return p.X // error: p.X undefined (type P has no field or method X)
}

func main() {
	p := Point { 1, 2, 0, 0}
	r := Rect {}
	e := Elli {}
	fmt.Printf("X: %d %d %d\n", GetX(p), GetX(r), GetX(e))
}

Different but with some similarity:
package main

func bar[F func(int) | func(int)int] (f F) {
	f(1) // invalid operation: cannot call non-function f (variable of type F constrained by func(int)|func(int) int)
}

func main() {}

@griesemer

We don't currently support field accesses of this kind even though the proposal says that this should/could work.
It doesn't support method access either.

Playground: https://gotipplay.golang.org/p/aEwSDTXYOlL
Of course method access can be solved by adding the common method to the constraint:
type AB interface {
    *A | *B
    Foo() bool
}

I would like to ask

does method access not work for the same reason as field access?
Is there a more formal explanation for why this doesn't work beside "it wasn't implemented"? It'd be useful when explaining this issue to others. It seems to me that the only relevant quote in the Go 1.18 specifications is "A type constraint [...] controls the operations supported by values of that type parameter." and then adding that selector expressions are not operations. Is there anything else to go by?

@blackgreen100  That is https://github.com/golang/go/issues/51183

Is there a more formal explanation for why this doesn't work beside "it wasn't implemented"? It'd be useful when explaining this issue to others. It seems to me that the only relevant quote in the Go 1.18 specifications is "A type constraint [...] controls the operations supported by values of that type parameter." and then adding that selector expressions are not operations. Is there anything else to go by?

The Go 1.18 release is a huge release and we simply haven't had the bandwidth to get everything done.

@blackgreen100 Note that the method set limitation is explicitly called out in the release notes (https://go.dev/doc/go1.18#generics).

This isn't going to happen in Go 1.19.

A little disappointed, but as long as the request is not rejected, it is still good.

Sorry for a question that is not related to this topic. Can someone please point me to a documentation for that ~ operator? I tried to google but couldn't find anything. I wonder how it works.
type Xer struct {
   X int
}

func GetX[P ~Xer](p P) int {
    return p.X
}

The type set of a term of the form ~T is the set of types whose underlying type is T.

See https://go.dev/ref/spec#General_interfaces

1.20?

I fee like without support for what was proposed in original post go generics simply incomplete. With few fields maybe we could create getter methods and do the work, but this is very cumbersome and kills the purpose of generics say struct has 10-20 fields and it is not uncommon to have this many.

We agree that the support for generics is not yet complete.  We're working on it actively.  This issue remains open.
That said, are there cases where generics are helpful with structs of 10 to 20 fields?  This feature is only useful if you have multiple structs with that many fields, where the fields you care about have identical names and types, and it's useful to write a complex constraint that is a union of those different struct types.  When does this case arise in practice?

I typically have a lot of database models with a consistent set of attributes on them (updated_at, updated_by, created_by, created_at, for example). We have about 7 common attributes (and potentially growing, just talked about adding a some location based attributes) we use for authorization on all our resources and for a generic authz check on a model it be nice to pass in any type as long as it had those attributes. We define our models in proto so while its possible to add a getter method and use an interface, its fairly error prone to ensure every developer remembers to add that method after the go code is generated.

It's important to be clear on what is being suggested here.  This is not "pass in any type as long as it had those attributes."  This is "pass in one of this specific list of types, each of which has these attributes, and then refer to those attributes in the generic code."
That is, code like this would be permitted.
type S1 struct { F, G int }
type S2 struct { F, H int }
type C interface { S1 | S2 }
func GetF[T C](s T) int { return s.F }
var x = GetF(S1{})

Code like this would not be permitted.
type S struct { F int }
type S1 struct { F, G int }
type S2 struct { F, H int }
type C interface { S }
func GetF[T C](s T) int { return s.F }
var x = GetF(S1{}) // INVALID: S1 does not satisfy constraint C

At work I have some complex data that consist of similar union types stored in the same database table, which have many common fields. For those, this feature would certainly help to implement a closed union type using generics.

@tkinz27
Maybe what you need is described in https://github.com/golang/go/issues/51259.

@ianlancetaylor  Thanks for clarifying, I misunderstood.
@go101 yes that is much closer to what I was thinking.

Personally I am more in favor of this issue than #51259, because this does not introduce any new syntax, but only allows semantics that are currently not allowed. This issue would still be very useful for handling the common data of closed unions and other cases of a known set of structs with common fields.

This feature is only useful if you have multiple structs with that many fields, where the fields you care about have identical names and types, and it's useful to write a complex constraint that is a union of those different struct types. When does this case arise in practice?

@ianlancetaylor  We have a DAG with many nodes at my company that forms the core of the product we sell. Each node is a struct which contains the same fields ID and ParentID, as well as many other fields unique to each node type. There are also a subset of nodes which have an overlapping 12 additional fields -- 14 in total.
There are 56 different types of nodes. We've needed to implement these by implementing an interface with getters and setters for each. It's easy, but it's also tedious to write and maintain and leads to arguably less conventional code in use, since now we need to do GetID() where .ID would be preferred. The file that contains these getter and setter definitions for the nodes is almost 3000 lines long. Sharing struct fields would eliminate all of that.

This feature is only useful if you have multiple structs with that many fields, where the fields you care about have identical names and types, and it's useful to write a complex constraint that is a union of those different struct types. When does this case arise in practice?

I wanted to make a generic event queue with the constraint on the provided struct to have a duration and id field
type Event struct {
	ID       string
	Duration int64
        ....
}

Whatever happens here, will not happen for 1.20. Bumping to 1.21.

Just wanted to add one more anecdote to this thread.
We have a few dozen types that all have a common field isDeleted, like you can see here.
A common check we do is if entry != nil && !entry.isDeleted {. This check is needed because the code is a "in-memory view" that periodically marks entries with isDeleted=true to indicate that these entries should be deleted from disk.
Anyway, we wanted to simplify this check into a simple IsDeleted(entry), which would be much less error-prone. But we couldn't because the following code requires accessing a member :(
// A generic utility function to check whether an Entry has been deleted from the view.
func IsEntryDeleted[E any](entry *E) bool {
	if entry == nil || entry.isDeleted {
		return true
	}
	return false
}

Of course, we could define an interface with a common getter for every single type that we have. But this would be highly redundant at this point when the compiler should clearly be smart enough to pick up on this member being common across all types.
I imagine many such use-cases exist where someone wants to do a complicated check on a struct's members, with multiple structs all having the same common members. Libraries that deal with vector math come to mind, where there may be multiple different structs that rely on a common "core" of members that require similar operations to be run on them.
Anyway, just wanted to say that it would be amazing if struct members could be accessible via generic functions in 1.21 :)

@griesemer Looking at this thread, there seems to be a wide consensus amongst the people in this thread that implementing this feature is a good idea. However it has been postponed several times now. It would be great if this was accepted, so this could be implemented for 1.21

I found a description in the go1.18 release note https://go.dev/doc/go1.18 : The Go compiler does not support accessing a struct field x.f where x is of type parameter type even if all types in the type parameter's type set have a field f. We may remove this restriction in a future release. I'm looking forward to this future release coming soon.

We may remove this restriction in a future release.

+1

I really hope this issue is resolved

Are there any news on this?
I was surprised that it doesn't work.
I would prefer to use instead of
func GetX[P interface { Point | Rect | Elli; GetX() int }] (p P) int {
	return p.GetX()
}

just
func GetX[P Point | Rect | Elli] (p P) int {
	return p.x
}

Seems so intuitive :man_shrugging:

btw Original example can be fixed using embedded fields:

Code
package main

import "fmt"

type xField int

func (x xField) X() int         { return int(x) }
func (x *xField) SetX(newX int) { *x = xField(newX) }

type yField int

func (y yField) Y() int         { return int(y) }
func (y *yField) SetY(newY int) { *y = yField(newY) }

type wField int

func (w wField) W() int         { return int(w) }
func (w *wField) SetW(newW int) { *w = wField(newW) }

type hField int

func (h hField) H() int         { return int(h) }
func (h *hField) SetH(newH int) { *h = hField(newH) }

type Point struct {
	xField
	yField
}

type Rect struct {
	xField
	yField
	wField
	hField
}

type Elli struct {
	xField
	yField
	wField
	hField
}

func GetX[P interface{ X() int }](p P) int {
	return p.X()
}

func main() {
	p := Point{1, 2}
	r := Rect{2, 3, 7, 8}
	r.SetW(8)
	e := Elli{4, 5, 9, 10}
	fmt.Printf("X: %d %d %d\n", GetX(p), GetX(r), GetX(e))
}

It is not very beautiful, but can reduce the amount of code if you need to write getters/setters. But I think the syntax type withX {X int} would be much cleaner.

Just another example for a use case and another workaround, this time without an interface.

There's a common pattern of chaining many "withX" calls, usually implemented as func (foo Foo) withX(x) Foo
When there are many foos that need to make some common code before setting X, e.g. check if a map is initialized before setting a value
I think it could be cleaner to use generics here, because interfaces would force the caller to assert the returned value back to the concrete type and won't be chain-able
We can't make generic "methods", so passing the generic type as argument instead (func withX(foo Foo, x) Foo)
Adding an example workaround for passing "generic" func literals instead of implementing interfaces for getters/setters - not sure regarding performance, but IMHO it feels weird to implement getters/setter in Go for this sole purpose

package options

import "io"

type GetOpts struct {
	url     string
	headers map[string]string
}

type PostOpts struct {
	url     string
	headers map[string]string
	body    io.Reader
}

type opts interface{ GetOpts | PostOpts }

// Desired implementation, for now it's a compile-time error
func WithHeader[Opts opts](o Opts, k, v string) Opts {
	if o.headers == nil {
		o.headers = make(map[string]string)
	}
	o.headers[k] = v
	return o
}

// With current generics, without getter/setter interfaces
// `headers` param is defined as generic only to make it easier to change
func withHeader[Opts opts, headers map[string]string](o Opts, k, v string,
	getter func(Opts) headers,
	setter func(*Opts, headers)) Opts {
	h := getter(o)
	if h == nil {
		h = make(headers)
	}
	h[k] = v
	setter(&o, h)
	return o
}
// Publishing a cleaner API usage without generics, that benefits from the single implementation
// Imagine a real-world use case where the verification is more complicated (e.g. appending a value to existing key instead of overriding)
func (o PostOpts) WithHeader(k, v string) PostOpts {
	return withHeader(o, k, v,
		func(o PostOpts) map[string]string { return o.headers },
		func(o *PostOpts, h map[string]string) { o.headers = h })
}

func (o GetOpts) WithHeader(k, v string) GetOpts {
	return withHeader(o, k, v,
		func(o GetOpts) map[string]string { return o.headers },
		func(o *GetOpts, h map[string]string) { o.headers = h })
}

It really feels like this functionality is required to make generics useful. A lot of people seem to end up in this issue because they expect this to work

On the typechecker side, the 1.21 release focuses on (much better) type inference. Didn't get to this. Moving along to 1.22.

Completely new to go but here would be my use case for field access on generics:
type User struct {
	name string
	password string
}

type Admin struct {
	name string
	level string
	password string
}

func redactPassword[T User | Admin](someUser T) (T){
	someUser.password = "*****"
	return someUser
}

func main() {
	fmt.Println("hello world?")

	user := User{"apple","banana"};

	fmt.Println(redactPassword(user))

}

lets me use the same function wherever i need to log the details of a struct without exposing one of the fields

Promoted fields also work (if their underlying types are the same):
package main

import "fmt"

type Base struct {
	X, Y, W, H int
}

type Point struct {
	Base
}

type Rect struct {
	Base
}

type Elli struct {
	Base
}

func GetX[P interface { Point | Rect | Elli }] (p P) int {
	return p.X // okay
}

func main() {
	p := Point {}
	r := Rect {}
	e := Elli {}
	fmt.Printf("X: %d %d %d\n", GetX(p), GetX(r), GetX(e))
}

The above example does not work, or am I missing something obvious.

@marmiha: The above doesn't work but you can workaround this by creating an interface to get/set the common base fields:
package main

import "fmt"

type IBase interface {
	GetX() int
}

type Base struct {
	X, Y, W, H int
}

func (b Base) GetX() int {
	return b.X
}

type Point struct {
	Base
}

type Rect struct {
	Base
}

type Elli struct {
	Base
}

func PrintX[T IBase](v T) {
	fmt.Printf("%d\n", v.GetX())
}

func main() {
	p := Point{}
	r := Rect{}
	e := Elli{}
	PrintX(p)
	PrintX(r)
	PrintX(e)

}

Now that this is a Proposal, what are the items that need to be discussed to converge towards an Accepted Proposal? (hopefully)

It needs to go through proposal review committee.  See https://go.dev/s/proposal.

This proposal has been added to the active column of the proposals project
and will now be reviewed at the weekly proposal review meetings.
— rsc for the proposal review group

@fzipp I don't believe this proposal actually is about "expanding the options for specifying type sets in constraints". This proposal is to write generic code you can already write more conveniently. That is, you can already write
type A struct { X int; Y string }
type B struct { X int; Y float64 }
type C interface{ A | B }
func F[T C](p *T) {
    switch p := any(p).(type) {
    case *A:
        p.X = 42
    case *B:
        p.X = 42
    }
}

So this proposal is just about being able to write
func F[T C](p *T) {
    p.X = 42
}

(Perhaps you are mixing this up with #51259, which is indeed about expanding the options to specify constraints)

I believe that there are more nuances here.
In both cases, the number of types are infinite. We are just used to basic interface constraints but these are also a construct. The type has to be built a certain way (with the relevant methods).
Having a given field is not too different.
Where it's different might be addressability. A method can only return a value.
But I think you actually both share the opinion (rightfully) that we should be cautious.
There are often hidden implicit negative constraints.
That's what makes type parameter embedding problematic wrt method promotions for instance. (reason why it's forbidden for now).
And also, the more features, the more complex the code written sometimes.

@fzipp that is https://github.com/golang/go/issues/51183, just one of the temporary limitations in custom generics.

@Merovius

https://github.com/golang/go/issues/48522#issuecomment-1752553994

It looks this proposal only cares about reading common fields, not writing them.
At least that is what the author's first comment shows.
If writing is also supported, then the dynamic values of interfaces should be pointers to structs?

@go101 I would find it strange, if we where to implement this proposal and not allow the example code I posted.
I don't understand why you talk about the dynamic values of interfaces. Perhaps you are referring to a hypothetical future in which we would allow interfaces with union elements to be used as types? In that case, note that allowing a selector expression on common fields if C is used as a constraint on a type parameter does not necessarily imply allowing it if C is used as type of a variable. For example, we allow using + if all types in the type set of a type parameter allow addition, but we would almost certainly are not going to allow it when using that interface as a type. So figuring out selector expression seems like a bridge we have to cross when we get there.
That being said, I can well imagine that we would - in that hypothetical future - allow that selector expression, make it panic if the dynamic value is nil and only make it addressable, if all types in the type set are pointer-types. Note that this is very different from the problem we are seeing in #51259, where the constraint "has a field F" would inherently cover both pointer and value types, so there is no way to know, a priori, if the dynamic value is addressable. With this proposal, we know the actual types, so we can decide statically, if they are addressable.
But again, I think the example code I posted should be made to work under this proposal - if all types in the type set of T are structs with field F and p is a *T, then IMO p.F should obviously be addressable and thus be a valid LHS in an assignment.

I don't understand why you talk about the dynamic values of interfaces.

Sometime type parameter types are treated as ordinary types, sometimes they are always viewed as interface types.
This is a difference between the generic world and non-generic world.
Here the dynamic values means

values of type arguments which are not interface types.
dynamic values of values of type arguments which are interface types.

So the answer to your following question is true.

Perhaps you are referring to a hypothetical future in which we would allow interfaces with union elements to be used as types?

This proposal does share some common problems with https://github.com/golang/go/issues/51259.
I don't think your above code should work
// Your code:
...

func F[T C](p *T) {
    p.X = 42
}

When constraints are allowed to be used as value types, C can be passed as a type argument here.
When this happen, the code is equivalent to
func F(p *C) {
   p.x = 42
}

However, dynamic values of (ordinary) interface types are immutable.
The costs to break the rule is high.

@go101 I think C shouldn't be able to instantiate itself.
It implements itself but doesn't satisfy itself.
That's in the future though as unions cannot be used as regular interfaces now.
It's easy to see here. An interface type does not have fields.
These really are wrappers.
Same thing when considering interface{int | string}.
The + operator for int is really defined as (int, int) - > int
Which is different from (string, string) - > string
These operations are overloaded and shouldn't be promoted to the interface itself. Doesn't make much sense.
Then again that's a bit off-topic.

IMHO, allowing using constraints as value types is the most important sub-feature of Go custom generics.
If this will not be supported, it is hard to say Go custom design is a success.
I don't think there are fatal obstacles which will prevent this from happening.
In fact, there are some larger obstacles which have been overcome. (Cool work, Go team!)
For your concern, please read https://github.com/golang/go/issues/61372#issuecomment-1713253229. You probably have read it.

@go101

When constraints are allowed to be used as value types, C can be passed as a type argument here.

It is already known per discussion on #57644 (particularly https://github.com/golang/go/issues/57644#issuecomment-1373377900, https://github.com/golang/go/issues/57644#issuecomment-1682267050) that, if a proposal like it is accepted, it still cannot be allowed for an interface containing union elements to instantiate types and functions with bounds they implement. As @atdiar says, such types may implement but not satisfy themselves. A great deal of existing code would cease to compile otherwise.

@zephyrtronium
My comment has mentioned:

Maybe, a better suggestion is to enhance type constraints so that
we can define non-interface type parameters and interface-only type parameters.

The intent of the original generics proposal was that an operation on a type parameter (i.e., on a value of type parameter type) shall be permitted if the operation is permitted on each element of the type set defined by the type parameter's constraint (see Operations based on type sets).
This issue is simply proposing that we apply this principle also to struct field accesses. So this proposal is in line with the original vision for generics, and essentially removes an implementation restriction.
For comparison, I note that it's currently possible to access a slice element of a generic slice type, if all elements in the respective type set  allow the slice operation. This code is valid (playground):
type S1 []int

func get[S S1 | []int](s S, i int) int {
	return s[i]
}

(Here the type set of S contains just two types, the S1 and []int type.)
That said, this slices example is a slightly bit different from the proposal at hand because the type set of S has a core type, and the index access is based on that core type. We have used the mechanism of the core type to explain behavior where we don't have a "traditional" unary or binary operator such as +, *, etc. Field selection (the . "dot" operation) would fall more in the latter category where the rule is not based on a core type but on the fact that all type set elements support the operation.

If this is accepted, will the following work?
type A struct {
	Foo int
	Bar string
}

type B struct{ Foo int }

type C interface{ A | B }

func foo[T C](f T) int { return f.Foo }

Isn't this too expensive for the compiler? To have to check every field of every possible type that satifies C? What if C has a lot of types and every type has a lot of fields?

I'm not sure what you mean by "expensive". The compiler already needs to check that each type argument to foo satisfies the C constraint (so test the type argument against each type in C). When compiling f.Foo, the compiler simply has see if f.Foo is valid for each possible type in C. We already do this all the time for operations such as +, -, etc. A field lookup is more expensive, but nor prohibitively so. And there's ways to cache information if so desired.

By "expensive", I meant it would be a quadratic operation.
In the example I sent, currentely, the compiler only needs to check that the argument type passed is either A or B. It doesn't need to check what fields A or B have, I assume.
That's where my worry came from. But glad it isn't too expensive. Thanks!

@go101 The comment you link to is not an actual response. For one, you suggest as a solution to "define < for interfaces, like we do ==", which is a bad idea in and off itself - many algorithms (like sorting) assume that a < b || a == b || a > b is true. Putting a foot-gun in, where a < b might be false purely because their dynamic types don't match seems bad. But also, you move the goal-post - the actual example was a+b which definitely does not have a reasonable definition, if the dynamic types of a and b are different.
Either way - the point is that your assumption that any interface will definitely be a valid type argument for a type-parameter constrained on it is anything but given. From what I can tell, you are pretty much alone in the belief that will be the case. And in any case - selector-expressions won't make that any harder. We already have to overcome significant practical hurdles to make that happen (as illustrated with +) and selector-expressions would not be qualitatively different.

Will there be a way to express a constraint as Any struct that has X, Y, Z field(s)? Not sure if this would be a different proposal.
For example:
type C interface{ ~struct{ Foo int } }

Currently, this require a struct that has exactly 1 field called Foo and that it's type is int. What I'm askig is that the constraint would allow for any struct that has the required field, so any struct with field Foo int would be allowed, even if it has more fields.

@phenpessoa That's https://github.com/golang/go/issues/51259

@Merovius

many algorithms (like sorting) assume that a < b || a == b || a > b is true

This even can't be promised nowadays.
It looks you are over-confident on your opinion.

I prefer #51259. Allowing operations shared by all primitive types feels different. The intersection of the method sets is not included and the "field set" is more like that than indexing or addition or the like.

Since this requests something that can already be done, and since methods can code, which can differ amongst methods of the same signature, allowing the behaviour amongst methods is clearly more powerful and useful, while allowing this behaviour amongst fields simply clutters up the language.
It gets really pathological when you have:
type Point struct {
	X, Y int
}

type Rect struct {
	X, Y, W, H uint
}

Using methods, this is easily handled.

I found a lot of comments proposing to use getters and setters. They do work. But unfortunately sometimes third-party packages refuse to provide setters. For example, the proto-gen-go of Protobuf. There are two closed proposals to add setters to fields:
https://github.com/golang/protobuf/issues/65
https://github.com/golang/protobuf/issues/664
As a user of this package, I felt helpless..
However, if this proposal is passed, some code generators will no longer require getters & setters.

@seancfoley I'm not sure what you are trying to demonstrate with your example. I don't think this proposal would allow to use selector-expressions with a union of those types either - obviously, a selector expression can only be allowed if all types in the type set have a common field with a common type.

@merovius My point is about the usefulness of a feature that would require similar data to synchronize on common types.
Sure, the author knows whether he can do it or not, so what?  That doesn't mean it's a worthwhile addition to the language.  It's not.  It becomes useless in a rather trivial manner.

I am not sure if this is already covered with this proposal, but I have another use case I haven't yet seen mentioned: providing default struct  with functions which accept it, but user can pass another struct to them which have the default one embedded. So users can attach additional data and methods, but functions I provide do not care about them, but should pass the value through.
Example:
type Base struct {
	Name string
}

type Extended struct {
	Base
	Age int
}

func SayHi[T Base](x T) (T, string) {
	return x, fmt.Sprintf("Hi, %s!", x.Name)
}

func main() {
	x, hi := SayHi(Extended{Name: "foo", Age: 30})
	fmt.Println(hi)
	fmt.Println(x.Age)
}

The example is a bit contrived, but the idea is that SayHi should be able to access everything on embedded Base (both fields and methods), but the returned x is in fact of the type passed in. So the extra fields and methods are available and can be passed through, while my code just cares about the Base.

@mitar That is #51259.

@mitar's example should not work. Because the type set of interface{Base} only contains one type: Base. So Extended is an invalid type argument. Besides this, Extended{Name: "foo", Age: 30} is an invalid literal.

@griesemer has been looking into possible ways to simplify the definition of generic type checking and in particular removing the concept of core types. It seems like we should wait on that effort before making any changes along these lines. This change might fall out of that, or it might not, but better to have a general cleanup than a pointwise fix that may or may not improve things.
In the interim there is always the ability to add explicit get/set methods and adding those to the constraint.

Based on the discussion above, this proposal seems like a likely decline.
— rsc for the proposal review group

I request this be put on hold instead of be declined if we are explicitly waiting on @griesemer's work. It doesn't make sense to me to decline on just the potential of it coming out of another solution.

I also don't see how this is a decline. It is a simple feature that seems
to be in popular demand. While it is possible to define getters and setters
as methods, the point of this proposal is that it would be a lot more
convenient if we could use generics so we don't have to do that.
On Fri, 3 Nov 2023, 03:31 deef, @.***> wrote:

I request this be put on hold instead of be declined if we are explicitly
waiting on @griesemer https://github.com/griesemer's work. It doesn't
make sense to me to decline on just the potential of it coming out of
another solution.
—
Reply to this email directly, view it on GitHub
https://github.com/golang/go/issues/48522#issuecomment-1791311521, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AAARM6OMXD5ZC5RTFZT4243YCPRGPAVCNFSM5EPKXW2KU5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TCNZZGEZTCMJVGIYQ
.
You are receiving this because you authored the thread.Message ID:
@.***>

@griesemer has been looking into possible ways to simplify the definition of generic type checking and in particular removing the concept of core types.

@griesemer
Which GH issues can we follow to watch the progress of this current research?

@piroux There wasn't one, but I created an umrella issue just now: #63940.

This proposal has been added to the active column of the proposals project
and will now be reviewed at the weekly proposal review meetings.
— rsc for the proposal review group

The bot did the wrong thing before. This was supposed to be declined, in favor of #63940.

I think it's a bit unfortunate that this issue was closed in favor of #63940 because many Go developers are probably not familiar with the concept of core types. However, 8 percent of developers who answered the latest Go developer survey felt that generics were too limited for their needs. Perhaps it would be better to leave an issue like this open to better understand the challenges people are facing rather than having an umbrella issue that seems focused on the internal implementation?

Core types are not an aspect of the internal implementation, they are defined in the language spec.  It won't help anybody to discuss the same issue in two different places.

Hi @creativecreature, FWIW note that https://github.com/golang/go/issues/63940 opens citing this issue here as a motivation, and I don’t think this aspect will be forgotten as work (hopefully) progresses.
From the opening comment of https://github.com/golang/go/issues/63940:

We should investigate if we can avoid the use of core types more widely. We already do avoid them for some operations, such as indexing. If we can avoid them everywhere, we should be able to enable some desired features (such as https://github.com/golang/go/issues/48522) w/o extra rules but as a matter of course.


Allow normalised programs to be executed

Add a run option so that normalised programs can be executed
Add an equivalent for the C API

Depends on #119.

I should have thought more about what I was trying to achieve, I've made all the de/normalise functions returns copies - which is pointlessly slow for our use cases.  So the first job is to convert them back to inplace conversions.


Implementing CSP with

Describe what feature you'd like. Pseudo-code, mockups, or screenshots of similar solutions are encouraged!
When using the standard Lightswitch component, it injects the following script into the head:
<script>
(function setInitialClassState() {
  const elemHtmlClasses = document.documentElement.classList;
  const condLocalStorageUserPrefs = localStorage.getItem("modeUserPrefers") === "false";
  const condLocalStorageUserPrefsExists = !("modeUserPrefers" in localStorage);
  const condMatchMedia = window.matchMedia("(prefers-color-scheme: dark)").matches;
  if (condLocalStorageUserPrefs || condLocalStorageUserPrefsExists && condMatchMedia) {
    elemHtmlClasses.add("dark");
  } else {
    elemHtmlClasses.remove("dark");
  }
})();
</script>

If a user configures SvelteKit to use CSP, the browser throws an error because the inline script does not contain a nonce.

Content Security Policy: The page’s settings blocked the loading of a resource at inline (“script-src”).

SvelteKit will automatically add the nonce if %sveltekit.nonce% is added to the script tag:
<script nonce="%sveltekit.nonce%">
What type of pull request would this be?
New Feature
Any links to similar examples or other references we should review?
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
https://kit.svelte.dev/docs/configuration#csp
https://github.com/skeletonlabs/skeleton/blob/dev/src/lib/utilities/LightSwitch/LightSwitch.svelte#L65

Adding some additional context here:
https://discord.com/channels/1003691521280856084/1048010639219642419/threads/1099012032843485314
I think this is a valuable add. We'll aim to add the nonce attribute to the script tag, so that it's always present, but ONLY if that doesn't interfere with with apps not utilizing CSP.
If implementing the attribute does cause issue, we'll need to find a way to dynamically implement this on demand.

@MyraManes FYI I've implemented this and saw no noticeable issue. We'll dogfood this internally on our dev branch through the remainder of the week. If there's no issue then this will be part of next week's release. Hope that helps!


Fix clean up logic on reconcile

Signed-off-by: Liam White<EMAIL_ADDRESS>Proposed changes
Fixes a bug where the project directory is cleaned up but not the things above it, leading to runaway storage consumption.

Signed-off-by: Liam White<EMAIL_ADDRESS>Proposed changes
Fixes a bug where the project directory is cleaned up but not the things above it, leading to runaway storage consumption.

Fixes https://github.com/pulumi/pulumi-kubernetes-operator/issues/104

/run-acceptance-tests


Introspection

Add full schema introspection support so that GraphiQL is more useful.

Maybe I prematurely approved #45, but here is a list that I think need to be addressed before closing #33.

For the query

{
  __schema {
    types {
      fields {
        type {
          name
        }
     }
  }
}

Type -> name is not returning the expected result. For List types, name should return null, but it currently causes a server error. For Object types, it currently returns 'Object', but I think it should return 'Character'.

For the query

{
  __schema {
    types {
      fields {
        type {
          fields {
            name
          }
        }
     }
  }
}

The nested 'fields' selection always returns an empty list.

List types should have an ofType field.

'directives' should return an empty list

Fixed in #51


Add expect method

Closes #24

I also added the equals: Callable param to the expect method. See the sample test in simple-testing-godot/sample tests/expect/tests/transaction_tests.gd.