blob: 22825b7cce412a443fbb5fdf17635a3dd7e5dc2d [file] [log] [blame] [edit]
/*
* Copyright 2025 WebAssembly Community Group participants
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ir/gc-type-utils.h"
#include "type-test.h"
#include "wasm-type.h"
#include "gtest/gtest.h"
namespace wasm {
using namespace GCTypeUtils;
class CastCheckTest : public TypeTest {
protected:
HeapType super, sub, subFinal;
void SetUp() override {
TypeBuilder builder(3);
builder[0] = Struct();
builder[0].setOpen();
builder[1] = Struct();
builder[1].subTypeOf(builder[0]).setOpen();
builder[2] = Struct();
builder[2].subTypeOf(builder[0]);
auto built = builder.build();
ASSERT_TRUE(built);
super = (*built)[0];
sub = (*built)[1];
subFinal = (*built)[2];
}
};
TEST_F(CastCheckTest, CastToSelfNonFinal) {
#define EXPECT_CAST( \
srcNullability, srcExactness, castNullability, castExactness, result) \
EXPECT_EQ(evaluateCastCheck(Type(super, srcNullability, srcExactness), \
Type(super, castNullability, castExactness)), \
result);
EXPECT_CAST(Nullable, Inexact, Nullable, Inexact, Success);
EXPECT_CAST(Nullable, Inexact, Nullable, Exact, Unknown);
EXPECT_CAST(Nullable, Inexact, NonNullable, Inexact, SuccessOnlyIfNonNull);
EXPECT_CAST(Nullable, Inexact, NonNullable, Exact, Unknown);
EXPECT_CAST(Nullable, Exact, Nullable, Inexact, Success);
EXPECT_CAST(Nullable, Exact, Nullable, Exact, Success);
EXPECT_CAST(Nullable, Exact, NonNullable, Inexact, SuccessOnlyIfNonNull);
EXPECT_CAST(Nullable, Exact, NonNullable, Exact, SuccessOnlyIfNonNull);
EXPECT_CAST(NonNullable, Inexact, Nullable, Inexact, Success);
EXPECT_CAST(NonNullable, Inexact, Nullable, Exact, Unknown);
EXPECT_CAST(NonNullable, Inexact, NonNullable, Inexact, Success);
EXPECT_CAST(NonNullable, Inexact, NonNullable, Exact, Unknown);
EXPECT_CAST(NonNullable, Exact, Nullable, Inexact, Success);
EXPECT_CAST(NonNullable, Exact, Nullable, Exact, Success);
EXPECT_CAST(NonNullable, Exact, NonNullable, Inexact, Success);
EXPECT_CAST(NonNullable, Exact, NonNullable, Exact, Success);
#undef EXPECT_CAST
}
TEST_F(CastCheckTest, CastToSelfFinal) {
#define EXPECT_CAST( \
srcNullability, srcExactness, castNullability, castExactness, result) \
EXPECT_EQ(evaluateCastCheck(Type(subFinal, srcNullability, srcExactness), \
Type(subFinal, castNullability, castExactness)), \
result);
EXPECT_CAST(Nullable, Inexact, Nullable, Inexact, Success);
EXPECT_CAST(Nullable, Inexact, Nullable, Exact, Success);
EXPECT_CAST(Nullable, Inexact, NonNullable, Inexact, SuccessOnlyIfNonNull);
EXPECT_CAST(Nullable, Inexact, NonNullable, Exact, SuccessOnlyIfNonNull);
EXPECT_CAST(Nullable, Exact, Nullable, Inexact, Success);
EXPECT_CAST(Nullable, Exact, Nullable, Exact, Success);
EXPECT_CAST(Nullable, Exact, NonNullable, Inexact, SuccessOnlyIfNonNull);
EXPECT_CAST(Nullable, Exact, NonNullable, Exact, SuccessOnlyIfNonNull);
EXPECT_CAST(NonNullable, Inexact, Nullable, Inexact, Success);
EXPECT_CAST(NonNullable, Inexact, Nullable, Exact, Success);
EXPECT_CAST(NonNullable, Inexact, NonNullable, Inexact, Success);
EXPECT_CAST(NonNullable, Inexact, NonNullable, Exact, Success);
EXPECT_CAST(NonNullable, Exact, Nullable, Inexact, Success);
EXPECT_CAST(NonNullable, Exact, Nullable, Exact, Success);
EXPECT_CAST(NonNullable, Exact, NonNullable, Inexact, Success);
EXPECT_CAST(NonNullable, Exact, NonNullable, Exact, Success);
#undef EXPECT_CAST
}
TEST_F(CastCheckTest, CastToSuper) {
#define EXPECT_CAST( \
srcNullability, srcExactness, castNullability, castExactness, result) \
EXPECT_EQ(evaluateCastCheck(Type(sub, srcNullability, srcExactness), \
Type(super, castNullability, castExactness)), \
result);
EXPECT_CAST(Nullable, Inexact, Nullable, Inexact, Success);
EXPECT_CAST(Nullable, Inexact, Nullable, Exact, SuccessOnlyIfNull);
EXPECT_CAST(Nullable, Inexact, NonNullable, Inexact, SuccessOnlyIfNonNull);
EXPECT_CAST(Nullable, Inexact, NonNullable, Exact, Failure);
EXPECT_CAST(Nullable, Exact, Nullable, Inexact, Success);
EXPECT_CAST(Nullable, Exact, Nullable, Exact, SuccessOnlyIfNull);
EXPECT_CAST(Nullable, Exact, NonNullable, Inexact, SuccessOnlyIfNonNull);
EXPECT_CAST(Nullable, Exact, NonNullable, Exact, Failure);
EXPECT_CAST(NonNullable, Inexact, Nullable, Inexact, Success);
EXPECT_CAST(NonNullable, Inexact, Nullable, Exact, Failure);
EXPECT_CAST(NonNullable, Inexact, NonNullable, Inexact, Success);
EXPECT_CAST(NonNullable, Inexact, NonNullable, Exact, Failure);
EXPECT_CAST(NonNullable, Exact, Nullable, Inexact, Success);
EXPECT_CAST(NonNullable, Exact, Nullable, Exact, Failure);
EXPECT_CAST(NonNullable, Exact, NonNullable, Inexact, Success);
EXPECT_CAST(NonNullable, Exact, NonNullable, Exact, Failure);
#undef EXPECT_CAST
}
TEST_F(CastCheckTest, CastToSub) {
#define EXPECT_CAST( \
srcNullability, srcExactness, castNullability, castExactness, result) \
EXPECT_EQ(evaluateCastCheck(Type(super, srcNullability, srcExactness), \
Type(sub, castNullability, castExactness)), \
result);
EXPECT_CAST(Nullable, Inexact, Nullable, Inexact, Unknown);
EXPECT_CAST(Nullable, Inexact, Nullable, Exact, Unknown);
EXPECT_CAST(Nullable, Inexact, NonNullable, Inexact, Unknown);
EXPECT_CAST(Nullable, Inexact, NonNullable, Exact, Unknown);
EXPECT_CAST(Nullable, Exact, Nullable, Inexact, SuccessOnlyIfNull);
EXPECT_CAST(Nullable, Exact, Nullable, Exact, SuccessOnlyIfNull);
EXPECT_CAST(Nullable, Exact, NonNullable, Inexact, Failure);
EXPECT_CAST(Nullable, Exact, NonNullable, Exact, Failure);
EXPECT_CAST(NonNullable, Inexact, Nullable, Inexact, Unknown);
EXPECT_CAST(NonNullable, Inexact, Nullable, Exact, Unknown);
EXPECT_CAST(NonNullable, Inexact, NonNullable, Inexact, Unknown);
EXPECT_CAST(NonNullable, Inexact, NonNullable, Exact, Unknown);
EXPECT_CAST(NonNullable, Exact, Nullable, Inexact, Failure);
EXPECT_CAST(NonNullable, Exact, Nullable, Exact, Failure);
EXPECT_CAST(NonNullable, Exact, NonNullable, Inexact, Failure);
EXPECT_CAST(NonNullable, Exact, NonNullable, Exact, Failure);
#undef EXPECT_CAST
}
TEST_F(CastCheckTest, CastToSibling) {
#define EXPECT_CAST( \
srcNullability, srcExactness, castNullability, castExactness, result) \
EXPECT_EQ(evaluateCastCheck(Type(sub, srcNullability, srcExactness), \
Type(subFinal, castNullability, castExactness)), \
result);
EXPECT_CAST(Nullable, Inexact, Nullable, Inexact, SuccessOnlyIfNull);
EXPECT_CAST(Nullable, Inexact, Nullable, Exact, SuccessOnlyIfNull);
EXPECT_CAST(Nullable, Inexact, NonNullable, Inexact, Failure);
EXPECT_CAST(Nullable, Inexact, NonNullable, Exact, Failure);
EXPECT_CAST(Nullable, Exact, Nullable, Inexact, SuccessOnlyIfNull);
EXPECT_CAST(Nullable, Exact, Nullable, Exact, SuccessOnlyIfNull);
EXPECT_CAST(Nullable, Exact, NonNullable, Inexact, Failure);
EXPECT_CAST(Nullable, Exact, NonNullable, Exact, Failure);
EXPECT_CAST(NonNullable, Inexact, Nullable, Inexact, Failure);
EXPECT_CAST(NonNullable, Inexact, Nullable, Exact, Failure);
EXPECT_CAST(NonNullable, Inexact, NonNullable, Inexact, Failure);
EXPECT_CAST(NonNullable, Inexact, NonNullable, Exact, Failure);
EXPECT_CAST(NonNullable, Exact, Nullable, Inexact, Failure);
EXPECT_CAST(NonNullable, Exact, Nullable, Exact, Failure);
EXPECT_CAST(NonNullable, Exact, NonNullable, Inexact, Failure);
EXPECT_CAST(NonNullable, Exact, NonNullable, Exact, Failure);
#undef EXPECT_CAST
}
TEST_F(CastCheckTest, CastToBottom) {
#define EXPECT_CAST(srcNullability, srcExactness, castNullability, result) \
EXPECT_EQ(evaluateCastCheck(Type(super, srcNullability, srcExactness), \
Type(HeapType::none, castNullability, Inexact)), \
result);
EXPECT_CAST(Nullable, Inexact, Nullable, SuccessOnlyIfNull);
EXPECT_CAST(Nullable, Inexact, NonNullable, Failure);
EXPECT_CAST(Nullable, Exact, Nullable, SuccessOnlyIfNull);
EXPECT_CAST(Nullable, Exact, NonNullable, Failure);
EXPECT_CAST(NonNullable, Inexact, Nullable, Failure);
EXPECT_CAST(NonNullable, Inexact, NonNullable, Failure);
EXPECT_CAST(NonNullable, Exact, Nullable, Failure);
EXPECT_CAST(NonNullable, Exact, NonNullable, Failure);
#undef EXPECT_CAST
}
TEST_F(CastCheckTest, CastFromBottom) {
#define EXPECT_CAST(srcNullability, castNullability, castExactness, result) \
EXPECT_EQ(evaluateCastCheck(Type(HeapType::none, srcNullability, Inexact), \
Type(super, castNullability, castExactness)), \
result);
EXPECT_CAST(Nullable, Nullable, Inexact, Success);
EXPECT_CAST(Nullable, Nullable, Exact, Success);
EXPECT_CAST(Nullable, NonNullable, Inexact, Failure);
EXPECT_CAST(Nullable, NonNullable, Exact, Failure);
EXPECT_CAST(NonNullable, Nullable, Inexact, GCTypeUtils::Unreachable);
EXPECT_CAST(NonNullable, Nullable, Exact, GCTypeUtils::Unreachable);
EXPECT_CAST(NonNullable, NonNullable, Inexact, GCTypeUtils::Unreachable);
EXPECT_CAST(NonNullable, NonNullable, Exact, GCTypeUtils::Unreachable);
#undef EXPECT_CAST
}
} // namespace wasm