| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
| |
If a method type arg is inferred Any, warn about the
function and not the innocent arg.
|
|
|
|
| |
This was slated for removal in 2.12.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Infer missing parameter types for function literals passed
to higher-order overloaded methods by deriving the
expected argument type from the function types in the
overloaded method type's argument types.
This eases the pain caused by methods becoming overloaded
because SAM types and function types are compatible,
which used to disable parameter type inference because
for overload resolution arguments are typed without
expected type, while typedFunction needs the expected
type to infer missing parameter types for function literals.
It also aligns us with dotty. The special case for
function literals seems reasonable, as it has precedent,
and it just enables the special case in typing function
literals (derive the param types from the expected type).
Since this does change type inference, you can opt out
using the Scala 2.11 source level.
Fix scala/scala-dev#157
|
| |
|
|
|
|
|
|
|
|
| |
Trying to figure out if we can avoid adapting to SAM, and just
type them once and for all in typedFunction. Looks like overload
resolution requires SAM adaptation to happen in adapt.
Cleaned up while I was in the area.
|
|
|
|
|
|
|
|
| |
Go beyond refactoring and introduce some hooks and patch some
holes that will become acute when we set Sammy loose.
Expanding sam requires class as first parent: `addObjectParent`.
(Tested in pos/sam_ctor_arg.scala, coming next.)
|
|
|
|
|
|
|
|
|
|
| |
Initial work to change settings and test by Svyatoslav Ilinskiy
Thanks!
To avoid cycles during overload resolution (which showed up
during bootstrapping), and to improve performance, I've guarded
the detection of SAM types in `isCompatible` to cases when the
LHS is potentially compatible.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Typechecking a pattern that defines a pattern type variable
initially assigns abstract type symbol with open type bounds.
Later on, pattern type inference kicks in to sharpen the type
of the variable based on constraints imposed by the expected
type (ie, the type of scrutinee of the pattern.)
However, before inference does this, a `TypeRef` to the abstract
type symbol can be queried for its base type with respect to some
class, which leads to it populating an internal cache. This cache
becomes stale when the underlying symbol has its type mutated.
The repercussions of this meant that a subsequent call to `baseType`
gave the wrong result (`NoType`), which lead to an `asSeenFrom`
operation to miss out of substitution of a type variable. Note the
appearance of `A` in the old type errors in the enclosed test case.
This commit takes an approach similar to 286dafbd to invalidate
caches after the mutation. I've routed both bandaids through the
same first aid kit: I'm sure over time we'll add additional calls
to this method, and additional cache invalidations within it.
|
|\
| |
| |
| |
| |
| |
| |
| |
| |
| | |
all conflicts were because the changes changed code that
doesn't exist anymore in 2.12; they were resolved with
`git checkout --ours`
c201eac changed bincompat-forward.whitelist.conf but
I dropped the change in this merge because it refers
to AbstractPromise which no longer exists in 2.12
|
| | |
|
|\|
| |
| |
| | |
merge/2.11.x-to-2.12.x-20152307
|
| | |
|
|\| |
|
| | |
|
|\|
| |
| |
| | |
merge/2.11.x-to-2.12.x-20150501
|
| |
| |
| |
| |
| | |
This commit corrects many typos found in scaladocs and comments.
There's also fixed the name of a private method in ICodeCheckers.
|
|\| |
|
| |
| |
| |
| |
| |
| | |
If args to a method are alias types, dealias to see if they
contain Any before warning about inferring it. Similarly for
return and expected types.
|
|/
|
|
|
|
|
|
|
|
|
|
|
| |
Takes a leaf out of dotty's book [1] and makes `asSeenFrom`
transparently change the prefix from the package class to the
package object when needed.
This fixes generic subsitution during overload resolution, as
reported in SI-9074.
This subsumes the former fix for SI-6225, which is removed here.
[1] https://github.com/lampepfl/dotty/pull/282
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This commit corrects many typos found in scaladocs, comments and
documentation. It should reduce a bit number of PRs which fix one
typo.
There are no changes in the 'real' code except one corrected name of
a JUnit test method and some error messages in exceptions. In the case
of typos in other method or field names etc., I just skipped them.
Obviously this commit doesn't fix all existing typos. I just generated
in IntelliJ the list of potential typos and looked through it quickly.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Playing with Java 8 Streams from the repl showed
we weren't eta-expanding, nor resolving overloading for SAMs.
Also, the way Java uses wildcards to represent use-site variance
stresses type inference past its bendiness point (due to excessive existentials).
I introduce `wildcardExtrapolation` to simplify the resulting types
(without losing precision): `wildcardExtrapolation(tp) =:= tp`.
For example, the `MethodType` given by `def bla(x: (_ >: String)): (_ <: Int)`
is both a subtype and a supertype of `def bla(x: String): Int`.
Translating http://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/
into Scala shows most of this works, though we have some more work to do (see near the end).
```
scala> import java.util.Arrays
scala> import java.util.stream.Stream
scala> import java.util.stream.IntStream
scala> val myList = Arrays.asList("a1", "a2", "b1", "c2", "c1")
myList: java.util.List[String] = [a1, a2, b1, c2, c1]
scala> myList.stream.filter(_.startsWith("c")).map(_.toUpperCase).sorted.forEach(println)
C1
C2
scala> myList.stream.filter(_.startsWith("c")).map(_.toUpperCase).sorted
res8: java.util.stream.Stream[?0] = java.util.stream.SortedOps$OfRef@133e7789
scala> Arrays.asList("a1", "a2", "a3").stream.findFirst.ifPresent(println)
a1
scala> Stream.of("a1", "a2", "a3").findFirst.ifPresent(println)
a1
scala> IntStream.range(1, 4).forEach(println)
<console>:37: error: object creation impossible, since method accept in trait IntConsumer of type (x$1: Int)Unit is not defined
(Note that Int does not match Any: class Int in package scala is a subclass of class Any in package scala, but method parameter types must match exactly.)
IntStream.range(1, 4).forEach(println)
^
scala> IntStream.range(1, 4).forEach(println(_: Int)) // TODO: can we avoid this annotation?
1
2
3
scala> Arrays.stream(Array(1, 2, 3)).map(n => 2 * n + 1).average.ifPresent(println(_: Double))
5.0
scala> Stream.of("a1", "a2", "a3").map(_.substring(1)).mapToInt(_.parseInt).max.ifPresent(println(_: Int)) // whoops!
ReplGlobal.abort: Unknown type: <error>, <error> [class scala.reflect.internal.Types$ErrorType$, class scala.reflect.internal.Types$ErrorType$] TypeRef? false
error: Unknown type: <error>, <error> [class scala.reflect.internal.Types$ErrorType$, class scala.reflect.internal.Types$ErrorType$] TypeRef? false
scala.reflect.internal.FatalError: Unknown type: <error>, <error> [class scala.reflect.internal.Types$ErrorType$, class scala.reflect.internal.Types$ErrorType$] TypeRef? false
at scala.reflect.internal.Reporting$class.abort(Reporting.scala:59)
scala> IntStream.range(1, 4).mapToObj(i => "a" + i).forEach(println)
a1
a2
a3
```
|
|\
| |
| | |
SI-8806 Add lower bound check to Any lint
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
We already exclude the lint check for infer-any if
Any is somewhere explicit.
This commit adds lower bounds of type params to
the somewheres.
Motivated by:
```
scala> f"${42}"
<console>:8: warning: a type was inferred to be `Any`; this may indicate a programming error.
f"${42}"
^
res0: String = 42
```
|
| |
| |
| |
| |
| | |
MultiChoiceSetting and Xlint with its deprecated aliases is now a bit
simpler, but there's still room for improvement, as noted in comments.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Move code that manipulates the error buffers / reporters
into combinators in Context/ContextReporter.
Eventually, would like to statically know when we're in silent mode,
and only then use buffering (push buffering code down to BufferingReporter).
Simplify TryTwice; avoid capturing mutable var in closure.
Changed inSilentMode to no longer check `&& !reporter.hasErrors`;
disassembling optimized code showed that this was keeping the inliner
from inlining this method.
Introduce a couple more combinators:
- withFreshErrorBuffer
- propagatingErrorsTo
- propagateImplicitTypeErrorsTo
|
| | |
|
| |
| |
| |
| |
| |
| |
| | |
The overarching goal is to route all contextual reporting
through a single entry point: `context.reporter`.
The following commits take baby steps towards this goal.
|
| |
| |
| |
| |
| | |
All functionality that's closely tied to the error buffer should be in
`Context`'s reporting infrastructure. (called `ContextReporter`, soon to follow.)
|
|/
|
|
|
|
|
|
|
|
| |
In this case, `infer.issue -> context.issue`.
Forwarders are dead weight that cause bit rot.
They tend to acquire functionality,
clutter their defining interface and
dilute the purpose of the method they forward to.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Inline the forwarders from CompilationUnit, which should not affect behavior.
Since all forwarders lead to global.reporter, don't first navigate
to a compilation unit, only to then forward back to global.reporter.
The cleanup in the previous commits revealed a ton of confusion
regarding how to report an error.
This was a mechanical search/replace, which has low potential for messing
things up, since the list of available methods are disjoint between
`reporter` and `currentRun.reporting`. The changes involving `typer.context`
were done previously.
Essentially, there are three ways to report:
- via typer.context, so that reporting can be silenced (buffered)
- via global.currentRun.reporting, which summarizes (e.g., deprecation)
- via global.reporter, which is (mostly) stateless and straightforward.
Ideally, these should all just go through `global.currentRun.reporting`,
with the typing context changing that reporter to buffer where necessary.
After the refactor, these are the ways in which we report (outside of typer):
- reporter.comment
- reporter.echo
- reporter.error
- reporter.warning
- currentRun.reporting.deprecationWarning
- currentRun.reporting.incompleteHandled
- currentRun.reporting.incompleteInputError
- currentRun.reporting.inlinerWarning
- currentRun.reporting.uncheckedWarning
Before:
- c.cunit.error
- c.enclosingUnit.deprecationWarning
- context.unit.error
- context.unit.warning
- csymCompUnit.warning
- cunit.error
- cunit.warning
- currentClass.cunit.warning
- currentIClazz.cunit.inlinerWarning
- currentRun.currentUnit.error
- currentRun.reporting
- currentUnit.deprecationWarning
- currentUnit.error
- currentUnit.warning
- getContext.unit.warning
- getCurrentCUnit.error
- global.currentUnit.uncheckedWarning
- global.currentUnit.warning
- global.reporter
- icls.cunit.warning
- item.cunit.warning
- reporter.comment
- reporter.echo
- reporter.error
- reporter.warning
- reporting.deprecationWarning
- reporting.incompleteHandled
- reporting.incompleteInputError
- reporting.inlinerWarning
- reporting.uncheckedWarning
- typer.context.unit.warning
- unit.deprecationWarning
- unit.echo
- unit.error
- unit.incompleteHandled
- unit.incompleteInputError
- unit.uncheckedWarning
- unit.warning
- v1.cunit.warning
All these methods ended up calling a method on `global.reporter`
or on `global.currentRun.reporting` (their interfaces are disjoint).
Also clean up `TypeDiagnostics`: inline nearly-single-use private methods.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This commit was co-authored with Lukas. His analysis is below.
If there are multiple applicable alternatives, drop those
that use default arguments. This is done indirectly by
checking applicability based on arity.
TODO: this `namesMatch` business is not spec'ed, and is
the wrong fix for SI-4592. We should instead clarify what
the spec means by "typing each argument with an undefined expected type".
What does typing a named argument entail when we don't know what
the valid parameter names are? (Since we're doing overload resolution,
there are multiple alternatives that can define different names.)
Luckily, the next step checks applicability to the individual alternatives,
so it knows whether an assignment is:
- a valid named argument
- a well-typed assignment (which doesn't necessarily have type `Unit`!)
- an error (e.g., rhs does not refer to a variable)
I propose the following solution (as a TODO):
check whether a named argument (when typing it in `doTypedApply`)
could be interpreted as an assign; `infer.checkNames` should use
the type of the well-typed assignment instead of `Unit`.
Lukas's analysis:
990fa04 misunderstood the spec of overloading resolution with
defaults. it should not discard applicable alternatives that define
defaults, but only those that use defaults in the given invocation.
bugs were shadowed because the refactoring used `alt.hasDefault` to
check whether the alternative has some parameters with defaults, but
this never worked.
d5bb19f fixed that part by checking the flags of parameters, which
fixed some but but un-shadowed others:
```
object t { def f(x: String = "") = 1; def f(x: Object) = 2 }
scala> t.f("") // should return 1, but returns 2 after d5bb19f
```
The commit message of d5bb19f also mentions that its test "should
fail to compile according to SI-4728", which is another
misunderstanding.
```
class A; class B extends A
object t { def f(x: A = null) = 1; def f(x: B*) = 2 }
t.f()
```
This should return `2`: both alternatives are applicable, so the one
that uses a default is eliminated, and we're left with the vararg one.
SI-4728 is different in that it uses explicit parameters,
`t.f(new B)` is ambiguous.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A recent commit fixed the behaviour of overloading with regards
to discarding candiates that include default arguments. The old
check was checking the wrong flag.
But, the new code is actually checking all parameter lists for
defaults, which led to a regression in scala-io, which is distilled
in the enclosed test case. Applications are typechecked one
parameter list at a time, so a holistic check for defaults doesn't
seem to make sense; only defaults in the first parameter list
ought to count.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The spec says
> Let B be the set of alternatives in A that are applicable (§6.6)
> [...] It is an error if none of the members in B is applicable. If
> there is one single applicable alternative, that alternative is
> chosen. Otherwise, let C be the set of applicable alternatives which
> don’t employ any default argument in the application to e1, ..., em.
> It is again an error if C is empty. Otherwise, one chooses the most
> specific alternative among the alternatives in C [...].
There are many ways to interpret this, but none of them involves
excluding default getters, which is what the old code was doing.
We now exclude all alternatives that define any default arguments.
NOTE: according to SI-4728, this should fail to compile with an
ambiguity error. The compiler has been accepting this program
for all of 2.10.x, as far as I can tell, so let's not change that
for 2.11.0-RC1...
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- Typer is created with Context.
- Typer creates an Inferencer with said Context.
- Typer mutates Typer#context after each import statement
- Typer mutates its current Context (e.g to disable implicits.)
- Typer asks a question of Inferencer
- Inferencer, looking at the old context, thinks that implicits
are allowed
- Inferencer saves implicit ambiguities into the wrong Context.
Because of this bug, overload resolution in blocks or template
bodies for applications that follow an import have been
considering implicit coercions in the first try at static overload
resolution, and, in the rare case that it encounters an ambigous
implicit in the process, leaking an unpositioned ambiguout error.
This commit ensures coherency between `typer.context` and
`typer.infer.context` by making the latter delegate to the former.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`isApplicableBasedOnArity` couldn't get of the ferris wheel after
as `followApply` kept insisting on another spin.
scala> ErrorType nonPrivateMember nme.apply
res0: $r.intp.global.Symbol = value apply
scala> res0.info
res1: $r.intp.global.Type = <error>
This commit makes `followApply` consider that an `ErrorType`
does not contain an `apply` member.
I also considered whether to do a deep check on the type
(`isErroneous`), but I can't motivate this with a test.
I tend to think we *shouldn't* do that: `List[${ErrorType}]`
still has an `apply` member that we should follow, right?
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
As usual, the hole has been exploited in the wild. While you
can't abstract over by-name-ness without running into the
ClassCastException or an un-applied Function0, there are cases
like the enclosed test where you can tiptoe around those
cases.
I've proposed a small change to Scalaz to avoid tripping over
this problem:
https://github.com/scalaz/scalaz/pull/562/files
But this commit I've also added a transitional flag, -Yinfer-by-name,
that they could use to back-publish older versions without code
changes. It is also an insurance policy for other projects that
might be exploiting the same hole.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Given:
def id[A](a: A): A = a
def foo(f: (=> Int) => Int) = ()
foo(id)
We eta-expanded `id` and inferred `A` to be `=> Int` to satisfy the
expected type set forth by the formal parameter `f`.
We really shouldn't go about inferring types that we can't *write*.
Our attempt to do so led promptly into a `ClassCastException` in the
enclosed test.
This commit:
- drops by-name-ness during `inferExprInstance`
- tests that this results in a type error for the reported bug
(neg/t7899)
- tests that a method with a by-name parameter can still be
eta expanded to match function with a corresponding by-name
parameter (run/t7899)
- discovers the same latent CCE in pos/t7584
- now that would be a type error
- so we compensate by using placeholder functions rather than
eta-expansion.
- and move that that test to `run` for good measure.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Reduced the amount of extraneous logging noise at the
default logging level.
Was brought to my usual crashing halt by the discovery of identical
logging statements throughout GenASM and elsewhere. I'm supposing
the reason people so grossly underestimate the cost of such duplication
is that most of the effects are in things which don't happen, aka
"silent evidence".
An example of a thing which isn't happening is the remainder of
this commit, which exists only in parallel universes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
It's the obvious translation from a raw Int into a value class.
It wasn't that long ago one could find a signature like this:
def merge(tps: List[Type], variance: Int, depth: Int): Type
Do you feel lucky, method caller? Well, do ya?
Anyway, now it is:
def merge(tps: List[Type], variance: Variance, depth: Depth): Type
Forget for a moment the fact that you'd probably rather not pass variance
for depth and depth for variance and look at the type signatures:
(List[Type], Variance, Depth) => Type
(List[Type], Int, Int) => Type
|
|
|
|
|
|
|
| |
This reverts commit 35122d6cda84bb2df69ca51c6b1b80e61693bf6f.
It also includes a test case embodying the reversion reason:
the test case no longer compiled. Parties interested in the
surrounding details may want to look at SI-7472.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
An extractor is no longer required to return Option[T], and
can instead return anything which directly contains methods
with these signatures:
def isEmpty: Boolean
def get: T
If the type of get contains methods with the names of
product selectors (_1, _2, etc.) then the type and arity
of the extraction is inferred from the type of get. If
it does not contain _1, then it is a single value
extractor analogous like Option[T].
This has significant benefits and opens new territory:
- an AnyVal based Option-like class can be used which
leverages null as None, and no allocations are necessary
- for primitive types the benefit is squared (see below)
- the performance difference between case classes and
extractors should now be largely eliminated
- this in turn allows us to recapture great swaths of
memory which are currently squandered (e.g. every
TypeRef has fields for pre and args, even though these
are more than half the time NoPrefix and Nil)
Here is a primitive example:
final class OptInt(val x: Int) extends AnyVal {
def get: Int = x
def isEmpty = x == Int.MinValue // or whatever is appropriate
}
// This boxes TWICE: Int => Integer => Some(Integer)
def unapply(x: Int): Option[Int]
// This boxes NONCE
def unapply(x: Int): OptInt
As a multi-value example, after I contribute some methods to TypeRef:
def isEmpty = false
def get = this
def _1 = pre
def _2 = sym
def _3 = args
Then it's extractor becomes
def unapply(x: TypeRef) = x
Which, it need hardly be said, involves no allocations.
|
|
|
|
|
|
|
| |
This method is right at the center of ALL KINDS of bad.
"this is quite nasty" begins the comment, and I credit its
deadpan understatement. A little logging is the least we
can offer the next guy.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Made the super unusual move (for me) of making a method longer
instead of shorter, because I had quite a time modifying the logic
as it was. Ideally we wouldn't use this method because it is much
less efficient than necessary. If one is typing a call like this:
def f(xs: Int*)
f(p1, p2, p3, ..., p500)
Then it is not necessary to create a list with 500 IntTpes. Once
you run out of non-varargs types, every argument which remains can
be typed against the vararg type directly.
|
|
|
|
|
|
|
|
| |
This exploits the infrastructure developed for checking the
checkability of type patterns to improve pattern type inference,
which suffered from a similar deficit. There was a hack for
SI-2486, the best I could manage at the time I wrote it; that
is replaced with the principled approach.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
I added a language.existential import to LazyCombiner.scala which
should not be necessary, but causes a spurious warning otherwise:
scala/src/library/scala/collection/parallel/mutable/LazyCombiner.scala:33:
warning: the existential type
scala.collection.parallel.mutable.LazyCombiner[_$1,_$2,_$3] forSome {
type _$1; type _$2; type _$3 <: scala.collection.generic.Growable[_$1] with scala.collection.generic.Sizing },
which cannot be expressed by wildcards, should be enabled by making the implicit value scala.language.existentials visible.
if (other.isInstanceOf[LazyCombiner[_, _, _]]) {
^
I created ticket SI-7750 to track this issue.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We have lots of core classes for which we need not go through
the symbol to get the type:
ObjectClass.tpe -> ObjectTpe
AnyClass.tpe -> AnyTpe
I updated everything to use the concise/direct version,
and eliminated a bunch of noise where places were calling
typeConstructor, erasedTypeRef, and other different-seeming methods
only to always wind up with the same type they would have received
from sym.tpe. There's only one Object type, before or after erasure,
with or without type arguments.
Calls to typeConstructor were especially damaging because (see
previous commit) it had a tendency to cache a different type than
the type one would find via other means. The two types would
compare =:=, but possibly not == and definitely not eq. (I still
don't understand what == is expected to do with types.)
|
|
|
|
|
| |
Oh exprTypeArgs, you will send us to the poorhouse with
your spendy ways. So many tuples have been dying needlessly.
|
| |
|
|
|
|
|
|
|
| |
Only to discover that it's really hard to move isCoercible
anywhere because it wants to call inferView which, despite its
suggestive name, is not visible in Infer. So I did what I
could and documented it a little.
|