Skip to content
Permalink
Browse files

Make sure that Hash[Int].new gets the correct descriptor

According to a bisect, this issue has existed since at least Christmas.
The problem was that Hash.new would do nothing about a descriptor.  Before
the scalar refactor, that meant that the descriptor was nqp::null.  After
that refactor, it has a default descriptor, but still not the right thing.
Apparently, when you say "my Int %h", the correct descriptor is codegenned
or otherwise correctly created.

This commit introduces a multi for Map.new: one without parameters, and
one with.  The one with calls the .new without parameters.  For the TypedHash
roles, there is a no-argument .new candidate that creates the correct
descriptor.  Which fixes R#2348.
  • Loading branch information...
lizmat committed Oct 8, 2018
1 parent 9273577 commit 9acbf000418cd716f532008a5a1704cccf684eae
Showing with 22 additions and 5 deletions.
  1. +17 −0 src/core/Hash.pm6
  2. +5 −5 src/core/Map.pm6
@@ -429,6 +429,15 @@ my class Hash { # declared in BOOTSTRAP
}

my role TypedHash[::TValue] does Associative[TValue] {

# make sure we get the right descriptor
multi method new(::?CLASS:) {
nqp::p6bindattrinvres(
nqp::create(self),Hash,'$!descriptor',
ContainerDescriptor.new(:of(TValue), :default(TValue))
)
}

# These ASSIGN-KEY candidates are only needed because of:
# my Int %h; try %h<a> = "foo"; dd %h
# leaving an uninitialized Int for key <a> in the hash. If
@@ -475,6 +484,14 @@ my class Hash { # declared in BOOTSTRAP
}
}
my role TypedHash[::TValue, ::TKey] does Associative[TValue] {

# make sure we get the right descriptor
multi method new(::?CLASS:) {
nqp::p6bindattrinvres(
nqp::create(self),Hash,'$!descriptor',
ContainerDescriptor.new(:of(TValue), :default(TValue))
)
}
method keyof () { TKey }
method AT-KEY(::?CLASS:D: TKey \key) is raw {
my \storage := nqp::getattr(self, Map, '$!storage');
@@ -42,11 +42,11 @@ my class Map does Iterable does Associative { # declared in BOOTSTRAP
ValueObjAt
)
}
method new(*@args) {
@args
?? nqp::create(self).STORE(@args, :initialize)
!! nqp::create(self)
}

# Calling self.new for the arguments case ensures that the right
# descriptor will be added for typed hashes.
multi method new(Map: ) { nqp::create(self) }
multi method new(Map: *@args) { self.new.STORE(@args, :initialize) }

multi method Map(Map:) { self }

0 comments on commit 9acbf00

Please sign in to comment.
You can’t perform that action at this time.