For the following case:
import ostrusted.qual.OsTrusted;
interface Iterator<T> {
T next();
}
abstract class CursorIterator implements Iterator<Object> {}
abstract class Test {
@OsTrusted Object foo(CursorIterator it) {
return it.next();
}
}
The return type of foo(CursorIterator it), which is @OsTrusted, ought to lead parameterized type Iterator<Object> to be inferred as Iterator<@OsTrusted Object>.
While the actual result is
@OsUntrusted
interface Iterator<T> {
T next(@OsTrusted Iterator<T> this);
}
@OsTrusted
abstract class CursorIterator implements @OsTrusted Iterator<Object> {}
abstract class Test {
@OsTrusted Object foo(@OsTrusted CursorIterator it) {
return it.next();
}
}
The invalid result stems from multiple problems in CFI.
Problem I - Implementation of asMemberOf
when getting the annotated type of it.next(), the following steps are performed.
- Get the owner of method element
next(), which is Iterator<T>
- Get the ATM of direct supertype of
CursorIterator, which is Iterator<Double>
- Build mappings using results of step 1 and 2, as something like
{ T->@VarAnnot(?) }
- Substitute type variables in
T next(Iterator<T> this) using the mappings in step 3
The problem occurs at step 2 when getting the annotated type of type element Iterator<Double>. The previously created @VarAnnot for CursorIterator class declaration is not used.
Problem II - Missing constraints
@VarAnnot(7)
interface Iterator<@VarAnnot(5) T extends @VarAnnot(6) Object> {
@VarAnnot(9)
T next(@VarAnnot(12) Iterator<@VarAnnot(13) T> this);
}
@VarAnnot(17)
abstract class CursorIterator implements @VarAnnot(15) Iterator<@VarAnnot(16) Object> {}
@VarAnnot(21)
abstract class Test {
@OsTrusted Object foo(@VarAnnot(25) Test this, @VarAnnot(24) CursorIterator it) {
return it.next();
}
}
Only the following constraints are created. (unrelated constraints omitted)
15 <: 7
24 <: 12
24 <: 17
As a result of the above issue, the type of it.next() after running InferenceTreeAnnotator turns out to be Object. Since When the ontology type system didn't specify a default qualifier, it.next() eventually has no annotation on it, such that a null slot takes part in the constraint, a crash.
opprop/ontology#50 workarounds this issue by specifying the default qualifier
For the following case:
The return type of
foo(CursorIterator it), which is@OsTrusted, ought to lead parameterized typeIterator<Object>to be inferred asIterator<@OsTrusted Object>.While the actual result is
The invalid result stems from multiple problems in CFI.
Problem I - Implementation of
asMemberOfwhen getting the annotated type of
it.next(), the following steps are performed.next(), which isIterator<T>CursorIterator, which isIterator<Double>{ T->@VarAnnot(?) }T next(Iterator<T> this)using the mappings in step 3The problem occurs at step 2 when getting the annotated type of type element
Iterator<Double>. The previously created@VarAnnotforCursorIteratorclass declaration is not used.Problem II - Missing constraints
Only the following constraints are created. (unrelated constraints omitted)
15 <: 7
24 <: 12
24 <: 17
As a result of the above issue, the type of
it.next()after runningInferenceTreeAnnotatorturns out to beObject. Since When the ontology type system didn't specify a default qualifier,it.next()eventually has no annotation on it, such that a null slot takes part in the constraint, a crash.opprop/ontology#50 workarounds this issue by specifying the default qualifier