    001    /* Copyright 2000, 2001, Compaq Computer Corporation */
    002
    003    package javafe.tc;
    004
    005    import javafe.ast.*;
    006    import javafe.util.*;
    007
    008
    009    /**
    010     * Env's are the environments used during typechecking to keep track
    011     * of what types, local variables, fields, and current/enclosing
    012     * instances are in scope.
    013     */
    014
    015    public abstract class Env {
    016
    017        ///////////////////////////////////////////////////////////////////////
    018        //                                                                   //
    019        // Methods implemented by each instance of Env                       //
    020        //                                                                   //
    021        ///////////////////////////////////////////////////////////////////////
    022
    023
    024        /***************************************************
    025         *                                                 *
    026         * Current/enclosing instances I:                  *
    027         *                                                 *
    028         **************************************************/
    029
    030        /**
    031         * Is there a current instance in scope? <p>
    032         *
    033         * E.g., is "this" (or "<enclosing class>.this") legal here? <p>
    034         *
    035         * This is also refered to as "are we in a static context?".  The
    036         * legality of super also depends on this result. <p>
    037         *
    038         * The legality of C.this, C != <enclosing class> is different; see
    039         * canAccessInstance(-).
    040         */
    041        abstract public boolean isStaticContext();
    042
    043
    044        /**
    045         * Return the intermost class enclosing the code that is checked
    046         * in this environment. <p>
    047         *
    048         * May return null if there is no enclosing class (aka, for
    049         * environments for CompilationUnits). <p>
    050         *
    051         * If isStaticContext() returns true, then this is the type of "this".
    052         */
    053        //@ ensures (this instanceof EnvForCU) == (\result==null);
    054        abstract public TypeSig getEnclosingClass();
    055
    056
    057        /**
    058         * If there is an enclosing instance in scope, then return the
    059         * (exact) type of the innermost such instance. <p>
    060         *
    061         * Note: this is considered a current instance, not an enclosing
    062         * instance, even inside its methods.
    063         */
    064        abstract public TypeSig getEnclosingInstance();
    065
    066
    067        /**
    068         * Returns a new Env that acts the same as us, except that its
    069         * current instance (if any) is not accessible. <p>
    070         *
    071         * Note: this routine is somewhat inefficient and should be
    072         * avoided unless an unknown environment needs to be coerced in
    073         * this way. <p>
    074         */
    075        //@ ensures \result != null;
    076        //@ ensures (this instanceof EnvForCU) == (\result instanceof EnvForCU);
    077        abstract public Env asStaticContext();
    078
    079
    080        /***************************************************
    081         *                                                 *
    082         * Simple names:                                   *
    083         *                                                 *
    084         **************************************************/
    085
    086        /**
    087         * Attempt to lookup a simple TypeName in this environment to get
    088         * the TypeSig it denotes.  Returns null if no such type
    089         * exists.<p>
    090         *
    091         * This routine does not check that the resulting type (if any)
    092         * is actually accessible, if caller is null. <p>
    093         *
    094         * If id is ambiguous, then if loc != Location.NULL then a fatal
    095         * error is reported at that location via ErrorSet else one of
    096         * its possible meanings is returned.<p>
    097         */
    098        abstract public TypeSig lookupSimpleTypeName(
    099                                    TypeSig caller, /*@ non_null @*/ Identifier id,
    100                                                     int loc);
    101
    102
    103        /**
    104         * Locate the lexically innermost field or local variable
    105         * declaration with a given name. <p>
    106         *
    107         * Let d be the lexically innermost field or local variable
    108         * declaration (including formals) of id (if any such declaration
    109         * exists).  Then this routine returns: <p>
    110         *
    111         *    d (a LocalVarDecl or FormalParaDecl) if d is a local
    112         *                                            variable declaration
    113         *
    114         *    the class C that lexically encloses us and contains the
    115         *    (inherited) field d if d is a field declaration
    116         *
    117         *    null if d does not exist
    118         *
    119         * Note: inherited fields are considered to lexically enclose the
    120         * code of their subclasses.  We give the class containing the
    121         * field instead of the field itself to postpone dealing with
    122         * multiple fields named id visible in the same class.<p>
    123         *
    124         * In the field case, id disambiguates to C[.this].id.<p>
    125         *
    126         * This routine does not check that a resulting field
    127         * is actually accessible. <p>
    128         */
    129        /*@ ensures \result==null || (\result instanceof GenericVarDecl)
    130                    || (\result instanceof TypeSig); */
    131        /*@ ensures \result instanceof GenericVarDecl ==>
    132                           ((GenericVarDecl)\result).id == id; */
    133        //@ ensures (this instanceof EnvForCU) ==> \result==null;
    134        abstract public ASTNode locateFieldOrLocal(/*@ non_null @*/ Identifier id);
    135
    136        public boolean isDuplicate(/*@ non_null */ Identifier id) {
    137            return locateFieldOrLocal(id) instanceof GenericVarDecl;
    138        }
    139
    140        /**
    141         * Locate the lexically innermost method named id. <p>
    142         *
    143         * Returns the TypeSig for the innermost lexically enclosing type
    144         * that has a method named id or null if no such type exists.<p>
    145         *
    146         * Note: inherited methods are considered to lexically enclose
    147         * the code of their subclasses.<p>
    148         *
    149         * id disambiguates to C[.this].id.<p>
    150         *
    151         * This routine does not check that a resulting method
    152         * is actually accessible. <p>
    153         */
    154        //@ ensures (this instanceof EnvForCU) ==> \result==null;
    155        abstract public TypeSig locateMethod(/*@ non_null @*/ Identifier id);
    156
    157
    158        /***************************************************
    159         *                                                 *
    160         * Debugging functions:                            *
    161         *                                                 *
    162         **************************************************/
    163
    164        /**
    165         * Display information about us to System.out.  This function is
    166         * intended only for debugging use.
    167         */
    168        abstract public void display();
    169
    170
    171        ///////////////////////////////////////////////////////////////////////
    172        //                                                                   //
    173        // Derived Methods                                                   //
    174        //                                                                   //
    175        ///////////////////////////////////////////////////////////////////////
    176
    177
    178        /***************************************************
    179         *                                                 *
    180         * Type variable names:                            *
    181         *                                                 *
    182         **************************************************/
    183
    184        /**
    185         * Attempts to find the canonical prefix of a given name that
    186         * denotes a TypeName in this environment. <p>
    187         *
    188         * A canonical prefix is composed of a base type name (either the
    189         * leftmost identifer or a fully-quantified outside type name
    190         * (P.I) depending), extended by some number of type member
    191         * accesses (.C1.C2...).
    192         *
    193         * If ignoreFields is not set, then we stop extending the base
    194         * type name as soon as we encounter an access that can refer to
    195         * a field.  If it is set, then we stop extending only when we
    196         * reach the end of the name or an access that cannot refer to a
    197         * type member. <p>
    198         *
    199         * If we encounter an ambiguous prefix, we report a fatal error
    200         * at loc via ErrorSet.<p>
    201         *
    202         * Otherwise, we return the TypeSig that the found prefix denotes
    203         * (null if the prefix is of length 0) and sets prefixSize to the
    204         * prefix's size. <p>
    205         *
    206         * This routine does not check that the resulting type (if any)
    207         * is actually accessible, unless caller is not null. <p>
    208         */
    209        //@ modifies prefixSize;
    210        //@ ensures \result==null ==> 0==prefixSize;
    211        //@ ensures \result != null ==> 0<prefixSize && prefixSize <= n.length;
    212        public TypeSig findTypeNamePrefix(TypeSig caller,
    213                                          /*@ non_null @*/ Name n,
    214                                          boolean ignoreFields) {
    215            // Check for an unqualified name first:
    216            TypeSig sig = lookupSimpleTypeName(caller,n.identifierAt(0),
    217                                               n.getStartLoc());
    218            prefixSize = 1;
    219            if (sig==null) {
    220                // Nope; must be a qualified name with a non-empty package prefix:
    221                while (++prefixSize<=n.size()) {
    222                    // Lookup n[0]..n[prefixSize-2] . n[prefixSize-1]:
    223                    sig = OutsideEnv.lookup(n.prefix(prefixSize-1).toStrings(),
    224                                    n.identifierAt(prefixSize-1).toString());
    225                    if (sig != null)
    226                        break;      // Stop at smallest qualified name
    227                }
    228                if (prefixSize>n.size()) {
    229                    prefixSize = 0;
    230                    return null;
    231                }
    232            }
    233
    234            // Here we have that n[0]..n[prefixSize-1] denotes the type sig
    235
    236            // Try and extend it as much as possible via nested types
    237            while (prefixSize<n.size()) {
    238                Identifier id = n.identifierAt(prefixSize);
    239                int idLoc = n.locIdAt(prefixSize);
    240
    241                // Stop if next access refers to a field & !ignoreFields:
    242                if (!ignoreFields && sig.hasField(id))
    243                    break;
    244
    245                // Stop if next access cannot refer to a type member:
    246                TypeSig next = sig.lookupType(caller, id, idLoc);
    247                if (next==null)
    248                    break;
    249
    250                sig = next;
    251                prefixSize++;
    252            }
    253
    254            return sig;
    255        }
    256        //* Holds the second return value of findTypeNamePrefix
    257        public int prefixSize;
    258
    259
    260        /**
    261         * Attempt to lookup a TypeName using this environment. <p>
    262         *
    263         * If it encounters an ambiguous prefix, a fatal error is
    264         * reported via ErrorSet.<p>
    265         *
    266         * Otherwise, returns the TypeSig that n denotes or null if n
    267         * does not denote a type.<p>
    268         *
    269         * This routine does not check that the resulting type (if any)
    270         * is actually accessible, unless caller is not null. <p>
    271         */
    272        public TypeSig lookupTypeName(TypeSig caller, /*@ non_null @*/ Name n) {
    273            TypeSig sig = findTypeNamePrefix(caller, n, true);
    274            if (prefixSize != n.size())
    275                return null;
    276
    277            return sig;
    278        }
    279
    280
    281        /**
    282         * This processes the annotations on a type name
    283         */
    284        //@ ensures \result != null;
    285        public TypeSig processTypeNameAnnotations(/*@ non_null @*/ TypeName n,
    286                                                  /*@ non_null @*/ TypeSig sig) {
    287            return PrepTypeDeclaration.inst.processTypeNameAnnotations(n,sig,this);
    288        }
    289
    290
    291        /**
    292         * Attempt to resolve a TypeName using this environment. <p>
    293         *
    294         * If an error occurs (including no such type), reports it to
    295         * ErrorSet via a fatal error.<p>
    296         *
    297         * Otherwise, returns the TypeSig that n denotes.  This TypeSig
    298         * may also later be obtained by using TypeSig.getSig on n.<p>
    299         *
    300         * This routine does not check that the resulting type (if any)
    301         * is actually accessible, unless caller is not null. <p>
    302         */
    303        //@ ensures \result != null;
    304        public TypeSig resolveTypeName(TypeSig caller, /*@ non_null @*/ TypeName tn) {
    305            Name n = tn.name;
    306
    307            TypeSig sig = TypeSig.getRawSig(tn);  // FIXME - use caller ?
    308            if (sig != null)
    309                return sig;
    310
    311            sig = lookupTypeName(caller, n);
    312            if (sig==null) {
    313                ErrorSet.fatal(tn.name.locIdAt(0),
    314                               "Can't find type named \""
    315                               + tn.name.printName() + "\"");
    316            }
    317
    318            sig = processTypeNameAnnotations(tn, sig);  // FIXME - use caller?
    319            TypeSig.setSig(tn, sig);
    320            return sig;
    321        }
    322
    323        /**
    324         * decoration holding the type environment in which a type is resolved.
    325         */
    326        //@ invariant typeEnv != null;
    327        //@ invariant typeEnv.decorationType == \type(Env);
    328        static public ASTDecoration typeEnv =
    329            new ASTDecoration("environment");
    330
    331        /**
    332         * Attempt to resolve a Type using this environment. <p>
    333         *
    334         * If an error occurs, reports it to ErrorSet via a fatal error.<p>
    335         *
    336         * This routine does not check that (immediate) types (if any)
    337         * are actually accessible, if caller is null. <p>
    338         */
    339        public void resolveType(TypeSig caller, /*@ non_null @*/ Type t) {
    340            typeEnv.set(t,this);
    341            switch(t.getTag()) {
    342              case TagConstants.ARRAYTYPE:
    343                resolveType(caller, ((ArrayType)t).elemType);
    344                break;
    345
    346              case TagConstants.TYPENAME:
    347                resolveTypeName(caller, (TypeName)t);
    348                break;
    349
    350              // No need to resolve primitive types or TypeSigs...
    351            }
    352        }
    353
    354
    355        /***************************************************
    356         *                                                 *
    357         * Expr names:                                     *
    358         *                                                 *
    359         **************************************************/
    360
    361        /**
    362         * Attempt to disambiguate an Expr Name.  Either returns the
    363         * disambiguated Name as an Expr or null if it does not denote
    364         * anything. <p>
    365         *
    366         * If non-null, the result will always be a field access of some
    367         * kind.
    368         *
    369         * If a prefix of n is ambiguous because of multiple
    370         * import-on-demand declarations, a fatal error will result.
    371         * Nothing is reported if n does not name anything.<p>
    372         *
    373         *
    374         * If n is a reference to a field f in lexically enclosing class
    375         * C, then the result will be of the form "[C.]this.n" if C's
    376         * instance fields are accessible and "C.n" otherwise.<p>
    377         *
    378         * (At this point we haven't decided which field f refers to so
    379         * we don't know if it is an instance field or not.)
    380         */
    381        //@ ensures !(\result instanceof AmbiguousVariableAccess);
    382        public Expr disambiguateExprName(/*@ non_null @*/ Name n) {
    383            /*
    384             * Find the smallest prefix of n, n[0]..n[prefix-1], such that
    385             * it denotes an Expr, call it left:
    386             */
    387            Expr left = null;
    388            Identifier leftmost = n.identifierAt(0);
    389            int leftmostLoc = n.getStartLoc();
    390
    391            ASTNode result = locateFieldOrLocal(leftmost);
    392            int prefix = 1;
    393            if (result instanceof GenericVarDecl) {
    394                // leftmost is a local variable:
    395                left = VariableAccess.make(leftmost, leftmostLoc,
    396                                           (GenericVarDecl)result);
    397            } else if (result instanceof TypeSig) {
    398                // leftmost is a field in class result:
    399                ObjectDesignator od = getObjectDesignator((TypeSig)result,
    400                                                          leftmostLoc);
    401                left = FieldAccess.make(od, leftmost, leftmostLoc);
    402            } else {
    403                // n *must* start with a typename then:
    404                TypeSig sig = findTypeNamePrefix(null, n, false); // FIXME - a caller for access checking?
    405                if (sig==null || prefixSize==n.size())
    406                    return null;
    407
    408                prefix = prefixSize+1;
    409                TypeName tn = TypeName.make(n.prefix(prefixSize));
    410                TypeSig.setSig(tn, sig);
    411                int leftmostDot = leftmostLoc;
    412                if (prefixSize>0)
    413                    leftmostDot = n.locDotAfter(prefixSize-1);
    414                ObjectDesignator od =
    415                    TypeObjectDesignator.make(leftmostDot, tn);
    416                left = FieldAccess.make(od, n.identifierAt(prefixSize),
    417                                        n.locIdAt(prefixSize));
    418            }
    419
    420
    421            /*
    422             * Extend the prefix to the full n by using field dereferences:
    423             */
    424            for (; prefix<n.size(); prefix++) {
    425                left = FieldAccess.make(
    426                                ExprObjectDesignator.make(n.locDotAfter(prefix-1),
    427                                                          left),
    428                                n.identifierAt(prefix),
    429                                n.locIdAt(prefix));
    430            }
    431
    432            return left;
    433        }
    434
    435        public Object disambiguateTypeOrFieldName(/*@ non_null */ Name n) {
    436            /*
    437             * Find the smallest prefix of n, n[0]..n[prefix-1], such that
    438             * it denotes an Expr, call it left:
    439             */
    440            Expr left = null;
    441            Identifier leftmost = n.identifierAt(0);
    442            int leftmostLoc = n.getStartLoc();
    443
    444            ASTNode result = locateFieldOrLocal(leftmost);
    445            int prefix = 1;
    446            if (result instanceof GenericVarDecl) {
    447                // leftmost is a local variable:
    448                left = VariableAccess.make(leftmost, leftmostLoc,
    449                                           (GenericVarDecl)result);
    450            } else if (result instanceof TypeSig) {
    451                // leftmost is a field in class result:
    452                ObjectDesignator od = getObjectDesignator((TypeSig)result,
    453                                                          leftmostLoc);
    454                left = FieldAccess.make(od, leftmost, leftmostLoc);
    455            } else {
    456                // n *must* start with a typename then:
    457                TypeSig sig = findTypeNamePrefix(null, n, false); // FIXME - a caller for access checking?
    458                if (sig==null) return null;
    459                if (prefixSize==n.size()) return sig;
    460
    461                prefix = prefixSize+1;
    462                TypeName tn = TypeName.make(n.prefix(prefixSize));
    463                TypeSig.setSig(tn, sig);
    464                int leftmostDot = leftmostLoc;
    465                if (prefixSize>0)
    466                    leftmostDot = n.locDotAfter(prefixSize-1);
    467                ObjectDesignator od =
    468                    TypeObjectDesignator.make(leftmostDot, tn);
    469                left = FieldAccess.make(od, n.identifierAt(prefixSize),
    470                                        n.locIdAt(prefixSize));
    471            }
    472
    473
    474            /*
    475             * Extend the prefix to the full n by using field dereferences:
    476             */
    477            for (; prefix<n.size(); prefix++) {
    478                left = FieldAccess.make(
    479                                ExprObjectDesignator.make(n.locDotAfter(prefix-1),
    480                                                          left),
    481                                n.identifierAt(prefix),
    482                                n.locIdAt(prefix));
    483            }
    484
    485            return left;
    486        }
    487
    488
    489        /***************************************************
    490         *                                                 *
    491         * Routine names:                                  *
    492         *                                                 *
    493         **************************************************/
    494
    495        /**
    496         * Attempt to disambiguate an AmbiguousMethodInvocation.  Either
    497         * returns the disambiguated method invocation as an Expr or
    498         * reports a fatal error to ErrorSet if it does not denote
    499         * anything.<p>
    500         *
    501         * The result will always be a method invocation.<p>
    502         *
    503         * If a prefix of n is ambiguous because of multiple
    504         * import-on-demand declarations, a fatal error will result.
    505         *
    506         *
    507         * If n is a reference to a method m in lexically enclosing class
    508         * C, then the result will be of the form "[C.]this.m" if C's
    509         * instance methods are accessible and "C.m" otherwise.<p>
    510         *
    511         * (At this point we haven't decided which method m refers to so
    512         * we don't know if it is an instance method or not.)
    513         */
    514        public MethodInvocation disambiguateMethodName(
    515                                    /*@ non_null @*/ AmbiguousMethodInvocation inv) {
    516            ObjectDesignator where;     // Where the method comes from
    517
    518            Name n = inv.name;
    519            int size = n.size();
    520            int nStart = n.getStartLoc();
    521
    522
    523            /*
    524             * Handle the simple name case first:
    525             */
    526            if (n.size()==1) {
    527                Identifier id = n.identifierAt(0);
    528                TypeSig container = locateMethod(id);
    529                if (container==null)
    530                    ErrorSet.fatal(nStart,
    531                                   "No method named " + id + " is in scope here.");
    532
    533                where = getObjectDesignator(container, nStart);
    534            } else {
    535                /*
    536                 * Not a simple name; try preceeding name as an ExprName first:
    537                 */
    538                Name butRight = n.prefix(size-1);
    539                Expr e = disambiguateExprName(butRight);
    540                if (e != null)
    541                    where = ExprObjectDesignator.make(n.locDotAfter(size-2), e);
    542                else {
    543                    /*
    544                     * then try preceeding name as a TypeName:
    545                     */
    546                    TypeSig t = lookupTypeName(null,butRight); // FIXME - a caller for access checking?
    547                    if (t != null) {
    548                        TypeName tn = TypeName.make(butRight);
    549                        TypeSig.setSig(tn, t);
    550                        where = TypeObjectDesignator.make(n.locDotAfter(size-2),
    551                                                          tn);
    552                    } else {
    553                        /*
    554                         * Give up!
    555                         */
    556                        ErrorSet.fatal(nStart,
    557                            "Can't disambiguate method name " + n.printName());
    558                        where = null;     // keep compiler happy
    559                    }
    560                }
    561            }
    562
    563
    564            // Return <where>.rightmost(...):
    565            Identifier rightmost = n.identifierAt(size-1);
    566            int rightmostLoc = n.locIdAt(size-1);
    567            return MethodInvocation.make(where, rightmost, null, rightmostLoc,
    568                                         inv.locOpenParen, inv.args);
    569        }
    570
    571
    572        /***************************************************
    573         *                                                 *
    574         * Current/enclosing instances II:                 *
    575         *                                                 *
    576         **************************************************/
    577
    578        /**
    579         * Returns the innermost current or enclosing instance, or null
    580         * if none exists.
    581         */
    582        public TypeSig getInnermostInstance() {
    583            if (!isStaticContext())
    584                return getEnclosingClass();
    585            else
    586                return getEnclosingInstance();
    587        }
    588
    589
    590        /**
    591         * Are C's instance variables accessible? <p>
    592         *
    593         * If C is getEnclosingClass(), then this is equivalent to
    594         * isStaticContext().
    595         */
    596        public boolean canAccessInstance(/*@ non_null @*/ TypeSig C) {
    597            /*
    598             * C's instance variables are accessible iff C is one of our
    599             * current or enclosing instances:
    600             */
    601            for (TypeSig instance = getInnermostInstance();
    602                 instance != null;
    603                 instance = instance.getEnv(true).getEnclosingInstance()) {
    604                if (instance==C)
    605                    return true;
    606            }
    607
    608            return false;
    609        }
    610
    611
    612        /**
    613         * Attempt to locate a current or enclosing instance that has
    614         * type T. <p>
    615         *
    616         * If such exist, return an inferred "<actual class>.this" Expr
    617         * for the innermost such one; otherwise, return null.  The
    618         * location fields of the Expr will be set to loc.<p>
    619         *
    620         * Note: The returned instance may have be of a subtype of T.<p>
    621         */
    622        //@ requires loc != Location.NULL;
    623        public Expr lookupEnclosingInstance(/*@ non_null @*/ TypeSig T,
    624                                            int loc) {
    625            TypeSig instance;
    626
    627            // Find innermost satisfactory instance if it exists:
    628            for (instance = getInnermostInstance();
    629                 instance != null;
    630                 instance = instance.getEnv(true).getEnclosingInstance()) {
    631                if (instance.isSubtypeOf(T))
    632                    break;
    633            }
    634
    635            if (instance==null)
    636                return null;
    637
    638            return getInferredThisExpr(instance, loc);
    639        }
    640
    641
    642        /***************************************************
    643         *                                                 *
    644         * Finding where something is declared:            *
    645         *                                                 *
    646         **************************************************/
    647
    648        /**
    649         * Decorates LocalVarDecl and FormalParaDecl nodes to point to
    650         * the TypeSig of the type they are declared in. <p>
    651         *
    652         * Set by the EnvForLocals constructor.<p>
    653         */
    654        //@ invariant whereDecoration.decorationType == \type(TypeSig);
    655        protected static final ASTDecoration whereDecoration
    656            = new ASTDecoration("whereDecoration");
    657
    658
    659        /**
    660         * What type is a GenericVarDecl declared in? <p>
    661         *
    662         * Precondition: decl's type has been "parsed"; an Env containing
    663         * decl has been constructed.<p>
    664         */
    665        //@ requires (decl instanceof FieldDecl) ==> ((FieldDecl)decl).hasParent;
    666        //@ ensures \result != null;
    667        public static TypeSig whereDeclared(/*@ non_null @*/ GenericVarDecl decl) {
    668            TypeSig result;
    669
    670            if (decl instanceof FieldDecl) {
    671                TypeDecl parent = ((FieldDecl)decl).getParent();
    672                Assert.notNull(parent);
    673                result = TypeSig.getSig(parent);
    674            } else {
    675                // LocalVarDecl or FormalParaDecl left here:
    676                result = (TypeSig)whereDecoration.get(decl);
    677            }
    678
    679            Assert.notNull(result);          //@ nowarn Pre;
    680            return result;
    681        }
    682
    683
    684        /***************************************************
    685         *                                                 *
    686         * Expr-construction utility functions:            *
    687         *                                                 *
    688         **************************************************/
    689
    690        /**
    691         * Return an inferred ThisExpr for "[C.]this", using location loc. <p>
    692         *
    693         * The "C." part is omitted if C is the type of this (e.g.,
    694         * getEnclosingClass()).
    695         */
    696        //@ requires loc != Location.NULL;
    697        //@ ensures \result != null;
    698        public final ThisExpr getInferredThisExpr(/*@ non_null @*/ TypeSig C,
    699                                                  int loc) {
    700            ThisExpr newThis = ThisExpr.make((C == getEnclosingClass())
    701                                             ? null : C, loc);
    702            newThis.inferred = true;
    703
    704            return newThis;
    705        }
    706
    707
    708        /**
    709         * Return an inferred ObjectDesignator for use in a reference to
    710         * a possibly-instance member of class C from here. <p>
    711         *
    712         *
    713         * If C's instance variables are not accessible from this point
    714         * (see canAccessInstance(-)), then returns "C.". <p>
    715         *
    716         * Otherwise returns an inferred "[C.]this.".
    717         * (cf. getInferredThisExpr(-))
    718         *
    719         * loc is used as the location for the this. and C. parts.
    720         */
    721        //@ requires loc != Location.NULL;
    722        //@ ensures \result != null;
    723        public final ObjectDesignator getObjectDesignator(/*@ non_null @*/ TypeSig C,
    724                                                          int loc) {
    725            if (!canAccessInstance(C))
    726                return TypeObjectDesignator.make(loc, C);
    727            else
    728                return ExprObjectDesignator.make(loc,
    729                                                 getInferredThisExpr(C, loc));
    730        }
    731    }