Skip to content

Commit

Permalink
[modulite] fixed inheritance late static bindings (#908)
Browse files Browse the repository at this point in the history
* added new tests for late static bindings in modulite

* fixed logic when modulite not correctly handles late static binding with cross-module inheritance

---------

Co-authored-by: Aleksandr Kirsanov <[email protected]>
  • Loading branch information
Hidanio and tolk-vm authored Oct 18, 2023
1 parent f6751bf commit c4031c7
Show file tree
Hide file tree
Showing 36 changed files with 1,425 additions and 0 deletions.
1 change: 1 addition & 0 deletions compiler/data/function-data.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class FunctionData {
// for lambdas: a function that contains this lambda ($this is captured from outer_function, it can also be a lambda on nesting)
// for generic instantiations: refs to an original (a generic) function
// for __invoke method of a lambda: refs to a lambda function that's called from this __invoke
// for inherited context functions Base::f(static=Derived): refs to Base::f (where it was cloned from)
FunctionPtr outer_function;

// use($var1, &$var2) for lambdas, implicit vars for arrow lambdas; auto-captured $this is also here, the first one
Expand Down
9 changes: 9 additions & 0 deletions compiler/modulite-check-rules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ static inline bool should_this_usage_context_be_ignored(FunctionPtr usage_contex
usage_context->class_id != usage_context->context_class) {
return true; // NOLINT(readability-simplify-boolean-expr)
}
// case 2.
// (no module): class Base { printAppend() { ... } }
// @mod : class Derived { print() { self::printAppend() } }
// then KPHP implicitly creates Derived::printAppend() { parent::printAppend() }
// and warns (on parent::) that "Base::printAppend() is not required by @mod"
// solution: ignore such auto-created inherited methods
if (usage_context->is_auto_inherited) {
return true;
}
return false;
}

Expand Down
4 changes: 4 additions & 0 deletions compiler/pipes/check-func-calls-and-vararg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,10 @@ VertexPtr CheckFuncCallsAndVarargPass::on_func_call(VertexAdaptor<op_func_call>
bool is_instance_call = f->modifiers.is_instance();
bool is_constructor_call = f->is_constructor() && !f->class_id->is_lambda_class();
if (f->type == FunctionData::func_local && !is_instance_call) {
// static::f() (and some other cases) could be earlier replaced by Base::f(static=Derived)
if (f->modifiers.is_static() && f->context_class && f->outer_function) {
f = f->outer_function; // refs back to Base::f()
}
modulite_check_when_call_function(current_function, f);
} else if (f->type == FunctionData::func_local && is_constructor_call) {
modulite_check_when_use_class(current_function, f->class_id);
Expand Down
1 change: 1 addition & 0 deletions compiler/pipes/sort-and-inherit-classes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ void SortAndInheritClassesF::inherit_static_method_from_parent(ClassPtr child_cl
std::string ctx_function_name = replace_backslashes(parent_class->name) + "$$" + local_name + "$$" + replace_backslashes(child_class->name);
FunctionPtr context_function = FunctionData::clone_from(parent_f, ctx_function_name);
context_function->context_class = child_class;
context_function->outer_function = parent_f;
CloneNestedLambdasPass::run_if_lambdas_inside(context_function, &function_stream);
stage::set_file(child_class->file_id);
stage::set_function(FunctionPtr{});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@ok
<?php
#ifndef KPHP
require_once 'kphp_tester_include.php';
#endif

$_ = \Messages011\MessagesLogger011::log();
\Messages011\MessagesLogger011::create();
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Logs011;

abstract class BaseLog011 {
protected static function logAction(): bool {
return true;
}

protected static function createLog(): void {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: "@messages011"
description: ""
namespace: "Messages011\\"

export:
- "MessagesLogger011"

force-internal:

require:
- "\\Logs011\\BaseLog011"
- "\\Logs011\\BaseLog011::createLog()"
- "\\Logs011\\BaseLog011::logAction()"

allow-internal-access:
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Messages011;

use Logs011\BaseLog011;

class MessagesLogger011 extends BaseLog011 {

public static function create(): void {
parent::createLog();
}

public static function log(): bool {
return parent::logAction();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@ok
KPHP_COMPOSER_ROOT={dir}
<?php
#ifndef KPHP
require_once 'kphp_tester_include.php';
#endif
require_once __DIR__ . '/vendor/autoload.php';

\Printer012\Printer012::print();
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace BasePrinter012;

use Vk\TestSrt\SomeStr;

class BasePrinter012 {
final public static function basePrint(): void {
$r1 = new SomeStr();
echo "BasePrint\n";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: "@printer012"
description: ""
namespace: "Printer012\\"

# "Public API" of the modulite: classes, functions, constants, etc.
# Symbols not listed here will be internal.
export:
- "Printer012"

# Class members to exclude, they override "export".
force-internal:

# Dependencies: other modulites, global classes, defines, etc.
require:
- "\\BasePrinter012\\BasePrinter012"

# Granting partial access to internal symbols, "as an exception".
allow-internal-access:
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Printer012;

use BasePrinter012\BasePrinter012;

class Printer012 extends BasePrinter012 {

public static function print(): void {
self::basePrint();
echo "print\n";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "phpt/012",
"autoload": {
"psr-4": {
"BasePrinter012\\": "./BasePrinter012",
"Printer012\\": "./Printer012"
}
},
"require": {
"vk/strings": "*"
},
"repositories": [
{
"type": "path",
"url": "./packages/vk-strings"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "vk/strings",
"version": "0.0.1",
"type": "library",
"autoload": {
"psr-4": {
"Vk\\TestSrt\\": "src/"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace Vk\TestSrt;

class SomeStr {
public static function concatStr(string $s1, string $s2): string {
return $s1 . $s2;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

// autoload.php @generated by Composer

if (PHP_VERSION_ID < 50600) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, $err);
} elseif (!headers_sent()) {
echo $err;
}
}
trigger_error(
$err,
E_USER_ERROR
);
}

require_once __DIR__ . '/composer/autoload_real.php';

return ComposerAutoloaderInit451b6d5135cd4eb8e84df3fc66c39587::getLoader();
Loading

0 comments on commit c4031c7

Please sign in to comment.