Skip to content

Commit

Permalink
Support better mixin handling
Browse files Browse the repository at this point in the history
  • Loading branch information
muglug committed May 27, 2020
1 parent 203ed6d commit 3c60609
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,20 @@ public static function analyze(
$codebase
);

$lhs_type_expanded = \Psalm\Internal\Type\TypeExpander::expandUnion(
$codebase,
new Type\Union([$lhs_type_part]),
$mixin_declaring_class_storage->name,
$fq_class_name,
$class_storage->parent_class
);

$new_lhs_type_part = array_values($lhs_type_expanded->getAtomicTypes())[0];

if ($new_lhs_type_part instanceof Type\Atomic\TNamedObject) {
$lhs_type_part = $new_lhs_type_part;
}

$mixin_class_storage = $codebase->classlike_storage_provider->get($class_storage->mixin->value);

$fq_class_name = $mixin_class_storage->name;
Expand Down
56 changes: 55 additions & 1 deletion tests/MixinAnnotationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ function toArray(B $b) : string {
return $b->foo;
}'
],
'inheritTemplatedMixin' => [
'inheritTemplatedMixinWithStatic' => [
'<?php
/**
* @template T
Expand Down Expand Up @@ -316,6 +316,60 @@ class A {}
(new A)->foo();',
'error_message' => 'UndefinedMethod'
],
'inheritTemplatedMixinWithSelf' => [
'<?php
/**
* @template T
*/
class Mixin {
/**
* @psalm-var T
*/
private $var;
/**
* @psalm-param T $var
*/
public function __construct ($var) {
$this->var = $var;
}
/**
* @psalm-return T
*/
public function type() {
return $this->var;
}
}
/**
* @template T as object
* @mixin Mixin<T>
*/
abstract class Foo {
/** @var Mixin<T> */
public object $obj;
public function __call(string $name, array $args) {
return $this->obj->$name(...$args);
}
}
/**
* @extends Foo<self>
*/
abstract class FooChild extends Foo{}
/**
* @psalm-suppress MissingConstructor
*/
final class FooGrandChild extends FooChild {}
function test() : FooGrandChild {
return (new FooGrandChild)->type();
}',
'error_message' => 'LessSpecificReturnStatement'
],
];
}
}

0 comments on commit 3c60609

Please sign in to comment.