Skip to content

Incorrect overriden function call #2819

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
szd12 opened this issue Mar 1, 2024 · 2 comments · Fixed by #2822
Closed

Incorrect overriden function call #2819

szd12 opened this issue Mar 1, 2024 · 2 comments · Fixed by #2822
Labels

Comments

@szd12
Copy link

szd12 commented Mar 1, 2024

Bug description

Incorrect function will be called if a derived class does not have a function override.

Steps to reproduce

Paste this code into the AssemblyScript playground window at www.assemblyscript.org

export function fib(n: i32): i32 {
  return x.f(n);
}

class A {
  f(a:i32):i32 { return a+1; }
}
class B extends A {
  f(a:i32):i32 { return super.f(a)+10; }
}
class C extends B {
  f(a:i32):i32 { return super.f(a)+100; }
}
class D extends C {
}

let x:A = new D();

expected output:

fib(0) = 111
fib(1) = 112
fib(2) = 113
...

actual output:

fib(0) = 11
fib(1) = 12
fib(2) = 13
...

Note: It will work correctly, if you change the variable definition to this:

let x:D = new D();

or this:

let x:A = new C();

AssemblyScript version

v0.27.24

@szd12 szd12 added the bug label Mar 1, 2024
@HerrCai0907
Copy link
Member

Thanks for your report. It is a bug in compiler.

@szd12
Copy link
Author

szd12 commented Mar 1, 2024

I think the bogus code is in compiler.ts/finalizeOverrideStub

        // Also alias each extender inheriting this exact overload
        let extenders = classInstance.extenders;
        if (extenders) {
          for (let _values = Set_values(extenders), i = 0, k = _values.length; i < k; ++i) {
            let extender = _values[i];
// bogus vvvvvvvv
            let instanceMembers = extender.prototype.instanceMembers;
            if (instanceMembers && instanceMembers.has(instance.declaration.name.text)) {
              continue; // skip those not inheriting
            }
            builder.addCase(extender.id, stmts);
// bogus ^^^^^^^
          }
        }

I recommend changing it into something like this:

        // Also alias each extender inheriting this exact overload
        let extenders = classInstance.extenders;
        if (extenders) {
          for (let _values = Set_values(extenders), i = 0, k = _values.length; i < k; ++i) {
            let extender = _values[i];
// fix vvvvvvvv
			for(;;) {	// going up the extension hierarchy
				let instanceMembers = extender.prototype.instanceMembers;
				if (instanceMembers && instanceMembers.has(instance.declaration.name.text)) {
				  break; // skip those not inheriting
				}
				if(extender.base == classInstance) {
					extender = _values[i];		// use original extender
					builder.addCase(extender.id, stmts);
					break;
				}
				extender = extender.base as Class;
			}
// fix ^^^^^^^
          }
        }

My project is running correctly after applying this change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants