Thanks to visit codestin.com
Credit goes to github.com

Skip to content

A lot of "unreachable code" warnings on Firefox #575

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
hajimehoshi opened this issue Jan 21, 2017 · 9 comments · Fixed by #1071
Closed

A lot of "unreachable code" warnings on Firefox #575

hajimehoshi opened this issue Jan 21, 2017 · 9 comments · Fixed by #1071

Comments

@hajimehoshi
Copy link
Member

It seems like this occurs even in the playground itself, so it's hard to suggest a minimum code snippet with the playground.

http://www.gopherjs.org/playground/#/uo5azM3CaP

@dmitshur
Copy link
Member

I can reproduce in Firefox 52.0a2.

image

@dmitshur
Copy link
Member

I'm seeing this issue occur again with latest playground, built with latest gopherjs. Reopning to track it. I'll try to add more details soon, but this is very easy to reproduce. I tested with Firefox Nightly.

@dmitshur dmitshur reopened this Mar 14, 2017
@dmitshur
Copy link
Member

It happens on the same input as in the original issue report.

http://www.gopherjs.org/playground/#/uo5azM3CaP

image

@dmitshur
Copy link
Member

Investing this a little further. To reproduce this with a simpler setup (a small Go package, and gopherjs serve), this will suffice:

package main

import "strconv"

func main() {
	u, err := strconv.ParseUint("42", 10, 64)
	if err != nil {
		panic(err)
	}
	if u != 42 {
		panic("u != 42")
	}
}

The unreachable code only happens for certain packages/functions. For example, importing only fmt and using fmt.Println doesn't cause it.

The above program generates:

image

The relevant line looks like this:

image

@dmitshur
Copy link
Member

Looking at the source of strconv.ParseUint, it becomes quite clear what's causing the issue and why it only affects some functions:

		...

		n1 := n + uint64(v)
		if n1 < n || n1 > maxVal {
			// n+v overflows
			n = maxUint64
			err = ErrRange
			goto Error
		}
		n = n1
	}

	return n, nil

Error:
	return n, &NumError{"ParseUint", s, err}
}

@dmitshur
Copy link
Member

This is also affecting:

  • "encoding/json".Decoder.peek
  • "math.big".nat.probablyPrimeMillerRabin
  • "net".conf.hostLookupOrder
  • "net".answer
  • "net".dnsRoundTripUDP
  • "net".exchange
  • "mime/multipart".Reader.NextPart

And possibly more. Those were just some that I found from some of my large codebase compiled with GopherJS.

@ghost
Copy link

ghost commented Apr 1, 2017

I don't know whether related, closure compiler reports "unreachable code" even for such a simple program as "Hello, world":

package main

func main() {
	println("Hello, world!")
}
main.js:2227: WARNING - unreachable code
		/* */ } return; } if ($f === undefined) { $f = { $blk: $init }; } $f.$s = $s; $f.$r = $r; return $f;
		                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

main.js:2237: WARNING - unreachable code
		/* */ } return; } if ($f === undefined) { $f = { $blk: $init }; } $f.$s = $s; $f.$r = $r; return $f;
		                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

main.js:2333: WARNING - unreachable code
		/* */ } return; } if ($f === undefined) { $f = { $blk: $init }; } $f.$s = $s; $f.$r = $r; return $f;
2224: $pkg.$init = function() {};
2225: /* */ var $f, $c = false, $s = 0, $r; if (this !== undefined && this.$blk !== undefined) { $f = this; $c = true; $s = $f.$s; $r = $f.$r; } s: while (true) { switch ($s) { case 0:
2226: init();
2227: /* */ } return; } if ($f === undefined) { $f = { $blk: $init }; } $f.$s = $s; $f.$r = $r; return $f;

And when the compiler is started with ADVANCED compilation level (as shown below), it also shows tons of warnings about "incorrect number of parameters" and something about "instantiation of non-constructor". Cannot say whether those are false positives though.

java -jar ~/closure.jar --js main.js --js_output_file main.min.js --compilation_level ADVANCED_OPTIMIZATIONS

@j7b
Copy link

j7b commented Dec 8, 2017

With just

package main
import _ "fmt"
func main() {}

Serve on Darwin using firefox (macos) gives 3 "unreachable code after return statement" first is in internal/poll FD.ptr.prototype.WriteTo:

	/* while (true) { */ case 1:
			_r = syscall.Sendto(fd.Sysfd, p, 0, sa); /* */ $s = 3; case 3: if($c) { $c = false; _r = _r.$blk(); } if (_r && _r.$blk !== undefined) { break s; }
			err$2 = _r;
			if ($interfaceIsEqual(err$2, new syscall.Errno(11)) && fd.pd.pollable()) {
				err$2 = fd.pd.waitWrite(fd.isFile);
				if ($interfaceIsEqual(err$2, $ifaceNil)) {
					/* continue; */ $s = 1; continue;
				}
			}
			if (!($interfaceIsEqual(err$2, $ifaceNil))) {
				$s = -1; return [0, err$2];
			}
			$s = -1; return [p.$length, $ifaceNil];
		/* } */ $s = 1; continue; case 2:

My eyeball-interpreter couldn't figure out where /* while (true) { */ happens but where that's commented out would make sense if it wasn't.

nevkontakte added a commit to nevkontakte/gopherjs that referenced this issue Oct 3, 2021
When GopherJS flattens a loop into a while-switch-case construct, it
needs to generate an instruction to go back to the beginning of the loop
after the last statement of the loop body. However, when the last
statement is a control statement itself (return, continue, break, goto),
this instruction becomes unnecessary and unreachable. Example Go code:

```go
func foo() {
  for {
    // Do something
    break
  }
}
```

This change prevents such an instruction from being generated. This has
a marginal artifact size reduction (1632 bytes on todomvc), but also
eliminates a warning Firefox prints in the console, which may be
confusing to users (gopherjs#1069, gopherjs#575).
nevkontakte added a commit to nevkontakte/gopherjs that referenced this issue Oct 3, 2021
The improved check is able to detect cases when the return statement is
wrapped in another statement, but is effectively the last executed
statement in a list, for example:

```go
func withGoto() (resultType, error) {
  // Do something.
  return result, nil
Error:
  return nil, err // This is inside an *ast.LabeledStmt!
}

func withBlock() resultType {
  // Do something.
  {
    // Do more.
    return result // This is inside a *ast.BlockStmt!
  }
}
```

Better detection prevents generation of unnecessary return statements at
the end of a function (marginally smaller output size), as well as
prevents "unreachable code" warnings in Firefox (gopherjs#575, gopherjs#1069).
nevkontakte added a commit to nevkontakte/gopherjs that referenced this issue Oct 3, 2021
The improved check is able to detect cases when the return statement is
wrapped in another statement, but is effectively the last executed
statement in a list, for example:

```go
func withGoto() (resultType, error) {
  // Do something.
  return result, nil
Error:
  return nil, err // This is inside an *ast.LabeledStmt!
}

func withBlock() resultType {
  // Do something.
  {
    // Do more.
    return result // This is inside a *ast.BlockStmt!
  }
}
```

Better detection prevents generation of unnecessary return statements at
the end of a function (marginally smaller output size), as well as
prevents "unreachable code" warnings in Firefox (gopherjs#575, gopherjs#1069).
@nevkontakte
Copy link
Member

#1071 should eliminate "unreachable code" warnings in Firefox for both cases that this issue mentions.

The Closure compiler warnings mentioned in #575 (comment) are of a different kind, based on a much more advanced analysis it does. AFAIK, GopherJS is not very friendly to Closure compiler in general. I have plans to do some work on reducing output size, so I'm going to punt on this problem until then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants