winapirustwindows-rs

What does the error message "required by a bound in this" mean?


I have the following code:

use bindings::Windows::Win32::DisplayDevices::POINT;
use bindings::Windows::Win32::Gdi::{GetPixel, GetWindowDC, HDC};
use bindings::Windows::Win32::SystemServices::{BOOL, PSTR};
use bindings::Windows::Win32::WindowsAndMessaging::{self, FindWindowA, HWND};
use std::ffi::CString;

fn main() {
    let mut window_name_2 = "Window Title";
    let hwnd;

    unsafe { hwnd = FindWindowA(std::ptr::null_mut(), window_name_2) }
}

It produces the error:

bindings::Windows::Win32::WindowsAndMessaging
pub unsafe fn FindWindowA<'a, T0__, T1__>(lpclassname: T0__, lpwindowname: T1__) -> HWND
where
    T0__: ::windows::IntoParam<'a, super::superSystemServices::PSTR>,
    T1__: ::windows::IntoParam<'a, super::superSystemServices::PSTR>,
the trait bound `*mut _: windows::traits::into_param::IntoParam<'_, PSTR>` is not satisfied
the trait `windows::traits::into_param::IntoParam<'_, PSTR>` is not implemented for `*mut _`rustcE0277
main.rs(1, 1): required by a bound in this
windows.rs(311, 23): required by this bound in `FindWindowA`

I don't understand what this means or how to fix it.


Solution

  • Update for version 0.8.0

    Version 0.8.0 of the windows-rs crate switched to using impl Trait, making both the signatures easier to read, as well as decluttering the error diagnostics.

    Given the code in the question, the error message now reads:

    error[E0277]: the trait bound `*mut _: IntoParam<'_, PSTR>` is not satisfied
       --> src\main.rs:11:21
        |
    11  |     unsafe { hwnd = FindWindowA(std::ptr::null_mut(), window_name_2) }
        |                     ^^^^^^^^^^^ the trait `IntoParam<'_, PSTR>` is not implemented for `*mut _`
        | 
       ::: C:\...\target\debug\build\findwindow_test-67a9095d9a724f24\out/windows.rs:129:27
        |
    129 |             pub unsafe fn FindWindowA<'a>(
        |                           ----------- required by a bound in this
    130 |                 lpclassname: impl ::windows::IntoParam<'a, super::SystemServices::PSTR>,
        |                                   ----------------------------------------------------- required by this bound in `FindWindowA`
    

    The underlying issue is still the same as before (see below): The IntoParam trait isn't implemented for the combination of types involved. The previous solution (see below) is still valid, although version 0.8.0 also introduced a NULL constant, so the following will work as well:

    unsafe { hwnd = FindWindowA(PSTR::NULL, window_name_2) }
    

    The GitHub repository also introduce a FAQ with an entry on this specific topic (How do I read the signatures of generated functions and methods? What's with IntoParam?)


    The real error message is a fair bit more enlightening:

    error[E0277]: the trait bound `*mut _: IntoParam<'_, PSTR>` is not satisfied
       --> src\main.rs:11:21
        |
    11  |     unsafe { hwnd = FindWindowA(std::ptr::null_mut(), window_name_2) }
        |                     ^^^^^^^^^^^ the trait `IntoParam<'_, PSTR>` is not implemented for `*mut _`
        | 
       ::: C:\...\target\debug\build\findwindow_test-805b35ca49628608\out/windows.rs:117:27
        |
    117 |             pub unsafe fn FindWindowA<
        |                           ----------- required by a bound in this
    118 |                 'a,
    119 |                 T0__: ::windows::IntoParam<'a, super::SystemServices::PSTR>,
        |                       ----------------------------------------------------- required by this bound in `FindWindowA`
    

    It's telling you which parameter doesn't meet the requirements, i.e. T0__, the first one. It's failing to implement the IntoParam trait to convert *mut _ into a PSTR. The purpose of the IntoParam trait is to allow convenient conversions between Rust types (like &str) and ABI types (like PSTR).

    To solve this, you can construct a default PSTR instead, i.e.

    unsafe { hwnd = FindWindowA(PSTR::default(), window_name_2) }
    

    PSTR (currently) lives in Windows::Win32::SystemServices.