Skip to content

Parsing of the thread_local macro doesn't work #15585

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
sergey-tikhonenko opened this issue Sep 9, 2023 · 8 comments
Closed

Parsing of the thread_local macro doesn't work #15585

sergey-tikhonenko opened this issue Sep 9, 2023 · 8 comments
Labels
C-bug Category: bug

Comments

@sergey-tikhonenko
Copy link

sergey-tikhonenko commented Sep 9, 2023

Summary

Parsing of the thread_local macro doesn't work for me. Also the following methods don't work for the thread_local macro and the TLV variable:

  • rust-analyzer/expandMacro
  • textDocument/hover
  • textDocument/definition
  • textDocument/references

Looks like recursive macro expansion doesn't work, see output for detail. It returns the thread_local_inner macro instead of an expanded code.

Code

use std::cell::RefCell;

static V: RwLock<i32> = RwLock::new(1);
thread_local! {
    static TLV: RefCell<i32> = RefCell::new(1);
}
fn main() {
    assert_eq!(*V.read().unwrap(), 1);
    TLV.with(|tlv| assert_eq!(*tlv.borrow(), 1));
    println!("TLV: {TLV:?}");
}

Expand output

// ==============================================
// Recursive expansion of the thread_local! macro
// ==============================================

$crate::thread::local_impl::thread_local_inner!(TLV, RefCell<i32>, (RefCell::new(1)));

LSP log

[DEBUG][2023-09-09 01:18:10] .../lua/vim/lsp.lua:1492	"LSP[rust_analyzer]"	"client.request"	1	"rust-analyzer/expandMacro"	{  position = {    character = 6,    line = 3  },  textDocument = {    uri = "file:///home/tserge/work/sandbox/rust/learn-rust-snippets/thread-local/src/main.rs"  }}	<function 1>	1
[DEBUG][2023-09-09 01:18:10] .../vim/lsp/rpc.lua:261	"rpc.send"	{  id = 9,  jsonrpc = "2.0",  method = "rust-analyzer/expandMacro",  params = {    position = {      character = 6,      line = 3    },    textDocument = {      uri = "file:///home/tserge/work/sandbox/rust/learn-rust-snippets/thread-local/src/main.rs"    }  }}
[DEBUG][2023-09-09 01:18:10] .../vim/lsp/rpc.lua:364	"rpc.receive"	{  id = 9,  jsonrpc = "2.0",  result = {    expansion = "$crate::thread::local_impl::thread_local_inner!(TLV, RefCell<i32>, (RefCell::new(1)));",    name = "thread_local!"  }}

LSP Log for hover, definition, references

[DEBUG][2023-09-09 12:37:55] .../lua/vim/lsp.lua:1492	"LSP[rust_analyzer]"	"client.request"	1	"textDocument/hover"	{  position = {    character = 5,    line = 8  },  textDocument = {    uri = "file:///home/tserge/work/sandbox/rust/learn-rust-snippets/thread-local/src/main.rs"  }}	<function 1>	1
[DEBUG][2023-09-09 12:37:55] .../vim/lsp/rpc.lua:261	"rpc.send"	{  id = 9,  jsonrpc = "2.0",  method = "textDocument/hover",  params = {    position = {      character = 5,      line = 8    },    textDocument = {      uri = "file:///home/tserge/work/sandbox/rust/learn-rust-snippets/thread-local/src/main.rs"    }  }}
[DEBUG][2023-09-09 12:37:55] .../vim/lsp/rpc.lua:364	"rpc.receive"	{  id = 9,  jsonrpc = "2.0"}

[DEBUG][2023-09-09 12:38:01] .../lua/vim/lsp.lua:1492	"LSP[rust_analyzer]"	"client.request"	1	"textDocument/hover"	{  position = {    character = 9,    line = 8  },  textDocument = {    uri = "file:///home/tserge/work/sandbox/rust/learn-rust-snippets/thread-local/src/main.rs"  }}	<function 1>	1
[DEBUG][2023-09-09 12:38:01] .../vim/lsp/rpc.lua:261	"rpc.send"	{  id = 10,  jsonrpc = "2.0",  method = "textDocument/hover",  params = {    position = {      character = 9,      line = 8    },    textDocument = {      uri = "file:///home/tserge/work/sandbox/rust/learn-rust-snippets/thread-local/src/main.rs"    }  }}
[DEBUG][2023-09-09 12:38:01] .../vim/lsp/rpc.lua:364	"rpc.receive"	{  id = 10,  jsonrpc = "2.0"}

[DEBUG][2023-09-09 12:40:20] .../lua/vim/lsp.lua:1492	"LSP[rust_analyzer]"	"client.request"	1	"textDocument/definition"	{  position = {    character = 11,    line = 8  },  textDocument = {    uri = "file:///home/tserge/work/sandbox/rust/learn-rust-snippets/thread-local/src/main.rs"  }}	<function 1>	1
[DEBUG][2023-09-09 12:40:20] .../vim/lsp/rpc.lua:261	"rpc.send"	{  id = 12,  jsonrpc = "2.0",  method = "textDocument/definition",  params = {    position = {      character = 11,      line = 8    },    textDocument = {      uri = "file:///home/tserge/work/sandbox/rust/learn-rust-snippets/thread-local/src/main.rs"    }  }}
[DEBUG][2023-09-09 12:40:20] .../vim/lsp/rpc.lua:364	"rpc.receive"	{  id = 12,  jsonrpc = "2.0",  result = {}}
[INFO][2023-09-09 12:40:20] ...lsp/handlers.lua:393	"textDocument/definition"	"No location found"

[DEBUG][2023-09-09 12:40:27] .../lua/vim/lsp.lua:1492	"LSP[rust_analyzer]"	"client.request"	1	"textDocument/definition"	{  position = {    character = 5,    line = 8  },  textDocument = {    uri = "file:///home/tserge/work/sandbox/rust/learn-rust-snippets/thread-local/src/main.rs"  }}	<function 1>	1
[DEBUG][2023-09-09 12:40:27] .../vim/lsp/rpc.lua:261	"rpc.send"	{  id = 13,  jsonrpc = "2.0",  method = "textDocument/definition",  params = {    position = {      character = 5,      line = 8    },    textDocument = {      uri = "file:///home/tserge/work/sandbox/rust/learn-rust-snippets/thread-local/src/main.rs"    }  }}
[DEBUG][2023-09-09 12:40:27] .../vim/lsp/rpc.lua:364	"rpc.receive"	{  id = 13,  jsonrpc = "2.0",  result = {}}
[INFO][2023-09-09 12:40:27] ...lsp/handlers.lua:393	"textDocument/definition"	"No location found"

[DEBUG][2023-09-09 12:40:59] .../lua/vim/lsp.lua:1492	"LSP[rust_analyzer]"	"client.request"	1	"textDocument/references"	{  context = {    includeDeclaration = true  },  position = {    character = 5,    line = 8  },  textDocument = {    uri = "file:///home/tserge/work/sandbox/rust/learn-rust-snippets/thread-local/src/main.rs"  }}	<function 1>	1
[DEBUG][2023-09-09 12:40:59] .../vim/lsp/rpc.lua:261	"rpc.send"	{  id = 14,  jsonrpc = "2.0",  method = "textDocument/references",  params = {    context = {      includeDeclaration = true    },    position = {      character = 5,      line = 8    },    textDocument = {      uri = "file:///home/tserge/work/sandbox/rust/learn-rust-snippets/thread-local/src/main.rs"    }  }}
[DEBUG][2023-09-09 12:40:59] .../vim/lsp/rpc.lua:364	"rpc.receive"	{  id = 14,  jsonrpc = "2.0",  result = {}}

[DEBUG][2023-09-09 12:41:08] .../lua/vim/lsp.lua:1492	"LSP[rust_analyzer]"	"client.request"	1	"textDocument/references"	{  context = {    includeDeclaration = true  },  position = {    character = 12,    line = 4  },  textDocument = {    uri = "file:///home/tserge/work/sandbox/rust/learn-rust-snippets/thread-local/src/main.rs"  }}	<function 1>	1
[DEBUG][2023-09-09 12:41:08] .../vim/lsp/rpc.lua:261	"rpc.send"	{  id = 15,  jsonrpc = "2.0",  method = "textDocument/references",  params = {    context = {      includeDeclaration = true    },    position = {      character = 12,      line = 4    },    textDocument = {      uri = "file:///home/tserge/work/sandbox/rust/learn-rust-snippets/thread-local/src/main.rs"    }  }}
[DEBUG][2023-09-09 12:41:08] .../vim/lsp/rpc.lua:364	"rpc.receive"	{  id = 15,  jsonrpc = "2.0",  result = {}}

But cargo expand works as expected:

$ cargo expand
    Checking thread-local v0.1.0 (/home/tserge/work/sandbox/rust/learn-rust-snippets/thread-local)
    Finished dev [unoptimized + debuginfo] target(s) in 0.02s

#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
use std::{cell::RefCell, sync::RwLock};
static V: RwLock<i32> = RwLock::new(1);
const TLV: ::std::thread::LocalKey<RefCell<i32>> = {
    #[inline]
    fn __init() -> RefCell<i32> {
        RefCell::new(1)
    }
    #[inline]
    unsafe fn __getit(
        init: ::std::option::Option<&mut ::std::option::Option<RefCell<i32>>>,
    ) -> ::std::option::Option<&'static RefCell<i32>> {
        #[thread_local]
        static __KEY: ::std::thread::local_impl::Key<RefCell<i32>> = ::std::thread::local_impl::Key::<
            RefCell<i32>,
        >::new();
        #[allow(unused_unsafe)]
        unsafe {
            __KEY
                .get(move || {
                    if let ::std::option::Option::Some(init) = init {
                        if let ::std::option::Option::Some(value) = init.take() {
                            return value;
                        } else if true {
                            {
                                ::core::panicking::panic_fmt(
                                    format_args!(
                                        "internal error: entered unreachable code: {0}",
                                        format_args!("missing default value"),
                                    ),
                                );
                            };
                        }
                    }
                    __init()
                })
        }
    }
    unsafe { ::std::thread::LocalKey::new(__getit) }
};
fn main() {
    match (&*V.read().unwrap(), &1) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(
                    kind,
                    &*left_val,
                    &*right_val,
                    ::core::option::Option::None,
                );
            }
        }
    };
    TLV.with(|tlv| match (&*tlv.borrow(), &1) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(
                    kind,
                    &*left_val,
                    &*right_val,
                    ::core::option::Option::None,
                );
            }
        }
    });
    {
        ::std::io::_print(format_args!("TLV: {0:?}\n", TLV));
    };
}

rust-analyzer version: rust-analyzer 0.3.1649-standalone

rustc version: rustc 1.72.0 (5680fa18f 2023-08-23)

relevant settings: (eg. client settings, or environment variables like CARGO, RUSTC, RUSTUP_HOME or CARGO_HOME)
$ rustup -V
rustup 1.26.0 (5af9b94 2023-04-05)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: The currently active rustc version is rustc 1.72.0 (5680fa18f 2023-08-23)

@sergey-tikhonenko sergey-tikhonenko added the C-bug Category: bug label Sep 9, 2023
@Veykril
Copy link
Member

Veykril commented Sep 9, 2023

hmm odd, this works fine for me on current r-a nightly, though I am on windows with 1.74-nightly rust. I don't think anything changed in std lib there though

@lnicola
Copy link
Member

lnicola commented Sep 9, 2023

Doesn't work for me on Linux, not sure if we support macros 2.0.

@sergey-tikhonenko
Copy link
Author

Sorry I didn't mention earlier, my system is linux and for nightly - the same behavior

$ rust-analyzer --version
rust-analyzer 1.74.0-nightly (62ebe3a 2023-09-08)
$ rustc -V
rustc 1.74.0-nightly (62ebe3a2b 2023-09-08)
$ lsb_release -a
Distributor ID:	Ubuntu
Description:	Ubuntu 22.04.3 LTS
Release:	22.04
Codename:	jammy

@veber-alex
Copy link
Contributor

Doesn't work on macos.
rust-analyzer version: 0.3.1681-standalone (0840038f0 2023-09-30)
rustc 1.75.0-nightly (187b8131d 2023-10-03)

@lnicola
Copy link
Member

lnicola commented Feb 26, 2024

Expands more or less correctly now, can you confirm @sergey-tikhonenko?

image

@sergey-tikhonenko
Copy link
Author

sergey-tikhonenko commented Feb 27, 2024

I see the same behaviour for both versions:

  • rust-analyzer 1.78.0-nightly (0ecbd06 2024-02-25)
  • rust-analyzer 0.3.1860-standalone

LSP method = "rust-analyzer/expandMacro" returns the following expansion = $crate::thread::local_impl::thread_local_inner!(TLV, RefCell<i32>, (RefCell::new(1)));

see LSP log

[DEBUG][2024-02-27 14:04:09] .../lua/vim/lsp.lua:1391	"LSP[rust_analyzer]"	"client.request"	1	"rust-analyzer/expandMacro"	{
  position = { character = 1, line = 6 },
  textDocument = { uri = "file:///home/tserge/work/sandbox/rust/learn-rust-snippets/thread-local/src/main.rs" }
}	<function 1>	2
[DEBUG][2024-02-27 14:04:09] .../vim/lsp/rpc.lua:284	"rpc.send"	{
  id = 10,
  jsonrpc = "2.0",
  method = "rust-analyzer/expandMacro",
  params = { position = { character = 1, line = 6 },
    textDocument = { uri = "file:///home/tserge/work/sandbox/rust/learn-rust-snippets/thread-local/src/main.rs" }
  }
}
[DEBUG][2024-02-27 14:04:09] .../vim/lsp/rpc.lua:387	"rpc.receive"	{
  id = 9,
  jsonrpc = "2.0",
  result = { { range = { ["end"] = { character = 12, line = 6 }, start = { character = 0, line = 6 } } } }
}
[DEBUG][2024-02-27 14:04:09] .../vim/lsp/rpc.lua:387	"rpc.receive"	{
  id = 10,
  jsonrpc = "2.0",
  result = {
    expansion = "$crate::thread::local_impl::thread_local_inner!(TLV, RefCell<i32>, (RefCell::new(1)));",
    name = "thread_local!"
  }
}

PS.

  1. what VScode plugin do you use for expansion? I use Rust Macro Expand, but it uses cargo-expand under the hood, rather then LSP.
  2. Can we have some IDE independent script to verify the issue? It's difficult for me to prepare it by myself, perhaps there is some almost ready one, that can be adjusted for the issue.

@Veykril
Copy link
Member

Veykril commented Feb 27, 2024

thread_local_inner is re-exported behind a cfg_if! invocation, so we can't resolve the macro in projects that don't depend on it, #7637, you can enable "rust-analyzer.cargo.sysrootQueryMetadata": true, which should make it work as well but note that this will write and delete a lock file in your sysroot folder due to a short coming of cargo metadata

@sergey-tikhonenko
Copy link
Author

sergey-tikhonenko commented Feb 28, 2024

Thanks, as a workaround, this works for me.
Will keep an eye on #7637 for a more suitable solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: bug
Projects
None yet
Development

No branches or pull requests

4 participants