diff --git a/src/go/scanner/scanner.go b/src/go/scanner/scanner.go index 75f835d3105..8742c299065 100644 --- a/src/go/scanner/scanner.go +++ b/src/go/scanner/scanner.go @@ -943,7 +943,13 @@ scanAgain: default: // next reports unexpected BOMs - don't repeat if ch != bom { - s.errorf(s.file.Offset(pos), "illegal character %#U", ch) + // Report an informative error for U+201[CD] quotation + // marks, which are easily introduced via copy and paste. + if ch == '“' || ch == '”' { + s.errorf(s.file.Offset(pos), "curly quotation mark %q (use neutral %q)", ch, '"') + } else { + s.errorf(s.file.Offset(pos), "illegal character %#U", ch) + } } insertSemi = s.insertSemi // preserve insertSemi info tok = token.ILLEGAL diff --git a/src/go/scanner/scanner_test.go b/src/go/scanner/scanner_test.go index 9046148ac2c..916a40a8744 100644 --- a/src/go/scanner/scanner_test.go +++ b/src/go/scanner/scanner_test.go @@ -813,6 +813,7 @@ var errors = []struct { {`"` + "abc\ufeffdef" + `"`, token.STRING, 4, `"` + "abc\ufeffdef" + `"`, "illegal byte order mark"}, // only first BOM is ignored {"abc\x00def", token.IDENT, 3, "abc", "illegal character NUL"}, {"abc\x00", token.IDENT, 3, "abc", "illegal character NUL"}, + {"“abc”", token.ILLEGAL, 0, "abc", `curly quotation mark '“' (use neutral '"')`}, } func TestScanErrors(t *testing.T) {