sourcepawn icon indicating copy to clipboard operation
sourcepawn copied to clipboard

Rule on function prototypes mixed for any/int and ref/non-ref variables

Open FortyTwoFortyTwo opened this issue 1 year ago • 7 comments

In 1.11, for function prototypes you're able to mix between any and non-any variables and not able to mix between ref and non-ref, but in 1.12.0.7165 this rule seems to be all over the place on what's allowed and not allowed.

  • No longer able to assign &int param to &any callback, yet still able to assign int param to any callback as normal.
  • Able to mostly mix between ref and non-ref on param and callback

ReturnFunction in this test example are only used to silence unused variable warnings.

typedef CallbackCell = function void (any value);
typedef CallbackRef = function void (any &value);

public void OnPluginStart()
{
	// 4 tests below does not report error in 1.11
	
	CallbackCell cellany = CellAny;	// no error
	ReturnFunction(cellany);
	
	CallbackCell cellint = CellInt;	// no error
	ReturnFunction(cellint);
	
	CallbackRef refany = RefAny;	// no error
	ReturnFunction(refany);
	
	CallbackRef refint = RefInt;	// error
	ReturnFunction(refint);
	
	// 4 tests below does report error in 1.11
	
	CallbackCell badcellany = RefAny;	// no error
	ReturnFunction(badcellany);
	
	CallbackCell badcellint = RefInt;	// no error
	ReturnFunction(badcellint);
	
	CallbackRef badrefany = CellAny;	// no error
	ReturnFunction(badrefany);
	
	CallbackRef badrefint = CellInt;	// error
	ReturnFunction(badrefint);
}

void CellAny(any value) {}
void CellInt(int value) {}
void RefAny(any &value) {}
void RefInt(int &value) {}

Function ReturnFunction(Function func)
{
	return func;
}

FortyTwoFortyTwo avatar Oct 30 '24 13:10 FortyTwoFortyTwo

SourcePawn Compiler 1.11
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2021 AlliedModders LLC

test.sp(22) : error 100: function prototypes do not match
test.sp(25) : error 100: function prototypes do not match
test.sp(28) : error 100: function prototypes do not match
test.sp(31) : error 100: function prototypes do not match

dvander avatar Nov 29 '24 01:11 dvander

1.11 does correctly report these four as not matching, but 1.12 gives a different result, where it now errors at line 17 and no errors on line 22, 25, and 28.

This makes it that RefInt(int &value) can no longer be used on CallbackRef = function void (any &value), but can instead be used on CallbackCell = function void (any value). Which don't make sense for ref function &value not able to be used on ref callback &value, but can on non-ref callback value

SourcePawn Compiler 1.12.0.7165
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2021 AlliedModders LLC

42test.sp(17) : error 100: function prototypes do not match
    17 |         CallbackRef refint = RefInt;        // error
-----------------------------^

42test.sp(31) : error 100: function prototypes do not match
    31 |         CallbackRef badrefint = CellInt;        // error
-----------------------------^

FortyTwoFortyTwo avatar Nov 29 '24 18:11 FortyTwoFortyTwo

Thanks, my eyes glazed over on the first look. I've fixed the lack of errors which was definitely a serious bug.

Re: any& coercing to int&... I'm on the fence. I don't love it, but it's not really unsafe. If it's something legitimately useful to a lot of plugins, I'll consider it.

dvander avatar Nov 29 '24 22:11 dvander

Allowing this coercion affected 0 plugins in the corpus...

dvander avatar Nov 29 '24 22:11 dvander

In 1.12.0.7165 there is still support for any coercing to int, but now not any& coercing to int& which seems odd to me.

non-ref coercing is very helpful for functions like CreateTimer and RequestFrame, passing over data param. But for ref coercing I only had one case this occurred to me, and that's from my own typeset. Don't know if anyone else used it too.

FortyTwoFortyTwo avatar Nov 29 '24 23:11 FortyTwoFortyTwo

Do you have a testcase for non-ref coercing that doesn't work?

dvander avatar Nov 30 '24 00:11 dvander

I think non-ref coercing all works fine for both 1.11 and 1.12, able to use any on int. It's just the case of whenever to allow ref coercing in 1.12, like any& to int&.

typedef CallbackCell = function void (any value);
typedef CallbackRef = function void (any &value);

public void OnPluginStart()
{
	// coercing 'int' param to 'any' callback, works fine
	CallbackCell cellint = CellInt;
	ReturnFunction(cellint);
	
	// coercing 'int&' param to 'any&' callback, function prototypes do not match
	CallbackRef refint = RefInt;
	ReturnFunction(refint);
}

void CellInt(int value) {}
void RefInt(int &value) {}

Function ReturnFunction(Function func)
{
	return func;
}
SourcePawn Compiler 1.12.0.7170
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2024 AlliedModders LLC

42test.sp(11) : error 100: function prototypes do not match
    11 |         CallbackRef refint = RefInt;
-----------------------------^

FortyTwoFortyTwo avatar Nov 30 '24 14:11 FortyTwoFortyTwo