use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.
the class Resolve method findInheritedMemberType.
/**
* Find a member type inherited from a superclass or interface.
* @param env The current environment.
* @param site The original type from where the selection takes
* place.
* @param name The type's name.
* @param c The class to search for the member type. This is
* always a superclass or implemented interface of
* site's class.
*/
Symbol findInheritedMemberType(Env<AttrContext> env, Type site, Name name, TypeSymbol c) {
Symbol bestSoFar = typeNotFound;
Symbol sym;
Type st = types.supertype(c.type);
if (st != null && st.hasTag(CLASS)) {
sym = findMemberType(env, site, name, st.tsym);
if (sym.kind < bestSoFar.kind)
bestSoFar = sym;
}
for (List<Type> l = types.interfaces(c.type); bestSoFar.kind != AMBIGUOUS && l.nonEmpty(); l = l.tail) {
sym = findMemberType(env, site, name, l.head.tsym);
if (bestSoFar.kind < AMBIGUOUS && sym.kind < AMBIGUOUS && sym.owner != bestSoFar.owner)
bestSoFar = new AmbiguityError(bestSoFar, sym);
else if (sym.kind < bestSoFar.kind)
bestSoFar = sym;
}
return bestSoFar;
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.
the class Resolve method mostSpecific.
/* Return the most specific of the two methods for a call,
* given that both are accessible and applicable.
* @param m1 A new candidate for most specific.
* @param m2 The previous most specific candidate.
* @param env The current environment.
* @param site The original type from where the selection
* takes place.
* @param allowBoxing Allow boxing conversions of arguments.
* @param useVarargs Box trailing arguments into an array for varargs.
*/
Symbol mostSpecific(List<Type> argtypes, Symbol m1, Symbol m2, Env<AttrContext> env, final Type site, boolean allowBoxing, boolean useVarargs) {
switch(m2.kind) {
case MTH:
if (m1 == m2)
return m1;
boolean m1SignatureMoreSpecific = signatureMoreSpecific(argtypes, env, site, m1, m2, allowBoxing, useVarargs);
boolean m2SignatureMoreSpecific = signatureMoreSpecific(argtypes, env, site, m2, m1, allowBoxing, useVarargs);
if (m1SignatureMoreSpecific && m2SignatureMoreSpecific) {
Type mt1 = types.memberType(site, m1);
Type mt2 = types.memberType(site, m2);
if (!types.overrideEquivalent(mt1, mt2))
return ambiguityError(m1, m2);
// one, or (d) merge both abstract signatures
if ((m1.flags() & BRIDGE) != (m2.flags() & BRIDGE))
return ((m1.flags() & BRIDGE) != 0) ? m2 : m1;
// if one overrides or hides the other, use it
TypeSymbol m1Owner = (TypeSymbol) m1.owner;
TypeSymbol m2Owner = (TypeSymbol) m2.owner;
if (types.asSuper(m1Owner.type, m2Owner) != null && ((m1.owner.flags_field & INTERFACE) == 0 || (m2.owner.flags_field & INTERFACE) != 0) && m1.overrides(m2, m1Owner, types, false))
return m1;
if (types.asSuper(m2Owner.type, m1Owner) != null && ((m2.owner.flags_field & INTERFACE) == 0 || (m1.owner.flags_field & INTERFACE) != 0) && m2.overrides(m1, m2Owner, types, false))
return m2;
boolean m1Abstract = (m1.flags() & ABSTRACT) != 0;
boolean m2Abstract = (m2.flags() & ABSTRACT) != 0;
if (m1Abstract && !m2Abstract)
return m2;
if (m2Abstract && !m1Abstract)
return m1;
// both abstract or both concrete
return ambiguityError(m1, m2);
}
if (m1SignatureMoreSpecific)
return m1;
if (m2SignatureMoreSpecific)
return m2;
return ambiguityError(m1, m2);
case AMBIGUOUS:
// compare m1 to ambiguous methods in m2
AmbiguityError e = (AmbiguityError) m2.baseSymbol();
boolean m1MoreSpecificThanAnyAmbiguous = true;
boolean allAmbiguousMoreSpecificThanM1 = true;
for (Symbol s : e.ambiguousSyms) {
Symbol moreSpecific = mostSpecific(argtypes, m1, s, env, site, allowBoxing, useVarargs);
m1MoreSpecificThanAnyAmbiguous &= moreSpecific == m1;
allAmbiguousMoreSpecificThanM1 &= moreSpecific == s;
}
if (m1MoreSpecificThanAnyAmbiguous)
return m1;
// more specific than m1, add it as a new ambiguous method:
if (!allAmbiguousMoreSpecificThanM1)
e.addAmbiguousSymbol(m1);
return e;
default:
throw new AssertionError();
}
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.
the class Attr method visitConditional.
public void visitConditional(JCConditional tree) {
Type condtype = attribExpr(tree.cond, env, syms.booleanType);
tree.polyKind = (!allowPoly || pt().hasTag(NONE) && pt() != Type.recoveryType || isBooleanOrNumeric(env, tree)) ? PolyKind.STANDALONE : PolyKind.POLY;
if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) {
// cannot get here (i.e. it means we are returning from void method - which is already an error)
resultInfo.checkContext.report(tree, diags.fragment("conditional.target.cant.be.void"));
result = tree.type = types.createErrorType(resultInfo.pt);
return;
}
ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ? unknownExprInfo : resultInfo.dup(new Check.NestedCheckContext(resultInfo.checkContext) {
// this will use enclosing check context to check compatibility of
// subexpression against target type; if we are in a method check context,
// depending on whether boxing is allowed, we could have incompatibilities
@Override
public void report(DiagnosticPosition pos, JCDiagnostic details) {
enclosingContext.report(pos, diags.fragment("incompatible.type.in.conditional", details));
}
});
Type truetype = attribTree(tree.truepart, env, condInfo);
Type falsetype = attribTree(tree.falsepart, env, condInfo);
Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(tree, truetype, falsetype) : pt();
if (condtype.constValue() != null && truetype.constValue() != null && falsetype.constValue() != null && !owntype.hasTag(NONE)) {
// constant folding
owntype = cfolder.coerce(condtype.isTrue() ? truetype : falsetype, owntype);
}
result = check(tree, owntype, VAL, resultInfo);
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.
the class Attr method visitReference.
@Override
public void visitReference(final JCMemberReference that) {
if (pt().isErroneous() || (pt().hasTag(NONE) && pt() != Type.recoveryType)) {
if (pt().hasTag(NONE)) {
// method reference only allowed in assignment or method invocation/cast context
log.error(that.pos(), "unexpected.mref");
}
result = that.type = types.createErrorType(pt());
return;
}
final Env<AttrContext> localEnv = env.dup(that);
try {
// attribute member reference qualifier - if this is a constructor
// reference, the expected kind must be a type
Type exprType = attribTree(that.expr, env, memberReferenceQualifierResult(that));
if (that.getMode() == JCMemberReference.ReferenceMode.NEW) {
exprType = chk.checkConstructorRefType(that.expr, exprType);
if (!exprType.isErroneous() && exprType.isRaw() && that.typeargs != null) {
log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()), diags.fragment("mref.infer.and.explicit.params"));
exprType = types.createErrorType(exprType);
}
}
if (exprType.isErroneous()) {
// if the qualifier expression contains problems,
// give up attribution of method reference
result = that.type = exprType;
return;
}
if (TreeInfo.isStaticSelector(that.expr, names)) {
// if the qualifier is a type, validate it; raw warning check is
// omitted as we don't know at this stage as to whether this is a
// raw selector (because of inference)
chk.validate(that.expr, env, false);
}
// attrib type-arguments
List<Type> typeargtypes = List.nil();
if (that.typeargs != null) {
typeargtypes = attribTypes(that.typeargs, localEnv);
}
Type desc;
Type currentTarget = pt();
boolean isTargetSerializable = resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK && isSerializable(currentTarget);
if (currentTarget != Type.recoveryType) {
currentTarget = types.removeWildcards(targetChecker.visit(currentTarget, that));
desc = types.findDescriptorType(currentTarget);
} else {
currentTarget = Type.recoveryType;
desc = fallbackDescriptorType(that);
}
setFunctionalInfo(localEnv, that, pt(), desc, currentTarget, resultInfo.checkContext);
List<Type> argtypes = desc.getParameterTypes();
Resolve.MethodCheck referenceCheck = rs.resolveMethodCheck;
if (resultInfo.checkContext.inferenceContext().free(argtypes)) {
referenceCheck = rs.new MethodReferenceCheck(resultInfo.checkContext.inferenceContext());
}
Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = null;
List<Type> saved_undet = resultInfo.checkContext.inferenceContext().save();
try {
refResult = rs.resolveMemberReference(localEnv, that, that.expr.type, that.name, argtypes, typeargtypes, referenceCheck, resultInfo.checkContext.inferenceContext(), resultInfo.checkContext.deferredAttrContext().mode);
} finally {
resultInfo.checkContext.inferenceContext().rollback(saved_undet);
}
Symbol refSym = refResult.fst;
Resolve.ReferenceLookupHelper lookupHelper = refResult.snd;
if (refSym.kind != MTH) {
boolean targetError;
switch(refSym.kind) {
case ABSENT_MTH:
targetError = false;
break;
case WRONG_MTH:
case WRONG_MTHS:
case AMBIGUOUS:
case HIDDEN:
case STATICERR:
case MISSING_ENCL:
case WRONG_STATICNESS:
targetError = true;
break;
default:
Assert.error("unexpected result kind " + refSym.kind);
targetError = false;
}
JCDiagnostic detailsDiag = ((Resolve.ResolveError) refSym.baseSymbol()).getDiagnostic(JCDiagnostic.DiagnosticType.FRAGMENT, that, exprType.tsym, exprType, that.name, argtypes, typeargtypes);
JCDiagnostic.DiagnosticType diagKind = targetError ? JCDiagnostic.DiagnosticType.FRAGMENT : JCDiagnostic.DiagnosticType.ERROR;
JCDiagnostic diag = diags.create(diagKind, log.currentSource(), that, "invalid.mref", Kinds.kindName(that.getMode()), detailsDiag);
if (targetError && currentTarget == Type.recoveryType) {
// a target error doesn't make sense during recovery stage
// as we don't know what actual parameter types are
result = that.type = currentTarget;
return;
} else {
if (targetError) {
resultInfo.checkContext.report(that, diag);
} else {
log.report(diag);
}
result = that.type = types.createErrorType(currentTarget);
return;
}
}
that.sym = refSym.baseSymbol();
that.kind = lookupHelper.referenceKind(that.sym);
that.ownerAccessible = rs.isAccessible(localEnv, that.sym.enclClass());
if (desc.getReturnType() == Type.recoveryType) {
// stop here
result = that.type = currentTarget;
return;
}
if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) {
if (that.getMode() == ReferenceMode.INVOKE && TreeInfo.isStaticSelector(that.expr, names) && that.kind.isUnbound() && !desc.getParameterTypes().head.isParameterized()) {
chk.checkRaw(that.expr, localEnv);
}
if (that.sym.isStatic() && TreeInfo.isStaticSelector(that.expr, names) && exprType.getTypeArguments().nonEmpty()) {
// static ref with class type-args
log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()), diags.fragment("static.mref.with.targs"));
result = that.type = types.createErrorType(currentTarget);
return;
}
if (that.sym.isStatic() && !TreeInfo.isStaticSelector(that.expr, names) && !that.kind.isUnbound()) {
// no static bound mrefs
log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()), diags.fragment("static.bound.mref"));
result = that.type = types.createErrorType(currentTarget);
return;
}
if (!refSym.isStatic() && that.kind == JCMemberReference.ReferenceKind.SUPER) {
// Check that super-qualified symbols are not abstract (JLS)
rs.checkNonAbstract(that.pos(), that.sym);
}
if (isTargetSerializable) {
chk.checkElemAccessFromSerializableLambda(that);
}
}
ResultInfo checkInfo = resultInfo.dup(newMethodTemplate(desc.getReturnType().hasTag(VOID) ? Type.noType : desc.getReturnType(), that.kind.isUnbound() ? argtypes.tail : argtypes, typeargtypes), new FunctionalReturnContext(resultInfo.checkContext));
Type refType = checkId(noCheckTree, lookupHelper.site, refSym, localEnv, checkInfo);
if (that.kind.isUnbound() && resultInfo.checkContext.inferenceContext().free(argtypes.head)) {
// re-generate inference constraints for unbound receiver
if (!types.isSubtype(resultInfo.checkContext.inferenceContext().asUndetVar(argtypes.head), exprType)) {
// cannot happen as this has already been checked - we just need
// to regenerate the inference constraints, as that has been lost
// as a result of the call to inferenceContext.save()
Assert.error("Can't get here");
}
}
if (!refType.isErroneous()) {
refType = types.createMethodTypeWithReturn(refType, adjustMethodReturnType(lookupHelper.site, that.name, checkInfo.pt.getParameterTypes(), refType.getReturnType()));
}
// go ahead with standard method reference compatibility check - note that param check
// is a no-op (as this has been taken care during method applicability)
boolean isSpeculativeRound = resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE;
// avoids recovery at this stage
that.type = currentTarget;
checkReferenceCompatible(that, desc, refType, resultInfo.checkContext, isSpeculativeRound);
if (!isSpeculativeRound) {
checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), desc, currentTarget);
}
result = check(that, currentTarget, VAL, resultInfo);
} catch (Types.FunctionDescriptorLookupError ex) {
JCDiagnostic cause = ex.getDiagnostic();
resultInfo.checkContext.report(that, cause);
result = that.type = types.createErrorType(pt());
return;
}
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.
the class Attr method checkReferenceCompatible.
@SuppressWarnings("fallthrough")
void checkReferenceCompatible(JCMemberReference tree, Type descriptor, Type refType, CheckContext checkContext, boolean speculativeAttr) {
Type returnType = checkContext.inferenceContext().asUndetVar(descriptor.getReturnType());
Type resType;
switch(tree.getMode()) {
case NEW:
if (!tree.expr.type.isRaw()) {
resType = tree.expr.type;
break;
}
default:
resType = refType.getReturnType();
}
Type incompatibleReturnType = resType;
if (returnType.hasTag(VOID)) {
incompatibleReturnType = null;
}
if (!returnType.hasTag(VOID) && !resType.hasTag(VOID)) {
if (resType.isErroneous() || new FunctionalReturnContext(checkContext).compatible(resType, returnType, types.noWarnings)) {
incompatibleReturnType = null;
}
}
if (incompatibleReturnType != null) {
checkContext.report(tree, diags.fragment("incompatible.ret.type.in.mref", diags.fragment("inconvertible.types", resType, descriptor.getReturnType())));
}
if (!speculativeAttr) {
List<Type> thrownTypes = checkContext.inferenceContext().asUndetVars(descriptor.getThrownTypes());
if (chk.unhandled(refType.getThrownTypes(), thrownTypes).nonEmpty()) {
log.error(tree, "incompatible.thrown.types.in.mref", refType.getThrownTypes());
}
}
}
Aggregations