Repository: google/closure-compiler
Pull request #1281 (2015-12-03 21:57:23)

Remove nosideeffects tag from JSON.parse and JSON.stringify
Or does it make any sence to mix throw and nosideeffects tags?

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.svg" height="40" alt="Review on Reviewable"/>](https://reviewable.io/reviews/google/closure-compiler/1281)
<!-- Reviewable:end -->



Patch:
diff --git a/externs/es3.js b/externs/es3.js
index 462b50591..fa5e5a676 100644
--- a/externs/es3.js
+++ b/externs/es3.js
@@ -71,17 +71,6 @@ Arguments.prototype.caller;
  */
 Arguments.prototype.length;
 
-/**
- * Not actually a global variable, but we need it in order for the current type
- * checker to typecheck the "arguments" variable in a function correctly.
- * TODO(tbreisacher): When the old type checker is gone, delete this and add
- * an 'arguments' variable of type Array<string> in the d8 externs.
- *
- * @type {!Arguments}
- * @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Functions_and_function_scope/arguments
- */
-var arguments;
-
 /**
  * @type {number}
  * @see http://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Infinity
diff --git a/externs/es5.js b/externs/es5.js
index 652a9502b..6e9517dbc 100644
--- a/externs/es5.js
+++ b/externs/es5.js
@@ -246,7 +246,6 @@ function JSONType() {}
  * @param {(function(string, *) : *)=} opt_reviver
  * @return {*} The JSON object.
  * @throws {Error}
- * @nosideeffects
  */
 JSONType.prototype.parse = function(jsonStr, opt_reviver) {};
 
@@ -257,7 +256,6 @@ JSONType.prototype.parse = function(jsonStr, opt_reviver) {};
  * @param {(number|string)=} opt_space
  * @return {string} JSON string which represents jsonObj.
  * @throws {Error}
- * @nosideeffects
  */
 JSONType.prototype.stringify = function(jsonObj, opt_replacer, opt_space) {};
 
diff --git a/externs/es6.js b/externs/es6.js
index fb57ee3e7..a2e1afd3b 100644
--- a/externs/es6.js
+++ b/externs/es6.js
@@ -377,43 +377,6 @@ ArrayBufferView.prototype.byteLength;
 var BufferSource;
 
 
-/**
- * An artificial interface to describe methods available on all TypedArray
- * objects so that they can be operated on in type safe but generic way.
- * @record
- * @extends {IArrayLike<number>}
- */
-function ITypedArray() {}
-
-/** @type {number} */
-ITypedArray.prototype.length;
-
-/** @const {number} */
-ITypedArray.prototype.BYTES_PER_ELEMENT;
-
-/**
- * @param {ArrayBufferView|Array<number>} array
- * @param {number=} opt_offset
- */
-ITypedArray.prototype.set = function(array, opt_offset) {};
-
-/**
- * @param {number} begin
- * @param {number=} opt_end
- * @return {ITypedArray}
- * @nosideeffects
- */
-ITypedArray.prototype.subarray = function(begin, opt_end) {};
-
-/**
- * @param {number} value
- * @param {number=} opt_begin
- * @param {number=} opt_end
- * @return {ITypedArray}
- */
-ITypedArray.prototype.fill = function(value, opt_begin, opt_end) {};
-
-
 /**
  * @param {number|ArrayBufferView|Array<number>|ArrayBuffer} length or array
  *     or buffer
@@ -421,7 +384,7 @@ ITypedArray.prototype.fill = function(value, opt_begin, opt_end) {};
  * @param {number=} opt_length
  * @constructor
  * @extends {ArrayBufferView}
- * @implements {ITypedArray}
+ * @implements {IArrayLike<number>}
  * @noalias
  * @throws {Error}
  * @modifies {arguments} If the user passes a backing array, then indexed
@@ -438,10 +401,10 @@ ITypedArray.prototype.fill = function(value, opt_begin, opt_end) {};
  */
 function Int8Array(length, opt_byteOffset, opt_length) {}
 
-/** @const {number} */
+/** @type {number} */
 Int8Array.BYTES_PER_ELEMENT;
 
-/** @const {number} */
+/** @type {number} */
 Int8Array.prototype.BYTES_PER_ELEMENT;
 
 /** @type {number} */
@@ -450,7 +413,6 @@ Int8Array.prototype.length;
 /**
  * @param {ArrayBufferView|Array<number>} array
  * @param {number=} opt_offset
- * @override
  */
 Int8Array.prototype.set = function(array, opt_offset) {};
 
@@ -458,7 +420,6 @@ Int8Array.prototype.set = function(array, opt_offset) {};
  * @param {number} begin
  * @param {number=} opt_end
  * @return {!Int8Array}
- * @override
  * @nosideeffects
  */
 Int8Array.prototype.subarray = function(begin, opt_end) {};
@@ -467,8 +428,7 @@ Int8Array.prototype.subarray = function(begin, opt_end) {};
  * @param {number} value
  * @param {number=} opt_begin
  * @param {number=} opt_end
- * @return {!Int8Array}
- * @override
+ * @nosideeffects
  * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/fill
  */
 Int8Array.prototype.fill = function(value, opt_begin, opt_end) {};
@@ -481,17 +441,17 @@ Int8Array.prototype.fill = function(value, opt_begin, opt_end) {};
  * @param {number=} opt_length
  * @constructor
  * @extends {ArrayBufferView}
- * @implements {ITypedArray}
+ * @implements {IArrayLike<number>}
  * @noalias
  * @throws {Error}
  * @modifies {arguments}
  */
 function Uint8Array(length, opt_byteOffset, opt_length) {}
 
-/** @const {number} */
+/** @type {number} */
 Uint8Array.BYTES_PER_ELEMENT;
 
-/** @const {number} */
+/** @type {number} */
 Uint8Array.prototype.BYTES_PER_ELEMENT;
 
 /** @type {number} */
@@ -500,7 +460,6 @@ Uint8Array.prototype.length;
 /**
  * @param {ArrayBufferView|Array<number>} array
  * @param {number=} opt_offset
- * @override
  */
 Uint8Array.prototype.set = function(array, opt_offset) {};
 
@@ -509,7 +468,6 @@ Uint8Array.prototype.set = function(array, opt_offset) {};
  * @param {number=} opt_end
  * @return {!Uint8Array}
  * @nosideeffects
- * @override
  */
 Uint8Array.prototype.subarray = function(begin, opt_end) {};
 
@@ -517,9 +475,8 @@ Uint8Array.prototype.subarray = function(begin, opt_end) {};
  * @param {number} value
  * @param {number=} opt_begin
  * @param {number=} opt_end
- * @return {!Uint8Array}
+ * @nosideeffects
  * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/fill
- * @override
  */
 Uint8Array.prototype.fill = function(value, opt_begin, opt_end) {};
 
@@ -531,17 +488,17 @@ Uint8Array.prototype.fill = function(value, opt_begin, opt_end) {};
  * @param {number=} opt_length
  * @constructor
  * @extends {ArrayBufferView}
- * @implements {ITypedArray}
+ * @implements {IArrayLike<number>}
  * @noalias
  * @throws {Error}
  * @modifies {arguments}
  */
 function Uint8ClampedArray(length, opt_byteOffset, opt_length) {}
 
-/** @const {number} */
+/** @type {number} */
 Uint8ClampedArray.BYTES_PER_ELEMENT;
 
-/** @const {number} */
+/** @type {number} */
 Uint8ClampedArray.prototype.BYTES_PER_ELEMENT;
 
 /** @type {number} */
@@ -550,7 +507,6 @@ Uint8ClampedArray.prototype.length;
 /**
  * @param {ArrayBufferView|Array<number>} array
  * @param {number=} opt_offset
- * @override
  */
 Uint8ClampedArray.prototype.set = function(array, opt_offset) {};
 
@@ -558,7 +514,6 @@ Uint8ClampedArray.prototype.set = function(array, opt_offset) {};
  * @param {number} begin
  * @param {number=} opt_end
  * @return {!Uint8ClampedArray}
- * @override
  * @nosideeffects
  */
 Uint8ClampedArray.prototype.subarray = function(begin, opt_end) {};
@@ -568,8 +523,7 @@ Uint8ClampedArray.prototype.subarray = function(begin, opt_end) {};
  * @param {number} value
  * @param {number=} opt_begin
  * @param {number=} opt_end
- * @return {!Uint8ClampedArray}
- * @override
+ * @nosideeffects
  * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/fill
  */
 Uint8ClampedArray.prototype.fill = function(value, opt_begin, opt_end) {};
@@ -591,17 +545,17 @@ var CanvasPixelArray;
  * @param {number=} opt_length
  * @constructor
  * @extends {ArrayBufferView}
- * @implements {ITypedArray}
+ * @implements {IArrayLike<number>}
  * @noalias
  * @throws {Error}
  * @modifies {arguments}
  */
 function Int16Array(length, opt_byteOffset, opt_length) {}
 
-/** @const {number} */
+/** @type {number} */
 Int16Array.BYTES_PER_ELEMENT;
 
-/** @const {number} */
+/** @type {number} */
 Int16Array.prototype.BYTES_PER_ELEMENT;
 
 /** @type {number} */
@@ -610,7 +564,6 @@ Int16Array.prototype.length;
 /**
  * @param {ArrayBufferView|Array<number>} array
  * @param {number=} opt_offset
- * @override
  */
 Int16Array.prototype.set = function(array, opt_offset) {};
 
@@ -619,7 +572,6 @@ Int16Array.prototype.set = function(array, opt_offset) {};
  * @param {number=} opt_end
  * @return {!Int16Array}
  * @nosideeffects
- * @override
  */
 Int16Array.prototype.subarray = function(begin, opt_end) {};
 
@@ -627,8 +579,7 @@ Int16Array.prototype.subarray = function(begin, opt_end) {};
  * @param {number} value Int16 value to fill the array.
  * @param {number=} opt_begin
  * @param {number=} opt_end
- * @return {!Int16Array}
- * @override
+ * @nosideeffects
  * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/fill
  */
 Int16Array.prototype.fill = function(value, opt_begin, opt_end) {};
@@ -641,17 +592,17 @@ Int16Array.prototype.fill = function(value, opt_begin, opt_end) {};
  * @param {number=} opt_length
  * @constructor
  * @extends {ArrayBufferView}
- * @implements {ITypedArray}
+ * @implements {IArrayLike<number>}
  * @noalias
  * @throws {Error}
  * @modifies {arguments}
  */
 function Uint16Array(length, opt_byteOffset, opt_length) {}
 
-/** @const {number} */
+/** @type {number} */
 Uint16Array.BYTES_PER_ELEMENT;
 
-/** @const {number} */
+/** @type {number} */
 Uint16Array.prototype.BYTES_PER_ELEMENT;
 
 /** @type {number} */
@@ -660,7 +611,6 @@ Uint16Array.prototype.length;
 /**
  * @param {ArrayBufferView|Array<number>} array
  * @param {number=} opt_offset
- * @override
  */
 Uint16Array.prototype.set = function(array, opt_offset) {};
 
@@ -668,7 +618,6 @@ Uint16Array.prototype.set = function(array, opt_offset) {};
  * @param {number} begin
  * @param {number=} opt_end
  * @return {!Uint16Array}
- * @override
  * @nosideeffects
  */
 Uint16Array.prototype.subarray = function(begin, opt_end) {};
@@ -677,8 +626,7 @@ Uint16Array.prototype.subarray = function(begin, opt_end) {};
  * @param {number} value Uint16 value to fill the array.
  * @param {number=} opt_begin
  * @param {number=} opt_end
- * @return {!Uint16Array}
- * @override
+ * @nosideeffects
  * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/fill
  */
 Uint16Array.prototype.fill = function(value, opt_begin, opt_end) {};
@@ -691,17 +639,17 @@ Uint16Array.prototype.fill = function(value, opt_begin, opt_end) {};
  * @param {number=} opt_length
  * @constructor
  * @extends {ArrayBufferView}
- * @implements {ITypedArray}
+ * @implements {IArrayLike<number>}
  * @noalias
  * @throws {Error}
  * @modifies {arguments}
  */
 function Int32Array(length, opt_byteOffset, opt_length) {}
 
-/** @const {number} */
+/** @type {number} */
 Int32Array.BYTES_PER_ELEMENT;
 
-/** @const {number} */
+/** @type {number} */
 Int32Array.prototype.BYTES_PER_ELEMENT;
 
 /** @type {number} */
@@ -710,7 +658,6 @@ Int32Array.prototype.length;
 /**
  * @param {ArrayBufferView|Array<number>} array
  * @param {number=} opt_offset
- * @override
  */
 Int32Array.prototype.set = function(array, opt_offset) {};
 
@@ -718,7 +665,6 @@ Int32Array.prototype.set = function(array, opt_offset) {};
  * @param {number} begin
  * @param {number=} opt_end
  * @return {!Int32Array}
- * @override
  * @nosideeffects
  */
 Int32Array.prototype.subarray = function(begin, opt_end) {};
@@ -727,8 +673,7 @@ Int32Array.prototype.subarray = function(begin, opt_end) {};
  * @param {number} value
  * @param {number=} opt_begin
  * @param {number=} opt_end
- * @return {!Int32Array}
- * @override
+ * @nosideeffects
  * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/fill
  */
 Int32Array.prototype.fill = function(value, opt_begin, opt_end) {};
@@ -741,17 +686,17 @@ Int32Array.prototype.fill = function(value, opt_begin, opt_end) {};
  * @param {number=} opt_length
  * @constructor
  * @extends {ArrayBufferView}
- * @implements {ITypedArray}
+ * @implements {IArrayLike<number>}
  * @noalias
  * @throws {Error}
  * @modifies {arguments}
  */
 function Uint32Array(length, opt_byteOffset, opt_length) {}
 
-/** @const {number} */
+/** @type {number} */
 Uint32Array.BYTES_PER_ELEMENT;
 
-/** @const {number} */
+/** @type {number} */
 Uint32Array.prototype.BYTES_PER_ELEMENT;
 
 /** @type {number} */
@@ -760,7 +705,6 @@ Uint32Array.prototype.length;
 /**
  * @param {ArrayBufferView|Array<number>} array
  * @param {number=} opt_offset
- * @override
  */
 Uint32Array.prototype.set = function(array, opt_offset) {};
 
@@ -768,7 +712,6 @@ Uint32Array.prototype.set = function(array, opt_offset) {};
  * @param {number} begin
  * @param {number=} opt_end
  * @return {!Uint32Array}
- * @override
  * @nosideeffects
  */
 Uint32Array.prototype.subarray = function(begin, opt_end) {};
@@ -777,8 +720,7 @@ Uint32Array.prototype.subarray = function(begin, opt_end) {};
  * @param {number} value
  * @param {number=} opt_begin
  * @param {number=} opt_end
- * @return {!Uint32Array}
- * @override
+ * @nosideeffects
  * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/fill
  */
 Uint32Array.prototype.fill = function(value, opt_begin, opt_end) {};
@@ -791,17 +733,17 @@ Uint32Array.prototype.fill = function(value, opt_begin, opt_end) {};
  * @param {number=} opt_length
  * @constructor
  * @extends {ArrayBufferView}
- * @implements {ITypedArray}
+ * @implements {IArrayLike<number>}
  * @noalias
  * @throws {Error}
  * @modifies {arguments}
  */
 function Float32Array(length, opt_byteOffset, opt_length) {}
 
-/** @const {number} */
+/** @type {number} */
 Float32Array.BYTES_PER_ELEMENT;
 
-/** @const {number} */
+/** @type {number} */
 Float32Array.prototype.BYTES_PER_ELEMENT;
 
 /** @type {number} */
@@ -810,7 +752,6 @@ Float32Array.prototype.length;
 /**
  * @param {ArrayBufferView|Array<number>} array
  * @param {number=} opt_offset
- * @override
  */
 Float32Array.prototype.set = function(array, opt_offset) {};
 
@@ -818,7 +759,6 @@ Float32Array.prototype.set = function(array, opt_offset) {};
  * @param {number} begin
  * @param {number=} opt_end
  * @return {!Float32Array}
- * @override
  * @nosideeffects
  */
 Float32Array.prototype.subarray = function(begin, opt_end) {};
@@ -827,8 +767,7 @@ Float32Array.prototype.subarray = function(begin, opt_end) {};
  * @param {number} value
  * @param {number=} opt_begin
  * @param {number=} opt_end
- * @return {!Float32Array}
- * @override
+ * @nosideeffects
  * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/fill
  */
 Float32Array.prototype.fill = function(value, opt_begin, opt_end) {};
@@ -841,17 +780,17 @@ Float32Array.prototype.fill = function(value, opt_begin, opt_end) {};
  * @param {number=} opt_length
  * @constructor
  * @extends {ArrayBufferView}
- * @implements {ITypedArray}
+ * @implements {IArrayLike<number>}
  * @noalias
  * @throws {Error}
  * @modifies {arguments}
  */
 function Float64Array(length, opt_byteOffset, opt_length) {}
 
-/** @const {number} */
+/** @type {number} */
 Float64Array.BYTES_PER_ELEMENT;
 
-/** @const {number} */
+/** @type {number} */
 Float64Array.prototype.BYTES_PER_ELEMENT;
 
 /** @type {number} */
@@ -860,7 +799,6 @@ Float64Array.prototype.length;
 /**
  * @param {ArrayBufferView|Array<number>} array
  * @param {number=} opt_offset
- * @override
  */
 Float64Array.prototype.set = function(array, opt_offset) {};
 
@@ -868,7 +806,6 @@ Float64Array.prototype.set = function(array, opt_offset) {};
  * @param {number} begin
  * @param {number=} opt_end
  * @return {!Float64Array}
- * @override
  * @nosideeffects
  */
 Float64Array.prototype.subarray = function(begin, opt_end) {};
@@ -877,8 +814,7 @@ Float64Array.prototype.subarray = function(begin, opt_end) {};
  * @param {number} value
  * @param {number=} opt_begin
  * @param {number=} opt_end
- * @return {!Float64Array}
- * @override
+ * @nosideeffects
  * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/fill
  */
 Float64Array.prototype.fill = function(value, opt_begin, opt_end) {};
diff --git a/src/com/google/javascript/jscomp/CheckMissingReturn.java b/src/com/google/javascript/jscomp/CheckMissingReturn.java
index e05343882..d527abd31 100644
--- a/src/com/google/javascript/jscomp/CheckMissingReturn.java
+++ b/src/com/google/javascript/jscomp/CheckMissingReturn.java
@@ -44,6 +44,7 @@ class CheckMissingReturn implements ScopedCallback {
           "Missing return statement. Function expected to return {0}.");
 
   private final AbstractCompiler compiler;
+  private final CheckLevel level;
   private final CodingConvention convention;
 
   private static final Predicate<Node> IS_RETURN = new Predicate<Node>() {
@@ -83,8 +84,13 @@ class CheckMissingReturn implements ScopedCallback {
     }
   };
 
-  CheckMissingReturn(AbstractCompiler compiler) {
+  /**
+   * @param level level of severity to report when a missing return statement
+   *     is discovered
+   */
+  CheckMissingReturn(AbstractCompiler compiler, CheckLevel level) {
     this.compiler = compiler;
+    this.level = level;
     this.convention = compiler.getCodingConvention();
   }
 
@@ -108,7 +114,8 @@ class CheckMissingReturn implements ScopedCallback {
 
     if (!test.allPathsSatisfyPredicate()) {
       compiler.report(
-          t.makeError(t.getScopeRoot(), MISSING_RETURN_STATEMENT, returnType.toString()));
+          t.makeError(t.getScopeRoot(), level,
+              MISSING_RETURN_STATEMENT, returnType.toString()));
     }
   }
 
diff --git a/src/com/google/javascript/jscomp/CommandLineRunner.java b/src/com/google/javascript/jscomp/CommandLineRunner.java
index e6faff131..1e6d4c923 100644
--- a/src/com/google/javascript/jscomp/CommandLineRunner.java
+++ b/src/com/google/javascript/jscomp/CommandLineRunner.java
@@ -526,17 +526,18 @@ public class CommandLineRunner extends
       hidden = true,
       usage =
           "Sets what language spec that input sources conform. "
-              + "Options: ECMASCRIPT3, ECMASCRIPT5, ECMASCRIPT5_STRICT, "
-              + "ECMASCRIPT6 (default), ECMASCRIPT6_STRICT, ECMASCRIPT6_TYPED (experimental)"
+              + "Options: ECMASCRIPT3 (default), ECMASCRIPT5, ECMASCRIPT5_STRICT, "
+              + "ECMASCRIPT6, ECMASCRIPT6_STRICT, ECMASCRIPT6_TYPED (experimental)"
     )
-    private String languageIn = "ECMASCRIPT6";
+    private String languageIn = "ECMASCRIPT3";
 
     @Option(name = "--language_out",
         hidden = true,
         usage = "Sets what language spec the output should conform to. "
-        + "Options: ECMASCRIPT3 (default), ECMASCRIPT5, ECMASCRIPT5_STRICT, "
+        + " If omitted, defaults to the value of language_in. "
+        + "Options: ECMASCRIPT3, ECMASCRIPT5, ECMASCRIPT5_STRICT, "
         + "ECMASCRIPT6_TYPED (experimental)")
-    private String languageOut = "ECMASCRIPT3";
+    private String languageOut = "";
 
     @Option(name = "--version",
         hidden = true,
diff --git a/src/com/google/javascript/jscomp/CompilerOptions.java b/src/com/google/javascript/jscomp/CompilerOptions.java
index 7cb96b1d1..a1a482705 100644
--- a/src/com/google/javascript/jscomp/CompilerOptions.java
+++ b/src/com/google/javascript/jscomp/CompilerOptions.java
@@ -384,11 +384,11 @@ public class CompilerOptions {
   /** Removes code that will never execute */
   public boolean removeDeadCode;
 
-  /**
-   * @deprecated Does nothing. Use the "missingReturn" diagnostic group
-   */
-  @Deprecated
+  public CheckLevel checkMissingReturn;
+
+  /** Checks for missing return statements */
   public void setCheckMissingReturn(CheckLevel level) {
+    this.checkMissingReturn = level;
   }
 
   public enum ExtractPrototypeMemberDeclarationsMode {
@@ -786,9 +786,6 @@ public class CompilerOptions {
   /** CommonJS module prefix. */
   List<String> moduleRoots = ImmutableList.of(ES6ModuleLoader.DEFAULT_FILENAME_PREFIX);
 
-  /** Rewrite polyfills. */
-  boolean rewritePolyfills = false;
-
   /** Runtime libraries to always inject. */
   List<String> forceLibraryInjection = ImmutableList.of();
 
@@ -995,6 +992,7 @@ public class CompilerOptions {
     checkGlobalNamesLevel = CheckLevel.OFF;
     brokenClosureRequiresLevel = CheckLevel.ERROR;
     checkGlobalThisLevel = CheckLevel.OFF;
+    checkMissingReturn = CheckLevel.OFF;
     checkMissingGetCssNameLevel = CheckLevel.OFF;
     checkMissingGetCssNameBlacklist = null;
     computeFunctionSideEffects = false;
diff --git a/src/com/google/javascript/jscomp/CompilerOptionsPreprocessor.java b/src/com/google/javascript/jscomp/CompilerOptionsPreprocessor.java
index 04b1733fa..0438d5757 100644
--- a/src/com/google/javascript/jscomp/CompilerOptionsPreprocessor.java
+++ b/src/com/google/javascript/jscomp/CompilerOptionsPreprocessor.java
@@ -63,6 +63,7 @@ final class CompilerOptionsPreprocessor {
     }
 
     if (options.getNewTypeInference()) {
+      options.checkMissingReturn = CheckLevel.OFF;
       options.checkGlobalThisLevel = CheckLevel.OFF;
     }
 
@@ -83,7 +84,7 @@ final class CompilerOptionsPreprocessor {
     if (options.removeUnusedPrototypePropertiesInExterns
         && options.exportLocalPropertyDefinitions) {
       throw new InvalidOptionsException(
-          "remove_unused_prototype_props_in_externs "
+          "remove_unused_prototype_properties_in_externs "
           + "and export_local_property_definitions cannot be used together.");
     }
 
diff --git a/src/com/google/javascript/jscomp/DefaultPassConfig.java b/src/com/google/javascript/jscomp/DefaultPassConfig.java
index 55fd88c4d..96cf2398d 100644
--- a/src/com/google/javascript/jscomp/DefaultPassConfig.java
+++ b/src/com/google/javascript/jscomp/DefaultPassConfig.java
@@ -310,10 +310,6 @@ public final class DefaultPassConfig extends PassConfig {
       checks.add(convertEs6ToEs3);
       checks.add(rewriteBlockScopedDeclaration);
       checks.add(rewriteGenerators);
-      if (!options.getLanguageOut().isEs6OrHigher() && options.rewritePolyfills) {
-        // TODO(sdh): output version check unnecessary?!?
-        checks.add(rewritePolyfills);
-      }
       checks.add(markTranspilationDone);
     }
 
@@ -364,7 +360,7 @@ public final class DefaultPassConfig extends PassConfig {
     }
 
     if (!options.disables(DiagnosticGroups.CHECK_USELESS_CODE) ||
-        (!options.getNewTypeInference() && !options.disables(DiagnosticGroups.MISSING_RETURN))) {
+        options.checkMissingReturn.isOn()) {
       checks.add(checkControlFlow);
     }
 
@@ -1196,14 +1192,6 @@ public final class DefaultPassConfig extends PassConfig {
         }
       };
 
-  private final HotSwapPassFactory rewritePolyfills =
-      new HotSwapPassFactory("RewritePolyfills", true) {
-        @Override
-        protected HotSwapCompilerPass create(final AbstractCompiler compiler) {
-          return new RewritePolyfills(compiler);
-        }
-      };
-
   private final HotSwapPassFactory es6SplitVariableDeclarations =
       new HotSwapPassFactory("Es6SplitVariableDeclarations", true) {
         @Override
@@ -1597,9 +1585,9 @@ public final class DefaultPassConfig extends PassConfig {
       if (!options.disables(DiagnosticGroups.CHECK_USELESS_CODE)) {
         callbacks.add(new CheckUnreachableCode(compiler));
       }
-      if (!options.getNewTypeInference() && !options.disables(DiagnosticGroups.MISSING_RETURN)) {
+      if (options.checkMissingReturn.isOn()) {
         callbacks.add(
-            new CheckMissingReturn(compiler));
+            new CheckMissingReturn(compiler, options.checkMissingReturn));
       }
       return combineChecks(compiler, callbacks);
     }
diff --git a/src/com/google/javascript/jscomp/InlineAliases.java b/src/com/google/javascript/jscomp/InlineAliases.java
index 56084361c..381dbc04a 100644
--- a/src/com/google/javascript/jscomp/InlineAliases.java
+++ b/src/com/google/javascript/jscomp/InlineAliases.java
@@ -80,8 +80,7 @@ final class InlineAliases implements CompilerPass {
      * the rhs will have already been substituted by the time we record the new alias.
      */
     private void visitAliasDefinition(Node lhs, JSDocInfo info) {
-      if (info != null && info.hasConstAnnotation() && !info.hasTypeInformation()
-          && lhs.isQualifiedName()) {
+      if (info != null && info.hasConstAnnotation() && lhs.isQualifiedName()) {
         Node rhs = NodeUtil.getRValueOfLValue(lhs);
         if (rhs != null && rhs.isQualifiedName()) {
           GlobalNamespace.Name lhsName = namespace.getOwnSlot(lhs.getQualifiedName());
diff --git a/src/com/google/javascript/jscomp/NewTypeInference.java b/src/com/google/javascript/jscomp/NewTypeInference.java
index 7c6ddf0a2..42f279d8c 100644
--- a/src/com/google/javascript/jscomp/NewTypeInference.java
+++ b/src/com/google/javascript/jscomp/NewTypeInference.java
@@ -1862,7 +1862,7 @@ final class NewTypeInference implements CompilerPass {
 
   private EnvTypePair analyzeFunctionBindFwd(Node call, TypeEnv inEnv) {
     Preconditions.checkArgument(call.isCall());
-    Bind bindComponents = this.convention.describeFunctionBind(call, true, false);
+    Bind bindComponents = convention.describeFunctionBind(call, true, false);
     Node boundFunNode = bindComponents.target;
     EnvTypePair pair = analyzeExprFwd(boundFunNode, inEnv);
     TypeEnv env = pair.env;
@@ -2737,8 +2737,8 @@ final class NewTypeInference implements CompilerPass {
     JSType recvReqType, recvSpecType;
 
     // First, analyze the receiver object.
-    if (NodeUtil.isPropertyTest(compiler, propAccessNode)
-        && !specializedType.isFalseOrFalsy()) {
+    if (specializedType.isTrueOrTruthy()
+        || propAccessNode.getParent().isTypeOf()) {
       recvReqType = reqObjType;
       recvSpecType = reqObjType.withProperty(propQname, specializedType);
     } else if (specializedType.isFalseOrFalsy()) {
@@ -2763,7 +2763,7 @@ final class NewTypeInference implements CompilerPass {
       return new EnvTypePair(pair.env,
           commonTypes.fromFunctionType(ft.transformByApplyProperty(commonTypes)));
     }
-    if (this.convention.isSuperClassReference(pname)) {
+    if (convention.isSuperClassReference(pname)) {
       if (ft != null && ft.isUniqueConstructor()) {
         JSType result = ft.getSuperPrototype();
         pair.type = result != null ? result : JSType.UNDEFINED;
@@ -3361,6 +3361,8 @@ final class NewTypeInference implements CompilerPass {
     Node propAccessNode = receiver.getParent();
     QualifiedName qname = new QualifiedName(pname);
     JSType reqObjType = pickReqObjType(propAccessNode).withLoose();
+    // In the BWD direction we don't have specialized types, so we use
+    // isPropertyTest to avoid spurious addition of properties to loose objects.
     if (!NodeUtil.isPropertyTest(compiler, propAccessNode)) {
       reqObjType = reqObjType.withProperty(qname, requiredType);
     }
@@ -3429,7 +3431,7 @@ final class NewTypeInference implements CompilerPass {
       return false;
     }
     return expr.getFirstChild().isQualifiedName()
-        && this.convention.isPropertyTestFunction(expr);
+        && convention.isPropertyTestFunction(expr);
   }
 
   private boolean isFunctionBind(Node expr, TypeEnv env, boolean isFwd) {
diff --git a/src/com/google/javascript/jscomp/NodeUtil.java b/src/com/google/javascript/jscomp/NodeUtil.java
index b8291cdaf..b429b6aa0 100644
--- a/src/com/google/javascript/jscomp/NodeUtil.java
+++ b/src/com/google/javascript/jscomp/NodeUtil.java
@@ -3192,9 +3192,9 @@ public final class NodeUtil {
 
       case Token.INSTANCEOF:
       case Token.TYPEOF:
-      case Token.AND:
         return true;
 
+      case Token.AND:
       case Token.HOOK:
         return parent.getFirstChild() == propAccess;
 
diff --git a/src/com/google/javascript/jscomp/RewritePolyfills.java b/src/com/google/javascript/jscomp/RewritePolyfills.java
deleted file mode 100644
index 5b7672d1d..000000000
--- a/src/com/google/javascript/jscomp/RewritePolyfills.java
+++ /dev/null
@@ -1,488 +0,0 @@
-/*
- * Copyright 2015 The Closure Compiler Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.javascript.jscomp;
-
-import static com.google.javascript.jscomp.parsing.parser.FeatureSet.ES3;
-import static com.google.javascript.jscomp.parsing.parser.FeatureSet.ES6;
-import static com.google.javascript.jscomp.parsing.parser.FeatureSet.ES6_IMPL;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMultimap;
-import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
-import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
-import com.google.javascript.jscomp.parsing.parser.FeatureSet;
-import com.google.javascript.rhino.InputId;
-import com.google.javascript.rhino.JSDocInfo;
-import com.google.javascript.rhino.Node;
-
-import java.util.HashSet;
-import java.util.Objects;
-import java.util.Set;
-
-import javax.annotation.Nullable;
-
-/**
- * Rewrites all the library polyfills.
- */
-public class RewritePolyfills implements HotSwapCompilerPass {
-
-  static final DiagnosticType INSUFFICIENT_OUTPUT_VERSION_ERROR = DiagnosticType.warning(
-      "JSC_INSUFFICIENT_OUTPUT_VERSION",
-      "Built-in '{0}' not supported in output version {1}: set --language_out to at least {2}");
-
-  // Also polyfill references to e.g. goog.global.Map or window.Map.
-  private static final String GLOBAL = "goog.global.";
-  private static final String WINDOW = "window.";
-
-  /**
-   * Represents a single polyfill: specifically, a native symbol
-   * (either a qualified name or a property name) that can be
-   * rewritten and/or installed to provide the functionality to
-   * a lower version.  This is a simple value type.
-   */
-  private static class Polyfill {
-    /**
-     * The language version at (or above) which the native symbol is
-     * available and sufficient.  If the language out flag is at least
-     * as high as {@code nativeVersion} then no rewriting will happen.
-     */
-    final FeatureSet nativeVersion;
-
-    /**
-     * The required language version for the polyfill to work.  This
-     * should not be higher than {@code nativeVersion}, but may be the same
-     * in cases where there is no polyfill provided.  This is used to
-     * emit a warning if the language out flag is too low.
-     */
-    final FeatureSet polyfillVersion;
-
-    /**
-     * Optional qualified name to drop-in replace for the native symbol.
-     * May be empty if no direct rewriting is to take place.
-     */
-    final String rewrite;
-
-    /**
-     * Optional "installer" to insert (once) at the top of a source file.
-     * If present, this should be a JavaScript statement, or empty if no
-     * installer should be inserted.
-     */
-    final String installer;
-
-    Polyfill(
-        FeatureSet nativeVersion, FeatureSet polyfillVersion, String rewrite, String installer) {
-      this.nativeVersion = nativeVersion;
-      this.polyfillVersion = polyfillVersion;
-      this.rewrite = rewrite;
-      this.installer = installer;
-    }
-  }
-
-  /**
-   * Describes all the available polyfills, including native and
-   * required versions, and how to use them.
-   */
-  static class Polyfills {
-    // Map of method polyfills, keyed by native method name.
-    private final ImmutableMultimap<String, Polyfill> methods;
-    // Map of static polyfills, keyed by fully-qualified native name.
-    private final ImmutableMap<String, Polyfill> statics;
-
-    private Polyfills(Builder builder) {
-      this.methods = builder.methodsBuilder.build();
-      this.statics = builder.staticsBuilder.build();
-    }
-
-    /**
-     * Provides a DSL for building a {@link Polyfills} object by calling
-     * {@link #addStatics}, {@link #addMethods}, and {@link #addClasses}
-     * to register the various polyfills and provide information about
-     * the native and polyfilled versions, and how to use the polyfills.
-     */
-    static class Builder {
-      private final ImmutableMultimap.Builder<String, Polyfill> methodsBuilder =
-          ImmutableMultimap.builder();
-      private final ImmutableMap.Builder<String, Polyfill> staticsBuilder = ImmutableMap.builder();
-
-      /**
-       * Registers one or more prototype method in a single namespace.
-       * The pass is agnostic with regard to the class whose prototype
-       * is being augmented.  The {@code base} parameter specifies the
-       * qualified namespace where all the {@code methods} reside.  Each
-       * method is expected to have a sibling named with the {@code $install}
-       * suffix.  The method calls themselves are not rewritten, but
-       * whenever one is detected, its installer(s) will be added to the
-       * top of the source file whenever the output version is less than
-       * {@code nativeVersion}.  For example, defining {@code
-       *    addMethods(ES6, ES5, "$jscomp.string", "startsWith", "endsWith")}
-       * will cause {@code $jscomp.string.startsWith$install();} to be
-       * added to any source file that calls, e.g. {@code foo.startsWith}.
-       *
-       * <p>If {@code base} is blank, then no polyfills will be installed.
-       * This is useful for documenting unimplemented polyfills.
-       */
-      Builder addMethods(
-          FeatureSet nativeVersion, FeatureSet polyfillVersion, String base, String... methods) {
-        if (!base.isEmpty()) {
-          for (String method : methods) {
-            methodsBuilder.put(
-                method,
-                new Polyfill(
-                    nativeVersion, polyfillVersion, "", base + "." + method + "$install();"));
-          }
-        }
-        // TODO(sdh): If base.isEmpty() then it means no polyfill is implemented.  Is there
-        // any way we can warn if the output language is too low?  It's not likely, since
-        // there's no good way to determine if it's actually intended as an ES6 method or
-        // else is defined elsewhere.
-        return this;
-      }
-
-      /**
-       * Registers one or more static rewrite polyfill, which is a
-       * simple rewrite of one qualified name to another.  For each
-       * {@code name} in {@code statics}, {@code nativeBase + '.' + name}
-       * will be replaced with {@code polyfillBase + '.' + name}
-       * whenever the output version is less than {@code nativeVersion}.
-       * For eaxmple, defining {@code
-       *    addStatics(ES6, ES5, "$jscomp.math", "Math", "clz32", "imul")}
-       * will cause {@code Math.clz32} to be rewritten as
-       * {@code $jscomp.math.clz32}.
-       *
-       * <p>If {@code polyfillBase} is blank, then no polyfills will be
-       * installed.  This is useful for documenting unimplemented polyfills,
-       * and will trigger a warning if the language output mode is less than
-       * the native version.
-       */
-      Builder addStatics(
-          FeatureSet nativeVersion,
-          FeatureSet polyfillVersion,
-          String polyfillBase,
-          String nativeBase,
-          String... statics) {
-        for (String item : statics) {
-          String nativeName = nativeBase + "." + item;
-          String polyfillName = !polyfillBase.isEmpty() ? polyfillBase + "." + item : "";
-          Polyfill polyfill = new Polyfill(nativeVersion, polyfillVersion, polyfillName, "");
-          staticsBuilder.put(nativeName, polyfill);
-          staticsBuilder.put(GLOBAL + nativeName, polyfill);
-          staticsBuilder.put(WINDOW + nativeName, polyfill);
-        }
-        return this;
-      }
-
-      /**
-       * Registers one or more class polyfill.  Class polyfills
-       * are both rewritten in place and also installed (so that
-       * faster native versions may be preferred if available).
-       * The {@code base} parameter is a qualified name prefix
-       * added to the class name to get the polyfill's name.
-       * A sibling method with the {@code $install} suffix should
-       * also be present.
-       * For example, defining {@code
-       *    addClasses(ES6, ES5, "$jscomp", "Map", "Set")}
-       * will cause {@code new Map()} to be rewritten as
-       * {@code new $jscomp.Map()} and will insert {@code
-       * $jscomp.Map$install();} at the top of the source
-       * file whenever the output version is less than
-       * {@code nativeVersion}.
-       *
-       * <p>If {@code base} is blank, then no polyfills will be
-       * installed.  This is useful for documenting unimplemented
-       * polyfills, and will trigger a warning if the language
-       * output mode is less than the native version.
-       */
-      Builder addClasses(
-          FeatureSet nativeVersion, FeatureSet polyfillVersion, String base, String... classes) {
-        for (String className : classes) {
-          String polyfillName = base + "." + className;
-          Polyfill polyfill =
-              !base.isEmpty()
-                  ? new Polyfill(
-                      nativeVersion, polyfillVersion, polyfillName, polyfillName + "$install();")
-                  : new Polyfill(nativeVersion, polyfillVersion, "", "");
-          staticsBuilder.put(className, polyfill);
-          staticsBuilder.put(GLOBAL + className, polyfill);
-          staticsBuilder.put(WINDOW + className, polyfill);
-        }
-        return this;
-      }
-
-      /** Builds the {@link Polyfills}. */
-      Polyfills build() {
-        return new Polyfills(this);
-      }
-    }
-  }
-
-  // TODO(sdh): ES6 output is still incomplete, so it's reasonable to use
-  // --language_out=ES5 even if targetting ES6 browsers - we need to find a way
-  // to distinguish this case and not give warnings for implemented features.
-
-  private static final Polyfills POLYFILLS = new Polyfills.Builder()
-      // Polyfills not (yet) implemented.
-      .addClasses(ES6, ES6, "", "Proxy", "Reflect")
-      .addClasses(ES6_IMPL, ES6_IMPL, "", "WeakMap", "WeakSet")
-      // TODO(sdh): typed arrays??? these are implemented everywhere except in IE9,
-      //            and introducing warnings would be problematic.
-      .addStatics(ES6_IMPL, ES6_IMPL, "", "Object",
-          "getOwnPropertySymbols", "setPrototypeOf")
-      .addStatics(ES6_IMPL, ES6_IMPL, "", "String", "raw")
-      .addMethods(ES6_IMPL, ES6_IMPL, "", "normalize")
-
-      // Implemented elsewhere (so no rewrite here)
-      .addClasses(ES6_IMPL, ES3, "", "Symbol")
-
-      // NOTE: The following polyfills will be implemented ASAP.  Once each is implemented,
-      // its output language will be changed from ES6 to ES3 and the polyfill namespace
-      // ($jscomp or $jscomp.*) will replace the empty string argument indicating that the
-      // polyfill should actually be used.
-
-      // (Soon-to-be) Implemented classes.
-      .addClasses(ES6_IMPL, ES6_IMPL, "", "Map", "Set")
-      // (Soon-to-be implemented) Math methods.
-      .addStatics(ES6_IMPL, ES6_IMPL, "", "Math",
-          "clz32", "imul", "sign", "log2", "log10", "log1p", "expm1", "cosh", "sinh", "tanh",
-          "acosh", "asinh", "atanh", "hypot", "trunc", "cbrt")
-      // (Soon-to-be implemented) Number methods.
-      .addStatics(ES6_IMPL, ES6_IMPL, "", "Number",
-          "isFinite", "isInteger", "isNaN", "isSafeInteger",
-          "EPSILON", "MAX_SAFE_INTEGER", "MIN_SAFE_INTEGER")
-      // (Soon-to-be implemented) Object methods.
-      .addStatics(ES6_IMPL, ES6_IMPL, "", "Object", "assign", "is")
-      // (Soon-to-be implemented) String methods.
-      .addStatics(ES6_IMPL, ES6_IMPL, "", "String", "fromCodePoint")
-      .addMethods(ES6_IMPL, ES6_IMPL, "",
-          "repeat", "codePointAt", "includes", "startsWith", "endsWith")
-      // (Soon-to-be implemented) Array methods.
-      .addStatics(ES6_IMPL, ES6_IMPL, "", "Array", "from", "of")
-      .addMethods(ES6_IMPL, ES6_IMPL, "",
-          "entries", "keys", "values", "copyWithin", "fill", "find", "findIndex")
-      .build();
-
-  private final AbstractCompiler compiler;
-  private final Polyfills polyfills;
-  private GlobalNamespace globals;
-
-  public RewritePolyfills(AbstractCompiler compiler) {
-    this(compiler, POLYFILLS);
-  }
-
-  // Visible for testing
-  RewritePolyfills(AbstractCompiler compiler, Polyfills polyfills) {
-    this.compiler = compiler;
-    this.polyfills = polyfills;
-  }
-
-  @Override
-  public void hotSwapScript(Node scriptRoot, Node originalRoot) {
-    Traverser traverser = new Traverser();
-    NodeTraversal.traverseEs6(compiler, scriptRoot, traverser);
-    if (traverser.changed) {
-      compiler.needsEs6Runtime = true;
-      compiler.reportCodeChange();
-    }
-  }
-
-  @Override
-  public void process(Node externs, Node root) {
-    this.globals = new GlobalNamespace(compiler, externs, root);
-    hotSwapScript(root, null);
-  }
-
-  private static class InjectedInstaller {
-    final JSModule module;
-    final String installer;
-    InjectedInstaller(JSModule module, String installer) {
-      this.module = module;
-      this.installer = installer;
-    }
-    @Override public int hashCode() {
-      return Objects.hash(module, installer);
-    }
-    @Override public boolean equals(@Nullable Object other) {
-      return other instanceof InjectedInstaller
-          && ((InjectedInstaller) other).installer.equals(installer)
-          && Objects.equals(((InjectedInstaller) other).module, module);
-    }
-  }
-
-  private class Traverser extends AbstractPostOrderCallback {
-
-    Set<InjectedInstaller> installers = new HashSet<>();
-    boolean changed = false;
-
-    @Override
-    public void visit(NodeTraversal traversal, Node node, Node parent) {
-
-      // Fix types in JSDoc.
-      JSDocInfo doc = node.getJSDocInfo();
-      if (doc != null) {
-        fixJsdoc(traversal.getScope(), doc);
-      }
-
-      // Find qualified names that match static calls
-      if (node.isQualifiedName()) {
-        String name = node.getQualifiedName();
-        Polyfill polyfill = null;
-
-        if (polyfills.statics.containsKey(name)) {
-          polyfill = polyfills.statics.get(name);
-        }
-
-        if (polyfill != null) {
-          // Check the scope to make sure it's a global name.
-          if (isRootInScope(node, traversal) || NodeUtil.isVarOrSimpleAssignLhs(node, parent)) {
-            return;
-          }
-
-          if (!languageOutIsAtLeast(polyfill.polyfillVersion)) {
-            traversal.report(
-                node,
-                INSUFFICIENT_OUTPUT_VERSION_ERROR,
-                name,
-                compiler.getOptions().getLanguageOut().toString(),
-                polyfill.polyfillVersion.toString());
-          }
-          if (!languageOutIsAtLeast(polyfill.nativeVersion)) {
-
-            if (!polyfill.installer.isEmpty()) {
-              // Note: add the installer *before* replacing the node!
-              addInstaller(node, polyfill.installer);
-            }
-
-            if (!polyfill.rewrite.isEmpty()) {
-              changed = true;
-              Node replacement = NodeUtil.newQName(compiler, polyfill.rewrite);
-              replacement.useSourceInfoIfMissingFromForTree(node);
-              parent.replaceChild(node, replacement);
-            }
-          }
-
-          // TODO(sdh): consider warning if language_in is too low?  it's not really any
-          // harm, and we can't do it consistently for the prototype methods, so maybe
-          // it's not worth doing here, either.
-
-          return; // isGetProp (below) overlaps, so just bail out now
-        }
-      }
-
-      // Add any requires that *might* match method calls (but don't rewrite anything)
-      if (node.isGetProp() && node.getLastChild().isString()) {
-        for (Polyfill polyfill : polyfills.methods.get(node.getLastChild().getString())) {
-          if (!languageOutIsAtLeast(polyfill.nativeVersion) && !polyfill.installer.isEmpty()) {
-            // Check if this is a global function.
-            if (!isStaticFunction(node, traversal)) {
-              addInstaller(node, polyfill.installer);
-            }
-          }
-        }
-      }
-    }
-
-    private boolean isStaticFunction(Node node, NodeTraversal traversal) {
-      if (!node.isQualifiedName()) {
-        return false;
-      }
-      String root = NodeUtil.getRootOfQualifiedName(node).getQualifiedName();
-      if (globals == null) {
-        return false;
-      }
-      GlobalNamespace.Name fullName = globals.getOwnSlot(node.getQualifiedName());
-      GlobalNamespace.Name rootName = globals.getOwnSlot(root);
-      if (fullName == null || rootName == null) {
-        return false;
-      }
-      GlobalNamespace.Ref rootDecl = rootName.getDeclaration();
-      if (rootDecl == null) {
-        return false;
-      }
-      Node globalDeclNode = rootDecl.getNode();
-      if (globalDeclNode == null) {
-        return false; // don't know where the root came from so assume it could be anything
-      }
-      Var rootScope = traversal.getScope().getVar(root);
-      if (rootScope == null) {
-        return true; // root is not in the current scope, so it's a static function
-      }
-      Node scopeDeclNode = rootScope.getNode();
-      return scopeDeclNode == globalDeclNode; // is the global name currently in scope?
-    }
-
-    // Fix all polyfill type references in any JSDoc.
-    private void fixJsdoc(Scope scope, JSDocInfo doc) {
-      for (Node node : doc.getTypeNodes()) {
-        fixJsdocType(scope, node);
-      }
-    }
-
-    private void fixJsdocType(Scope scope, Node node) {
-      if (node.isString()) {
-        Polyfill polyfill = polyfills.statics.get(node.getString());
-        // Note: all classes are unqualified names, so we don't need to deal with dots
-        if (polyfill != null
-            && scope.getVar(node.getString()) == null
-            && !languageOutIsAtLeast(polyfill.nativeVersion)) {
-          node.setString(polyfill.rewrite);
-        }
-      }
-      for (Node child = node.getFirstChild(); child != null; child = child.getNext()) {
-        fixJsdocType(scope, child);
-      }
-    }
-
-    private void addInstaller(Node sourceNode, String function) {
-      // Find the module
-      InputId inputId = sourceNode.getInputId();
-      CompilerInput input = inputId != null ? compiler.getInput(inputId) : null;
-      JSModule module = input != null ? input.getModule() : null;
-      InjectedInstaller injected = new InjectedInstaller(module, function);
-      if (installers.add(injected)) {
-        changed = true;
-        Node installer = compiler.parseSyntheticCode(function).removeChildren();
-        installer.useSourceInfoIfMissingFromForTree(sourceNode);
-        Node enclosingScript = NodeUtil.getEnclosingScript(sourceNode);
-        enclosingScript.addChildrenToFront(installer);
-      }
-    }
-
-    private boolean languageOutIsAtLeast(LanguageMode mode) {
-      return compiler.getOptions().getLanguageOut().compareTo(mode) >= 0;
-    }
-
-    private boolean languageOutIsAtLeast(FeatureSet features) {
-      switch (features.version()) {
-        case "ts":
-          return languageOutIsAtLeast(LanguageMode.ECMASCRIPT6_TYPED);
-        case "es6":
-        case "es6-impl": // TODO(sdh): support a separate language mode for es6-impl?
-          return languageOutIsAtLeast(LanguageMode.ECMASCRIPT6);
-        case "es5":
-          return languageOutIsAtLeast(LanguageMode.ECMASCRIPT5);
-        case "es3":
-          return languageOutIsAtLeast(LanguageMode.ECMASCRIPT3);
-        default:
-          return false;
-      }
-    }
-  }
-
-  private static boolean isRootInScope(Node node, NodeTraversal traversal) {
-    String rootName = NodeUtil.getRootOfQualifiedName(node).getQualifiedName();
-    return traversal.getScope().getVar(rootName) != null;
-  }
-}
diff --git a/src/com/google/javascript/jscomp/newtypes/JSTypeCreatorFromJSDoc.java b/src/com/google/javascript/jscomp/newtypes/JSTypeCreatorFromJSDoc.java
index ed6f0f677..2e5a8a051 100644
--- a/src/com/google/javascript/jscomp/newtypes/JSTypeCreatorFromJSDoc.java
+++ b/src/com/google/javascript/jscomp/newtypes/JSTypeCreatorFromJSDoc.java
@@ -106,6 +106,11 @@ public final class JSTypeCreatorFromJSDoc {
         "JSC_NTI_BAD_ARRAY_TYPE_SYNTAX",
         "The [] type syntax is not supported. Please use Array.<T> instead");
 
+  public static final DiagnosticType UNION_WITH_UNKNOWN =
+    DiagnosticType.warning(
+        "JSC_NTI_UNION_WITH_UNKNOWN",
+        "A union type that includes ? is equivalent to '?'");
+
   public static final DiagnosticType CANNOT_MAKE_TYPEVAR_NON_NULL =
     DiagnosticType.warning(
         "JSC_NTI_CANNOT_MAKE_TYPEVAR_NON_NULL",
@@ -189,6 +194,7 @@ public final class JSTypeCreatorFromJSDoc {
       TEMPLATED_GETTER_SETTER,
       TWO_JSDOCS,
       UNION_IS_UNINHABITABLE,
+      UNION_WITH_UNKNOWN,
       WRONG_PARAMETER_ORDER);
 
   private final CodingConvention convention;
@@ -286,9 +292,6 @@ public final class JSTypeCreatorFromJSDoc {
       case Token.EMPTY: // for function types that don't declare a return type
         return JSType.UNKNOWN;
       case Token.VOID:
-        // TODO(dimvar): void can be represented in 2 ways: Token.VOID and a
-        // Token.STRING whose getString() is "void".
-        // Change jsdoc parsing to only have one representation.
         return JSType.UNDEFINED;
       case Token.LB:
         warnings.add(JSError.make(n, BAD_ARRAY_TYPE_SYNTAX));
@@ -305,8 +308,15 @@ public final class JSTypeCreatorFromJSDoc {
           // TODO(dimvar): When the union has many things, we join and throw
           // away types, except the result of the last join. Very inefficient.
           // Consider optimizing.
-          JSType nextType = getTypeFromCommentHelper(child, registry, typeParameters);
+          JSType nextType =
+              getTypeFromCommentHelper(child, registry, typeParameters);
           if (nextType.isUnknown()) {
+            if (child.getType() == Token.QMARK
+                && child.getFirstChild() == null) {
+              // Only warn for explicit ?, not for other unknowns such as
+              // forward-declared types.
+              warnings.add(JSError.make(n, UNION_WITH_UNKNOWN));
+            }
             return JSType.UNKNOWN;
           }
           JSType nextUnion = JSType.join(union, nextType);
@@ -346,22 +356,6 @@ public final class JSTypeCreatorFromJSDoc {
     }
   }
 
-  // Looks at the type AST without evaluating it
-  private boolean isUnionWithUndefined(Node n) {
-    if (n == null || n.getType() != Token.PIPE) {
-      return false;
-    }
-    for (Node child : n.children()) {
-      if (child.getType() == Token.VOID
-          || child.getType() == Token.STRING
-          && (child.getString().equals("void")
-              || child.getString().equals("undefined"))) {
-        return true;
-      }
-    }
-    return false;
-  }
-
   private JSType getRecordTypeHelper(Node n, DeclaredTypeRegistry registry,
       ImmutableList<String> typeParameters)
       throws UnknownTypeException {
@@ -379,8 +373,8 @@ public final class JSTypeCreatorFromJSDoc {
           ? JSType.UNKNOWN
           : getTypeFromCommentHelper(propNode.getLastChild(), registry, typeParameters);
       Property prop;
-      if (propType.equals(JSType.UNDEFINED)
-          || isUnionWithUndefined(propNode.getLastChild())) {
+      if (!propType.isUnknown() && !propType.isTop()
+          && JSType.UNDEFINED.isSubtypeOf(propType)) {
         prop = Property.makeOptional(null, propType, propType);
       } else {
         prop = Property.make(propType, propType);
diff --git a/src/com/google/javascript/jscomp/parsing/parser/FeatureSet.java b/src/com/google/javascript/jscomp/parsing/parser/FeatureSet.java
deleted file mode 100644
index ef758e588..000000000
--- a/src/com/google/javascript/jscomp/parsing/parser/FeatureSet.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2015 The Closure Compiler Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.javascript.jscomp.parsing.parser;
-
-import java.util.Objects;
-
-/**
- * Represents various aspects of language version and support.
- * This is somewhat redundant with LanguageMode, but is separate
- * for two reasons: (1) it's used for parsing, which cannot
- * depend on LanguageMode, and (2) it's concerned with slightly
- * different nuances: implemented features and modules rather
- * than strictness.
- *
- * <p>In the long term, it would be good to disentangle all these
- * concerns and pull out a single LanguageSyntax enum with a
- * separate strict mode flag, and then these could possibly be
- * unified.
- */
-public final class FeatureSet {
-
-  /** The number of the language version: 3, 5, or 6. */
-  private final int number;
-  /** Whether this includes features not supported in current stable browsers. */
-  private final boolean unsupported;
-  /** Whether ES6 modules are included. */
-  private final boolean es6Modules;
-  /** Whether TypeScript syntax is included (for .d.ts support). */
-  private final boolean typeScript;
-
-  /** The bare minimum set of features in ES3. */
-  public static final FeatureSet ES3 = new FeatureSet(3, false, false, false);
-  /** Features from ES5 only. */
-  public static final FeatureSet ES5 = new FeatureSet(5, false, false, false);
-  /** The subset of ES6 features that are implemented in stable Chrome, Firefox, and Edge. */
-  public static final FeatureSet ES6_IMPL = new FeatureSet(6, false, false, false);
-  /** The full set of ES6 features, not including modules. */
-  public static final FeatureSet ES6 = new FeatureSet(6, true, false, false);
-  /** All ES6 features, including modules. */
-  public static final FeatureSet ES6_MODULES = new FeatureSet(6, true, true, false);
-  /** TypeScript syntax. */
-  public static final FeatureSet TYPESCRIPT = new FeatureSet(6, true, false, true);
-
-  private FeatureSet(int number, boolean unsupported, boolean es6Modules, boolean typeScript) {
-    this.number = number;
-    this.unsupported = unsupported;
-    this.es6Modules = es6Modules;
-    this.typeScript = typeScript;
-  }
-
-  /** Returns a string representation suitable for encoding in depgraph and deps.js files. */
-  public String version() {
-    if (typeScript) {
-      return "ts";
-    } else if (unsupported || es6Modules) {
-      return "es6";
-    } else if (number > 5) {
-      return "es6-impl";
-    } else if (number > 3) {
-      return "es5";
-    }
-    return "es3";
-  }
-
-  /** Returns whether this feature set includes ES6 modules. */
-  public boolean hasEs6Modules() {
-    return es6Modules;
-  }
-
-  /** Returns whether this feature set includes typescript features. */
-  public boolean isTypeScript() {
-    return typeScript;
-  }
-
-  /** Returns a feature set combining all the features from {@code this} and {@code other}. */
-  public FeatureSet require(FeatureSet other) {
-    if (other.number > number
-        || (other.unsupported && !unsupported)
-        || (other.es6Modules && !es6Modules)
-        || (other.typeScript && !typeScript)) {
-      return new FeatureSet(
-          Math.max(number, other.number),
-          unsupported || other.unsupported,
-          es6Modules || other.es6Modules,
-          typeScript || other.typeScript);
-    }
-    return this;
-  }
-
-  @Override
-  public boolean equals(Object other) {
-    return other instanceof FeatureSet
-        && ((FeatureSet) other).number == number
-        && ((FeatureSet) other).unsupported == unsupported
-        && ((FeatureSet) other).es6Modules == es6Modules
-        && ((FeatureSet) other).typeScript == typeScript;
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(number, unsupported, es6Modules, typeScript);
-  }
-}
diff --git a/src/com/google/javascript/rhino/jstype/JSType.java b/src/com/google/javascript/rhino/jstype/JSType.java
index 4a9814aee..76240026c 100644
--- a/src/com/google/javascript/rhino/jstype/JSType.java
+++ b/src/com/google/javascript/rhino/jstype/JSType.java
@@ -43,14 +43,15 @@ import static com.google.javascript.rhino.jstype.TernaryValue.UNKNOWN;
 
 import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
+import com.google.common.collect.HashBasedTable;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Table;
 import com.google.javascript.rhino.ErrorReporter;
 import com.google.javascript.rhino.JSDocInfo;
 import com.google.javascript.rhino.TypeI;
 
 import java.io.Serializable;
 import java.util.Comparator;
-import java.util.IdentityHashMap;
 
 /**
  * Represents JavaScript value types.<p>
@@ -1587,36 +1588,30 @@ public abstract class JSType implements TypeI, Serializable {
   /**
    * base cache data structure
    */
-  private abstract static class MatchCache {
-    private IdentityHashMap<JSType, IdentityHashMap<JSType, MatchStatus>> matchCache;
-    private boolean isStructuralTyping;
+  protected abstract static class MatchCache {
+    protected Table<JSType, JSType, MatchStatus> matchCache;
+    protected boolean isStructuralTyping;
 
-    MatchCache(boolean isStructuralTyping) {
+    protected MatchCache(boolean isStructuralTyping) {
       this.isStructuralTyping = isStructuralTyping;
       this.matchCache = null;
     }
 
-    boolean isStructuralTyping() {
+    protected boolean isStructuralTyping() {
       return isStructuralTyping;
     }
 
     void updateCache(JSType subType, JSType superType, MatchStatus isMatch) {
-      IdentityHashMap<JSType, MatchStatus> map = this.matchCache.get(subType);
-      if (map == null) {
-        map = new IdentityHashMap<>();
-      }
-      map.put(superType, isMatch);
-      this.matchCache.put(subType, map);
+      this.matchCache.put(subType, superType, isMatch);
     }
 
     MatchStatus checkCache(JSType subType, JSType superType) {
       if (this.matchCache == null) {
-        this.matchCache = new IdentityHashMap<>();
+        this.matchCache = HashBasedTable.create();
       }
       // check the cache
-      if (this.matchCache.containsKey(subType)
-          && this.matchCache.get(subType).containsKey(superType)) {
-        return this.matchCache.get(subType).get(superType);
+      if (this.matchCache.contains(subType, superType)) {
+        return this.matchCache.get(subType, superType);
       } else {
         this.updateCache(subType, superType, MatchStatus.PROCESSING);
         return null;


Test patch:
diff --git a/test/com/google/javascript/jscomp/CheckMissingReturnTest.java b/test/com/google/javascript/jscomp/CheckMissingReturnTest.java
index ef82dc447..652f5f7e9 100644
--- a/test/com/google/javascript/jscomp/CheckMissingReturnTest.java
+++ b/test/com/google/javascript/jscomp/CheckMissingReturnTest.java
@@ -30,7 +30,8 @@ public final class CheckMissingReturnTest extends CompilerTestCase {
 
   @Override
   protected CompilerPass getProcessor(final Compiler compiler) {
-    return new CombinedCompilerPass(compiler, new CheckMissingReturn(compiler));
+    return new CombinedCompilerPass(compiler,
+        new CheckMissingReturn(compiler, CheckLevel.ERROR));
   }
 
   public void testMissingReturn() {
@@ -240,7 +241,7 @@ public final class CheckMissingReturnTest extends CompilerTestCase {
 
   private void testMissingInTraditionalFunction(String returnType, String body) {
     String js = createFunction(returnType, body);
-    testWarning(js, CheckMissingReturn.MISSING_RETURN_STATEMENT);
+    testError(js, CheckMissingReturn.MISSING_RETURN_STATEMENT);
   }
 
   private void testNotMissingInTraditionalFunction(String returnType, String body) {
@@ -250,7 +251,7 @@ public final class CheckMissingReturnTest extends CompilerTestCase {
   private void testMissingInShorthandFunction(String returnType, String body) {
     setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
     String js = createShorthandFunctionInObjLit(returnType, body);
-    testWarning(js, CheckMissingReturn.MISSING_RETURN_STATEMENT);
+    testError(js, CheckMissingReturn.MISSING_RETURN_STATEMENT);
   }
 
   private void testNotMissingInShorthandFunction(String returnType, String body) {
diff --git a/test/com/google/javascript/jscomp/CommandLineRunnerTest.java b/test/com/google/javascript/jscomp/CommandLineRunnerTest.java
index d7430eab4..b1c6e5c6a 100644
--- a/test/com/google/javascript/jscomp/CommandLineRunnerTest.java
+++ b/test/com/google/javascript/jscomp/CommandLineRunnerTest.java
@@ -468,12 +468,10 @@ public final class CommandLineRunnerTest extends TestCase {
   // Integration tests
 
   public void testIssue70a() {
-    args.add("--language_in=ECMASCRIPT5");
     test("function foo({}) {}", RhinoErrorReporter.ES6_FEATURE);
   }
 
   public void testIssue70b() {
-    args.add("--language_in=ECMASCRIPT5");
     test("function foo([]) {}", RhinoErrorReporter.ES6_FEATURE);
   }
 
@@ -703,7 +701,6 @@ public final class CommandLineRunnerTest extends TestCase {
 
   public void testSourceSortingOn3() {
     args.add("--manage_closure_dependencies=true");
-    args.add("--language_in=ECMASCRIPT5");
     test(new String[] {
           "goog.addDependency('sym', [], []);\nvar x = 3;",
           "var COMPILED = false;",
@@ -716,7 +713,6 @@ public final class CommandLineRunnerTest extends TestCase {
 
   public void testSourceSortingCircularDeps1() {
     args.add("--manage_closure_dependencies=true");
-    args.add("--language_in=ECMASCRIPT5");
     test(new String[] {
           "goog.provide('gin'); goog.require('tonic'); var gin = {};",
           "goog.provide('tonic'); goog.require('gin'); var tonic = {};",
@@ -727,20 +723,19 @@ public final class CommandLineRunnerTest extends TestCase {
 
   public void testSourceSortingCircularDeps2() {
     args.add("--manage_closure_dependencies=true");
-    args.add("--language_in=ECMASCRIPT5");
     test(new String[] {
           "goog.provide('roses.lime.juice');",
           "goog.provide('gin'); goog.require('tonic'); var gin = {};",
           "goog.provide('tonic'); goog.require('gin'); var tonic = {};",
           "goog.require('gin'); goog.require('tonic');",
-          "goog.provide('gimlet'); goog.require('gin'); goog.require('roses.lime.juice');"
+          "goog.provide('gimlet');" +
+          "     goog.require('gin'); goog.require('roses.lime.juice');"
          },
          JSModule.CIRCULAR_DEPENDENCY_ERROR);
   }
 
   public void testSourcePruningOn1() {
     args.add("--manage_closure_dependencies=true");
-    args.add("--language_in=ECMASCRIPT5");
     test(new String[] {
           "goog.require('beer');",
           "goog.provide('beer');",
@@ -1283,8 +1278,7 @@ public final class CommandLineRunnerTest extends TestCase {
     assertThat(compiler.getErrors()).hasLength(2);
   }
 
-  public void testES3() {
-    args.add("--language_in=ECMASCRIPT3");
+  public void testES3ByDefault() {
     useStringComparison = true;
     test(
         "var x = f.function",
@@ -1292,10 +1286,6 @@ public final class CommandLineRunnerTest extends TestCase {
         RhinoErrorReporter.INVALID_ES3_PROP_NAME);
   }
 
-  public void testES6TranspiledByDefault() {
-    test("var x = class X {};", "var x = function() {};");
-  }
-
   public void testES5ChecksByDefault() {
     testSame("var x = 3; delete x;");
   }
@@ -1313,7 +1303,6 @@ public final class CommandLineRunnerTest extends TestCase {
 
   public void testES5Strict() {
     args.add("--language_in=ECMASCRIPT5_STRICT");
-    args.add("--language_out=ECMASCRIPT5_STRICT");
     test("var x = f.function", "'use strict';var x = f.function");
     test("var let", RhinoErrorReporter.PARSE_ERROR);
     test("function f(x) { delete x; }", StrictModeCheck.DELETE_VARIABLE);
@@ -1321,15 +1310,13 @@ public final class CommandLineRunnerTest extends TestCase {
 
   public void testES5StrictUseStrict() {
     args.add("--language_in=ECMASCRIPT5_STRICT");
-    args.add("--language_out=ECMASCRIPT5_STRICT");
     Compiler compiler = compile(new String[] {"var x = f.function"});
     String outputSource = compiler.toSource();
-    assertThat(outputSource).startsWith("'use strict'");
+    assertThat(outputSource.substring(0, 12)).isEqualTo("'use strict'");
   }
 
   public void testES5StrictUseStrictMultipleInputs() {
     args.add("--language_in=ECMASCRIPT5_STRICT");
-    args.add("--language_out=ECMASCRIPT5_STRICT");
     Compiler compiler = compile(new String[] {"var x = f.function",
         "var y = f.function", "var z = f.function"});
     String outputSource = compiler.toSource();
diff --git a/test/com/google/javascript/jscomp/InlineAliasesTest.java b/test/com/google/javascript/jscomp/InlineAliasesTest.java
index 3128e2040..571b7a110 100644
--- a/test/com/google/javascript/jscomp/InlineAliasesTest.java
+++ b/test/com/google/javascript/jscomp/InlineAliasesTest.java
@@ -354,14 +354,6 @@ public class InlineAliasesTest extends Es6CompilerTestCase {
     testSame("var ns = {}; var /** @define {boolean} */ alias = ns.Foo; var x = new alias;");
   }
 
-  public void testConstWithTypesAreNotInlined() {
-      testSame(
-        LINE_JOINER.join(
-            "var /** @type {number} */ n = 5",
-            "var /** @const {number} */ alias = n;",
-            "var x = use(alias)"));
-  }
-
   public void testPrivateVariablesAreNotInlined() {
     testSame("/** @private */ var x = 0; var /** @const */ alias = x; var y = alias;");
     testSame("var x_ = 0; var /** @const */ alias = x_; var y = alias;");
diff --git a/test/com/google/javascript/jscomp/NewTypeInferenceES5OrLowerTest.java b/test/com/google/javascript/jscomp/NewTypeInferenceES5OrLowerTest.java
index bd6171f2f..44d4abe86 100644
--- a/test/com/google/javascript/jscomp/NewTypeInferenceES5OrLowerTest.java
+++ b/test/com/google/javascript/jscomp/NewTypeInferenceES5OrLowerTest.java
@@ -5744,7 +5744,9 @@ public final class NewTypeInferenceES5OrLowerTest extends NewTypeInferenceTestBa
 
   public void testQuestionableUnionJsDoc() {
     // 'string|?' is the same as '?'
-    typeCheck("/** @type {string|?} */ var x;");
+    typeCheck(
+        "/** @type {string|?} */ var x;",
+        JSTypeCreatorFromJSDoc.UNION_WITH_UNKNOWN);
 
     typeCheck(Joiner.on('\n').join(
         "goog.forwardDeclare('a');",
@@ -11013,7 +11015,6 @@ public final class NewTypeInferenceES5OrLowerTest extends NewTypeInferenceTestBa
         "  }",
         "}"),
         NewTypeInference.MISTYPED_ASSIGN_RHS);
-
     typeCheck(Joiner.on('\n').join(
         CLOSURE_BASE,
         "function f(/** (number|string) */ x) {",
@@ -11021,7 +11022,6 @@ public final class NewTypeInferenceES5OrLowerTest extends NewTypeInferenceTestBa
         "    x < 'str';",
         "  }",
         "}"));
-
     typeCheck(Joiner.on('\n').join(
         CLOSURE_BASE,
         "function f(/** (number|string) */ x) {",
@@ -11029,7 +11029,6 @@ public final class NewTypeInferenceES5OrLowerTest extends NewTypeInferenceTestBa
         "    x - 5;",
         "  }",
         "}"));
-
     typeCheck(Joiner.on('\n').join(
         CLOSURE_BASE,
         "function f(/** (number|boolean) */ x) {",
@@ -11037,7 +11036,6 @@ public final class NewTypeInferenceES5OrLowerTest extends NewTypeInferenceTestBa
         "    var /** boolean */ b = x;",
         "  }",
         "}"));
-
     typeCheck(Joiner.on('\n').join(
         CLOSURE_BASE,
         "/**",
@@ -11047,7 +11045,6 @@ public final class NewTypeInferenceES5OrLowerTest extends NewTypeInferenceTestBa
         "function f(x) {",
         "  return goog.isString(x) && (1 < 2) ? x : 'a';",
         "}"));
-
     typeCheck(Joiner.on('\n').join(
         CLOSURE_BASE,
         "/**",
@@ -11063,14 +11060,6 @@ public final class NewTypeInferenceES5OrLowerTest extends NewTypeInferenceTestBa
         "  }",
         "  return false;",
         "}"));
-
-    typeCheck(Joiner.on('\n').join(
-        CLOSURE_BASE,
-        "function f(/** !Object */ obj) {",
-        "  if (goog.isDef(obj.myfun)) {",
-        "    return obj.myfun();",
-        "  }",
-        "}"));
   }
 
   public void testGoogIsPredicatesFalse() {
@@ -13806,17 +13795,6 @@ public final class NewTypeInferenceES5OrLowerTest extends NewTypeInferenceTestBa
         "function f(/** { a: (number|undefined) } */ x) {}",
         "f({ a: 'asdf' });"),
         NewTypeInference.INVALID_ARGUMENT_TYPE);
-
-    typeCheck(Joiner.on('\n').join(
-        "/** @param {{foo: (?|undefined)}} x */",
-        "function g(x) {}",
-        "g({bar:123});"));
-
-    typeCheck(Joiner.on('\n').join(
-        "/** @param {{foo: ?}} x */",
-        "function g(x) {}",
-        "g({bar:123});"),
-        NewTypeInference.INVALID_ARGUMENT_TYPE);
   }
 
   public void testJoinWithTruthyOrFalsy() {
diff --git a/test/com/google/javascript/jscomp/RewritePolyfillsTest.java b/test/com/google/javascript/jscomp/RewritePolyfillsTest.java
deleted file mode 100644
index 614b035af..000000000
--- a/test/com/google/javascript/jscomp/RewritePolyfillsTest.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright 2015 The Closure Compiler Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.google.javascript.jscomp;
-
-import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
-import com.google.javascript.jscomp.RewritePolyfills.Polyfills;
-import com.google.javascript.jscomp.parsing.parser.FeatureSet;
-
-/** Unit tests for the RewritePolyfills compiler pass. */
-public final class RewritePolyfillsTest extends CompilerTestCase {
-
-  private static final LanguageMode ES6 = LanguageMode.ECMASCRIPT6_STRICT;
-  private static final LanguageMode ES5 = LanguageMode.ECMASCRIPT5_STRICT;
-  private static final LanguageMode ES3 = LanguageMode.ECMASCRIPT3;
-
-  private static final Polyfills POLYFILLS = new Polyfills.Builder()
-      // Classes
-      .addClasses(FeatureSet.ES6, FeatureSet.ES6, "", "Proxy")
-      .addClasses(FeatureSet.ES6, FeatureSet.ES5, "$jscomp", "Map")
-      .addClasses(FeatureSet.ES6, FeatureSet.ES3, "$jscomp", "Set")
-      // Statics
-      .addStatics(FeatureSet.ES6, FeatureSet.ES6, "", "Array", "from")
-      .addStatics(FeatureSet.ES6, FeatureSet.ES5, "$jscomp.math", "Math", "clz32")
-      .addStatics(FeatureSet.ES6, FeatureSet.ES3, "$jscomp.array", "Array", "of")
-      .addStatics(FeatureSet.ES5, FeatureSet.ES3, "$jscomp.object", "Object", "keys")
-      // Methods
-      .addMethods(FeatureSet.ES6, FeatureSet.ES6, "", "normalize")
-      .addMethods(FeatureSet.ES6, FeatureSet.ES5, "$jscomp.string", "endsWith")
-      .addMethods(FeatureSet.ES6, FeatureSet.ES3, "$jscomp.array", "fill")
-      .addMethods(FeatureSet.ES5, FeatureSet.ES3, "$jscomp.array", "forEach")
-      .build();
-
-
-  @Override
-  protected CompilerPass getProcessor(Compiler compiler) {
-    return new RewritePolyfills(compiler, POLYFILLS);
-  }
-
-  @Override
-  protected int getNumRepetitions() {
-    return 1;
-  }
-
-  public void testEmpty() {
-    setLanguage(ES6, ES5);
-    testSame("");
-  }
-
-  public void testClassesRewritten() {
-    setLanguage(ES6, ES5);
-    test(
-        "var m = new Map();",
-        "$jscomp.Map$install(); var m = new $jscomp.Map();");
-    assertTrue(getLastCompiler().needsEs6Runtime);
-
-    setLanguage(ES6, ES3);
-    test(
-        "var s = new Set();",
-        "$jscomp.Set$install(); var s = new $jscomp.Set();");
-    assertTrue(getLastCompiler().needsEs6Runtime);
-  }
-
-  public void testClassesRewrittenInstallerNotDuplicated() {
-    setLanguage(ES6, ES5);
-    test(
-        "var m = new Map(); var n = new Map();",
-        "$jscomp.Map$install(); var m = new $jscomp.Map(); var n = new $jscomp.Map()");
-  }
-
-  public void testClassesNotRewrittenIfSufficientLanguageOut() {
-    setLanguage(ES6, ES6);
-    testSame("new Proxy();");
-    assertFalse(getLastCompiler().needsEs6Runtime);
-
-    testSame("var m = new Map();");
-    assertFalse(getLastCompiler().needsEs6Runtime);
-
-    testSame("new Set();");
-    assertFalse(getLastCompiler().needsEs6Runtime);
-  }
-
-  public void testClassesNotRewrittenIfDeclaredInScope() {
-    setLanguage(ES6, ES5);
-    testSame("/** @constructor */ var Map = function() {}; new Map();");
-    assertFalse(getLastCompiler().needsEs6Runtime);
-  }
-
-  public void testClassesWarnIfInsufficientLanguageOut() {
-    setLanguage(ES6, ES5);
-    testSame("new Proxy();", RewritePolyfills.INSUFFICIENT_OUTPUT_VERSION_ERROR);
-    assertFalse(getLastCompiler().needsEs6Runtime);
-
-    setLanguage(ES6, ES3);
-    test(
-        "new Map();",
-        "$jscomp.Map$install(); new $jscomp.Map();",
-        null,
-        RewritePolyfills.INSUFFICIENT_OUTPUT_VERSION_ERROR);
-    assertTrue(getLastCompiler().needsEs6Runtime);
-  }
-
-  public void testJsdocTypesRewritten() {
-    setLanguage(ES6, ES5);
-    test(
-        "/** @type {!Map<string, {x: !Set<string>, y: number}>} */ var x;",
-        "/** @type {!$jscomp.Map<string, {x: !$jscomp.Set<string>, y: number}>} */ var x;");
-
-    setLanguage(ES6, ES3);
-    test(
-        "/** @param {function(!Set<string>)} s */ function f(s) {}",
-        "/** @param {function(!$jscomp.Set<string>)} s */ function f(s) {}");
-  }
-
-  public void testJsdocTypesNotRewrittenIfSufficientLanguageOut() {
-    setLanguage(ES6, ES6);
-    testSame("/** @type {!Map<string, {x: !Set<string>, y: number}>} */ var x;");
-  }
-
-  public void testStaticMethodsRewritten() {
-    setLanguage(ES6, ES5);
-    test(
-        "Math.clz32(x);",
-        "$jscomp.math.clz32(x);");
-    assertTrue(getLastCompiler().needsEs6Runtime);
-
-    setLanguage(ES6, ES3);
-    test(
-        "Array.of(x);",
-        "$jscomp.array.of(x);");
-    assertTrue(getLastCompiler().needsEs6Runtime);
-
-    setLanguage(ES6, ES3);
-    test(
-        "Object.keys(x);",
-        "$jscomp.object.keys(x);");
-    assertTrue(getLastCompiler().needsEs6Runtime); // No point separating out separate ES5 runtime
-  }
-
-  public void testStaticMethodsNotRewrittenIfSufficientLanguageOut() {
-    setLanguage(ES6, ES6);
-    testSame("Array.from(x);");
-    assertFalse(getLastCompiler().needsEs6Runtime);
-
-    testSame("Math.clz32(x);");
-    assertFalse(getLastCompiler().needsEs6Runtime);
-
-    testSame("Array.of(x);");
-    assertFalse(getLastCompiler().needsEs6Runtime);
-
-    setLanguage(ES5, ES5);
-    testSame("Object.keys(x);");
-    assertFalse(getLastCompiler().needsEs6Runtime);
-  }
-
-  public void testStaticMethodsNotRewrittenIfDeclaredInScope() {
-    setLanguage(ES6, ES5);
-    testSame("var Math = {clz32: function() {}}; Math.clz32(x);");
-    assertFalse(getLastCompiler().needsEs6Runtime);
-  }
-
-  public void testStaticMethodsWarnIfInsufficientLanguageOut() {
-    setLanguage(ES6, ES5);
-    testSame("Array.from(x);", RewritePolyfills.INSUFFICIENT_OUTPUT_VERSION_ERROR);
-    assertFalse(getLastCompiler().needsEs6Runtime);
-
-    setLanguage(ES6, ES3);
-    test(
-        "Math.clz32(x);",
-        "$jscomp.math.clz32(x);",
-        null,
-        RewritePolyfills.INSUFFICIENT_OUTPUT_VERSION_ERROR);
-    assertTrue(getLastCompiler().needsEs6Runtime);
-  }
-
-  public void testPrototypeMethodsInstalled() {
-    setLanguage(ES6, ES5);
-    test(
-        "x.endsWith(y);",
-        "$jscomp.string.endsWith$install(); x.endsWith(y);");
-    assertTrue(getLastCompiler().needsEs6Runtime);
-
-    test(
-        "x.fill();",
-        "$jscomp.array.fill$install(); x.fill();");
-    assertTrue(getLastCompiler().needsEs6Runtime);
-
-    setLanguage(ES5, ES3);
-    test(
-        "x.forEach(y);",
-        "$jscomp.array.forEach$install(); x.forEach(y);");
-    assertTrue(getLastCompiler().needsEs6Runtime);
-  }
-
-  public void testPrototypeMethodsNotInstalledIfSufficientLanguageOut() {
-    setLanguage(ES6, ES6);
-    testSame("x.normalize();");
-    assertFalse(getLastCompiler().needsEs6Runtime);
-
-    testSame("x.endsWith();");
-    assertFalse(getLastCompiler().needsEs6Runtime);
-
-    testSame("x.fill(y);");
-    assertFalse(getLastCompiler().needsEs6Runtime);
-
-    setLanguage(ES5, ES5);
-    testSame("x.forEach();");
-    assertFalse(getLastCompiler().needsEs6Runtime);
-  }
-
-  public void testPrototypeMethodsInstalledIfStaticMethodShadowed() {
-    setLanguage(ES6, ES5);
-    test(
-        "var string = {}; string.endsWith = function() {}; "
-        + "string.foo = function(string) { return string.endsWith('x'); };",
-
-        "$jscomp.string.endsWith$install(); "
-        + "var string = {}; string.endsWith = function() {}; "
-        + "string.foo = function(string) { return string.endsWith('x'); };");
-    assertTrue(getLastCompiler().needsEs6Runtime);
-  }
-
-  public void testPrototypeMethodsNotInstalledIfActuallyStatic() {
-    setLanguage(ES6, ES5);
-    testSame("var string = {}; string.endsWith = function() {}; string.endsWith('x');");
-    assertFalse(getLastCompiler().needsEs6Runtime);
-
-    testSame("var string = {endsWith: function() {}}; string.endsWith('x');");
-    assertFalse(getLastCompiler().needsEs6Runtime);
-
-    testSame(
-        "var string = {}; string.endsWith = function() {}; "
-        + "string.foo = function() { return string.endsWith('x'); };");
-    assertFalse(getLastCompiler().needsEs6Runtime);
-  }
-}