Skip to content

compile-time assert numControllers == len(controllersArray)#1112

Merged
knative-prow-robot merged 4 commits into
knative:masterfrom
syedriko:compile_time_assert
Apr 30, 2019
Merged

compile-time assert numControllers == len(controllersArray)#1112
knative-prow-robot merged 4 commits into
knative:masterfrom
syedriko:compile_time_assert

Conversation

@syedriko
Copy link
Copy Markdown
Contributor

@syedriko syedriko commented Apr 27, 2019

Replace a runtime check with a compile-time assert in two controller mainlines
Sister PR in serving knative/serving#3923

@googlebot googlebot added the cla: yes Indicates the PR's author has signed the CLA. label Apr 27, 2019
@knative-prow-robot knative-prow-robot added the size/S Denotes a PR that changes 10-29 lines, ignoring generated files. label Apr 27, 2019
@knative-prow-robot
Copy link
Copy Markdown
Contributor

Hi @syedriko. Thanks for your PR.

I'm waiting for a knative member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@knative-prow-robot knative-prow-robot added the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label Apr 27, 2019
@syedriko
Copy link
Copy Markdown
Contributor Author

/cc @evankanderson

@n3wscott
Copy link
Copy Markdown
Contributor

I find this pretty hard to read. We have e2e tests that will catch the error.

@grantr
Copy link
Copy Markdown
Contributor

grantr commented Apr 29, 2019

/ok-to-test

@knative-prow-robot knative-prow-robot added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Apr 29, 2019
Copy link
Copy Markdown
Contributor

@grantr grantr left a comment

Choose a reason for hiding this comment

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

This is clever and I like it. Thanks @syedriko! The var _ line is a bit hard to read but a comment can explain it adequately. I think it's worth having - relying on E2E tests to debug this problem would be extremely frustrating.

I have some minor suggestions to improve the clarity of the other lines.

Comment thread cmd/controller/main.go Outdated
// Add new controllers to this array.
// You also need to modify numControllers above to match this.
controllers := []*kncontroller.Impl{
controllersArray := [...]*kncontroller.Impl{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This might be clearer as [numControllers]*kncontroller.Impl. That will also catch the issue of numControllers < len(controllersArray).

Copy link
Copy Markdown
Contributor Author

@syedriko syedriko Apr 29, 2019

Choose a reason for hiding this comment

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

Thanks, @grantr!
I picked the [...] form to make sure the length of the array comes strictly from the list of initializers. If we specify the length as you're suggesting, there's a risk of 0-valued elements at the end of the array if there are fewer initializers than the specified length inside of [].
The [numControllers - len(controllersArray)] part of the incantation covers the case of numControllers < len(controllersArray), as that makes the difference negative.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Makes sense, I forgot about the zero value being filled in at the end.

Comment thread cmd/controller/main.go Outdated
if len(controllers) != numControllers {
logger.Fatalf("Number of controllers and QPS settings mismatch: %d != %d", len(controllers), numControllers)
}
controllers := controllersArray[:]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since this seems to only be used in the StartAll call below, we could inline this declaration there:

go kncontroller.StartAll(stopCh, controllersArray[:]...)

Comment thread cmd/controller/main.go Outdated
logger.Fatalf("Number of controllers and QPS settings mismatch: %d != %d", len(controllers), numControllers)
}
controllers := controllersArray[:]
// compile-time assert numControllers == len(controllersArray)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This would be clearer as a complete sentence. I suggest something like

// This line asserts at compile time that the length of controllersArray is equal to numControllers.

Comment thread cmd/controller/main.go
// Start all of the controllers.
logger.Info("Starting controllers.")
go kncontroller.StartAll(stopCh, controllers...)
go kncontroller.StartAll(stopCh, controllers[:]...)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just FYI this will conflict with #1118 which is also yours :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yep, the cost of separating the two different issues :)

Copy link
Copy Markdown
Contributor

@grantr grantr left a comment

Choose a reason for hiding this comment

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

Thanks for fixing this in both serving and eventing @syedriko! Those who find it unbearably ugly now have motivation to fix the need to specify numControllers. 😺

/lgtm

@knative-prow-robot knative-prow-robot added lgtm Indicates that a PR is ready to be merged. approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Apr 29, 2019
Comment thread cmd/controller/main.go
// var _ [N-M]int
// asserts at compile time that N >= M, which we can use to establish equality of N and M:
// (N >= M) && (M >= N) => (N == M)
var _ [numControllers - len(controllers)][len(controllers) - numControllers]int
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

: This is freaking awesome! <well, slighlty changed>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I'm wary of relying on something that needs a 5-line comment to explain a 1-liner technique for compile-ish time-ish bounds checking. I don't really understand how this works and I expect that like most folks, I will assume that it works and not notice when if it somehow doesn't.

I'd be more comfortable with runtime checking supported by a test (since Go's type system doesn't idiomatically encode these kinds of restrictions).

Copy link
Copy Markdown
Contributor Author

@syedriko syedriko May 3, 2019

Choose a reason for hiding this comment

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

I'm wary of relying on something that needs a 5-line comment

I started with a one-liner comment, but was quickly (and correctly) prompted that an explanation is in order.

I don't really understand how this works and I expect that like most folks, I will assume
that it works and not notice when if it somehow doesn't.

There's no need to assume, I wouldn't want to:
https://golang.org/ref/spec#Array_types
The length is part of the array's type; it must evaluate to a non-negative constant representable by a value of type int.

var _ [N-M]int
(N - M >=0) <=> (N => M) <=> ((N > M) || (N == M))

var _ [M-N]int
(M - N >=0) <=> (M => N) <=> ((M > N) || (M == N))

var _ [N-M][M-N]int
For what N and M
((N > M) || (N == M)) && ((M > N) || (M == N)) == true?

For integers M and N, there're only 3 ordering possibilities:

  1. N > M. Substitute:
    (true || false) && (false || false) == false

  2. M > N
    (false || false) && (true || false) == false

  3. N == M
    The only alternative left. But still substitute:
    (false || true) && (false || true) == true

compile-ish time-ish

I'm not familiar with that program translation phase. At the present this is a compile-time check. Even if somehow in some Go implementation far, far away that line is evaluated at runtime, it will still fail and we're going to be no worse off than we started.

The earlier a problem is detected, the quicker it can be fixed. It'd be much more productive to find a way to make that assert unnecessary in the first place.

@vaikas
Copy link
Copy Markdown
Contributor

vaikas commented Apr 29, 2019

/lgtm
/approve

@knative-prow-robot
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: grantr, syedriko, vaikas-google

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:
  • OWNERS [grantr,vaikas-google]

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@syedriko
Copy link
Copy Markdown
Contributor Author

/test pull-knative-eventing-integration-tests

@knative-prow-robot knative-prow-robot merged commit c67c680 into knative:master Apr 30, 2019
@syedriko syedriko deleted the compile_time_assert branch April 30, 2019 14:36
lberk added a commit to lberk/eventing that referenced this pull request Mar 2, 2021
Remove echo statements, add -x flag for verbosity on jenkins runs
matzew pushed a commit to matzew/eventing that referenced this pull request Feb 25, 2025
…5 updates (knative#1112)

* [release-v1.16][gomod]: Bump the patch group across 1 directory with 5 updates

Bumps the patch group with 2 updates in the / directory: [k8s.io/api](https://github.com/kubernetes/api) and [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver).


Updates `k8s.io/api` from 0.30.3 to 0.30.10
- [Commits](kubernetes/api@v0.30.3...v0.30.10)

Updates `k8s.io/apiextensions-apiserver` from 0.30.3 to 0.30.10
- [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases)
- [Commits](kubernetes/apiextensions-apiserver@v0.30.3...v0.30.10)

Updates `k8s.io/apimachinery` from 0.30.3 to 0.30.10
- [Commits](kubernetes/apimachinery@v0.30.3...v0.30.10)

Updates `k8s.io/apiserver` from 0.30.3 to 0.30.10
- [Commits](kubernetes/apiserver@v0.30.3...v0.30.10)

Updates `k8s.io/client-go` from 0.30.3 to 0.30.10
- [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md)
- [Commits](kubernetes/client-go@v0.30.3...v0.30.10)

---
updated-dependencies:
- dependency-name: k8s.io/api
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch
- dependency-name: k8s.io/apiextensions-apiserver
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch
- dependency-name: k8s.io/apimachinery
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch
- dependency-name: k8s.io/apiserver
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch
- dependency-name: k8s.io/client-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Run make generate-release

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. cla: yes Indicates the PR's author has signed the CLA. lgtm Indicates that a PR is ready to be merged. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. size/S Denotes a PR that changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants