Thread overview
Strange casting error when using lamdas
Dec 03, 2019
Robert M. Münch
Dec 03, 2019
Robert M. Münch
Dec 05, 2019
Robert M. Münch
Dec 05, 2019
Robert M. Münch
Dec 04, 2019
Robert M. Münch
December 03, 2019
I have very strange casting error I don't understand:

alias typeof(windows_message_streams[WM_MOUSEMOVE].filter!(win => (win.wParam & MK_LBUTTON))) WM_MOUSEMOVE_LBUTTON_TYPE;
WM_MOUSEMOVE_LBUTTON_TYPE WM_MOUSEMOVE_LBUTTON_STREAM;
pragma(msg,typeof(WM_MOUSEMOVE_LBUTTON_STREAM));

>> FilterObservable!(__lambda39, SubjectObject!(OS_State))

WM_MOUSEMOVE_LBUTTON_STREAM = cast(WM_MOUSEMOVE_LBUTTON_TYPE)(windows_message_streams[WM_MOUSEMOVE].filter!(win => (win.wParam & MK_LBUTTON)));
pragma(msg,typeof(wstreams[WM_MOUSEMOVE].filter!(win => (win.wParam & MK_LBUTTON))));

>> FilterObservable!(__lambda7, SubjectObject!(OS_State))

..\..\gui.d(317,104): Error: cannot cast expression filter(windows_message_streams[512u]) of type FilterObservable!(__lambda6, SubjectObject!(OS_State)) to FilterObservable!(__lambda39, SubjectObject!(OS_State)) because of different sizes
FilterObservable!(__lambda7, SubjectObject!(OS_State))

My code worked in the past but now it doesn't and I don't know why. I don't understand the "because of different sizes" message.

It looks like I have to explicitly create a lambda and re-use it. But how to do that?

-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster

December 03, 2019
On 2019-12-03 16:34:43 +0000, Robert M. Münch said:

> I have very strange casting error I don't understand:
> 
> alias typeof(windows_message_streams[WM_MOUSEMOVE].filter!(win => (win.wParam & MK_LBUTTON))) WM_MOUSEMOVE_LBUTTON_TYPE;
> WM_MOUSEMOVE_LBUTTON_TYPE WM_MOUSEMOVE_LBUTTON_STREAM;
> pragma(msg,typeof(WM_MOUSEMOVE_LBUTTON_STREAM));
> 
>>> FilterObservable!(__lambda39, SubjectObject!(OS_State))
> 
> WM_MOUSEMOVE_LBUTTON_STREAM = cast(WM_MOUSEMOVE_LBUTTON_TYPE)(windows_message_streams[WM_MOUSEMOVE].filter!(win => (win.wParam & MK_LBUTTON)));
> pragma(msg,typeof(wstreams[WM_MOUSEMOVE].filter!(win => (win.wParam & MK_LBUTTON))));
> 
>>> FilterObservable!(__lambda7, SubjectObject!(OS_State))
> 
> ..\..\gui.d(317,104): Error: cannot cast expression filter(windows_message_streams[512u]) of type FilterObservable!(__lambda6, SubjectObject!(OS_State)) to FilterObservable!(__lambda39, SubjectObject!(OS_State)) because of different sizes
> FilterObservable!(__lambda7, SubjectObject!(OS_State))
> 
> My code worked in the past but now it doesn't and I don't know why. I don't understand the "because of different sizes" message.
> 
> It looks like I have to explicitly create a lambda and re-use it. But how to do that?

The first three lines are on module level, the second two lines are inside a class member function.

pragma(msg,WM_MOUSEMOVE_LBUTTON_STREAM.sizeof);

>> 8LU

but

pragma(msg,windows_message_streams[WM_MOUSEMOVE].filter!(win => (win.wParam & MK_LBUTTON)).sizeof);

>> 16LU

Why do these two things have different sizes even the declaration is exactly the same?

-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster

December 04, 2019
On 2019-12-03 16:34:43 +0000, Robert M. Münch said:

> I have very strange casting error I don't understand:
> 
> alias typeof(windows_message_streams[WM_MOUSEMOVE].filter!(win => (win.wParam & MK_LBUTTON))) WM_MOUSEMOVE_LBUTTON_TYPE;
> WM_MOUSEMOVE_LBUTTON_TYPE WM_MOUSEMOVE_LBUTTON_STREAM;
> pragma(msg,typeof(WM_MOUSEMOVE_LBUTTON_STREAM));
> 
>>> FilterObservable!(__lambda39, SubjectObject!(OS_State))
> 
> WM_MOUSEMOVE_LBUTTON_STREAM = cast(WM_MOUSEMOVE_LBUTTON_TYPE)(windows_message_streams[WM_MOUSEMOVE].filter!(win => (win.wParam & MK_LBUTTON)));
> pragma(msg,typeof(wstreams[WM_MOUSEMOVE].filter!(win => (win.wParam & MK_LBUTTON))));
> 
>>> FilterObservable!(__lambda7, SubjectObject!(OS_State))
> 
> ..\..\gui.d(317,104): Error: cannot cast expression filter(windows_message_streams[512u]) of type FilterObservable!(__lambda6, SubjectObject!(OS_State)) to FilterObservable!(__lambda39, SubjectObject!(OS_State)) because of different sizes
> FilterObservable!(__lambda7, SubjectObject!(OS_State))
> 
> My code worked in the past but now it doesn't and I don't know why. I don't understand the "because of different sizes" message.
> 
> It looks like I have to explicitly create a lambda and re-use it. But how to do that?

So, it all boils down to a breaking change in the RX framework... which I still don't understand...

-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster

December 04, 2019
On 12/3/19 12:35 PM, Robert M. Münch wrote:
> The first three lines are on module level, the second two lines are inside a class member function.
> 
> pragma(msg,WM_MOUSEMOVE_LBUTTON_STREAM.sizeof);
> 
>>> 8LU
> 
> but
> 
> pragma(msg,windows_message_streams[WM_MOUSEMOVE].filter!(win => (win.wParam & MK_LBUTTON)).sizeof);
> 
>>> 16LU
> 
> Why do these two things have different sizes even the declaration is exactly the same?
> 

Is one a delegate and one a function pointer? This can easily happen for untyped lambdas.

-Steve
December 05, 2019
On 2019-12-04 19:23:07 +0000, Steven Schveighoffer said:

> Is one a delegate and one a function pointer? This can easily happen for untyped lambdas.

That's a very good point and hint. A function pointer will be 8LU and a delegate 16LU, right? This is a strong argument that this is really the problem.

How can I find out? That's why I used a pragma to get the type of the alias. So, the alias needs to become a delegate. No clue how to write this down.


-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster

December 05, 2019
On 2019-12-04 19:23:07 +0000, Steven Schveighoffer said:

> Is one a delegate and one a function pointer? This can easily happen for untyped lambdas.

Not sure if the code-snippets already give an explanation but the differences I have are:

1. Working case

template filter(alias pred)
{
	auto filter(TObservable)(auto ref TObservable observable)
	{
       	static struct FilterObservable
       	{
				...
			}

			return FilterObservable(observable);
	}
}

2. Non-Working case

template filter(alias pred)
{
   auto filter(TObservable)(auto ref TObservable observable)
   {
       return FilterObservable!(pred, TObservable)(observable);
   }
}

struct FilterObservable(alias pred, TObservable)
{
	...
}

The constructor has the same implementaion in both cases.

-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster

December 05, 2019
On 12/5/19 3:57 AM, Robert M. Münch wrote:
> On 2019-12-04 19:23:07 +0000, Steven Schveighoffer said:
> 
>> Is one a delegate and one a function pointer? This can easily happen for untyped lambdas.
> 
> That's a very good point and hint. A function pointer will be 8LU and a delegate 16LU, right? This is a strong argument that this is really the problem.
> 
> How can I find out? That's why I used a pragma to get the type of the alias. So, the alias needs to become a delegate. No clue how to write this down.
> 
> 

Use std.functional.toDelegate. If it's already a delegate, it just returns the delegate, otherwise it makes a delegate out of a function pointer.

-Steve