Static type when expecting dynamic type


(Howard Lovatt) #1

Hi All,

Anyone know what is going on here:

    //: Closure picks up static type not dynamic

    class MutableReference<T> {
        init() {
            guard type(of: self) != MutableReference.self else {
                fatalError("MutableReference is an abstract class; create a
derrivative of MutableReference")
            }
        }
        var value: T {
            get {
                fatalError("Calculated property value getter should be
overridden")
            }
            set {
                fatalError("Calculated property value setter should be
overridden")
            }
        }
    }

    class DefaultMutableReference<T>: MutableReference<T> {
        private var _value: T
        override var value: T {
            get {
                return _value
            }
            set {
                _value = newValue
            }
        }
        init(_ value: T) {
            _value = value
        }
    }

    let e: (MutableReference<[Int]>, Int) -> Void = { $0.value.append($1) }
    let dmr = DefaultMutableReference([2])
    dmr.value // [2]
    e(dmr, 2) // fatal error: Calculated property value getter should be
overridden
    dmr.value // Expect [2, 2]

If I change `e` to:
    let e: (DefaultMutableReference<[Int]>, Int) -> Void = {
$0.value.append($1) }

It works fine.

IE the closure is using the static type of its first argument and not
dynamically dispatching.

Am I doing something wrong? Is there a way round where I can still use the
base class for `e`?

Thanks for any help in advance,

-- Howard.


(Jordan Rose) #2

Seems like a bug, and moreover it seems like a regression from Swift 3.0. Mind filing a report at bugs.swift.org <http://bugs.swift.org/>?

Thanks!
Jordan

···

On Feb 1, 2017, at 20:49, Howard Lovatt via swift-users <swift-users@swift.org> wrote:

Hi All,

Anyone know what is going on here:

    //: Closure picks up static type not dynamic
    
    class MutableReference<T> {
        init() {
            guard type(of: self) != MutableReference.self else {
                fatalError("MutableReference is an abstract class; create a derrivative of MutableReference")
            }
        }
        var value: T {
            get {
                fatalError("Calculated property value getter should be overridden")
            }
            set {
                fatalError("Calculated property value setter should be overridden")
            }
        }
    }
    
    class DefaultMutableReference<T>: MutableReference<T> {
        private var _value: T
        override var value: T {
            get {
                return _value
            }
            set {
                _value = newValue
            }
        }
        init(_ value: T) {
            _value = value
        }
    }

    let e: (MutableReference<[Int]>, Int) -> Void = { $0.value.append($1) }
    let dmr = DefaultMutableReference([2])
    dmr.value // [2]
    e(dmr, 2) // fatal error: Calculated property value getter should be overridden
    dmr.value // Expect [2, 2]
If I change `e` to:

    let e: (DefaultMutableReference<[Int]>, Int) -> Void = { $0.value.append($1) }
It works fine.

IE the closure is using the static type of its first argument and not dynamically dispatching.

Am I doing something wrong? Is there a way round where I can still use the base class for `e`?

Thanks for any help in advance,

-- Howard.

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Slava Pestov) #3

The problem is were not marking the materializeForSet accessor in DefaultMutableReference.value as an override. Definitely a bug:

sil_vtable DefaultMutableReference {
  #MutableReference.init!initializer.1: _TFC1d23DefaultMutableReferencecfT_GS0_x_ // DefaultMutableReference.init() -> DefaultMutableReference<A>
  #MutableReference.value!getter.1: _TFC1d23DefaultMutableReferenceg5valuex // DefaultMutableReference.value.getter
  #MutableReference.value!setter.1: _TFC1d23DefaultMutableReferences5valuex // DefaultMutableReference.value.setter
  #MutableReference.value!materializeForSet.1: _TFC1d16MutableReferencem5valuex // MutableReference.value.materializeForSet
  #DefaultMutableReference.value!materializeForSet.1: _TFC1d23DefaultMutableReferencem5valuex // DefaultMutableReference.value.materializeForSet

The last entry should not exist.

I’ll have a fix shortly.

Slava

···

On Feb 2, 2017, at 9:04 AM, Jordan Rose via swift-users <swift-users@swift.org> wrote:

Seems like a bug, and moreover it seems like a regression from Swift 3.0. Mind filing a report at bugs.swift.org <http://bugs.swift.org/>?

Thanks!
Jordan

On Feb 1, 2017, at 20:49, Howard Lovatt via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

Hi All,

Anyone know what is going on here:

    //: Closure picks up static type not dynamic
    
    class MutableReference<T> {
        init() {
            guard type(of: self) != MutableReference.self else {
                fatalError("MutableReference is an abstract class; create a derrivative of MutableReference")
            }
        }
        var value: T {
            get {
                fatalError("Calculated property value getter should be overridden")
            }
            set {
                fatalError("Calculated property value setter should be overridden")
            }
        }
    }
    
    class DefaultMutableReference<T>: MutableReference<T> {
        private var _value: T
        override var value: T {
            get {
                return _value
            }
            set {
                _value = newValue
            }
        }
        init(_ value: T) {
            _value = value
        }
    }

    let e: (MutableReference<[Int]>, Int) -> Void = { $0.value.append($1) }
    let dmr = DefaultMutableReference([2])
    dmr.value // [2]
    e(dmr, 2) // fatal error: Calculated property value getter should be overridden
    dmr.value // Expect [2, 2]
If I change `e` to:

    let e: (DefaultMutableReference<[Int]>, Int) -> Void = { $0.value.append($1) }
It works fine.

IE the closure is using the static type of its first argument and not dynamically dispatching.

Am I doing something wrong? Is there a way round where I can still use the base class for `e`?

Thanks for any help in advance,

-- Howard.

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Howard Lovatt) #4

Thanks for your prompt responses.

Have filed a bug:

SR-3840 - Closure picks up static type not dynamic
<https://bugs.swift.org/browse/SR-3840>

  -- Howard.

···

On 3 February 2017 at 08:57, Slava Pestov <spestov@apple.com> wrote:

The problem is were not marking the materializeForSet accessor
in DefaultMutableReference.value as an override. Definitely a bug:

sil_vtable DefaultMutableReference {
  #MutableReference.init!initializer.1: _TFC1d23DefaultMutableReferencecfT_GS0_x_
    // DefaultMutableReference.init() -> DefaultMutableReference<A>
  #MutableReference.value!getter.1: _TFC1d23DefaultMutableReferenceg5valuex
  // DefaultMutableReference.value.getter
  #MutableReference.value!setter.1: _TFC1d23DefaultMutableReferences5valuex
  // DefaultMutableReference.value.setter
  #MutableReference.value!materializeForSet.1: _
TFC1d16MutableReferencem5valuex // MutableReference.value.
materializeForSet
  #DefaultMutableReference.value!materializeForSet.1: _
TFC1d23DefaultMutableReferencem5valuex // DefaultMutableReference.value.
materializeForSet

The last entry should not exist.

I’ll have a fix shortly.

Slava

On Feb 2, 2017, at 9:04 AM, Jordan Rose via swift-users < > swift-users@swift.org> wrote:

Seems like a bug, and moreover it seems like a regression from Swift 3.0.
Mind filing a report at bugs.swift.org?

Thanks!
Jordan

On Feb 1, 2017, at 20:49, Howard Lovatt via swift-users < > swift-users@swift.org> wrote:

Hi All,

Anyone know what is going on here:

    //: Closure picks up static type not dynamic

    class MutableReference<T> {
        init() {
            guard type(of: self) != MutableReference.self else {
                fatalError("MutableReference is an abstract class; create
a derrivative of MutableReference")
            }
        }
        var value: T {
            get {
                fatalError("Calculated property value getter should be
overridden")
            }
            set {
                fatalError("Calculated property value setter should be
overridden")
            }
        }
    }

    class DefaultMutableReference<T>: MutableReference<T> {
        private var _value: T
        override var value: T {
            get {
                return _value
            }
            set {
                _value = newValue
            }
        }
        init(_ value: T) {
            _value = value
        }
    }

    let e: (MutableReference<[Int]>, Int) -> Void = { $0.value.append($1) }
    let dmr = DefaultMutableReference([2])
    dmr.value // [2]
    e(dmr, 2) // fatal error: Calculated property value getter should be
overridden
    dmr.value // Expect [2, 2]

If I change `e` to:
    let e: (DefaultMutableReference<[Int]>, Int) -> Void = {
$0.value.append($1) }

It works fine.

IE the closure is using the static type of its first argument and not
dynamically dispatching.

Am I doing something wrong? Is there a way round where I can still use the
base class for `e`?

Thanks for any help in advance,

-- Howard.
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users