aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/assists/src/handlers/fix_visibility.rs10
-rw-r--r--crates/hir/src/semantics/source_to_def.rs4
-rw-r--r--crates/hir_def/src/adt.rs28
-rw-r--r--crates/hir_ty/Cargo.toml6
-rw-r--r--crates/ide/src/completion/complete_postfix/format_like.rs2
-rw-r--r--crates/ide/src/lib.rs6
-rw-r--r--crates/ide/src/references.rs88
-rw-r--r--crates/ide/src/references/rename.rs175
-rw-r--r--crates/ide_db/src/search.rs116
-rw-r--r--crates/proc_macro_srv/src/proc_macro/bridge/client.rs1
-rw-r--r--crates/proc_macro_srv/src/proc_macro/bridge/mod.rs4
-rw-r--r--crates/proc_macro_srv/src/proc_macro/bridge/server.rs2
-rw-r--r--crates/proc_macro_srv/src/proc_macro/mod.rs22
-rw-r--r--crates/proc_macro_srv/src/rustc_server.rs10
-rw-r--r--crates/profile/Cargo.toml2
-rw-r--r--crates/project_model/src/sysroot.rs10
-rw-r--r--crates/rust-analyzer/src/handlers.rs17
-rw-r--r--crates/syntax/Cargo.toml2
18 files changed, 379 insertions, 126 deletions
diff --git a/crates/assists/src/handlers/fix_visibility.rs b/crates/assists/src/handlers/fix_visibility.rs
index 7cd76ea06..d505e9444 100644
--- a/crates/assists/src/handlers/fix_visibility.rs
+++ b/crates/assists/src/handlers/fix_visibility.rs
@@ -324,14 +324,14 @@ pub struct Foo { pub bar: () }
324 324
325 #[test] 325 #[test]
326 fn fix_visibility_of_enum_variant_field() { 326 fn fix_visibility_of_enum_variant_field() {
327 check_assist( 327 // Enum variants, as well as their fields, always get the enum's visibility. In fact, rustc
328 // rejects any visibility specifiers on them, so this assist should never fire on them.
329 check_assist_not_applicable(
328 fix_visibility, 330 fix_visibility,
329 r"mod foo { pub enum Foo { Bar { bar: () } } } 331 r"mod foo { pub enum Foo { Bar { bar: () } } }
330 fn main() { foo::Foo::Bar { <|>bar: () }; } ", 332 fn main() { foo::Foo::Bar { <|>bar: () }; } ",
331 r"mod foo { pub enum Foo { Bar { $0pub(crate) bar: () } } }
332 fn main() { foo::Foo::Bar { bar: () }; } ",
333 ); 333 );
334 check_assist( 334 check_assist_not_applicable(
335 fix_visibility, 335 fix_visibility,
336 r" 336 r"
337//- /lib.rs 337//- /lib.rs
@@ -340,8 +340,6 @@ fn main() { foo::Foo::Bar { <|>bar: () }; }
340//- /foo.rs 340//- /foo.rs
341pub enum Foo { Bar { bar: () } } 341pub enum Foo { Bar { bar: () } }
342", 342",
343 r"pub enum Foo { Bar { $0pub(crate) bar: () } }
344",
345 ); 343 );
346 check_assist_not_applicable( 344 check_assist_not_applicable(
347 fix_visibility, 345 fix_visibility,
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index 5918b9541..66fc11611 100644
--- a/crates/hir/src/semantics/source_to_def.rs
+++ b/crates/hir/src/semantics/source_to_def.rs
@@ -189,6 +189,10 @@ impl SourceToDefCtx<'_, '_> {
189 let def = self.type_alias_to_def(container.with_value(it))?; 189 let def = self.type_alias_to_def(container.with_value(it))?;
190 def.into() 190 def.into()
191 }, 191 },
192 ast::Variant(it) => {
193 let def = self.enum_variant_to_def(container.with_value(it))?;
194 VariantId::from(def).into()
195 },
192 _ => continue, 196 _ => continue,
193 } 197 }
194 }; 198 };
diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs
index d69ff2fc7..6539959c3 100644
--- a/crates/hir_def/src/adt.rs
+++ b/crates/hir_def/src/adt.rs
@@ -14,7 +14,7 @@ use tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree};
14use crate::{ 14use crate::{
15 body::{CfgExpander, LowerCtx}, 15 body::{CfgExpander, LowerCtx},
16 db::DefDatabase, 16 db::DefDatabase,
17 item_tree::{AttrOwner, Field, Fields, ItemTree, ModItem}, 17 item_tree::{AttrOwner, Field, Fields, ItemTree, ModItem, RawVisibilityId},
18 src::HasChildSource, 18 src::HasChildSource,
19 src::HasSource, 19 src::HasSource,
20 trace::Trace, 20 trace::Trace,
@@ -91,7 +91,7 @@ impl StructData {
91 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); 91 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone();
92 92
93 let strukt = &item_tree[loc.id.value]; 93 let strukt = &item_tree[loc.id.value];
94 let variant_data = lower_fields(&item_tree, &cfg_options, &strukt.fields); 94 let variant_data = lower_fields(&item_tree, &cfg_options, &strukt.fields, None);
95 Arc::new(StructData { 95 Arc::new(StructData {
96 name: strukt.name.clone(), 96 name: strukt.name.clone(),
97 variant_data: Arc::new(variant_data), 97 variant_data: Arc::new(variant_data),
@@ -105,7 +105,7 @@ impl StructData {
105 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); 105 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone();
106 106
107 let union = &item_tree[loc.id.value]; 107 let union = &item_tree[loc.id.value];
108 let variant_data = lower_fields(&item_tree, &cfg_options, &union.fields); 108 let variant_data = lower_fields(&item_tree, &cfg_options, &union.fields, None);
109 109
110 Arc::new(StructData { 110 Arc::new(StructData {
111 name: union.name.clone(), 111 name: union.name.clone(),
@@ -126,7 +126,8 @@ impl EnumData {
126 for var_id in enum_.variants.clone() { 126 for var_id in enum_.variants.clone() {
127 if item_tree.attrs(var_id.into()).is_cfg_enabled(&cfg_options) { 127 if item_tree.attrs(var_id.into()).is_cfg_enabled(&cfg_options) {
128 let var = &item_tree[var_id]; 128 let var = &item_tree[var_id];
129 let var_data = lower_fields(&item_tree, &cfg_options, &var.fields); 129 let var_data =
130 lower_fields(&item_tree, &cfg_options, &var.fields, Some(enum_.visibility));
130 131
131 variants.alloc(EnumVariantData { 132 variants.alloc(EnumVariantData {
132 name: var.name.clone(), 133 name: var.name.clone(),
@@ -296,13 +297,18 @@ fn lower_struct(
296 } 297 }
297} 298}
298 299
299fn lower_fields(item_tree: &ItemTree, cfg_options: &CfgOptions, fields: &Fields) -> VariantData { 300fn lower_fields(
301 item_tree: &ItemTree,
302 cfg_options: &CfgOptions,
303 fields: &Fields,
304 override_visibility: Option<RawVisibilityId>,
305) -> VariantData {
300 match fields { 306 match fields {
301 Fields::Record(flds) => { 307 Fields::Record(flds) => {
302 let mut arena = Arena::new(); 308 let mut arena = Arena::new();
303 for field_id in flds.clone() { 309 for field_id in flds.clone() {
304 if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) { 310 if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) {
305 arena.alloc(lower_field(item_tree, &item_tree[field_id])); 311 arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
306 } 312 }
307 } 313 }
308 VariantData::Record(arena) 314 VariantData::Record(arena)
@@ -311,7 +317,7 @@ fn lower_fields(item_tree: &ItemTree, cfg_options: &CfgOptions, fields: &Fields)
311 let mut arena = Arena::new(); 317 let mut arena = Arena::new();
312 for field_id in flds.clone() { 318 for field_id in flds.clone() {
313 if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) { 319 if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) {
314 arena.alloc(lower_field(item_tree, &item_tree[field_id])); 320 arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
315 } 321 }
316 } 322 }
317 VariantData::Tuple(arena) 323 VariantData::Tuple(arena)
@@ -320,10 +326,14 @@ fn lower_fields(item_tree: &ItemTree, cfg_options: &CfgOptions, fields: &Fields)
320 } 326 }
321} 327}
322 328
323fn lower_field(item_tree: &ItemTree, field: &Field) -> FieldData { 329fn lower_field(
330 item_tree: &ItemTree,
331 field: &Field,
332 override_visibility: Option<RawVisibilityId>,
333) -> FieldData {
324 FieldData { 334 FieldData {
325 name: field.name.clone(), 335 name: field.name.clone(),
326 type_ref: field.type_ref.clone(), 336 type_ref: field.type_ref.clone(),
327 visibility: item_tree[field.visibility].clone(), 337 visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(),
328 } 338 }
329} 339}
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml
index 0f3c85926..e9c62c6aa 100644
--- a/crates/hir_ty/Cargo.toml
+++ b/crates/hir_ty/Cargo.toml
@@ -17,9 +17,9 @@ ena = "0.14.0"
17log = "0.4.8" 17log = "0.4.8"
18rustc-hash = "1.1.0" 18rustc-hash = "1.1.0"
19scoped-tls = "1" 19scoped-tls = "1"
20chalk-solve = "0.32" 20chalk-solve = "0.33"
21chalk-ir = "0.32" 21chalk-ir = "0.33"
22chalk-recursive = "0.32" 22chalk-recursive = "0.33"
23 23
24stdx = { path = "../stdx", version = "0.0.0" } 24stdx = { path = "../stdx", version = "0.0.0" }
25hir_def = { path = "../hir_def", version = "0.0.0" } 25hir_def = { path = "../hir_def", version = "0.0.0" }
diff --git a/crates/ide/src/completion/complete_postfix/format_like.rs b/crates/ide/src/completion/complete_postfix/format_like.rs
index 81c33bf3a..50d1e5c81 100644
--- a/crates/ide/src/completion/complete_postfix/format_like.rs
+++ b/crates/ide/src/completion/complete_postfix/format_like.rs
@@ -25,6 +25,7 @@ static KINDS: &[(&str, &str)] = &[
25 ("fmt", "format!"), 25 ("fmt", "format!"),
26 ("panic", "panic!"), 26 ("panic", "panic!"),
27 ("println", "println!"), 27 ("println", "println!"),
28 ("eprintln", "eprintln!"),
28 ("logd", "log::debug!"), 29 ("logd", "log::debug!"),
29 ("logt", "log::trace!"), 30 ("logt", "log::trace!"),
30 ("logi", "log::info!"), 31 ("logi", "log::info!"),
@@ -259,6 +260,7 @@ mod tests {
259 fn test_into_suggestion() { 260 fn test_into_suggestion() {
260 let test_vector = &[ 261 let test_vector = &[
261 ("println!", "{}", r#"println!("{}", $1)"#), 262 ("println!", "{}", r#"println!("{}", $1)"#),
263 ("eprintln!", "{}", r#"eprintln!("{}", $1)"#),
262 ( 264 (
263 "log::info!", 265 "log::info!",
264 "{} {expr} {} {2 + 2}", 266 "{} {expr} {} {2 + 2}",
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 5db6e1311..686cee3a1 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -77,7 +77,9 @@ pub use crate::{
77 hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult}, 77 hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult},
78 inlay_hints::{InlayHint, InlayHintsConfig, InlayKind}, 78 inlay_hints::{InlayHint, InlayHintsConfig, InlayKind},
79 markup::Markup, 79 markup::Markup,
80 references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult}, 80 references::{
81 Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult, RenameError,
82 },
81 runnables::{Runnable, RunnableKind, TestId}, 83 runnables::{Runnable, RunnableKind, TestId},
82 syntax_highlighting::{ 84 syntax_highlighting::{
83 Highlight, HighlightModifier, HighlightModifiers, HighlightTag, HighlightedRange, 85 Highlight, HighlightModifier, HighlightModifiers, HighlightTag, HighlightedRange,
@@ -498,7 +500,7 @@ impl Analysis {
498 &self, 500 &self,
499 position: FilePosition, 501 position: FilePosition,
500 new_name: &str, 502 new_name: &str,
501 ) -> Cancelable<Option<RangeInfo<SourceChange>>> { 503 ) -> Cancelable<Result<RangeInfo<SourceChange>, RenameError>> {
502 self.with_db(|db| references::rename(db, position, new_name)) 504 self.with_db(|db| references::rename(db, position, new_name))
503 } 505 }
504 506
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index e0830eb4f..f65a05ea3 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -26,6 +26,7 @@ use syntax::{
26use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo}; 26use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo};
27 27
28pub(crate) use self::rename::rename; 28pub(crate) use self::rename::rename;
29pub use self::rename::RenameError;
29 30
30pub use ide_db::search::{Reference, ReferenceAccess, ReferenceKind}; 31pub use ide_db::search::{Reference, ReferenceAccess, ReferenceKind};
31 32
@@ -406,6 +407,23 @@ enum Foo {
406 } 407 }
407 408
408 #[test] 409 #[test]
410 fn test_find_all_refs_enum_var_field() {
411 check(
412 r#"
413enum Foo {
414 A,
415 B { field<|>: u8 },
416 C,
417}
418"#,
419 expect![[r#"
420 field RECORD_FIELD FileId(0) 26..35 26..31 Other
421
422 "#]],
423 );
424 }
425
426 #[test]
409 fn test_find_all_refs_two_modules() { 427 fn test_find_all_refs_two_modules() {
410 check( 428 check(
411 r#" 429 r#"
@@ -669,6 +687,76 @@ fn g() { f(); }
669 ); 687 );
670 } 688 }
671 689
690 #[test]
691 fn test_find_all_refs_struct_pat() {
692 check(
693 r#"
694struct S {
695 field<|>: u8,
696}
697
698fn f(s: S) {
699 match s {
700 S { field } => {}
701 }
702}
703"#,
704 expect![[r#"
705 field RECORD_FIELD FileId(0) 15..24 15..20 Other
706
707 FileId(0) 68..73 FieldShorthandForField Read
708 "#]],
709 );
710 }
711
712 #[test]
713 fn test_find_all_refs_enum_var_pat() {
714 check(
715 r#"
716enum En {
717 Variant {
718 field<|>: u8,
719 }
720}
721
722fn f(e: En) {
723 match e {
724 En::Variant { field } => {}
725 }
726}
727"#,
728 expect![[r#"
729 field RECORD_FIELD FileId(0) 32..41 32..37 Other
730
731 FileId(0) 102..107 FieldShorthandForField Read
732 "#]],
733 );
734 }
735
736 #[test]
737 fn test_find_all_refs_enum_var_privacy() {
738 check(
739 r#"
740mod m {
741 pub enum En {
742 Variant {
743 field<|>: u8,
744 }
745 }
746}
747
748fn f() -> m::En {
749 m::En::Variant { field: 0 }
750}
751"#,
752 expect![[r#"
753 field RECORD_FIELD FileId(0) 56..65 56..61 Other
754
755 FileId(0) 125..130 Other Read
756 "#]],
757 );
758 }
759
672 fn check(ra_fixture: &str, expect: Expect) { 760 fn check(ra_fixture: &str, expect: Expect) {
673 check_with_scope(ra_fixture, None, expect) 761 check_with_scope(ra_fixture, None, expect)
674 } 762 }
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index 8cbe1ae5a..f3b5cfc8c 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -6,11 +6,16 @@ use ide_db::{
6 defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass}, 6 defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass},
7 RootDatabase, 7 RootDatabase,
8}; 8};
9use std::convert::TryInto; 9
10use std::{
11 convert::TryInto,
12 error::Error,
13 fmt::{self, Display},
14};
10use syntax::{ 15use syntax::{
11 algo::find_node_at_offset, 16 algo::find_node_at_offset,
12 ast::{self, NameOwner}, 17 ast::{self, NameOwner},
13 lex_single_valid_syntax_kind, match_ast, AstNode, SyntaxKind, SyntaxNode, SyntaxToken, 18 lex_single_syntax_kind, match_ast, AstNode, SyntaxKind, SyntaxNode, SyntaxToken,
14}; 19};
15use test_utils::mark; 20use test_utils::mark;
16use text_edit::TextEdit; 21use text_edit::TextEdit;
@@ -20,17 +25,37 @@ use crate::{
20 SourceChange, SourceFileEdit, TextRange, TextSize, 25 SourceChange, SourceFileEdit, TextRange, TextSize,
21}; 26};
22 27
28#[derive(Debug)]
29pub struct RenameError(pub(crate) String);
30
31impl fmt::Display for RenameError {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 Display::fmt(&self.0, f)
34 }
35}
36
37impl Error for RenameError {}
38
23pub(crate) fn rename( 39pub(crate) fn rename(
24 db: &RootDatabase, 40 db: &RootDatabase,
25 position: FilePosition, 41 position: FilePosition,
26 new_name: &str, 42 new_name: &str,
27) -> Option<RangeInfo<SourceChange>> { 43) -> Result<RangeInfo<SourceChange>, RenameError> {
28 let sema = Semantics::new(db); 44 let sema = Semantics::new(db);
29 45
30 match lex_single_valid_syntax_kind(new_name)? { 46 match lex_single_syntax_kind(new_name) {
31 SyntaxKind::IDENT | SyntaxKind::UNDERSCORE => (), 47 Some(res) => match res {
32 SyntaxKind::SELF_KW => return rename_to_self(&sema, position), 48 (SyntaxKind::IDENT, _) => (),
33 _ => return None, 49 (SyntaxKind::UNDERSCORE, _) => (),
50 (SyntaxKind::SELF_KW, _) => return rename_to_self(&sema, position),
51 (_, Some(syntax_error)) => {
52 return Err(RenameError(format!("Invalid name `{}`: {}", new_name, syntax_error)))
53 }
54 (_, None) => {
55 return Err(RenameError(format!("Invalid name `{}`: not an identifier", new_name)))
56 }
57 },
58 None => return Err(RenameError(format!("Invalid name `{}`: not an identifier", new_name))),
34 } 59 }
35 60
36 let source_file = sema.parse(position.file_id); 61 let source_file = sema.parse(position.file_id);
@@ -103,7 +128,7 @@ fn rename_mod(
103 position: FilePosition, 128 position: FilePosition,
104 module: Module, 129 module: Module,
105 new_name: &str, 130 new_name: &str,
106) -> Option<RangeInfo<SourceChange>> { 131) -> Result<RangeInfo<SourceChange>, RenameError> {
107 let mut source_file_edits = Vec::new(); 132 let mut source_file_edits = Vec::new();
108 let mut file_system_edits = Vec::new(); 133 let mut file_system_edits = Vec::new();
109 134
@@ -125,7 +150,7 @@ fn rename_mod(
125 150
126 if let Some(src) = module.declaration_source(sema.db) { 151 if let Some(src) = module.declaration_source(sema.db) {
127 let file_id = src.file_id.original_file(sema.db); 152 let file_id = src.file_id.original_file(sema.db);
128 let name = src.value.name()?; 153 let name = src.value.name().unwrap();
129 let edit = SourceFileEdit { 154 let edit = SourceFileEdit {
130 file_id, 155 file_id,
131 edit: TextEdit::replace(name.syntax().text_range(), new_name.into()), 156 edit: TextEdit::replace(name.syntax().text_range(), new_name.into()),
@@ -133,35 +158,40 @@ fn rename_mod(
133 source_file_edits.push(edit); 158 source_file_edits.push(edit);
134 } 159 }
135 160
136 let RangeInfo { range, info: refs } = find_all_refs(sema, position, None)?; 161 let RangeInfo { range, info: refs } = find_all_refs(sema, position, None)
162 .ok_or_else(|| RenameError("No references found at position".to_string()))?;
137 let ref_edits = refs 163 let ref_edits = refs
138 .references 164 .references
139 .into_iter() 165 .into_iter()
140 .map(|reference| source_edit_from_reference(reference, new_name)); 166 .map(|reference| source_edit_from_reference(reference, new_name));
141 source_file_edits.extend(ref_edits); 167 source_file_edits.extend(ref_edits);
142 168
143 Some(RangeInfo::new(range, SourceChange::from_edits(source_file_edits, file_system_edits))) 169 Ok(RangeInfo::new(range, SourceChange::from_edits(source_file_edits, file_system_edits)))
144} 170}
145 171
146fn rename_to_self( 172fn rename_to_self(
147 sema: &Semantics<RootDatabase>, 173 sema: &Semantics<RootDatabase>,
148 position: FilePosition, 174 position: FilePosition,
149) -> Option<RangeInfo<SourceChange>> { 175) -> Result<RangeInfo<SourceChange>, RenameError> {
150 let source_file = sema.parse(position.file_id); 176 let source_file = sema.parse(position.file_id);
151 let syn = source_file.syntax(); 177 let syn = source_file.syntax();
152 178
153 let fn_def = find_node_at_offset::<ast::Fn>(syn, position.offset)?; 179 let fn_def = find_node_at_offset::<ast::Fn>(syn, position.offset)
154 let params = fn_def.param_list()?; 180 .ok_or_else(|| RenameError("No surrounding method declaration found".to_string()))?;
181 let params =
182 fn_def.param_list().ok_or_else(|| RenameError("Method has no parameters".to_string()))?;
155 if params.self_param().is_some() { 183 if params.self_param().is_some() {
156 return None; // method already has self param 184 return Err(RenameError("Method already has a self parameter".to_string()));
157 } 185 }
158 let first_param = params.params().next()?; 186 let first_param =
187 params.params().next().ok_or_else(|| RenameError("Method has no parameters".into()))?;
159 let mutable = match first_param.ty() { 188 let mutable = match first_param.ty() {
160 Some(ast::Type::RefType(rt)) => rt.mut_token().is_some(), 189 Some(ast::Type::RefType(rt)) => rt.mut_token().is_some(),
161 _ => return None, // not renaming other types 190 _ => return Err(RenameError("Not renaming other types".to_string())),
162 }; 191 };
163 192
164 let RangeInfo { range, info: refs } = find_all_refs(sema, position, None)?; 193 let RangeInfo { range, info: refs } = find_all_refs(sema, position, None)
194 .ok_or_else(|| RenameError("No reference found at position".to_string()))?;
165 195
166 let param_range = first_param.syntax().text_range(); 196 let param_range = first_param.syntax().text_range();
167 let (param_ref, usages): (Vec<Reference>, Vec<Reference>) = refs 197 let (param_ref, usages): (Vec<Reference>, Vec<Reference>) = refs
@@ -169,7 +199,7 @@ fn rename_to_self(
169 .partition(|reference| param_range.intersect(reference.file_range.range).is_some()); 199 .partition(|reference| param_range.intersect(reference.file_range.range).is_some());
170 200
171 if param_ref.is_empty() { 201 if param_ref.is_empty() {
172 return None; 202 return Err(RenameError("Parameter to rename not found".to_string()));
173 } 203 }
174 204
175 let mut edits = usages 205 let mut edits = usages
@@ -185,7 +215,7 @@ fn rename_to_self(
185 ), 215 ),
186 }); 216 });
187 217
188 Some(RangeInfo::new(range, SourceChange::from(edits))) 218 Ok(RangeInfo::new(range, SourceChange::from(edits)))
189} 219}
190 220
191fn text_edit_from_self_param( 221fn text_edit_from_self_param(
@@ -216,12 +246,13 @@ fn rename_self_to_param(
216 position: FilePosition, 246 position: FilePosition,
217 self_token: SyntaxToken, 247 self_token: SyntaxToken,
218 new_name: &str, 248 new_name: &str,
219) -> Option<RangeInfo<SourceChange>> { 249) -> Result<RangeInfo<SourceChange>, RenameError> {
220 let source_file = sema.parse(position.file_id); 250 let source_file = sema.parse(position.file_id);
221 let syn = source_file.syntax(); 251 let syn = source_file.syntax();
222 252
223 let text = sema.db.file_text(position.file_id); 253 let text = sema.db.file_text(position.file_id);
224 let fn_def = find_node_at_offset::<ast::Fn>(syn, position.offset)?; 254 let fn_def = find_node_at_offset::<ast::Fn>(syn, position.offset)
255 .ok_or_else(|| RenameError("No surrounding method declaration found".to_string()))?;
225 let search_range = fn_def.syntax().text_range(); 256 let search_range = fn_def.syntax().text_range();
226 257
227 let mut edits: Vec<SourceFileEdit> = vec![]; 258 let mut edits: Vec<SourceFileEdit> = vec![];
@@ -235,7 +266,8 @@ fn rename_self_to_param(
235 syn.token_at_offset(offset).find(|t| t.kind() == SyntaxKind::SELF_KW) 266 syn.token_at_offset(offset).find(|t| t.kind() == SyntaxKind::SELF_KW)
236 { 267 {
237 let edit = if let Some(ref self_param) = ast::SelfParam::cast(usage.parent()) { 268 let edit = if let Some(ref self_param) = ast::SelfParam::cast(usage.parent()) {
238 text_edit_from_self_param(syn, self_param, new_name)? 269 text_edit_from_self_param(syn, self_param, new_name)
270 .ok_or_else(|| RenameError("No target type found".to_string()))?
239 } else { 271 } else {
240 TextEdit::replace(usage.text_range(), String::from(new_name)) 272 TextEdit::replace(usage.text_range(), String::from(new_name))
241 }; 273 };
@@ -246,15 +278,18 @@ fn rename_self_to_param(
246 let range = ast::SelfParam::cast(self_token.parent()) 278 let range = ast::SelfParam::cast(self_token.parent())
247 .map_or(self_token.text_range(), |p| p.syntax().text_range()); 279 .map_or(self_token.text_range(), |p| p.syntax().text_range());
248 280
249 Some(RangeInfo::new(range, SourceChange::from(edits))) 281 Ok(RangeInfo::new(range, SourceChange::from(edits)))
250} 282}
251 283
252fn rename_reference( 284fn rename_reference(
253 sema: &Semantics<RootDatabase>, 285 sema: &Semantics<RootDatabase>,
254 position: FilePosition, 286 position: FilePosition,
255 new_name: &str, 287 new_name: &str,
256) -> Option<RangeInfo<SourceChange>> { 288) -> Result<RangeInfo<SourceChange>, RenameError> {
257 let RangeInfo { range, info: refs } = find_all_refs(sema, position, None)?; 289 let RangeInfo { range, info: refs } = match find_all_refs(sema, position, None) {
290 Some(range_info) => range_info,
291 None => return Err(RenameError("No references found at position".to_string())),
292 };
258 293
259 let edit = refs 294 let edit = refs
260 .into_iter() 295 .into_iter()
@@ -262,10 +297,10 @@ fn rename_reference(
262 .collect::<Vec<_>>(); 297 .collect::<Vec<_>>();
263 298
264 if edit.is_empty() { 299 if edit.is_empty() {
265 return None; 300 return Err(RenameError("No references found at position".to_string()));
266 } 301 }
267 302
268 Some(RangeInfo::new(range, SourceChange::from(edit))) 303 Ok(RangeInfo::new(range, SourceChange::from(edit)))
269} 304}
270 305
271#[cfg(test)] 306#[cfg(test)]
@@ -280,25 +315,45 @@ mod tests {
280 fn check(new_name: &str, ra_fixture_before: &str, ra_fixture_after: &str) { 315 fn check(new_name: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
281 let ra_fixture_after = &trim_indent(ra_fixture_after); 316 let ra_fixture_after = &trim_indent(ra_fixture_after);
282 let (analysis, position) = fixture::position(ra_fixture_before); 317 let (analysis, position) = fixture::position(ra_fixture_before);
283 let source_change = analysis.rename(position, new_name).unwrap(); 318 let rename_result = analysis
284 let mut text_edit_builder = TextEdit::builder(); 319 .rename(position, new_name)
285 let mut file_id: Option<FileId> = None; 320 .unwrap_or_else(|err| panic!("Rename to '{}' was cancelled: {}", new_name, err));
286 if let Some(change) = source_change { 321 match rename_result {
287 for edit in change.info.source_file_edits { 322 Ok(source_change) => {
288 file_id = Some(edit.file_id); 323 let mut text_edit_builder = TextEdit::builder();
289 for indel in edit.edit.into_iter() { 324 let mut file_id: Option<FileId> = None;
290 text_edit_builder.replace(indel.delete, indel.insert); 325 for edit in source_change.info.source_file_edits {
326 file_id = Some(edit.file_id);
327 for indel in edit.edit.into_iter() {
328 text_edit_builder.replace(indel.delete, indel.insert);
329 }
291 } 330 }
331 let mut result = analysis.file_text(file_id.unwrap()).unwrap().to_string();
332 text_edit_builder.finish().apply(&mut result);
333 assert_eq_text!(ra_fixture_after, &*result);
292 } 334 }
293 } 335 Err(err) => {
294 let mut result = analysis.file_text(file_id.unwrap()).unwrap().to_string(); 336 if ra_fixture_after.starts_with("error:") {
295 text_edit_builder.finish().apply(&mut result); 337 let error_message = ra_fixture_after
296 assert_eq_text!(ra_fixture_after, &*result); 338 .chars()
339 .into_iter()
340 .skip("error:".len())
341 .collect::<String>();
342 assert_eq!(error_message.trim(), err.to_string());
343 return;
344 } else {
345 panic!("Rename to '{}' failed unexpectedly: {}", new_name, err)
346 }
347 }
348 };
297 } 349 }
298 350
299 fn check_expect(new_name: &str, ra_fixture: &str, expect: Expect) { 351 fn check_expect(new_name: &str, ra_fixture: &str, expect: Expect) {
300 let (analysis, position) = fixture::position(ra_fixture); 352 let (analysis, position) = fixture::position(ra_fixture);
301 let source_change = analysis.rename(position, new_name).unwrap().unwrap(); 353 let source_change = analysis
354 .rename(position, new_name)
355 .unwrap()
356 .expect("Expect returned RangeInfo to be Some, but was None");
302 expect.assert_debug_eq(&source_change) 357 expect.assert_debug_eq(&source_change)
303 } 358 }
304 359
@@ -313,11 +368,30 @@ mod tests {
313 } 368 }
314 369
315 #[test] 370 #[test]
316 fn test_rename_to_invalid_identifier() { 371 fn test_rename_to_invalid_identifier1() {
317 let (analysis, position) = fixture::position(r#"fn main() { let i<|> = 1; }"#); 372 check(
318 let new_name = "invalid!"; 373 "invalid!",
319 let source_change = analysis.rename(position, new_name).unwrap(); 374 r#"fn main() { let i<|> = 1; }"#,
320 assert!(source_change.is_none()); 375 "error: Invalid name `invalid!`: not an identifier",
376 );
377 }
378
379 #[test]
380 fn test_rename_to_invalid_identifier2() {
381 check(
382 "multiple tokens",
383 r#"fn main() { let i<|> = 1; }"#,
384 "error: Invalid name `multiple tokens`: not an identifier",
385 );
386 }
387
388 #[test]
389 fn test_rename_to_invalid_identifier3() {
390 check(
391 "let",
392 r#"fn main() { let i<|> = 1; }"#,
393 "error: Invalid name `let`: not an identifier",
394 );
321 } 395 }
322 396
323 #[test] 397 #[test]
@@ -350,6 +424,15 @@ fn main() {
350 } 424 }
351 425
352 #[test] 426 #[test]
427 fn test_rename_unresolved_reference() {
428 check(
429 "new_name",
430 r#"fn main() { let _ = unresolved_ref<|>; }"#,
431 "error: No references found at position",
432 );
433 }
434
435 #[test]
353 fn test_rename_for_macro_args() { 436 fn test_rename_for_macro_args() {
354 check( 437 check(
355 "b", 438 "b",
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index edab1d644..8e3dcd99c 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -12,8 +12,9 @@ use once_cell::unsync::Lazy;
12use rustc_hash::FxHashMap; 12use rustc_hash::FxHashMap;
13use syntax::{ast, match_ast, AstNode, TextRange, TextSize}; 13use syntax::{ast, match_ast, AstNode, TextRange, TextSize};
14 14
15use crate::defs::NameClass;
15use crate::{ 16use crate::{
16 defs::{classify_name_ref, Definition, NameRefClass}, 17 defs::{classify_name, classify_name_ref, Definition, NameRefClass},
17 RootDatabase, 18 RootDatabase,
18}; 19};
19 20
@@ -226,9 +227,9 @@ impl<'a> FindUsages<'a> {
226 227
227 let search_scope = { 228 let search_scope = {
228 let base = self.def.search_scope(sema.db); 229 let base = self.def.search_scope(sema.db);
229 match self.scope { 230 match &self.scope {
230 None => base, 231 None => base,
231 Some(scope) => base.intersection(&scope), 232 Some(scope) => base.intersection(scope),
232 } 233 }
233 }; 234 };
234 235
@@ -251,54 +252,83 @@ impl<'a> FindUsages<'a> {
251 continue; 252 continue;
252 } 253 }
253 254
254 let name_ref: ast::NameRef = 255 match sema.find_node_at_offset_with_descend(&tree, offset) {
255 match sema.find_node_at_offset_with_descend(&tree, offset) { 256 Some(name_ref) => {
256 Some(it) => it, 257 if self.found_name_ref(&name_ref, sink) {
257 None => continue,
258 };
259
260 match classify_name_ref(&sema, &name_ref) {
261 Some(NameRefClass::Definition(def)) if &def == self.def => {
262 let kind = if is_record_lit_name_ref(&name_ref)
263 || is_call_expr_name_ref(&name_ref)
264 {
265 ReferenceKind::StructLiteral
266 } else {
267 ReferenceKind::Other
268 };
269
270 let reference = Reference {
271 file_range: sema.original_range(name_ref.syntax()),
272 kind,
273 access: reference_access(&def, &name_ref),
274 };
275 if sink(reference) {
276 return; 258 return;
277 } 259 }
278 } 260 }
279 Some(NameRefClass::FieldShorthand { local, field }) => { 261 None => match sema.find_node_at_offset_with_descend(&tree, offset) {
280 let reference = match self.def { 262 Some(name) => {
281 Definition::Field(_) if &field == self.def => Reference { 263 if self.found_name(&name, sink) {
282 file_range: self.sema.original_range(name_ref.syntax()), 264 return;
283 kind: ReferenceKind::FieldShorthandForField, 265 }
284 access: reference_access(&field, &name_ref),
285 },
286 Definition::Local(l) if &local == l => Reference {
287 file_range: self.sema.original_range(name_ref.syntax()),
288 kind: ReferenceKind::FieldShorthandForLocal,
289 access: reference_access(&Definition::Local(local), &name_ref),
290 },
291 _ => continue, // not a usage
292 };
293 if sink(reference) {
294 return;
295 } 266 }
296 } 267 None => {}
297 _ => {} // not a usage 268 },
298 } 269 }
299 } 270 }
300 } 271 }
301 } 272 }
273
274 fn found_name_ref(
275 &self,
276 name_ref: &ast::NameRef,
277 sink: &mut dyn FnMut(Reference) -> bool,
278 ) -> bool {
279 match classify_name_ref(self.sema, &name_ref) {
280 Some(NameRefClass::Definition(def)) if &def == self.def => {
281 let kind = if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref)
282 {
283 ReferenceKind::StructLiteral
284 } else {
285 ReferenceKind::Other
286 };
287
288 let reference = Reference {
289 file_range: self.sema.original_range(name_ref.syntax()),
290 kind,
291 access: reference_access(&def, &name_ref),
292 };
293 sink(reference)
294 }
295 Some(NameRefClass::FieldShorthand { local, field }) => {
296 let reference = match self.def {
297 Definition::Field(_) if &field == self.def => Reference {
298 file_range: self.sema.original_range(name_ref.syntax()),
299 kind: ReferenceKind::FieldShorthandForField,
300 access: reference_access(&field, &name_ref),
301 },
302 Definition::Local(l) if &local == l => Reference {
303 file_range: self.sema.original_range(name_ref.syntax()),
304 kind: ReferenceKind::FieldShorthandForLocal,
305 access: reference_access(&Definition::Local(local), &name_ref),
306 },
307 _ => return false, // not a usage
308 };
309 sink(reference)
310 }
311 _ => false, // not a usage
312 }
313 }
314
315 fn found_name(&self, name: &ast::Name, sink: &mut dyn FnMut(Reference) -> bool) -> bool {
316 match classify_name(self.sema, name) {
317 Some(NameClass::FieldShorthand { local: _, field }) => {
318 let reference = match self.def {
319 Definition::Field(_) if &field == self.def => Reference {
320 file_range: self.sema.original_range(name.syntax()),
321 kind: ReferenceKind::FieldShorthandForField,
322 // FIXME: mutable patterns should have `Write` access
323 access: Some(ReferenceAccess::Read),
324 },
325 _ => return false, // not a usage
326 };
327 sink(reference)
328 }
329 _ => false, // not a usage
330 }
331 }
302} 332}
303 333
304fn reference_access(def: &Definition, name_ref: &ast::NameRef) -> Option<ReferenceAccess> { 334fn reference_access(def: &Definition, name_ref: &ast::NameRef) -> Option<ReferenceAccess> {
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 cb4b3bdb0..55d6330cc 100644
--- a/crates/proc_macro_srv/src/proc_macro/bridge/client.rs
+++ b/crates/proc_macro_srv/src/proc_macro/bridge/client.rs
@@ -160,6 +160,7 @@ macro_rules! define_handles {
160} 160}
161define_handles! { 161define_handles! {
162 'owned: 162 'owned:
163 FreeFunctions,
163 TokenStream, 164 TokenStream,
164 TokenStreamBuilder, 165 TokenStreamBuilder,
165 TokenStreamIter, 166 TokenStreamIter,
diff --git a/crates/proc_macro_srv/src/proc_macro/bridge/mod.rs b/crates/proc_macro_srv/src/proc_macro/bridge/mod.rs
index aeb05aad4..b97886eb9 100644
--- a/crates/proc_macro_srv/src/proc_macro/bridge/mod.rs
+++ b/crates/proc_macro_srv/src/proc_macro/bridge/mod.rs
@@ -57,6 +57,10 @@ use std::thread;
57macro_rules! with_api { 57macro_rules! with_api {
58 ($S:ident, $self:ident, $m:ident) => { 58 ($S:ident, $self:ident, $m:ident) => {
59 $m! { 59 $m! {
60 FreeFunctions {
61 fn drop($self: $S::FreeFunctions);
62 fn track_env_var(var: &str, value: Option<&str>);
63 },
60 TokenStream { 64 TokenStream {
61 fn drop($self: $S::TokenStream); 65 fn drop($self: $S::TokenStream);
62 fn clone($self: &$S::TokenStream) -> $S::TokenStream; 66 fn clone($self: &$S::TokenStream) -> $S::TokenStream;
diff --git a/crates/proc_macro_srv/src/proc_macro/bridge/server.rs b/crates/proc_macro_srv/src/proc_macro/bridge/server.rs
index 45d41ac02..3acb239af 100644
--- a/crates/proc_macro_srv/src/proc_macro/bridge/server.rs
+++ b/crates/proc_macro_srv/src/proc_macro/bridge/server.rs
@@ -11,6 +11,8 @@ use super::client::HandleStore;
11/// Declare an associated item of one of the traits below, optionally 11/// Declare an associated item of one of the traits below, optionally
12/// adjusting it (i.e., adding bounds to types and default bodies to methods). 12/// adjusting it (i.e., adding bounds to types and default bodies to methods).
13macro_rules! associated_item { 13macro_rules! associated_item {
14 (type FreeFunctions) =>
15 (type FreeFunctions: 'static;);
14 (type TokenStream) => 16 (type TokenStream) =>
15 (type TokenStream: 'static + Clone;); 17 (type TokenStream: 'static + Clone;);
16 (type TokenStreamBuilder) => 18 (type TokenStreamBuilder) =>
diff --git a/crates/proc_macro_srv/src/proc_macro/mod.rs b/crates/proc_macro_srv/src/proc_macro/mod.rs
index ee0dc9722..fc6e7344f 100644
--- a/crates/proc_macro_srv/src/proc_macro/mod.rs
+++ b/crates/proc_macro_srv/src/proc_macro/mod.rs
@@ -924,3 +924,25 @@ impl fmt::Debug for Literal {
924 self.0.fmt(f) 924 self.0.fmt(f)
925 } 925 }
926} 926}
927
928pub mod tracked_env {
929 use std::env::{self, VarError};
930 use std::ffi::OsStr;
931
932 /// Retrieve an environment variable and add it to build dependency info.
933 /// Build system executing the compiler will know that the variable was accessed during
934 /// compilation, and will be able to rerun the build when the value of that variable changes.
935 /// Besides the dependency tracking this function should be equivalent to `env::var` from the
936 /// standard library, except that the argument must be UTF-8.
937 pub fn var<K: AsRef<OsStr> + AsRef<str>>(key: K) -> Result<String, VarError> {
938 use std::ops::Deref;
939
940 let key: &str = key.as_ref();
941 let value = env::var(key);
942 super::bridge::client::FreeFunctions::track_env_var(
943 key,
944 value.as_ref().map(|t| t.deref()).ok(),
945 );
946 value
947 }
948}
diff --git a/crates/proc_macro_srv/src/rustc_server.rs b/crates/proc_macro_srv/src/rustc_server.rs
index 7d1695c86..c5fe3591e 100644
--- a/crates/proc_macro_srv/src/rustc_server.rs
+++ b/crates/proc_macro_srv/src/rustc_server.rs
@@ -242,6 +242,8 @@ impl TokenStreamBuilder {
242 } 242 }
243} 243}
244 244
245pub struct FreeFunctions;
246
245#[derive(Clone)] 247#[derive(Clone)]
246pub struct TokenStreamIter { 248pub struct TokenStreamIter {
247 trees: IntoIter<TokenTree>, 249 trees: IntoIter<TokenTree>,
@@ -254,6 +256,7 @@ pub struct Rustc {
254} 256}
255 257
256impl server::Types for Rustc { 258impl server::Types for Rustc {
259 type FreeFunctions = FreeFunctions;
257 type TokenStream = TokenStream; 260 type TokenStream = TokenStream;
258 type TokenStreamBuilder = TokenStreamBuilder; 261 type TokenStreamBuilder = TokenStreamBuilder;
259 type TokenStreamIter = TokenStreamIter; 262 type TokenStreamIter = TokenStreamIter;
@@ -267,6 +270,13 @@ impl server::Types for Rustc {
267 type MultiSpan = Vec<Span>; 270 type MultiSpan = Vec<Span>;
268} 271}
269 272
273impl server::FreeFunctions for Rustc {
274 fn track_env_var(&mut self, _var: &str, _value: Option<&str>) {
275 // FIXME: track env var accesses
276 // https://github.com/rust-lang/rust/pull/71858
277 }
278}
279
270impl server::TokenStream for Rustc { 280impl server::TokenStream for Rustc {
271 fn new(&mut self) -> Self::TokenStream { 281 fn new(&mut self) -> Self::TokenStream {
272 Self::TokenStream::new() 282 Self::TokenStream::new()
diff --git a/crates/profile/Cargo.toml b/crates/profile/Cargo.toml
index 261172d61..c5dfdff32 100644
--- a/crates/profile/Cargo.toml
+++ b/crates/profile/Cargo.toml
@@ -11,7 +11,7 @@ doctest = false
11 11
12[dependencies] 12[dependencies]
13once_cell = "1.3.1" 13once_cell = "1.3.1"
14cfg-if = "0.1.10" 14cfg-if = "1"
15libc = "0.2.73" 15libc = "0.2.73"
16backtrace = { version = "0.3.44", optional = true } 16backtrace = { version = "0.3.44", optional = true }
17 17
diff --git a/crates/project_model/src/sysroot.rs b/crates/project_model/src/sysroot.rs
index 871808d89..e529e07b0 100644
--- a/crates/project_model/src/sysroot.rs
+++ b/crates/project_model/src/sysroot.rs
@@ -90,9 +90,15 @@ impl Sysroot {
90 } 90 }
91 91
92 if sysroot.by_name("core").is_none() { 92 if sysroot.by_name("core").is_none() {
93 let var_note = if env::var_os("RUST_SRC_PATH").is_some() {
94 " (`RUST_SRC_PATH` might be incorrect, try unsetting it)"
95 } else {
96 ""
97 };
93 anyhow::bail!( 98 anyhow::bail!(
94 "could not find libcore in sysroot path `{}`", 99 "could not find libcore in sysroot path `{}`{}",
95 sysroot_src_dir.as_ref().display() 100 sysroot_src_dir.as_ref().display(),
101 var_note,
96 ); 102 );
97 } 103 }
98 104
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index ba73abcac..215be850f 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -646,14 +646,9 @@ pub(crate) fn handle_prepare_rename(
646 let _p = profile::span("handle_prepare_rename"); 646 let _p = profile::span("handle_prepare_rename");
647 let position = from_proto::file_position(&snap, params)?; 647 let position = from_proto::file_position(&snap, params)?;
648 648
649 let optional_change = snap.analysis.rename(position, "dummy")?; 649 let change = snap.analysis.rename(position, "dummy")??;
650 let range = match optional_change {
651 None => return Ok(None),
652 Some(it) => it.range,
653 };
654
655 let line_index = snap.analysis.file_line_index(position.file_id)?; 650 let line_index = snap.analysis.file_line_index(position.file_id)?;
656 let range = to_proto::range(&line_index, range); 651 let range = to_proto::range(&line_index, change.range);
657 Ok(Some(PrepareRenameResponse::Range(range))) 652 Ok(Some(PrepareRenameResponse::Range(range)))
658} 653}
659 654
@@ -672,12 +667,8 @@ pub(crate) fn handle_rename(
672 .into()); 667 .into());
673 } 668 }
674 669
675 let optional_change = snap.analysis.rename(position, &*params.new_name)?; 670 let change = snap.analysis.rename(position, &*params.new_name)??;
676 let source_change = match optional_change { 671 let workspace_edit = to_proto::workspace_edit(&snap, change.info)?;
677 None => return Ok(None),
678 Some(it) => it.info,
679 };
680 let workspace_edit = to_proto::workspace_edit(&snap, source_change)?;
681 Ok(Some(workspace_edit)) 672 Ok(Some(workspace_edit))
682} 673}
683 674
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index 0b15f10e9..547fe9f47 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -13,7 +13,7 @@ doctest = false
13[dependencies] 13[dependencies]
14itertools = "0.9.0" 14itertools = "0.9.0"
15rowan = "0.10.0" 15rowan = "0.10.0"
16rustc_lexer = { version = "681.0.0", package = "rustc-ap-rustc_lexer" } 16rustc_lexer = { version = "682.0.0", package = "rustc-ap-rustc_lexer" }
17rustc-hash = "1.1.0" 17rustc-hash = "1.1.0"
18arrayvec = "0.5.1" 18arrayvec = "0.5.1"
19once_cell = "1.3.1" 19once_cell = "1.3.1"