Skip to content

Reference to field or property with explicit this in then block #2343

Open

Description

@eric-milles

Describe the bug

Making a reference to the spec's field or property using explicit-this in the then block produces an STC error. No error shows for this.myField in the when block.

this.myField in the then is written as $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(0), this).myField in the feature method. record returns Object, so as far as STC is concerned, it can't find the property "myField" in java.lang.Object.

Spock 2.4
Groovy 5.0.5

To Reproduce

@groovy.transform.TypeChecked
class SomeSpec extends Specification {
  String myField
  void testField() {
   when:
    this.myField = 'test'
   then:
    this.myField == 'test' // [Static type checking] - No such property: myField for class: java.lang.Object
  }
}

Expected behavior

this.myField checks properly or is exempted from STC in when, then, expect, etc.

Actual behavior

"[Static type checking] - No such property: myField for class: java.lang.Object"

Java version

Java 25.0.2

Buildtool version

Eclipse 2026-06 / Groovy 5.0.5

What operating system are you using

Windows

Activity

  1. Vampire commented on Apr 21, 2026

    @Vampire
    Member

    I don't think we support @TypeChecked or @CompileStatic but afair too much rely on Groovy duck-typing for this to work.
    Otherwise, I guess we probably need to sprinkle in type-casts in various places or make some methods generic instead of Object.

  2. eric-milles commented on Apr 21, 2026

    @eric-milles
    ContributorAuthor

    Not sure how record works, but if it was T <T> record(int i, T t) instead of Object record(int i, Object o) then you should get inferencing. Also, I'd need to look further to understand why the when block is okay. Might be a source position thing.

  3. Vampire commented on Apr 21, 2026

    @Vampire
    Member

    That's what I meant with "make some methods generic instead of Object", yes.
    But I somehow doubt that the record method is the only problematic part.

    In the when it is not a problem because it is not rewritten to be an assertion.
    It is just an assignment and stays like that.
    If you in the when write assert this.myField == 'test' you get the same problem there.

    I'm not saying we should not make the record generic.
    I'm just saying that there will most probably quite some other parts that are not compatible with STC.

  4. mvanhorn commented on Oct 10, 2026

    @mvanhorn

    Condition rewriting wraps the receiver in ValueRecorder.record, whose declared return type was Object. That signature discarded the receiver's static type, preventing the type checker from resolving its members.

    ValueRecorder.record now uses a type parameter for its argument and return value, preserving the recorded expression's static type without changing the recording logic. Regression coverage exercises properties and public fields across then, expect, and explicit assertions in when.

    #2435

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions