Skip to content

Commit d2b292f

Browse files
committed
incoherent cyclic references between synthesized members
``` trait T { val a: String ; val b: a.type } class C extends T { // a, b synthesized, but the a in b's type, a.type, refers to the original symbol, not the clone in C } ``` poking around ASF v memberInfo using lazy type completer to only do ASF when synth symbol should be there it seems symbols occurring in types of synthesized members do not get rebound to other synthesized symbols package <empty>#4 { abstract <defaultparam/trait> trait N#7352 extends scala#22.AnyRef#2378 { <method> <deferred> <mutable> <accessor> <triedcooking> <sub_synth> def N$_setter_$self_$eq#15011(x$1#15012: <empty>#3.this.N#7352): scala#23.this.Unit#2340; <method> <deferred> <mutable> <accessor> <triedcooking> <sub_synth> def N$_setter_$n_$eq#15013(x$1#15014: N#7352.this.self#7442.type): scala#23.this.Unit#2340; <method> def /*N*/$init$scala#7441(): scala#23.this.Unit#2340 = { () }; <method> <deferred> <stable> <accessor> <triedcooking> <sub_synth> def self#7442: <empty>#3.this.N#7352; N#7352.this.N$_setter_$self_$eq#15011(scala#22.Predef#1729.$qmark$qmark$qmark#6917); <method> <deferred> <stable> <accessor> <sub_synth> def n#7443: N#7352.this.self#7442.type; N#7352.this.N$_setter_$n_$eq#15013(N#7352.this.self#7442) }; abstract class M#7353 extends scala#22.AnyRef#2378 { <method> <triedcooking> def <init>#13465(): <empty>#3.this.M#7353 = { M#7353.super.<init>scala#2719(); () }; <method> <deferred> <stable> <accessor> <triedcooking> def self#13466: <empty>#3.this.N#7352; <method> <deferred> <stable> <accessor> def n#13467: M#7353.this.self#13466.type }; class C#7354 extends M#7353 with <empty>#3.this.N#7352 { <method> <stable> <accessor> <triedcooking> def self#15016: <empty>#3.this.N#7352 = C#7354.this.self #15015; <triedcooking> private[this] val self #15015: <empty>#3.this.N#7352 = _; <method> <stable> <accessor> def n#15018: C#7354.this.self#7442.type = C#7354.this.n #15017; <triedcooking> private[this] val n #15017: C#7354.this.self#7442.type = _; <method> <mutable> <accessor> <triedcooking> def N$_setter_$self_$eq#15019(x$1#15021: <empty>#3.this.N#7352): scala#23.this.Unit#2340 = C#7354.this.self #15015 = x$1#15021; <method> <mutable> <accessor> <triedcooking> def N$_setter_$n_$eq#15022(x$1#15025: C#7354.this.self#7442.type): scala#23.this.Unit#2340 = C#7354.this.n #15017 = x$1#15025; <method> def <init>#14997(): <empty>#3.this.C#7354 = { C#7354.super.<init>#13465(); () } } } [running phase pickler on dependent_rebind.scala] [running phase refchecks on dependent_rebind.scala] test/files/trait-defaults/dependent_rebind.scala:16: error: overriding field n#15049 in trait N#7352 of type C#7354.this.self#15016.type; value n #15017 has incompatible type; found : => C#7354.this.self#7442.type (with underlying type => C#7354.this.self#7442.type) required: => N#7352.this.self#7442.type class C extends M with N ^
1 parent f2f9a0e commit d2b292f

File tree

2 files changed

+26
-5
lines changed

2 files changed

+26
-5
lines changed

src/compiler/scala/tools/nsc/transform/Fields.scala

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,11 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
219219
}
220220
// if we don't cloneInfo, method argument symbols are shared between trait and subclasses --> lambalift proxy crash
221221
// TODO: use derive symbol variant?
222-
val clonedInfo = accessor.info.cloneInfo(clonedAccessor)
223-
val relativeInfo = clonedInfo.asSeenFrom(clazz.thisType, accessor.owner)
224-
// println(s"cloning accessor $accessor to $clazz / $clonedInfo -> $relativeInfo")
225-
clonedAccessor setInfo relativeInfo
222+
223+
// println(s"cloning accessor $accessor to $clazz / $clonedInfo -> $relativeInfo")
224+
clonedAccessor setInfo (new LazyType {
225+
override def complete(sym: Symbol) = sym setInfo ((clazz.thisType memberType accessor) cloneInfo clonedAccessor) // accessor.info.cloneInfo(clonedAccessor).asSeenFrom(clazz.thisType, accessor.owner)
226+
})
226227
}
227228

228229
// when considering whether to mix in the trait setter, forget about conflicts -- they will be reported for the getter
@@ -247,7 +248,10 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
247248
else if (accessorConflictsExistingVal(accessor) || isOverriddenAccessor(accessor, clazz)) Nil
248249
else if (accessor.isGetter && fieldMemoizationIn(accessor, clazz).needsField) {
249250
// add field if needed
250-
val field = clazz.newValue(accessor.localName, accessor.pos) setInfo fieldTypeForGetterIn(accessor, clazz.thisType)
251+
252+
val field = clazz.newValue(accessor.localName, accessor.pos) setInfo (new LazyType {
253+
override def complete(sym: Symbol) = sym setInfo fieldTypeForGetterIn(accessor, clazz.thisType)
254+
})
251255

252256
val newFlags = (
253257
(PrivateLocal | NEEDS_TREES)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// derived from test/files/pos/S5.scala
2+
3+
// compile with -uniqid to see a hint of the trouble
4+
trait N {
5+
// the symbol for self does not get rebound when synthesizing members in C
6+
val self: N = ???
7+
val n: self.type = self
8+
}
9+
10+
// uncomment extends clause for another bug
11+
abstract class M /*extends N*/ {
12+
val self: N
13+
val n: self.type
14+
}
15+
16+
class C extends M with N
17+

0 commit comments

Comments
 (0)