function eachSelfAssignment(left,right,props,report){if(!left||!right){// do nothing
}else if(left.type==="Identifier"&&right.type==="Identifier"&&left.name===right.name){report(right);}else if(left.type==="ArrayPattern"&&right.type==="ArrayExpression"){var end=Math.min(left.elements.length,right.elements.length);for(var i=0;i<end;++i){var rightElement=right.elements[i];eachSelfAssignment(left.elements[i],rightElement,props,report);// After a spread element, those indices are unknown.
if(rightElement&&rightElement.type==="SpreadElement"){break;}}}else if(left.type==="RestElement"&&right.type==="SpreadElement"){eachSelfAssignment(left.argument,right.argument,props,report);}else if(left.type==="ObjectPattern"&&right.type==="ObjectExpression"&&right.properties.length>=1){// Gets the index of the last spread property.
// It's possible to overwrite properties followed by it.
var startJ=0;for(var _i=right.properties.length-1;_i>=0;--_i){if(right.properties[_i].type==="ExperimentalSpreadProperty"){startJ=_i+1;break;}}for(var _i2=0;_i2<left.properties.length;++_i2){for(var j=startJ;j<right.properties.length;++j){eachSelfAssignment(left.properties[_i2],right.properties[j],props,report);}}}else if(left.type==="Property"&&right.type==="Property"&&!left.computed&&!right.computed&&right.kind==="init"&&!right.method&&left.key.name===right.key.name){eachSelfAssignment(left.value,right.value,props,report);}else if(props&&left.type==="MemberExpression"&&right.type==="MemberExpression"&&isSameMember(left,right)){report(right);}}//------------------------------------------------------------------------------
Traverses 2 Pattern nodes in parallel, then reports self-assignments.

@param {ASTNode|null} left - A left node to traverse. This is a Pattern or
     a Property.
@param {ASTNode|null} right - A right node to traverse. This is a Pattern or
     a Property.
@param {boolean} props - The flag to check member expressions as well.
@param {Function} report - A callback function to report.
@returns {void}