Skip to content

Regression: Typemap type mismatch in 1.34.0+ #60375

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
IslandUsurper opened this issue Apr 29, 2019 · 14 comments
Closed

Regression: Typemap type mismatch in 1.34.0+ #60375

IslandUsurper opened this issue Apr 29, 2019 · 14 comments
Labels
C-bug Category: This is a bug. P-high High priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@IslandUsurper
Copy link

I first reported this issue at gabdube/native-windows-gui#69, but discussion on Discord led me to file an issue here.

native-windows-ui stores data about the application (form controls, state, etc.) through a typemap. While my program worked on Rust 1.32.0 and 1.33.0, it breaks on 1.34.0 and 1.34.1. Sadly, this is a runtime error, and no backtrace is generated even with the RUST_BACKTRACE flag.

The error that is generated is native_windows_gui::Error::BadType.

@IslandUsurper
Copy link
Author

Ping: @dpc

@jonas-schievink jonas-schievink added C-bug Category: This is a bug. I-nominated regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 29, 2019
@Centril
Copy link
Contributor

Centril commented Apr 29, 2019

Sadly, this is a runtime error, and no backtrace is generated even with the RUST_BACKTRACE flag.

Would it be possible to paste the runtime error?

@dpc
Copy link
Contributor

dpc commented Apr 29, 2019

@IslandUsurper Did you want to ping the other dpc? 😄

@IslandUsurper
Copy link
Author

IslandUsurper commented Apr 30, 2019

@Centril, here's the error.

thread 'main' panicked at 'Failed to find a control: They key exists in the Ui, but the type requested did not match the type of the underlying object', src\libcore\result.rs:997:5

@dpc, sorry, are you not the dpc I was talking to on Discord? Who's the other one?

@Centril
Copy link
Contributor

Centril commented Apr 30, 2019

cc @Dylan-DPC ^---

@chinuno-usami
Copy link

Same problem while running the example in README of natice-windows-gui .
But I got backtrace log below.

thread 'main' panicked at 'Failed to find a control: The key exists in the Ui, but the type requested did not match the type of the underlying object', src\libcore\result.rs:997:5
stack backtrace:
   0: std::sys::windows::backtrace::set_frames
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\/src\libstd\sys\windows\backtrace\mod.rs:94
   1: std::sys::windows::backtrace::unwind_backtrace
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\/src\libstd\sys\windows\backtrace\mod.rs:81
   2: std::sys_common::backtrace::_print
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\/src\libstd\sys_common\backtrace.rs:70
   3: std::sys_common::backtrace::print
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\/src\libstd\sys_common\backtrace.rs:58
   4: std::panicking::default_hook::{{closure}}
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\/src\libstd\panicking.rs:200
   5: std::panicking::default_hook
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\/src\libstd\panicking.rs:215
   6: std::panicking::rust_panic_with_hook
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\/src\libstd\panicking.rs:478
   7: std::panicking::continue_panic_fmt
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\/src\libstd\panicking.rs:385
   8: std::panicking::rust_begin_panic
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\/src\libstd\panicking.rs:312
   9: core::panicking::panic_fmt
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\/src\libcore\panicking.rs:85
  10: core::result::unwrap_failed<native_windows_gui::error::Error>
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\src\libcore\macros.rs:17
  11: core::result::Result<core::cell::Ref<alloc::boxed::Box<native_windows_gui::controls::textinput::TextInput>>, native_windows_gui::error::Error>::expect<core::cell::Ref<alloc::boxed::Box<native_windows_gui::controls::textinput::TextInput>>,native_windows_gui::error::Error>
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\src\libcore\result.rs:825
  12: cuter_gui2::setup_ui::{{closure}}
             at .\src\main.rs:51
  13: native_windows_gui::ui::UiInner<cuter_gui2::AppId>::trigger<cuter_gui2::AppId>
             at C:\Users\cirno\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\native-windows-gui-0.2.0\src\ui.rs:359
  14: native_windows_gui::low::events::process_events<cuter_gui2::AppId>
             at C:\Users\cirno\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\native-windows-gui-0.2.0\src\low\events.rs:235
  15: Str_SetPtrW
  16: Ordinal411
  17: CallWindowProcW
  18: CallWindowProcW
  19: MapWindowPoints
  20: KiUserCallbackDispatcher
  21: NtUserMessageCall
  22: Exported
  23: SendMessageW
  24: SendMessageW
  25: Ordinal235
  26: SizeBoxHwnd
  27: CallWindowProcW
  28: CallWindowProcW
  29: Str_SetPtrW
  30: DefSubclassProc
  31: native_windows_gui::low::events::process_events<cuter_gui2::AppId>
             at C:\Users\cirno\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\native-windows-gui-0.2.0\src\low\events.rs:245
  32: Str_SetPtrW
  33: Ordinal411
  34: CallWindowProcW
  35: DispatchMessageW
  36: native_windows_gui::low::events::dispatch_events
             at C:\Users\cirno\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\native-windows-gui-0.2.0\src\low\events.rs:307
  37: native_windows_gui::ui::dispatch_events
             at C:\Users\cirno\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\native-windows-gui-0.2.0\src\ui.rs:797
  38: cuter_gui2::main
             at .\src\main.rs:75
  39: std::rt::lang_start::{{closure}}<()>
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\src\libstd\rt.rs:64
  40: std::rt::lang_start_internal::{{closure}}
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\/src\libstd\rt.rs:49
  41: std::panicking::try::do_call<closure,i32>
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\/src\libstd\panicking.rs:297
  42: panic_unwind::__rust_maybe_catch_panic
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\/src\libpanic_unwind\lib.rs:87
  43: std::panicking::try
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\/src\libstd\panicking.rs:276
  44: std::panic::catch_unwind
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\/src\libstd\panic.rs:388
  45: std::rt::lang_start_internal
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\/src\libstd\rt.rs:48
  46: std::rt::lang_start<()>
             at /rustc/fc50f328b0353b285421b8ff5d4100966387a997\src\libstd\rt.rs:64
  47: main
  48: invoke_main
             at f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:64
  49: __scrt_common_main_seh
             at f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:253
  50: BaseThreadInitThunk
  51: RtlUserThreadStart

OS : Windows 10 2016 ltsb (version 1607)
Toolchain:
stable-x86_64-pc-windows-msvc (default)
rustc 1.34.1 (fc50f32 2019-04-24)

The last frame in main is 12 , a nwg_get! macro call, defined as

/**
    Return controls from the Ui. Panics if one of the controls could not be retrieved.  
    
    
    To avoid the panic, use `ui.get` directly.

    Usage:  
    `let control = nwg_get!(ui; (control ID, control type))`  
    `let (control1, control2) = nwg_get!(ui; [(control1_ID, control1 type), (control2_ID, control2_type)])`  
*/
#[macro_export]
macro_rules! nwg_get {
    ( $ui:ident; ($n:expr, $t:ty) ) => {
        $ui.get::<$t>(&$n).expect("Failed to find a control")
    };

    ( $ui:ident; [ $( ($n:expr, $t:ty) ),* ] ) => {
        (
            $( $ui.get::<$t>(&$n).expect("Failed to find a control") ),*
        )
    }
}

@pnkfelix
Copy link
Member

pnkfelix commented May 2, 2019

triage: Not quite clear on what is going on here; maybe something with using TypeId as a key in a hashmap? Leaving unprioritized and nominated for now...

@nikomatsakis
Copy link
Contributor

It seems like what is really needed here is to try and narrow this to a standalone test case that is not reliant on TypeMap etc.

@nikomatsakis
Copy link
Contributor

triage: P-high

Behavorial regression, unknown cause, needs help to track down the problem.

@nikomatsakis nikomatsakis added P-high High priority and removed I-nominated labels May 9, 2019
@gabdube
Copy link

gabdube commented May 10, 2019

Hey this is my project. I'll try to isolate the problem to make it a bit easier to fix... hopefully.

@gabdube
Copy link

gabdube commented May 10, 2019

Ok I think I've found something. Hopefully it makes sense. It seems like there are two methods named "type_id" (one from Any and another from my ResourceT trait) available and the code. The method that insert the typeId use the wrong one.

For example, this code does not compile:

use std::any::Any;
use std::any::TypeId;

trait Resource {
}

trait ResourceT {
    fn type_id(&self) -> TypeId;
}

struct TestResourceT {
    value: u32
}

impl ResourceT for TestResourceT {
    fn type_id(&self) -> TypeId { TypeId::of::<TestResource>() }
}

struct TestResource {}

fn main() {
    let test = TestResourceT{ value: 10 };

    println!("{:?}", TypeId::of::<TestResource>());
    println!("{:?}", test.type_id());
}

The compiler will output

   Compiling nwg-test v0.1.0 (C:\Users\Gab\Documents\projects\success\nwg-test)
error[E0034]: multiple applicable items in scope
  --> src\main.rs:32:27
   |
32 |     println!("{:?}", test.type_id());
   |                           ^^^^^^^ multiple `type_id` found
   |
note: candidate #1 is defined in an impl of the trait `ResourceT` for the type `TestResourceT`
  --> src\main.rs:18:5
   |
18 |     fn type_id(&self) -> TypeId { TypeId::of::<TestResource>() }
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: candidate #2 is defined in an impl of the trait `std::any::Any` for the type `_`

That said, if you remove use std::any::Any; from the imports, everything works fine.

Here's a snippet that run the bogus code from native-windows-gui: https://gist.github.com/gabdube/ef27e073c209b23b06d794dca9982af2

Again, removing use std::any::Any fix the problem.

@jonas-schievink jonas-schievink added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. and removed T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 10, 2019
@steveklabnik
Copy link
Member

Triage: latest example still reproduces

@bstrie
Copy link
Contributor

bstrie commented Jul 3, 2021

I reduced the failing test case:

// This program compiles but asserts when std::any::Any is in scope,
// but compiles and runs successfully when it is not in scope.
use std::any::Any;

use std::any::TypeId;

trait Resource {
    fn type_id(&self) -> TypeId;
}

impl Resource for () {
    fn type_id(&self) -> TypeId { TypeId::of::<()>() }
}

fn main() {
    let tid_orig = TypeId::of::<()>();    
    
    let ref_res: &dyn Resource = &();
    let tid_from_ref = ref_res.type_id();
    
    let box_res: Box<dyn Resource> = Box::new(());
    let tid_from_box = box_res.type_id();
    
    dbg!(tid_orig, tid_from_ref, tid_from_box);
    
    assert_eq!(tid_orig, tid_from_ref); // passes
    assert_eq!(tid_orig, tid_from_box); // fails
}

Take note of the asserts; the failure only happens on boxed trait objects. It took me a while to realize that Any's blanket impl is only on T: 'static, so what's happening is that without Any in scope, method resolution autoderefs until it reaches <() as Resource>::type_id. But with Any in scope, it still autoderefs &dyn Resource (because it's not 'static) until it gets to <() as Resource>::type_id (at which point I would expect the compiler to emit an ambiguous name error, and it is very weird to me that it doesn't do so... a possible bug?)--but for Box<dyn Resource>, which is 'static, no autoderef happens and what is returned is the TypeId of Box<dyn Resource>.

So I don't think there's any action to be taken here. The behavior here is a consequence of trait objects, autoderef, and a blanket impl. 1.34 just happened to be the release when Any::type_id was stabilized. So while I do think that the failure to provide a static error on the &dyn Trait case could use investigation, otherwise it seems method resolution is working as intended.

@joshtriplett
Copy link
Member

We reviewed this in today's @rust-lang/libs meeting. Sorry that this took so long for us to get to!

This kind of issue is why we don't normally implement methods on Box or Rc or Arc, but Any has a blanket implementation for all static types. We talked this through, and we don't see any way around this; we'd recommend renaming the method, or calling it with the type explicitly named rather than using method syntax.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. P-high High priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests