profile
viewpoint

griesemer/tryhard 95

tryhard finds and rewrites code suitable for try.

griesemer/dotGo2016 21

Prototype implementation of operator methods (fork of https://github.com/golang/go)

griesemer/2016-talks 10

Slides and Links to slides for 2016 talks

griesemer/proposal 5

Go Project Design Documents

griesemer/ivy 4

ivy, an APL-like calculator

issue commentgolang/go

strings: Docs & Examples unclear about difference between ToTitle and ToUpper

Assigned to @mpvl who is our local Unicode expert.

dionysius

comment created time in 14 hours

issue commentgolang/go

x/tools/go/internal/gcimporter: remove support for binary import/export format

Assuming we can do this, setting milestone to 1.15 so we can do this in sync with the std/lib change.

griesemer

comment created time in a day

issue commentgolang/go

x/tools/go/internal/gcimporter: remove support for binary import/export format

Related: #27999. cc: @stamblerre

griesemer

comment created time in a day

issue openedgolang/go

x/tools/go/internal/gcimporter: remove support for binary import/export format

Now that we have removed support for the (defunct) binary import/export format in the std library, investigate if we can remove the corresponding code in the x/tools version.

Reminder issue.

created time in a day

issue closedgolang/go

go/importer: remove support for (now defunct) binary export format (reminder issue)

The compiler only generates the new indexed export format, and any support for the old binary export format has been removed.

We can eliminate the support from go/importer as well.

(Before we do, double-check that the latest version of that code is ported to x/tools where it needs to survive for another 3 release cycles - until 1.14.)

closed time in a day

griesemer

issue commentgolang/go

go/importer: remove support for (now defunct) binary export format (reminder issue)

The x/tools breakage has been fixed. Closing again.

griesemer

comment created time in a day

issue commentgolang/go

proposal: Go 2: integrated compile time language

An integrated compile-time language makes a compiler essentially programmable; there's no question that this would be very powerful. In a similar vain, at a time it was fashionable to make programming languages customizable, from the simple ability to define the precedence of operators (see e.g., Prolog), to the more complex of controlling evaluation of operands, etc.

While such languages can make it much easier to solve certain problems, they also make it much harder to understand what is going on because the programming language can be changed. A reader will effectively have to learn a new language before they can read the code.

Your proposal description is sufficiently high-level and the examples don't show the meta-language, so it's unclear to me how flexible an approach you are envisioning. But clearly you want to analyze format strings at compile time, so there's plenty of power here that could lead to programs that are extremely hard to understand. For instance, the meta-language could modify format strings and thus making it almost impossible to determine what a program is doing w/o actually performing the compile-time computation in one's head. This leads to code that may be easy to write but hard to read for anybody else but the writer (and it will be hard to read for the writer as well after enough time has passed).

In short, I believe any such attempt would significantly reduce Go's readability, yet readability is one of the top priorities for Go, so we're not going to easily compromise on that.

jonperryman

comment created time in 2 days

issue commentgolang/go

proposal: Go 2 review meeting minutes

2020-02-18 / @bradfitz, @griesemer, @iant

  • #37243 Go 2: improve error handling with “??” keyword for a special case
    • likely decline, final call for comments
  • #37165 Add ?? operator to select first non-zero value
    • commented
    • on hold
  • #36508 Go 2: remove map from keywords
    • likely decline, final call for comments
  • #36890 Go 2: permit converting a string constant to a byte array type
    • retitled
  • #36955 Go 2: allow channel/map/type assertions in return (val, bool)
    • commented
    • likely decline, final call for comments
  • #36972 Go 2: compiler chosen constants - make(const, <min>, <max>)
    • commented
  • #37039 Go 2: add C# like nameof() built-in function
    • commented
griesemer

comment created time in 2 days

issue commentgolang/go

cmd/compile: the compiler should probably recognize runtime.Goexit

The definition of "terminating statements" is based strictly on properties of the language spec (which are unlikely to change), not APIs (which may change).

Also, even if we added runtime.Goexit it wouldn't be satisfactory anyway: It's not unlikely that runtime.Goexit is factored out into a function that does cleanups or perhaps prints additional error information; thus it is that function that will be called (possibly from multiple places) in a program. And unless we propagate the "exit" information to the caller, knowing that runtime.Goexit doesn't return won't be very helpful - it'll save a single return statement. That doesn't seem worth it.

More precisely, runtime.Goexit doesn't terminate the function, it terminates the goroutine that calls it. If we wanted to capture that correctly, we'd need to propagate that up the call stack, with extra rules. I am not convinced this is worth the extra complexity or the mixing of language spec and library APIs.

Not really a proposal, but leaving open for a decision by the proposal review commitee.

perillo

comment created time in 3 days

issue closedgolang/go

cmd/compile: cannot use struct fields in short variable declaration i.e. f.field, err := fn()

<!-- Please answer these questions before submitting your issue. Thanks! For questions please use one of our forums: https://github.com/golang/go/wiki/Questions -->

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

go 1.12.6 <pre> $ go version

</pre>

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

"darwin" <details><summary><code>go env</code> Output</summary><br><pre> $ go env

</pre></details>

What did you do?

Option1: if I have two variables one defined and other undefined then the := does not identify the defined variable and results in compile error "non-name fs.err on left side of :=" The line of code is as follows

d, fs.err := fs.client.Collection(fs.CollectionName).Doc(fs.ID).Get(fs.ctx) In order to make it work d needs to be defined var d *firestore.DocumentSnapshot

Option 2: while the following fragment works and go infer the type for d var err error d, err := fs.client.Collection(fs.CollectionName).Doc(fs.ID).Get(fs.ctx)

In the line above fs is a struct and has been defined. In this case I am receiving it as an argument <!-- If possible, provide a recipe for reproducing the error. A complete runnable program is good. A link on play.golang.org is best. -->

What did you expect to see?

I expect go to infer types for non defined parameters, as it does in the second scenario above

What did you see instead?

Option 1 does not work while Option 2 works

closed time in 13 days

saritseal

issue commentgolang/go

cmd/compile: cannot use struct fields in short variable declaration i.e. f.field, err := fn()

There's been various discussions in the past regarding relaxing the rules for := assignments (see #377 as the tracking issue for several proposals).

But as has been said before by @odeke-em, this is working as intended.

saritseal

comment created time in 13 days

issue commentgolang/go

x/tools/go/types/typeutil: wrong computed method set

Smaller reproducer: https://play.golang.org/p/TRM-fN9nvVd

The primary function types.LookupFieldOrMethod correctly reports a field, but types.NewMethodSet returns the method. Looks like a bug in the method set computation.

(As an aside, types.NewMethodSet is not directly used by go/types, so there's no danger ofgo/typesdirectly being compromised by this - it was requested forx/tools/go/types/typeutil`. I should have said no at that time... :-)

dotaheor

comment created time in 14 days

issue commentgolang/go

cmd/compile: confusing error message for 'a == x && b = y'

@cuonglm Since I was already investigating this a bit more, I just sent out at CL.

josharian

comment created time in 14 days

issue commentgolang/go

cmd/compile: confusing error message for 'a == x && b = y'

@cuonglm I assigned myself to this just so I can keep track of it. Feel free to go ahead for now.

josharian

comment created time in 14 days

issue commentgolang/go

cmd/compile: confusing error message for 'a == x && b = y'

@cuonglm It would be nice to fix this as it is probably a common typo. But at the same time it's subtle to get it right w/o going overboard. Your tentative patch seems reasonable. How about just highlighting the LHS and RHS of the assignment better with parentheses? For instance if the error message were:

syntax error: assignment (a == "a" && b) = "b" used as value

That is, we put parentheses around expressions if they are complex? (Needless to say that this is not even a valid assignment, but I don't think it's worthwhile spending code on figuring this out in the parser.)

Even simpler, maybe it is good enough to take the current approach and just syntaxErrorAt and use the position of the = (which is the assignment's Pos()).

josharian

comment created time in 14 days

issue commentgolang/go

proposal: Go 2: language: make slices of constant strings constant if the indexes are constant

We discussed this issue in the proposal review committee. Since this proposal is not backward-compatible and we put a premium on language stability, we decided to not proceed with this for Go 1.15.

We discussed introducing a vet check instead, but it doesn't seem warranted since this change is essentially language fine-tuning - a "nice to have" if it were backward-compatible, but not important.

I will leave this open for future consideration, when non-backward compatible changes become viable due to universal use of modules.

ainar-g

comment created time in 15 days

issue commentgolang/go

proposal: Go 2 review meeting minutes

2020-02-04 / @griesemer, @iant

  • #35093 Go 2: functions which, when called, can cause the current function to return
    • closed (no further comments)
  • #36702 proposal: Go needs a comparable collection type
    • commented
    • put on hold
  • #36816 proposal: Go 2: expand power of range for slices/arrays
    • commented
  • #36855 Go 2: initialise funcs with custom type names
    • commented
    • likely decline, final call for comments
  • #36863 Go 2: indentation in multiline raw string literals
    • closed (duplicate of #32950)
  • #36884 Go 2: explicit nil and pointer param
    • commented
    • likely decline, final call for comments
  • #36890 Go 2: byte array <-> string conversions
    • commented
  • #36924 Go 2: add nameof() built-in function
    • commented
  • #36387 Go 2: exhaustive switching for enum type-safety
    • commented
griesemer

comment created time in 16 days

issue commentgolang/go

spec: review/clarify uses of "slice of bytes"

Marking for Go 1.15.

griesemer

comment created time in 18 days

issue commentgolang/go

spec: review/clarify uses of "slice of bytes"

@josharian The reason for this issue is that not all implementations agree. @mdempsky 's comment explains how they disagree.

I think we should first get the spec to be crystal clear before making changes. It sounds like we're leaning towards making the interpretation more liberal, so this should not break future code, but enable more. This is not urgent, either.

griesemer

comment created time in 18 days

issue commentgolang/go

go/types: what is the new method (*Checker).LookupFieldOrMethod?

It probably doesn't need to exported - will investigate.

ianlancetaylor

comment created time in 21 days

issue commentgolang/lint

Master doesn't build anymore: undefined: types.NewInterface2

It looks like golint is using an old version of x/tools/go/internal/gcimporter. The current version supports both 1.10 and newer.

Soulou

comment created time in 22 days

issue commentgolang/go

proposal: Go 2: language: make slices of constant strings constant if the indexes are constant

@jimmyfrasche Very nice! Indeed it would.

ainar-g

comment created time in 22 days

issue commentgolang/go

proposal: Go 2: language: make slices of constant strings constant if the indexes are constant

It turns out that this proposed change is not backward-compatible after all ...

Consider "A"[0] : With the proposed change, this expression evaluates to the untyped byte constant 65. But if we try to negate this value, as in:

var _ = -"A"[0]

we will get an error: -"A"[0] (constant -65 of type byte) overflows byte . This is currently (without the change) valid code. Oops!

For similar reasons, constant index expressions are not backwards-compatible either. The length of a constant slice expression len("abc"[0:2]) is an untyped integer constant (3), but if we negate it and try to assign it to a variable of uint type, we will get an error.

var _ uint = -len("abc"[0:2])

(Without the change, these values are not constant, and the compiler won't complain.)

Fun times!

ainar-g

comment created time in 22 days

issue closedgriesemer/tryhard

additional stats

[Pasted from post on the try() thread]

The following stats would be valuable...

  1. the number of call sites yielding an error
  2. the number of single-statement if err != nil [&& ...] handlers (candidates for on err https://github.com/golang/go/issues/32611)
  3. the number of those which return anything (candidates for defer https://github.com/golang/go/issues/32676)
  4. the number of those which return err (candidates for try())
  5. the number of those which are in exported functions of non-main packages (likely false positive)

closed time in 23 days

networkimprov

issue closedgriesemer/tryhard

consider counting and listing instances of uniform error handling within a func

As far as I understand, this first-cut version of tryhard currently undercounts possible uses of try because tryhard does not look for cases of uniform error handling within a function.

Consider reporting at least certain classes of uniform error handling within a function.

These would be candidates for try + defer. Actually re-writing to use defer could be left as an exercise for the reader.

For example, it would be nice to identify f() and g() below as each having two candidate locations for try:

// f uses a function literal to annotate errors uniformly
func f(arg int) error {
	report := func(err error) error { return fmt.Errorf("f failed for %v: %v", arg, err) }

	err := g(arg)
	if err != nil {
		return report(err)
	}

	err = h(arg)
	if err != nil {
		return report(err)
	}
	return nil
}

// g uses repeated code (e.g., copy/paste) to annotate errors uniformly
func g(arg int) error {
	err := h(arg)
	if err != nil {
		return fmt.Errorf("g failed for %v: %v", arg, err)
	}

	err = f(arg)
	if err != nil {
		return fmt.Errorf("g failed with %v: %v", arg, err)
	}
	return nil
}

func h(arg int) error {
	return nil
}

This is a variation (I think?) of the suggestions in https://github.com/golang/go/issues/32437#issuecomment-507764541.

closed time in 23 days

thepudds

issue commentgriesemer/tryhard

consider counting and listing instances of uniform error handling within a func

Closing. try proposal was abandoned.

thepudds

comment created time in 23 days

issue commentgriesemer/tryhard

additional stats

Closing. `'try' proposal was abandoned.

networkimprov

comment created time in 23 days

issue closedgriesemer/tryhard

false negative, possibly due to an else statement

This should be safe to transform:

			if err := dump(w, n, rec); err != nil {
				return err
			} else {
				fmt.Fprintln(w)
			}

to:

			try(dump(w, n, rec)
			fmt.Fprintln(w)

(The key restriction is that err does not appear in the else block.

closed time in 23 days

josharian

issue commentgriesemer/tryhard

false negative, possibly due to an else statement

@codenoid Yes. Thanks for reminding me.

Closing this issue as "wontfix" since we have abandoned the try proposal.

josharian

comment created time in 23 days

issue commentgolang/go

proposal: Go 2 review meeting minutes

2020-01-28 / @bradfitz, @griesemer, @iant

  • #36457 Go 2: A compatible generics syntax
    • commented
    • closed (folded into #15292)
  • #36533 make generic parentheses declaration order consistent with array bracket declaration order
    • commented
    • closed (folded into #15292)
  • #36669 Go 2: decorator support, like python decorator
    • commented
    • likely decline, final call for comments
  • #36387 Go 2: exhaustive switching for enum type-safety
    • commented
  • #36338 Go 2: error handling with error receiver function
    • commented
  • #36332 Go 2: obtain struct field name in type-safe way
    • commented
    • likely decline, final call for comments
  • #36303 new builtin to pick from one of two values
    • commented
    • likely decline, final call for comments
  • #36177 make generic code clearer
    • commented
    • closed (folded into #15292)
griesemer

comment created time in 23 days

issue commentgolang/go

proposal: Go 2: error handling with error receiver function

FYI, here's the discussion of the try version that used an explicit error handler and some of the questions around it: https://github.com/golang/proposal/blob/master/design/32437-try-builtin.md#design-iterations.

drupsys

comment created time in 23 days

issue commentgolang/go

proposal: Go 2 review meeting minutes

2020-01-14 / @bradfitz, @griesemer, @iant

  • #36508 Go 2: remove map from keywords
    • commented
  • #36669 Go 2: decorator support, like python decorator
    • commented
  • #36626 Go 2: make no result values expected when self has no return value too
    • commented
  • #33080 allow conversion between return types and structs
    • commented
  • #36284 Go2: Drying up Error Handling in Go
    • commented
griesemer

comment created time in a month

issue commentgolang/go

go/token: what is base offset?

@jadekler A token.Pos is simply a byte offset from a file's base offset, which is the offset corresponding to the file's first byte. The next file's base offset is usually the current file's base offset plus the file size + 1 (for padding). This maps a set (list) of files' positions to contiguous integer values. Usually you don't need to worry about this, just provide a negative value (-1) and AddFile will take care of it.

I'll add a bit more documentation.

jadekler

comment created time in a month

issue commentgolang/go

runtime: stack traces of endless recursion should print top and bottom

I'm going to mark this for 1.15 so it receives some visibility. This will be very helpful whenever an endless recursion strikes. We can always put it back on backlog.

griesemer

comment created time in a month

issue commentgolang/go

proposal: allow && and || operators and parentheses in build tags

I didn't have a particularly strong opinion about this topic but I must admit that the existing notation always confuses me, too. In math x y means x*y (a multiplicative operation) and that makes me think x y means x & y (also a multiplicative operation). Consequently I read a b, c d as a && b || c && d but that is exactly the opposite of what the current notation means. The only part that seems obvious to me is the "!". The existing notation works of course and (probably, @rsc ?) was born from a desire to have very simple and efficient implementation, but the time has probably come to make this nicer.

After reviewing this discussion and briefly looking at @mvdan 's code I also vote for @josharian 's suggestion. Accept both variants and have a tool to rewrite to the new form (it doesn't have to be gofmt; in general now we expect that gofmt does not modify a source file beyond white space formatting). The tools is a nice-to-have, accepting the new format and documenting it would be the first step.

@mvdan 's code uses the go/parser to parse the boolean expression for simplicity (a single function call). If that is not efficient enough for some reason, it's trivial to write a simple boolean expression parser. Splitting into tokens doesn't require a full blown scanner, it probably can be done inline or on a line base.

mundaym

comment created time in a month

issue commentgolang/go

proposal: Go 2 review meeting minutes

2020-01-14 / @bradfitz, @griesemer, @iant

  • #36407 Go 2: run for loop in a goroutine with go keyword
    • commented
    • likely decline, final call for comments

We also discussed how we can make the Go 2 proposal review process more scalable. Currently it is fairly simple to create a new Go 2 proposal (like the proposal process intended), but then it becomes a significant burden for the proposal committee to ask and answer many of the questions that should have been answered by the proposal. We are planning to introduce a template of questions (CL 214820) with the intent to dismiss new proposals quickly if they don’t have reasonable answers for most of the questions.

griesemer

comment created time in a month

issue commentgolang/go

index/suffixarray: added functionality via longest common prefix array

Agreeing with @ianlancetaylor : It is not that we're not interested in having more functionality, the problem is that by adding more functionality to the std library we're adding maintenance burden (to the Go team) for a library that is not super-widely used but of significant complexity.

Marking NeedsDecision for input from the proposal committee.

petar-dambovaliev

comment created time in a month

issue commentgolang/go

proposal: Go 2 review meeting minutes

2020-01-07 / @bradfitz, @griesemer, @iant

  • #33957 Go 2: Destructuring operator to assign fields in different types of the structs
    • closed (no change in concensus)
  • #35093 Go 2: functions which, when called, can cause the current function to return
    • likely decline, final call for comments
  • #35307 Go 2: vector basic type
    • closed (no change in concensus)
  • #35387 Go 2: file scope
    • closed (no change in concensus)
  • #35528 compact syntax for multiple property assignation on a same object
    • closed (no change in concensus)
  • #35535 treat declared function names as type names
    • closed (no further comments)
  • #35654 Go 2: don't allow taking address of slice elements
    • closed (no further comments)
  • #33167 Go 2: allow self-referencing closures
    • closed (no further comments)
  • #33359 Go 2: negative slice/array indexes
    • closed (no change in concensus)
  • #35179 Go 2: add try statement to specify handler for unhandled errors
    • closed (no change in concensus)
griesemer

comment created time in a month

issue commentgolang/go

cmd/compile: error points to nonexistent file

Agreed.

rsc

comment created time in a month

issue commentgolang/go

go/ast: comment text changes newline type

gopherbot closed this - but yes, this is "working as intended" as far as I can tell. If you have any information indicating this is not the case, feel free to reopen with the relevant information. Thanks.

aykevl

comment created time in 2 months

issue commentgolang/go

go/types: improve error message quality for ptr receiver errors (go/types differs from go tool compile)

This is a go/types, not a gopls issue. Stand-alone test case: https://play.golang.org/p/LAbt1say8h2

The compiler reports: ./prog.go:14:30: cannot use httputil.ReverseProxy literal (type httputil.ReverseProxy) as type http.Handler in return argument: httputil.ReverseProxy does not implement http.Handler (ServeHTTP method has pointer receiver)

go/types reports: ./prog.go:14:9: cannot use (httputil.ReverseProxy literal) (value of type httputil.ReverseProxy) as http.Handler value in return statement: missing method ServeHTTP

It should not be too hard to make the go/types error better.

gertcuykens

comment created time in 2 months

issue commentgolang/go

Proposal: make generic code clearer

One issue I see with the notation

[T Readable, Archive io.Reader]
func ReadArray(arr []T, ar Archive)

is that the call of ReadArray - when types are not inferred, doesn't match the declaration: In the declaration, the type parameters are declared before the function name, in the call they are passed after the function name. This is an aspect we have paid attention to in the past. I am not saying it cannot be changed, but it's something to be aware of.

We have played with a lot of different notations for the type parameters, including using [ and ] and < and >. They all have their problems. [ is surprisingly cumbersome in situations such as x[T] where we would allow a trailing comma (as in x[T,] if the [T] is a type parameter list (because we allow a trailing comma in all parameter lists for consistency); but we can't allow a trailing comma if x[T] is a index expression. Unfortunately we can't know until type checking time at which point it's too late. It can be made to work, but it's not great.

We've also been playing with more condensed forms of type parameter lists, for instance:

func ReadArray(type T Readable, Archive io.Reader : arr []T, ar Archive)

or

func ReadArray(type T Readable, Archive io.Reader ; arr []T, ar Archive)

This latter version would allow the following form (because of automatic semicolon insertion):

func ReadArray(
   type T Readable, Archive io.Reader
   arr []T, ar Archive
)

I personally like the latter because it's light-weight in the simple case, and allows for nice notation across multiple lines in the more complex case w/o extra overhead.

Anyway, I prefer not debating the syntax for now because that's something we can change relatively easily once we have everything else nailed down. What we have now is workable to make progress.

Regarding contracts: I am feeling very strongly that a contract is simply syntactic sugar for a set of interfaces. Specifically, given a general contract

contract C(T1, T2, ... Tn) {
   T1 m11()
   T1 m12()
   ...
   T2 m21()
   T2 m22()
   ...
}

etc. we have to represent the type bounds for each type parameter. The type bounds for type parameter Ti are all the contract entries referring to Ti. If we bundle these together, and if we do this for all type parameters, we get a set of parameterized interfaces, as in:

type I1(type T1, T2, ... Tn) interface {
   m11()
   m12()
   ...
}

type I2(type T1, T2, ... Tn) interface {
   m21()
   m22()
   ...
}
...

This is of course cumbersome to write but it is easy for the type-checker to create these interfaces from a contract. Everything that we can express in a contract we can express in an (extended) interface. For this to work, we also extend interfaces to have type lists, such as in (for example):

type Adder(type T) interface {
   Add(x T) T
   type int, float32, complex64
}

Whether we should allow such interfaces in places outside type parameter bounds is not clear yet, but it's very clear that this makes implementation straight-forward and explainable. More importantly, using interfaces as type bounds does fit with the type theory of generic type systems.

Finally, considering contracts as syntactic sugar for interfaces also resolves the dilemma of what it means to mix contracts and interfaces. The dilemma disappears. A contract is simple a set of interfaces which (sometimes, but not always) may be less cumbersome to write down in form of a contract. I believe in the vast majority of cases, there will be exactly one type parameter, and in the vast majority of cases that type parameter has very simple constraints. Often it will be an interface such as io.Reader or can be written in place. In those cases, a contract is more work.

Using parameterized interfaces also resolves the issue with what you call template methods - which is not a term we have defined for Go or know what it means. In refining our design at this point (syntax aside) it's really important to boil it down to the fine-grained semantics that permits us to implement a type checker that is understood and sound. We should not invent arbitrary mechanisms that are not fundamentally grounded in type theory. We are deliberately not trying to implement something like C++ templates, for that matter (as they cannot be type-checked seperately, w/o instantiation, which is the primary reason the resulting error messages are unreadable if there's a mistake somewhere).

Regarding your last example (contract FooBarable) I don't understand that notation. At least as you have written, that contract is not permitted in the current design draft (each constraint in the contract must be preceded by a type parameter). More generally, a contract does not specify global functions ever - it's representing constraints on a type parameter. But more importantly, I don't see what you gain from being able to specify a specific set of global functions. Both Foo and Bar operate on any type that implements an io.Reader (for Foo) or an io.Writer (for Bar), respectively. Clearly, for Example to work, the type of t must support both. So what's wrong with XXX just being io.ReadWriter?

(As an aside, I just verified that

package p

import "io"

func Foo (type T io.Reader) (r T)

func Bar (type T io.Writer) (w T)

func Example (type T io.ReadWriter) (t T) {
   Foo(t)
   Bar(t)
}

type-checks fine with the current prototype, as expected.)

xushiwei

comment created time in 2 months

issue commentgolang/go

Proposal: Go2: Functions which when called, can cause the current function to return

@iangudger Thanks for providing additional background.

Unfortunately, even a nice non-local return mechanism doesn't quite address the error handling problem because - while some of the machinery could be factored out - the factored out code (a local function/closure) would only work for that one enclosing function. As you mention yourself, those couldn't be easily shared/re-used. Furthermore, even in one function a single closure may not suffice due to signature type requirements that may not be uniform.

Real macros have even more problems. Macros were a clear non-goal from day one.

At some point in the distant past I would preferred a non-local return over a panic approach. The non-local return can be more light-weight (no need to recover to stop the unwinding as there is a definite stack frame which is the one from which to return) and it allows the simulation of panic (albeit that requires passing around some top-level closure from which to non-locally return). They also seem simply a (if non-trivial) generalization of the existing concept of the "return". But non-local returns are somewhat alien to C-like languages. We already have an explicit return, and there would have to be another form of return.

In Smalltalk it works fine because there's only one kind of return - if it happens to be in a closure it's always non-local (and causing the surrounding method to return). Without an explicit return, Smalltalk methods and closures simply return the result of the last expression executed. Such an approach would probably be a poor fit for Go.

The various attempts are improving error handling all failed one way or another. For now, the Go Team is not actively looking for another change in this direction - what we have may not be perfect but is has worked for 10 years. If a promising new idea comes up we can always pick it up. Better to err on the side of caution.

iangudger

comment created time in 2 months

issue commentgolang/go

Proposal: Go2: Functions which when called, can cause the current function to return

There is a strong connection between the functionality of panic and a non-local return (i.e., a mechanism to return from an outer function): In both cases the stack has to be unwound safely, and in both cases one might want to protect a stack frame from being "silently" unwound. That protection in Go is via defer and (and possibly recover), which allows an activation frame to install clean-up actions to be executed before a stack frame is unwound.

Thus, the heavy lifting that panic and recover are doing will also have to be done by another non-local return mechanism (it is very likely that one would want to use defer with any such mechanism).

In other words, panic, defer and recover are equivalent to any other non-local return mechanism and form of stack unwinding protection (that latter of which was not mentioned in this proposal, but would be a likely follow-up demand).

Since we already have panic, defer and recover there's really no need for yet another mechanism. Or, vice versa, if we had another mechanism, we wouldn't need panic.

(For comparison: Smalltalk is a language that actually does support non-local returns. It also supports a method called "unwindProtect:" (or similiar; unfortunately Smalltalk dialects are not standardized). "unwindProtect:" is exactly equivalent to Go's defer. A Go panic can be emulated in Smalltalk by executing a non-local return of a top-level closure (which essentially causes the entire stack to unwind).

In summary, I don't think we need an alternative feature here. And to confirm what @iant has been stating earlier, it is perfectly ok to use a panic (and defer plus recover) to "quickly exit" a top-level function from a deep call-stack. For another example see e.g., text/tabwriter and its use of panics for that purpose.

iangudger

comment created time in 2 months

issue commentgolang/go

proposal: Go 2 review meeting minutes

2019-12-17 / @griesemer

  • #35086 Go2: Error checking and handling inspired on Switch/Case statements
    • closed (no final comments)
  • #35206 Go 2: Discard methods
    • closed (no final comments)

Note: Due to other reviewers being ooo I only processed two proposals that were scheduled for closing.

griesemer

comment created time in 2 months

issue closedgolang/go

proposal: Go 2: Discard methods

type bird struct {
}

func (this *bird) eat() {
}

func (this *bird) drink() {
}

func (this *bird) sleep() {
}

func (this *bird) fly() {
}

type ostrich struct {
    bird
}

func (this *ostrich) runAboutWildly() {
}

// Discard fly
func (this *ostrich) ~ fly()
bigbird := ostrich{}
bigbird.sleep()
bigbird.fly() // not found fly

Provides a way to disable method。 Sometime I will inherit a large number of method when I combine a structure, however I want to abandon some of those methods

closed time in 2 months

JavinYang

issue commentgolang/go

proposal: Go 2: Discard methods

No final comments. Closing.

JavinYang

comment created time in 2 months

issue closedgolang/go

Proposal: Go2: Error checking and handling inspired on Switch/Case statements

Proposal: Go2: Error checking and handling inspired on Switch/Case statements

  • Author: Gustavo Bittencourt

Summary

This proposal tries to address an aspect of Go programs which "have too much code checking errors and not enough code handling them" (Error Handling — Problem Overview). To solve this, the proposal is inspired by Switch/Case statements in Go.

Introduction

This proposal creates the new statement, handle, that defines a scope where one variable is checked and handled as soon there is assignment operation with that variable. That variable is called "handled variable". For example, the following code is how Go handles errors:

func printSum(a, b string) error {
	x, err := strconv.Atoi(a)
	if err != nil {
		return fmt.Errorf("printSum(%q + %q): %v", a, b, err)
	}
	y, err := strconv.Atoi(b)
	if err != nil {
		return fmt.Errorf("printSum(%q + %q): %v", a, b, err)
	}
	fmt.Println("result:", x+y)
	return nil
}

In this proposal, the function could be the following:

func printSum(a, b string) error {
	var err error
	handle err {
		x, err := strconv.Atoi(a)
		y, err := strconv.Atoi(b)
		fmt.Println("result:", x + y)
	case err != nil:
		return fmt.Errorf("printSum(%q + %q): %v", a, b, err)
	}
	return nil
}

The handle statement defines a handled variable (err in the above example) and a scope where this variable is handled. In the handle scope, each time the handled variable is in the left-hand side of an assignment operation, immediately after that assignment operation, it will be executed the checks defined in the case statements.

The case statements are evaluated top-to-bottom; the first one that is true, triggers the execution of the statements of the associated case; the other cases are skipped. If no case matches no one is executed. There is no "default" case.

Defining error handled-variable in the handle statement

The handled variable can be defined in the handle statement, so the code can be even shorter.

func printSum(a, b string) error {
	handle err error {  // <-- the variable 'err' is defined here
		x, err := strconv.Atoi(a)
		y, err := strconv.Atoi(b)
		fmt.Println("result:", x + y)
	case err != nil:
		return fmt.Errorf("printSum(%q + %q): %v", a, b, err)
	}
	return nil
}

Example: Error handling with defer statement

In Golang:

func CopyFile(src, dst string) error {
	r, err := os.Open(src)
	if err != nil {
		return err
	}
	defer r.Close()
	w, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer w.Close()
	if _, err := io.Copy(w, r); err != nil {
		return err
	}
	if err := w.Close(); err != nil {
		return err
	}
}

In this proposal:

func CopyFile(src, dst string) error {
	handle err Error {
		r, err := os.Open(src)
		defer r.Close()
		w, err := os.Create(dst)
		defer w.Close()
		_, err = io.Copy(w, r)
		err = w.Close()
	case err != nil:
		return err
	}
}

Example: Error handling without return

In Golang:

func main() {
	hex, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		log.Fatal(err)
	}
	data, err := parseHexdump(string(hex))
	if err != nil {
		log.Fatal(err)
	}
	os.Stdout.Write(data)
}

In this proposal:

func main() {
	handle err Error {
		hex, err := ioutil.ReadAll(os.Stdin)
		data, err := parseHexdump(string(hex))
		os.Stdout.Write(data)
	case err != nil:
		log.Fatal(err)
	}
}

Handling non-error variable

It is possible to handle non-error variables, like:

func doSomething() error {
	handle i int {
		i = func1()
		i = func2()
	case i == -1:
		return fmt.Errorf("Error: out-of-bound")
	case i == -2:
		return fmt.Errorf("Error: not a number")
	}
}

Nested handle scopes

There are some hard decisions to make the nested handle scopes works properly. So, this proposal suggests to forbid nested handle scopes.

closed time in 2 months

gbitten

issue commentgolang/go

Proposal: Go2: Error checking and handling inspired on Switch/Case statements

No final comments. Closing.

gbitten

comment created time in 2 months

issue commentgolang/go

Proposal: make generic code clearer

Hello @xushiwei; thanks for the feedback!

Here are (my) preliminary answers to your questions:

  1. Now that I have written quite a bit of generic code using my work-in-progress prototype, I also feel that func New (type Node, Edge G) (nodes []Node) *Graph(Node, Edge) is not all that great for readability. That said, currently we are concentrating on the semantics a bit more and leaving the notation alone, simply to make progress. Once we are confident with the semantics, it's relatively easy to polish/update the syntax.

Your suggestion of writing

[Node, Edge G]
func New(nodes []Node) *Graph[Node, Edge] {
    ...
}

does read pretty nicely, but it doesn't match the function invocation (at least if type parameters are passed explicitly which is necessary here because the Edge type cannot be inferred). How would one call this function and pass in the Edge type?

  1. Regarding the "operator notation" you are advocating: Yes, we have been thinking about this as well. Earlier generics proposals did exactly what you are suggesting. The problem is not (binary) operators, though. The problem is that there are a lot of additional operations such as conversions, assignability, etc. that we need to express as well, and there is no "obvious" method notation for those constraints. The current notation of enumerating the types works surprisingly well; but it also closes the door a bit on operator methods. But see 1): For now we concentrate on the semantics to make some progress.

  2. I agree with you that a contract is a form of generic interface. Please see https://golang.org/cl/187317, specifically the Commit message of that CL. Internally, a contract is disassembled into interfaces. In other words, in my mind, a contract is simply syntactic sugar for a set of interfaces.

  3. Interesting suggestion. I have to think a bit more about it. That said, for now, we like to get the basics correct before venturing further afield. The basics we are concerned about right now are the following questions:

  • what exactly is the connection between interfaces and contracts (my current thinking is that contracts are syntactic sugar for interfaces)?
  • can we do better that enumerate a list of types for operator constraints?

And on the syntactic side:

  • can we improve the type parameter notation to make type-parameterized function signatures more readable?
xushiwei

comment created time in 2 months

issue commentgolang/go

spec: some wording need to be adjusted for embedding alias of pointer types

Just FYI: go/types also accepts this code.

go101

comment created time in 2 months

issue commentgolang/go

proposal: Go 2 review meeting minutes

2019-12-10 / @bradfitz, @griesemer, @iant

  • #35966 Go 2: universal zero value with type inference
    • commented
  • #33167 Go 2: allow self-referencing closures
    • likely decline, final call for comments
  • #33359 Go 2: negative slice/array indexes
    • likely decline, final call for comments
griesemer

comment created time in 2 months

issue commentgolang/go

doc: go spec says grammar is "regular", but it is not regular in grammar sense

I think the comment made in #1798 still stands - this is not a statement about the language category. Leaving open for a bit just to see if an equally attractive alternative phrasing emerges. Perhaps: "The grammar is compact and has a regular structure, ..." which is really what we're trying to express.

ehdtee

comment created time in 2 months

issue commentgolang/go

go/types: include import path in type error messages

The latest CL now matches the behavior of the compiler.

stapelberg

comment created time in 3 months

issue commentgolang/go

math: add MaxUint, MinInt, MaxInt

@rverma-jm This proposal is specifically about the functions mentioned in the title. Please do not hijack this proposal as it is now accepted. Instead open a new proposal if you want to add something else. Thanks.

Silentd00m

comment created time in 3 months

issue commentgolang/go

proposal: Go 2 review meeting minutes

2019-12-03 / @bradfitz, @griesemer, @iant

  • #34996 Go 2: syntax for explicitly implementable interfaces
    • closed (no change in consensus)
  • #35010 Go 2: integer comparison casting
    • closed (no final comments)
  • #33161 Go 2: block scoped error handling
    • closed (no final comments)
  • #35528 compact syntax for multiple property assignation on a same object
    • likely decline, final call for comments
  • #35535 treat declared function names as type names
    • likely decline, final call for comments
  • #31795 Go 2: change len, cap to return untyped ints if result is constant
    • closed (retracted by author)
  • #35654 Go 2: don't allow taking address of slice elements
    • likely decline, final call for comments
griesemer

comment created time in 3 months

issue closedgolang/go

proposal: Go 2: change len, cap to return untyped ints if result is constant

Reminder issue.

Can we change len, cap, etc. to return an untyped value rather than an int if they are constant expressions? Investigate if this is possible in a backward-compatible way.

closed time in 3 months

griesemer

issue commentgolang/go

proposal: Go 2: change len, cap to return untyped ints if result is constant

Agreeing with @rsc here. While this seems like an easy win at first glance, it's not clear that the corner cases are worth the extra complexity. I am retracting this proposal.

griesemer

comment created time in 3 months

issue commentgolang/go

go/types: include import path in type error messages

The fix is trivial (https://golang.org/cl/209578) but may have implications for client code that parses error messages. Also, we're currently in the 1.14 freeze and this may cause needless instability. Marking NeedsDecision for input from others.

stapelberg

comment created time in 3 months

issue commentgolang/go

go/types: include import path in type error messages

Marking tentatively for 1.14 since this only affects an error message.

stapelberg

comment created time in 3 months

issue commentgolang/go

proposal: math/big: add Int.BytesWithSize

My original thought was also Read, but that name suggests that there's a result (n int, err error) as well which is perhaps overkill, especially if we never expect an error and if we don't care about the n since the buffer will be 0-padded. Also, given a Read method, one would expect a client to be able to call Read repeatedly to get all the bytes of an Int, which is not the case.

Maybe FillBytes if you don't like AsBytes? The former implies more of an "action" (of filling in the bytes) rather than a function call (that returns a value) as does the latter.

FiloSottile

comment created time in 3 months

issue commentgolang/go

go/ast: comment text changes newline type

Generally, the go/scanner removes CRs in comments (not just at the end, also inside the comment) and elsewhere. Changing this (in the go/scanner) is likely going to break existing tools in subtle ways.

We also want tools such as gofmt to produce the same result independent of whether one runs on a Windows machine or not, which requires that newlines are always represented in one way, using LF.

I would expect this to work if you run the code on gofmt-ed code. Does it not?

aykevl

comment created time in 3 months

issue commentgolang/go

proposal: math/big: add Int.BytesWithSize

Would it make sense to provide the byte slice to avoid a copy?

func (x *Int) AsBytes(buf []byte)
FiloSottile

comment created time in 3 months

issue commentgolang/go

proposal: Go 2 review meeting minutes

2019-11-19 / @bradfitz, @griesemer, @iant

  • #33167 Go 2: allow self-referencing closures
    • commented
    • removed final call for comments label due to valid feedback
  • #34896 Go 2: looping with deferred condition as do while
    • closed (no further comments)
  • #34144 Go 2: extend "continue" to jump to start of function
    • closed (no further comments)
  • #34088 Go 2: allow trailing commas in the switch case enumerations
    • closed (no change in concensus)
  • #35086 Go2: Error checking and handling inspired on Switch/Case statements
    • commented
    • likely decline, final call for comments
  • #35093 Go2: Functions which when called, can cause the current function to return
    • commented
  • #35179 Go 2: add try statement to specify handler for unhandled errors
    • commented
    • likely decline, final call for comments
  • #35206 Go 2: Discard methods
    • commented
    • likely decline, final call for comments
  • #35304 anonymous struct literals
    • commented (in fair detail)
  • #35307 Go2: Vector Basic Type - Similar to []T but with enhancements
    • commented
griesemer

comment created time in 3 months

issue commentgolang/go

proposal: anonymous struct literals

Presumably one could write:

var s struct{x int; y float32} = struct{...}{1, 2}

and the 2 in the struct literal would become a float32 in the assignment?

rogpeppe

comment created time in 3 months

issue commentgolang/go

proposal: Go 2 review meeting minutes

2019-11-12 / @bradfitz, @griesemer

  • #32895 Go 2: mini-package: a solution to unify Go builtin and custom generics
    • closed (no change in consensus)
  • #33078 "Filled types": a mechanism to guarantee types are not nil at compile time
    • closed (author ok’ed closing the issue)

Note: This was an abbreviated mtg due to external scheduling conflicts.

griesemer

comment created time in 3 months

issue openedgolang/go

math/big: investigate if (Int) BenchmarkDiv can fail in rare circumstances due to error in et

Reminder issue to look into comment in https://golang.org/cl/172018 on BenchmarkDiv.

created time in 3 months

issue openedgolang/go

math/big: apply simplification suggested in CL 73231 (or abandon)

Reminder issue: Decide whether to apply https://go-review.googlesource.com/c/go/+/73231 for Go 1.15 (early) or abandon.

Specifically: The change must be applied to the new function lehmerSimulate. Also, need to verify that there's no performance regression.

created time in 3 months

issue commentgolang/go

cmd/compile: inlining signed shift from Go 1.13 package into Go 1.12 package causes compilation error

Not a regression, but would be nice to get fixed.

mdempsky

comment created time in 3 months

issue commentgolang/go

cmd/compile: compilation of Go 1.13 package fails when importing exported interface type with overlapping methods from Go 1.14 package

When compiling a Go 1.13 package, shouldn't we fail if we depend on a Go 1.14 feature?

mdempsky

comment created time in 3 months

issue commentgolang/go

encoding/binary: Read fails to detect a non-pointer 'data' argument

@odeke-em Thanks. On it.

martin-juhlin

comment created time in 3 months

issue commentgolang/go

proposal: Go 2 review meeting minutes

2019-11-05 / @bradfitz, @griesemer, @iant

  • #33088: Go2: automatically take address of pointer parameters (reference arg behavior)
    • closed (one comment, no substantial change)
  • #33150: Go 2: use symbol or function call in assignment for error handling
    • closed (one comment, no substantial change)
  • #34515 Go 2: extended type inference for make and new
    • commented
  • #34868 compile-time boolean assertions
    • commented
  • #34996 Go 2: syntax for explicitly implementable interfaces
    • commented
    • likely decline, final call for comments
  • #35010 Go 2: integer comparison casting
    • commented
    • likely decline, final call for comments
griesemer

comment created time in 4 months

issue commentgolang/go

proposal: spec: support ... TODO statement

One way to look at ... is for it to mean "(compiler, please) fill in the blanks".

We already do this in array literals; e.g., in [...]int{1, 2, 3} the ... means "fill in the obvious array length" (which would be 3 in this case).

Generalizing this idea, len(...) in a[len(...) - 1] could mean "fill in the expression denoting the indexed array" (in this case of course a would be shorter than ... but in general that may not be the case). This has been mentioned in #33359 .

Furthermore, ... in make(...) and new(...) could mean "fill in the type per context". For instance, one might be able to write:

var m map[string]float64
m = make(...) // make a map of m's type

See also #34515.

... is also discussed in conjunction with return statements where a return of the form return ..., err would also mean, "fill in the leading result expressions with the appropriate zero values". See #21182.

With this general interpretation, ... as a statement would mean "fill in the (obvious) statement" - which there isn't one, so at runtime we get a panic.

It could allow us to compile/type-check incomplete pseudo code as it might be used in a presentation. It would also be quite useful when rapidly developing a new piece of code (where I currently stub out missing pieces with panic(0)).

I'm not convinced this is a good idea yet, but it seems as if it could be reasonably generalized, it's relatively simple, and has interesting use cases. It seems intriguing, especially if the use cases read naturally and almost explain themselves.

Q: Would ...{} mean, use the context-correct type for the composite literal? Not sure.

bradfitz

comment created time in 4 months

issue commentgolang/go

x/tools/go/ssa: panic: no ssa.Value for function argument

@dominikh Yes, it's possible that type-checking might proceed in a different order - it's not obviously clear what would have changed w/o analyzing this case in detail, though. I created #35374 to follow up on this when I have a chance. Thanks for tracking this down.

dominikh

comment created time in 4 months

issue openedgolang/go

go/types: investigate commit bdd0ff08 effect on type-checking outcome

Follow-up on #33279. Investigate impact of commit bdd0ff08 on this piece of code:

package pkg

func fn() {
	func(arg int) []int {
		_ = arg
		return nil
	}(0)[0]++
}

created time in 4 months

issue closedgolang/go

go/types: comparison of Defined (Named) types fails

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

<pre> go version go1.13.3 linux/amd64 </pre>

Does this issue reproduce with the latest release?

<pre> Yes. </pre>

What operating system and processor architecture are you using (go env)?

<details><summary><code>go env</code> Output</summary><br><pre> GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/fabel/.cache/go-build"
GOENV="/home/fabel/.config/go/env"
GOEXE=""
GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="linux" GONOPROXY="" GONOSUMDB="" GOOS="linux" GOPATH="/home/fabel/go" GOPRIVATE="" GOPROXY="https://proxy.golang.org,direct" GOROOT="/usr/local/go" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64" GCCGO="gccgo" AR="ar" CC="gcc" CXX="g++" CGO_ENABLED="1" GOMOD="/home/fabel/go/src/github.com/golang/go/src/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-build619135294=/tmp/go-build -gno-record-gcc-switches" </pre></details>

What did you do?

package main

import (
	"fmt"
	"go/importer"
	"go/token"
	"go/types"
)

const importThis = "."

type SType struct{}

var SInstance SType

func main() {
	theScope := importScope(importThis)
	typeofSType := theScope.Lookup("SType").Type()

	theSameScope := importScope(importThis)
	typeofSInstance := theSameScope.Lookup("SInstance").Type()

	if types.AssignableTo(typeofSInstance, typeofSType) {
		fmt.Println("EXPECTED.")
	} else {
		fmt.Println("UNEXPECTED!")
	}
}

func importScope(importpath string) *types.Scope {
	goImporter := importer.ForCompiler(token.NewFileSet(), "source", nil)
	pkg, err := goImporter.Import(importpath)
	if err != nil {
		panic(`run it from source dir to make const "importThis" true`)
	}

	return pkg.Scope()
}

What did you expect to see?

<pre> EXPECTED. </pre>

What did you see instead?

<pre> UNEXPECTED! </pre>

closed time in 4 months

guzenok

issue commentgolang/go

go/types: comparison of Defined (Named) types fails

This is working as intended.

The bug is not in go/types, it is in the sample program provided. During a single compilation, or in this program, for the duration of the program, go/types Objects and Types must be canonicalized for them to be directly comparable. Specifically, this means, that one cannot mix and match Objects imported by different importer because it is the responsibility of an importer to canonicalize Objects and Types.

The bug in the sample program provided is that importScope creates a new importer with each call instead of reusing one. The fix is easy: create the importer only once and reuse it: This program works as expected:

package main

import (
	"fmt"
	"go/importer"
	"go/token"
	"go/types"
)

const importThis = "."

type SType struct{}

var SInstance SType

func main() {
	theScope := importScope(importThis)
	typeofSType := theScope.Lookup("SType").Type()

	theSameScope := importScope(importThis)
	typeofSInstance := theSameScope.Lookup("SInstance").Type()

	if types.AssignableTo(typeofSInstance, typeofSType) {
		fmt.Println("EXPECTED.")
	} else {
		fmt.Println("UNEXPECTED!")
	}
}

// A single goImporter must be used for all imports to ensure
// identical Objects and types are properly canonicalized.
var goImporter = importer.ForCompiler(token.NewFileSet(), "source", nil)

func importScope(importpath string) *types.Scope {
	// goImporter := importer.ForCompiler(token.NewFileSet(), "source", nil) // <<< THIS IS THE BUG
	pkg, err := goImporter.Import(importpath)
	if err != nil {
		panic(`run it from source dir to make const "importThis" true`)
	}

	return pkg.Scope()
}
guzenok

comment created time in 4 months

issue commentgolang/go

proposal: Go 2: Type parameterized interface default methods

This is a summary of the proposal as I understand it:

  1. For each method m of an interface type T one may declare a default implementation (at most one).

  2. The default implementation of a method m looks like any other method declaration except that a) the receiver type name T (which is the name of the interface) must be preceded with a $ as in $T, and b) the signature must match the existing method signature of m in the interface type.

  3. Inside a default method, $T denotes the actual (concrete) type of the receiver.

  4. A concrete (non-interface) type C implements such an interface T if C implements all methods which don't have a default implementation (more accurately: which don't have a default implementation that compiles for C).

(Then there is some fine print regarding embedding, etc. which doesn't seem relevant to understand the basic idea.)

First of all, I think this could be simplified: Instead of requiring that method signatures must match (which is only extra work for a compiler, and requires that two signatures be kept in sync by a programmer), why not simply permit that concrete methods may be added to an interface type as we allow for other types? Then we don't need the special rules. We can just write:

type Interface interface{}

func (s $Interface) Len() int { return len(s) }
func (s $Interface) Less(i, j int) bool { return s[i] < s[j] }
func (s $Interface) Swap(i, j int) {s[i], s[j] = s[j], s[i] }

The default methods would be part of the method set, of course, and they could be implemented by concrete types as before. The signature is the same. (This doesn't change the proposal's capabilities.)

The problem with this specific example though is that for many types, the default implementation doesn't compile (as you mention yourself), because many type don't understand indexing (in this example). In that case you suggest one has to provide default implementations for the relevant methods. But the only way to find out about this in general is by compiling the default methods (over and over, for each type C) again (note that a default method may be hugely complicated). Worse, the default method doesn't compile, it's not obviously clear what's wrong (with the concrete type) because the error depends on some implementation detail. This is something we absolutely want to avoid (and we do avoid it in the current contracts design draft). From a client's perspective it also seems odd that sometimes one doesn't have to provide an implementation for a default method, and sometimes one does, entirely depending on the internals of the default method.

Implementation-wise, default methods may often have to be custom-generated for each concrete type because they are effectively generic methods.

In summary, I don't see why we would not rather provide parameterized types and constraints (contracts) instead of a more restricted approach such as this which nevertheless has all the same problems. For instance, with the current contracts design, we can write:

// The existing sort.Interface.
type Interface interface{
    Len() int
    Less(i, j int) bool
    Swap(i, j int)
}

// A sort.Interface default implementation for a type T.
type Default(type T Indexable) T

func (s Default(T)) Len() int { return len(s) }
func (s Default(T)) Less(i, j int) bool { return s[i] < s[j] }
func (s Default(T)) Swap(i, j int) {s[i], s[j] = s[j], s[i] }

where Indexable is a contract that says that T must be a type that understands indexing (and thus len).

smyrman

comment created time in 4 months

issue commentgolang/go

proposal: Go 2 review meeting minutes


2019-10-29 / @bradfitz, @griesemer, @iant

  • #33029 Go 2: add "or err: statement" after function calls for error handling
    • closed (no further comments)
  • #33046 Go 2: Make goroutine return channel with function result (promise)
    • closed (no further comments)
  • #33067 Go 2: remove the "if" keyword and use "err?!" to avoid error handling boilerplate
    • closed (no further comments)
  • #33070 Go 2: list symbols that don't require package name
    • closed (no further comments)
  • #33074 Go 2: Use ?<variable> simplify handling of multiple-return-values
    • closed (by submitter on 2019-10-07)
  • #33167 Go 2: allow self-referencing closures
    • commented
    • likely decline, final call for comments
  • #33359 Go 2: negative slice/array indexes
    • commented
  • #33957 Go 2: Destructuring operator to assign fields in different types of the structs
    • commented
  • #34174 string interpolation
    • commented
  • #34403 Go 2: aggregate error handling & defer syntax sugar
    • likely decline, final call for comments
griesemer

comment created time in 4 months

issue commentgolang/go

go/types: some small problems in docs

Agreed. CL forthcoming.

yaxinlx

comment created time in 4 months

issue commentgolang/go

doc: suggest: restrore the "defined type" terminology to "named type".

@go101 Yes, it should have been type T = struct { f int }. Corrected.

go101

comment created time in 4 months

issue commentgolang/go

cmd/compile/internal/syntax: TestStdLib verbosely broken on Windows

The actual error was a silly oversight for Windows (hardwired path separator). The verbose long test output is independent. Will fix separately (see #35223).

bcmills

comment created time in 4 months

issue openedgolang/go

cmd/compile/internal/syntax

Reminder issue: Disable verbose logging/output when running all tests. Use a flag (-v?) to enable the logging instead.

created time in 4 months

issue commentgolang/go

proposal: spec: generic programming facilities

@JavierZunzunegui Discussing conversions of the sort []B([]A) if B(a) (with a of type A) is permitted seems to be mostly orthogonal to generic features. I think we don't need to bring this in here.

adg

comment created time in 4 months

issue commentgolang/go

proposal: Go 2: syntax for explicitly implementable interfaces

@sergefdrv I'm not sure I understand what you mean by the need to have to define dummy methods for interfaces that are recursively embedded.

But here's an example of the use of dummy methods (I'd call them "qualifying methods") in one of the oldest packages in the Go eco-system: go/ast, see the Expr,Stmt, and Decl interfaces with the respective methods exprNode, stmtNode, and declNode (btw., in other situations one may choose to export those methods). Yes, all of the concrete implementation must implement those qualifying methods (see lines 492ff), but that's not a big deal. Having to declare in each of those concrete implementations that they implement a specific interface would only be marginally shorter. It would also require a new language mechanism (and introduce all kinds of syntactic questions since all kinds of types - not just structs - can implement an interface). And it (likely) wouldn't permit the same fine-grained control (non-exported or exported qualifying or dummy method), or the ability to express that a type satisfies multiple interfaces, etc.

In short, I see zero advantage in adding a specific language mechanism that can be beautifully expressed with a mechanism we already have (methods), especially when the method names are chosen carefully. There is neither more safety, nor more readability, nor significantly simpler code. Nor is this something that people want to do so often that some form of syntactic sugar is warranted.

Maybe using methods is "unusual" when coming from other languages, but a point of Go is to not add machinery for things that can be easily expressed with existing mechanisms. Yes, it needs to be learned (or found), and that is ok.

sergefdrv

comment created time in 4 months

issue commentgolang/go

proposal: spec: generic programming facilities

@JavierZunzunegui One of the interesting properties of parameterized (generic) code is that the compiler can customize it based on the type(s) the code is instantiated with. For instance, one migth want to use a byte type rather than int because it leads to significant space savings (imagine a function that allocates huge slices of the generic type). So simply restricting the code to a "large enough" type is an unsatisfying answer, even for an "opinionated" language such as Go.

Furthermore, it's not just about algorithms that use "large" untyped constants which may be not so common: dismissing such algorithms with a question "how many of those are there anyways" is simply hand-waving to deflect a problem that does exist. Just for your consideration: It seems not unreasonable for a large number of algorithms to use integer constants such as -1, 0, 1. Note that one could not use -1 in conjunction with untyped integers, just to give you a simple example. Clearly we cannot just ignore that. We need to be able to specify this in a contract.

adg

comment created time in 4 months

issue commentgolang/go

proposal: spec: generic programming facilities

@JavierZunzunegui I am not saying at all that T be defined as a float32 - it could be a float32, a float64, or even one of the complex types. More generally, if the constant were an integer, there could be a variety of integer types that would be valid to pass in to this function, and some that aren't. It's certainly not a "wrong problem statement". The problem is real - it's certainly not contrived at all to want to be able to write such functions - and the problem doesn't go away by declaring it "wrong".

adg

comment created time in 4 months

issue commentgolang/go

proposal: spec: generic programming facilities

@JavierZunzunegui I don't see how the caller can do such conversions w/o exposing them in the interface. For instance, I might want to implement a generic numeric algorithm (a parameterized function) operating on various integer or floating point types. As part of that algorithm, the function code needs to assign constant values c1, c2, etc. to values of the parameter type T. I don't see how the code can do this without knowing that it's ok to assign these constants to a variable of type T. (One certainly wouldn't want to have to pass those constants into the function.)

func NumericAlgorithm(type T SomeContract)(vector []T) T {
   ...
   vector[i] = 3.1415  // <<< how do we know this is valid without the contract telling us?
   ...
}
adg

comment created time in 4 months

issue commentgolang/go

proposal: spec: generic programming facilities

@JavierZunzunegui Providing a "method format" (or operator format) for basic unary/binary operators is not the problem. It's fairly straight-forward to introduce methods such as +(x int) int by simply allowing operator symbols as method names, and to extend that to built-in types (though even this breaks down for shifts since the right-hand operator can be an arbitrary integer type - we don't have a way to express this at the moment). The problem is that that is not sufficient. One of the things that a contract needs to express is whether a value x of type X can be converted to the type of a type parameter T as in T(x) (and vice versa). That is, one needs to invent a "method format" for permissible conversions. Furthermore, there needs to be a way to express that an untyped constant c can be assigned to (or converted to) a variable of type parameter type T: is it legal to assign, say, 256 to t of type T? What if T is byte? There's a few more things like this. One can invent "method format" notation for these things, but it gets complicated quickly, and it's not clear it's more understandable or readable.

I'm not saying it can't be done, but we have not found a satisfactory and clear approach. The current design draft which simply enumerates types on the other hand is pretty straight-forward to understand.

adg

comment created time in 4 months

issue commentgolang/go

doc: suggest: restrore the "defined type" terminology to "named type".

I'm concerned that switching back is only going to increase confusion. I leave this open for now so others can chime in, but there's no urgent need to change this.

I agree that defined type is not great, but named type is not great either in the presence of alias types. It is difficult to argue that T as declared in type T struct { f int } doesn't have a name (clearly it does have the name T) and thus is not a named type (if it has a name, why is it not a named type?).

go101

comment created time in 4 months

issue commentgolang/go

proposal: Go 2: integer comparison casting

Today, the rules for comparison operators are slightly different from other operators, but for numeric types the rules end up effectively being the same: For comparisons the spec says that one of the operands must be assignable to the type of the other. For integer types this means that the operands have to be effectively the same (excluding untyped operands and shifts for which we have special rules). This is the rule we have for other binary operators: both operands must have the same type.

Since comparisons have special rules already, we can perhaps (but see below) tweak those rules w/o affecting anything else.

That said, I think it's a slippery slope: Once we allow say i16 < i32 (with i16, i32 operands of type int16 and int32), it's quite natural to ask why i16 + i32 should not be permitted. And by extension, why i32 = i16 should not be permitted as well. In fact, if we allow such assignments, the rules for comparison don't have to be changed at all, since changing the assignment rule would change the comparison rule (which is based on assignability) and it would just fall out naturally.

So I think another way of asking this question is: Should (by way of example) i32 = i16 be permitted (and we let the rest follow)?

Perhaps that's a step too far and only comparison rules should be relaxed as proposed. But even that is not so simple. For instance, the code:

var x interface{} = byte(0)
y := 0
result := x == y

is valid and result is false because the dynamic type of x (byte) and the type of y (int) don't match. We couldn't change this behavior without loosing backward-compatibility, but arguably this comparison would then work differently if we allowed byte(0) == int(0) to be ok.

One final observation: Let's assume i32 = i16 were permitted, this would have some consequences on our current contracts (generic) proposal, specifically type inference for parameterized functions: Currently, the proposed inference mechanism is extremely straight-forward. If "widening assignments" are permitted, one would also expect them to be used in type inference which will make the type inference algorithm less straight-forward (an inferred parameter type T is going to be the "smallest (numeric) type large enough" to cover all arguments assigned to parameters of type T).

Just to be clear, I am not for or against this proposal at this point. Just trying to explore the lay of the land.

Hucaru

comment created time in 4 months

issue commentgolang/go

proposal: net: add BufferedPipe (buffered Pipe)

@bcmills What is your concrete suggestion? Do you propose that BufferedPipe (https://github.com/golang/go/issues/34502#issuecomment-537591528) should take a size argument?

iangudger

comment created time in 4 months

issue commentgolang/go

proposal: Go 2: allow trailing commas in the switch case enumerations

@ainar-g These syntax suggestion seem to make it worse - now I have to write some form of parentheses around lists? Just so that I can add an optional comma at the end? This cure seems worse than the disease.

ainar-g

comment created time in 4 months

issue commentgolang/go

proposal: Go 2 review meeting minutes

2019-10-22 / @bradfitz, @griesemer

  • #35010 Go 2: integer comparison casting
    • commented
  • #34996 Go 2: syntax for explicitly implementable interfaces
    • commented
  • #34896 Go 2: looping with deferred condition as do while
    • commented
    • likely decline, final call for comments
  • #34144 Go 2: extend "continue" to jump to start of function
    • commented
    • likely decline, final call for comments
  • #34088 Go 2: allow trailing commas in the switch case enumerations
    • commented
    • likely decline, final call for comments
  • #34515 Go 2: extended type inference for make and new
    • commented
griesemer

comment created time in 4 months

issue commentgolang/go

proposal: Go 2: extended type inference for make and new

Regarding typeof: Instead of a new keyword, typeof could easily be a built-in. The possible "danger" of a typeof operator is that people might start using it all over the place, for all kinds of declarations, thereby reducing the readability of the code.

There's clearly a strong sentiment for being able to use make() or new() and have both of them infer the necessary type. Though we don't have anything else in the language that behaves like this at the moment. Is there a better syntax?

DeedleFake

comment created time in 4 months

issue commentgolang/go

proposal: Go 2: allow trailing commas in the switch case enumerations

Given the feedback above, this is a likely-decline. Leaving open for 4 weeks for final comments/better syntax suggestions.

ainar-g

comment created time in 4 months

issue commentgolang/go

proposal: Go 2: looping with deferred condition as do while

From your examples it is unclear what you're trying to achieve here. Also, there doesn't seem to be much support for it. For these reason this is a likely-decline. Leaving open for 4 weeks for comments.

gocs

comment created time in 4 months

issue commentgolang/go

proposal: Go 2: syntax for explicitly implementable interfaces

What is the benefit of this approach over "sealed interfaces" besides perhaps making a dependency more explicit in the code?

sergefdrv

comment created time in 4 months

more