mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 11:20:54 +00:00
Rollup merge of #144243 - lnicola:sync-from-ra, r=lnicola
Subtree update of `rust-analyzer` r? ```@ghost```
This commit is contained in:
commit
1bcd093474
41
Cargo.lock
generated
41
Cargo.lock
generated
@ -1268,7 +1268,7 @@ dependencies = [
|
||||
"expect-test",
|
||||
"intern",
|
||||
"parser",
|
||||
"ra-ap-rustc_lexer",
|
||||
"ra-ap-rustc_lexer 0.122.0",
|
||||
"rustc-hash 2.1.1",
|
||||
"smallvec",
|
||||
"span",
|
||||
@ -1504,7 +1504,7 @@ dependencies = [
|
||||
"drop_bomb",
|
||||
"edition",
|
||||
"expect-test",
|
||||
"ra-ap-rustc_lexer",
|
||||
"ra-ap-rustc_lexer 0.122.0",
|
||||
"rustc-literal-escaper",
|
||||
"stdx",
|
||||
"tracing",
|
||||
@ -1614,7 +1614,7 @@ dependencies = [
|
||||
"object",
|
||||
"paths",
|
||||
"proc-macro-test",
|
||||
"ra-ap-rustc_lexer",
|
||||
"ra-ap-rustc_lexer 0.122.0",
|
||||
"span",
|
||||
"syntax-bridge",
|
||||
"tt",
|
||||
@ -1756,9 +1756,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_abi"
|
||||
version = "0.121.0"
|
||||
version = "0.122.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ee51482d1c9d3e538acda8cce723db8eea1a81540544bf362bf4c3d841b2329"
|
||||
checksum = "fb01e1fec578003c85481c1cad4ff8cd8195b07c2dc85ae3f716108507ae15d5"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"ra-ap-rustc_hashes",
|
||||
@ -1768,18 +1768,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_hashes"
|
||||
version = "0.121.0"
|
||||
version = "0.122.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19c8f1e0c28e24e1b4c55dc08058c6c9829df2204497d4034259f491d348c204"
|
||||
checksum = "e0ec056e72a472ffef8761ce96ece6c626eb07368c09d0105b6df30d27d07673"
|
||||
dependencies = [
|
||||
"rustc-stable-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_index"
|
||||
version = "0.121.0"
|
||||
version = "0.122.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f33f429cec6b92fa2c7243883279fb29dd233fdc3e94099aff32aa91aa87f50"
|
||||
checksum = "0fcdd1001db0295e59052e9f53aeda588bbe81e362534f4687d41bd44777b5a7"
|
||||
dependencies = [
|
||||
"ra-ap-rustc_index_macros",
|
||||
"smallvec",
|
||||
@ -1787,9 +1787,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_index_macros"
|
||||
version = "0.121.0"
|
||||
version = "0.122.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9b55910dbe1fe7ef34bdc1d1bcb41e99b377eb680ea58a1218d95d6b4152257"
|
||||
checksum = "728d64dd98e25530b32e3f7c7c1e844e52722b269360daa1cdeba9dff9727a26"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -1807,21 +1807,32 @@ dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_lexer"
|
||||
version = "0.122.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "415f0821f512608d825b3215489a6a6a2c18ed9f0045953d514e7ec23d4b90ab"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"unicode-properties",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_parse_format"
|
||||
version = "0.121.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81057891bc2063ad9e353f29462fbc47a0f5072560af34428ae9313aaa5e9d97"
|
||||
dependencies = [
|
||||
"ra-ap-rustc_lexer",
|
||||
"ra-ap-rustc_lexer 0.121.0",
|
||||
"rustc-literal-escaper",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_pattern_analysis"
|
||||
version = "0.121.0"
|
||||
version = "0.122.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe21a3542980d56d2435e96c2720773cac1c63fd4db666417e414729da192eb3"
|
||||
checksum = "4657fcfdfe06e2a02ec8180d4e7c95aecf4811ba50367e363d1a2300b7623284"
|
||||
dependencies = [
|
||||
"ra-ap-rustc_index",
|
||||
"rustc-hash 2.1.1",
|
||||
@ -2581,7 +2592,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"intern",
|
||||
"ra-ap-rustc_lexer",
|
||||
"ra-ap-rustc_lexer 0.122.0",
|
||||
"stdx",
|
||||
"text-size",
|
||||
]
|
||||
|
@ -89,11 +89,11 @@ vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
|
||||
vfs = { path = "./crates/vfs", version = "0.0.0" }
|
||||
edition = { path = "./crates/edition", version = "0.0.0" }
|
||||
|
||||
ra-ap-rustc_lexer = { version = "0.121", default-features = false }
|
||||
ra-ap-rustc_lexer = { version = "0.122", default-features = false }
|
||||
ra-ap-rustc_parse_format = { version = "0.121", default-features = false }
|
||||
ra-ap-rustc_index = { version = "0.121", default-features = false }
|
||||
ra-ap-rustc_abi = { version = "0.121", default-features = false }
|
||||
ra-ap-rustc_pattern_analysis = { version = "0.121", default-features = false }
|
||||
ra-ap-rustc_index = { version = "0.122", default-features = false }
|
||||
ra-ap-rustc_abi = { version = "0.122", default-features = false }
|
||||
ra-ap-rustc_pattern_analysis = { version = "0.122", default-features = false }
|
||||
|
||||
# local crates that aren't published to crates.io. These should not have versions.
|
||||
|
||||
|
@ -68,6 +68,11 @@ impl CfgExpr {
|
||||
next_cfg_expr(&mut tt.iter()).unwrap_or(CfgExpr::Invalid)
|
||||
}
|
||||
|
||||
#[cfg(feature = "tt")]
|
||||
pub fn parse_from_iter<S: Copy>(tt: &mut tt::iter::TtIter<'_, S>) -> CfgExpr {
|
||||
next_cfg_expr(tt).unwrap_or(CfgExpr::Invalid)
|
||||
}
|
||||
|
||||
/// Fold the cfg by querying all basic `Atom` and `KeyValue` predicates.
|
||||
pub fn fold(&self, query: &dyn Fn(&CfgAtom) -> bool) -> Option<bool> {
|
||||
match self {
|
||||
@ -96,7 +101,14 @@ fn next_cfg_expr<S: Copy>(it: &mut tt::iter::TtIter<'_, S>) -> Option<CfgExpr> {
|
||||
};
|
||||
|
||||
let ret = match it.peek() {
|
||||
Some(TtElement::Leaf(tt::Leaf::Punct(punct))) if punct.char == '=' => {
|
||||
Some(TtElement::Leaf(tt::Leaf::Punct(punct)))
|
||||
// Don't consume on e.g. `=>`.
|
||||
if punct.char == '='
|
||||
&& (punct.spacing == tt::Spacing::Alone
|
||||
|| it.remaining().flat_tokens().get(1).is_none_or(|peek2| {
|
||||
!matches!(peek2, tt::TokenTree::Leaf(tt::Leaf::Punct(_)))
|
||||
})) =>
|
||||
{
|
||||
match it.remaining().flat_tokens().get(1) {
|
||||
Some(tt::TokenTree::Leaf(tt::Leaf::Literal(literal))) => {
|
||||
it.next();
|
||||
|
@ -550,3 +550,51 @@ fn main() { "\"hello\""; }
|
||||
"##]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cfg_select() {
|
||||
check(
|
||||
r#"
|
||||
#[rustc_builtin_macro]
|
||||
pub macro cfg_select($($tt:tt)*) {}
|
||||
|
||||
cfg_select! {
|
||||
false => { fn false_1() {} }
|
||||
any(false, true) => { fn true_1() {} }
|
||||
}
|
||||
|
||||
cfg_select! {
|
||||
false => { fn false_2() {} }
|
||||
_ => { fn true_2() {} }
|
||||
}
|
||||
|
||||
cfg_select! {
|
||||
false => { fn false_3() {} }
|
||||
}
|
||||
|
||||
cfg_select! {
|
||||
false
|
||||
}
|
||||
|
||||
cfg_select! {
|
||||
false =>
|
||||
}
|
||||
|
||||
"#,
|
||||
expect![[r#"
|
||||
#[rustc_builtin_macro]
|
||||
pub macro cfg_select($($tt:tt)*) {}
|
||||
|
||||
fn true_1() {}
|
||||
|
||||
fn true_2() {}
|
||||
|
||||
/* error: none of the predicates in this `cfg_select` evaluated to true */
|
||||
|
||||
/* error: expected `=>` after cfg expression */
|
||||
|
||||
/* error: expected a token tree after `=>` */
|
||||
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -127,6 +127,7 @@ register_builtin! {
|
||||
(asm, Asm) => asm_expand,
|
||||
(global_asm, GlobalAsm) => global_asm_expand,
|
||||
(naked_asm, NakedAsm) => naked_asm_expand,
|
||||
(cfg_select, CfgSelect) => cfg_select_expand,
|
||||
(cfg, Cfg) => cfg_expand,
|
||||
(core_panic, CorePanic) => panic_expand,
|
||||
(std_panic, StdPanic) => panic_expand,
|
||||
@ -355,6 +356,71 @@ fn naked_asm_expand(
|
||||
ExpandResult::ok(expanded)
|
||||
}
|
||||
|
||||
fn cfg_select_expand(
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
tt: &tt::TopSubtree,
|
||||
span: Span,
|
||||
) -> ExpandResult<tt::TopSubtree> {
|
||||
let loc = db.lookup_intern_macro_call(id);
|
||||
let cfg_options = loc.krate.cfg_options(db);
|
||||
|
||||
let mut iter = tt.iter();
|
||||
let mut expand_to = None;
|
||||
while let Some(next) = iter.peek() {
|
||||
let active = if let tt::TtElement::Leaf(tt::Leaf::Ident(ident)) = next
|
||||
&& ident.sym == sym::underscore
|
||||
{
|
||||
iter.next();
|
||||
true
|
||||
} else {
|
||||
cfg_options.check(&CfgExpr::parse_from_iter(&mut iter)) != Some(false)
|
||||
};
|
||||
match iter.expect_glued_punct() {
|
||||
Ok(it) if it.len() == 2 && it[0].char == '=' && it[1].char == '>' => {}
|
||||
_ => {
|
||||
let err_span = iter.peek().map(|it| it.first_span()).unwrap_or(span);
|
||||
return ExpandResult::new(
|
||||
tt::TopSubtree::empty(tt::DelimSpan::from_single(span)),
|
||||
ExpandError::other(err_span, "expected `=>` after cfg expression"),
|
||||
);
|
||||
}
|
||||
}
|
||||
let expand_to_if_active = match iter.next() {
|
||||
Some(tt::TtElement::Subtree(_, tt)) => tt.remaining(),
|
||||
_ => {
|
||||
let err_span = iter.peek().map(|it| it.first_span()).unwrap_or(span);
|
||||
return ExpandResult::new(
|
||||
tt::TopSubtree::empty(tt::DelimSpan::from_single(span)),
|
||||
ExpandError::other(err_span, "expected a token tree after `=>`"),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
if expand_to.is_none() && active {
|
||||
expand_to = Some(expand_to_if_active);
|
||||
}
|
||||
}
|
||||
match expand_to {
|
||||
Some(expand_to) => {
|
||||
let mut builder = tt::TopSubtreeBuilder::new(tt::Delimiter {
|
||||
kind: tt::DelimiterKind::Invisible,
|
||||
open: span,
|
||||
close: span,
|
||||
});
|
||||
builder.extend_with_tt(expand_to);
|
||||
ExpandResult::ok(builder.build())
|
||||
}
|
||||
None => ExpandResult::new(
|
||||
tt::TopSubtree::empty(tt::DelimSpan::from_single(span)),
|
||||
ExpandError::other(
|
||||
span,
|
||||
"none of the predicates in this `cfg_select` evaluated to true",
|
||||
),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn cfg_expand(
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
|
@ -10,7 +10,7 @@ use syntax::{
|
||||
use crate::{
|
||||
AssistId,
|
||||
assist_context::{AssistContext, Assists, SourceChangeBuilder},
|
||||
utils::generate_trait_impl_text,
|
||||
utils::generate_trait_impl_text_intransitive,
|
||||
};
|
||||
|
||||
// Assist: generate_deref
|
||||
@ -150,7 +150,7 @@ fn generate_edit(
|
||||
),
|
||||
};
|
||||
let strukt_adt = ast::Adt::Struct(strukt);
|
||||
let deref_impl = generate_trait_impl_text(
|
||||
let deref_impl = generate_trait_impl_text_intransitive(
|
||||
&strukt_adt,
|
||||
&trait_path.display(db, edition).to_string(),
|
||||
&impl_code,
|
||||
@ -227,6 +227,28 @@ impl core::ops::Deref for B {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generate_record_deref_with_generic() {
|
||||
check_assist(
|
||||
generate_deref,
|
||||
r#"
|
||||
//- minicore: deref
|
||||
struct A<T>($0T);
|
||||
"#,
|
||||
r#"
|
||||
struct A<T>(T);
|
||||
|
||||
impl<T> core::ops::Deref for A<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generate_record_deref_short_path() {
|
||||
check_assist(
|
||||
|
@ -134,6 +134,9 @@ fn get_trait_mut(apply_trait: &hir::Trait, famous: FamousDefs<'_, '_>) -> Option
|
||||
if trait_ == famous.core_borrow_Borrow().as_ref() {
|
||||
return Some("BorrowMut");
|
||||
}
|
||||
if trait_ == famous.core_ops_Deref().as_ref() {
|
||||
return Some("DerefMut");
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
@ -142,6 +145,7 @@ fn process_method_name(name: ast::Name) -> Option<(ast::Name, &'static str)> {
|
||||
"index" => "index_mut",
|
||||
"as_ref" => "as_mut",
|
||||
"borrow" => "borrow_mut",
|
||||
"deref" => "deref_mut",
|
||||
_ => return None,
|
||||
};
|
||||
Some((name, new_name))
|
||||
@ -258,6 +262,39 @@ impl core::convert::AsRef<i32> for Foo {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
||||
check_assist(
|
||||
generate_mut_trait_impl,
|
||||
r#"
|
||||
//- minicore: deref
|
||||
struct Foo(i32);
|
||||
|
||||
impl core::ops::Deref$0 for Foo {
|
||||
type Target = i32;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
struct Foo(i32);
|
||||
|
||||
$0impl core::ops::DerefMut for Foo {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::Deref for Foo {
|
||||
type Target = i32;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
@ -567,6 +567,7 @@ pub(crate) fn generate_impl_text(adt: &ast::Adt, code: &str) -> String {
|
||||
///
|
||||
/// This is useful for traits like `PartialEq`, since `impl<T> PartialEq for U<T>` often requires `T: PartialEq`.
|
||||
// FIXME: migrate remaining uses to `generate_trait_impl`
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn generate_trait_impl_text(adt: &ast::Adt, trait_text: &str, code: &str) -> String {
|
||||
generate_impl_text_inner(adt, Some(trait_text), true, code)
|
||||
}
|
||||
|
@ -531,7 +531,7 @@ impl<'a> FindUsages<'a> {
|
||||
node.token_at_offset(offset)
|
||||
.find(|it| {
|
||||
// `name` is stripped of raw ident prefix. See the comment on name retrieval below.
|
||||
it.text().trim_start_matches("r#") == name
|
||||
it.text().trim_start_matches('\'').trim_start_matches("r#") == name
|
||||
})
|
||||
.into_iter()
|
||||
.flat_map(move |token| {
|
||||
@ -938,7 +938,12 @@ impl<'a> FindUsages<'a> {
|
||||
})
|
||||
};
|
||||
// We need to search without the `r#`, hence `as_str` access.
|
||||
self.def.name(sema.db).or_else(self_kw_refs).map(|it| it.as_str().to_smolstr())
|
||||
// We strip `'` from lifetimes and labels as otherwise they may not match with raw-escaped ones,
|
||||
// e.g. if we search `'foo` we won't find `'r#foo`.
|
||||
self.def
|
||||
.name(sema.db)
|
||||
.or_else(self_kw_refs)
|
||||
.map(|it| it.as_str().trim_start_matches('\'').to_smolstr())
|
||||
}
|
||||
};
|
||||
let name = match &name {
|
||||
|
@ -48,7 +48,6 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
|
||||
let mut res = vec![];
|
||||
let mut visited_comments = FxHashSet::default();
|
||||
let mut visited_nodes = FxHashSet::default();
|
||||
let mut merged_fn_bodies = FxHashSet::default();
|
||||
|
||||
// regions can be nested, here is a LIFO buffer
|
||||
let mut region_starts: Vec<TextSize> = vec![];
|
||||
@ -73,7 +72,7 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(body) = fn_node.body() {
|
||||
if fn_node.body().is_some() {
|
||||
res.push(Fold {
|
||||
range: TextRange::new(
|
||||
node.text_range().start(),
|
||||
@ -81,7 +80,6 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
|
||||
),
|
||||
kind: FoldKind::Function,
|
||||
});
|
||||
merged_fn_bodies.insert(body.syntax().text_range());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -3088,4 +3088,42 @@ fn main() {
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn raw_labels_and_lifetimes() {
|
||||
check(
|
||||
r#"
|
||||
fn foo<'r#fn>(s: &'r#fn str) {
|
||||
let _a: &'r#fn str = s;
|
||||
let _b: &'r#fn str;
|
||||
'r#break$0: {
|
||||
break 'r#break;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
'r#break Label FileId(0) 87..96 87..95
|
||||
|
||||
FileId(0) 113..121
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
fn foo<'r#fn$0>(s: &'r#fn str) {
|
||||
let _a: &'r#fn str = s;
|
||||
let _b: &'r#fn str;
|
||||
'r#break: {
|
||||
break 'r#break;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
'r#fn LifetimeParam FileId(0) 7..12
|
||||
|
||||
FileId(0) 18..23
|
||||
FileId(0) 44..49
|
||||
FileId(0) 72..77
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -156,6 +156,7 @@ define_symbols! {
|
||||
cfg_attr,
|
||||
cfg_eval,
|
||||
cfg,
|
||||
cfg_select,
|
||||
char,
|
||||
clone,
|
||||
Clone,
|
||||
|
@ -217,6 +217,17 @@ pub enum TtElement<'a, S> {
|
||||
Subtree(&'a Subtree<S>, TtIter<'a, S>),
|
||||
}
|
||||
|
||||
impl<S: Copy + fmt::Debug> fmt::Debug for TtElement<'_, S> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Leaf(leaf) => f.debug_tuple("Leaf").field(leaf).finish(),
|
||||
Self::Subtree(subtree, inner) => {
|
||||
f.debug_tuple("Subtree").field(subtree).field(inner).finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Copy> TtElement<'_, S> {
|
||||
#[inline]
|
||||
pub fn first_span(&self) -> S {
|
||||
|
@ -1 +1 @@
|
||||
a9fb6103b05c6ad6eee6bed4c0bb5a2e8e1024c6
|
||||
e05ab47e6c418fb2b9faa2eae9a7e70c65c98eaa
|
||||
|
Loading…
x
Reference in New Issue
Block a user