aboutsummaryrefslogtreecommitdiff
path: root/crates/ide
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2021-01-15 17:57:32 +0000
committerLukas Wirth <[email protected]>2021-01-15 18:21:23 +0000
commitcb863390f23bc2eac6561d55def9bd3ba54605fc (patch)
treeb19b39d9b6231e8857a4096cc803cf35e2ddbe81 /crates/ide
parent0c58aa9dc0e24f0fa6a6ee7eb0c35041dedddb0a (diff)
Handle self/super/crate in PathSegment as NameRef
Diffstat (limited to 'crates/ide')
-rw-r--r--crates/ide/src/diagnostics.rs4
-rw-r--r--crates/ide/src/display/navigation_target.rs23
-rw-r--r--crates/ide/src/goto_definition.rs35
-rw-r--r--crates/ide/src/hover.rs47
-rw-r--r--crates/ide/src/references.rs119
-rw-r--r--crates/ide/src/references/rename.rs2
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs39
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html6
-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.html6
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlighting.html18
11 files changed, 115 insertions, 186 deletions
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index 2e5395b51..b35bc2bae 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -18,7 +18,7 @@ use itertools::Itertools;
18use rustc_hash::FxHashSet; 18use rustc_hash::FxHashSet;
19use syntax::{ 19use syntax::{
20 ast::{self, AstNode}, 20 ast::{self, AstNode},
21 SyntaxNode, TextRange, T, 21 SyntaxNode, TextRange,
22}; 22};
23use text_edit::TextEdit; 23use text_edit::TextEdit;
24 24
@@ -232,7 +232,7 @@ fn text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(
232 single_use_tree: &ast::UseTree, 232 single_use_tree: &ast::UseTree,
233) -> Option<TextEdit> { 233) -> Option<TextEdit> {
234 let use_tree_list_node = single_use_tree.syntax().parent()?; 234 let use_tree_list_node = single_use_tree.syntax().parent()?;
235 if single_use_tree.path()?.segment()?.syntax().first_child_or_token()?.kind() == T![self] { 235 if single_use_tree.path()?.segment()?.self_token().is_some() {
236 let start = use_tree_list_node.prev_sibling_or_token()?.text_range().start(); 236 let start = use_tree_list_node.prev_sibling_or_token()?.text_range().start();
237 let end = use_tree_list_node.text_range().end(); 237 let end = use_tree_list_node.text_range().end();
238 return Some(TextEdit::delete(TextRange::new(start, end))); 238 return Some(TextEdit::delete(TextRange::new(start, end)));
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs
index 4eecae697..685052e7f 100644
--- a/crates/ide/src/display/navigation_target.rs
+++ b/crates/ide/src/display/navigation_target.rs
@@ -400,24 +400,33 @@ impl TryToNav for hir::GenericParam {
400impl ToNav for hir::Local { 400impl ToNav for hir::Local {
401 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 401 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
402 let src = self.source(db); 402 let src = self.source(db);
403 let node = match &src.value { 403 let (node, focus_range) = match &src.value {
404 Either::Left(bind_pat) => { 404 Either::Left(bind_pat) => (
405 bind_pat.name().map_or_else(|| bind_pat.syntax().clone(), |it| it.syntax().clone()) 405 bind_pat.syntax().clone(),
406 } 406 bind_pat
407 Either::Right(it) => it.syntax().clone(), 407 .name()
408 .map(|it| src.with_value(&it.syntax().clone()).original_file_range(db).range),
409 ),
410 Either::Right(it) => (it.syntax().clone(), it.self_token().map(|it| it.text_range())),
408 }; 411 };
409 let full_range = src.with_value(&node).original_file_range(db); 412 let full_range = src.with_value(&node).original_file_range(db);
410 let name = match self.name(db) { 413 let name = match self.name(db) {
411 Some(it) => it.to_string().into(), 414 Some(it) => it.to_string().into(),
412 None => "".into(), 415 None => "".into(),
413 }; 416 };
414 let kind = if self.is_param(db) { SymbolKind::ValueParam } else { SymbolKind::Local }; 417 let kind = if self.is_self(db) {
418 SymbolKind::SelfParam
419 } else if self.is_param(db) {
420 SymbolKind::ValueParam
421 } else {
422 SymbolKind::Local
423 };
415 NavigationTarget { 424 NavigationTarget {
416 file_id: full_range.file_id, 425 file_id: full_range.file_id,
417 name, 426 name,
418 kind: Some(kind), 427 kind: Some(kind),
419 full_range: full_range.range, 428 full_range: full_range.range,
420 focus_range: None, 429 focus_range,
421 container_name: None, 430 container_name: None,
422 description: None, 431 description: None,
423 docs: None, 432 docs: None,
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index cd4afc804..988a5668f 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -1,7 +1,6 @@
1use either::Either; 1use either::Either;
2use hir::{HasAttrs, ModuleDef, Semantics}; 2use hir::{HasAttrs, ModuleDef, Semantics};
3use ide_db::{ 3use ide_db::{
4 base_db::FileId,
5 defs::{Definition, NameClass, NameRefClass}, 4 defs::{Definition, NameClass, NameRefClass},
6 symbol_index, RootDatabase, 5 symbol_index, RootDatabase,
7}; 6};
@@ -13,7 +12,7 @@ use crate::{
13 display::{ToNav, TryToNav}, 12 display::{ToNav, TryToNav},
14 doc_links::extract_definitions_from_markdown, 13 doc_links::extract_definitions_from_markdown,
15 runnables::doc_owner_to_def, 14 runnables::doc_owner_to_def,
16 FilePosition, NavigationTarget, RangeInfo, SymbolKind, 15 FilePosition, NavigationTarget, RangeInfo,
17}; 16};
18 17
19// Feature: Go to Definition 18// Feature: Go to Definition
@@ -49,19 +48,6 @@ pub(crate) fn goto_definition(
49 let nav = def.try_to_nav(sema.db)?; 48 let nav = def.try_to_nav(sema.db)?;
50 vec![nav] 49 vec![nav]
51 }, 50 },
52 ast::SelfParam(self_param) => {
53 vec![self_to_nav_target(self_param, position.file_id)?]
54 },
55 ast::PathSegment(segment) => {
56 segment.self_token()?;
57 let path = segment.parent_path();
58 if path.qualifier().is_some() && !ast::PathExpr::can_cast(path.syntax().parent()?.kind()) {
59 return None;
60 }
61 let func = segment.syntax().ancestors().find_map(ast::Fn::cast)?;
62 let self_param = func.param_list()?.self_param()?;
63 vec![self_to_nav_target(self_param, position.file_id)?]
64 },
65 ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, &lt) { 51 ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, &lt) {
66 let def = name_class.referenced_or_defined(sema.db); 52 let def = name_class.referenced_or_defined(sema.db);
67 let nav = def.try_to_nav(sema.db)?; 53 let nav = def.try_to_nav(sema.db)?;
@@ -69,6 +55,11 @@ pub(crate) fn goto_definition(
69 } else { 55 } else {
70 reference_definition(&sema, Either::Left(&lt)).to_vec() 56 reference_definition(&sema, Either::Left(&lt)).to_vec()
71 }, 57 },
58 ast::SelfParam(self_param) => {
59 let def = NameClass::classify_self_param(&sema, &self_param)?.referenced_or_defined(sema.db);
60 let nav = def.try_to_nav(sema.db)?;
61 vec![nav]
62 },
72 _ => return None, 63 _ => return None,
73 } 64 }
74 }; 65 };
@@ -134,20 +125,6 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
134 } 125 }
135} 126}
136 127
137fn self_to_nav_target(self_param: ast::SelfParam, file_id: FileId) -> Option<NavigationTarget> {
138 let self_token = self_param.self_token()?;
139 Some(NavigationTarget {
140 file_id,
141 full_range: self_param.syntax().text_range(),
142 focus_range: Some(self_token.text_range()),
143 name: self_token.text().clone(),
144 kind: Some(SymbolKind::SelfParam),
145 container_name: None,
146 description: None,
147 docs: None,
148 })
149}
150
151#[derive(Debug)] 128#[derive(Debug)]
152pub(crate) enum ReferenceResult { 129pub(crate) enum ReferenceResult {
153 Exact(NavigationTarget), 130 Exact(NavigationTarget),
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 317b6f011..6022bd275 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -98,6 +98,7 @@ pub(crate) fn hover(
98 ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)), 98 ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)),
99 ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime) 99 ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime)
100 .map_or_else(|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced(sema.db)), |d| d.defined(sema.db)), 100 .map_or_else(|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced(sema.db)), |d| d.defined(sema.db)),
101 ast::SelfParam(self_param) => NameClass::classify_self_param(&sema, &self_param).and_then(|d| d.defined(sema.db)),
101 _ => None, 102 _ => None,
102 } 103 }
103 }; 104 };
@@ -134,17 +135,14 @@ pub(crate) fn hover(
134 return None; 135 return None;
135 } 136 }
136 137
137 let node = token.ancestors().find(|n| { 138 let node = token
138 ast::Expr::can_cast(n.kind()) 139 .ancestors()
139 || ast::Pat::can_cast(n.kind()) 140 .find(|n| ast::Expr::can_cast(n.kind()) || ast::Pat::can_cast(n.kind()))?;
140 || ast::SelfParam::can_cast(n.kind())
141 })?;
142 141
143 let ty = match_ast! { 142 let ty = match_ast! {
144 match node { 143 match node {
145 ast::Expr(it) => sema.type_of_expr(&it)?, 144 ast::Expr(it) => sema.type_of_expr(&it)?,
146 ast::Pat(it) => sema.type_of_pat(&it)?, 145 ast::Pat(it) => sema.type_of_pat(&it)?,
147 ast::SelfParam(self_param) => sema.type_of_self(&self_param)?,
148 // If this node is a MACRO_CALL, it means that `descend_into_macros` failed to resolve. 146 // If this node is a MACRO_CALL, it means that `descend_into_macros` failed to resolve.
149 // (e.g expanding a builtin macro). So we give up here. 147 // (e.g expanding a builtin macro). So we give up here.
150 ast::MacroCall(_it) => return None, 148 ast::MacroCall(_it) => return None,
@@ -386,7 +384,7 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
386 return tokens.max_by_key(priority); 384 return tokens.max_by_key(priority);
387 fn priority(n: &SyntaxToken) -> usize { 385 fn priority(n: &SyntaxToken) -> usize {
388 match n.kind() { 386 match n.kind() {
389 IDENT | INT_NUMBER | LIFETIME_IDENT => 3, 387 IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] => 3,
390 T!['('] | T![')'] => 2, 388 T!['('] | T![')'] => 2,
391 kind if kind.is_trivia() => 0, 389 kind if kind.is_trivia() => 0,
392 _ => 1, 390 _ => 1,
@@ -3130,6 +3128,39 @@ fn foo<T: Foo>(t: T$0){}
3130 } 3128 }
3131 3129
3132 #[test] 3130 #[test]
3131 fn test_hover_self_has_go_to_type() {
3132 check_actions(
3133 r#"
3134struct Foo;
3135impl Foo {
3136 fn foo(&self$0) {}
3137}
3138"#,
3139 expect![[r#"
3140 [
3141 GoToType(
3142 [
3143 HoverGotoTypeData {
3144 mod_path: "test::Foo",
3145 nav: NavigationTarget {
3146 file_id: FileId(
3147 0,
3148 ),
3149 full_range: 0..11,
3150 focus_range: 7..10,
3151 name: "Foo",
3152 kind: Struct,
3153 description: "struct Foo",
3154 },
3155 },
3156 ],
3157 ),
3158 ]
3159 "#]],
3160 );
3161 }
3162
3163 #[test]
3133 fn hover_displays_normalized_crate_names() { 3164 fn hover_displays_normalized_crate_names() {
3134 check( 3165 check(
3135 r#" 3166 r#"
@@ -3193,6 +3224,7 @@ impl Foo {
3193"#, 3224"#,
3194 expect![[r#" 3225 expect![[r#"
3195 *&self* 3226 *&self*
3227
3196 ```rust 3228 ```rust
3197 &Foo 3229 &Foo
3198 ``` 3230 ```
@@ -3212,6 +3244,7 @@ impl Foo {
3212"#, 3244"#,
3213 expect![[r#" 3245 expect![[r#"
3214 *self: Arc<Foo>* 3246 *self: Arc<Foo>*
3247
3215 ```rust 3248 ```rust
3216 Arc<Foo> 3249 Arc<Foo>
3217 ``` 3250 ```
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 7d4757e02..51a2f4327 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -11,6 +11,7 @@
11 11
12pub(crate) mod rename; 12pub(crate) mod rename;
13 13
14use either::Either;
14use hir::Semantics; 15use hir::Semantics;
15use ide_db::{ 16use ide_db::{
16 base_db::FileId, 17 base_db::FileId,
@@ -21,10 +22,10 @@ use ide_db::{
21use syntax::{ 22use syntax::{
22 algo::find_node_at_offset, 23 algo::find_node_at_offset,
23 ast::{self, NameOwner}, 24 ast::{self, NameOwner},
24 match_ast, AstNode, SyntaxNode, TextRange, TokenAtOffset, T, 25 AstNode, SyntaxNode, TextRange, TokenAtOffset, T,
25}; 26};
26 27
27use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo, SymbolKind}; 28use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo};
28 29
29#[derive(Debug, Clone)] 30#[derive(Debug, Clone)]
30pub struct ReferenceSearchResult { 31pub struct ReferenceSearchResult {
@@ -90,10 +91,6 @@ pub(crate) fn find_all_refs(
90 let _p = profile::span("find_all_refs"); 91 let _p = profile::span("find_all_refs");
91 let syntax = sema.parse(position.file_id).syntax().clone(); 92 let syntax = sema.parse(position.file_id).syntax().clone();
92 93
93 if let Some(res) = try_find_self_references(&syntax, position) {
94 return Some(res);
95 }
96
97 let (opt_name, search_kind) = if let Some(name) = 94 let (opt_name, search_kind) = if let Some(name) =
98 get_struct_def_name_for_struct_literal_search(&sema, &syntax, position) 95 get_struct_def_name_for_struct_literal_search(&sema, &syntax, position)
99 { 96 {
@@ -122,13 +119,16 @@ pub(crate) fn find_all_refs(
122 119
123 let mut kind = ReferenceKind::Other; 120 let mut kind = ReferenceKind::Other;
124 if let Definition::Local(local) = def { 121 if let Definition::Local(local) = def {
125 if let either::Either::Left(pat) = local.source(sema.db).value { 122 match local.source(sema.db).value {
126 if matches!( 123 Either::Left(pat) => {
127 pat.syntax().parent().and_then(ast::RecordPatField::cast), 124 if matches!(
128 Some(pat_field) if pat_field.name_ref().is_none() 125 pat.syntax().parent().and_then(ast::RecordPatField::cast),
129 ) { 126 Some(pat_field) if pat_field.name_ref().is_none()
130 kind = ReferenceKind::FieldShorthandForLocal; 127 ) {
128 kind = ReferenceKind::FieldShorthandForLocal;
129 }
131 } 130 }
131 Either::Right(_) => kind = ReferenceKind::SelfParam,
132 } 132 }
133 } else if matches!( 133 } else if matches!(
134 def, 134 def,
@@ -251,79 +251,6 @@ fn get_enum_def_name_for_struct_literal_search(
251 None 251 None
252} 252}
253 253
254fn try_find_self_references(
255 syntax: &SyntaxNode,
256 position: FilePosition,
257) -> Option<RangeInfo<ReferenceSearchResult>> {
258 let FilePosition { file_id, offset } = position;
259 let self_token = syntax.token_at_offset(offset).find(|t| t.kind() == T![self])?;
260 let parent = self_token.parent();
261 match_ast! {
262 match parent {
263 ast::SelfParam(it) => (),
264 ast::PathSegment(segment) => {
265 segment.self_token()?;
266 let path = segment.parent_path();
267 if path.qualifier().is_some() && !ast::PathExpr::can_cast(path.syntax().parent()?.kind()) {
268 return None;
269 }
270 },
271 _ => return None,
272 }
273 };
274 let function = parent.ancestors().find_map(ast::Fn::cast)?;
275 let self_param = function.param_list()?.self_param()?;
276 let param_self_token = self_param.self_token()?;
277
278 let declaration = Declaration {
279 nav: NavigationTarget {
280 file_id,
281 full_range: self_param.syntax().text_range(),
282 focus_range: Some(param_self_token.text_range()),
283 name: param_self_token.text().clone(),
284 kind: Some(SymbolKind::SelfParam),
285 container_name: None,
286 description: None,
287 docs: None,
288 },
289 kind: ReferenceKind::SelfKw,
290 access: Some(if self_param.mut_token().is_some() {
291 ReferenceAccess::Write
292 } else {
293 ReferenceAccess::Read
294 }),
295 };
296 let refs = function
297 .body()
298 .map(|body| {
299 body.syntax()
300 .descendants()
301 .filter_map(ast::PathExpr::cast)
302 .filter_map(|expr| {
303 let path = expr.path()?;
304 if path.qualifier().is_none() {
305 path.segment()?.self_token()
306 } else {
307 None
308 }
309 })
310 .map(|token| FileReference {
311 range: token.text_range(),
312 kind: ReferenceKind::SelfKw,
313 access: declaration.access, // FIXME: properly check access kind here instead of copying it from the declaration
314 })
315 .collect()
316 })
317 .unwrap_or_default();
318 let mut references = UsageSearchResult::default();
319 references.references.insert(file_id, refs);
320
321 Some(RangeInfo::new(
322 param_self_token.text_range(),
323 ReferenceSearchResult { declaration, references },
324 ))
325}
326
327#[cfg(test)] 254#[cfg(test)]
328mod tests { 255mod tests {
329 use expect_test::{expect, Expect}; 256 use expect_test::{expect, Expect};
@@ -512,7 +439,7 @@ fn main() {
512 i = 5; 439 i = 5;
513}"#, 440}"#,
514 expect![[r#" 441 expect![[r#"
515 i Local FileId(0) 24..25 Other Write 442 i Local FileId(0) 20..25 24..25 Other Write
516 443
517 FileId(0) 50..51 Other Write 444 FileId(0) 50..51 Other Write
518 FileId(0) 54..55 Other Read 445 FileId(0) 54..55 Other Read
@@ -536,7 +463,7 @@ fn bar() {
536} 463}
537"#, 464"#,
538 expect![[r#" 465 expect![[r#"
539 spam Local FileId(0) 19..23 Other 466 spam Local FileId(0) 19..23 19..23 Other
540 467
541 FileId(0) 34..38 Other Read 468 FileId(0) 34..38 Other Read
542 FileId(0) 41..45 Other Read 469 FileId(0) 41..45 Other Read
@@ -551,7 +478,7 @@ fn bar() {
551fn foo(i : u32) -> u32 { i$0 } 478fn foo(i : u32) -> u32 { i$0 }
552"#, 479"#,
553 expect![[r#" 480 expect![[r#"
554 i ValueParam FileId(0) 7..8 Other 481 i ValueParam FileId(0) 7..8 7..8 Other
555 482
556 FileId(0) 25..26 Other Read 483 FileId(0) 25..26 Other Read
557 "#]], 484 "#]],
@@ -565,7 +492,7 @@ fn foo(i : u32) -> u32 { i$0 }
565fn foo(i$0 : u32) -> u32 { i } 492fn foo(i$0 : u32) -> u32 { i }
566"#, 493"#,
567 expect![[r#" 494 expect![[r#"
568 i ValueParam FileId(0) 7..8 Other 495 i ValueParam FileId(0) 7..8 7..8 Other
569 496
570 FileId(0) 25..26 Other Read 497 FileId(0) 25..26 Other Read
571 "#]], 498 "#]],
@@ -813,7 +740,7 @@ fn foo() {
813} 740}
814"#, 741"#,
815 expect![[r#" 742 expect![[r#"
816 i Local FileId(0) 23..24 Other Write 743 i Local FileId(0) 19..24 23..24 Other Write
817 744
818 FileId(0) 34..35 Other Write 745 FileId(0) 34..35 Other Write
819 FileId(0) 38..39 Other Read 746 FileId(0) 38..39 Other Read
@@ -853,7 +780,7 @@ fn foo() {
853} 780}
854"#, 781"#,
855 expect![[r#" 782 expect![[r#"
856 i Local FileId(0) 19..20 Other 783 i Local FileId(0) 19..20 19..20 Other
857 784
858 FileId(0) 26..27 Other Write 785 FileId(0) 26..27 Other Write
859 "#]], 786 "#]],
@@ -995,10 +922,10 @@ impl Foo {
995} 922}
996"#, 923"#,
997 expect![[r#" 924 expect![[r#"
998 self SelfParam FileId(0) 47..51 47..51 SelfKw Read 925 self SelfParam FileId(0) 47..51 47..51 SelfParam
999 926
1000 FileId(0) 71..75 SelfKw Read 927 FileId(0) 71..75 Other Read
1001 FileId(0) 152..156 SelfKw Read 928 FileId(0) 152..156 Other Read
1002 "#]], 929 "#]],
1003 ); 930 );
1004 } 931 }
@@ -1105,7 +1032,7 @@ fn main() {
1105} 1032}
1106"#, 1033"#,
1107 expect![[r#" 1034 expect![[r#"
1108 a Local FileId(0) 59..60 Other 1035 a Local FileId(0) 59..60 59..60 Other
1109 1036
1110 FileId(0) 80..81 Other Read 1037 FileId(0) 80..81 Other Read
1111 "#]], 1038 "#]],
@@ -1123,7 +1050,7 @@ fn main() {
1123} 1050}
1124"#, 1051"#,
1125 expect![[r#" 1052 expect![[r#"
1126 a Local FileId(0) 59..60 Other 1053 a Local FileId(0) 59..60 59..60 Other
1127 1054
1128 FileId(0) 80..81 Other Read 1055 FileId(0) 80..81 Other Read
1129 "#]], 1056 "#]],
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index 039efb26f..9ac4af026 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -444,7 +444,7 @@ fn rename_reference(
444 mark::hit!(rename_not_an_ident_ref); 444 mark::hit!(rename_not_an_ident_ref);
445 bail!("Invalid name `{}`: not an identifier", new_name) 445 bail!("Invalid name `{}`: not an identifier", new_name)
446 } 446 }
447 (IdentifierKind::ToSelf, ReferenceKind::SelfKw) => { 447 (IdentifierKind::ToSelf, ReferenceKind::SelfParam) => {
448 unreachable!("rename_self_to_param should've been called instead") 448 unreachable!("rename_self_to_param should've been called instead")
449 } 449 }
450 (IdentifierKind::ToSelf, _) => { 450 (IdentifierKind::ToSelf, _) => {
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index 34bae49a8..87578e70a 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -226,35 +226,16 @@ pub(super) fn element(
226 T![unsafe] => h | HlMod::Unsafe, 226 T![unsafe] => h | HlMod::Unsafe,
227 T![true] | T![false] => HlTag::BoolLiteral.into(), 227 T![true] | T![false] => HlTag::BoolLiteral.into(),
228 T![self] => { 228 T![self] => {
229 let self_param_is_mut = element 229 let self_param = element.parent().and_then(ast::SelfParam::cast);
230 .parent() 230 if let Some(NameClass::Definition(def)) = self_param
231 .and_then(ast::SelfParam::cast) 231 .and_then(|self_param| NameClass::classify_self_param(sema, &self_param))
232 .and_then(|p| p.mut_token())
233 .is_some();
234 let self_path = &element
235 .parent()
236 .as_ref()
237 .and_then(SyntaxNode::parent)
238 .and_then(ast::Path::cast)
239 .and_then(|p| sema.resolve_path(&p));
240 let mut h = HlTag::Symbol(SymbolKind::SelfParam).into();
241 if self_param_is_mut
242 || matches!(self_path,
243 Some(hir::PathResolution::Local(local))
244 if local.is_self(db)
245 && (local.is_mut(db) || local.ty(db).is_mutable_reference())
246 )
247 { 232 {
248 h |= HlMod::Mutable 233 highlight_def(db, def) | HlMod::Definition
249 } 234 } else if element.ancestors().any(|it| it.kind() == USE_TREE) {
250 235 HlTag::Symbol(SymbolKind::SelfParam).into()
251 if let Some(hir::PathResolution::Local(local)) = self_path { 236 } else {
252 if is_consumed_lvalue(element, &local, db) { 237 return None;
253 h |= HlMod::Consuming;
254 }
255 } 238 }
256
257 h
258 } 239 }
259 T![ref] => element 240 T![ref] => element
260 .parent() 241 .parent()
@@ -345,7 +326,9 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
345 hir::GenericParam::LifetimeParam(_) => HlTag::Symbol(SymbolKind::LifetimeParam), 326 hir::GenericParam::LifetimeParam(_) => HlTag::Symbol(SymbolKind::LifetimeParam),
346 }, 327 },
347 Definition::Local(local) => { 328 Definition::Local(local) => {
348 let tag = if local.is_param(db) { 329 let tag = if local.is_self(db) {
330 HlTag::Symbol(SymbolKind::SelfParam)
331 } else if local.is_param(db) {
349 HlTag::Symbol(SymbolKind::ValueParam) 332 HlTag::Symbol(SymbolKind::ValueParam)
350 } else { 333 } else {
351 HlTag::Symbol(SymbolKind::Local) 334 HlTag::Symbol(SymbolKind::Local)
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
index e36e6fc3f..d421a7803 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
@@ -42,16 +42,16 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
42 42
43<span class="keyword">impl</span> <span class="struct">foo</span> <span class="brace">{</span> 43<span class="keyword">impl</span> <span class="struct">foo</span> <span class="brace">{</span>
44 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 44 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
45 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 45 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
46<span class="brace">}</span> 46<span class="brace">}</span>
47 47
48<span class="keyword">trait</span> <span class="trait declaration">t</span> <span class="brace">{</span> 48<span class="keyword">trait</span> <span class="trait declaration">t</span> <span class="brace">{</span>
49 <span class="keyword">fn</span> <span class="function declaration static associated">t_is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 49 <span class="keyword">fn</span> <span class="function declaration static associated">t_is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
50 <span class="keyword">fn</span> <span class="function declaration associated">t_is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 50 <span class="keyword">fn</span> <span class="function declaration associated">t_is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
51<span class="brace">}</span> 51<span class="brace">}</span>
52 52
53<span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="brace">{</span> 53<span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="brace">{</span>
54 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 54 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
55 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 55 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
56<span class="brace">}</span> 56<span class="brace">}</span>
57 </code></pre> \ No newline at end of file 57 </code></pre> \ No newline at end of file
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 6dadda1c1..5e877df88 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
@@ -93,7 +93,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
93 <span class="comment documentation">/// ```sh</span> 93 <span class="comment documentation">/// ```sh</span>
94 <span class="comment documentation">/// echo 1</span> 94 <span class="comment documentation">/// echo 1</span>
95 <span class="comment documentation">/// ```</span> 95 <span class="comment documentation">/// ```</span>
96 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">foo</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">bool</span> <span class="brace">{</span> 96 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">foo</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">bool</span> <span class="brace">{</span>
97 <span class="bool_literal">true</span> 97 <span class="bool_literal">true</span>
98 <span class="brace">}</span> 98 <span class="brace">}</span>
99<span class="brace">}</span> 99<span class="brace">}</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 9d4d6d4a0..036cb6c11 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
@@ -46,7 +46,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
46<span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="semicolon">;</span> 46<span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="semicolon">;</span>
47 47
48<span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="brace">{</span> 48<span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="brace">{</span>
49 <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration associated unsafe">unsafe_method</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 49 <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration associated unsafe">unsafe_method</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
50<span class="brace">}</span> 50<span class="brace">}</span>
51 51
52<span class="keyword">struct</span> <span class="struct declaration">TypeForStaticMut</span> <span class="brace">{</span> 52<span class="keyword">struct</span> <span class="struct declaration">TypeForStaticMut</span> <span class="brace">{</span>
@@ -61,11 +61,11 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
61<span class="brace">}</span> 61<span class="brace">}</span>
62 62
63<span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="brace">{</span> 63<span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="brace">{</span>
64 <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span><span class="semicolon">;</span> 64 <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span><span class="semicolon">;</span>
65<span class="brace">}</span> 65<span class="brace">}</span>
66 66
67<span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="brace">{</span> 67<span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="brace">{</span>
68 <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 68 <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
69<span class="brace">}</span> 69<span class="brace">}</span>
70 70
71<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> 71<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
index 6b7447c46..237149566 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
@@ -66,25 +66,25 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
66<span class="brace">}</span> 66<span class="brace">}</span>
67 67
68<span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="brace">{</span> 68<span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="brace">{</span>
69 <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span><span class="semicolon">;</span> 69 <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span><span class="semicolon">;</span>
70<span class="brace">}</span> 70<span class="brace">}</span>
71 71
72<span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="brace">{</span> 72<span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="brace">{</span>
73 <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span> 73 <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
74 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> 74 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span>
75 <span class="brace">}</span> 75 <span class="brace">}</span>
76<span class="brace">}</span> 76<span class="brace">}</span>
77 77
78<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="brace">{</span> 78<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="brace">{</span>
79 <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="parenthesis">(</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">Foo</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span> 79 <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="parenthesis">(</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">Foo</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
80 <span class="value_param">f</span><span class="operator">.</span><span class="function consuming associated">baz</span><span class="parenthesis">(</span><span class="self_keyword mutable consuming">self</span><span class="parenthesis">)</span> 80 <span class="value_param">f</span><span class="operator">.</span><span class="function consuming associated">baz</span><span class="parenthesis">(</span><span class="self_keyword mutable consuming">self</span><span class="parenthesis">)</span>
81 <span class="brace">}</span> 81 <span class="brace">}</span>
82 82
83 <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="parenthesis">)</span> <span class="brace">{</span> 83 <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable">self</span><span class="parenthesis">)</span> <span class="brace">{</span>
84 <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span> 84 <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span>
85 <span class="brace">}</span> 85 <span class="brace">}</span>
86 86
87 <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span> 87 <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
88 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> 88 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span>
89 <span class="brace">}</span> 89 <span class="brace">}</span>
90<span class="brace">}</span> 90<span class="brace">}</span>
@@ -95,15 +95,15 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
95<span class="brace">}</span> 95<span class="brace">}</span>
96 96
97<span class="keyword">impl</span> <span class="struct">FooCopy</span> <span class="brace">{</span> 97<span class="keyword">impl</span> <span class="struct">FooCopy</span> <span class="brace">{</span>
98 <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">FooCopy</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="brace">{</span> 98 <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">FooCopy</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="brace">{</span>
99 <span class="value_param">f</span><span class="operator">.</span><span class="function associated">baz</span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="parenthesis">)</span> 99 <span class="value_param">f</span><span class="operator">.</span><span class="function associated">baz</span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="parenthesis">)</span>
100 <span class="brace">}</span> 100 <span class="brace">}</span>
101 101
102 <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="parenthesis">)</span> <span class="brace">{</span> 102 <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable">self</span><span class="parenthesis">)</span> <span class="brace">{</span>
103 <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span> 103 <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span>
104 <span class="brace">}</span> 104 <span class="brace">}</span>
105 105
106 <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="brace">{</span> 106 <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="brace">{</span>
107 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> 107 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span>
108 <span class="brace">}</span> 108 <span class="brace">}</span>
109<span class="brace">}</span> 109<span class="brace">}</span>
@@ -213,7 +213,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
213<span class="keyword">use</span> <span class="enum">Option</span><span class="operator">::</span><span class="punctuation">*</span><span class="semicolon">;</span> 213<span class="keyword">use</span> <span class="enum">Option</span><span class="operator">::</span><span class="punctuation">*</span><span class="semicolon">;</span>
214 214
215<span class="keyword">impl</span><span class="angle">&lt;</span><span class="type_param declaration">T</span><span class="angle">&gt;</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="type_param">T</span><span class="angle">&gt;</span> <span class="brace">{</span> 215<span class="keyword">impl</span><span class="angle">&lt;</span><span class="type_param declaration">T</span><span class="angle">&gt;</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="type_param">T</span><span class="angle">&gt;</span> <span class="brace">{</span>
216 <span class="keyword">fn</span> <span class="function declaration associated">and</span><span class="angle">&lt;</span><span class="type_param declaration">U</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="comma">,</span> <span class="value_param declaration">other</span><span class="colon">:</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="type_param">U</span><span class="angle">&gt;</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="parenthesis">(</span><span class="type_param">T</span><span class="comma">,</span> <span class="type_param">U</span><span class="parenthesis">)</span><span class="angle">&gt;</span> <span class="brace">{</span> 216 <span class="keyword">fn</span> <span class="function declaration associated">and</span><span class="angle">&lt;</span><span class="type_param declaration">U</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="comma">,</span> <span class="value_param declaration">other</span><span class="colon">:</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="type_param">U</span><span class="angle">&gt;</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="parenthesis">(</span><span class="type_param">T</span><span class="comma">,</span> <span class="type_param">U</span><span class="parenthesis">)</span><span class="angle">&gt;</span> <span class="brace">{</span>
217 <span class="keyword control">match</span> <span class="value_param">other</span> <span class="brace">{</span> 217 <span class="keyword control">match</span> <span class="value_param">other</span> <span class="brace">{</span>
218 <span class="enum_variant">None</span> <span class="operator">=&gt;</span> <span class="macro">unimplemented!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span> 218 <span class="enum_variant">None</span> <span class="operator">=&gt;</span> <span class="macro">unimplemented!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span>
219 <span class="variable declaration">Nope</span> <span class="operator">=&gt;</span> <span class="variable">Nope</span><span class="comma">,</span> 219 <span class="variable declaration">Nope</span> <span class="operator">=&gt;</span> <span class="variable">Nope</span><span class="comma">,</span>