Skip to content

Inline Method changes behavior for polymorphic method call #4425

Description

@EngTes1

Description

When using Inline Method on a method that is overridden in a subclass, VS Code Java performs the refactoring successfully, but the refactored program changes its runtime behavior.

The original program relies on dynamic dispatch. After inlining the superclass method body, the polymorphic method call is replaced with a fixed value, which breaks the original behavior.

Steps to reproduce

  1. Create the following Java code.
  2. Place the caret on method f in class A.
  3. Invoke Refactor -> Inline Method.
  4. Apply the inline refactoring.
  5. Run the program before and after refactoring.

Original code

package org.example;

public class Main {
    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new B();

        a1.test();
        a2.test();
    }
}

class A {

    int f() {
        return 1;
    }

    void test() {
        int x = f(); // Inline target
        System.out.println(x);
    }
}

class B extends A {
    @Override
    int f() {
        return 2;
    }
}

Actual behavior

VS Code Java performs the inline refactoring. The refactored program still compiles, but its runtime behavior changes.

Original output:

1
2

Refactored output:

1
1

Refactored code generated by VS Code Java:

package org.example;

public class Main {
    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new B();

        a1.test();
        a2.test();
    }
}

class A {

    void test() {
        int x = 1;
        System.out.println(x);
    }
}

class B extends A {
    @Override
    int f() {
        return 2;
    }
}

The inline refactoring replaces the polymorphic method call f() with the body of A.f(). However, the call inside A.test() is dynamically dispatched at runtime. When test() is invoked on an instance of B, the original program calls B.f() and prints 2.

After refactoring, this dynamic dispatch is removed, so both calls print 1.

Expected behavior

Inline Method should preserve the runtime behavior of the original program.

The refactoring should either:

  1. reject the inline operation, or
  2. report a warning/error indicating that inlining this method may change behavior because the method is overridden and the call is dynamically dispatched.

It should not silently generate behavior-changing code.

No activity

Activity on this issue will appear here.

Activity

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