001    /* Copyright (c) 2015, Jesper Öqvist <jesper.oqvist@cs.lth.se>
002     * All rights reserved.
003     *
004     * Redistribution and use in source and binary forms, with or without
005     * modification, are permitted provided that the following conditions are met:
006     *
007     * 1. Redistributions of source code must retain the above copyright notice,
008     * this list of conditions and the following disclaimer.
009     *
010     * 2. Redistributions in binary form must reproduce the above copyright notice,
011     * this list of conditions and the following disclaimer in the documentation
012     * and/or other materials provided with the distribution.
013     *
014     * 3. Neither the name of the copyright holder nor the names of its
015     * contributors may be used to endorse or promote products derived from this
016     * software without specific prior written permission.
017     *
018     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
022     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
028     * POSSIBILITY OF SUCH DAMAGE.
029     */
030    
031    /**
032     * Attributes for checking if a type argument is within the bounds of a given
033     * type variable.
034     */
035    aspect GenericBoundCheck {
036      /**
037       * @param bound the bounded type variable
038       * @param par a parameterization of the type for which the type variable
039       * occurs in the type parameter list
040       * @return {@code true} if this type is within the bounds of the parameter type
041       */
042      syn boolean TypeDecl.withinBounds(TypeDecl bound, Parameterization par) =
043          bound.boundOf(this, par);
044    
045      eq UnknownType.withinBounds(TypeDecl bound, Parameterization par) = false;
046    
047      eq WildcardType.withinBounds(TypeDecl bound, Parameterization par) = true;
048      eq WildcardExtendsType.withinBounds(TypeDecl bound, Parameterization par) =
049          bound.boundOf(extendsType(), par) || extendsType().boundOf(bound, par);
050      eq WildcardSuperType.withinBounds(TypeDecl bound, Parameterization par) =
051          bound.boundOf(superType(), par);
052    
053      /**
054       * Check if a type is in the bound of this type, given a specific
055       * parameterization of this type.
056       *
057       * See JLS SE7 $4.5
058       *
059       * @param argument argument type
060       * @param par a parameterization
061       * @return {@code true} if the argument type is in the bound of this type
062       */
063      syn boolean TypeDecl.boundOf(TypeDecl argument, Parameterization par) = false;
064    
065      eq TypeVariable.boundOf(TypeDecl argument, Parameterization par) {
066        for (int i = 0; i < getNumTypeBound(); ++i) {
067          TypeDecl bound = getTypeBound(i).type();
068          if (bound.usesTypeVariable()) {
069            Access substituted = bound.substitute(par);
070            substituted.setParent(this);
071            bound = substituted.type();
072          }
073          if (!argument.subtype(bound)) {
074            return false;
075          }
076        }
077        return true;
078      }
079    
080      syn boolean TypeDecl.boundOfWildcard(WildcardType type) = false;
081      eq TypeVariable.boundOfWildcard(WildcardType type) = true;
082    
083      syn boolean TypeDecl.boundOfWildcardExtends(WildcardExtendsType type) = false;
084      eq TypeVariable.boundOfWildcardExtends(WildcardExtendsType type) =
085          type.extendsType().subtype(this);
086    
087      syn boolean TypeDecl.boundOfWildcardSuper(WildcardSuperType type) = false;
088      eq TypeVariable.boundOfWildcardSuper(WildcardSuperType type) =
089          type.superType().subtype(this);
090    }
091