27 |
27 |
28 import com.sun.tools.javac.util.*; |
28 import com.sun.tools.javac.util.*; |
29 import com.sun.tools.javac.util.List; |
29 import com.sun.tools.javac.util.List; |
30 import com.sun.tools.javac.code.*; |
30 import com.sun.tools.javac.code.*; |
31 import com.sun.tools.javac.code.Type.*; |
31 import com.sun.tools.javac.code.Type.*; |
|
32 import com.sun.tools.javac.code.Type.ForAll.ConstraintKind; |
32 import com.sun.tools.javac.code.Symbol.*; |
33 import com.sun.tools.javac.code.Symbol.*; |
33 import com.sun.tools.javac.util.JCDiagnostic; |
34 import com.sun.tools.javac.util.JCDiagnostic; |
34 |
35 |
35 import static com.sun.tools.javac.code.TypeTags.*; |
36 import static com.sun.tools.javac.code.TypeTags.*; |
36 |
37 |
48 /** A value for prototypes that admit any type, including polymorphic ones. */ |
49 /** A value for prototypes that admit any type, including polymorphic ones. */ |
49 public static final Type anyPoly = new Type(NONE, null); |
50 public static final Type anyPoly = new Type(NONE, null); |
50 |
51 |
51 Symtab syms; |
52 Symtab syms; |
52 Types types; |
53 Types types; |
|
54 Check chk; |
53 Resolve rs; |
55 Resolve rs; |
54 JCDiagnostic.Factory diags; |
56 JCDiagnostic.Factory diags; |
55 |
57 |
56 public static Infer instance(Context context) { |
58 public static Infer instance(Context context) { |
57 Infer instance = context.get(inferKey); |
59 Infer instance = context.get(inferKey); |
63 protected Infer(Context context) { |
65 protected Infer(Context context) { |
64 context.put(inferKey, this); |
66 context.put(inferKey, this); |
65 syms = Symtab.instance(context); |
67 syms = Symtab.instance(context); |
66 types = Types.instance(context); |
68 types = Types.instance(context); |
67 rs = Resolve.instance(context); |
69 rs = Resolve.instance(context); |
|
70 chk = Check.instance(context); |
68 diags = JCDiagnostic.Factory.instance(context); |
71 diags = JCDiagnostic.Factory.instance(context); |
69 ambiguousNoInstanceException = |
72 ambiguousNoInstanceException = |
70 new NoInstanceException(true, diags); |
73 new NoInstanceException(true, diags); |
71 unambiguousNoInstanceException = |
74 unambiguousNoInstanceException = |
72 new NoInstanceException(false, diags); |
75 new NoInstanceException(false, diags); |
248 public Type instantiateExpr(ForAll that, |
251 public Type instantiateExpr(ForAll that, |
249 Type to, |
252 Type to, |
250 Warner warn) throws InferenceException { |
253 Warner warn) throws InferenceException { |
251 List<Type> undetvars = Type.map(that.tvars, fromTypeVarFun); |
254 List<Type> undetvars = Type.map(that.tvars, fromTypeVarFun); |
252 for (List<Type> l = undetvars; l.nonEmpty(); l = l.tail) { |
255 for (List<Type> l = undetvars; l.nonEmpty(); l = l.tail) { |
253 UndetVar v = (UndetVar) l.head; |
256 UndetVar uv = (UndetVar) l.head; |
|
257 TypeVar tv = (TypeVar)uv.qtype; |
254 ListBuffer<Type> hibounds = new ListBuffer<Type>(); |
258 ListBuffer<Type> hibounds = new ListBuffer<Type>(); |
255 for (List<Type> l1 = types.getBounds((TypeVar) v.qtype); l1.nonEmpty(); l1 = l1.tail) { |
259 for (Type t : that.getConstraints(tv, ConstraintKind.EXTENDS).prependList(types.getBounds(tv))) { |
256 if (!l1.head.containsSome(that.tvars)) { |
260 if (!t.containsSome(that.tvars) && t.tag != BOT) { |
257 hibounds.append(l1.head); |
261 hibounds.append(t); |
258 } |
262 } |
259 } |
263 } |
260 v.hibounds = hibounds.toList(); |
264 List<Type> inst = that.getConstraints(tv, ConstraintKind.EQUAL); |
|
265 if (inst.nonEmpty() && inst.head.tag != BOT) { |
|
266 uv.inst = inst.head; |
|
267 } |
|
268 uv.hibounds = hibounds.toList(); |
261 } |
269 } |
262 Type qtype1 = types.subst(that.qtype, that.tvars, undetvars); |
270 Type qtype1 = types.subst(that.qtype, that.tvars, undetvars); |
263 if (!types.isSubtype(qtype1, to)) { |
271 if (!types.isSubtype(qtype1, to)) { |
264 throw unambiguousNoInstanceException |
272 throw unambiguousNoInstanceException |
265 .setMessage("no.conforming.instance.exists", |
273 .setMessage("no.conforming.instance.exists", |
271 |
279 |
272 // check bounds |
280 // check bounds |
273 List<Type> targs = Type.map(undetvars, getInstFun); |
281 List<Type> targs = Type.map(undetvars, getInstFun); |
274 targs = types.subst(targs, that.tvars, targs); |
282 targs = types.subst(targs, that.tvars, targs); |
275 checkWithinBounds(that.tvars, targs, warn); |
283 checkWithinBounds(that.tvars, targs, warn); |
276 return that.inst(targs, types); |
284 return chk.checkType(warn.pos(), that.inst(targs, types), to); |
277 } |
285 } |
278 |
286 |
279 /** Instantiate method type `mt' by finding instantiations of |
287 /** Instantiate method type `mt' by finding instantiations of |
280 * `tvars' so that method can be applied to `argtypes'. |
288 * `tvars' so that method can be applied to `argtypes'. |
281 */ |
289 */ |
347 minimizeInst((UndetVar) t, warn); |
355 minimizeInst((UndetVar) t, warn); |
348 |
356 |
349 /** Type variables instantiated to bottom */ |
357 /** Type variables instantiated to bottom */ |
350 ListBuffer<Type> restvars = new ListBuffer<Type>(); |
358 ListBuffer<Type> restvars = new ListBuffer<Type>(); |
351 |
359 |
|
360 /** Undet vars instantiated to bottom */ |
|
361 final ListBuffer<Type> restundet = new ListBuffer<Type>(); |
|
362 |
352 /** Instantiated types or TypeVars if under-constrained */ |
363 /** Instantiated types or TypeVars if under-constrained */ |
353 ListBuffer<Type> insttypes = new ListBuffer<Type>(); |
364 ListBuffer<Type> insttypes = new ListBuffer<Type>(); |
354 |
365 |
355 /** Instantiated types or UndetVars if under-constrained */ |
366 /** Instantiated types or UndetVars if under-constrained */ |
356 ListBuffer<Type> undettypes = new ListBuffer<Type>(); |
367 ListBuffer<Type> undettypes = new ListBuffer<Type>(); |
357 |
368 |
358 for (Type t : undetvars) { |
369 for (Type t : undetvars) { |
359 UndetVar uv = (UndetVar)t; |
370 UndetVar uv = (UndetVar)t; |
360 if (uv.inst.tag == BOT) { |
371 if (uv.inst.tag == BOT) { |
361 restvars.append(uv.qtype); |
372 restvars.append(uv.qtype); |
|
373 restundet.append(uv); |
362 insttypes.append(uv.qtype); |
374 insttypes.append(uv.qtype); |
363 undettypes.append(uv); |
375 undettypes.append(uv); |
364 uv.inst = null; |
376 uv.inst = null; |
365 } else { |
377 } else { |
366 insttypes.append(uv.inst); |
378 insttypes.append(uv.inst); |
377 final List<Type> inferredTypes = insttypes.toList(); |
389 final List<Type> inferredTypes = insttypes.toList(); |
378 final List<Type> all_tvars = tvars; //this is the wrong tvars |
390 final List<Type> all_tvars = tvars; //this is the wrong tvars |
379 final MethodType mt2 = new MethodType(mt.argtypes, null, mt.thrown, syms.methodClass); |
391 final MethodType mt2 = new MethodType(mt.argtypes, null, mt.thrown, syms.methodClass); |
380 mt2.restype = new ForAll(restvars.toList(), mt.restype) { |
392 mt2.restype = new ForAll(restvars.toList(), mt.restype) { |
381 @Override |
393 @Override |
|
394 public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) { |
|
395 for (Type t : restundet.toList()) { |
|
396 UndetVar uv = (UndetVar)t; |
|
397 if (uv.qtype == tv) { |
|
398 switch (ck) { |
|
399 case EXTENDS: return uv.hibounds; |
|
400 case SUPER: return uv.lobounds; |
|
401 case EQUAL: return uv.inst != null ? List.of(uv.inst) : List.<Type>nil(); |
|
402 } |
|
403 } |
|
404 } |
|
405 return List.nil(); |
|
406 } |
|
407 |
|
408 @Override |
382 public Type inst(List<Type> inferred, Types types) throws NoInstanceException { |
409 public Type inst(List<Type> inferred, Types types) throws NoInstanceException { |
383 List<Type> formals = types.subst(mt2.argtypes, tvars, inferred); |
410 List<Type> formals = types.subst(mt2.argtypes, tvars, inferred); |
384 if (!rs.argumentsAcceptable(capturedArgs, formals, |
411 if (!rs.argumentsAcceptable(capturedArgs, formals, |
385 allowBoxing, useVarargs, warn)) { |
412 allowBoxing, useVarargs, warn)) { |
386 // inferred method is not applicable |
413 // inferred method is not applicable |
387 throw invalidInstanceException.setMessage("inferred.do.not.conform.to.params", formals, argtypes); |
414 throw invalidInstanceException.setMessage("inferred.do.not.conform.to.params", formals, argtypes); |
388 } |
415 } |
389 // check that inferred bounds conform to their bounds |
416 // check that inferred bounds conform to their bounds |
390 checkWithinBounds(all_tvars, |
417 checkWithinBounds(all_tvars, |
391 types.subst(inferredTypes, tvars, inferred), warn); |
418 types.subst(inferredTypes, tvars, inferred), warn); |
392 return super.inst(inferred, types); |
419 return super.inst(inferred, types); |
393 }}; |
420 }}; |
394 return mt2; |
421 return mt2; |
395 } |
422 } |
396 else if (!rs.argumentsAcceptable(capturedArgs, mt.getParameterTypes(), allowBoxing, useVarargs, warn)) { |
423 else if (!rs.argumentsAcceptable(capturedArgs, mt.getParameterTypes(), allowBoxing, useVarargs, warn)) { |
397 // inferred method is not applicable |
424 // inferred method is not applicable |