@@ -569,6 +569,40 @@ ast::ExpressionPtr Translator::desugarMlhs(core::LocOffsets loc, PrismNode *lhs,
569569 if (PM_NODE_TYPE_P (c, PM_MULTI_TARGET_NODE)) {
570570 auto *mlhs = down_cast<pm_multi_target_node>(c);
571571 stats.emplace_back (desugarMlhs (cloc, mlhs, move (val)));
572+ } else if (PM_NODE_TYPE_P (c, PM_CALL_TARGET_NODE)) {
573+ // Target of an indirect write to the result of a method call
574+ // ... like `self.target1, self.target2 = 1, 2`, `rescue => self.target`, etc.
575+ auto callTargetNode = down_cast<pm_call_target_node>(c);
576+ auto receiverNode = callTargetNode->receiver ;
577+
578+ if (PM_NODE_FLAG_P (callTargetNode, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) {
579+ categoryCounterInc (" Prism fallback" , " PM_CALL_TARGET_NODE with PM_CALL_NODE_FLAGS_SAFE_NAVIGATION" );
580+ throw PrismFallback{};
581+ }
582+
583+ ast::ExpressionPtr receiver;
584+ if (receiverNode == nullptr ) { // Convert `foo()` to `self.foo()`
585+ receiver = MK::Self (zcloc);
586+ } else {
587+ receiver = desugar (receiverNode);
588+ }
589+
590+ // Unsupported nodes are desugared to an empty tree.
591+ // Treat them as if they were `self` to match `Desugar.cc`.
592+ // TODO: Clean up after direct desugaring is complete.
593+ // https://github.com/Shopify/sorbet/issues/671
594+ ast::Send::Flags flags;
595+ if (ast::isa_tree<ast::EmptyTree>(receiver)) {
596+ receiver = MK::Self (zcloc);
597+ flags.isPrivateOk = true ;
598+ } else {
599+ flags.isPrivateOk = PM_NODE_FLAG_P (callTargetNode, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY);
600+ }
601+
602+ auto methodName = translateConstantName (callTargetNode->name );
603+ auto methodNameLoc = translateLoc (callTargetNode->message_loc );
604+ ast::Send::ARGS_store emptyArgs;
605+ stats.emplace_back (MK::Send (cloc, move (receiver), methodName, methodNameLoc, 0 , move (emptyArgs), flags));
572606 } else {
573607 ast::ExpressionPtr lh = desugar (c);
574608 if (auto restParam = ast::cast_tree<ast::RestParam>(lh)) {
@@ -1746,37 +1780,7 @@ ast::ExpressionPtr Translator::desugar(pm_node_t *node) {
17461780 }
17471781 case PM_CALL_TARGET_NODE: { // Target of an indirect write to the result of a method call
17481782 // ... like `self.target1, self.target2 = 1, 2`, `rescue => self.target`, etc.
1749- auto callTargetNode = down_cast<pm_call_target_node>(node);
1750- auto receiverNode = callTargetNode->receiver ;
1751-
1752- if (PM_NODE_FLAG_P (callTargetNode, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) {
1753- categoryCounterInc (" Prism fallback" , " PM_CALL_TARGET_NODE with PM_CALL_NODE_FLAGS_SAFE_NAVIGATION" );
1754- throw PrismFallback{};
1755- }
1756-
1757- ast::ExpressionPtr receiver;
1758- if (receiverNode == nullptr ) { // Convert `foo()` to `self.foo()`
1759- receiver = MK::Self (location.copyWithZeroLength ());
1760- } else {
1761- receiver = desugar (receiverNode);
1762- }
1763-
1764- // Unsupported nodes are desugared to an empty tree.
1765- // Treat them as if they were `self` to match `Desugar.cc`.
1766- // TODO: Clean up after direct desugaring is complete.
1767- // https://github.com/Shopify/sorbet/issues/671
1768- ast::Send::Flags flags;
1769- if (ast::isa_tree<ast::EmptyTree>(receiver)) {
1770- receiver = MK::Self (location.copyWithZeroLength ());
1771- flags.isPrivateOk = true ;
1772- } else {
1773- flags.isPrivateOk = PM_NODE_FLAG_P (callTargetNode, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY);
1774- }
1775-
1776- auto methodName = translateConstantName (callTargetNode->name );
1777- auto methodNameLoc = translateLoc (callTargetNode->message_loc );
1778- ast::Send::ARGS_store emptyArgs;
1779- return MK::Send (location, move (receiver), methodName, methodNameLoc, 0 , move (emptyArgs), flags);
1783+ unreachable (" PM_CALL_TARGET_NODE is handled specially in `desugarMlhs()`." );
17801784 }
17811785 case PM_CASE_MATCH_NODE: { // A pattern-matching `case` statement that only uses `in` (and not `when`)
17821786 auto caseMatchNode = down_cast<pm_case_match_node>(node);
0 commit comments