Skip to content

Invalid result of inferring parameterized type #310

@d367wang

Description

@d367wang

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.

  1. Get the owner of method element next(), which is Iterator<T>
  2. Get the ATM of direct supertype of CursorIterator, which is Iterator<Double>
  3. Build mappings using results of step 1 and 2, as something like { T->@VarAnnot(?) }
  4. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions