Improved reported error for PP1003 (#2305)

Summary:
Previous error message:
`Property access conflicts with write in optimized function (unknown function) at 11:11 to 11:16`

New error message:
`Write to property "func" on <unnamed object> at optimized function fn[20:13 22:22] conflicts with access in function nested[11:11]`

Output generated off "Failure 2" in issue #2252
Pull Request resolved: https://github.com/facebook/prepack/pull/2305

Differential Revision: D8979410

Pulled By: cblappert

fbshipit-source-id: a4f507d8a77a44a0f4ca7619faf3a9fe03dabf45
This commit is contained in:
Chris Blappert 2018-07-24 14:17:22 -07:00 committed by Facebook Github Bot
parent 66115d4377
commit 62b11dcb6e
3 changed files with 45 additions and 7 deletions

View File

@ -38,6 +38,7 @@ import { handleReportedSideEffect } from "./utils.js";
import { ShapeInformation } from "../utils/ShapeInformation";
import type { ArgModel } from "../utils/ShapeInformation";
import * as t from "@babel/types";
import { stringOfLocation } from "../utils/babelhelpers";
type AdditionalFunctionEntry = {
value: ECMAScriptSourceFunctionValue | AbstractValue,
@ -299,7 +300,11 @@ export class Functions {
let conflicts: Map<BabelNodeSourceLocation, CompilerDiagnostic> = new Map();
for (let fun1 of additionalFunctions) {
invariant(fun1 instanceof FunctionValue);
let fun1Name = this.functionExpressions.get(fun1) || fun1.intrinsicName || "(unknown function)";
let fun1Location = fun1.expressionLocation;
let fun1Name =
this.functionExpressions.get(fun1) ||
fun1.getDebugName() ||
`(unknown function ${fun1Location ? stringOfLocation(fun1Location) : ""})`;
// Also do argument validation here
let additionalFunctionEffects = this.writeEffects.get(fun1);
invariant(additionalFunctionEffects !== undefined);
@ -318,8 +323,13 @@ export class Functions {
for (let fun2 of additionalFunctions) {
if (fun1 === fun2) continue;
invariant(fun2 instanceof FunctionValue);
let fun2Location = fun2.expressionLocation;
let fun2Name =
this.functionExpressions.get(fun2) ||
fun2.getDebugName() ||
`(unknown function ${fun2Location ? stringOfLocation(fun2Location) : ""})`;
let reportFn = () => {
this.reportWriteConflicts(fun1Name, conflicts, e1.modifiedProperties, this._callOfFunction(fun2));
this.reportWriteConflicts(fun1Name, fun2Name, conflicts, e1.modifiedProperties, this._callOfFunction(fun2));
return null;
};
let fun2Effects = this.writeEffects.get(fun2);
@ -344,14 +354,26 @@ export class Functions {
}
reportWriteConflicts(
fname: string,
f1name: string,
f2name: string,
conflicts: Map<BabelNodeSourceLocation, CompilerDiagnostic>,
pbs: PropertyBindings,
call2: void => Value
): void {
let reportConflict = (location: BabelNodeSourceLocation) => {
let reportConflict = (
location: BabelNodeSourceLocation,
object: string = "",
key?: string,
originalLocation: BabelNodeSourceLocation | void | null
) => {
let firstLocationString = originalLocation ? `${stringOfLocation(originalLocation)}` : "";
let propString = key ? ` "${key}"` : "";
let objectString = object ? ` on object "${object}" ` : "";
if (!objectString && key) objectString = " on <unnamed object> ";
let error = new CompilerDiagnostic(
`Property access conflicts with write in optimized function ${fname}`,
`Write to property${propString}${objectString}at optimized function ${f1name}[${firstLocationString}] conflicts with access in function ${f2name}[${
location.start.line
}:${location.start.column}]`,
location,
"PP1003",
"FatalError"
@ -366,14 +388,22 @@ export class Functions {
this.realm.reportObjectGetOwnProperties = (ob: ObjectValue) => {
let location = this.realm.currentLocation;
invariant(location);
if (writtenObjects.has(ob) && !conflicts.has(location)) reportConflict(location);
if (writtenObjects.has(ob) && !conflicts.has(location))
reportConflict(location, ob.getDebugName(), undefined, ob.expressionLocation);
};
let oldReportPropertyAccess = this.realm.reportPropertyAccess;
this.realm.reportPropertyAccess = (pb: PropertyBinding) => {
if (ObjectValue.refuseSerializationOnPropertyBinding(pb)) return;
let location = this.realm.currentLocation;
if (!location) return; // happens only when accessing an additional function property
if (pbs.has(pb) && !conflicts.has(location)) reportConflict(location);
if (pbs.has(pb) && !conflicts.has(location)) {
let originalLocation =
pb.descriptor && pb.descriptor.value && !Array.isArray(pb.descriptor.value)
? pb.descriptor.value.expressionLocation
: undefined;
let keyString = pb.key instanceof Value ? pb.key.toDisplayString() : pb.key;
reportConflict(location, pb.object ? pb.object.getDebugName() : undefined, keyString, originalLocation);
}
};
try {
ignoreErrorsIn(this.realm, () => this.realm.evaluateForEffectsInGlobalEnv(call2));

View File

@ -53,4 +53,8 @@ export default class FunctionValue extends ObjectValue {
hasDefaultLength(): boolean {
invariant(false, "abstract method; please override");
}
getDebugName(): string {
return super.getDebugName() || this.getName();
}
}

View File

@ -193,4 +193,8 @@ export default class Value {
_serialize(set: Function, stack: Map<Value, any>): any {
invariant(false, "abstract method; please override");
}
getDebugName(): string | void {
return this.intrinsicName || this.__originalName;
}
}