| 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).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
|\
| |
| | |
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
|
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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`.
|
| |
| |
| |
| |
| |
| |
| | |
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.
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
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
|
|\ \ \
| |/ /
|/| | |
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".
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
- 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
|
| |/ / /
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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-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.
|
|/ / / /
| | | |
| | | |
| | | |
| | | | |
Now when resetAllAttrs is gone, we can use a shorter name for the one
and only resetLocalAttrs.
|
|\ \ \ \
| |/ / /
|/| | | |
SI-8170 Fix regression in TypeRef#transform w. PolyTypes
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
Regressed in SI-8046 / edc9edb7, by my hand.
At the time, I noticed the problem: transform wasn't accounting
for the potential Poly-Type-ness of its argument, and this would
lead to under-substituted types. The commit comment of edc9edb7
shows an example.
But the remedy wasn't the right one. The root problem is
that a TypeMap over a PolyType can return one with cloned
type parameter symbols, which means we've lose the ability
to substitute the type arguments into the result.
This commit detects up front whether the type-under-transform
is a PolyType with the current TypeRef's type parameters, and
just runs the `asSeenFrom` over its result type.
|
|\ \ \ \
| |_|/ /
|/| | | |
SI-7322 Interpolator idents must be encoded
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
Otherwise, they are not found.
This matters for term names with a differential encoding.
Footnote, normally ident() encodes, but INTERPOLATIONID
is !isIdent, so that is not used here. Maybe that would
be the better improvement.
|
|\ \ \ \
| |/ / /
|/| | | |
Prohibit views targeting AnyVal
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
Library changes in Scala 2.10 mean that we are left with the
unfortunate situation of admitting:
scala> "": AnyVal
res0: AnyVal =
We already have explicit checks in place to prevent views
targeting `AnyRef`. This commit balances this out by prohibiting
`AnyVal`, as well.
The enclosed test shows that this case is now prevented. If multiple
implicits views are applicable, the ambiguity error is still raised;
these check comes right at the end. Maybe that ought to be changed,
but I don't think it matters too much.
I've also disabled this prohibition under -Xsource:2.10.
|
|\ \ \ \
| | | | |
| | | | | |
Newline after empty string interp
|
| | |/ /
| |/| |
| | | |
| | | |
| | | | |
Consume the newline non-raw for safe handling after
single-line interpolation.
|
|/ / /
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
The soundness hole was exploited in Scalaz. They have fixed their
codebase correctly for Scalac 7.1.x, but have less freedom to
break source compatiblity in 7.0.x.
After this commit, they could choose to compile that branch with
-Xsource:2.10
|
|\ \ \ |
|
| |\ \ \
| | | | |
| | | | | |
Fix bug with super-accessors / dependent types
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
Super-accessors are generated as `DefDef`'s with `EmptyTree` as a
placeholder for the RHS. This is filled in later in `Mixin` in
`completeSuperAccessor`.
A change in `Uncurry` (SI-6443 / 493197f), however, converted this
to a `{ EmptyTree }`, which evaded the pattern match in mixin.
This commit adds a special case to the dependent method treatment
in Uncurry to avoid generating redundant blocks.
|
| |\ \ \ \
| | | | | |
| | | | | | |
[nomaster] Backport variance validator performance fix
|
| | |/ / /
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
% time qbin/scalac test/files/pos/t8146-performance.scala
real 0m2.015s
user 0m2.892s
sys 0m0.215s
% time scalac-hash v2.10.3 test/files/pos/t8146-performance.scala
real 1m13.652s
user 1m14.245s
sys 0m0.508s
Cherry-picks one hunk from 882f8e64.
|
|\ \ \ \ \
| | | | | |
| | | | | | |
Merge 2.10.x
|
| |\| | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
Conflicts:
src/compiler/scala/tools/nsc/typechecker/Typers.scala
|
| | |/ / /
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
Names/Defaults eagerly transforms an application with temporaries
to maintain evaluation order, and dutifully changes owners of
symbols along the way.
However, if this approach doesn't work out, we throw away this
and try a auto-tupling. However, we an still witness symbols
owned by the temporaries.
This commit records which symbols are owned by the context.owner
before `transformNamedApplication`, and rolls back the changes
before `tryTupleApply`.
Perhaps a better approach would be to separate the names/defaults
applicability checks from the evaluation-order-preserving transform,
and only call the latter after we have decided to go that way.
|
| |\| | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
Check files updated: test/files/presentation/t8085*.check
Conflicts:
build.xml
src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
|
| | |\ \ \
| | | | | |
| | | | | | |
Fix inliner cycle with recursion, separate compilation
|
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
ICodeReaders, which decompiles JVM bytecode to ICode, was not
setting the `recursive` attribute of `IMethod`. This meant that
the inliner got into a cycle, repeatedly inlining the recursive
call.
The method name `filter` was needed to trigger this as the inliner
heuristically treats that as a more attractive inlining candidate,
based on `isMonadicMethod`.
This commit:
- refactors the checking / setting of `virtual`
- adds this to ICodeReaders
- tests the case involving `invokevirtual`
I'm not sure how to setup a test that fails without the other changes
to `ICodeReader` (for invokestatic and invokespecial).
|