§2.4.3 Role creation in the presence of smart lifting

Explicitly instantiating a role R1 bound to a base B where smart lifting of B to R1 would actually provide a subrole R2 is dangerous: Instantiation enters the R1 into the team's internal cache. If at any time later lifting this B to R2 is requested, which is a legal request, the runtime system will answer by throwing a org.objectteams.WrongRoleException because it finds the R1 instead of the required R2. For this reason, in this specific situation the explicit instantiation new R1(..) will be flagged by a warning. The problem can be avoided by using R2 in the instantiation expression.

Example code (WrongRoleException):
1
public class B { void bm() {} }
2
public team class T {
3
  protected class R1 playedBy B {...}
4
  protected class R2 extends R1 { // inherits the binding to B
5
    void rm() { /* body omitted */ }
6
  }
7
  public B getDecoratedB() {
8
    return new R1(new B()); // compile-time warning!
9
  }
10
  public void requestLifting(B as R2 r) {}
11
}
12
// plus these calls:
13
T t = new T();
14
B b = t.getDecoratedB(); // creates an R1 for b
15
t.requestLifting(b); // => org.objectteams.WrongRoleException!
  • A note on line 8: this line passes a fresh instance of B to the lifting constructor of R1 (see §2.4.1.(b)). In order to return this B instance lowering is implicitly used for the return statement.
  • When line 15 is executed, a lifting of b to R2 is requested but due to line 8 an R1 is found in the internal cache.