Bug #63911 [Com]: Ignore conflicting trait methods originationg from identical sub traits

From: Date: Sat, 12 Dec 2015 15:44:20 +0000
Subject: Bug #63911 [Com]: Ignore conflicting trait methods originationg from identical sub traits
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-197833@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=63911&edit=1

 ID:                 63911
 Comment by:         serovov at gmail dot com
 Reported by:        bitluni at bitluni dot net
 Summary:            Ignore conflicting trait methods originationg from
                     identical sub traits
 Status:             Verified
 Type:               Bug
 Package:            Class/Object related
 Operating System:   *
 PHP Version:        5.6.9
 Assigned To:        gron
 Block user comment: N
 Private report:     N

 New Comment:

I would like to add another test case to this issue. It should handle same methods not only from
sub-traits but also from current class.

Thanks!

<?php

trait helper {
    public function helper() {}
}


trait util_useful {
    use helper;
    public function do_something_useful() {$this->helper(); return 'useful';}
}

trait util_useless {
    use helper;
    public function do_something_useless() {$this->helper();  return 'useless';}
}

class utils {
    use helper;
    use util_useful;
    use util_useless;

    public function use_helper() { $this->helper();}
}

$ob = new utils();

echo $ob->do_something_useful(), "\n";
echo $ob->do_something_useless(), "\n";
echo $ob->use_helper(), "\n";

?>


Previous Comments:
------------------------------------------------------------------------
[2015-06-09 14:13:32] cmb@php.net

Related To: Bug #69774

------------------------------------------------------------------------
[2015-06-09 14:12:04] cmb@php.net

I would assume that a use statement simply injects the members of
the trait into the lexically current class/trait. So B and C in
the test script of the OP have separate a() methods, which leads
to a conflict when both traits are used in D.

The section "The Flattening Property" in the respective RFC[1]
supports this assumption:

| Traits are only entities of the literal code written in your
| source files. There is no notion about Traits at runtime. They
| are used to group methods and reuse code and are totally
| flattened into the classes composed from them. It is almost like
| a language supported and failsafe copy'n'paste mechanism to
| build classes.

The section "Traits Composed from Traits"[2] furthermore states:

> Since Traits are fully flattened away at compile time it is
> possible to use Traits to compose Traits without any additional
> impact on the semantics.

According to that information I would say the behavior is to be
expected, and as such is not a bug, but rather needs to be
documented in the PHP manual.

As gron stated otherwise, I'm assigning to him. Stefan, can you
please have a look at this issue?

See also <http://3v4l.org/RkYH5>.

[1] <https://wiki.php.net/rfc/horizontalreuse#the_flattening_property>
[2] <https://wiki.php.net/rfc/horizontalreuse#traits_composed_from_traits>

------------------------------------------------------------------------
[2015-03-17 15:02:57] paul at edunation dot co dot uk

Fixing this issue could make traits a far more useful composition tool! (and avoid countless
insteadof statements)

If tampering with the "use" statement is problematic, could an explicit
"use_once" statement not add a simple, per-class usage check for a given trait?

------------------------------------------------------------------------
[2014-12-24 05:15:27] keithdavis at solidtechservice dot com

I suppose that would work, but that does still divert from the actual issue here - that there is
nothing to "override", as it's the same trait being used twice.

------------------------------------------------------------------------
[2014-12-22 21:10:51] mw dot wanrooij at vodafonevast dot nl

In my humble opinion, a solution/improvement would be that precedence order should not only be
appliccable to classes, but also to traits.

To expand on the given example at the start of this topic, when:
trait A
{
    public function a(){}
    public function b(){}
    public function c(){}
    public function z(){}
}
trait B
{
    use A;
}
trait C
{
    use A;
}
class D
{
    use B, C;
}
The expected result here would be that methods in trait C override methods in trait B, unless
explicitly specified using the insteadof operator.

Shortened example using the insteadof operator:
class D
{
    use B;
    use C {
        B::a insteadof C;
    }
}
Here, the expected results would be that methods in trait C override methods in trait B, except for
method B::a() which is explicitly defined to be used instead of C::a()

If one would change which methods would override other methods, one would simply change the
precedence other, as with the example:
class D
{
    use C;
    use B {
        C::a insteadof B;
    }
}
Here, the expected results would be that methods in trait B override methods in trait C, except for
method C::a() which is explicitly defined to be used instead of B::a()

Am I making sense?

------------------------------------------------------------------------


The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at

    https://bugs.php.net/bug.php?id=63911


--
Edit this bug report at https://bugs.php.net/bug.php?id=63911&edit=1


Thread (21 messages)

« previous php.bugs (#197833) next »