blob: bd6f7c5da17acc42e7952cd5334f102dd90f3fba [file] [log] [blame]
// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.keepanno.annotations;
/**
* Usage constraints for how a target is used and what must be kept.
*
* <p>Providing the constraints on how an item is being used allows shrinkers to optimize or remove
* aspects of the item that do not change that usage constraint.
*
* <p>For example, invoking a method reflectively does not use any annotations on that method, and
* it is safe to remove the annotations. However, it would not be safe to remove parameters from the
* method.
*/
public enum KeepConstraint {
/**
* Indicates that the target item is being looked up reflectively.
*
* <p>Looking up an item reflectively requires that it remains on its expected context, which for
* a method or field means it must remain on its defining class. In other words, the item cannot
* be removed or moved.
*
* <p>Note that looking up a member does not imply that the holder class of the member can be
* looked up. If both the class and the member need to be looked, make sure to have a target for
* both.
*
* <p>Note also that the item can be looked up within its context but no constraint is placed on
* its name, accessibility or any other properties of the item.
*
* <p>If assumptions are being made about other aspects, additional constraints and targets should
* be added to the keep annotation.
*/
LOOKUP,
/**
* Indicates that the name of the target item is being used.
*
* <p>This usage constraint is needed if the target is being looked up reflectively by using its
* name. Setting it will prohibit renaming of the target item.
*
* <p>Note that preserving the name of a member does not imply that the holder class of the member
* will preserve its qualified or simple name. If both the class and the member need to preserve
* their names, make sure to have a target for both.
*
* <p>Note that preserving the name of a member does not preserve the types of its parameters or
* its return type for methods or the type for fields.
*/
NAME,
/**
* Indicates that the visibility of the target must be at least as visible as declared.
*
* <p>Setting this constraint ensures that any (reflective) access to the target that is allowed
* remains valid. In other words, a public class, field or method must remain public. For a
* non-public target its visibility may be relaxed in the direction: {@code private ->
* package-private -> protected -> public}.
*
* <p>Note that this constraint does not place any restrictions on any other accesses flags than
* visibility. In particular, flags such a static, final and abstract may change.
*
* <p>Used together with {@link #VISIBILITY_RESTRICT} the visibility will remain invariant.
*/
VISIBILITY_RELAX,
/**
* Indicates that the visibility of the target must be at most as visible as declared.
*
* <p>Setting this constraint ensures that any (reflective) access to the target that would fail
* will continue to fail. In other words, a private class, field or method must remain private.
* Concretely the visibility of the target item may be restricted in the direction: {@code public
* -> protected -> package-private -> private}.
*
* <p>Note that this constraint does not place any restrictions on any other accesses flags than
* visibility. In particular, flags such a static, final and abstract may change.
*
* <p>Used together with {@link #VISIBILITY_RELAX} the visibility will remain invariant.
*/
VISIBILITY_RESTRICT,
/**
* Indicates that the visibility of the target must remain as declared.
*
* <p>Note that this constraint does not place any restrictions on any other accesses flags than
* visibility. In particular, flags such a static, final and abstract may change.
*
* <p>This is equivalent to using both {@link #VISIBILITY_RELAX} and {@link #VISIBILITY_RESTRICT}.
*/
VISIBILITY_INVARIANT,
/**
* Indicates that the class target is being instantiated reflectively.
*
* <p>This usage constraint is only valid on class targets.
*
* <p>Being instantiated prohibits reasoning about the class instances at compile time. In other
* words, the compiler must assume the class to be possibly instantiated at all times.
*
* <p>Note that the constraint {@link KeepConstraint#LOOKUP} is needed to reflectively obtain a
* class. This constraint only implies that if the class is referenced in the program it may be
* instantiated.
*/
CLASS_INSTANTIATE,
/**
* Indicates that the method target is being invoked reflectively.
*
* <p>This usage constraint is only valid on method targets.
*
* <p>To be invoked reflectively the method must retain the structure of the method. Thus, unused
* arguments cannot be removed. However, it does not imply preserving the types of its parameters
* or its return type. If the parameter types are being obtained reflectively then those need a
* keep target independent of the method.
*
* <p>Note that the constraint {@link KeepConstraint#LOOKUP} is needed to reflectively obtain a
* method reference. This constraint only implies that if the method is referenced in the program
* it may be reflectively invoked.
*/
METHOD_INVOKE,
/**
* Indicates that the field target is reflectively read from.
*
* <p>This usage constraint is only valid on field targets.
*
* <p>A field that has its value read from, requires that the field value must remain. Thus, if
* field remains, its value cannot be replaced. It can still be removed in full, be inlined and
* its value reasoned about at compile time.
*
* <p>Note that the constraint {@link KeepConstraint#LOOKUP} is needed to reflectively obtain
* access to the field. This constraint only implies that if a field is referenced then it may be
* reflectively read.
*/
FIELD_GET,
/**
* Indicates that the field target is reflectively written to.
*
* <p>This usage constraint is only valid on field targets.
*
* <p>A field that has its value written to, requires that the field value must be treated as
* unknown.
*
* <p>Note that the constraint {@link KeepConstraint#LOOKUP} is needed to reflectively obtain
* access to the field. This constraint only implies that if a field is referenced then it may be
* reflectively written.
*/
FIELD_SET,
/**
* Indicates that the target method can be replaced by an alternative definition at runtime.
*
* <p>This usage constraint is only valid on method targets.
*
* <p>Replacing a method implies that the concrete implementation of the target cannot be known at
* compile time. Thus, it cannot be moved or otherwise assumed to have particular properties.
* Being able to replace the method still allows the compiler to fully remove it if it is
* statically found to be unused.
*
* <p>Note also that no restriction is placed on the method name. To ensure the same name add
* {@link #NAME} to the constraint set.
*/
METHOD_REPLACE,
/**
* Indicates that the target field can be replaced by an alternative definition at runtime.
*
* <p>This usage constraint is only valid on field targets.
*
* <p>Replacing a field implies that the concrete implementation of the target cannot be known at
* compile time. Thus, it cannot be moved or otherwise assumed to have particular properties.
* Being able to replace the method still allows the compiler to fully remove it if it is
* statically found to be unused.
*
* <p>Note also that no restriction is placed on the field name. To ensure the same name add
* {@link #NAME} to the constraint set.
*/
FIELD_REPLACE,
/**
* Indicates that the target item must never be inlined or merged.
*
* <p>This ensures that if the item is actually used in the program it will remain in some form.
* For example, a method may still be renamed, but it will be present as a frame in stack traces
* produced by the runtime (before potentially being retraced). For classes, they too may be
* renamed, but will not have been merged with other classes or have their allocations fully
* eliminated (aka class inlining).
*
* <p>For members this also ensures that the field value or method body cannot be reasoned about
* outside the item itself. For example, a field value cannot be assumed to be a particular value,
* and a method cannot be assumed to have particular properties for callers, such as always
* throwing or a constant return value.
*/
NEVER_INLINE,
/**
* Indicates that the class hierarchy below the target class may be extended at runtime.
*
* <p>This ensures that new subtypes of the target class can later be linked and/or class loaded
* at runtime.
*
* <p>This does not ensure that the class remains if it is otherwise dead code and can be fully
* removed.
*
* <p>Note that this constraint does not ensure that particular methods remain on the target
* class. If methods or fields of the target class are being targeted by a subclass that was
* classloaded or linked later, then keep annotations are needed for those targets too. Such
* non-visible uses requires the same annotations to preserve as for reflective uses.
*/
CLASS_OPEN_HIERARCHY,
}