| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
| |
A safer version of the fix for SI-6169 (#3471)
Only modify the skolems to avoid leaking the sharper bounds to `quantified`.
The included test case was minimized from akka-camel
(src/main/scala/akka/camel/Consumer.scala).
|
|\
| |
| | |
SI-8276 Test for cyclic error caused by (reverted) SI-1786 fix
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
We reverted SI-1786 recently on the grounds that its means of
avoiding cycles (not sharpening bounds of T[_] when T is
uninitialized) caused unacceptable non-determinism (well:
compilation order dependency) to type inference.
Nary a day later, @gkossakowski hit a regression in scala-io.
Bisection revealed that it stopped working in 2dbd17a2 and
started working agiain after the revert. How's that for
prescience!
I've distilled the cyclic error in scala-io in this test
case.
I'm yet to pinpoint this, followon error, which didn't survive
the shrink ray, and only appeared in the original code:
error: java.lang.IndexOutOfBoundsException: 0
at scala.collection.LinearSeqOptimized$class.apply(LinearSeqOptimized.scala:51)
at scala.collection.immutable.List.apply(List.scala:83)
at scala.reflect.internal.tpe.TypeMaps$AsSeenFromMap.correspondingTypeArgument(TypeMaps.scala:5
|
|/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In 2fa2db7840 I fixed a bug where applicable implicit conversions
would not be found for numeric types if one introduced any aliasing
or singleton types, for the usual reasons involving the absence of
uniform type normalization. See pos/t7228 for examples - that test
case has 20 errors in 2.10.3 but compiles in master.
An unintended side effect was making implicit search less oblivious.
It turns out that in so doing I had created ambiguity where there was
none before. Not because it was any more ambiguous, but because the
compiler now had the wits to notice the ambiguity at an earlier time.
The fix for this is not intuitive. The way the internal logic is,
we need to keep the wool over implicit search's eyes, which leads
to those unrecognized types being passed to adapt, where they are
recognized and weak subtyping suffices to be more specific. It is
sufficient for SI-7228 that weak subtyping be done correctly - the
other change, which is reverted here, was exposing the type arguments
of Function1 when a view exists as a subtype of Function1.
It is also possible this could be remedied by calling weak_<:<
somewhere which is presently <:<, but I don't know where and it
has a far greater chance of affecting something else than does
this, which is a straight reversion of a post-2.10.3 change.
|
|\
| |
| | |
SI-8134 SI-5954 Fix companions in package object under separate comp.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
I noticed that the pos/5954d was tripping a println "assertion".
This stemmed from an inconsistency between
`TypeRef#{parents, baseTypeSeq}` for a package objects compiled
from source that also has a class file from a previous compilation
run.
I've elevated the println to a devWarning, and changed
`updatePosFlags`, the home of this evil symbol overwriting,
to invalidate the caches in the symbols info. Yuck.
I believe that this symptom is peculiar to package objects because
of the way that the completer for packages calls `parents` during
the Namer phase for package objects, before we switch the symbol
to represent the package-object-from-source. But it seems prudent
to defensively invalidate the caches for any symbol that finds its
way into `updatePosFlags`.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
The tests cases enclosed exhibited two failures modes under
separate compilation.
1. When a synthetic companion object for a case- or implicit-class
defined in a package object is called for,
`Namer#ensureCompanionObject` is used to check for an explicitly
defined companion before decided to create a synthetic one.
This lookup of an existing companion symbol by `companionObjectOf`
would locate a symbol backed by a class file which was in the
scope of the enclosing package class. Furthermore, because the
owner of that symbol is the package object class that has now
been noted as corresponding to a source file in the current
run, the class-file backed module symbol is *also* deemed to
be from the current run. (This logic is in `Run#compiles`.)
Thinking the companion module already existed, no synthetic
module was created, which would lead to a crash in extension
methods, which needs to add methods to it.
2. In cases when the code explicitly contains the companion pair,
we still ran into problems in the backend whereby the class-file
based and source-file based symbols for the module ended up in
the same scope (of the package class). This tripped an assertion
in `Symbol#companionModule`.
We get into these problems because of the eager manner in which
class-file based package object are opened in `openPackageModule`.
The members of the module are copied into the scope of the enclosing
package:
scala> ScalaPackage.info.member(nme.List)
res0: $r#59116.intp#45094.global#28436.Symbol#29451 = value List#2462
scala> ScalaPackage.info.member(nme.PACKAGE).info.member(nme.List)
res1: $r#59116.intp#45094.global#28436.Symbol#29451 = value List#2462
This seems to require a two-pronged defense:
1. When we attach a pre-existing symbol for a package object symbol
to the tree of its new source, unlink the "forwarder" symbols
(its decls from the enclosing
package class.
2. In `Flatten`, in the spirit of `replaceSymbolInCurrentScope`,
remove static member modules from the scope of the enclosing
package object (aka `exitingFlatten(nestedModule.owner)`).
This commit also removes the warnings about defining companions
in package objects and converts those neg tests to pos (with
-Xfatal-warnings to prove they are warning free.)
Defining nested classes/objects in package objects still has
a drawback: you can't shift a class from the package to the
package object, or vice versa, in a binary compatible manner,
because of the `package$` prefix on the flattened name of
nested classes. For this reason, the `-Xlint` warning about
this remains. This issue is tracked as SI-4344.
However, if one heeds this warning and incrementatlly recompiles,
we no longer need to run into a DoubleDefinition error (which
was dressed up with a more specific diagnostic in SI-5760.)
The neg test case for that bug has been converted to a pos.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
This commit does not close SI-5900. It only addresses a regression
in 2.11 prereleases caused by SI-7886.
The fix for SI-7886 was incomplete (as shown by the last commit)
and incorrect (as shown by the regression in pos/t5900a.scala and
the fact it ended up inferring type parameters.)
I believe that the key to fixing this problem will be unifying
the inference of case class constructor patterns and extractor
patterns.
I've explored that idea:
https://gist.github.com/retronym/7704153
https://github.com/retronym/scala/compare/ticket/5900
But didn't quite get there.
|
|\ \
| | |
| | | |
SI-8244 Fix raw type regression under separate compilation
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
In #1901, handling of raw types encountered in signatures during class
file parsing was changed to work in the same manner as
`classExistentialType`, by using
`existentialAbstraction(cls.tparms, cls.tpe_*)`
But this never creates fresh existential symbols, and just sticks
the class type parameters it `quantified`:
scala> trait T[A <: String]
defined trait T
scala> val cls = typeOf[T[_]].typeSymbol
cls = trait T#101864
scala> cls.typeParams
res0 = List(type A#101865)
scala> cls.tpe_*
res1 = T#101864[A#101865]
scala> classExistentialType(cls)
res3 = T#101864[_ <: String#7209]
scala> val ExistentialType(quantified, result) = res3
List(type A#101865)
In the enclosed test case, this class type parameter was substituted
during `typeOf[X] memberType sym`, which led us unsoundly thinking
that `Raw[_]` was `Raw[X]`.
I've added a TODO comment to review the other usages of
`classExistentialType`.
Test variations include joint and separate compilation, and the
corresponding Scala-only code. All fail with type errors now,
as we expect. I've also added a distillation of a bootstrap
error that failed when I forgot to wrap the `existentialType`.
|
|/ /
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
[Most of this comment and the initial fix were implemented by Jason Zaugg.
I just cleaned it up a bit.]
After a soundness fix in SI-3873, instantiation of dependent
method type results behaved differently depending on whether the argument
from which we were propagating information had a stable type
or not. This is particular to substitution into singleton types
over the parameter in question.
If the argument was stable, it was substituted into singleton
types, such as the one below in the prefix in `a.type#B`
(which is the longhand version of `a.B`)
scala> class A { type B >: Null <: AnyRef }
defined class A
scala> object AA extends A { type B = String }
defined object AA
scala> def foo(a: A): a.B = null
foo: (a: A)a.B
scala> foo(AA)
res0: AA.B = null
But what if it isn't stable?
scala> foo({def a = AA; a: A { type B <: String}})
res1: a.B = null
This commit changes that to:
scala> foo({def a = AA; a: A { type B <: String}})
res1: A{type B <: String}#B = null
|
|\ \
| | |
| | | |
SI-8177 co-evolve more than just RefinedTypes
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
We look for any prefix that has a refinement class for a type symbol.
This includes ThisTypes, which were not considered before.
pos/t8177g.scala, neg/t0764*scala now compile, as they should
Additional test cases contributed by Jason & Paul.
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
`asSeenFrom` produced a typeref of the shape `T'#A` where `A` referred to a symbol
defined in a `T` of times past.
More precisely, the `TypeRef` case of `TypeMap`'s `mapOver` correctly modified a prefix
from having an underlying type of `{ type A = AIn }` to `{ type A = Int }`,
with a new symbol for `A` (now with info `Int`), but the symbol in the outer
`TypeRef` wasn't co-evolved (so it still referred to the `A` in `{ type A = AIn }`
underlying the old prefix).
`coEvolveSym` used to only look at prefixes that were directly `RefinedType`s,
but this bug shows they could also be `SingleType`s with an underlying `RefinedType`.
|
|\ \ \
| |/ /
|/| | |
A test case for a name binding progression
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
I noticed the change when adapting Slick to work with
Scala 2.11 in `AbstractSourceCodeGenerator.scala`.
The behaviour changed in a70c8219.
This commit locks down the new, correct behaviour with a test.
|
|\ \ \
| |/ /
|/| | |
SI-6736 Range.contains is wrong
|
| | |
| | |
| | |
| | |
| | |
| | | |
Operations are reasonable when they don't require indexing or conversion into a collection. These include head, tail, init, last, drop, take, dropWhile, takeWhile, dropRight, takeRight, span.
Tests added also to verify the new behavior.
|
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
Fix for SI-7475 in #3440 took care of this one.
I nixed the old (redundant) test cases and replaced by a single run/ test,
which didn't compile until.
|
|\ \ \
| | | |
| | | | |
SI-7475 Private members aren't inheritable, findMember overhaul
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
It turns out `findMembers` has been a bit sloppy in recent
years and has returned private members from *anywhere* up the
base class sequence. Access checks usually pick up the slack
and eliminate the unwanted privates.
But, in concert with the "concrete beats abstract" rule in
`findMember`, the following mishap appeared:
scala> :paste
// Entering paste mode (ctrl-D to finish)
trait T { def a: Int }
trait B { private def a: Int = 0 }
trait C extends T with B { a }
// Exiting paste mode, now interpreting.
<console>:9: error: method a in trait B cannot be accessed in C
trait C extends T with B { a }
^
I noticed this when compiling Akka against JDK 8; a new private method
in the bowels of the JDK was enough to break the build!
It turns out that some finesse in needed to interpret SLS 5.2:
> The private modifier can be used with any definition or declaration
> in a template. They are not inherited by subclasses [...]
So, can we simply exclude privates from all but the first base class?
No, as that might be a refinement class! The following must be
allowed:
trait A { private def foo = 0; trait T { self: A => this.foo } }
This commit:
- tracks when the walk up the base class sequence passes the
first non-refinement class, and excludes private members
- ... except, if we are at a direct parent of a refinement
class itself
- Makes a corresponding change to OverridingPairs, to only consider
private members if they are owned by the `base` Symbol under
consideration. We don't need to deal with the subtleties of
refinements there as that code is only used for bona-fide classes.
- replaces use of `hasTransOwner` when considering whether a
private[this] symbol is a member.
The last condition was not grounded in the spec at all. The change
is visible in cases like:
// Old
scala> trait A { private[this] val x = 0; class B extends A { this.x } }
<console>:7: error: value x in trait A cannot be accessed in A.this.B
trait A { private[this] val x = 0; class B extends A { this.x } }
^
// New
scala> trait A { private[this] val x = 0; class B extends A { this.x } }
<console>:8: error: value x is not a member of A.this.B
trait A { private[this] val x = 0; class B extends A { this.x } }
^
Furthermore, we no longer give a `private[this]` member a free pass
if it is sourced from the very first base class.
trait Cake extends Slice {
private[this] val bippy = ()
}
trait Slice { self: Cake =>
bippy // BCS: Cake, Slice, AnyRef, Any
}
The different handling between `private` and `private[this]`
still seems a bit dubious.
The spec says:
> An different form of qualification is private[this]. A member M
> marked with this modifier can be accessed only from within the
> object in which it is defined. That is, a selection p.M is only
> legal if the prefix is this or O.this, for some class O enclosing
> the reference. In addition, the restrictions for unqualified
> private apply.
This sounds like a question of access, not membership. If so, we
should admit `private[this]` members from parents of refined types
in `FindMember`.
AFAICT, not too much rests on the distinction: do we get a
"no such member", or "member foo inaccessible" error? I welcome
scrutinee of the checkfile of `neg/t7475f.scala` to help put
this last piece into the puzzle.
One more thing: findMember does not have *any* code the corresponds
to the last sentence of:
> SLS 5.2 The modifier can be qualified with an identifier C
> (e.g. private[C]) that must denote a class or package enclosing
> the definition. Members labeled with such a modifier are accessible
> respectively only from code inside the package C or only from code
> inside the class C and its companion module (§5.4).
> Such members are also inherited only from templates inside C.
When I showed Martin this, he suggested it was an error in the
spec, and we should leave the access checking to callers of
that inherited qualified-private member.
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
Swathes of important logic are duplicated between `findMember`
and `findMembers` after they separated on grounds of irreconcilable
differences about how fast they should run:
d905558 Variation #10 to optimze findMember
fcb0c01 Attempt #9 to opimize findMember.
71d2ceb Attempt #8 to opimize findMember.
77e5692 Attempty #7 to optimize findMember
275115e Fixing problem that caused fingerprints to fail in
e94252e Attemmpt #6 to optimize findMember
73e61b8 Attempt #5 to optimize findMember.
04f0b65 Attempt #4 to optimize findMember
0e3c70f Attempt #3 to optimize findMember
41f4497 Attempt #2 to optimize findMember
1a73aa0 Attempt #1 to optimize findMember
This didn't actually bear fruit, and the intervening years have
seen the implementations drift.
Now is the time to reunite them under the banner of `FindMemberBase`.
Each has a separate subclass to customise the behaviour. This is
primarily used by `findMember` to cache member types and to assemble
the resulting list of symbols in an low-allocation manner.
While there I have introduced some polymorphic calls, the call sites
are only bi-morphic, and our typical pattern of compilation involves
far more `findMember` calls, so I expect that JIT will keep the
virtual call cost to an absolute minimum.
Test results have been updated now that `findMembers` correctly
excludes constructors and doesn't inherit privates.
Coming up next: we can actually fix SI-7475!
|
|\ \ \ \
| | | | |
| | | | | |
Revert "SI-1786 incorporate defined bounds in inference"
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
Have to revert because the stricter bounds that it inferred break e.g., slick.
(Backstop for that added as pos/t1786-counter.scala, as minimized by Jason)
Worse, the fix was compilation order-dependent.
There's a less invasive fix (SI-6169) that could be generalized
in `sharpenQuantifierBounds` (used in `skolemizeExistential`),
but I'd rather not mess with existentials at this point.
This reverts commit e28c3edda4dd405ed382227d2a688b799bf33c72.
Conflicts:
src/compiler/scala/tools/nsc/typechecker/Typers.scala
test/files/pos/t1786.scala
|
|/ / / /
| | | |
| | | |
| | | |
| | | |
| | | | |
Created to convince moors that certain code should compile, it
wound up flushing out some quite nutty behavior. Some day this
will compile rather than having an 11-failure checkfile.
|
|\ \ \ \
| | | | |
| | | | | |
changes the order of whitebox typechecks. yes, again.
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
My first attempt at SI-6992 was about having whitebox expansions first
typecheck against outerPt and only then verify that the result is compatible
with innerPt.
That was a nice try, but soon after it went live in 2.11.0-M8, we've got
multiple reports with problems - both shapeless and then in a week specs2
started having issues with their whitebox macros.
In shapeless, typecheck against outerPt screwed up type inference, which
was more or less fixable by explicit type annotations, so I decided to
wait a bit before jumping to conclusions.
However, in specs2 the problem was more insidious. After being typechecked
against outerPt, expansions were being implicitly converted to a type
that became incompatible with innerPt. This revealed a fatal flaw of the
implemented approach - if allowed to typecheck against outerPt first,
whitebox macros could never be robust.
Now realizing that "outerPt > innerPt" doesn't work, I nevertheless wasn't
looking forward to rolling that back to "innerPt > outerPt", because that
would revive SI-6992 and SI-8048 that are highly unintuitive, especially
the latter one.
Therefore, this commit combines the permissiveness of "... > innerPt"
approaches with the robustness of "innerPt > outerPt", introducing
"WildcardType > innerPt > outerPt".
|
| |/ / /
|/| | |
| | | |
| | | |
| | | |
| | | | |
Previously pq used pattern1 which required parens to be used in
alternative pattern. This commit tweaks it to allow pq"a | b"
syntax. Also adds some tests for alternative syntax.
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
- 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.
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
And the same for !=
If we tried to declare these signatures in non-fictional classes,
we would be chastised about collapsing into the "same signature after
erasure".
This will have an influence of typing, as the typechecking of
arguments is sensitive to overloading: if multiple variants are
feasible, the argument will be typechecked with a wildcard expected
type. So people inspecting the types of the arguments to `==` before
this change might have seen an interesting type for
`if (true) x else y`, but now the `If` will have type `Any`, as we
don't need to calculate the LUB.
I've left a TODO to note that we should really make `Any#{==, !=}`
non-final and include a final override in `AnyVal`. But I don't think
that is particularly urgent.
|
|\ \ \ \
| | | | |
| | | | | |
Make the Abstract* classes public.
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
Several weaknesses in the implementation converge and force multiply.
1) Type constructor inference is not persistent. During implicit search
it will give up after the first seen parent even if some deeper base type
(even another direct parent) would satisfy the search.
2) Type inference is not aware of access restrictions. Inferred types are
calculated with disregard for whether the inferred type is visible at
the point of inference. That means that package-private types - which may be
private for any number of good reasons, such as not wanting them to appear in
bytecode thus creating binary compatibility obligations - are not private.
There is no such thing as a qualified private type.
package p {
trait PublicInterface[T] { def foo(): Int }
private[p] trait ImplementationOnly[T] extends PublicInterface[T] { def foo(): Int = 1 }
class PublicClass extends ImplementationOnly[PublicClass]
}
package q {
object Test {
def f[A, CC[X]](xs: CC[A]): CC[A] = xs
def g = f(new p.PublicClass) // inferred type: p.ImplementationOnly[p.PublicClass]
def h = g.foo()
// Bytecode contains:
// public p.ImplementationOnly<p.PublicClass> g();
// public int h();
// 0: aload_0
// 1: invokevirtual #30 // Method g:()Lp/ImplementationOnly;
// 4: invokeinterface #33, 1 // InterfaceMethod p/ImplementationOnly.foo:()I
// 9: ireturn
}
}
3) The trait encoding leads to a proliferation of forwarder methods, so much so that
1.5 Mb of bytecode was taken off of the standard library size by creating abstract classes
which act as central mixin points so that leaf classes can inherit some methods the
old fashioned way rather than each receiving their own copy of every trait defined method.
This was done for 2.10 through the creation of the Abstract* classes, all of which were
given reduced visibility to keep them out of the API.
private[collection] class AbstractSeq extends ...
This achieved its intended goal very nicely, but also some unintended ones.
In combination with 1) above:
scala> val rand = new scala.util.Random()
rand: scala.util.Random = scala.util.Random@7f85a53b
// this works
scala> rand.shuffle(0 to 5)
res1: scala.collection.immutable.IndexedSeq[Int] = Vector(4, 0, 1, 2, 5, 3)
// and this doesn't! good luck reasoning that one out
scala> rand.shuffle(0 until 5)
<console>:9: error: Cannot construct a collection of type scala.collection.AbstractSeq[Int]
with elements of type Int based on a collection of type scala.collection.AbstractSeq[Int].
rand.shuffle(0 until 5)
^
// Somewhat comically, in scala 2.9 it was flipped: to failed (differently), until worked.
scala> scala.util.Random.shuffle(0 to 5)
<console>:8: error: type mismatch;
found : scala.collection.immutable.Range.Inclusive
required: ?CC[?T]
scala> scala.util.Random.shuffle(0 until 5)
res2: scala.collection.immutable.IndexedSeq[Int] = Vector(4, 3, 1, 2, 0)
In combination with 2) above:
scala> def f[A, CC[X]](xs: CC[A]): CC[A] = xs
f: [A, CC[X]](xs: CC[A])CC[A]
scala> var x = f(1 until 10)
x: scala.collection.AbstractSeq[Int] = Range(1, 2, 3, 4, 5, 6, 7, 8, 9)
// It has inferred a type for our value which it will not allow us to use or even to reference.
scala> var y: scala.collection.AbstractSeq[Int] = x
<console>:10: error: class AbstractSeq in package collection cannot be accessed in package collection
var y: scala.collection.AbstractSeq[Int] = x
^
// This one is a straight regression - in scala 2.9,
scala> var x = f(1 until 10)
x: scala.collection.immutable.IndexedSeq[Int] = Range(1, 2, 3, 4, 5, 6, 7, 8, 9)
Since 1) and 2) are essentially unfixable - at least by me - I propose
to ameliorate these regressions by attacking the symptoms at the leaves.
That means making all the Abstract* classes public - keeping in mind that
they must already be assumed to be in the binary compatibility footprint,
since they have been leaking throughout their existence. This only impacts
the inference of inaccessible collections types - it doesn't help with the
more serious issue with type inference.
|
|\ \ \ \ \
| | | | | |
| | | | | | |
SI-6260 Avoid double-def error with lambdas over value classes
|
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
- fix typo
- remove BRIDGE flag from the method that we promote from
a bridge to a bona-fide method
- note possibility for delambdafy to avoid the bridge method
creation in *all* cases.
- note inconsistency with anonymous class naming between
`-Ydelamdafy:{inline,method}`
|
| | |_|/ /
| |/| | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
Post-erasure of value classs in method signatures to the underlying
type wreaks havoc when the erased signature overlaps with the
generic signature from an overriden method. There just isn't room
for both. But we *really* need both; callers to the interface method
will be passing boxed values that the bridge needs to unbox and
pass to the specific method that accepts unboxed values.
This most commonly turns up with value classes that erase to
Object that are used as the parameter or the return type of
an anonymous function.
This was thought to have been intractable, unless we chose
a different name for the unboxed, specific method in the
subclass. But that sounds like a big task that would require
call-site rewriting, ala specialization.
But there is an important special case in which we don't need
to rewrite call sites. If the class defining the method is
anonymous, there is actually no need for the unboxed method;
it will *only* ever be called via the generic method.
I came to this realisation when looking at how Java 8 lambdas
are handled. I was expecting bridge methods, but found none.
The lambda body is placed directly in a method exactly matching
the generic signature.
This commit detects the clash between bridge and target,
and recovers for anonymous classes by mangling the name
of the target method's symbol. This is used as the bytecode
name. The generic bridge forward to that, as before, with
the requisite box/unbox operations.
|
|\ \ \ \ \
| | | | | |
| | | | | | |
SI-7570 top-level codegen for toolboxes
|
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
Provides a way to inject top-level classes, traits and modules into
toolbox universes.
Previously that was impossible, because compile and eval both wrap their
arguments into an enclosing method of a synthetic module, which makes it
impossible to later on refer to any definitions from the outside.
|
|\ \ \ \ \ \
| | | | | | |
| | | | | | | |
SI-6411 SI-7328 value class fixes for runtime reflection
|
| | | | | | | |
|
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | | |
This automatically brings performance fixes and correct handling of
values class / by-name params into the constructor land.
|
| | | | | | | |
|
| |/ / / / /
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
The `transformedType` method, which is used to bring Scala types to Java
world, was written in pre-valueclass times. Therefore, this method only
called transforms from erasure, uncurry and refChecks.
Now runtime reflection becomes aware of posterasure and as a consequence
methods, which have value classes in their signatures, can be called
without having to wrap them in catch-a-crash clause.
Another facet to this fix was the realization that value classes need
to be unwrapped, e.g. C(2) needs to be transformed to just 2, when they
are used naked in method signatures (i.e. `c` in `def foo(c: C)` needs
to be unwrapped, whereas `cs: List[C]`, `cs: C*` and even `cs: Array[C]`
do not).
|
|\ \ \ \ \ \
| | | | | | |
| | | | | | | |
SI-7933 REPL javax.script eval is cached result
|
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | | |
The problem is that the repl underneath the script engine evaluates input to
val res0..resN, so it is a one shot operation. To allow repetition,
compile(script) now returns a CompiledScript object whose eval method can be
called any number of times.
|
|\ \ \ \ \ \ \
| | | | | | | |
| | | | | | | | |
SI-8207 Allow import qualified by self reference
|
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | | |
This regressed in SI-6815 / #2374. We check if the result of
`typedQualifier(Ident(selfReference))` is a stable identifier
pattern. But we actually see the expansion to `C.this`, which
doesn't qualify.
This commit adds a special cases to `importSig` to compensate.
This is safe enough, because the syntax prevents the following:
scala> class C { import C.this.toString }
<console>:1: error: '.' expected but '}' found.
class C { import C.this.toString }
^
So loosening the check here doesn't admit invalid programs.
I've backed this up with a `neg` test.
The enclosed test also checks that we can use the self
reference in a singleton type, and as a qualifier in
a type selection (These weren't actually broken.)
Maybe it would be more principled to avoid expanding the self
reference in `typedIdent`. I can imagine that the current situation
is a pain for refactoring tools that try to implement a rename
refactoring, for example.
Seems a bit risky at the minute, but I've noted the idea
in a comment.
|
|\ \ \ \ \ \ \ \
| | | | | | | | |
| | | | | | | | | |
SI-6169 Refine java wildcard bounds using corresponding tparam
|
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | | |
Also fixes part of SI-8197. Necessary complement to SI-1786 (#2518),
because we now infer tighter bounds for RHSs to conform to.
When opening an existential, Java puts constraints in the typing environment
that are derived from the bounds on the type parameters of the existentially
quantified type, so let's do the same for existentials over java-defined
classes in skolemizeExistential...
Example from test case:
```
public class Exist<T extends String> {
// java helpfully re-interprets Exist<?> as Exist<? extends String>
public Exist<?> foo() { throw new RuntimeException(); }
}
```
In Scala syntax, given a java-defined `class C[T <: String]`, the
existential type `C[_]` is improved to `C[_ <: String]` before skolemization,
which models what Java does (track the bounds as type constraints in the typing environment)
(Also tried doing this once during class file parsing or
when creating the existential type, but that causes cyclic errors
because it happens too early.)
|
|\ \ \ \ \ \ \ \ \
| | | | | | | | | |
| | | | | | | | | | |
SI-8237 Avoid cyclic constraints when inferring hk type args
|
| | |_|_|_|_|/ / /
| |/| | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | | |
An `AppliedTypeVars` spawned from `HKTypeVar#applyArgs`
(necessarily) shares the same `TypeConstraints`.
But, we can have multiple ATVs based on a single HKTV floating
around during inference, and they can appear on both sides
of type relations. An example of this is traced out in
the enclosed test.
This commit avoids registering upper/lower bound constraints
when this is detected.
In the enclosed test, we end up with an empty set of constraints
for `?E`, which results in inference of Nothing, which is what
we expect.
I have also improved the printing of ATVs (to include the args)
and sharpened the log message when `solve` leaves type variables
instantiated to `NoType`, rather than some other type that doesn't
conform to the bounds. Both of these changes helped me to get
to the bottom of this ticket. The improved `ATV#toString` shows
up in some updated checkfiles.
The reported test has quite a checkered history:
- in 2.10.0 it worked, but more by good luck than good planning
- after the fix for SI-7226 / 221f52757aa6, it started crashing
- from 3bd897ba0054f (a merge from 2.10.x just before 2.11.0-M1)
we started getting a type inference failure, rather than a crash.
"no type parameters for method exists [...] because cyclic
instantiation".
- It still crashes in `isGround` in 2.10.3.
|