perl5 icon indicating copy to clipboard operation
perl5 copied to clipboard

`local $h{$k}` doesn't remove previously non-existing key from shared hashes

Open ikegami opened this issue 1 year ago • 2 comments

core threads local

Description

local $h{$k} should remove the element if it didn't previously exist. In other words, local $h{$k} should restore the state of existence of $h{$k}.

This isn't explicitly documented as far as I can tell, but perl58delta indicates that version 5.8 introduced a fix to obtain that behaviour for tied hashes. (Adding EXISTS and DELETE handlers was required to fix this!)

However, shared hashes still behave incorrectly. The element is left existing but undef.

Steps to Reproduce

use strict;
use warnings;

use threads;
use threads::shared;

sub test {
   my $name = shift;
   my $h    = shift;

   { local $h->{ x } = "blah"; }

   printf( "%s: %s\n",
      $name,
      ( !exists(  $h->{ x } ) ? "!exists"
      : !defined( $h->{ x } ) ? "exists && !defined"
      :                         "exists && defined"
      )
   );
}

{ my %h;         test( "Normal hash", \%h ); }
{ my %h :shared; test( "Shared hash", \%h ); }

Expected behavior

Consistent behaviour is expected. Instead, we get

Normal hash: !exists
Shared hash: exists && !defined

Perl configuration

$ perl -v | grep 'This is'
This is perl 5, version 38, subversion 0 (v5.38.0) built for x86_64-linux-thread-multi

ikegami avatar May 27 '24 17:05 ikegami

From https://stackoverflow.com/q/78537778/589924

ikegami avatar May 27 '24 17:05 ikegami

Yeah, this doesn't seem to be handled right now. The element magic probably needs a local handler.

Leont avatar May 28 '24 13:05 Leont