diff --git a/crates/ide/src/inlay_hints/closing_brace.rs b/crates/ide/src/inlay_hints/closing_brace.rs
index 3767d34e2c7a..1836dbc8c904 100644
--- a/crates/ide/src/inlay_hints/closing_brace.rs
+++ b/crates/ide/src/inlay_hints/closing_brace.rs
@@ -7,8 +7,8 @@ use hir::{HirDisplay, Semantics};
 use ide_db::{FileRange, RootDatabase};
 use span::EditionedFileId;
 use syntax::{
-    ast::{self, AstNode, HasLoopBody, HasName},
-    match_ast, SyntaxKind, SyntaxNode, T,
+    ast::{self, AstNode, HasGenericParams, HasLoopBody, HasName, HasVisibility},
+    match_ast, SyntaxKind, SyntaxNode, SyntaxToken, T,
 };
 
 use crate::{
@@ -16,6 +16,7 @@ use crate::{
     InlayKind,
 };
 
+/// Applies closing-brace inlay hints to this syntax node.
 pub(super) fn hints(
     acc: &mut Vec<InlayHint>,
     sema: &Semantics<'_, RootDatabase>,
@@ -23,113 +24,304 @@ pub(super) fn hints(
     file_id: EditionedFileId,
     original_node: SyntaxNode,
 ) -> Option<()> {
+    // If `config.closing_brace_hints_min_lines == None`, closing brace hints are disabled.
     let min_lines = config.closing_brace_hints_min_lines?;
 
-    let name = |it: ast::Name| it.syntax().text_range();
-
-    let mut node = original_node.clone();
-    let mut closing_token;
-    let (label, name_range) = if let Some(item_list) = ast::AssocItemList::cast(node.clone()) {
-        closing_token = item_list.r_curly_token()?;
-
-        let parent = item_list.syntax().parent()?;
-        match_ast! {
-            match parent {
-                ast::Impl(imp) => {
-                    let imp = sema.to_def(&imp)?;
-                    let ty = imp.self_ty(sema.db);
-                    let trait_ = imp.trait_(sema.db);
-                    let hint_text = match trait_ {
-                        Some(tr) => format!(
-                            "impl {} for {}",
-                            tr.name(sema.db).display(sema.db, file_id.edition()),
-                            ty.display_truncated(sema.db, config.max_length, file_id.edition(),
-                        )),
-                        None => format!("impl {}", ty.display_truncated(sema.db, config.max_length, file_id.edition())),
-                    };
-                    (hint_text, None)
-                },
-                ast::Trait(tr) => {
-                    (format!("trait {}", tr.name()?), tr.name().map(name))
-                },
-                _ => return None,
-            }
-        }
-    } else if let Some(list) = ast::ItemList::cast(node.clone()) {
-        closing_token = list.r_curly_token()?;
-
-        let module = ast::Module::cast(list.syntax().parent()?)?;
-        (format!("mod {}", module.name()?), module.name().map(name))
-    } else if let Some(label) = ast::Label::cast(node.clone()) {
-        // in this case, `ast::Label` could be seen as a part of `ast::BlockExpr`
-        // the actual number of lines in this case should be the line count of the parent BlockExpr,
-        // which the `min_lines` config cares about
-        node = node.parent()?;
-
-        let parent = label.syntax().parent()?;
-        let block;
-        match_ast! {
-            match parent {
-                ast::BlockExpr(block_expr) => {
-                    block = block_expr.stmt_list()?;
-                },
-                ast::AnyHasLoopBody(loop_expr) => {
-                    block = loop_expr.loop_body()?.stmt_list()?;
-                },
-                _ => return None,
-            }
-        }
-        closing_token = block.r_curly_token()?;
-
-        let lifetime = label.lifetime()?.to_string();
-
-        (lifetime, Some(label.syntax().text_range()))
-    } else if let Some(block) = ast::BlockExpr::cast(node.clone()) {
-        closing_token = block.stmt_list()?.r_curly_token()?;
-
-        let parent = block.syntax().parent()?;
-        match_ast! {
-            match parent {
-                ast::Fn(it) => {
-                    // FIXME: this could include parameters, but `HirDisplay` prints too much info
-                    // and doesn't respect the max length either, so the hints end up way too long
-                    (format!("fn {}", it.name()?), it.name().map(name))
-                },
-                ast::Static(it) => (format!("static {}", it.name()?), it.name().map(name)),
-                ast::Const(it) => {
-                    if it.underscore_token().is_some() {
-                        ("const _".into(), None)
-                    } else {
-                        (format!("const {}", it.name()?), it.name().map(name))
+    // FIXME: `ast::WhereClause` members of functions, structs, etc. are not currently included in closing brace inlay hints,
+    //   because formatting them was annoying.
+    // It would be nice to include sufficiently-short where clauses in the output.
+
+    // Check if `node` is block-like. If it is, display an inlay hint based on the type of its parent.
+    let node = original_node.clone();
+    let inlay_hint = match_ast! {
+        match (node) {
+            ast::AssocItemList(item_list) => {
+                let closing_token = item_list.r_curly_token()?;
+
+                let parent = item_list.syntax().parent()?;
+                match_ast! {
+                    match parent {
+                        ast::Impl(imp) => {
+                            let imp = sema.to_def(&imp)?;
+                            let ty = imp.self_ty(sema.db);
+                            let trait_ = imp.trait_(sema.db);
+                            let text = match trait_ {
+                                Some(tr) => format!(
+                                    "impl {} for {}",
+                                    tr.name(sema.db).display(sema.db, file_id.edition()),
+                                    ty.display_truncated(sema.db, config.max_length, file_id.edition(),
+                                )),
+                                None => format!("impl {}", ty.display_truncated(sema.db, config.max_length, file_id.edition())),
+                            };
+                            to_inlay_hint(config, min_lines, file_id, node, closing_token, &text, None)
+                        },
+                        ast::Trait(tr) => {
+                            let text = format!("trait {}", tr.name()?);
+                            to_inlay_hint(config, min_lines, file_id, node, closing_token, &text, Some(tr.name()?.syntax()))
+                        },
+                        _ => return None,
                     }
-                },
-                _ => return None,
+                }
+            },
+            ast::ItemList(list) => {
+                // `node` is the item list of a `module` declaration.
+                let closing_token = list.r_curly_token()?;
+                let module = ast::Module::cast(list.syntax().parent()?)?;
+                let text = format!("mod {}", module.name()?);
+                to_inlay_hint(config, min_lines, file_id, node, closing_token, &text, Some(module.name()?.syntax()))
+            },
+            ast::BlockExpr(block) => {
+                let closing_token = block.stmt_list()?.r_curly_token()?;
+
+                let parent = block.syntax().parent()?;
+                match_ast! {
+                    match parent {
+                        ast::Fn(it) => {
+                            let visibility_text = it.visibility().map_or(String::new(), |it| format!("{it} "));
+                            let default_text = it.default_token().map_or(String::new(), |it| format!("{it} "));
+                            let const_text = it.const_token().map_or(String::new(), |it| format!("{it} "));
+                            let async_text = it.async_token().map_or(String::new(), |it| format!("{it} "));
+                            let unsafe_text = it.unsafe_token().map_or(String::new(), |it| format!("{it} "));
+                            let safe_text = it.safe_token().map_or(String::new(), |it| format!("{it} "));
+                            let abi_text = it.abi().map_or(String::new(), |it| format!("{it} "));
+                            let name_text = format!(" {}", it.name()?);
+                            let generic_param_text = it.generic_param_list().map_or(String::new(), |it| format!("{it}"));
+                            let param_text = it.param_list().map_or(String::new(), |it| format!("{it}"));
+                            let ret_type_text = it.ret_type().map_or(String::new(), |it| format!(" {it}"));
+
+                            let text = format!("{visibility_text}{default_text}{const_text}{async_text}{unsafe_text}{safe_text}{abi_text}fn{name_text}{generic_param_text}{param_text}{ret_type_text}");
+                            to_inlay_hint(config, min_lines, file_id, node, closing_token, &text, it.name().as_ref().map(|it| it.syntax()))
+                        },
+                        ast::Static(it) => {
+                            let text = format!("static {}", it.name()?);
+                            to_inlay_hint(config, min_lines, file_id, node, closing_token, &text, it.name().as_ref().map(|it| it.syntax()))
+                        },
+                        ast::Const(it) => {
+                            let ty_text = it.ty().map_or(String::new(), |it| format!(": {it}"));
+
+                            if it.underscore_token().is_some() {
+                                let text = format!("const _{ty_text}");
+                                to_inlay_hint(config, min_lines, file_id, node, closing_token, &text, None)
+                            } else {
+                                let text = format!("const {}{}", it.name()?, ty_text);
+                                to_inlay_hint(config, min_lines, file_id, node, closing_token, &text, None)
+                            }
+                        },
+                        ast::LoopExpr(it) => {
+                            let label_text = it.label().and_then(|it| it.lifetime()).map_or(String::new(), |it| format!("{it}: "));
+                            let text = format!("{label_text}loop");
+                            to_inlay_hint(config, min_lines, file_id, node, closing_token, &text, None)
+                        },
+                        ast::WhileExpr(it) => {
+                            let label_text = it.label().and_then(|it| it.lifetime()).map_or(String::new(), |it| format!("{it}: "));
+                            let condition = it.condition();
+                            let condition_text = condition.clone().map_or(String::new(), |it| format!(" {it}"));
+                            let text = format!("{label_text}while{condition_text}");
+                            to_inlay_hint(config, min_lines, file_id, node, closing_token, &text, None)
+                        },
+                        ast::ForExpr(it) => {
+                            let label_text = it.label().and_then(|it| it.lifetime()).map_or(String::new(), |it| format!("{it}: "));
+                            let pattern_text = it.pat().map_or(String::new(), |it| format!(" {it} "));
+                            let iterable_text = it.iterable().map_or(String::new(), |it| format!(" {it}"));
+                            let text = format!("{label_text}for{pattern_text}in{iterable_text}");
+                            to_inlay_hint(config, min_lines, file_id, node, closing_token, &text, None)
+                        },
+                        ast::ClosureExpr(it) => {
+                            let const_text = it.const_token().map_or(String::new(), |it| format!("{it} "));
+                            let static_text = it.static_token().map_or(String::new(), |it| format!("{it} "));
+                            let move_text = it.move_token().map_or(String::new(), |it| format!("{it} "));
+                            let param_text = it.param_list().clone().map_or(String::new(), |it| format!("{it}"));
+                            let ret_type_text = it.ret_type().map_or(String::new(), |it| format!(" {it}"));
+                            let text = format!("{const_text}{static_text}{move_text}{param_text}{ret_type_text}");
+                            to_inlay_hint(config, min_lines, file_id, node, closing_token, &text, None)
+                        },
+                        ast::MatchArm(it) => {
+                            let pattern_text = it.pat().map_or(String::new(), |it| format!("{it}"));
+                            let guard_text = it.guard().map_or(String::new(), |it| format!(" {it}"));
+                            let text = format!("{pattern_text}{guard_text}");
+                            to_inlay_hint(config, min_lines, file_id, node, closing_token, &text, None)
+                        },
+                        ast::IfExpr(parent) => {
+                            // `node` is the then-branch or the else-branch of the parent if-expression.
+                            let then_branch = parent.then_branch()?;
+                            let then_branch = then_branch.syntax();
+
+                            if node == *then_branch {
+                                // `node` is the then-branch.
+                                // Check whether `parent` is the else-branch of another parent if-expr.
+                                let parent_is_else_branch = parent.syntax().parent().and_then(ast::IfExpr::cast).is_some();
+                                let else_text = if parent_is_else_branch {"else "} else {""}.to_owned();
+
+                                let condition_text = parent.condition().map_or(String::new(), |it| format!(" {it}"));
+                                let if_text = format!("{else_text}if{condition_text}");
+                                to_inlay_hint(config, min_lines, file_id, node, closing_token, &if_text, None)
+                            } else {
+                                // `node` is the else-branch.
+                                match parent.else_branch()? {
+                                    ast::ElseBranch::Block(_) => to_inlay_hint(config, min_lines, file_id, node, closing_token, "else", None),
+                                    ast::ElseBranch::IfExpr(_) => {
+                                        // Since the else branch is an if-expr, it will have its own then- and else-branches.
+                                        return None;
+                                    }
+                                }
+                            }
+                        },
+                        _ => {
+                            // Bare block. Check for labels and modifiers.
+                            let label_lifetime = block.label().and_then(|it| it.lifetime());
+                            let async_token = block.async_token();
+                            let move_token = block.move_token();
+                            let const_token = block.const_token();
+                            let unsafe_token = block.unsafe_token();
+                            let try_token = block.try_token();
+
+                            if label_lifetime.is_none() && async_token.is_none() && move_token.is_none()
+                                && const_token.is_none() && unsafe_token.is_none() && try_token.is_none() {
+                                    return None;
+                            }
+
+                            let label_text = label_lifetime.map_or(String::new(), |it| format!("{it}: "));
+                            let async_text = async_token.map_or(String::new(), |it| format!("{it} "));
+                            let move_text = move_token.map_or(String::new(), |it| format!("{it} "));
+                            let const_text = const_token.map_or(String::new(), |it| format!("{it} "));
+                            let unsafe_text = unsafe_token.map_or(String::new(), |it| format!("{it} "));
+                            let try_text = try_token.map_or(String::new(), |it| format!("{it} "));
+
+                            let text = format!("{label_text}{async_text}{move_text}{const_text}{unsafe_text}{try_text}");
+                            let text = text.trim_end();
+                            to_inlay_hint(config, min_lines, file_id, node, closing_token, text, None)
+                        }
+                    }
+                }
+            },
+            ast::MacroCall(mac) => {
+                let last_token = mac.syntax().last_token()?;
+                if last_token.kind() != T![;] && last_token.kind() != SyntaxKind::R_CURLY {
+                    return None;
+                }
+                let closing_token = last_token;
+                let text = format!("{}!", mac.path()?);
+                let target_node = mac.path().and_then(|it| it.segment());
+                let target_node = target_node.as_ref().map(|it| it.syntax());
+
+                to_inlay_hint(config, min_lines, file_id, node, closing_token, &text, target_node)
+            },
+            ast::MatchArmList(arm_list) => {
+                // `node` is the block (`MatchArmsList`) of a match expression.
+                let closing_token = arm_list.r_curly_token()?;
+                let match_expr = arm_list.syntax().parent()?;
+                let match_expr = ast::MatchExpr::cast(match_expr)?;
+
+                let matched_expr_text = match_expr.expr().map_or(String::new(), |it| format!(" {it}"));
+                let text = format!("match{matched_expr_text}");
+
+                to_inlay_hint(config, min_lines, file_id, node, closing_token, &text, None)
+            },
+            ast::RecordFieldList(record_field_list) => {
+                // `node` is one of:
+                // - the record field list of a struct
+                // - the record field list of an enum variant
+                // - the record field list of a union
+                let closing_token = record_field_list.r_curly_token()?;
+                let parent = record_field_list.syntax().parent()?;
+
+                match_ast! {
+                    match parent {
+                        ast::Struct(strukt) => {
+                            let visibility_text = strukt.visibility().map_or(String::new(), |it| format!("{it} "));
+                            let name_text = strukt.name().map_or(String::new(), |it| format!(" {it}"));
+                            let generic_param_text =
+                                strukt.generic_param_list().map_or(String::new(), |it| format!("{it}"));
+                            let text = format!("{visibility_text}struct{name_text}{generic_param_text}");
+                            to_inlay_hint(config, min_lines, file_id, node, closing_token, &text, strukt.name().as_ref().map(|it| it.syntax()))
+                        },
+                        ast::Variant(variant) => {
+                            let visibility_text = variant.visibility().map_or(String::new(), |it| format!("{it} "));
+                            let name_text = variant.name().map_or(String::new(), |it| format!("{it}"));
+                            let text = format!("{visibility_text}{name_text}");
+
+                            to_inlay_hint(config, min_lines, file_id, node, closing_token, &text, variant.name().as_ref().map(|it| it.syntax()))
+                        },
+                        ast::Union(parent_union) => {
+                            let visibility_text = parent_union.visibility().map_or(String::new(), |it| format!("{it} "));
+                            let name_text = parent_union.name().map_or(String::new(), |it| format!(" {it}"));
+                            let generic_param_text =
+                                parent_union.generic_param_list().map_or(String::new(), |it| format!("{it}"));
+                            let text = format!("{visibility_text}union{name_text}{generic_param_text}");
+
+                            to_inlay_hint(config, min_lines, file_id, node, closing_token, &text, parent_union.name().as_ref().map(|it| it.syntax()))
+                        },
+                        _ => { return None; }
+                    }
+                }
+            },
+            ast::VariantList(variant_list) => {
+                // `node` is the variant list of an enum
+                let closing_token = variant_list.r_curly_token()?;
+                let parent_enum = variant_list.syntax().parent()?;
+                let parent_enum = ast::Enum::cast(parent_enum)?;
+                let visibility_text = parent_enum.visibility().map_or(String::new(), |it| format!("{it} "));
+                let name_text = parent_enum.name().map_or(String::new(), |it| format!(" {it}"));
+                let generic_param_text =
+                    parent_enum.generic_param_list().map_or(String::new(), |it| format!("{it}"));
+                let text = format!("{visibility_text}enum{name_text}{generic_param_text}");
+
+                to_inlay_hint(config, min_lines, file_id, node, closing_token, &text, parent_enum.name().as_ref().map(|it| it.syntax()))
+            },
+            _ => {
+                return None;
             }
         }
-    } else if let Some(mac) = ast::MacroCall::cast(node.clone()) {
-        let last_token = mac.syntax().last_token()?;
-        if last_token.kind() != T![;] && last_token.kind() != SyntaxKind::R_CURLY {
-            return None;
-        }
-        closing_token = last_token;
+    }?;
+    acc.push(inlay_hint);
 
-        (
-            format!("{}!", mac.path()?),
-            mac.path().and_then(|it| it.segment()).map(|it| it.syntax().text_range()),
-        )
-    } else {
-        return None;
+    None
+}
+
+fn to_inlay_hint(
+    config: &InlayHintsConfig,
+    min_lines: usize,
+    file_id: EditionedFileId,
+    node: SyntaxNode,
+    mut closing_token: SyntaxToken,
+    label_text: &str,
+    target_node: Option<&SyntaxNode>,
+) -> Option<InlayHint> {
+    // FIXME: To keep inlay hints from getting too long, we directly truncate them to a certain length.
+    // It would probably be better to update the `HirDisplay::hir_fmt` implementations,
+    //  to respect `HirDisplayWrapper` and intelligently truncate sub-tokens,
+    //  which would let us use `HirDisplay::display_truncated` for the inlay hints.
+    let join_and_truncate = |label: &str| -> String {
+        let max_length = config.max_length;
+        let mut label = label.replace('\n', " ");
+
+        label = format!("// {label}");
+        match max_length {
+            Some(max_length) => {
+                if label.len() > max_length {
+                    label.truncate(usize::saturating_sub(max_length, 1));
+                    label.push('…');
+                    label
+                } else {
+                    label
+                }
+            }
+            None => label.to_string(),
+        }
     };
 
+    let label_text = join_and_truncate(label_text);
+    let target_range = target_node.map(|it| it.text_range());
+
     if let Some(mut next) = closing_token.next_token() {
-        if next.kind() == T![;] {
+        if next.kind() == T![;] || next.kind() == T![,] {
             if let Some(tok) = next.next_token() {
                 closing_token = next;
                 next = tok;
             }
         }
         if !(next.kind() == SyntaxKind::WHITESPACE && next.text().contains('\n')) {
-            // Only display the hint if the `}` is the last token on the line
+            // Only display the hint if the `}` or `};` is the last token on the line
             return None;
         }
     }
@@ -140,19 +332,22 @@ pub(super) fn hints(
         return None;
     }
 
-    let linked_location = name_range.map(|range| FileRange { file_id: file_id.into(), range });
-    acc.push(InlayHint {
+    let linked_location = target_range.map(|range| FileRange { file_id: file_id.into(), range });
+    InlayHint {
         range: closing_token.text_range(),
         kind: InlayKind::ClosingBrace,
-        label: InlayHintLabel::simple(label, None, linked_location.map(LazyProperty::Computed)),
+        label: InlayHintLabel::simple(
+            label_text,
+            None,
+            linked_location.map(LazyProperty::Computed),
+        ),
         text_edit: None,
         position: InlayHintPosition::After,
         pad_left: true,
         pad_right: false,
-        resolve_parent: Some(original_node.text_range()),
-    });
-
-    None
+        resolve_parent: Some(node.text_range()),
+    }
+    .into()
 }
 
 #[cfg(test)]
@@ -172,93 +367,445 @@ fn a() {}
 fn f() {
 } // no hint unless `}` is the last token on the line
 
-fn g() {
+fn g() -> bool {
+    false
   }
-//^ fn g
+//^ // fn g() -> bool
 
 fn h<T>(with: T, arguments: u8, ...) {
   }
-//^ fn h
+//^ // fn h<T>(with: T, arguments: u8, ...)
+
+pub fn f_pub() {
+  }
+//^ // pub fn f_pub()
+
+const fn f_const() {
+  }
+//^ // const fn f_const()
+
+default fn f_default() {
+  }
+//^ // default fn f_default()
+
+safe fn f_safe() {
+  }
+//^ // safe fn f_safe()
+
+unsafe fn f_unsafe() {
+  }
+//^ // unsafe fn f_unsafe()
+
+async fn f_async() {
+  }
+//^ // async fn f_async()
+
+extern "C" fn f_abi() {
+  }
+//^ // extern "C" fn f_abi()
 
 trait Tr {
     fn f();
     fn g() {
     }
-  //^ fn g
+  //^ // fn g()
   }
-//^ trait Tr
+//^ // trait Tr
 impl Tr for () {
   }
-//^ impl Tr for ()
+//^ // impl Tr for ()
 impl dyn Tr {
   }
-//^ impl dyn Tr
+//^ // impl dyn Tr
 
 static S0: () = 0;
 static S1: () = {};
 static S2: () = {
  };
-//^ static S2
+//^ // static S2
 const _: () = {
  };
-//^ const _
+//^ // const _: ()
 
 mod m {
   }
-//^ mod m
+//^ // mod m
 
 m! {}
 m!();
 m!(
  );
-//^ m!
+//^ // m!
 
 m! {
   }
-//^ m!
+//^ // m!
 
 fn f() {
     let v = vec![
     ];
   }
-//^ fn f
+//^ // fn f()
 "#,
         );
     }
 
     #[test]
-    fn hints_closing_brace_for_block_expr() {
+    fn hints_closing_brace_loop_expr() {
+        check_with_config(
+            InlayHintsConfig { closing_brace_hints_min_lines: Some(2), ..DISABLED_CONFIG },
+            r#"
+fn wrap_loops() {
+    'a: loop {
+        loop {
+            break 'a;
+        }
+      //^ // loop
+    }
+  //^ // 'a: loop
+  }
+//^ // fn wrap_loops()
+            "#,
+        );
+    }
+
+    #[test]
+    fn hints_closing_brace_block_expr() {
         check_with_config(
             InlayHintsConfig { closing_brace_hints_min_lines: Some(2), ..DISABLED_CONFIG },
             r#"
-fn test() {
-    'end: {
-        'do_a: {
-            'do_b: {
 
-            }
-          //^ 'do_b
-            break 'end;
+    let block: ast::BlockExpr = todo!();
+    let label_lifetime = block.label().map(|it| it.lifetime()).flatten();
+    let async_token = block.async_token();
+    let move_token = block.move_token();
+    let const_token = block.const_token();
+    let unsafe_token = block.unsafe_token();
+    let try_token = block.try_token();
+fn wrap_blocks() {
+    'a: {
+        {
         }
-      //^ 'do_a
     }
-  //^ 'end
+  //^ // 'a:
 
-    'a: loop {
-        'b: for i in 0..5 {
-            'c: while true {
+    async {
+        async move {
+        }
+      //^ // async move
+    }
+  //^ // async
 
+    unsafe {
+    }
+  //^ // unsafe
 
-            }
-          //^ 'c
+    try {
+    }
+  //^ // try
+  }
+//^ // fn wrap_blocks()
+            "#,
+        );
+    }
+
+    #[test]
+    fn hints_closing_brace_while_expr() {
+        check_with_config(
+            InlayHintsConfig { closing_brace_hints_min_lines: Some(2), ..DISABLED_CONFIG },
+            r#"
+fn while_wrapper() {
+    while true {
+        'a: while true {
         }
-      //^ 'b
+      //^ // 'a: while true
     }
-  //^ 'a
+  //^ // while true
 
+    let a = false;
+    while a {
+        'a: while a {
+        }
+      //^ // 'a: while a
+    }
+  //^ // while a
+
+    fn b() -> bool { true }
+    while b() {
+        'b: while b() {
+        }
+      //^ // 'b: while b()
+    }
+  //^ // while b()
   }
-//^ fn test
-"#,
+//^ // fn while_wrapper()
+            "#,
+        );
+    }
+
+    #[test]
+    fn hints_closing_brace_while_let_expr() {
+        check_with_config(
+            InlayHintsConfig { closing_brace_hints_min_lines: Some(2), ..DISABLED_CONFIG },
+            r#"
+fn while_let_wrapper() {
+    while let Some(val) = None {
+    }
+  //^ // while let Some(val) = None
+  }
+//^ // fn while_let_wrapper()
+            "#,
+        );
+    }
+
+    #[test]
+    fn hints_closing_brace_for_in_expr() {
+        check_with_config(
+            InlayHintsConfig { closing_brace_hints_min_lines: Some(2), ..DISABLED_CONFIG },
+            r#"
+fn for_in_wrapper() {
+    for _ in 0..=10 {
+        'a: for _ in 0..=10 {
+        }
+      //^ // 'a: for _ in 0..=10
+    }
+  //^ // for _ in 0..=10
+  }
+//^ // fn for_in_wrapper()
+            "#,
+        );
+    }
+
+    #[test]
+    fn hints_closing_brace_closure_expr() {
+        check_with_config(
+            InlayHintsConfig { closing_brace_hints_min_lines: Some(2), ..DISABLED_CONFIG },
+            r#"
+fn closure_wrapper() {
+    let a = || {
+        0
+    };
+   //^ // ||
+
+    let b = |_: u32| {
+        0
+    };
+   //^ // |_: u32|
+
+   let c = |_: u64| -> u64 {
+        0
+   };
+  //^ // |_: u64| -> u64
+  }
+//^ // fn closure_wrapper()
+            "#,
+        );
+    }
+
+    #[test]
+    fn hints_closing_brace_match_expr() {
+        check_with_config(
+            InlayHintsConfig { closing_brace_hints_min_lines: Some(2), ..DISABLED_CONFIG },
+            r#"
+enum Example {
+    A(u32),
+    B(u32, u32),
+    C(u32, u32, u32)
+  }
+//^ // enum Example
+
+fn match_wrapper() {
+    match Example::C(1, 2, 3) {
+        Example::A(a) => {
+            a
+        },
+       //^ // Example::A(a)
+        Example::B(b1, b2) => {
+            b1 + b2
+        },
+       //^ // Example::B(b1, b2)
+        Example::C(c1, c2, c3) => {
+            c1 * c2 * c3
+        }
+      //^ // Example::C(c1, c2, c3)
+    };
+   //^ // match Example::C(1, 2, 3)
+  }
+//^ // fn match_wrapper()
+            "#,
+        );
+    }
+
+    #[test]
+    fn hints_closing_brace_struct() {
+        check_with_config(
+            InlayHintsConfig { closing_brace_hints_min_lines: Some(2), ..DISABLED_CONFIG },
+            r#"
+struct NoInlayHint
+;
+
+pub(in crate::foo) struct A {
+  }
+//^ // pub(in crate::foo) struct A
+
+struct B {
+    a: u32,
+    b: u32,
+  }
+//^ // struct B
+
+struct C<'a, const T_A: u32, T_B> {
+    a: &'a u32,
+    b: T_B,
+  }
+//^ // struct C<'a, const T_A: u32, T_B>
+
+            "#,
+        );
+    }
+
+    #[test]
+    fn hints_closing_brace_enum() {
+        check_with_config(
+            InlayHintsConfig { closing_brace_hints_min_lines: Some(2), ..DISABLED_CONFIG },
+            r#"
+pub(in crate::foo) enum A {
+  }
+//^ // pub(in crate::foo) enum A
+
+enum B {
+    A,
+    B,
+  }
+//^ // enum B
+
+enum C<'a, const T_A: u32, T_B> {
+    A(&'a u32),
+    B(T_B),
+  }
+//^ // enum C<'a, const T_A: u32, T_B>
+
+enum EnumStructFieldWrapper {
+    A {
+        a: u32,
+        b: u32,
+    }
+  //^ // A
+  }
+//^ // enum EnumStructFieldWrapper
+            "#,
+        );
+    }
+
+    #[test]
+    fn hints_closing_brace_union() {
+        check_with_config(
+            InlayHintsConfig { closing_brace_hints_min_lines: Some(2), ..DISABLED_CONFIG },
+            r#"
+pub(in crate::foo) union A {
+  }
+//^ // pub(in crate::foo) union A
+
+union B {
+    a: u32,
+    b: u32,
+  }
+//^ // union B
+
+union C<'a, const T_A: u32, T_B> {
+    a: &'a u32,
+    b: T_B,
+  }
+//^ // union C<'a, const T_A: u32, T_B>
+
+            "#,
+        );
+    }
+
+    #[test]
+    fn hints_closing_brace_if() {
+        check_with_config(
+            InlayHintsConfig { closing_brace_hints_min_lines: Some(2), ..DISABLED_CONFIG },
+            r#"
+fn if_wrapper() {
+    if true {
+    }
+  //^ // if true
+
+    fn return_true() -> bool {
+        true
+    }
+  //^ // fn return_true() -> bool
+
+    if true && return_true() {
+    }
+  //^ // if true && return_true()
+
+    if false {
+    } else {
+    }
+  //^ // else
+
+    if 0 == 1 {
+    }
+  //^ // if 0 == 1
+    else if 0 == 2 {
+    }
+  //^ // else if 0 == 2
+    else {
+    }
+  //^ // else
+  }
+//^ // fn if_wrapper()
+            "#,
+        );
+    }
+
+    #[test]
+    fn hints_closing_brace_if_let() {
+        check_with_config(
+            InlayHintsConfig { closing_brace_hints_min_lines: Some(2), ..DISABLED_CONFIG },
+            r#"
+fn if_let_wrapper() {
+    if let Some(0) = Some(0) {
+    }
+  //^ // if let Some(0) = Some(0)
+
+    if let Some(0) = None {
+    } else {
+    }
+  //^ // else
+  }
+//^ // fn if_let_wrapper()
+            "#,
+        );
+    }
+
+    #[test]
+    fn hints_closing_brace_truncation() {
+        check_with_config(
+            InlayHintsConfig {
+                closing_brace_hints_min_lines: Some(2),
+                max_length: Some(40),
+                ..DISABLED_CONFIG
+            },
+            r#"
+// Not truncated
+// 40 chars including beginning "// " and params
+fn with_40_chars_including_params_() {
+  }
+//^ // fn with_40_chars_including_params_()
+
+// Truncated after 'o'
+// 39 chars before X including "// "
+fn with_39_chars_before_X__________oXXXXXX() {
+  }
+//^ // fn with_39_chars_before_X__________o…
+
+pub(in crate::foo) enum C<'a, const T_A: u32, T_B> {
+  }
+//^ // pub(in crate::foo) enum C<'a, const …
+            "#,
         );
     }
 }
diff --git a/docs/book/src/assists_generated.md b/docs/book/src/assists_generated.md
index 761a7f859bef..9d68a873ffef 100644
--- a/docs/book/src/assists_generated.md
+++ b/docs/book/src/assists_generated.md
@@ -1,7 +1,7 @@
 //! Generated by `cargo xtask codegen assists-doc-tests`, do not edit by hand.
 
 ### `add_braces`
-**Source:**  [add_braces.rs](/crates/ide-assists/src/handlers/add_braces.rs#8) 
+**Source:**  [add_braces.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_braces.rs#L8) 
 
 Adds braces to lambda and match arm expressions.
 
@@ -29,7 +29,7 @@ fn foo(n: i32) -> i32 {
 
 
 ### `add_explicit_type`
-**Source:**  [add_explicit_type.rs](/crates/ide-assists/src/handlers/add_explicit_type.rs#7) 
+**Source:**  [add_explicit_type.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_explicit_type.rs#L7) 
 
 Specify type for a let binding.
 
@@ -49,7 +49,7 @@ fn main() {
 
 
 ### `add_hash`
-**Source:**  [raw_string.rs](/crates/ide-assists/src/handlers/raw_string.rs#89) 
+**Source:**  [raw_string.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/raw_string.rs#L89) 
 
 Adds a hash to a raw string literal.
 
@@ -69,7 +69,7 @@ fn main() {
 
 
 ### `add_impl_default_members`
-**Source:**  [add_missing_impl_members.rs](/crates/ide-assists/src/handlers/add_missing_impl_members.rs#58) 
+**Source:**  [add_missing_impl_members.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_missing_impl_members.rs#L58) 
 
 Adds scaffold for overriding default impl members.
 
@@ -105,7 +105,7 @@ impl Trait for () {
 
 
 ### `add_impl_missing_members`
-**Source:**  [add_missing_impl_members.rs](/crates/ide-assists/src/handlers/add_missing_impl_members.rs#16) 
+**Source:**  [add_missing_impl_members.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_missing_impl_members.rs#L16) 
 
 Adds scaffold for required impl members.
 
@@ -141,7 +141,7 @@ impl Trait<u32> for () {
 
 
 ### `add_label_to_loop`
-**Source:**  [add_label_to_loop.rs](/crates/ide-assists/src/handlers/add_label_to_loop.rs#9) 
+**Source:**  [add_label_to_loop.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_label_to_loop.rs#L9) 
 
 Adds a label to a loop.
 
@@ -167,7 +167,7 @@ fn main() {
 
 
 ### `add_lifetime_to_type`
-**Source:**  [add_lifetime_to_type.rs](/crates/ide-assists/src/handlers/add_lifetime_to_type.rs#5) 
+**Source:**  [add_lifetime_to_type.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_lifetime_to_type.rs#L5) 
 
 Adds a new lifetime to a struct, enum or union.
 
@@ -189,7 +189,7 @@ struct Point<'a> {
 
 
 ### `add_missing_match_arms`
-**Source:**  [add_missing_match_arms.rs](/crates/ide-assists/src/handlers/add_missing_match_arms.rs#14) 
+**Source:**  [add_missing_match_arms.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_missing_match_arms.rs#L16) 
 
 Adds missing clauses to a `match` expression.
 
@@ -218,7 +218,7 @@ fn handle(action: Action) {
 
 
 ### `add_return_type`
-**Source:**  [add_return_type.rs](/crates/ide-assists/src/handlers/add_return_type.rs#6) 
+**Source:**  [add_return_type.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_return_type.rs#L6) 
 
 Adds the return type to a function or closure inferred from its tail expression if it doesn't have a return
 type specified. This assists is useable in a functions or closures tail expression or return type position.
@@ -235,7 +235,7 @@ fn foo() -> i32 { 42i32 }
 
 
 ### `add_turbo_fish`
-**Source:**  [add_turbo_fish.rs](/crates/ide-assists/src/handlers/add_turbo_fish.rs#14) 
+**Source:**  [add_turbo_fish.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_turbo_fish.rs#L14) 
 
 Adds `::<_>` to a call of a generic method or function.
 
@@ -257,7 +257,7 @@ fn main() {
 
 
 ### `apply_demorgan`
-**Source:**  [apply_demorgan.rs](/crates/ide-assists/src/handlers/apply_demorgan.rs#16) 
+**Source:**  [apply_demorgan.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/apply_demorgan.rs#L16) 
 
 Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws).
 This transforms expressions of the form `!l || !r` into `!(l && r)`.
@@ -280,7 +280,7 @@ fn main() {
 
 
 ### `apply_demorgan_iterator`
-**Source:**  [apply_demorgan.rs](/crates/ide-assists/src/handlers/apply_demorgan.rs#132) 
+**Source:**  [apply_demorgan.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/apply_demorgan.rs#L132) 
 
 Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws) to
 `Iterator::all` and `Iterator::any`.
@@ -311,7 +311,7 @@ fn main() {
 
 
 ### `auto_import`
-**Source:**  [auto_import.rs](/crates/ide-assists/src/handlers/auto_import.rs#73) 
+**Source:**  [auto_import.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/auto_import.rs#L73) 
 
 If the name is unresolved, provides all possible imports for it.
 
@@ -333,7 +333,7 @@ fn main() {
 
 
 ### `bind_unused_param`
-**Source:**  [bind_unused_param.rs](/crates/ide-assists/src/handlers/bind_unused_param.rs#12) 
+**Source:**  [bind_unused_param.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/bind_unused_param.rs#L12) 
 
 Binds unused function parameter to an underscore.
 
@@ -351,7 +351,7 @@ fn some_function(x: i32) {
 
 
 ### `bool_to_enum`
-**Source:**  [bool_to_enum.rs](/crates/ide-assists/src/handlers/bool_to_enum.rs#29) 
+**Source:**  [bool_to_enum.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/bool_to_enum.rs#L29) 
 
 This converts boolean local variables, fields, constants, and statics into a new
 enum with two variants `Bool::True` and `Bool::False`, as well as replacing
@@ -385,7 +385,7 @@ fn main() {
 
 
 ### `change_visibility`
-**Source:**  [change_visibility.rs](/crates/ide-assists/src/handlers/change_visibility.rs#13) 
+**Source:**  [change_visibility.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/change_visibility.rs#L13) 
 
 Adds or changes existing visibility specifier.
 
@@ -401,7 +401,7 @@ pub(crate) fn frobnicate() {}
 
 
 ### `comment_to_doc`
-**Source:**  [convert_comment_from_or_to_doc.rs](/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs#9) 
+**Source:**  [convert_comment_from_or_to_doc.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs#L9) 
 
 Converts comments to documentation.
 
@@ -419,7 +419,7 @@ Converts comments to documentation.
 
 
 ### `convert_bool_then_to_if`
-**Source:**  [convert_bool_then.rs](/crates/ide-assists/src/handlers/convert_bool_then.rs#131) 
+**Source:**  [convert_bool_then.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_bool_then.rs#L131) 
 
 Converts a `bool::then` method call to an equivalent if expression.
 
@@ -443,7 +443,7 @@ fn main() {
 
 
 ### `convert_closure_to_fn`
-**Source:**  [convert_closure_to_fn.rs](/crates/ide-assists/src/handlers/convert_closure_to_fn.rs#25) 
+**Source:**  [convert_closure_to_fn.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_closure_to_fn.rs#L25) 
 
 This converts a closure to a freestanding function, changing all captures to parameters.
 
@@ -469,7 +469,7 @@ fn main() {
 
 
 ### `convert_for_loop_with_for_each`
-**Source:**  [convert_iter_for_each_to_for.rs](/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs#76) 
+**Source:**  [convert_iter_for_each_to_for.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs#L76) 
 
 Converts a for loop into a for_each loop on the Iterator.
 
@@ -495,7 +495,7 @@ fn main() {
 
 
 ### `convert_from_to_tryfrom`
-**Source:**  [convert_from_to_tryfrom.rs](/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs#10) 
+**Source:**  [convert_from_to_tryfrom.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs#L10) 
 
 Converts a From impl to a TryFrom impl, wrapping returns in `Ok`.
 
@@ -527,7 +527,7 @@ impl TryFrom<usize> for Thing {
 
 
 ### `convert_if_to_bool_then`
-**Source:**  [convert_bool_then.rs](/crates/ide-assists/src/handlers/convert_bool_then.rs#20) 
+**Source:**  [convert_bool_then.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_bool_then.rs#L20) 
 
 Converts an if expression into a corresponding `bool::then` call.
 
@@ -551,7 +551,7 @@ fn main() {
 
 
 ### `convert_integer_literal`
-**Source:**  [convert_integer_literal.rs](/crates/ide-assists/src/handlers/convert_integer_literal.rs#5) 
+**Source:**  [convert_integer_literal.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_integer_literal.rs#L5) 
 
 Converts the base of integer literals to other bases.
 
@@ -567,7 +567,7 @@ const _: i32 = 0b1010;
 
 
 ### `convert_into_to_from`
-**Source:**  [convert_into_to_from.rs](/crates/ide-assists/src/handlers/convert_into_to_from.rs#8) 
+**Source:**  [convert_into_to_from.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_into_to_from.rs#L8) 
 
 Converts an Into impl to an equivalent From impl.
 
@@ -597,7 +597,7 @@ impl From<usize> for Thing {
 
 
 ### `convert_iter_for_each_to_for`
-**Source:**  [convert_iter_for_each_to_for.rs](/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs#11) 
+**Source:**  [convert_iter_for_each_to_for.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs#L11) 
 
 Converts an Iterator::for_each function into a for loop.
 
@@ -623,7 +623,7 @@ fn main() {
 
 
 ### `convert_let_else_to_match`
-**Source:**  [convert_let_else_to_match.rs](/crates/ide-assists/src/handlers/convert_let_else_to_match.rs#9) 
+**Source:**  [convert_let_else_to_match.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_let_else_to_match.rs#L9) 
 
 Converts let-else statement to let statement and match expression.
 
@@ -646,7 +646,7 @@ fn main() {
 
 
 ### `convert_match_to_let_else`
-**Source:**  [convert_match_to_let_else.rs](/crates/ide-assists/src/handlers/convert_match_to_let_else.rs#12) 
+**Source:**  [convert_match_to_let_else.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_match_to_let_else.rs#L12) 
 
 Converts let statement with match initializer to let-else statement.
 
@@ -669,7 +669,7 @@ fn foo(opt: Option<()>) {
 
 
 ### `convert_named_struct_to_tuple_struct`
-**Source:**  [convert_named_struct_to_tuple_struct.rs](/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs#11) 
+**Source:**  [convert_named_struct_to_tuple_struct.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs#L11) 
 
 Converts struct with named fields to tuple struct, and analogously for enum variants with named
 fields.
@@ -714,7 +714,7 @@ impl Point {
 
 
 ### `convert_nested_function_to_closure`
-**Source:**  [convert_nested_function_to_closure.rs](/crates/ide-assists/src/handlers/convert_nested_function_to_closure.rs#7) 
+**Source:**  [convert_nested_function_to_closure.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_nested_function_to_closure.rs#L7) 
 
 Converts a function that is defined within the body of another function into a closure.
 
@@ -742,7 +742,7 @@ fn main() {
 
 
 ### `convert_to_guarded_return`
-**Source:**  [convert_to_guarded_return.rs](/crates/ide-assists/src/handlers/convert_to_guarded_return.rs#24) 
+**Source:**  [convert_to_guarded_return.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_to_guarded_return.rs#L24) 
 
 Replace a large conditional with a guarded return.
 
@@ -769,7 +769,7 @@ fn main() {
 
 
 ### `convert_tuple_return_type_to_struct`
-**Source:**  [convert_tuple_return_type_to_struct.rs](/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs#20) 
+**Source:**  [convert_tuple_return_type_to_struct.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs#L20) 
 
 This converts the return type of a function from a tuple type
 into a tuple struct and updates the body accordingly.
@@ -800,7 +800,7 @@ fn foo() -> FooResult {
 
 
 ### `convert_tuple_struct_to_named_struct`
-**Source:**  [convert_tuple_struct_to_named_struct.rs](/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs#10) 
+**Source:**  [convert_tuple_struct_to_named_struct.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs#L10) 
 
 Converts tuple struct to struct with named fields, and analogously for tuple enum variants.
 
@@ -844,7 +844,7 @@ impl Point {
 
 
 ### `convert_two_arm_bool_match_to_matches_macro`
-**Source:**  [convert_two_arm_bool_match_to_matches_macro.rs](/crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs#8) 
+**Source:**  [convert_two_arm_bool_match_to_matches_macro.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs#L8) 
 
 Convert 2-arm match that evaluates to a boolean into the equivalent matches! invocation.
 
@@ -867,7 +867,7 @@ fn main() {
 
 
 ### `convert_while_to_loop`
-**Source:**  [convert_while_to_loop.rs](/crates/ide-assists/src/handlers/convert_while_to_loop.rs#20) 
+**Source:**  [convert_while_to_loop.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_while_to_loop.rs#L20) 
 
 Replace a while with a loop.
 
@@ -894,7 +894,7 @@ fn main() {
 
 
 ### `destructure_struct_binding`
-**Source:**  [destructure_struct_binding.rs](/crates/ide-assists/src/handlers/destructure_struct_binding.rs#18) 
+**Source:**  [destructure_struct_binding.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/destructure_struct_binding.rs#L18) 
 
 Destructures a struct binding in place.
 
@@ -926,7 +926,7 @@ fn main() {
 
 
 ### `destructure_tuple_binding`
-**Source:**  [destructure_tuple_binding.rs](/crates/ide-assists/src/handlers/destructure_tuple_binding.rs#19) 
+**Source:**  [destructure_tuple_binding.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/destructure_tuple_binding.rs#L19) 
 
 Destructures a tuple binding in place.
 
@@ -948,7 +948,7 @@ fn main() {
 
 
 ### `desugar_async_into_impl_future`
-**Source:**  [toggle_async_sugar.rs](/crates/ide-assists/src/handlers/toggle_async_sugar.rs#103) 
+**Source:**  [toggle_async_sugar.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/toggle_async_sugar.rs#L103) 
 
 Rewrites asynchronous function from `async fn` into `-> impl Future`.
 This action does not touch the function body and therefore `0`
@@ -970,7 +970,7 @@ pub fn foo() -> impl core::future::Future<Output = usize> {
 
 
 ### `desugar_doc_comment`
-**Source:**  [desugar_doc_comment.rs](/crates/ide-assists/src/handlers/desugar_doc_comment.rs#14) 
+**Source:**  [desugar_doc_comment.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/desugar_doc_comment.rs#L14) 
 
 Desugars doc-comments to the attribute form.
 
@@ -988,7 +988,7 @@ comment"]
 
 
 ### `expand_glob_import`
-**Source:**  [expand_glob_import.rs](/crates/ide-assists/src/handlers/expand_glob_import.rs#18) 
+**Source:**  [expand_glob_import.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_glob_import.rs#L19) 
 
 Expands glob imports.
 
@@ -1017,8 +1017,34 @@ fn qux(bar: Bar, baz: Baz) {}
 ```
 
 
+### `expand_glob_reexport`
+**Source:**  [expand_glob_import.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_glob_import.rs#L81) 
+
+Expands non-private glob imports.
+
+#### Before
+```rust
+mod foo {
+    pub struct Bar;
+    pub struct Baz;
+}
+
+pub use foo::*┃;
+```
+
+#### After
+```rust
+mod foo {
+    pub struct Bar;
+    pub struct Baz;
+}
+
+pub use foo::{Bar, Baz};
+```
+
+
 ### `explicit_enum_discriminant`
-**Source:**  [explicit_enum_discriminant.rs](/crates/ide-assists/src/handlers/explicit_enum_discriminant.rs#11) 
+**Source:**  [explicit_enum_discriminant.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/explicit_enum_discriminant.rs#L11) 
 
 Adds explicit discriminant to all enum variants.
 
@@ -1044,7 +1070,7 @@ enum TheEnum {
 
 
 ### `extract_constant`
-**Source:**  [extract_variable.rs](/crates/ide-assists/src/handlers/extract_variable.rs#35) 
+**Source:**  [extract_variable.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/extract_variable.rs#L35) 
 
 Extracts subexpression into a constant.
 
@@ -1065,7 +1091,7 @@ fn main() {
 
 
 ### `extract_expressions_from_format_string`
-**Source:**  [extract_expressions_from_format_string.rs](/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs#14) 
+**Source:**  [extract_expressions_from_format_string.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs#L14) 
 
 Move an expression out of a format string.
 
@@ -1085,7 +1111,7 @@ fn main() {
 
 
 ### `extract_function`
-**Source:**  [extract_function.rs](/crates/ide-assists/src/handlers/extract_function.rs#39) 
+**Source:**  [extract_function.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/extract_function.rs#L39) 
 
 Extracts selected statements and comments into new function.
 
@@ -1117,7 +1143,7 @@ fn ┃fun_name(n: i32) {
 
 
 ### `extract_module`
-**Source:**  [extract_module.rs](/crates/ide-assists/src/handlers/extract_module.rs#29) 
+**Source:**  [extract_module.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/extract_module.rs#L29) 
 
 Extracts a selected region as separate module. All the references, visibility and imports are
 resolved.
@@ -1148,7 +1174,7 @@ fn bar(name: i32) -> i32 {
 
 
 ### `extract_static`
-**Source:**  [extract_variable.rs](/crates/ide-assists/src/handlers/extract_variable.rs#52) 
+**Source:**  [extract_variable.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/extract_variable.rs#L52) 
 
 Extracts subexpression into a static.
 
@@ -1169,7 +1195,7 @@ fn main() {
 
 
 ### `extract_struct_from_enum_variant`
-**Source:**  [extract_struct_from_enum_variant.rs](/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs#26) 
+**Source:**  [extract_struct_from_enum_variant.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs#L26) 
 
 Extracts a struct from enum variant.
 
@@ -1187,7 +1213,7 @@ enum A { One(One) }
 
 
 ### `extract_type_alias`
-**Source:**  [extract_type_alias.rs](/crates/ide-assists/src/handlers/extract_type_alias.rs#10) 
+**Source:**  [extract_type_alias.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/extract_type_alias.rs#L10) 
 
 Extracts the selected type as a type alias.
 
@@ -1209,7 +1235,7 @@ struct S {
 
 
 ### `extract_variable`
-**Source:**  [extract_variable.rs](/crates/ide-assists/src/handlers/extract_variable.rs#18) 
+**Source:**  [extract_variable.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/extract_variable.rs#L18) 
 
 Extracts subexpression into a variable.
 
@@ -1230,7 +1256,7 @@ fn main() {
 
 
 ### `fill_record_pattern_fields`
-**Source:**  [fill_record_pattern_fields.rs](/crates/ide-assists/src/handlers/fill_record_pattern_fields.rs#8) 
+**Source:**  [fill_record_pattern_fields.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/fill_record_pattern_fields.rs#L8) 
 
 Fills fields by replacing rest pattern in record patterns.
 
@@ -1254,7 +1280,7 @@ fn foo(bar: Bar) {
 
 
 ### `fix_visibility`
-**Source:**  [fix_visibility.rs](/crates/ide-assists/src/handlers/fix_visibility.rs#14) 
+**Source:**  [fix_visibility.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/fix_visibility.rs#L14) 
 
 Makes inaccessible item public.
 
@@ -1280,7 +1306,7 @@ fn main() {
 
 
 ### `flip_binexpr`
-**Source:**  [flip_binexpr.rs](/crates/ide-assists/src/handlers/flip_binexpr.rs#8) 
+**Source:**  [flip_binexpr.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/flip_binexpr.rs#L8) 
 
 Flips operands of a binary expression.
 
@@ -1300,7 +1326,7 @@ fn main() {
 
 
 ### `flip_comma`
-**Source:**  [flip_comma.rs](/crates/ide-assists/src/handlers/flip_comma.rs#10) 
+**Source:**  [flip_comma.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/flip_comma.rs#L10) 
 
 Flips two comma-separated items.
 
@@ -1320,7 +1346,7 @@ fn main() {
 
 
 ### `flip_trait_bound`
-**Source:**  [flip_trait_bound.rs](/crates/ide-assists/src/handlers/flip_trait_bound.rs#9) 
+**Source:**  [flip_trait_bound.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/flip_trait_bound.rs#L9) 
 
 Flips two trait bounds.
 
@@ -1336,7 +1362,7 @@ fn foo<T: Copy + Clone>() { }
 
 
 ### `generate_constant`
-**Source:**  [generate_constant.rs](/crates/ide-assists/src/handlers/generate_constant.rs#14) 
+**Source:**  [generate_constant.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_constant.rs#L14) 
 
 Generate a named constant.
 
@@ -1361,7 +1387,7 @@ fn main() {
 
 
 ### `generate_default_from_enum_variant`
-**Source:**  [generate_default_from_enum_variant.rs](/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs#6) 
+**Source:**  [generate_default_from_enum_variant.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs#L6) 
 
 Adds a Default impl for an enum using a variant.
 
@@ -1391,7 +1417,7 @@ impl Default for Version {
 
 
 ### `generate_default_from_new`
-**Source:**  [generate_default_from_new.rs](/crates/ide-assists/src/handlers/generate_default_from_new.rs#13) 
+**Source:**  [generate_default_from_new.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_default_from_new.rs#L13) 
 
 Generates default implementation from new method.
 
@@ -1425,7 +1451,7 @@ impl Default for Example {
 
 
 ### `generate_delegate_methods`
-**Source:**  [generate_delegate_methods.rs](/crates/ide-assists/src/handlers/generate_delegate_methods.rs#15) 
+**Source:**  [generate_delegate_methods.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_delegate_methods.rs#L15) 
 
 Generate delegate methods.
 
@@ -1465,7 +1491,7 @@ impl Person {
 
 
 ### `generate_delegate_trait`
-**Source:**  [generate_delegate_trait.rs](/crates/ide-assists/src/handlers/generate_delegate_trait.rs#29) 
+**Source:**  [generate_delegate_trait.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_delegate_trait.rs#L29) 
 
 Generate delegate trait implementation for `StructField`s.
 
@@ -1531,7 +1557,7 @@ impl SomeTrait for B {
 
 
 ### `generate_deref`
-**Source:**  [generate_deref.rs](/crates/ide-assists/src/handlers/generate_deref.rs#16) 
+**Source:**  [generate_deref.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_deref.rs#L16) 
 
 Generate `Deref` impl using the given struct field.
 
@@ -1561,7 +1587,7 @@ impl core::ops::Deref for B {
 
 
 ### `generate_derive`
-**Source:**  [generate_derive.rs](/crates/ide-assists/src/handlers/generate_derive.rs#8) 
+**Source:**  [generate_derive.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_derive.rs#L8) 
 
 Adds a new `#[derive()]` clause to a struct or enum.
 
@@ -1584,7 +1610,7 @@ struct Point {
 
 
 ### `generate_doc_example`
-**Source:**  [generate_documentation_template.rs](/crates/ide-assists/src/handlers/generate_documentation_template.rs#76) 
+**Source:**  [generate_documentation_template.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_documentation_template.rs#L76) 
 
 Generates a rustdoc example when editing an item's documentation.
 
@@ -1610,7 +1636,7 @@ pub fn add(a: i32, b: i32) -> i32 { a + b }
 
 
 ### `generate_documentation_template`
-**Source:**  [generate_documentation_template.rs](/crates/ide-assists/src/handlers/generate_documentation_template.rs#13) 
+**Source:**  [generate_documentation_template.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_documentation_template.rs#L13) 
 
 Adds a documentation template above a function definition / declaration.
 
@@ -1645,7 +1671,7 @@ impl S {
 
 
 ### `generate_enum_as_method`
-**Source:**  [generate_enum_projection_method.rs](/crates/ide-assists/src/handlers/generate_enum_projection_method.rs#59) 
+**Source:**  [generate_enum_projection_method.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_enum_projection_method.rs#L59) 
 
 Generate an `as_` method for this enum variant.
 
@@ -1677,7 +1703,7 @@ impl Value {
 
 
 ### `generate_enum_is_method`
-**Source:**  [generate_enum_is_method.rs](/crates/ide-assists/src/handlers/generate_enum_is_method.rs#11) 
+**Source:**  [generate_enum_is_method.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_enum_is_method.rs#L11) 
 
 Generate an `is_` method for this enum variant.
 
@@ -1711,7 +1737,7 @@ impl Version {
 
 
 ### `generate_enum_try_into_method`
-**Source:**  [generate_enum_projection_method.rs](/crates/ide-assists/src/handlers/generate_enum_projection_method.rs#12) 
+**Source:**  [generate_enum_projection_method.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_enum_projection_method.rs#L12) 
 
 Generate a `try_into_` method for this enum variant.
 
@@ -1743,7 +1769,7 @@ impl Value {
 
 
 ### `generate_enum_variant`
-**Source:**  [generate_enum_variant.rs](/crates/ide-assists/src/handlers/generate_enum_variant.rs#10) 
+**Source:**  [generate_enum_variant.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_enum_variant.rs#L10) 
 
 Adds a variant to an enum.
 
@@ -1772,7 +1798,7 @@ fn main() {
 
 
 ### `generate_fn_type_alias_named`
-**Source:**  [generate_fn_type_alias.rs](/crates/ide-assists/src/handlers/generate_fn_type_alias.rs#10) 
+**Source:**  [generate_fn_type_alias.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_fn_type_alias.rs#L10) 
 
 Generate a type alias for the function with named parameters.
 
@@ -1790,7 +1816,7 @@ unsafe fn foo(n: i32) -> i32 { 42i32 }
 
 
 ### `generate_fn_type_alias_unnamed`
-**Source:**  [generate_fn_type_alias.rs](/crates/ide-assists/src/handlers/generate_fn_type_alias.rs#24) 
+**Source:**  [generate_fn_type_alias.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_fn_type_alias.rs#L24) 
 
 Generate a type alias for the function with unnamed parameters.
 
@@ -1808,7 +1834,7 @@ unsafe fn foo(n: i32) -> i32 { 42i32 }
 
 
 ### `generate_from_impl_for_enum`
-**Source:**  [generate_from_impl_for_enum.rs](/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs#8) 
+**Source:**  [generate_from_impl_for_enum.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs#L8) 
 
 Adds a From impl for this enum variant with one tuple field.
 
@@ -1830,7 +1856,7 @@ impl From<u32> for A {
 
 
 ### `generate_function`
-**Source:**  [generate_function.rs](/crates/ide-assists/src/handlers/generate_function.rs#28) 
+**Source:**  [generate_function.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_function.rs#L28) 
 
 Adds a stub function with a signature matching the function under the cursor.
 
@@ -1860,7 +1886,7 @@ fn bar(arg: &str, baz: Baz) ${0:-> _} {
 
 
 ### `generate_getter`
-**Source:**  [generate_getter_or_setter.rs](/crates/ide-assists/src/handlers/generate_getter_or_setter.rs#73) 
+**Source:**  [generate_getter_or_setter.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_getter_or_setter.rs#L73) 
 
 Generate a getter method.
 
@@ -1886,7 +1912,7 @@ impl Person {
 
 
 ### `generate_getter_mut`
-**Source:**  [generate_getter_or_setter.rs](/crates/ide-assists/src/handlers/generate_getter_or_setter.rs#127) 
+**Source:**  [generate_getter_or_setter.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_getter_or_setter.rs#L127) 
 
 Generate a mut getter method.
 
@@ -1912,7 +1938,7 @@ impl Person {
 
 
 ### `generate_impl`
-**Source:**  [generate_impl.rs](/crates/ide-assists/src/handlers/generate_impl.rs#20) 
+**Source:**  [generate_impl.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_impl.rs#L20) 
 
 Adds a new inherent impl for a type.
 
@@ -1934,7 +1960,7 @@ impl<T: Clone> Ctx<T> {┃}
 
 
 ### `generate_is_empty_from_len`
-**Source:**  [generate_is_empty_from_len.rs](/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs#12) 
+**Source:**  [generate_is_empty_from_len.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs#L12) 
 
 Generates is_empty implementation from the len method.
 
@@ -1969,7 +1995,7 @@ impl MyStruct {
 
 
 ### `generate_mut_trait_impl`
-**Source:**  [generate_mut_trait_impl.rs](/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs#12) 
+**Source:**  [generate_mut_trait_impl.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs#L12) 
 
 Adds a IndexMut impl from the `Index` trait.
 
@@ -2007,7 +2033,7 @@ impl<T> core::ops::Index<Axis> for [T; 3] {
 
 
 ### `generate_new`
-**Source:**  [generate_new.rs](/crates/ide-assists/src/handlers/generate_new.rs#14) 
+**Source:**  [generate_new.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_new.rs#L14) 
 
 Adds a `fn new` for a type.
 
@@ -2033,7 +2059,7 @@ impl<T: Clone> Ctx<T> {
 
 
 ### `generate_setter`
-**Source:**  [generate_getter_or_setter.rs](/crates/ide-assists/src/handlers/generate_getter_or_setter.rs#13) 
+**Source:**  [generate_getter_or_setter.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_getter_or_setter.rs#L13) 
 
 Generate a setter method.
 
@@ -2059,7 +2085,7 @@ impl Person {
 
 
 ### `generate_trait_from_impl`
-**Source:**  [generate_trait_from_impl.rs](/crates/ide-assists/src/handlers/generate_trait_from_impl.rs#18) 
+**Source:**  [generate_trait_from_impl.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_trait_from_impl.rs#L18) 
 
 Generate trait for an already defined inherent impl and convert impl to a trait impl.
 
@@ -2118,7 +2144,7 @@ impl<const N: usize> ${0:NewTrait}<N> for Foo<N> {
 
 
 ### `generate_trait_impl`
-**Source:**  [generate_impl.rs](/crates/ide-assists/src/handlers/generate_impl.rs#66) 
+**Source:**  [generate_impl.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/generate_impl.rs#L66) 
 
 Adds a new trait impl for a type.
 
@@ -2140,7 +2166,7 @@ impl<T: Clone> ${0:_} for Ctx<T> {}
 
 
 ### `inline_call`
-**Source:**  [inline_call.rs](/crates/ide-assists/src/handlers/inline_call.rs#170) 
+**Source:**  [inline_call.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_call.rs#L170) 
 
 Inlines a function or method body creating a `let` statement per parameter unless the parameter
 can be inlined. The parameter will be inlined either if it the supplied argument is a simple local
@@ -2165,7 +2191,7 @@ fn foo(name: Option<&str>) {
 
 
 ### `inline_const_as_literal`
-**Source:**  [inline_const_as_literal.rs](/crates/ide-assists/src/handlers/inline_const_as_literal.rs#6) 
+**Source:**  [inline_const_as_literal.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_const_as_literal.rs#L6) 
 
 Evaluate and inline const variable as literal.
 
@@ -2189,7 +2215,7 @@ fn something() -> &'static str {
 
 
 ### `inline_into_callers`
-**Source:**  [inline_call.rs](/crates/ide-assists/src/handlers/inline_call.rs#32) 
+**Source:**  [inline_call.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_call.rs#L32) 
 
 Inline a function or method body into all of its callers where possible, creating a `let` statement per parameter
 unless the parameter can be inlined. The parameter will be inlined either if it the supplied argument is a simple local
@@ -2232,7 +2258,7 @@ fn bar() {
 
 
 ### `inline_local_variable`
-**Source:**  [inline_local_variable.rs](/crates/ide-assists/src/handlers/inline_local_variable.rs#17) 
+**Source:**  [inline_local_variable.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_local_variable.rs#L17) 
 
 Inlines a local variable.
 
@@ -2253,7 +2279,7 @@ fn main() {
 
 
 ### `inline_macro`
-**Source:**  [inline_macro.rs](/crates/ide-assists/src/handlers/inline_macro.rs#7) 
+**Source:**  [inline_macro.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_macro.rs#L7) 
 
 Takes a macro and inlines it one step.
 
@@ -2289,7 +2315,7 @@ fn main() {
 
 
 ### `inline_type_alias`
-**Source:**  [inline_type_alias.rs](/crates/ide-assists/src/handlers/inline_type_alias.rs#106) 
+**Source:**  [inline_type_alias.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_type_alias.rs#L106) 
 
 Replace a type alias with its concrete type.
 
@@ -2313,7 +2339,7 @@ fn main() {
 
 
 ### `inline_type_alias_uses`
-**Source:**  [inline_type_alias.rs](/crates/ide-assists/src/handlers/inline_type_alias.rs#24) 
+**Source:**  [inline_type_alias.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_type_alias.rs#L24) 
 
 Inline a type alias into all of its uses where possible.
 
@@ -2341,7 +2367,7 @@ fn foo() {
 
 
 ### `into_to_qualified_from`
-**Source:**  [into_to_qualified_from.rs](/crates/ide-assists/src/handlers/into_to_qualified_from.rs#10) 
+**Source:**  [into_to_qualified_from.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/into_to_qualified_from.rs#L10) 
 
 Convert an `into` method call to a fully qualified `from` call.
 
@@ -2378,7 +2404,7 @@ fn main() -> () {
 
 
 ### `introduce_named_generic`
-**Source:**  [introduce_named_generic.rs](/crates/ide-assists/src/handlers/introduce_named_generic.rs#7) 
+**Source:**  [introduce_named_generic.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/introduce_named_generic.rs#L7) 
 
 Replaces `impl Trait` function argument with the named generic.
 
@@ -2394,7 +2420,7 @@ fn foo<┃B: Bar>(bar: B) {}
 
 
 ### `introduce_named_lifetime`
-**Source:**  [introduce_named_lifetime.rs](/crates/ide-assists/src/handlers/introduce_named_lifetime.rs#13) 
+**Source:**  [introduce_named_lifetime.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/introduce_named_lifetime.rs#L13) 
 
 Change an anonymous lifetime to a named lifetime.
 
@@ -2422,7 +2448,7 @@ impl<'a> Cursor<'a> {
 
 
 ### `invert_if`
-**Source:**  [invert_if.rs](/crates/ide-assists/src/handlers/invert_if.rs#13) 
+**Source:**  [invert_if.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/invert_if.rs#L13) 
 
 This transforms if expressions of the form `if !x {A} else {B}` into `if x {B} else {A}`
 This also works with `!=`. This assist can only be applied with the cursor on `if`.
@@ -2443,7 +2469,7 @@ fn main() {
 
 
 ### `line_to_block`
-**Source:**  [convert_comment_block.rs](/crates/ide-assists/src/handlers/convert_comment_block.rs#9) 
+**Source:**  [convert_comment_block.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_comment_block.rs#L9) 
 
 Converts comments between block and single-line form.
 
@@ -2463,7 +2489,7 @@ Converts comments between block and single-line form.
 
 
 ### `make_raw_string`
-**Source:**  [raw_string.rs](/crates/ide-assists/src/handlers/raw_string.rs#7) 
+**Source:**  [raw_string.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/raw_string.rs#L7) 
 
 Adds `r#` to a plain string literal.
 
@@ -2483,7 +2509,7 @@ fn main() {
 
 
 ### `make_usual_string`
-**Source:**  [raw_string.rs](/crates/ide-assists/src/handlers/raw_string.rs#47) 
+**Source:**  [raw_string.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/raw_string.rs#L47) 
 
 Turns a raw string into a plain string.
 
@@ -2503,7 +2529,7 @@ fn main() {
 
 
 ### `merge_imports`
-**Source:**  [merge_imports.rs](/crates/ide-assists/src/handlers/merge_imports.rs#21) 
+**Source:**  [merge_imports.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/merge_imports.rs#L21) 
 
 Merges neighbor imports with a common prefix.
 
@@ -2520,7 +2546,7 @@ use std::{fmt::Formatter, io};
 
 
 ### `merge_match_arms`
-**Source:**  [merge_match_arms.rs](/crates/ide-assists/src/handlers/merge_match_arms.rs#12) 
+**Source:**  [merge_match_arms.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/merge_match_arms.rs#L12) 
 
 Merges the current match arm with the following if their bodies are identical.
 
@@ -2549,7 +2575,7 @@ fn handle(action: Action) {
 
 
 ### `merge_nested_if`
-**Source:**  [merge_nested_if.rs](/crates/ide-assists/src/handlers/merge_nested_if.rs#11) 
+**Source:**  [merge_nested_if.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/merge_nested_if.rs#L11) 
 
 This transforms if expressions of the form `if x { if y {A} }` into `if x && y {A}`
 This assist can only be applied with the cursor on `if`.
@@ -2570,7 +2596,7 @@ fn main() {
 
 
 ### `move_arm_cond_to_match_guard`
-**Source:**  [move_guard.rs](/crates/ide-assists/src/handlers/move_guard.rs#69) 
+**Source:**  [move_guard.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/move_guard.rs#L69) 
 
 Moves if expression from match arm body into a guard.
 
@@ -2600,7 +2626,7 @@ fn handle(action: Action) {
 
 
 ### `move_bounds_to_where_clause`
-**Source:**  [move_bounds.rs](/crates/ide-assists/src/handlers/move_bounds.rs#12) 
+**Source:**  [move_bounds.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/move_bounds.rs#L12) 
 
 Moves inline type bounds to a where clause.
 
@@ -2620,7 +2646,7 @@ fn apply<T, U, F>(f: F, x: T) -> U where F: FnOnce(T) -> U {
 
 
 ### `move_const_to_impl`
-**Source:**  [move_const_to_impl.rs](/crates/ide-assists/src/handlers/move_const_to_impl.rs#14) 
+**Source:**  [move_const_to_impl.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/move_const_to_impl.rs#L14) 
 
 Move a local constant item in a method to impl's associated constant. All the references will be
 qualified with `Self::`.
@@ -2653,7 +2679,7 @@ impl S {
 
 
 ### `move_from_mod_rs`
-**Source:**  [move_from_mod_rs.rs](/crates/ide-assists/src/handlers/move_from_mod_rs.rs#12) 
+**Source:**  [move_from_mod_rs.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/move_from_mod_rs.rs#L12) 
 
 Moves xxx/mod.rs to xxx.rs.
 
@@ -2672,7 +2698,7 @@ fn t() {}
 
 
 ### `move_guard_to_arm_body`
-**Source:**  [move_guard.rs](/crates/ide-assists/src/handlers/move_guard.rs#8) 
+**Source:**  [move_guard.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/move_guard.rs#L8) 
 
 Moves match guard into match arm body.
 
@@ -2704,7 +2730,7 @@ fn handle(action: Action) {
 
 
 ### `move_module_to_file`
-**Source:**  [move_module_to_file.rs](/crates/ide-assists/src/handlers/move_module_to_file.rs#15) 
+**Source:**  [move_module_to_file.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/move_module_to_file.rs#L15) 
 
 Moves inline module's contents to a separate file.
 
@@ -2722,7 +2748,7 @@ mod foo;
 
 
 ### `move_to_mod_rs`
-**Source:**  [move_to_mod_rs.rs](/crates/ide-assists/src/handlers/move_to_mod_rs.rs#12) 
+**Source:**  [move_to_mod_rs.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/move_to_mod_rs.rs#L12) 
 
 Moves xxx.rs to xxx/mod.rs.
 
@@ -2741,7 +2767,7 @@ fn t() {}
 
 
 ### `normalize_import`
-**Source:**  [normalize_import.rs](/crates/ide-assists/src/handlers/normalize_import.rs#9) 
+**Source:**  [normalize_import.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/normalize_import.rs#L9) 
 
 Normalizes an import.
 
@@ -2757,7 +2783,7 @@ use std::{fmt::Formatter, io};
 
 
 ### `promote_local_to_const`
-**Source:**  [promote_local_to_const.rs](/crates/ide-assists/src/handlers/promote_local_to_const.rs#17) 
+**Source:**  [promote_local_to_const.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/promote_local_to_const.rs#L17) 
 
 Promotes a local variable to a const item changing its name to a `SCREAMING_SNAKE_CASE` variant
 if the local uses no non-const expressions.
@@ -2790,7 +2816,7 @@ fn main() {
 
 
 ### `pull_assignment_up`
-**Source:**  [pull_assignment_up.rs](/crates/ide-assists/src/handlers/pull_assignment_up.rs#11) 
+**Source:**  [pull_assignment_up.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/pull_assignment_up.rs#L11) 
 
 Extracts variable assignment to outside an if or match statement.
 
@@ -2822,7 +2848,7 @@ fn main() {
 
 
 ### `qualify_method_call`
-**Source:**  [qualify_method_call.rs](/crates/ide-assists/src/handlers/qualify_method_call.rs#10) 
+**Source:**  [qualify_method_call.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/qualify_method_call.rs#L10) 
 
 Replaces the method call with a qualified function call.
 
@@ -2852,7 +2878,7 @@ fn main() {
 
 
 ### `qualify_path`
-**Source:**  [qualify_path.rs](/crates/ide-assists/src/handlers/qualify_path.rs#24) 
+**Source:**  [qualify_path.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/qualify_path.rs#L24) 
 
 If the name is unresolved, provides all possible qualified paths for it.
 
@@ -2872,7 +2898,7 @@ fn main() {
 
 
 ### `reformat_number_literal`
-**Source:**  [number_representation.rs](/crates/ide-assists/src/handlers/number_representation.rs#7) 
+**Source:**  [number_representation.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/number_representation.rs#L7) 
 
 Adds or removes separators from integer literal.
 
@@ -2888,7 +2914,7 @@ const _: i32 = 1_012_345;
 
 
 ### `remove_dbg`
-**Source:**  [remove_dbg.rs](/crates/ide-assists/src/handlers/remove_dbg.rs#9) 
+**Source:**  [remove_dbg.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/remove_dbg.rs#L9) 
 
 Removes `dbg!()` macro call.
 
@@ -2908,7 +2934,7 @@ fn main() {
 
 
 ### `remove_hash`
-**Source:**  [raw_string.rs](/crates/ide-assists/src/handlers/raw_string.rs#117) 
+**Source:**  [raw_string.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/raw_string.rs#L117) 
 
 Removes a hash from a raw string literal.
 
@@ -2928,7 +2954,7 @@ fn main() {
 
 
 ### `remove_mut`
-**Source:**  [remove_mut.rs](/crates/ide-assists/src/handlers/remove_mut.rs#5) 
+**Source:**  [remove_mut.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/remove_mut.rs#L5) 
 
 Removes the `mut` keyword.
 
@@ -2948,7 +2974,7 @@ impl Walrus {
 
 
 ### `remove_parentheses`
-**Source:**  [remove_parentheses.rs](/crates/ide-assists/src/handlers/remove_parentheses.rs#5) 
+**Source:**  [remove_parentheses.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/remove_parentheses.rs#L5) 
 
 Removes redundant parentheses.
 
@@ -2968,7 +2994,7 @@ fn main() {
 
 
 ### `remove_unused_imports`
-**Source:**  [remove_unused_imports.rs](/crates/ide-assists/src/handlers/remove_unused_imports.rs#17) 
+**Source:**  [remove_unused_imports.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/remove_unused_imports.rs#L17) 
 
 Removes any use statements in the current selection that are unused.
 
@@ -2989,7 +3015,7 @@ mod foo {
 
 
 ### `remove_unused_param`
-**Source:**  [remove_unused_param.rs](/crates/ide-assists/src/handlers/remove_unused_param.rs#15) 
+**Source:**  [remove_unused_param.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/remove_unused_param.rs#L15) 
 
 Removes unused function parameter.
 
@@ -3013,7 +3039,7 @@ fn main() {
 
 
 ### `reorder_fields`
-**Source:**  [reorder_fields.rs](/crates/ide-assists/src/handlers/reorder_fields.rs#8) 
+**Source:**  [reorder_fields.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/reorder_fields.rs#L8) 
 
 Reorder the fields of record literals and record patterns in the same order as in
 the definition.
@@ -3032,7 +3058,7 @@ const test: Foo = Foo {foo: 1, bar: 0}
 
 
 ### `reorder_impl_items`
-**Source:**  [reorder_impl_items.rs](/crates/ide-assists/src/handlers/reorder_impl_items.rs#11) 
+**Source:**  [reorder_impl_items.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/reorder_impl_items.rs#L11) 
 
 Reorder the items of an `impl Trait`. The items will be ordered
 in the same order as in the trait definition.
@@ -3071,7 +3097,7 @@ impl Foo for Bar {
 
 
 ### `replace_arith_with_checked`
-**Source:**  [replace_arith_op.rs](/crates/ide-assists/src/handlers/replace_arith_op.rs#9) 
+**Source:**  [replace_arith_op.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_arith_op.rs#L9) 
 
 Replaces arithmetic on integers with the `checked_*` equivalent.
 
@@ -3091,7 +3117,7 @@ fn main() {
 
 
 ### `replace_arith_with_saturating`
-**Source:**  [replace_arith_op.rs](/crates/ide-assists/src/handlers/replace_arith_op.rs#28) 
+**Source:**  [replace_arith_op.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_arith_op.rs#L28) 
 
 Replaces arithmetic on integers with the `saturating_*` equivalent.
 
@@ -3111,7 +3137,7 @@ fn main() {
 
 
 ### `replace_arith_with_wrapping`
-**Source:**  [replace_arith_op.rs](/crates/ide-assists/src/handlers/replace_arith_op.rs#50) 
+**Source:**  [replace_arith_op.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_arith_op.rs#L50) 
 
 Replaces arithmetic on integers with the `wrapping_*` equivalent.
 
@@ -3131,7 +3157,7 @@ fn main() {
 
 
 ### `replace_char_with_string`
-**Source:**  [replace_string_with_char.rs](/crates/ide-assists/src/handlers/replace_string_with_char.rs#51) 
+**Source:**  [replace_string_with_char.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_string_with_char.rs#L51) 
 
 Replace a char literal with a string literal.
 
@@ -3151,7 +3177,7 @@ fn main() {
 
 
 ### `replace_derive_with_manual_impl`
-**Source:**  [replace_derive_with_manual_impl.rs](/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs#20) 
+**Source:**  [replace_derive_with_manual_impl.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs#L20) 
 
 Converts a `derive` impl into a manual one.
 
@@ -3175,7 +3201,7 @@ impl Debug for S {
 
 
 ### `replace_if_let_with_match`
-**Source:**  [replace_if_let_with_match.rs](/crates/ide-assists/src/handlers/replace_if_let_with_match.rs#20) 
+**Source:**  [replace_if_let_with_match.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_if_let_with_match.rs#L20) 
 
 Replaces a `if let` expression with a `match` expression.
 
@@ -3206,7 +3232,7 @@ fn handle(action: Action) {
 
 
 ### `replace_is_some_with_if_let_some`
-**Source:**  [replace_is_method_with_if_let_method.rs](/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs#9) 
+**Source:**  [replace_is_method_with_if_let_method.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs#L9) 
 
 Replace `if x.is_some()` with `if let Some(_tmp) = x` or `if x.is_ok()` with `if let Ok(_tmp) = x`.
 
@@ -3228,7 +3254,7 @@ fn main() {
 
 
 ### `replace_let_with_if_let`
-**Source:**  [replace_let_with_if_let.rs](/crates/ide-assists/src/handlers/replace_let_with_if_let.rs#9) 
+**Source:**  [replace_let_with_if_let.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_let_with_if_let.rs#L9) 
 
 Replaces `let` with an `if let`.
 
@@ -3255,7 +3281,7 @@ fn compute() -> Option<i32> { None }
 
 
 ### `replace_match_with_if_let`
-**Source:**  [replace_if_let_with_match.rs](/crates/ide-assists/src/handlers/replace_if_let_with_match.rs#188) 
+**Source:**  [replace_if_let_with_match.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_if_let_with_match.rs#L188) 
 
 Replaces a binary `match` with a wildcard pattern and no guards with an `if let` expression.
 
@@ -3286,7 +3312,7 @@ fn handle(action: Action) {
 
 
 ### `replace_named_generic_with_impl`
-**Source:**  [replace_named_generic_with_impl.rs](/crates/ide-assists/src/handlers/replace_named_generic_with_impl.rs#18) 
+**Source:**  [replace_named_generic_with_impl.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_named_generic_with_impl.rs#L18) 
 
 Replaces named generic with an `impl Trait` in function argument.
 
@@ -3302,7 +3328,7 @@ fn new(location: impl AsRef<Path>) -> Self {}
 
 
 ### `replace_qualified_name_with_use`
-**Source:**  [replace_qualified_name_with_use.rs](/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs#13) 
+**Source:**  [replace_qualified_name_with_use.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs#L13) 
 
 Adds a use statement for a given fully-qualified name.
 
@@ -3320,7 +3346,7 @@ fn process(map: HashMap<String, String>) {}
 
 
 ### `replace_string_with_char`
-**Source:**  [replace_string_with_char.rs](/crates/ide-assists/src/handlers/replace_string_with_char.rs#11) 
+**Source:**  [replace_string_with_char.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_string_with_char.rs#L11) 
 
 Replace string literal with char literal.
 
@@ -3340,7 +3366,7 @@ fn main() {
 
 
 ### `replace_try_expr_with_match`
-**Source:**  [replace_try_expr_with_match.rs](/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs#18) 
+**Source:**  [replace_try_expr_with_match.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs#L18) 
 
 Replaces a `try` expression with a `match` expression.
 
@@ -3363,7 +3389,7 @@ fn handle() {
 
 
 ### `replace_turbofish_with_explicit_type`
-**Source:**  [replace_turbofish_with_explicit_type.rs](/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs#12) 
+**Source:**  [replace_turbofish_with_explicit_type.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs#L12) 
 
 Converts `::<_>` to an explicit type assignment.
 
@@ -3385,7 +3411,7 @@ fn main() {
 
 
 ### `replace_with_eager_method`
-**Source:**  [replace_method_eager_lazy.rs](/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs#89) 
+**Source:**  [replace_method_eager_lazy.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs#L89) 
 
 Replace `unwrap_or_else` with `unwrap_or` and `ok_or_else` with `ok_or`.
 
@@ -3407,7 +3433,7 @@ fn foo() {
 
 
 ### `replace_with_lazy_method`
-**Source:**  [replace_method_eager_lazy.rs](/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs#9) 
+**Source:**  [replace_method_eager_lazy.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs#L9) 
 
 Replace `unwrap_or` with `unwrap_or_else` and `ok_or` with `ok_or_else`.
 
@@ -3429,7 +3455,7 @@ fn foo() {
 
 
 ### `sort_items`
-**Source:**  [sort_items.rs](/crates/ide-assists/src/handlers/sort_items.rs#12) 
+**Source:**  [sort_items.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/sort_items.rs#L12) 
 
 Sorts item members alphabetically: fields, enum variants and methods.
 
@@ -3520,7 +3546,7 @@ enum Animal {
 
 
 ### `split_import`
-**Source:**  [split_import.rs](/crates/ide-assists/src/handlers/split_import.rs#5) 
+**Source:**  [split_import.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/split_import.rs#L5) 
 
 Wraps the tail of import into braces.
 
@@ -3536,7 +3562,7 @@ use std::{collections::HashMap};
 
 
 ### `sugar_impl_future_into_async`
-**Source:**  [toggle_async_sugar.rs](/crates/ide-assists/src/handlers/toggle_async_sugar.rs#13) 
+**Source:**  [toggle_async_sugar.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/toggle_async_sugar.rs#L13) 
 
 Rewrites asynchronous function from `-> impl Future` into `async fn`.
 This action does not touch the function body and therefore `async { 0 }`
@@ -3558,7 +3584,7 @@ pub async fn foo() -> usize {
 
 
 ### `toggle_ignore`
-**Source:**  [toggle_ignore.rs](/crates/ide-assists/src/handlers/toggle_ignore.rs#8) 
+**Source:**  [toggle_ignore.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/toggle_ignore.rs#L8) 
 
 Adds `#[ignore]` attribute to the test.
 
@@ -3581,7 +3607,7 @@ fn arithmetics {
 
 
 ### `toggle_macro_delimiter`
-**Source:**  [toggle_macro_delimiter.rs](/crates/ide-assists/src/handlers/toggle_macro_delimiter.rs#9) 
+**Source:**  [toggle_macro_delimiter.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/toggle_macro_delimiter.rs#L9) 
 
 Change macro delimiters in the order of `( -> { -> [ -> (`.
 
@@ -3605,7 +3631,7 @@ sth!{ }
 
 
 ### `unmerge_match_arm`
-**Source:**  [unmerge_match_arm.rs](/crates/ide-assists/src/handlers/unmerge_match_arm.rs#10) 
+**Source:**  [unmerge_match_arm.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/unmerge_match_arm.rs#L10) 
 
 Splits the current match with a `|` pattern into two arms with identical bodies.
 
@@ -3634,7 +3660,7 @@ fn handle(action: Action) {
 
 
 ### `unmerge_use`
-**Source:**  [unmerge_use.rs](/crates/ide-assists/src/handlers/unmerge_use.rs#12) 
+**Source:**  [unmerge_use.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/unmerge_use.rs#L12) 
 
 Extracts single use item from use list.
 
@@ -3651,7 +3677,7 @@ use std::fmt::Display;
 
 
 ### `unnecessary_async`
-**Source:**  [unnecessary_async.rs](/crates/ide-assists/src/handlers/unnecessary_async.rs#17) 
+**Source:**  [unnecessary_async.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/unnecessary_async.rs#L17) 
 
 Removes the `async` mark from functions which have no `.await` in their body.
 Looks for calls to the functions and removes the `.await` on the call site.
@@ -3670,7 +3696,7 @@ pub async fn bar() { foo() }
 
 
 ### `unqualify_method_call`
-**Source:**  [unqualify_method_call.rs](/crates/ide-assists/src/handlers/unqualify_method_call.rs#9) 
+**Source:**  [unqualify_method_call.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/unqualify_method_call.rs#L9) 
 
 Transforms universal function call syntax into a method call.
 
@@ -3692,7 +3718,7 @@ fn main() {
 
 
 ### `unwrap_block`
-**Source:**  [unwrap_block.rs](/crates/ide-assists/src/handlers/unwrap_block.rs#12) 
+**Source:**  [unwrap_block.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/unwrap_block.rs#L12) 
 
 This assist removes if...else, for, while and loop control statements to just keep the body.
 
@@ -3714,7 +3740,7 @@ fn foo() {
 
 
 ### `unwrap_option_return_type`
-**Source:**  [unwrap_return_type.rs](/crates/ide-assists/src/handlers/unwrap_return_type.rs#13) 
+**Source:**  [unwrap_return_type.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/unwrap_return_type.rs#L13) 
 
 Unwrap the function's return type.
 
@@ -3730,7 +3756,7 @@ fn foo() -> i32 { 42i32 }
 
 
 ### `unwrap_result_return_type`
-**Source:**  [unwrap_return_type.rs](/crates/ide-assists/src/handlers/unwrap_return_type.rs#26) 
+**Source:**  [unwrap_return_type.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/unwrap_return_type.rs#L26) 
 
 Unwrap the function's return type.
 
@@ -3746,7 +3772,7 @@ fn foo() -> i32 { 42i32 }
 
 
 ### `unwrap_tuple`
-**Source:**  [unwrap_tuple.rs](/crates/ide-assists/src/handlers/unwrap_tuple.rs#8) 
+**Source:**  [unwrap_tuple.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/unwrap_tuple.rs#L8) 
 
 Unwrap the tuple to different variables.
 
@@ -3767,7 +3793,7 @@ fn main() {
 
 
 ### `wrap_return_type_in_option`
-**Source:**  [wrap_return_type.rs](/crates/ide-assists/src/handlers/wrap_return_type.rs#16) 
+**Source:**  [wrap_return_type.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/wrap_return_type.rs#L16) 
 
 Wrap the function's return type into Option.
 
@@ -3783,7 +3809,7 @@ fn foo() -> Option<i32> { Some(42i32) }
 
 
 ### `wrap_return_type_in_result`
-**Source:**  [wrap_return_type.rs](/crates/ide-assists/src/handlers/wrap_return_type.rs#29) 
+**Source:**  [wrap_return_type.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/wrap_return_type.rs#L29) 
 
 Wrap the function's return type into Result.
 
@@ -3799,7 +3825,7 @@ fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }
 
 
 ### `wrap_unwrap_cfg_attr`
-**Source:**  [wrap_unwrap_cfg_attr.rs](/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs#12) 
+**Source:**  [wrap_unwrap_cfg_attr.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs#L12) 
 
 Wraps an attribute to a cfg_attr attribute or unwraps a cfg_attr attribute to the inner attributes.