Merge pull request #21725 from Veykril/push-skvpqzkooolm

fix: Fix wrong confiditon in `Visibility::min`
diff --git a/crates/hir-ty/src/infer/cast.rs b/crates/hir-ty/src/infer/cast.rs
index d69b00a..fc38361 100644
--- a/crates/hir-ty/src/infer/cast.rs
+++ b/crates/hir-ty/src/infer/cast.rs
@@ -328,11 +328,7 @@
                     //
                     // Note that trait upcasting goes through a different mechanism (`coerce_unsized`)
                     // and is unaffected by this check.
-                    (Some(src_principal), Some(dst_principal)) => {
-                        if src_principal == dst_principal {
-                            return Ok(());
-                        }
-
+                    (Some(src_principal), Some(_)) => {
                         // We need to reconstruct trait object types.
                         // `m_src` and `m_dst` won't work for us here because they will potentially
                         // contain wrappers, which we do not care about.
diff --git a/crates/ide-assists/src/handlers/fix_visibility.rs b/crates/ide-assists/src/handlers/fix_visibility.rs
index 0fd8057..5134b98 100644
--- a/crates/ide-assists/src/handlers/fix_visibility.rs
+++ b/crates/ide-assists/src/handlers/fix_visibility.rs
@@ -2,7 +2,7 @@
 use ide_db::FileId;
 use syntax::{
     AstNode, TextRange,
-    ast::{self, HasVisibility as _, edit_in_place::HasVisibilityEdit, make},
+    ast::{self, HasVisibility as _, syntax_factory::SyntaxFactory},
 };
 
 use crate::{AssistContext, AssistId, Assists};
@@ -59,10 +59,12 @@
 
     let (vis_owner, target, target_file, target_name) = target_data_for_def(ctx.db(), def)?;
 
+    let make = SyntaxFactory::without_mappings();
+
     let missing_visibility = if current_module.krate(ctx.db()) == target_module.krate(ctx.db()) {
-        make::visibility_pub_crate()
+        make.visibility_pub_crate()
     } else {
-        make::visibility_pub()
+        make.visibility_pub()
     };
 
     let assist_label = match target_name {
@@ -75,15 +77,36 @@
         }
     };
 
-    acc.add(AssistId::quick_fix("fix_visibility"), assist_label, target, |edit| {
-        edit.edit_file(target_file);
+    acc.add(AssistId::quick_fix("fix_visibility"), assist_label, target, |builder| {
+        let mut editor = builder.make_editor(vis_owner.syntax());
 
-        let vis_owner = edit.make_mut(vis_owner);
-        vis_owner.set_visibility(Some(missing_visibility.clone_for_update()));
+        if let Some(current_visibility) = vis_owner.visibility() {
+            editor.replace(current_visibility.syntax(), missing_visibility.syntax());
+        } else {
+            let vis_before = vis_owner
+                .syntax()
+                .children_with_tokens()
+                .find(|it| {
+                    !matches!(
+                        it.kind(),
+                        syntax::SyntaxKind::WHITESPACE
+                            | syntax::SyntaxKind::COMMENT
+                            | syntax::SyntaxKind::ATTR
+                    )
+                })
+                .unwrap_or_else(|| vis_owner.syntax().first_child_or_token().unwrap());
 
-        if let Some((cap, vis)) = ctx.config.snippet_cap.zip(vis_owner.visibility()) {
-            edit.add_tabstop_before(cap, vis);
+            editor.insert_all(
+                syntax::syntax_editor::Position::before(vis_before),
+                vec![missing_visibility.syntax().clone().into(), make.whitespace(" ").into()],
+            );
         }
+
+        if let Some(cap) = ctx.config.snippet_cap {
+            editor.add_annotation(missing_visibility.syntax(), builder.make_tabstop_before(cap));
+        }
+
+        builder.add_file_edits(target_file, editor);
     })
 }
 
diff --git a/crates/ide-assists/src/handlers/generate_derive.rs b/crates/ide-assists/src/handlers/generate_derive.rs
index 06fef4a..3ef68f0 100644
--- a/crates/ide-assists/src/handlers/generate_derive.rs
+++ b/crates/ide-assists/src/handlers/generate_derive.rs
@@ -1,7 +1,7 @@
 use syntax::{
     SyntaxKind::{ATTR, COMMENT, WHITESPACE},
     T,
-    ast::{self, AstNode, HasAttrs, edit::IndentLevel, make},
+    ast::{self, AstNode, HasAttrs, edit::IndentLevel, syntax_factory::SyntaxFactory},
     syntax_editor::{Element, Position},
 };
 
@@ -42,13 +42,15 @@
     };
 
     acc.add(AssistId::generate("generate_derive"), "Add `#[derive]`", target, |edit| {
+        let make = SyntaxFactory::without_mappings();
+
         match derive_attr {
             None => {
-                let derive = make::attr_outer(make::meta_token_tree(
-                    make::ext::ident_path("derive"),
-                    make::token_tree(T!['('], vec![]).clone_for_update(),
-                ))
-                .clone_for_update();
+                let derive =
+                    make.attr_outer(make.meta_token_tree(
+                        make.ident_path("derive"),
+                        make.token_tree(T!['('], vec![]),
+                    ));
 
                 let mut editor = edit.make_editor(nominal.syntax());
                 let indent = IndentLevel::from_node(nominal.syntax());
@@ -57,11 +59,12 @@
                     .children_with_tokens()
                     .find(|it| !matches!(it.kind(), WHITESPACE | COMMENT | ATTR))
                     .map_or(Position::first_child_of(nominal.syntax()), Position::before);
+
                 editor.insert_all(
                     after_attrs_and_comments,
                     vec![
                         derive.syntax().syntax_element(),
-                        make::tokens::whitespace(&format!("\n{indent}")).syntax_element(),
+                        make.whitespace(&format!("\n{indent}")).syntax_element(),
                     ],
                 );
 
@@ -72,7 +75,9 @@
                     .expect("failed to get token tree out of Meta")
                     .r_paren_token()
                     .expect("make::attr_outer was expected to have a R_PAREN");
+
                 let tabstop_before = edit.make_tabstop_before(cap);
+
                 editor.add_annotation(delimiter, tabstop_before);
                 edit.add_file_edits(ctx.vfs_file_id(), editor);
             }
diff --git a/crates/ide-assists/src/handlers/replace_if_let_with_match.rs b/crates/ide-assists/src/handlers/replace_if_let_with_match.rs
index d2452f2..dcadb53 100644
--- a/crates/ide-assists/src/handlers/replace_if_let_with_match.rs
+++ b/crates/ide-assists/src/handlers/replace_if_let_with_match.rs
@@ -57,7 +57,7 @@
     let if_exprs = successors(Some(if_expr.clone()), |expr| match expr.else_branch()? {
         ast::ElseBranch::IfExpr(expr) => Some(expr),
         ast::ElseBranch::Block(block) => {
-            let block = unwrap_trivial_block(block).clone_for_update();
+            let block = unwrap_trivial_block(block);
             else_block = Some(block.reset_indent().indent(IndentLevel(1)));
             None
         }
@@ -91,7 +91,7 @@
             guard
         };
 
-        let body = if_expr.then_branch()?.clone_for_update().indent(IndentLevel(1));
+        let body = if_expr.then_branch()?.indent(IndentLevel(1));
         cond_bodies.push((cond, guard, body));
     }
 
@@ -114,7 +114,7 @@
                 let make_match_arm =
                     |(pat, guard, body): (_, Option<ast::Expr>, ast::BlockExpr)| {
                         // Dedent from original position, then indent for match arm
-                        let body = body.dedent(indent).indent(IndentLevel::single());
+                        let body = body.dedent(indent);
                         let body = unwrap_trivial_block(body);
                         match (pat, guard.map(|it| make.match_guard(it))) {
                             (Some(pat), guard) => make.match_arm(pat, guard, body),
@@ -127,8 +127,8 @@
                         }
                     };
                 let arms = cond_bodies.into_iter().map(make_match_arm).chain([else_arm]);
-                let match_expr =
-                    make.expr_match(scrutinee_to_be_expr, make.match_arm_list(arms)).indent(indent);
+                let expr = scrutinee_to_be_expr.reset_indent();
+                let match_expr = make.expr_match(expr, make.match_arm_list(arms)).indent(indent);
                 match_expr.into()
             };
 
@@ -246,7 +246,7 @@
         first_arm.guard(),
         second_arm.guard(),
     )?;
-    let scrutinee = match_expr.expr()?;
+    let scrutinee = match_expr.expr()?.reset_indent();
     let guard = guard.and_then(|it| it.condition());
 
     let let_ = match &if_let_pat {
@@ -293,10 +293,8 @@
             } else {
                 condition
             };
-            let then_expr =
-                then_expr.clone_for_update().reset_indent().indent(IndentLevel::single());
-            let else_expr =
-                else_expr.clone_for_update().reset_indent().indent(IndentLevel::single());
+            let then_expr = then_expr.reset_indent();
+            let else_expr = else_expr.reset_indent();
             let then_block = make_block_expr(then_expr);
             let else_expr = if is_empty_expr(&else_expr) { None } else { Some(else_expr) };
             let if_let_expr = make
@@ -956,7 +954,9 @@
             r#"
 fn main() {
     if true {
-        $0if let Ok(rel_path) = path.strip_prefix(root_path) {
+        $0if let Ok(rel_path) = path.strip_prefix(root_path)
+            .and(x)
+        {
             let rel_path = RelativePathBuf::from_path(rel_path)
                 .ok()?;
             Some((*id, rel_path))
@@ -971,7 +971,8 @@
             r#"
 fn main() {
     if true {
-        match path.strip_prefix(root_path) {
+        match path.strip_prefix(root_path)
+            .and(x) {
             Ok(rel_path) => {
                 let rel_path = RelativePathBuf::from_path(rel_path)
                     .ok()?;
@@ -993,7 +994,9 @@
             r#"
 fn main() {
     if true {
-        $0if let Ok(rel_path) = path.strip_prefix(root_path) {
+        $0if let Ok(rel_path) = path.strip_prefix(root_path)
+            .and(x)
+        {
             Foo {
                 x: 1
             }
@@ -1008,7 +1011,8 @@
             r#"
 fn main() {
     if true {
-        match path.strip_prefix(root_path) {
+        match path.strip_prefix(root_path)
+            .and(x) {
             Ok(rel_path) => {
                 Foo {
                     x: 1
@@ -1023,7 +1027,33 @@
     }
 }
 "#,
-        )
+        );
+
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+fn main() {
+    if true {
+        $0if true
+            && false
+        {
+            foo()
+        }
+    }
+}
+"#,
+            r#"
+fn main() {
+    if true {
+        match true
+            && false {
+            true => foo(),
+            false => (),
+        }
+    }
+}
+"#,
+        );
     }
 
     #[test]
@@ -1878,7 +1908,9 @@
             r#"
 fn main() {
     if true {
-        $0match path.strip_prefix(root_path) {
+        $0match path.strip_prefix(root_path)
+            .and(x)
+        {
             Ok(rel_path) => Foo {
                 x: 2
             }
@@ -1892,7 +1924,8 @@
             r#"
 fn main() {
     if true {
-        if let Ok(rel_path) = path.strip_prefix(root_path) {
+        if let Ok(rel_path) = path.strip_prefix(root_path)
+            .and(x) {
             Foo {
                 x: 2
             }
@@ -1911,7 +1944,9 @@
             r#"
 fn main() {
     if true {
-        $0match path.strip_prefix(root_path) {
+        $0match path.strip_prefix(root_path)
+            .and(x)
+        {
             Ok(rel_path) => {
                 let rel_path = RelativePathBuf::from_path(rel_path)
                     .ok()?;
@@ -1929,7 +1964,8 @@
             r#"
 fn main() {
     if true {
-        if let Ok(rel_path) = path.strip_prefix(root_path) {
+        if let Ok(rel_path) = path.strip_prefix(root_path)
+            .and(x) {
             let rel_path = RelativePathBuf::from_path(rel_path)
                 .ok()?;
             Some((*id, rel_path))
diff --git a/crates/ide-completion/src/completions/pattern.rs b/crates/ide-completion/src/completions/pattern.rs
index eeb2c65..6e93281 100644
--- a/crates/ide-completion/src/completions/pattern.rs
+++ b/crates/ide-completion/src/completions/pattern.rs
@@ -95,7 +95,7 @@
                     if refutable || single_variant_enum(variant.parent_enum(ctx.db)) =>
                 {
                     acc.add_variant_pat(ctx, pattern_ctx, None, variant, Some(name.clone()));
-                    true
+                    false
                 }
                 hir::ModuleDef::Adt(hir::Adt::Enum(e)) => refutable || single_variant_enum(e),
                 hir::ModuleDef::Const(..) => refutable,
diff --git a/crates/ide-completion/src/tests/pattern.rs b/crates/ide-completion/src/tests/pattern.rs
index b872802..0d85f2e 100644
--- a/crates/ide-completion/src/tests/pattern.rs
+++ b/crates/ide-completion/src/tests/pattern.rs
@@ -122,7 +122,6 @@
             st Record
             st Tuple
             st Unit
-            ev TupleV
             bn Record {…} Record { field$1 }$0
             bn Tuple(…)            Tuple($1)$0
             bn TupleV(…)          TupleV($1)$0
@@ -159,8 +158,6 @@
         expect![[r#"
             en Bar
             st Foo
-            ev Nil
-            ev Value
             bn Foo {…} Foo { x$1 }$0
             bn Nil             Nil$0
             bn Value         Value$0
@@ -189,7 +186,6 @@
             st Record
             st Tuple
             st Unit
-            ev Variant
             bn Record {…} Record { field$1 }$0
             bn Tuple(…)            Tuple($1)$0
             bn Variant               Variant$0
@@ -355,6 +351,34 @@
 }
 
 #[test]
+fn enum_unqualified() {
+    check_with_base_items(
+        r#"
+use Enum::*;
+fn func() {
+    if let $0 = unknown {}
+}
+"#,
+        expect![[r#"
+            ct CONST
+            en Enum
+            ma makro!(…)      macro_rules! makro
+            md module
+            st Record
+            st Tuple
+            st Unit
+            bn Record {…}   Record { field$1 }$0
+            bn RecordV {…} RecordV { field$1 }$0
+            bn Tuple(…)              Tuple($1)$0
+            bn TupleV(…)            TupleV($1)$0
+            bn UnitV                     UnitV$0
+            kw mut
+            kw ref
+        "#]],
+    );
+}
+
+#[test]
 fn completes_in_record_field_pat() {
     check(
         r#"
diff --git a/crates/ide-completion/src/tests/record.rs b/crates/ide-completion/src/tests/record.rs
index 045b2d0..c1274f6 100644
--- a/crates/ide-completion/src/tests/record.rs
+++ b/crates/ide-completion/src/tests/record.rs
@@ -61,8 +61,6 @@
             en Baz
             en Result
             md core
-            ev Err
-            ev Ok
             bn Baz::Bar Baz::Bar$0
             bn Baz::Foo Baz::Foo$0
             bn Err(…)    Err($1)$0
@@ -89,10 +87,6 @@
             en Baz
             en Result
             md core
-            ev Bar
-            ev Err
-            ev Foo
-            ev Ok
             bn Bar        Bar$0
             bn Err(…) Err($1)$0
             bn Foo        Foo$0
diff --git a/crates/ide-diagnostics/src/handlers/invalid_cast.rs b/crates/ide-diagnostics/src/handlers/invalid_cast.rs
index 7479f81..405d8df 100644
--- a/crates/ide-diagnostics/src/handlers/invalid_cast.rs
+++ b/crates/ide-diagnostics/src/handlers/invalid_cast.rs
@@ -517,11 +517,13 @@
 
 fn add_auto<'a>(x: *mut dyn Trait<'a>) -> *mut (dyn Trait<'a> + Send) {
     x as _
+  //^^^^^^ error: cannot add auto trait to dyn bound via pointer cast
 }
 
 // (to test diagnostic list formatting)
 fn add_multiple_auto<'a>(x: *mut dyn Trait<'a>) -> *mut (dyn Trait<'a> + Send + Sync + Unpin) {
     x as _
+  //^^^^^^ error: cannot add auto trait to dyn bound via pointer cast
 }
 "#,
         );
diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs
index 654ff4f..b8ce3a8 100644
--- a/crates/load-cargo/src/lib.rs
+++ b/crates/load-cargo/src/lib.rs
@@ -26,7 +26,7 @@
 use itertools::Itertools;
 use proc_macro_api::{
     MacroDylib, ProcMacroClient,
-    bidirectional_protocol::msg::{SubRequest, SubResponse},
+    bidirectional_protocol::msg::{ParentSpan, SubRequest, SubResponse},
 };
 use project_model::{CargoConfig, PackageRoot, ProjectManifest, ProjectWorkspace};
 use span::{Span, SpanAnchor, SyntaxContext};
@@ -659,6 +659,44 @@
                     ctx: current_span.ctx.into_u32(),
                 })
             }
+            SubRequest::SpanParent { file_id, ast_id, start, end, ctx } => {
+                let span = Span {
+                    range: TextRange::new(TextSize::from(start), TextSize::from(end)),
+                    anchor: SpanAnchor {
+                        file_id: span::EditionedFileId::from_raw(file_id),
+                        ast_id: span::ErasedFileAstId::from_raw(ast_id),
+                    },
+                    // SAFETY: We only receive spans from the server. If someone mess up the communication UB can happen,
+                    // but that will be their problem.
+                    ctx: unsafe { SyntaxContext::from_u32(ctx) },
+                };
+
+                if let Some(macro_call_id) = span.ctx.outer_expn(db) {
+                    let macro_call_loc = db.lookup_intern_macro_call(macro_call_id.into());
+
+                    let call_site_file = macro_call_loc.kind.file_id();
+                    let call_site_ast_id = macro_call_loc.kind.erased_ast_id();
+
+                    if let Some(editioned_file_id) = call_site_file.file_id() {
+                        let range = db
+                            .ast_id_map(editioned_file_id.into())
+                            .get_erased(call_site_ast_id)
+                            .text_range();
+
+                        let parent_span = Some(ParentSpan {
+                            file_id: editioned_file_id.editioned_file_id(db).as_u32(),
+                            ast_id: span::ROOT_ERASED_FILE_AST_ID.into_raw(),
+                            start: u32::from(range.start()),
+                            end: u32::from(range.end()),
+                            ctx: macro_call_loc.ctxt.into_u32(),
+                        });
+
+                        return Ok(SubResponse::SpanParentResult { parent_span });
+                    }
+                }
+
+                Ok(SubResponse::SpanParentResult { parent_span: None })
+            }
         };
         match self.0.expand(
             subtree.view(),
diff --git a/crates/proc-macro-api/src/bidirectional_protocol/msg.rs b/crates/proc-macro-api/src/bidirectional_protocol/msg.rs
index 10a8d66..ab4bed8 100644
--- a/crates/proc-macro-api/src/bidirectional_protocol/msg.rs
+++ b/crates/proc-macro-api/src/bidirectional_protocol/msg.rs
@@ -22,6 +22,7 @@
     LineColumn { file_id: u32, ast_id: u32, offset: u32 },
     ByteRange { file_id: u32, ast_id: u32, start: u32, end: u32 },
     SpanSource { file_id: u32, ast_id: u32, start: u32, end: u32, ctx: u32 },
+    SpanParent { file_id: u32, ast_id: u32, start: u32, end: u32, ctx: u32 },
 }
 
 #[derive(Debug, Serialize, Deserialize)]
@@ -50,12 +51,24 @@
         end: u32,
         ctx: u32,
     },
+    SpanParentResult {
+        parent_span: Option<ParentSpan>,
+    },
     Cancel {
         reason: String,
     },
 }
 
 #[derive(Debug, Serialize, Deserialize)]
+pub struct ParentSpan {
+    pub file_id: u32,
+    pub ast_id: u32,
+    pub start: u32,
+    pub end: u32,
+    pub ctx: u32,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
 pub enum BidirectionalMessage {
     Request(Request),
     Response(Response),
diff --git a/crates/proc-macro-srv-cli/src/main_loop.rs b/crates/proc-macro-srv-cli/src/main_loop.rs
index 2c54b18..c525ed8 100644
--- a/crates/proc-macro-srv-cli/src/main_loop.rs
+++ b/crates/proc-macro-srv-cli/src/main_loop.rs
@@ -309,6 +309,40 @@
             other => handle_failure(other),
         }
     }
+
+    fn span_parent(
+        &mut self,
+        proc_macro_srv::span::Span { range, anchor, ctx }: proc_macro_srv::span::Span,
+    ) -> Option<proc_macro_srv::span::Span> {
+        let response = self.roundtrip(bidirectional::SubRequest::SpanParent {
+            file_id: anchor.file_id.as_u32(),
+            ast_id: anchor.ast_id.into_raw(),
+            start: range.start().into(),
+            end: range.end().into(),
+            ctx: ctx.into_u32(),
+        });
+
+        match response {
+            Ok(bidirectional::SubResponse::SpanParentResult { parent_span }) => {
+                parent_span.map(|bidirectional::ParentSpan { file_id, ast_id, start, end, ctx }| {
+                    proc_macro_srv::span::Span {
+                        range: proc_macro_srv::span::TextRange::new(
+                            proc_macro_srv::span::TextSize::new(start),
+                            proc_macro_srv::span::TextSize::new(end),
+                        ),
+                        anchor: proc_macro_srv::span::SpanAnchor {
+                            file_id: proc_macro_srv::span::EditionedFileId::from_raw(file_id),
+                            ast_id: proc_macro_srv::span::ErasedFileAstId::from_raw(ast_id),
+                        },
+                        // SAFETY: spans originate from the server. If the protocol is violated,
+                        // undefined behavior is the caller’s responsibility.
+                        ctx: unsafe { proc_macro_srv::span::SyntaxContext::from_u32(ctx) },
+                    }
+                })
+            }
+            other => handle_failure(other),
+        }
+    }
 }
 
 fn handle_expand_ra(
diff --git a/crates/proc-macro-srv/src/lib.rs b/crates/proc-macro-srv/src/lib.rs
index 6b770e4..65de804 100644
--- a/crates/proc-macro-srv/src/lib.rs
+++ b/crates/proc-macro-srv/src/lib.rs
@@ -121,6 +121,7 @@
 
     fn byte_range(&mut self, span: Span) -> Range<usize>;
     fn span_source(&mut self, span: Span) -> Span;
+    fn span_parent(&mut self, span: Span) -> Option<Span>;
 }
 
 const EXPANDER_STACK_SIZE: usize = 8 * 1024 * 1024;
diff --git a/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
index 5eb16c3..6b6bfcc 100644
--- a/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
+++ b/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
@@ -164,8 +164,10 @@
         self.callback.as_mut()?.source_text(span)
     }
 
-    fn span_parent(&mut self, _span: Self::Span) -> Option<Self::Span> {
-        // FIXME requires db, looks up the parent call site
+    fn span_parent(&mut self, span: Self::Span) -> Option<Self::Span> {
+        if let Some(ref mut callback) = self.callback {
+            return callback.span_parent(span);
+        }
         None
     }
     fn span_source(&mut self, span: Self::Span) -> Self::Span {
diff --git a/crates/proc-macro-srv/src/tests/utils.rs b/crates/proc-macro-srv/src/tests/utils.rs
index 28d826d..31beca2 100644
--- a/crates/proc-macro-srv/src/tests/utils.rs
+++ b/crates/proc-macro-srv/src/tests/utils.rs
@@ -146,6 +146,10 @@
     fn span_source(&mut self, span: Span) -> Span {
         span
     }
+
+    fn span_parent(&mut self, _span: Span) -> Option<Span> {
+        None
+    }
 }
 
 pub fn assert_expand_with_callback(
diff --git a/crates/project-model/src/cargo_config_file.rs b/crates/project-model/src/cargo_config_file.rs
index ae36deb..9c7f109 100644
--- a/crates/project-model/src/cargo_config_file.rs
+++ b/crates/project-model/src/cargo_config_file.rs
@@ -158,14 +158,15 @@
             build: semver::BuildMetadata::EMPTY,
         };
 
-    const MINIMUM_TOOLCHAIN_VERSION_SUPPORTING_LOCKFILE_PATH_ENV: semver::Version =
-        semver::Version {
-            major: 1,
-            minor: 95,
-            patch: 0,
-            pre: semver::Prerelease::EMPTY,
-            build: semver::BuildMetadata::EMPTY,
-        };
+    // TODO: turn this into a const and remove pre once 1.95 is stable
+    #[allow(non_snake_case)]
+    let MINIMUM_TOOLCHAIN_VERSION_SUPPORTING_LOCKFILE_PATH_ENV: semver::Version = semver::Version {
+        major: 1,
+        minor: 95,
+        patch: 0,
+        pre: semver::Prerelease::new("nightly").unwrap(),
+        build: semver::BuildMetadata::EMPTY,
+    };
 
     let usage = if *toolchain_version >= MINIMUM_TOOLCHAIN_VERSION_SUPPORTING_LOCKFILE_PATH_ENV {
         LockfileUsage::WithEnvVar
diff --git a/crates/rust-analyzer/src/handlers/dispatch.rs b/crates/rust-analyzer/src/handlers/dispatch.rs
index 90deae2..67bd643 100644
--- a/crates/rust-analyzer/src/handlers/dispatch.rs
+++ b/crates/rust-analyzer/src/handlers/dispatch.rs
@@ -414,7 +414,8 @@
         let params = match not.extract::<N::Params>(N::METHOD) {
             Ok(it) => it,
             Err(ExtractError::JsonError { method, error }) => {
-                panic!("Invalid request\nMethod: {method}\n error: {error}",)
+                tracing::error!(method = %method, error = %error, "invalid notification");
+                return self;
             }
             Err(ExtractError::MethodMismatch(not)) => {
                 self.not = Some(not);
diff --git a/crates/syntax/src/ast/syntax_factory/constructors.rs b/crates/syntax/src/ast/syntax_factory/constructors.rs
index 6e17d26..2718219 100644
--- a/crates/syntax/src/ast/syntax_factory/constructors.rs
+++ b/crates/syntax/src/ast/syntax_factory/constructors.rs
@@ -79,8 +79,12 @@
         make::path_concat(first, second).clone_for_update()
     }
 
+    pub fn visibility_pub_crate(&self) -> ast::Visibility {
+        make::visibility_pub_crate().clone_for_update()
+    }
+
     pub fn visibility_pub(&self) -> ast::Visibility {
-        make::visibility_pub()
+        make::visibility_pub().clone_for_update()
     }
 
     pub fn struct_(