Repository: rust-analyzer/rust-analyzer
Pull request #7895 (2021-03-06 20:02:23)

:arrow_up: xflags
bors r+
🤖

bors[bot]: Build failed:
  * [Rust (ubuntu-latest)](https://github.com/rust-analyzer/rust-analyzer/runs/2047641126)

Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 39f27098a8..c392a89070 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1919,18 +1919,18 @@ checksum = "06069a848f95fceae3e5e03c0ddc8cb78452b56654ee0c8e68f938cf790fb9e3"
 
 [[package]]
 name = "xflags"
-version = "0.1.4"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "222e914b43cec5d7305ac5116d10a14b3a52c50e9062d642c92631f3beabc729"
+checksum = "59ad6ce6a0b7224130015b4ebac796478ac04e0079f5d222a690efea06a9208a"
 dependencies = [
  "xflags-macros",
 ]
 
 [[package]]
 name = "xflags-macros"
-version = "0.1.4"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52f18f5b4aa7f95e209d5b9274f6164c3938920b4d5c75f97f0dd16daee25ddd"
+checksum = "c8037d3ca14996158b03c0fa905d0834906ef0fc7044df72c1f5ff690e5e62c9"
 dependencies = [
  "proc-macro2",
 ]
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index 9ee4b3059b..7656db974f 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -365,14 +365,14 @@ impl Module {
         let _p = profile::span("Module::diagnostics").detail(|| {
             format!("{:?}", self.name(db).map_or("<unknown>".into(), |name| name.to_string()))
         });
-        let def_map = self.id.def_map(db.upcast());
-        def_map.add_diagnostics(db.upcast(), self.id.local_id, sink);
+        let crate_def_map = self.id.def_map(db.upcast());
+        crate_def_map.add_diagnostics(db.upcast(), self.id.local_id, sink);
         for decl in self.declarations(db) {
             match decl {
                 crate::ModuleDef::Function(f) => f.diagnostics(db, sink),
                 crate::ModuleDef::Module(m) => {
                     // Only add diagnostics from inline modules
-                    if def_map[m.id.local_id].origin.is_inline() {
+                    if crate_def_map[m.id.local_id].origin.is_inline() {
                         m.diagnostics(db, sink)
                     }
                 }
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs
index 16e1bac402..ff4b4a0cf2 100644
--- a/crates/hir_def/src/body.rs
+++ b/crates/hir_def/src/body.rs
@@ -87,11 +87,11 @@ impl Expander {
         module: ModuleId,
     ) -> Expander {
         let cfg_expander = CfgExpander::new(db, current_file_id, module.krate);
-        let def_map = module.def_map(db);
+        let crate_def_map = module.def_map(db);
         let ast_id_map = db.ast_id_map(current_file_id);
         Expander {
             cfg_expander,
-            def_map,
+            def_map: crate_def_map,
             current_file_id,
             ast_id_map,
             module: module.local_id,
diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs
index 75c2d756bf..65d85c86a7 100644
--- a/crates/hir_def/src/child_by_source.rs
+++ b/crates/hir_def/src/child_by_source.rs
@@ -74,8 +74,8 @@ impl ChildBySource for ImplId {
 
 impl ChildBySource for ModuleId {
     fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap {
-        let def_map = self.def_map(db);
-        let module_data = &def_map[self.local_id];
+        let crate_def_map = self.def_map(db);
+        let module_data = &crate_def_map[self.local_id];
         module_data.scope.child_by_source(db)
     }
 }
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs
index 77ff21739d..e85f85e49e 100644
--- a/crates/hir_def/src/resolver.rs
+++ b/crates/hir_def/src/resolver.rs
@@ -34,7 +34,7 @@ pub struct Resolver {
 // FIXME how to store these best
 #[derive(Debug, Clone)]
 struct ModuleItemMap {
-    def_map: Arc<DefMap>,
+    crate_def_map: Arc<DefMap>,
     module_id: LocalModuleId,
 }
 
@@ -337,11 +337,11 @@ impl Resolver {
         let mut traits = FxHashSet::default();
         for scope in &self.scopes {
             if let Scope::ModuleScope(m) = scope {
-                if let Some(prelude) = m.def_map.prelude() {
+                if let Some(prelude) = m.crate_def_map.prelude() {
                     let prelude_def_map = prelude.def_map(db);
                     traits.extend(prelude_def_map[prelude.local_id].scope.traits());
                 }
-                traits.extend(m.def_map[m.module_id].scope.traits());
+                traits.extend(m.crate_def_map[m.module_id].scope.traits());
             }
         }
         traits
@@ -349,7 +349,7 @@ impl Resolver {
 
     fn module_scope(&self) -> Option<(&DefMap, LocalModuleId)> {
         self.scopes.iter().rev().find_map(|scope| match scope {
-            Scope::ModuleScope(m) => Some((&*m.def_map, m.module_id)),
+            Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)),
 
             _ => None,
         })
@@ -413,21 +413,21 @@ impl Scope {
                 //         def: m.module.into(),
                 //     }),
                 // );
-                m.def_map[m.module_id].scope.entries().for_each(|(name, def)| {
+                m.crate_def_map[m.module_id].scope.entries().for_each(|(name, def)| {
                     f(name.clone(), ScopeDef::PerNs(def));
                 });
-                m.def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| {
+                m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| {
                     let scope = PerNs::macros(macro_, Visibility::Public);
                     seen.insert((name.clone(), scope));
                     f(name.clone(), ScopeDef::PerNs(scope));
                 });
-                m.def_map.extern_prelude().for_each(|(name, &def)| {
+                m.crate_def_map.extern_prelude().for_each(|(name, &def)| {
                     f(name.clone(), ScopeDef::PerNs(PerNs::types(def, Visibility::Public)));
                 });
                 BUILTIN_SCOPE.iter().for_each(|(name, &def)| {
                     f(name.clone(), ScopeDef::PerNs(def));
                 });
-                if let Some(prelude) = m.def_map.prelude() {
+                if let Some(prelude) = m.crate_def_map.prelude() {
                     let prelude_def_map = prelude.def_map(db);
                     prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| {
                         let seen_tuple = (name.clone(), def);
@@ -513,8 +513,8 @@ impl Resolver {
         self.push_scope(Scope::ImplDefScope(impl_def))
     }
 
-    fn push_module_scope(self, def_map: Arc<DefMap>, module_id: LocalModuleId) -> Resolver {
-        self.push_scope(Scope::ModuleScope(ModuleItemMap { def_map, module_id }))
+    fn push_module_scope(self, crate_def_map: Arc<DefMap>, module_id: LocalModuleId) -> Resolver {
+        self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id }))
     }
 
     fn push_expr_scope(
@@ -534,7 +534,7 @@ impl ModuleItemMap {
         path: &ModPath,
     ) -> Option<ResolveValueResult> {
         let (module_def, idx) =
-            self.def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other);
+            self.crate_def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other);
         match idx {
             None => {
                 let value = to_value_ns(module_def)?;
@@ -564,7 +564,7 @@ impl ModuleItemMap {
         path: &ModPath,
     ) -> Option<(TypeNs, Option<usize>)> {
         let (module_def, idx) =
-            self.def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other);
+            self.crate_def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other);
         let res = to_type_ns(module_def)?;
         Some((res, idx))
     }
diff --git a/crates/ide_assists/src/handlers/generate_default_from_new.rs b/crates/ide_assists/src/handlers/generate_default_from_new.rs
deleted file mode 100644
index fa12545792..0000000000
--- a/crates/ide_assists/src/handlers/generate_default_from_new.rs
+++ /dev/null
@@ -1,374 +0,0 @@
-use crate::{
-    assist_context::{AssistContext, Assists},
-    AssistId,
-};
-use ide_db::helpers::FamousDefs;
-use syntax::{
-    ast::{self, Impl, NameOwner},
-    AstNode,
-};
-use test_utils::mark;
-
-// Assist: generate_default_from_new
-//
-// Generates default implementation from new method.
-//
-// ```
-// struct Example { _inner: () }
-//
-// impl Example {
-//     pub fn n$0ew() -> Self {
-//         Self { _inner: () }
-//     }
-// }
-// ```
-// ->
-// ```
-// struct Example { _inner: () }
-//
-// impl Example {
-//     pub fn new() -> Self {
-//         Self { _inner: () }
-//     }
-// }
-//
-// impl Default for Example {
-//     fn default() -> Self {
-//         Self::new()
-//     }
-// }
-// ```
-pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
-    let fn_node = ctx.find_node_at_offset::<ast::Fn>()?;
-    let fn_name = fn_node.name()?;
-
-    if fn_name.text() != "new" {
-        mark::hit!(other_function_than_new);
-        return None;
-    }
-
-    if fn_node.param_list()?.params().next().is_some() {
-        mark::hit!(new_function_with_parameters);
-        return None;
-    }
-
-    let impl_ = fn_node.syntax().ancestors().into_iter().find_map(ast::Impl::cast)?;
-    if is_default_implemented(ctx, &impl_) {
-        mark::hit!(default_block_is_already_present);
-        mark::hit!(struct_in_module_with_default);
-        return None;
-    }
-
-    let insert_location = impl_.syntax().text_range();
-
-    acc.add(
-        AssistId("generate_default_from_new", crate::AssistKind::Generate),
-        "Generate a Default impl from a new fn",
-        insert_location,
-        move |builder| {
-            let code = default_fn_node_for_new(impl_);
-            builder.insert(insert_location.end(), code);
-        },
-    )
-}
-
-fn default_fn_node_for_new(impl_: Impl) -> String {
-    format!(
-        "
-
-impl Default for {} {{
-    fn default() -> Self {{
-        Self::new()
-    }}
-}}",
-        impl_.self_ty().unwrap().syntax().text()
-    )
-}
-
-fn is_default_implemented(ctx: &AssistContext, impl_: &Impl) -> bool {
-    let db = ctx.sema.db;
-    let impl_ = ctx.sema.to_def(impl_);
-    let impl_def = match impl_ {
-        Some(value) => value,
-        None => return false,
-    };
-
-    let ty = impl_def.target_ty(db);
-    let krate = impl_def.module(db).krate();
-    let default = FamousDefs(&ctx.sema, Some(krate)).core_default_Default();
-    let default_trait = match default {
-        Some(value) => value,
-        None => return false,
-    };
-
-    ty.impls_trait(db, default_trait, &[])
-}
-
-#[cfg(test)]
-mod tests {
-    use ide_db::helpers::FamousDefs;
-
-    use crate::tests::{check_assist, check_assist_not_applicable};
-
-    use super::*;
-
-    #[test]
-    fn generate_default() {
-        check_pass(
-            r#"
-struct Example { _inner: () }
-
-impl Example {
-    pub fn ne$0w() -> Self {
-        Self { _inner: () }
-    }
-}
-
-fn main() {}
-"#,
-            r#"
-struct Example { _inner: () }
-
-impl Example {
-    pub fn new() -> Self {
-        Self { _inner: () }
-    }
-}
-
-impl Default for Example {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
-fn main() {}
-"#,
-        );
-    }
-
-    #[test]
-    fn generate_default2() {
-        check_pass(
-            r#"
-struct Test { value: u32 }
-
-impl Test {
-    pub fn ne$0w() -> Self {
-        Self { value: 0 }
-    }
-}
-"#,
-            r#"
-struct Test { value: u32 }
-
-impl Test {
-    pub fn new() -> Self {
-        Self { value: 0 }
-    }
-}
-
-impl Default for Test {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn new_function_with_parameters() {
-        mark::check!(new_function_with_parameters);
-        check_not_applicable(
-            r#"
-struct Example { _inner: () }
-
-impl Example {
-    pub fn $0new(value: ()) -> Self {
-        Self { _inner: value }
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn other_function_than_new() {
-        mark::check!(other_function_than_new);
-        check_not_applicable(
-            r#"
-struct Example { _inner: () }
-
-impl Example {
-    pub fn a$0dd() -> Self {
-        Self { _inner: () }
-    }
-}
-
-"#,
-        );
-    }
-
-    #[test]
-    fn default_block_is_already_present() {
-        mark::check!(default_block_is_already_present);
-        check_not_applicable(
-            r#"
-struct Example { _inner: () }
-
-impl Example {
-    pub fn n$0ew() -> Self {
-        Self { _inner: () }
-    }
-}
-
-impl Default for Example {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn standalone_new_function() {
-        check_not_applicable(
-            r#"
-fn n$0ew() -> u32 {
-    0
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn multiple_struct_blocks() {
-        check_pass(
-            r#"
-struct Example { _inner: () }
-struct Test { value: u32 }
-
-impl Example {
-    pub fn new$0() -> Self {
-        Self { _inner: () }
-    }
-}
-"#,
-            r#"
-struct Example { _inner: () }
-struct Test { value: u32 }
-
-impl Example {
-    pub fn new() -> Self {
-        Self { _inner: () }
-    }
-}
-
-impl Default for Example {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn when_struct_is_after_impl() {
-        check_pass(
-            r#"
-impl Example {
-    pub fn $0new() -> Self {
-        Self { _inner: () }
-    }
-}
-
-struct Example { _inner: () }
-"#,
-            r#"
-impl Example {
-    pub fn new() -> Self {
-        Self { _inner: () }
-    }
-}
-
-impl Default for Example {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
-struct Example { _inner: () }
-"#,
-        );
-    }
-
-    #[test]
-    fn struct_in_module() {
-        check_pass(
-            r#"
-mod test {
-    struct Example { _inner: () }
-
-    impl Example {
-        pub fn n$0ew() -> Self {
-            Self { _inner: () }
-        }
-    }
-}
-"#,
-            r#"
-mod test {
-    struct Example { _inner: () }
-
-    impl Example {
-        pub fn new() -> Self {
-            Self { _inner: () }
-        }
-    }
-
-impl Default for Example {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn struct_in_module_with_default() {
-        mark::check!(struct_in_module_with_default);
-        check_not_applicable(
-            r#"
-mod test {
-    struct Example { _inner: () }
-
-    impl Example {
-        pub fn n$0ew() -> Self {
-            Self { _inner: () }
-        }
-    }
-
-    impl Default for Example {
-        fn default() -> Self {
-            Self::new()
-        }
-    }
-}
-"#,
-        );
-    }
-
-    fn check_pass(before: &str, after: &str) {
-        let before = &format!("//- /main.rs crate:main deps:core{}{}", before, FamousDefs::FIXTURE);
-        check_assist(generate_default_from_new, before, after);
-    }
-
-    fn check_not_applicable(before: &str) {
-        let before = &format!("//- /main.rs crate:main deps:core{}{}", before, FamousDefs::FIXTURE);
-        check_assist_not_applicable(generate_default_from_new, before);
-    }
-}
diff --git a/crates/ide_assists/src/handlers/replace_string_with_char.rs b/crates/ide_assists/src/handlers/replace_string_with_char.rs
index 634b9c0b79..317318c247 100644
--- a/crates/ide_assists/src/handlers/replace_string_with_char.rs
+++ b/crates/ide_assists/src/handlers/replace_string_with_char.rs
@@ -25,16 +25,13 @@ pub(crate) fn replace_string_with_char(acc: &mut Assists, ctx: &AssistContext) -
     if value.chars().take(2).count() != 1 {
         return None;
     }
-    let quote_offets = token.quote_offsets()?;
 
     acc.add(
         AssistId("replace_string_with_char", AssistKind::RefactorRewrite),
         "Replace string with char",
         target,
         |edit| {
-            let (left, right) = quote_offets.quotes;
-            edit.replace(left, String::from('\''));
-            edit.replace(right, String::from('\''));
+            edit.replace(token.syntax().text_range(), format!("'{}'", value));
         },
     )
 }
@@ -50,10 +47,10 @@ mod tests {
         check_assist_target(
             replace_string_with_char,
             r#"
-fn f() {
-    let s = "$0c";
-}
-"#,
+            fn f() {
+                let s = "$0c";
+            }
+            "#,
             r#""c""#,
         );
     }
@@ -63,15 +60,15 @@ fn f() {
         check_assist(
             replace_string_with_char,
             r#"
-fn f() {
-    let s = "$0c";
-}
-"#,
+    fn f() {
+        let s = "$0c";
+    }
+    "#,
             r##"
-fn f() {
-    let s = 'c';
-}
-"##,
+    fn f() {
+        let s = 'c';
+    }
+    "##,
         )
     }
 
@@ -80,15 +77,15 @@ fn f() {
         check_assist(
             replace_string_with_char,
             r#"
-fn f() {
-    let s = "$0😀";
-}
-"#,
+    fn f() {
+        let s = "$0😀";
+    }
+    "#,
             r##"
-fn f() {
-    let s = '😀';
-}
-"##,
+    fn f() {
+        let s = '😀';
+    }
+    "##,
         )
     }
 
@@ -97,10 +94,10 @@ fn f() {
         check_assist_not_applicable(
             replace_string_with_char,
             r#"
-fn f() {
-    let s = "$0test";
-}
-"#,
+    fn f() {
+        let s = "$0test";
+    }
+    "#,
         )
     }
 
@@ -109,15 +106,15 @@ fn f() {
         check_assist(
             replace_string_with_char,
             r#"
-fn f() {
-    format!($0"x", 92)
-}
-"#,
+                fn f() {
+                    format!($0"x", 92)
+                }
+                "#,
             r##"
-fn f() {
-    format!('x', 92)
-}
-"##,
+                fn f() {
+                    format!('x', 92)
+                }
+                "##,
         )
     }
 
@@ -126,66 +123,15 @@ fn f() {
         check_assist(
             replace_string_with_char,
             r#"
-fn f() {
-    find($0"x");
-}
-"#,
+                fn f() {
+                    find($0"x");
+                }
+                "#,
             r##"
-fn f() {
-    find('x');
-}
-"##,
-        )
-    }
-
-    #[test]
-    fn replace_string_with_char_newline() {
-        check_assist(
-            replace_string_with_char,
-            r#"
-fn f() {
-    find($0"\n");
-}
-"#,
-            r##"
-fn f() {
-    find('\n');
-}
-"##,
-        )
-    }
-
-    #[test]
-    fn replace_string_with_char_unicode_escape() {
-        check_assist(
-            replace_string_with_char,
-            r#"
-fn f() {
-    find($0"\u{7FFF}");
-}
-"#,
-            r##"
-fn f() {
-    find('\u{7FFF}');
-}
-"##,
-        )
-    }
-
-    #[test]
-    fn replace_raw_string_with_char() {
-        check_assist(
-            replace_string_with_char,
-            r##"
-fn f() {
-    $0r#"X"#
-}
-"##,
-            r##"
-fn f() {
-    'X'
-}
-"##,
+                fn f() {
+                    find('x');
+                }
+                "##,
         )
     }
 }
diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs
index ea62d5f5da..9c8148462c 100644
--- a/crates/ide_assists/src/lib.rs
+++ b/crates/ide_assists/src/lib.rs
@@ -127,7 +127,6 @@ mod handlers {
     mod flip_comma;
     mod flip_trait_bound;
     mod generate_default_from_enum_variant;
-    mod generate_default_from_new;
     mod generate_derive;
     mod generate_enum_is_method;
     mod generate_enum_projection_method;
@@ -190,7 +189,6 @@ mod handlers {
             flip_comma::flip_comma,
             flip_trait_bound::flip_trait_bound,
             generate_default_from_enum_variant::generate_default_from_enum_variant,
-            generate_default_from_new::generate_default_from_new,
             generate_derive::generate_derive,
             generate_enum_is_method::generate_enum_is_method,
             generate_enum_projection_method::generate_enum_as_method,
diff --git a/crates/proc_macro_srv/src/dylib.rs b/crates/proc_macro_srv/src/dylib.rs
index baf10fea93..28a6ee5471 100644
--- a/crates/proc_macro_srv/src/dylib.rs
+++ b/crates/proc_macro_srv/src/dylib.rs
@@ -138,7 +138,7 @@ impl Expander {
                         parsed_body,
                         false,
                     );
-                    return res.map(|it| it.into_subtree());
+                    return res.map(|it| it.subtree);
                 }
                 bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => {
                     let res = client.run(
@@ -147,7 +147,7 @@ impl Expander {
                         parsed_body,
                         false,
                     );
-                    return res.map(|it| it.into_subtree());
+                    return res.map(|it| it.subtree);
                 }
                 bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => {
                     let res = client.run(
@@ -157,7 +157,7 @@ impl Expander {
                         parsed_body,
                         false,
                     );
-                    return res.map(|it| it.into_subtree());
+                    return res.map(|it| it.subtree);
                 }
                 _ => continue,
             }
diff --git a/crates/proc_macro_srv/src/proc_macro/bridge/client.rs b/crates/proc_macro_srv/src/proc_macro/bridge/client.rs
index b036d4e201..ca6749b9bc 100644
--- a/crates/proc_macro_srv/src/proc_macro/bridge/client.rs
+++ b/crates/proc_macro_srv/src/proc_macro/bridge/client.rs
@@ -238,7 +238,7 @@ macro_rules! define_client_side {
         $(impl $name {
             #[allow(unused)]
             $(pub(crate) fn $method($($arg: $arg_ty),*) $(-> $ret_ty)* {
-                panic!("crates should be linked against the sysroot version of proc_macro, not this one from rust-analyzer");
+                panic!("hello");
                 // Bridge::with(|bridge| {
                 //     let mut b = bridge.cached_buffer.take();
 
diff --git a/crates/proc_macro_srv/src/rustc_server.rs b/crates/proc_macro_srv/src/rustc_server.rs
index ceefd187d2..14c853c775 100644
--- a/crates/proc_macro_srv/src/rustc_server.rs
+++ b/crates/proc_macro_srv/src/rustc_server.rs
@@ -25,35 +25,27 @@ type Span = tt::TokenId;
 
 #[derive(Debug, Clone)]
 pub struct TokenStream {
-    pub token_trees: Vec<TokenTree>,
+    pub subtree: tt::Subtree,
 }
 
 impl TokenStream {
     pub fn new() -> Self {
-        TokenStream { token_trees: Default::default() }
+        TokenStream { subtree: Default::default() }
     }
 
     pub fn with_subtree(subtree: tt::Subtree) -> Self {
-        if subtree.delimiter.is_some() {
-            TokenStream { token_trees: vec![TokenTree::Subtree(subtree)] }
-        } else {
-            TokenStream { token_trees: subtree.token_trees }
-        }
-    }
-
-    pub fn into_subtree(self) -> tt::Subtree {
-        tt::Subtree { delimiter: None, token_trees: self.token_trees }
+        TokenStream { subtree }
     }
 
     pub fn is_empty(&self) -> bool {
-        self.token_trees.is_empty()
+        self.subtree.token_trees.is_empty()
     }
 }
 
 /// Creates a token stream containing a single token tree.
 impl From<TokenTree> for TokenStream {
     fn from(tree: TokenTree) -> TokenStream {
-        TokenStream { token_trees: vec![tree] }
+        TokenStream { subtree: tt::Subtree { delimiter: None, token_trees: vec![tree] } }
     }
 }
 
@@ -86,10 +78,10 @@ impl Extend<TokenStream> for TokenStream {
             for tkn in item {
                 match tkn {
                     tt::TokenTree::Subtree(subtree) if subtree.delimiter.is_none() => {
-                        self.token_trees.extend(subtree.token_trees);
+                        self.subtree.token_trees.extend(subtree.token_trees);
                     }
                     _ => {
-                        self.token_trees.push(tkn);
+                        self.subtree.token_trees.push(tkn);
                     }
                 }
             }
@@ -172,7 +164,7 @@ pub mod token_stream {
         type IntoIter = super::IntoIter<TokenTree>;
 
         fn into_iter(self) -> Self::IntoIter {
-            self.token_trees.into_iter()
+            self.subtree.token_trees.into_iter()
         }
     }
 
@@ -193,22 +185,28 @@ pub mod token_stream {
                 mbe::parse_to_token_tree(src).ok_or("Failed to parse from mbe")?;
 
             let subtree = subtree_replace_token_ids_with_unspecified(subtree);
-            Ok(TokenStream::with_subtree(subtree))
+            Ok(TokenStream { subtree })
         }
     }
 
     impl ToString for TokenStream {
         fn to_string(&self) -> String {
-            return tokentrees_to_text(&self.token_trees[..]);
+            let tt = self.subtree.clone().into();
+            to_text(&tt)
+        }
+    }
 
-            fn tokentrees_to_text(tkns: &[tt::TokenTree]) -> String {
-                tkns.iter()
+    fn to_text(tkn: &tt::TokenTree) -> String {
+        match tkn {
+            tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident.text.clone().into(),
+            tt::TokenTree::Leaf(tt::Leaf::Literal(literal)) => literal.text.clone().into(),
+            tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => format!("{}", punct.char),
+            tt::TokenTree::Subtree(subtree) => {
+                let content = subtree
+                    .token_trees
+                    .iter()
                     .fold((String::new(), true), |(last, last_to_joint), tkn| {
-                        let s = [last, tokentree_to_text(tkn)].join(if last_to_joint {
-                            ""
-                        } else {
-                            " "
-                        });
+                        let s = [last, to_text(tkn)].join(if last_to_joint { "" } else { " " });
                         let mut is_joint = false;
                         if let tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) = tkn {
                             if punct.spacing == tt::Spacing::Joint {
@@ -217,25 +215,15 @@ pub mod token_stream {
                         }
                         (s, is_joint)
                     })
-                    .0
-            }
-
-            fn tokentree_to_text(tkn: &tt::TokenTree) -> String {
-                match tkn {
-                    tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident.text.clone().into(),
-                    tt::TokenTree::Leaf(tt::Leaf::Literal(literal)) => literal.text.clone().into(),
-                    tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => format!("{}", punct.char),
-                    tt::TokenTree::Subtree(subtree) => {
-                        let content = tokentrees_to_text(&subtree.token_trees);
-                        let (open, close) = match subtree.delimiter.map(|it| it.kind) {
-                            None => ("", ""),
-                            Some(tt::DelimiterKind::Brace) => ("{", "}"),
-                            Some(tt::DelimiterKind::Parenthesis) => ("(", ")"),
-                            Some(tt::DelimiterKind::Bracket) => ("[", "]"),
-                        };
-                        format!("{}{}{}", open, content, close)
-                    }
-                }
+                    .0;
+
+                let (open, close) = match subtree.delimiter.map(|it| it.kind) {
+                    None => ("", ""),
+                    Some(tt::DelimiterKind::Brace) => ("{", "}"),
+                    Some(tt::DelimiterKind::Parenthesis) => ("(", ")"),
+                    Some(tt::DelimiterKind::Bracket) => ("[", "]"),
+                };
+                format!("{}{}{}", open, content, close)
             }
         }
     }
@@ -445,7 +433,10 @@ fn spacing_to_external(spacing: Spacing) -> bridge::Spacing {
 
 impl server::Group for Rustc {
     fn new(&mut self, delimiter: bridge::Delimiter, stream: Self::TokenStream) -> Self::Group {
-        Self::Group { delimiter: delim_to_internal(delimiter), token_trees: stream.token_trees }
+        Self::Group {
+            delimiter: delim_to_internal(delimiter),
+            token_trees: stream.subtree.token_trees,
+        }
     }
     fn delimiter(&mut self, group: &Self::Group) -> bridge::Delimiter {
         delim_to_external(group.delimiter)
@@ -453,7 +444,9 @@ impl server::Group for Rustc {
 
     // NOTE: Return value of do not include delimiter
     fn stream(&mut self, group: &Self::Group) -> Self::TokenStream {
-        TokenStream { token_trees: group.token_trees.clone() }
+        TokenStream {
+            subtree: tt::Subtree { delimiter: None, token_trees: group.token_trees.clone() },
+        }
     }
 
     fn span(&mut self, group: &Self::Group) -> Self::Span {
@@ -762,48 +755,28 @@ mod tests {
     #[test]
     fn test_rustc_server_to_string() {
         let s = TokenStream {
-            token_trees: vec![
-                tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
-                    text: "struct".into(),
-                    id: tt::TokenId::unspecified(),
-                })),
-                tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
-                    text: "T".into(),
-                    id: tt::TokenId::unspecified(),
-                })),
-                tt::TokenTree::Subtree(tt::Subtree {
-                    delimiter: Some(tt::Delimiter {
+            subtree: tt::Subtree {
+                delimiter: None,
+                token_trees: vec![
+                    tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
+                        text: "struct".into(),
+                        id: tt::TokenId::unspecified(),
+                    })),
+                    tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
+                        text: "T".into(),
                         id: tt::TokenId::unspecified(),
-                        kind: tt::DelimiterKind::Brace,
+                    })),
+                    tt::TokenTree::Subtree(tt::Subtree {
+                        delimiter: Some(tt::Delimiter {
+                            id: tt::TokenId::unspecified(),
+                            kind: tt::DelimiterKind::Brace,
+                        }),
+                        token_trees: vec![],
                     }),
-                    token_trees: vec![],
-                }),
-            ],
+                ],
+            },
         };
 
         assert_eq!(s.to_string(), "struct T {}");
     }
-
-    #[test]
-    fn test_rustc_server_from_str() {
-        use std::str::FromStr;
-        let subtree_paren_a = tt::TokenTree::Subtree(tt::Subtree {
-            delimiter: Some(tt::Delimiter {
-                id: tt::TokenId::unspecified(),
-                kind: tt::DelimiterKind::Parenthesis,
-            }),
-            token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
-                text: "a".into(),
-                id: tt::TokenId::unspecified(),
-            }))],
-        });
-
-        let t1 = TokenStream::from_str("(a)").unwrap();
-        assert_eq!(t1.token_trees.len(), 1);
-        assert_eq!(t1.token_trees[0], subtree_paren_a);
-
-        let t2 = TokenStream::from_str("(a);").unwrap();
-        assert_eq!(t2.token_trees.len(), 2);
-        assert_eq!(t2.token_trees[0], subtree_paren_a);
-    }
 }
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index 8789f08521..3130785ccc 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -24,7 +24,7 @@ jod-thread = "0.1.0"
 log = "0.4.8"
 lsp-types = { version = "0.88.0", features = ["proposed"] }
 parking_lot = "0.11.0"
-xflags = "0.1.2"
+xflags = "0.2.1"
 oorandom = "11.1.2"
 rustc-hash = "1.1.0"
 serde = { version = "1.0.106", features = ["derive"] }
diff --git a/crates/rust-analyzer/src/bin/flags.rs b/crates/rust-analyzer/src/bin/flags.rs
index 244912d26e..3a7caaf3fc 100644
--- a/crates/rust-analyzer/src/bin/flags.rs
+++ b/crates/rust-analyzer/src/bin/flags.rs
@@ -6,7 +6,9 @@ use ide_ssr::{SsrPattern, SsrRule};
 use rust_analyzer::cli::{BenchWhat, Position, Verbosity};
 use vfs::AbsPathBuf;
 
-xflags::args_parser! {
+xflags::xflags! {
+    src "./src/bin/flags.rs"
+
     /// LSP server for the Rust programming language.
     cmd rust-analyzer {
         /// Verbosity level, can be repeated multiple times.
@@ -120,7 +122,7 @@ xflags::args_parser! {
 
 // generated start
 // The following code is generated by `xflags` macro.
-// Run `env XFLAGS_DUMP= cargo build` to regenerate.
+// Run `env UPDATE_XFLAGS=1 cargo build` to regenerate.
 #[derive(Debug)]
 pub struct RustAnalyzer {
     pub verbose: u32,
@@ -158,7 +160,7 @@ pub struct Parse {
 }
 
 #[derive(Debug)]
-pub struct Symbols {}
+pub struct Symbols;
 
 #[derive(Debug)]
 pub struct Highlight {
@@ -211,14 +213,13 @@ pub struct Search {
 }
 
 #[derive(Debug)]
-pub struct ProcMacro {}
+pub struct ProcMacro;
 
 impl RustAnalyzer {
-    pub const HELP: &'static str = Self::_HELP;
+    pub const HELP: &'static str = Self::HELP_;
 
     pub fn from_env() -> xflags::Result<Self> {
-        let mut p = xflags::rt::Parser::new_from_env();
-        Self::_parse(&mut p)
+        Self::from_env_()
     }
 }
 // generated end
diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml
index b17dde598b..e084f0df65 100644
--- a/xtask/Cargo.toml
+++ b/xtask/Cargo.toml
@@ -15,5 +15,5 @@ ungrammar = "=1.11"
 walkdir = "2.3.1"
 write-json = "0.1.0"
 xshell = "0.1"
-xflags = "0.1.2"
+xflags = "0.2.1"
 # Avoid adding more dependencies to this crate
diff --git a/xtask/src/flags.rs b/xtask/src/flags.rs
index 56eda5b1e5..b39d937cac 100644
--- a/xtask/src/flags.rs
+++ b/xtask/src/flags.rs
@@ -2,7 +2,9 @@
 
 use crate::install::{ClientOpt, Malloc, ServerOpt};
 
-xflags::args_parser! {
+xflags::xflags! {
+    src "./src/flags.rs"
+
     /// Run custom build command.
     cmd xtask {
         default cmd help {
@@ -55,7 +57,7 @@ xflags::args_parser! {
 
 // generated start
 // The following code is generated by `xflags` macro.
-// Run `env XFLAGS_DUMP= cargo build` to regenerate.
+// Run `env UPDATE_XFLAGS=1 cargo build` to regenerate.
 #[derive(Debug)]
 pub struct Xtask {
     pub subcommand: XtaskCmd,
@@ -96,13 +98,13 @@ pub struct Codegen {
 }
 
 #[derive(Debug)]
-pub struct Lint {}
+pub struct Lint;
 
 #[derive(Debug)]
-pub struct FuzzTests {}
+pub struct FuzzTests;
 
 #[derive(Debug)]
-pub struct PreCache {}
+pub struct PreCache;
 
 #[derive(Debug)]
 pub struct Release {
@@ -131,11 +133,10 @@ pub struct Bb {
 }
 
 impl Xtask {
-    pub const HELP: &'static str = Self::_HELP;
+    pub const HELP: &'static str = Self::HELP_;
 
     pub fn from_env() -> xflags::Result<Self> {
-        let mut p = xflags::rt::Parser::new_from_env();
-        Self::_parse(&mut p)
+        Self::from_env_()
     }
 }
 // generated end


Test patch:
diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs
index 304b5798f2..4f007aa48b 100644
--- a/crates/ide_assists/src/tests/generated.rs
+++ b/crates/ide_assists/src/tests/generated.rs
@@ -439,37 +439,6 @@ impl Default for Version {
     )
 }
 
-#[test]
-fn doctest_generate_default_from_new() {
-    check_doc_test(
-        "generate_default_from_new",
-        r#####"
-struct Example { _inner: () }
-
-impl Example {
-    pub fn n$0ew() -> Self {
-        Self { _inner: () }
-    }
-}
-"#####,
-        r#####"
-struct Example { _inner: () }
-
-impl Example {
-    pub fn new() -> Self {
-        Self { _inner: () }
-    }
-}
-
-impl Default for Example {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-"#####,
-    )
-}
-
 #[test]
 fn doctest_generate_derive() {
     check_doc_test(
diff --git a/crates/proc_macro_srv/src/tests/utils.rs b/crates/proc_macro_srv/src/tests/utils.rs
index 0484c3af44..22813052df 100644
--- a/crates/proc_macro_srv/src/tests/utils.rs
+++ b/crates/proc_macro_srv/src/tests/utils.rs
@@ -52,7 +52,7 @@ pub fn assert_expand(
     let expander = dylib::Expander::new(&path).unwrap();
     let fixture = parse_string(ra_fixture).unwrap();
 
-    let res = expander.expand(macro_name, &fixture.into_subtree(), None).unwrap();
+    let res = expander.expand(macro_name, &fixture.subtree, None).unwrap();
     assert_eq_text!(&expect.trim(), &format!("{:?}", res));
 }