mvdan/goreduce

Cannot reduce program that doesn't type-check (internal compiler error)

ALTree opened this issue · 9 comments

I'm on go version devel +5e954047bc Fri Mar 24 20:07:15 2017 +0000 linux/amd64.

The following code:

package b

func Func2107() {
	if false {
		Var2528 := (**[1]*int)(nil)
		(func() map[interface{}]uint {
			return map[interface{}]uint{}
		})()[interface{}(nil)]--
	}
}

crashes goreduce when run as goreduce -match="cannot inline" . Func2107 with:

panic: types.Check should not error here

goroutine 1 [running]:
main.(*reducer).reduceLoop(0xc4200ac8c0, 0x0)
	/home/alberto/gocode/src/github.com/mvdan/goreduce/reduce.go:230 +0x2b8
main.reduce(0x7ffceafc94ad, 0x1, 0x7ffceafc94af, 0x8, 0x7ffceafc949f, 0xd, 0x7ff880, 0xc42000c020, 0xc42000e220, 0x0, ...)
	/home/alberto/gocode/src/github.com/mvdan/goreduce/reduce.go:150 +0x1213
main.main()
	/home/alberto/gocode/src/github.com/mvdan/goreduce/main.go:44 +0x10e
mvdan commented

Thanks for reporting! Not sure why this would happen.

mvdan commented

Ah, this is a weird one. The issue is that go/types finds Var2528 is declared but not used, but cmd/compile does not. I was relying on the fact that if cmd/compile correctly type-checked a program, go/types would accept it too.

mvdan commented

Seems like we can't tell go/types to ignore unused variables - only unused imports.

The only other solution I can think of right now is to ignore go/types errors and try our best without them. A quick test makes goreduce get to:

package b

func Func2107() {
        if false {
                Var2528 := (*[0]int)(nil)
                func() map[interface{}]uint {
                        return map[interface{}]uint{}
                }()[interface{}(nil)]--
        }
}

This is a slippery slope though, as the reducer can't do much without type information.

@josharian do you know why cmd/compile and go/types diverge like this? Or is this a cmd/compile bug and I should file an issue?

mvdan commented

Another insight: cmd/compile does error properly on this:

func f() {
        if false {
                foo := 1
        }
}

So it seems like the issue is that cmd/compile got to the internal error before getting to the type checker (unused var) error. Not sure what to do here, if we want the tool to be able to work with these compiler errors.

I see two ways: either you want goreduce to work on programs that crash the compiler (and I don't know if that's feasible); or you can just say "yeah if it crashes the compiler don't run goreduce on it" and in that case I guess you could just fix goreduce so that it reports what's wrong (i.e. compiler error) instead of panicking.

mvdan commented

@ALTree while reducing runtime crashes or simpler compiler errors is useful, I would like the tool to also be able to work on internal compiler errors. After all, these are the ones that are likely to be found by tools like gosmith.

IMO the question is: is there anything to be done to be able to get type info (like get go/types to get past soft errors), or should it just do its best with just the AST if type info is not available?

mvdan commented

Ah, I believe we can indeed get go/types to ignore soft errors by using the types.Config.Error callback func. Will run some tests.

mvdan commented

Okay, that worked. Thanks for reporting, I hadn't thought about internal compiler errors much yet (I didn't have any to test on, to begin with).

mvdan commented

Also, if either of you has any idea on how to have unit/regression tests for compiler crashes, that would be great. I obviously can't rely on real ones, as they would be fixed sooner than later.