Skip to content

How should class foo { } behave if used multiple times? #16

@wolfsage

Description

@wolfsage

You can use class somename multiple times, but with varying degrees of success. Should you be able to?

Consider this script:

#!./perl -Ilib

use v5.36;

use Data::Dumper;

use feature 'class', 'defer';
no warnings 'experimental::class';

class Hello {
  field $x;
  method x { $x } 

  class Hello {
    field $y;
    method y { $y } 

    class Hello {
      field $z;
      method z { "X: $x, Y: $y, Z: $z\n" }
 
     ADJUST {
        my $arg = shift;
        warn Data::Dumper::Dumper($arg);

        $x = delete $arg->{x};
        $y = delete $arg->{y};
        $z = delete $arg->{z};
      }
    }
  }
}

print Hello->new(x => 1, y => 2, z => 3)->z;

And its output:

Subroutine Hello::new redefined at ./multiple-class-same-name.pl line 14.
Subroutine Hello::new redefined at ./multiple-class-same-name.pl line 18.
$VAR1 = {
          'z' => 3,
          'y' => 2,
          'x' => 1
        };
X: 3, Y: 3, Z: 3

Also of interest, for each class declaration of an already existing name that we overwrite, we lose 40 bytes:

mhorsfall@tworivers:~/p5/perl$ valgrind --leak-check=full ./multiple-class-same-name.pl 2>&1 | grep 'definitely' -A 10
==4642== 96 (80 direct, 16 indirect) bytes in 2 blocks are definitely lost in loss record 419 of 838
==4642==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4642==    by 0x1E8395: Perl_safesysmalloc (util.c:161)
==4642==    by 0x1A5CD2: Perl_newPADNAMELIST (pad.c:2631)
==4642==    by 0x201364: Perl_class_add_field (class.c:364)
==4642==    by 0x1A7ED7: S_pad_alloc_name (pad.c:570)
==4642==    by 0x1A7F36: Perl_pad_add_name_pvn (pad.c:625)
==4642==    by 0x14F19C: Perl_allocmy (op.c:783)
==4642==    by 0x19F19B: S_pending_ident (toke.c:9771)
==4642==    by 0x19F19B: Perl_yylex (toke.c:9466)
==4642==    by 0x1A2479: Perl_yyparse (perly.c:357)
--
==4642==    definitely lost: 80 bytes in 2 blocks
==4642==    indirectly lost: 16 bytes in 2 blocks
==4642==      possibly lost: 992,532 bytes in 1,674 blocks
==4642==    still reachable: 610,292 bytes in 4,305 blocks
==4642==                       of which reachable via heuristic:
==4642==                         newarray           : 8,704 bytes in 268 blocks
==4642==         suppressed: 0 bytes in 0 blocks
==4642== Reachable blocks (those to which a pointer was found) are not shown.
==4642== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==4642== 
==4642== For counts of detected and suppressed errors, rerun with: -v

The memory we're throwing away is:

aux->xhv_class_fields = newPADNAMELIST(0);

I guess because Perl_class_setup_stash is called again and does:

    HvAUX(stash)->xhv_class_adjust_blocks = NULL;
    HvAUX(stash)->xhv_class_fields        = NULL;
    HvAUX(stash)->xhv_class_next_fieldix  = 0;

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is needed

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions