Auto merge of #144233 - cjgillot:unsat-mir, r=oli-obk
Consider parent predicates in ImpossiblePredicates pass.
This pass is double edged. It avoids some ICEs (yay!) but also degrades diagnostics from constant evaluation.
Fixes rust-lang/rust#121363
Fixes rust-lang/rust#131507
Fixes rust-lang/rust#140100
Fixes rust-lang/rust#140365
diff --git a/Cargo.lock b/Cargo.lock
index e55cd80..c471234 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1268,7 +1268,7 @@
"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 @@
"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 @@
"object",
"paths",
"proc-macro-test",
- "ra-ap-rustc_lexer",
+ "ra-ap-rustc_lexer 0.122.0",
"span",
"syntax-bridge",
"tt",
@@ -1756,9 +1756,9 @@
[[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 @@
[[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 @@
[[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",
@@ -1808,20 +1808,31 @@
]
[[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 @@
dependencies = [
"arrayvec",
"intern",
- "ra-ap-rustc_lexer",
+ "ra-ap-rustc_lexer 0.122.0",
"stdx",
"text-size",
]
diff --git a/Cargo.toml b/Cargo.toml
index 41fa06a..700c116 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -89,11 +89,11 @@
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.
diff --git a/crates/cfg/src/cfg_expr.rs b/crates/cfg/src/cfg_expr.rs
index 0ec082d..aed00aa 100644
--- a/crates/cfg/src/cfg_expr.rs
+++ b/crates/cfg/src/cfg_expr.rs
@@ -68,6 +68,11 @@
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 @@
};
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();
diff --git a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
index 1c3af47..eeaf865 100644
--- a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
+++ b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
@@ -550,3 +550,51 @@
"##]],
);
}
+
+#[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 `=>` */
+
+ "#]],
+ );
+}
diff --git a/crates/hir-expand/src/builtin/fn_macro.rs b/crates/hir-expand/src/builtin/fn_macro.rs
index 60fbc66..4a9af01 100644
--- a/crates/hir-expand/src/builtin/fn_macro.rs
+++ b/crates/hir-expand/src/builtin/fn_macro.rs
@@ -127,6 +127,7 @@
(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 @@
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,
diff --git a/crates/ide-assists/src/handlers/generate_deref.rs b/crates/ide-assists/src/handlers/generate_deref.rs
index c7b97dc..55a09c5 100644
--- a/crates/ide-assists/src/handlers/generate_deref.rs
+++ b/crates/ide-assists/src/handlers/generate_deref.rs
@@ -10,7 +10,7 @@
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 @@
),
};
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,
@@ -228,6 +228,28 @@
}
#[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(
generate_deref,
diff --git a/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs b/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs
index 4ddab2c..dc26ec7 100644
--- a/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs
+++ b/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs
@@ -134,6 +134,9 @@
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 @@
"index" => "index_mut",
"as_ref" => "as_mut",
"borrow" => "borrow_mut",
+ "deref" => "deref_mut",
_ => return None,
};
Some((name, new_name))
@@ -260,6 +264,39 @@
}
"#,
);
+
+ 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
+ }
+}
+"#,
+ );
}
#[test]
diff --git a/crates/ide-assists/src/utils.rs b/crates/ide-assists/src/utils.rs
index 2c8cb6e..fbce1d3 100644
--- a/crates/ide-assists/src/utils.rs
+++ b/crates/ide-assists/src/utils.rs
@@ -567,6 +567,7 @@
///
/// 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)
}
diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs
index 4efb83b..9cf0bcf 100644
--- a/crates/ide-db/src/search.rs
+++ b/crates/ide-db/src/search.rs
@@ -531,7 +531,7 @@
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 @@
})
};
// 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 {
diff --git a/crates/ide/src/folding_ranges.rs b/crates/ide/src/folding_ranges.rs
index c081796..698fd14 100755
--- a/crates/ide/src/folding_ranges.rs
+++ b/crates/ide/src/folding_ranges.rs
@@ -48,7 +48,6 @@
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 @@
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 @@
),
kind: FoldKind::Function,
});
- merged_fn_bodies.insert(body.syntax().text_range());
continue;
}
}
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index fe874bc..86b88a1 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -3088,4 +3088,42 @@
"#]],
);
}
+
+ #[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
+ "#]],
+ );
+ }
}
diff --git a/crates/intern/src/symbol/symbols.rs b/crates/intern/src/symbol/symbols.rs
index 1ccd20c..4780743 100644
--- a/crates/intern/src/symbol/symbols.rs
+++ b/crates/intern/src/symbol/symbols.rs
@@ -156,6 +156,7 @@
cfg_attr,
cfg_eval,
cfg,
+ cfg_select,
char,
clone,
Clone,
diff --git a/crates/tt/src/iter.rs b/crates/tt/src/iter.rs
index 3246156..2e89d76 100644
--- a/crates/tt/src/iter.rs
+++ b/crates/tt/src/iter.rs
@@ -217,6 +217,17 @@
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 {
diff --git a/rust-version b/rust-version
index 57ff326..c2b1c15 100644
--- a/rust-version
+++ b/rust-version
@@ -1 +1 @@
-a9fb6103b05c6ad6eee6bed4c0bb5a2e8e1024c6
+e05ab47e6c418fb2b9faa2eae9a7e70c65c98eaa