aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/completion/src/completions/postfix.rs59
-rw-r--r--crates/completion/src/lib.rs2
-rw-r--r--crates/ide/src/goto_definition.rs56
-rw-r--r--crates/ide/src/hover.rs46
-rw-r--r--crates/ide/src/references/rename.rs166
-rw-r--r--crates/ide/src/syntax_highlighting.rs19
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlighting.html10
-rw-r--r--crates/rust-analyzer/src/config.rs2
10 files changed, 319 insertions, 45 deletions
diff --git a/crates/completion/src/completions/postfix.rs b/crates/completion/src/completions/postfix.rs
index 7fbda7a6b..1785794cc 100644
--- a/crates/completion/src/completions/postfix.rs
+++ b/crates/completion/src/completions/postfix.rs
@@ -5,6 +5,7 @@ mod format_like;
5use ide_db::ty_filter::TryEnum; 5use ide_db::ty_filter::TryEnum;
6use syntax::{ 6use syntax::{
7 ast::{self, AstNode, AstToken}, 7 ast::{self, AstNode, AstToken},
8 SyntaxKind::BLOCK_EXPR,
8 TextRange, TextSize, 9 TextRange, TextSize,
9}; 10};
10use text_edit::TextEdit; 11use text_edit::TextEdit;
@@ -220,6 +221,30 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
220 ) 221 )
221 .add_to(acc); 222 .add_to(acc);
222 223
224 let parent_node = dot_receiver.syntax().parent().and_then(|p| p.parent());
225 if let Some(parent) = parent_node {
226 if parent.kind() == BLOCK_EXPR {
227 postfix_snippet(
228 ctx,
229 cap,
230 &dot_receiver,
231 "let",
232 "let",
233 &format!("let $0 = {};", receiver_text),
234 )
235 .add_to(acc);
236 postfix_snippet(
237 ctx,
238 cap,
239 &dot_receiver,
240 "letm",
241 "let mut",
242 &format!("let mut $0 = {};", receiver_text),
243 )
244 .add_to(acc);
245 }
246 }
247
223 if let ast::Expr::Literal(literal) = dot_receiver.clone() { 248 if let ast::Expr::Literal(literal) = dot_receiver.clone() {
224 if let Some(literal_text) = ast::String::cast(literal.token()) { 249 if let Some(literal_text) = ast::String::cast(literal.token()) {
225 add_format_like_completions(acc, ctx, &dot_receiver, cap, &literal_text); 250 add_format_like_completions(acc, ctx, &dot_receiver, cap, &literal_text);
@@ -296,6 +321,38 @@ fn main() {
296 sn dbg dbg!(expr) 321 sn dbg dbg!(expr)
297 sn dbgr dbg!(&expr) 322 sn dbgr dbg!(&expr)
298 sn if if expr {} 323 sn if if expr {}
324 sn let let
325 sn letm let mut
326 sn match match expr {}
327 sn not !expr
328 sn ok Ok(expr)
329 sn ref &expr
330 sn refm &mut expr
331 sn some Some(expr)
332 sn while while expr {}
333 "#]],
334 );
335 }
336
337 #[test]
338 fn postfix_completion_works_for_function_calln() {
339 check(
340 r#"
341fn foo(elt: bool) -> bool {
342 !elt
343}
344
345fn main() {
346 let bar = true;
347 foo(bar.<|>)
348}
349"#,
350 expect![[r#"
351 sn box Box::new(expr)
352 sn call function(expr)
353 sn dbg dbg!(expr)
354 sn dbgr dbg!(&expr)
355 sn if if expr {}
299 sn match match expr {} 356 sn match match expr {}
300 sn not !expr 357 sn not !expr
301 sn ok Ok(expr) 358 sn ok Ok(expr)
@@ -321,6 +378,8 @@ fn main() {
321 sn call function(expr) 378 sn call function(expr)
322 sn dbg dbg!(expr) 379 sn dbg dbg!(expr)
323 sn dbgr dbg!(&expr) 380 sn dbgr dbg!(&expr)
381 sn let let
382 sn letm let mut
324 sn match match expr {} 383 sn match match expr {}
325 sn ok Ok(expr) 384 sn ok Ok(expr)
326 sn ref &expr 385 sn ref &expr
diff --git a/crates/completion/src/lib.rs b/crates/completion/src/lib.rs
index aecc1378b..1ec2e9be7 100644
--- a/crates/completion/src/lib.rs
+++ b/crates/completion/src/lib.rs
@@ -44,6 +44,8 @@ pub use crate::{
44// - `expr.while` -> `while expr {}` or `while let ... {}` for `Option` or `Result` 44// - `expr.while` -> `while expr {}` or `while let ... {}` for `Option` or `Result`
45// - `expr.ref` -> `&expr` 45// - `expr.ref` -> `&expr`
46// - `expr.refm` -> `&mut expr` 46// - `expr.refm` -> `&mut expr`
47// - `expr.let` -> `let <|> = expr;`
48// - `expr.letm` -> `let mut <|> = expr;`
47// - `expr.not` -> `!expr` 49// - `expr.not` -> `!expr`
48// - `expr.dbg` -> `dbg!(expr)` 50// - `expr.dbg` -> `dbg!(expr)`
49// - `expr.dbgr` -> `dbg!(&expr)` 51// - `expr.dbgr` -> `dbg!(&expr)`
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index d41dd3d92..b9810457f 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -1,5 +1,6 @@
1use hir::Semantics; 1use hir::Semantics;
2use ide_db::{ 2use ide_db::{
3 base_db::FileId,
3 defs::{NameClass, NameRefClass}, 4 defs::{NameClass, NameRefClass},
4 symbol_index, RootDatabase, 5 symbol_index, RootDatabase,
5}; 6};
@@ -40,10 +41,17 @@ pub(crate) fn goto_definition(
40 vec![nav] 41 vec![nav]
41 }, 42 },
42 ast::SelfParam(self_param) => { 43 ast::SelfParam(self_param) => {
43 let ty = sema.type_of_self(&self_param)?; 44 vec![self_to_nav_target(self_param, position.file_id)?]
44 let adt_def = ty.autoderef(db).filter_map(|ty| ty.as_adt()).last()?; 45 },
45 let nav = adt_def.to_nav(db); 46 ast::PathSegment(segment) => {
46 vec![nav] 47 segment.self_token()?;
48 let path = segment.parent_path();
49 if path.qualifier().is_some() && !ast::PathExpr::can_cast(path.syntax().parent()?.kind()) {
50 return None;
51 }
52 let func = segment.syntax().ancestors().find_map(ast::Fn::cast)?;
53 let self_param = func.param_list()?.self_param()?;
54 vec![self_to_nav_target(self_param, position.file_id)?]
47 }, 55 },
48 _ => return None, 56 _ => return None,
49 } 57 }
@@ -63,6 +71,20 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
63 } 71 }
64} 72}
65 73
74fn self_to_nav_target(self_param: ast::SelfParam, file_id: FileId) -> Option<NavigationTarget> {
75 let self_token = self_param.self_token()?;
76 Some(NavigationTarget {
77 file_id,
78 full_range: self_param.syntax().text_range(),
79 focus_range: Some(self_token.text_range()),
80 name: self_token.text().clone(),
81 kind: self_token.kind(),
82 container_name: None,
83 description: None,
84 docs: None,
85 })
86}
87
66#[derive(Debug)] 88#[derive(Debug)]
67pub(crate) enum ReferenceResult { 89pub(crate) enum ReferenceResult {
68 Exact(NavigationTarget), 90 Exact(NavigationTarget),
@@ -987,31 +1009,31 @@ fn g() -> <() as Iterator<A = (), B<|> = u8>>::A {}
987 } 1009 }
988 1010
989 #[test] 1011 #[test]
990 fn todo_def_type_for_self() { 1012 fn goto_self_param_ty_specified() {
991 check( 1013 check(
992 r#" 1014 r#"
993struct Foo {} 1015struct Foo {}
994 //^^^
995 1016
996impl Foo { 1017impl Foo {
997 fn bar(&self<|>) {} 1018 fn bar(self: &Foo) {
998} 1019 //^^^^
999"#, 1020 let foo = sel<|>f;
1000 ); 1021 }
1022}"#,
1023 )
1001 } 1024 }
1002 1025
1003 #[test] 1026 #[test]
1004 fn todo_def_type_for_arbitrary_self() { 1027 fn goto_self_param_on_decl() {
1005 check( 1028 check(
1006 r#" 1029 r#"
1007struct Arc<T>(T);
1008 //^^^
1009struct Foo {} 1030struct Foo {}
1010 1031
1011impl Foo { 1032impl Foo {
1012 fn bar(self<|>: Arc<Self>) {} 1033 fn bar(&self<|>) {
1013} 1034 //^^^^
1014"#, 1035 }
1015 ); 1036}"#,
1037 )
1016 } 1038 }
1017} 1039}
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 832192881..94ad800a0 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -139,14 +139,17 @@ pub(crate) fn hover(
139 } 139 }
140 } 140 }
141 141
142 let node = token 142 let node = token.ancestors().find(|n| {
143 .ancestors() 143 ast::Expr::can_cast(n.kind())
144 .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some())?; 144 || ast::Pat::can_cast(n.kind())
145 || ast::SelfParam::can_cast(n.kind())
146 })?;
145 147
146 let ty = match_ast! { 148 let ty = match_ast! {
147 match node { 149 match node {
148 ast::Expr(it) => sema.type_of_expr(&it)?, 150 ast::Expr(it) => sema.type_of_expr(&it)?,
149 ast::Pat(it) => sema.type_of_pat(&it)?, 151 ast::Pat(it) => sema.type_of_pat(&it)?,
152 ast::SelfParam(self_param) => sema.type_of_self(&self_param)?,
150 // If this node is a MACRO_CALL, it means that `descend_into_macros` failed to resolve. 153 // If this node is a MACRO_CALL, it means that `descend_into_macros` failed to resolve.
151 // (e.g expanding a builtin macro). So we give up here. 154 // (e.g expanding a builtin macro). So we give up here.
152 ast::MacroCall(_it) => return None, 155 ast::MacroCall(_it) => return None,
@@ -3282,4 +3285,41 @@ fn main() {
3282 "#]], 3285 "#]],
3283 ); 3286 );
3284 } 3287 }
3288
3289 #[test]
3290 fn hover_self_param_shows_type() {
3291 check(
3292 r#"
3293struct Foo {}
3294impl Foo {
3295 fn bar(&sel<|>f) {}
3296}
3297"#,
3298 expect![[r#"
3299 *&self*
3300 ```rust
3301 &Foo
3302 ```
3303 "#]],
3304 );
3305 }
3306
3307 #[test]
3308 fn hover_self_param_shows_type_for_arbitrary_self_type() {
3309 check(
3310 r#"
3311struct Arc<T>(T);
3312struct Foo {}
3313impl Foo {
3314 fn bar(sel<|>f: Arc<Foo>) {}
3315}
3316"#,
3317 expect![[r#"
3318 *self: Arc<Foo>*
3319 ```rust
3320 Arc<Foo>
3321 ```
3322 "#]],
3323 );
3324 }
3285} 3325}
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index 91c64bd4a..731457696 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -221,24 +221,47 @@ fn rename_to_self(
221 let source_file = sema.parse(position.file_id); 221 let source_file = sema.parse(position.file_id);
222 let syn = source_file.syntax(); 222 let syn = source_file.syntax();
223 223
224 let fn_def = find_node_at_offset::<ast::Fn>(syn, position.offset) 224 let (fn_def, fn_ast) = find_node_at_offset::<ast::Fn>(syn, position.offset)
225 .and_then(|fn_ast| sema.to_def(&fn_ast).zip(Some(fn_ast)))
225 .ok_or_else(|| RenameError("No surrounding method declaration found".to_string()))?; 226 .ok_or_else(|| RenameError("No surrounding method declaration found".to_string()))?;
226 let params = 227 let param_range = fn_ast
227 fn_def.param_list().ok_or_else(|| RenameError("Method has no parameters".to_string()))?; 228 .param_list()
228 if params.self_param().is_some() { 229 .and_then(|p| p.params().next())
230 .ok_or_else(|| RenameError("Method has no parameters".to_string()))?
231 .syntax()
232 .text_range();
233 if !param_range.contains(position.offset) {
234 return Err(RenameError("Only the first parameter can be self".to_string()));
235 }
236
237 let impl_block = find_node_at_offset::<ast::Impl>(syn, position.offset)
238 .and_then(|def| sema.to_def(&def))
239 .ok_or_else(|| RenameError("No impl block found for function".to_string()))?;
240 if fn_def.self_param(sema.db).is_some() {
229 return Err(RenameError("Method already has a self parameter".to_string())); 241 return Err(RenameError("Method already has a self parameter".to_string()));
230 } 242 }
243
244 let params = fn_def.params(sema.db);
231 let first_param = 245 let first_param =
232 params.params().next().ok_or_else(|| RenameError("Method has no parameters".into()))?; 246 params.first().ok_or_else(|| RenameError("Method has no parameters".into()))?;
233 let mutable = match first_param.ty() { 247 let first_param_ty = first_param.ty();
234 Some(ast::Type::RefType(rt)) => rt.mut_token().is_some(), 248 let impl_ty = impl_block.target_ty(sema.db);
235 _ => return Err(RenameError("Not renaming other types".to_string())), 249 let (ty, self_param) = if impl_ty.remove_ref().is_some() {
250 // if the impl is a ref to the type we can just match the `&T` with self directly
251 (first_param_ty.clone(), "self")
252 } else {
253 first_param_ty.remove_ref().map_or((first_param_ty.clone(), "self"), |ty| {
254 (ty, if first_param_ty.is_mutable_reference() { "&mut self" } else { "&self" })
255 })
236 }; 256 };
237 257
258 if ty != impl_ty {
259 return Err(RenameError("Parameter type differs from impl block type".to_string()));
260 }
261
238 let RangeInfo { range, info: refs } = find_all_refs(sema, position, None) 262 let RangeInfo { range, info: refs } = find_all_refs(sema, position, None)
239 .ok_or_else(|| RenameError("No reference found at position".to_string()))?; 263 .ok_or_else(|| RenameError("No reference found at position".to_string()))?;
240 264
241 let param_range = first_param.syntax().text_range();
242 let (param_ref, usages): (Vec<Reference>, Vec<Reference>) = refs 265 let (param_ref, usages): (Vec<Reference>, Vec<Reference>) = refs
243 .into_iter() 266 .into_iter()
244 .partition(|reference| param_range.intersect(reference.file_range.range).is_some()); 267 .partition(|reference| param_range.intersect(reference.file_range.range).is_some());
@@ -254,10 +277,7 @@ fn rename_to_self(
254 277
255 edits.push(SourceFileEdit { 278 edits.push(SourceFileEdit {
256 file_id: position.file_id, 279 file_id: position.file_id,
257 edit: TextEdit::replace( 280 edit: TextEdit::replace(param_range, String::from(self_param)),
258 param_range,
259 String::from(if mutable { "&mut self" } else { "&self" }),
260 ),
261 }); 281 });
262 282
263 Ok(RangeInfo::new(range, SourceChange::from(edits))) 283 Ok(RangeInfo::new(range, SourceChange::from(edits)))
@@ -280,7 +300,11 @@ fn text_edit_from_self_param(
280 300
281 let mut replacement_text = String::from(new_name); 301 let mut replacement_text = String::from(new_name);
282 replacement_text.push_str(": "); 302 replacement_text.push_str(": ");
283 replacement_text.push_str(self_param.mut_token().map_or("&", |_| "&mut ")); 303 match (self_param.amp_token(), self_param.mut_token()) {
304 (None, None) => (),
305 (Some(_), None) => replacement_text.push('&'),
306 (_, Some(_)) => replacement_text.push_str("&mut "),
307 };
284 replacement_text.push_str(type_name.as_str()); 308 replacement_text.push_str(type_name.as_str());
285 309
286 Some(TextEdit::replace(self_param.syntax().text_range(), replacement_text)) 310 Some(TextEdit::replace(self_param.syntax().text_range(), replacement_text))
@@ -1082,6 +1106,95 @@ impl Foo {
1082} 1106}
1083"#, 1107"#,
1084 ); 1108 );
1109 check(
1110 "self",
1111 r#"
1112struct Foo { i: i32 }
1113
1114impl Foo {
1115 fn f(foo<|>: Foo) -> i32 {
1116 foo.i
1117 }
1118}
1119"#,
1120 r#"
1121struct Foo { i: i32 }
1122
1123impl Foo {
1124 fn f(self) -> i32 {
1125 self.i
1126 }
1127}
1128"#,
1129 );
1130 }
1131
1132 #[test]
1133 fn test_parameter_to_self_error_no_impl() {
1134 check(
1135 "self",
1136 r#"
1137struct Foo { i: i32 }
1138
1139fn f(foo<|>: &mut Foo) -> i32 {
1140 foo.i
1141}
1142"#,
1143 "error: No impl block found for function",
1144 );
1145 check(
1146 "self",
1147 r#"
1148struct Foo { i: i32 }
1149struct Bar;
1150
1151impl Bar {
1152 fn f(foo<|>: &mut Foo) -> i32 {
1153 foo.i
1154 }
1155}
1156"#,
1157 "error: Parameter type differs from impl block type",
1158 );
1159 }
1160
1161 #[test]
1162 fn test_parameter_to_self_error_not_first() {
1163 check(
1164 "self",
1165 r#"
1166struct Foo { i: i32 }
1167impl Foo {
1168 fn f(x: (), foo<|>: &mut Foo) -> i32 {
1169 foo.i
1170 }
1171}
1172"#,
1173 "error: Only the first parameter can be self",
1174 );
1175 }
1176
1177 #[test]
1178 fn test_parameter_to_self_impl_ref() {
1179 check(
1180 "self",
1181 r#"
1182struct Foo { i: i32 }
1183impl &Foo {
1184 fn f(foo<|>: &Foo) -> i32 {
1185 foo.i
1186 }
1187}
1188"#,
1189 r#"
1190struct Foo { i: i32 }
1191impl &Foo {
1192 fn f(self) -> i32 {
1193 self.i
1194 }
1195}
1196"#,
1197 );
1085 } 1198 }
1086 1199
1087 #[test] 1200 #[test]
@@ -1110,6 +1223,31 @@ impl Foo {
1110 } 1223 }
1111 1224
1112 #[test] 1225 #[test]
1226 fn test_owned_self_to_parameter() {
1227 check(
1228 "foo",
1229 r#"
1230struct Foo { i: i32 }
1231
1232impl Foo {
1233 fn f(<|>self) -> i32 {
1234 self.i
1235 }
1236}
1237"#,
1238 r#"
1239struct Foo { i: i32 }
1240
1241impl Foo {
1242 fn f(foo: Foo) -> i32 {
1243 foo.i
1244 }
1245}
1246"#,
1247 );
1248 }
1249
1250 #[test]
1113 fn test_self_in_path_to_parameter() { 1251 fn test_self_in_path_to_parameter() {
1114 check( 1252 check(
1115 "foo", 1253 "foo",
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index 1ed77b40b..5150a970c 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -76,6 +76,7 @@ pub(crate) fn highlight(
76 let mut current_macro_call: Option<ast::MacroCall> = None; 76 let mut current_macro_call: Option<ast::MacroCall> = None;
77 let mut format_string_highlighter = FormatStringHighlighter::default(); 77 let mut format_string_highlighter = FormatStringHighlighter::default();
78 let mut macro_rules_highlighter = MacroRulesHighlighter::default(); 78 let mut macro_rules_highlighter = MacroRulesHighlighter::default();
79 let mut inside_attribute = false;
79 80
80 // Walk all nodes, keeping track of whether we are inside a macro or not. 81 // Walk all nodes, keeping track of whether we are inside a macro or not.
81 // If in macro, expand it first and highlight the expanded code. 82 // If in macro, expand it first and highlight the expanded code.
@@ -132,9 +133,12 @@ pub(crate) fn highlight(
132 _ => (), 133 _ => (),
133 } 134 }
134 135
135 // Check for Rust code in documentation
136 match &event { 136 match &event {
137 // Check for Rust code in documentation
137 WalkEvent::Leave(NodeOrToken::Node(node)) => { 138 WalkEvent::Leave(NodeOrToken::Node(node)) => {
139 if ast::Attr::can_cast(node.kind()) {
140 inside_attribute = false
141 }
138 if let Some((doctest, range_mapping, new_comments)) = 142 if let Some((doctest, range_mapping, new_comments)) =
139 injection::extract_doc_comments(node) 143 injection::extract_doc_comments(node)
140 { 144 {
@@ -146,6 +150,9 @@ pub(crate) fn highlight(
146 ); 150 );
147 } 151 }
148 } 152 }
153 WalkEvent::Enter(NodeOrToken::Node(node)) if ast::Attr::can_cast(node.kind()) => {
154 inside_attribute = true
155 }
149 _ => (), 156 _ => (),
150 } 157 }
151 158
@@ -188,12 +195,16 @@ pub(crate) fn highlight(
188 } 195 }
189 } 196 }
190 197
191 if let Some((highlight, binding_hash)) = highlight_element( 198 if let Some((mut highlight, binding_hash)) = highlight_element(
192 &sema, 199 &sema,
193 &mut bindings_shadow_count, 200 &mut bindings_shadow_count,
194 syntactic_name_ref_highlighting, 201 syntactic_name_ref_highlighting,
195 element_to_highlight.clone(), 202 element_to_highlight.clone(),
196 ) { 203 ) {
204 if inside_attribute {
205 highlight = highlight | HighlightModifier::Attribute;
206 }
207
197 if macro_rules_highlighter.highlight(element_to_highlight.clone()).is_none() { 208 if macro_rules_highlighter.highlight(element_to_highlight.clone()).is_none() {
198 stack.add(HighlightedRange { range, highlight, binding_hash }); 209 stack.add(HighlightedRange { range, highlight, binding_hash });
199 } 210 }
@@ -474,7 +485,9 @@ fn highlight_element(
474 485
475 // Highlight references like the definitions they resolve to 486 // Highlight references like the definitions they resolve to
476 NAME_REF if element.ancestors().any(|it| it.kind() == ATTR) => { 487 NAME_REF if element.ancestors().any(|it| it.kind() == ATTR) => {
477 Highlight::from(HighlightTag::Function) | HighlightModifier::Attribute 488 // even though we track whether we are in an attribute or not we still need this special case
489 // as otherwise we would emit unresolved references for name refs inside attributes
490 Highlight::from(HighlightTag::Function)
478 } 491 }
479 NAME_REF => { 492 NAME_REF => {
480 let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); 493 let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap();
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
index 6be88f856..d79fa6dca 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
@@ -50,7 +50,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
50 <span class="comment documentation">/// # Examples</span> 50 <span class="comment documentation">/// # Examples</span>
51 <span class="comment documentation">///</span> 51 <span class="comment documentation">///</span>
52 <span class="comment documentation">/// ```</span> 52 <span class="comment documentation">/// ```</span>
53 <span class="comment documentation">/// #</span><span class="generic injected"> </span><span class="attribute injected">#</span><span class="attribute injected">!</span><span class="attribute injected">[</span><span class="function attribute injected">allow</span><span class="punctuation injected">(</span><span class="attribute injected">unused_mut</span><span class="punctuation injected">)</span><span class="attribute injected">]</span> 53 <span class="comment documentation">/// #</span><span class="generic injected"> </span><span class="attribute attribute injected">#</span><span class="attribute attribute injected">!</span><span class="attribute attribute injected">[</span><span class="function attribute injected">allow</span><span class="punctuation attribute injected">(</span><span class="attribute attribute injected">unused_mut</span><span class="punctuation attribute injected">)</span><span class="attribute attribute injected">]</span>
54 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="keyword injected">mut</span><span class="generic injected"> </span><span class="variable declaration injected mutable">foo</span><span class="punctuation injected">:</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="generic injected"> </span><span class="operator injected">=</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected"> 54 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="keyword injected">mut</span><span class="generic injected"> </span><span class="variable declaration injected mutable">foo</span><span class="punctuation injected">:</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="generic injected"> </span><span class="operator injected">=</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected">
55</span> <span class="comment documentation">/// ```</span> 55</span> <span class="comment documentation">/// ```</span>
56 <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function declaration static">new</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="struct">Foo</span> <span class="punctuation">{</span> 56 <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function declaration static">new</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
index 4b6d6adc9..1d05b7713 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
@@ -54,7 +54,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
54 54
55<span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable unsafe">global_mut</span><span class="punctuation">:</span> <span class="struct">TypeForStaticMut</span> <span class="operator">=</span> <span class="struct">TypeForStaticMut</span> <span class="punctuation">{</span> <span class="field">a</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span><span class="punctuation">;</span> 55<span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable unsafe">global_mut</span><span class="punctuation">:</span> <span class="struct">TypeForStaticMut</span> <span class="operator">=</span> <span class="struct">TypeForStaticMut</span> <span class="punctuation">{</span> <span class="field">a</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span><span class="punctuation">;</span>
56 56
57<span class="attribute">#</span><span class="attribute">[</span><span class="function attribute">repr</span><span class="punctuation">(</span><span class="attribute">packed</span><span class="punctuation">)</span><span class="attribute">]</span> 57<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">repr</span><span class="punctuation attribute">(</span><span class="attribute attribute">packed</span><span class="punctuation attribute">)</span><span class="attribute attribute">]</span>
58<span class="keyword">struct</span> <span class="struct declaration">Packed</span> <span class="punctuation">{</span> 58<span class="keyword">struct</span> <span class="struct declaration">Packed</span> <span class="punctuation">{</span>
59 <span class="field declaration">a</span><span class="punctuation">:</span> <span class="builtin_type">u16</span><span class="punctuation">,</span> 59 <span class="field declaration">a</span><span class="punctuation">:</span> <span class="builtin_type">u16</span><span class="punctuation">,</span>
60<span class="punctuation">}</span> 60<span class="punctuation">}</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
index 6a10a9dcd..15fbf2ce3 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
@@ -40,18 +40,18 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
40 40
41<span class="comment">// Needed for function consuming vs normal</span> 41<span class="comment">// Needed for function consuming vs normal</span>
42<span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration">marker</span> <span class="punctuation">{</span> 42<span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration">marker</span> <span class="punctuation">{</span>
43 <span class="attribute">#</span><span class="attribute">[</span><span class="function attribute">lang</span><span class="attribute"> </span><span class="operator">=</span><span class="attribute"> </span><span class="string_literal">"copy"</span><span class="attribute">]</span> 43 <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">lang</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"copy"</span><span class="attribute attribute">]</span>
44 <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">Copy</span> <span class="punctuation">{</span><span class="punctuation">}</span> 44 <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">Copy</span> <span class="punctuation">{</span><span class="punctuation">}</span>
45<span class="punctuation">}</span> 45<span class="punctuation">}</span>
46 46
47<span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration">ops</span> <span class="punctuation">{</span> 47<span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration">ops</span> <span class="punctuation">{</span>
48 <span class="attribute">#</span><span class="attribute">[</span><span class="function attribute">lang</span><span class="attribute"> </span><span class="operator">=</span><span class="attribute"> </span><span class="string_literal">"fn_once"</span><span class="attribute">]</span> 48 <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">lang</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"fn_once"</span><span class="attribute attribute">]</span>
49 <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">FnOnce</span><span class="punctuation">&lt;</span><span class="type_param declaration">Args</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">}</span> 49 <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">FnOnce</span><span class="punctuation">&lt;</span><span class="type_param declaration">Args</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">}</span>
50 50
51 <span class="attribute">#</span><span class="attribute">[</span><span class="function attribute">lang</span><span class="attribute"> </span><span class="operator">=</span><span class="attribute"> </span><span class="string_literal">"fn_mut"</span><span class="attribute">]</span> 51 <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">lang</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"fn_mut"</span><span class="attribute attribute">]</span>
52 <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">FnMut</span><span class="punctuation">&lt;</span><span class="type_param declaration">Args</span><span class="punctuation">&gt;</span><span class="punctuation">:</span> <span class="trait">FnOnce</span><span class="punctuation">&lt;</span><span class="type_param">Args</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">}</span> 52 <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">FnMut</span><span class="punctuation">&lt;</span><span class="type_param declaration">Args</span><span class="punctuation">&gt;</span><span class="punctuation">:</span> <span class="trait">FnOnce</span><span class="punctuation">&lt;</span><span class="type_param">Args</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">}</span>
53 53
54 <span class="attribute">#</span><span class="attribute">[</span><span class="function attribute">lang</span><span class="attribute"> </span><span class="operator">=</span><span class="attribute"> </span><span class="string_literal">"fn"</span><span class="attribute">]</span> 54 <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">lang</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"fn"</span><span class="attribute attribute">]</span>
55 <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">Fn</span><span class="punctuation">&lt;</span><span class="type_param declaration">Args</span><span class="punctuation">&gt;</span><span class="punctuation">:</span> <span class="trait">FnMut</span><span class="punctuation">&lt;</span><span class="type_param">Args</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">}</span> 55 <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">Fn</span><span class="punctuation">&lt;</span><span class="type_param declaration">Args</span><span class="punctuation">&gt;</span><span class="punctuation">:</span> <span class="trait">FnMut</span><span class="punctuation">&lt;</span><span class="type_param">Args</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">}</span>
56<span class="punctuation">}</span> 56<span class="punctuation">}</span>
57 57
@@ -85,7 +85,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
85 <span class="punctuation">}</span> 85 <span class="punctuation">}</span>
86<span class="punctuation">}</span> 86<span class="punctuation">}</span>
87 87
88<span class="attribute">#</span><span class="attribute">[</span><span class="function attribute">derive</span><span class="punctuation">(</span><span class="attribute">Copy</span><span class="punctuation">)</span><span class="attribute">]</span> 88<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">derive</span><span class="punctuation attribute">(</span><span class="attribute attribute">Copy</span><span class="punctuation attribute">)</span><span class="attribute attribute">]</span>
89<span class="keyword">struct</span> <span class="struct declaration">FooCopy</span> <span class="punctuation">{</span> 89<span class="keyword">struct</span> <span class="struct declaration">FooCopy</span> <span class="punctuation">{</span>
90 <span class="field declaration">x</span><span class="punctuation">:</span> <span class="builtin_type">u32</span><span class="punctuation">,</span> 90 <span class="field declaration">x</span><span class="punctuation">:</span> <span class="builtin_type">u32</span><span class="punctuation">,</span>
91<span class="punctuation">}</span> 91<span class="punctuation">}</span>
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 30299a465..59269a74b 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -480,7 +480,7 @@ macro_rules! config_data {
480 480
481config_data! { 481config_data! {
482 struct ConfigData { 482 struct ConfigData {
483 assist_importMergeBehaviour: MergeBehaviourDef = MergeBehaviourDef::None, 483 assist_importMergeBehaviour: MergeBehaviourDef = MergeBehaviourDef::Full,
484 assist_importPrefix: ImportPrefixDef = ImportPrefixDef::Plain, 484 assist_importPrefix: ImportPrefixDef = ImportPrefixDef::Plain,
485 485
486 callInfo_full: bool = true, 486 callInfo_full: bool = true,