diff options
Diffstat (limited to 'crates')
23 files changed, 319 insertions, 208 deletions
diff --git a/crates/ra_assists/src/assists/add_missing_impl_members.rs b/crates/ra_assists/src/assists/add_missing_impl_members.rs index 23da1e65f..682455bce 100644 --- a/crates/ra_assists/src/assists/add_missing_impl_members.rs +++ b/crates/ra_assists/src/assists/add_missing_impl_members.rs | |||
@@ -100,12 +100,11 @@ fn strip_docstring(item: ast::ImplItem) -> ast::ImplItem { | |||
100 | } | 100 | } |
101 | 101 | ||
102 | fn add_body(fn_def: ast::FnDef) -> ast::FnDef { | 102 | fn add_body(fn_def: ast::FnDef) -> ast::FnDef { |
103 | let mut ast_editor = AstEditor::new(fn_def.clone()); | ||
104 | if fn_def.body().is_none() { | 103 | if fn_def.body().is_none() { |
105 | let body = make::block_from_expr(make::expr_unimplemented()); | 104 | fn_def.with_body(make::block_from_expr(make::expr_unimplemented())) |
106 | ast_editor.set_body(&body); | 105 | } else { |
106 | fn_def | ||
107 | } | 107 | } |
108 | ast_editor.ast().to_owned() | ||
109 | } | 108 | } |
110 | 109 | ||
111 | /// Given an `ast::ImplBlock`, resolves the target trait (the one being | 110 | /// Given an `ast::ImplBlock`, resolves the target trait (the one being |
@@ -332,5 +331,4 @@ impl Foo for S { | |||
332 | }", | 331 | }", |
333 | ) | 332 | ) |
334 | } | 333 | } |
335 | |||
336 | } | 334 | } |
diff --git a/crates/ra_assists/src/assists/auto_import.rs b/crates/ra_assists/src/assists/auto_import.rs index 43c14ad23..419e93330 100644 --- a/crates/ra_assists/src/assists/auto_import.rs +++ b/crates/ra_assists/src/assists/auto_import.rs | |||
@@ -448,7 +448,6 @@ fn make_assist_add_in_tree_list( | |||
448 | fmt_segments_raw(target, &mut buf); | 448 | fmt_segments_raw(target, &mut buf); |
449 | edit.insert(offset, buf); | 449 | edit.insert(offset, buf); |
450 | } else { | 450 | } else { |
451 | |||
452 | } | 451 | } |
453 | } | 452 | } |
454 | 453 | ||
diff --git a/crates/ra_assists/src/ast_editor.rs b/crates/ra_assists/src/ast_editor.rs index 2a685f26e..72c8c478a 100644 --- a/crates/ra_assists/src/ast_editor.rs +++ b/crates/ra_assists/src/ast_editor.rs | |||
@@ -6,7 +6,7 @@ use rustc_hash::FxHashMap; | |||
6 | use ra_fmt::leading_indent; | 6 | use ra_fmt::leading_indent; |
7 | use ra_syntax::{ | 7 | use ra_syntax::{ |
8 | algo, | 8 | algo, |
9 | ast::{self, TypeBoundsOwner}, | 9 | ast::{self, make::tokens, TypeBoundsOwner}, |
10 | AstNode, Direction, InsertPosition, SyntaxElement, | 10 | AstNode, Direction, InsertPosition, SyntaxElement, |
11 | SyntaxKind::*, | 11 | SyntaxKind::*, |
12 | T, | 12 | T, |
@@ -229,26 +229,6 @@ impl AstEditor<ast::ImplItem> { | |||
229 | } | 229 | } |
230 | } | 230 | } |
231 | 231 | ||
232 | impl AstEditor<ast::FnDef> { | ||
233 | pub fn set_body(&mut self, body: &ast::Block) { | ||
234 | let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new(); | ||
235 | let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.ast().body() { | ||
236 | old_body.syntax().clone().into() | ||
237 | } else if let Some(semi) = self.ast().semicolon_token() { | ||
238 | to_insert.push(tokens::single_space().into()); | ||
239 | semi.into() | ||
240 | } else { | ||
241 | to_insert.push(tokens::single_space().into()); | ||
242 | to_insert.push(body.syntax().clone().into()); | ||
243 | self.ast = self.insert_children(InsertPosition::Last, to_insert.into_iter()); | ||
244 | return; | ||
245 | }; | ||
246 | to_insert.push(body.syntax().clone().into()); | ||
247 | let replace_range = RangeInclusive::new(old_body_or_semi.clone(), old_body_or_semi); | ||
248 | self.ast = self.replace_children(replace_range, to_insert.into_iter()) | ||
249 | } | ||
250 | } | ||
251 | |||
252 | impl AstEditor<ast::TypeParam> { | 232 | impl AstEditor<ast::TypeParam> { |
253 | pub fn remove_bounds(&mut self) -> &mut Self { | 233 | pub fn remove_bounds(&mut self) -> &mut Self { |
254 | let colon = match self.ast.colon_token() { | 234 | let colon = match self.ast.colon_token() { |
@@ -263,53 +243,3 @@ impl AstEditor<ast::TypeParam> { | |||
263 | self | 243 | self |
264 | } | 244 | } |
265 | } | 245 | } |
266 | |||
267 | mod tokens { | ||
268 | use once_cell::sync::Lazy; | ||
269 | use ra_syntax::{AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken, T}; | ||
270 | |||
271 | static SOURCE_FILE: Lazy<Parse<SourceFile>> = Lazy::new(|| SourceFile::parse(",\n; ;")); | ||
272 | |||
273 | pub(crate) fn comma() -> SyntaxToken { | ||
274 | SOURCE_FILE | ||
275 | .tree() | ||
276 | .syntax() | ||
277 | .descendants_with_tokens() | ||
278 | .filter_map(|it| it.into_token()) | ||
279 | .find(|it| it.kind() == T![,]) | ||
280 | .unwrap() | ||
281 | } | ||
282 | |||
283 | pub(crate) fn single_space() -> SyntaxToken { | ||
284 | SOURCE_FILE | ||
285 | .tree() | ||
286 | .syntax() | ||
287 | .descendants_with_tokens() | ||
288 | .filter_map(|it| it.into_token()) | ||
289 | .find(|it| it.kind() == WHITESPACE && it.text().as_str() == " ") | ||
290 | .unwrap() | ||
291 | } | ||
292 | |||
293 | #[allow(unused)] | ||
294 | pub(crate) fn single_newline() -> SyntaxToken { | ||
295 | SOURCE_FILE | ||
296 | .tree() | ||
297 | .syntax() | ||
298 | .descendants_with_tokens() | ||
299 | .filter_map(|it| it.into_token()) | ||
300 | .find(|it| it.kind() == WHITESPACE && it.text().as_str() == "\n") | ||
301 | .unwrap() | ||
302 | } | ||
303 | |||
304 | pub(crate) struct WsBuilder(SourceFile); | ||
305 | |||
306 | impl WsBuilder { | ||
307 | pub(crate) fn new(text: &str) -> WsBuilder { | ||
308 | WsBuilder(SourceFile::parse(text).ok().unwrap()) | ||
309 | } | ||
310 | pub(crate) fn ws(&self) -> SyntaxToken { | ||
311 | self.0.syntax().first_child_or_token().unwrap().into_token().unwrap() | ||
312 | } | ||
313 | } | ||
314 | |||
315 | } | ||
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 897af2b02..3ca3320f7 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -340,5 +340,4 @@ mod tests { | |||
340 | assert_eq!(assists.next().expect("expected assist").0.label, "introduce variable"); | 340 | assert_eq!(assists.next().expect("expected assist").0.label, "introduce variable"); |
341 | assert_eq!(assists.next().expect("expected assist").0.label, "replace with match"); | 341 | assert_eq!(assists.next().expect("expected assist").0.label, "replace with match"); |
342 | } | 342 | } |
343 | |||
344 | } | 343 | } |
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 20413cb3d..fd7afcbb6 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -339,10 +339,14 @@ pub struct Struct { | |||
339 | } | 339 | } |
340 | 340 | ||
341 | impl Struct { | 341 | impl Struct { |
342 | pub fn module(self, db: &impl HirDatabase) -> Module { | 342 | pub fn module(self, db: &impl DefDatabase) -> Module { |
343 | self.id.module(db) | 343 | self.id.module(db) |
344 | } | 344 | } |
345 | 345 | ||
346 | pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { | ||
347 | self.module(db).krate(db) | ||
348 | } | ||
349 | |||
346 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { | 350 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { |
347 | db.struct_data(self).name.clone() | 351 | db.struct_data(self).name.clone() |
348 | } | 352 | } |
@@ -423,10 +427,14 @@ pub struct Enum { | |||
423 | } | 427 | } |
424 | 428 | ||
425 | impl Enum { | 429 | impl Enum { |
426 | pub fn module(self, db: &impl HirDatabase) -> Module { | 430 | pub fn module(self, db: &impl DefDatabase) -> Module { |
427 | self.id.module(db) | 431 | self.id.module(db) |
428 | } | 432 | } |
429 | 433 | ||
434 | pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { | ||
435 | self.module(db).krate(db) | ||
436 | } | ||
437 | |||
430 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { | 438 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { |
431 | db.enum_data(self).name.clone() | 439 | db.enum_data(self).name.clone() |
432 | } | 440 | } |
@@ -514,7 +522,7 @@ impl Adt { | |||
514 | } | 522 | } |
515 | } | 523 | } |
516 | 524 | ||
517 | pub(crate) fn krate(self, db: &impl HirDatabase) -> Option<Crate> { | 525 | pub fn krate(self, db: &impl HirDatabase) -> Option<Crate> { |
518 | match self { | 526 | match self { |
519 | Adt::Struct(s) => s.module(db), | 527 | Adt::Struct(s) => s.module(db), |
520 | Adt::Union(s) => s.module(db), | 528 | Adt::Union(s) => s.module(db), |
diff --git a/crates/ra_hir/src/marks.rs b/crates/ra_hir/src/marks.rs index 72f76bb79..0fed46802 100644 --- a/crates/ra_hir/src/marks.rs +++ b/crates/ra_hir/src/marks.rs | |||
@@ -9,7 +9,6 @@ test_utils::marks!( | |||
9 | glob_across_crates | 9 | glob_across_crates |
10 | std_prelude | 10 | std_prelude |
11 | match_ergonomics_ref | 11 | match_ergonomics_ref |
12 | trait_resolution_on_fn_type | ||
13 | infer_while_let | 12 | infer_while_let |
14 | macro_rules_from_other_crates_are_visible_with_macro_use | 13 | macro_rules_from_other_crates_are_visible_with_macro_use |
15 | prelude_is_macro_use | 14 | prelude_is_macro_use |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index fae9c1e22..d161735e8 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -14,11 +14,11 @@ pub(crate) mod display; | |||
14 | 14 | ||
15 | use std::ops::Deref; | 15 | use std::ops::Deref; |
16 | use std::sync::Arc; | 16 | use std::sync::Arc; |
17 | use std::{fmt, mem}; | 17 | use std::{fmt, iter, mem}; |
18 | 18 | ||
19 | use crate::{ | 19 | use crate::{ |
20 | db::HirDatabase, expr::ExprId, type_ref::Mutability, Adt, DefWithBody, GenericParams, Name, | 20 | db::HirDatabase, expr::ExprId, type_ref::Mutability, Adt, Crate, DefWithBody, GenericParams, |
21 | Trait, TypeAlias, | 21 | HasGenericParams, Name, Trait, TypeAlias, |
22 | }; | 22 | }; |
23 | use display::{HirDisplay, HirFormatter}; | 23 | use display::{HirDisplay, HirFormatter}; |
24 | 24 | ||
@@ -111,6 +111,81 @@ pub enum TypeCtor { | |||
111 | Closure { def: DefWithBody, expr: ExprId }, | 111 | Closure { def: DefWithBody, expr: ExprId }, |
112 | } | 112 | } |
113 | 113 | ||
114 | impl TypeCtor { | ||
115 | pub fn num_ty_params(self, db: &impl HirDatabase) -> usize { | ||
116 | match self { | ||
117 | TypeCtor::Bool | ||
118 | | TypeCtor::Char | ||
119 | | TypeCtor::Int(_) | ||
120 | | TypeCtor::Float(_) | ||
121 | | TypeCtor::Str | ||
122 | | TypeCtor::Never => 0, | ||
123 | TypeCtor::Slice | ||
124 | | TypeCtor::Array | ||
125 | | TypeCtor::RawPtr(_) | ||
126 | | TypeCtor::Ref(_) | ||
127 | | TypeCtor::Closure { .. } // 1 param representing the signature of the closure | ||
128 | => 1, | ||
129 | TypeCtor::Adt(adt) => { | ||
130 | let generic_params = adt.generic_params(db); | ||
131 | generic_params.count_params_including_parent() | ||
132 | } | ||
133 | TypeCtor::FnDef(callable) => { | ||
134 | let generic_params = callable.generic_params(db); | ||
135 | generic_params.count_params_including_parent() | ||
136 | } | ||
137 | TypeCtor::AssociatedType(type_alias) => { | ||
138 | let generic_params = type_alias.generic_params(db); | ||
139 | generic_params.count_params_including_parent() | ||
140 | } | ||
141 | TypeCtor::FnPtr { num_args } => num_args as usize + 1, | ||
142 | TypeCtor::Tuple { cardinality } => cardinality as usize, | ||
143 | } | ||
144 | } | ||
145 | |||
146 | pub fn krate(self, db: &impl HirDatabase) -> Option<Crate> { | ||
147 | match self { | ||
148 | TypeCtor::Bool | ||
149 | | TypeCtor::Char | ||
150 | | TypeCtor::Int(_) | ||
151 | | TypeCtor::Float(_) | ||
152 | | TypeCtor::Str | ||
153 | | TypeCtor::Never | ||
154 | | TypeCtor::Slice | ||
155 | | TypeCtor::Array | ||
156 | | TypeCtor::RawPtr(_) | ||
157 | | TypeCtor::Ref(_) | ||
158 | | TypeCtor::FnPtr { .. } | ||
159 | | TypeCtor::Tuple { .. } => None, | ||
160 | TypeCtor::Closure { def, .. } => def.krate(db), | ||
161 | TypeCtor::Adt(adt) => adt.krate(db), | ||
162 | TypeCtor::FnDef(callable) => callable.krate(db), | ||
163 | TypeCtor::AssociatedType(type_alias) => type_alias.krate(db), | ||
164 | } | ||
165 | } | ||
166 | |||
167 | pub fn as_generic_def(self) -> Option<crate::generics::GenericDef> { | ||
168 | match self { | ||
169 | TypeCtor::Bool | ||
170 | | TypeCtor::Char | ||
171 | | TypeCtor::Int(_) | ||
172 | | TypeCtor::Float(_) | ||
173 | | TypeCtor::Str | ||
174 | | TypeCtor::Never | ||
175 | | TypeCtor::Slice | ||
176 | | TypeCtor::Array | ||
177 | | TypeCtor::RawPtr(_) | ||
178 | | TypeCtor::Ref(_) | ||
179 | | TypeCtor::FnPtr { .. } | ||
180 | | TypeCtor::Tuple { .. } | ||
181 | | TypeCtor::Closure { .. } => None, | ||
182 | TypeCtor::Adt(adt) => Some(adt.into()), | ||
183 | TypeCtor::FnDef(callable) => Some(callable.into()), | ||
184 | TypeCtor::AssociatedType(type_alias) => Some(type_alias.into()), | ||
185 | } | ||
186 | } | ||
187 | } | ||
188 | |||
114 | /// A nominal type with (maybe 0) type parameters. This might be a primitive | 189 | /// A nominal type with (maybe 0) type parameters. This might be a primitive |
115 | /// type like `bool`, a struct, tuple, function pointer, reference or | 190 | /// type like `bool`, a struct, tuple, function pointer, reference or |
116 | /// several other things. | 191 | /// several other things. |
@@ -271,11 +346,65 @@ impl Substs { | |||
271 | .into(), | 346 | .into(), |
272 | ) | 347 | ) |
273 | } | 348 | } |
349 | |||
350 | pub fn build_for_def( | ||
351 | db: &impl HirDatabase, | ||
352 | def: impl crate::HasGenericParams, | ||
353 | ) -> SubstsBuilder { | ||
354 | let params = def.generic_params(db); | ||
355 | let param_count = params.count_params_including_parent(); | ||
356 | Substs::builder(param_count) | ||
357 | } | ||
358 | |||
359 | pub fn build_for_generics(generic_params: &GenericParams) -> SubstsBuilder { | ||
360 | Substs::builder(generic_params.count_params_including_parent()) | ||
361 | } | ||
362 | |||
363 | pub fn build_for_type_ctor(db: &impl HirDatabase, type_ctor: TypeCtor) -> SubstsBuilder { | ||
364 | Substs::builder(type_ctor.num_ty_params(db)) | ||
365 | } | ||
366 | |||
367 | fn builder(param_count: usize) -> SubstsBuilder { | ||
368 | SubstsBuilder { vec: Vec::with_capacity(param_count), param_count } | ||
369 | } | ||
370 | } | ||
371 | |||
372 | #[derive(Debug, Clone)] | ||
373 | pub struct SubstsBuilder { | ||
374 | vec: Vec<Ty>, | ||
375 | param_count: usize, | ||
274 | } | 376 | } |
275 | 377 | ||
276 | impl From<Vec<Ty>> for Substs { | 378 | impl SubstsBuilder { |
277 | fn from(v: Vec<Ty>) -> Self { | 379 | pub fn build(self) -> Substs { |
278 | Substs(v.into()) | 380 | assert_eq!(self.vec.len(), self.param_count); |
381 | Substs(self.vec.into()) | ||
382 | } | ||
383 | |||
384 | pub fn push(mut self, ty: Ty) -> Self { | ||
385 | self.vec.push(ty); | ||
386 | self | ||
387 | } | ||
388 | |||
389 | fn remaining(&self) -> usize { | ||
390 | self.param_count - self.vec.len() | ||
391 | } | ||
392 | |||
393 | pub fn fill_with_bound_vars(mut self, starting_from: u32) -> Self { | ||
394 | self.vec.extend((starting_from..starting_from + self.remaining() as u32).map(Ty::Bound)); | ||
395 | self | ||
396 | } | ||
397 | |||
398 | pub fn fill_with_unknown(mut self) -> Self { | ||
399 | self.vec.extend(iter::repeat(Ty::Unknown).take(self.remaining())); | ||
400 | self | ||
401 | } | ||
402 | |||
403 | pub fn use_parent_substs(mut self, parent_substs: &Substs) -> Self { | ||
404 | assert!(self.vec.is_empty()); | ||
405 | assert!(parent_substs.len() <= self.param_count); | ||
406 | self.vec.extend(parent_substs.iter().cloned()); | ||
407 | self | ||
279 | } | 408 | } |
280 | } | 409 | } |
281 | 410 | ||
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs index 94f8ecdc9..02492ca14 100644 --- a/crates/ra_hir/src/ty/autoderef.rs +++ b/crates/ra_hir/src/ty/autoderef.rs | |||
@@ -7,7 +7,7 @@ use std::iter::successors; | |||
7 | 7 | ||
8 | use log::{info, warn}; | 8 | use log::{info, warn}; |
9 | 9 | ||
10 | use super::{traits::Solution, Canonical, Ty, TypeWalk}; | 10 | use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk}; |
11 | use crate::{db::HirDatabase, name, HasGenericParams, Resolver}; | 11 | use crate::{db::HirDatabase, name, HasGenericParams, Resolver}; |
12 | 12 | ||
13 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 13 | const AUTODEREF_RECURSION_LIMIT: usize = 10; |
@@ -44,7 +44,8 @@ fn deref_by_trait( | |||
44 | }; | 44 | }; |
45 | let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?; | 45 | let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?; |
46 | 46 | ||
47 | if target.generic_params(db).count_params_including_parent() != 1 { | 47 | let generic_params = target.generic_params(db); |
48 | if generic_params.count_params_including_parent() != 1 { | ||
48 | // the Target type + Deref trait should only have one generic parameter, | 49 | // the Target type + Deref trait should only have one generic parameter, |
49 | // namely Deref's Self type | 50 | // namely Deref's Self type |
50 | return None; | 51 | return None; |
@@ -54,12 +55,13 @@ fn deref_by_trait( | |||
54 | 55 | ||
55 | let env = super::lower::trait_env(db, resolver); | 56 | let env = super::lower::trait_env(db, resolver); |
56 | 57 | ||
58 | let parameters = Substs::build_for_generics(&generic_params) | ||
59 | .push(ty.value.clone().shift_bound_vars(1)) | ||
60 | .build(); | ||
61 | |||
57 | let projection = super::traits::ProjectionPredicate { | 62 | let projection = super::traits::ProjectionPredicate { |
58 | ty: Ty::Bound(0), | 63 | ty: Ty::Bound(0), |
59 | projection_ty: super::ProjectionTy { | 64 | projection_ty: super::ProjectionTy { associated_ty: target, parameters }, |
60 | associated_ty: target, | ||
61 | parameters: vec![ty.value.clone().shift_bound_vars(1)].into(), | ||
62 | }, | ||
63 | }; | 65 | }; |
64 | 66 | ||
65 | let obligation = super::Obligation::Projection(projection); | 67 | let obligation = super::Obligation::Projection(projection); |
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 8f92468e6..2e4a489a0 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -688,14 +688,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
688 | }; | 688 | }; |
689 | let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown)); | 689 | let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown)); |
690 | 690 | ||
691 | let inner_tys: Substs = args | 691 | let inner_tys = args |
692 | .iter() | 692 | .iter() |
693 | .zip(expectations_iter) | 693 | .zip(expectations_iter) |
694 | .map(|(&pat, ty)| self.infer_pat(pat, ty, default_bm)) | 694 | .map(|(&pat, ty)| self.infer_pat(pat, ty, default_bm)) |
695 | .collect::<Vec<_>>() | 695 | .collect(); |
696 | .into(); | ||
697 | 696 | ||
698 | Ty::apply(TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, inner_tys) | 697 | Ty::apply(TypeCtor::Tuple { cardinality: args.len() as u16 }, Substs(inner_tys)) |
699 | } | 698 | } |
700 | Pat::Ref { pat, mutability } => { | 699 | Pat::Ref { pat, mutability } => { |
701 | let expectation = match expected.as_reference() { | 700 | let expectation = match expected.as_reference() { |
@@ -1229,7 +1228,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1229 | ty: pat_ty.clone(), | 1228 | ty: pat_ty.clone(), |
1230 | projection_ty: ProjectionTy { | 1229 | projection_ty: ProjectionTy { |
1231 | associated_ty: into_iter_item_alias, | 1230 | associated_ty: into_iter_item_alias, |
1232 | parameters: vec![iterable_ty].into(), | 1231 | parameters: Substs::single(iterable_ty), |
1233 | }, | 1232 | }, |
1234 | }; | 1233 | }; |
1235 | self.obligations.push(Obligation::Projection(projection)); | 1234 | self.obligations.push(Obligation::Projection(projection)); |
@@ -1262,7 +1261,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1262 | sig_tys.push(ret_ty.clone()); | 1261 | sig_tys.push(ret_ty.clone()); |
1263 | let sig_ty = Ty::apply( | 1262 | let sig_ty = Ty::apply( |
1264 | TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, | 1263 | TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, |
1265 | sig_tys.into(), | 1264 | Substs(sig_tys.into()), |
1266 | ); | 1265 | ); |
1267 | let closure_ty = Ty::apply_one( | 1266 | let closure_ty = Ty::apply_one( |
1268 | TypeCtor::Closure { def: self.body.owner(), expr: tgt_expr }, | 1267 | TypeCtor::Closure { def: self.body.owner(), expr: tgt_expr }, |
@@ -1399,7 +1398,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1399 | ty: ty.clone(), | 1398 | ty: ty.clone(), |
1400 | projection_ty: ProjectionTy { | 1399 | projection_ty: ProjectionTy { |
1401 | associated_ty: future_future_output_alias, | 1400 | associated_ty: future_future_output_alias, |
1402 | parameters: vec![inner_ty].into(), | 1401 | parameters: Substs::single(inner_ty), |
1403 | }, | 1402 | }, |
1404 | }; | 1403 | }; |
1405 | self.obligations.push(Obligation::Projection(projection)); | 1404 | self.obligations.push(Obligation::Projection(projection)); |
@@ -1418,7 +1417,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1418 | ty: ty.clone(), | 1417 | ty: ty.clone(), |
1419 | projection_ty: ProjectionTy { | 1418 | projection_ty: ProjectionTy { |
1420 | associated_ty: ops_try_ok_alias, | 1419 | associated_ty: ops_try_ok_alias, |
1421 | parameters: vec![inner_ty].into(), | 1420 | parameters: Substs::single(inner_ty), |
1422 | }, | 1421 | }, |
1423 | }; | 1422 | }; |
1424 | self.obligations.push(Obligation::Projection(projection)); | 1423 | self.obligations.push(Obligation::Projection(projection)); |
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs index feb7481b2..db979353a 100644 --- a/crates/ra_hir/src/ty/infer/path.rs +++ b/crates/ra_hir/src/ty/infer/path.rs | |||
@@ -158,13 +158,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
158 | AssocItem::Const(c) => ValueNs::Const(c), | 158 | AssocItem::Const(c) => ValueNs::Const(c), |
159 | AssocItem::TypeAlias(_) => unreachable!(), | 159 | AssocItem::TypeAlias(_) => unreachable!(), |
160 | }; | 160 | }; |
161 | let generics = item.generic_params(self.db); | 161 | let substs = Substs::build_for_def(self.db, item) |
162 | let mut substs = Vec::with_capacity(generics.count_params_including_parent()); | 162 | .use_parent_substs(&trait_ref.substs) |
163 | substs.extend(trait_ref.substs.iter().cloned()); | 163 | .fill_with_unknown() |
164 | substs.extend(std::iter::repeat(Ty::Unknown).take(generics.params.len())); | 164 | .build(); |
165 | 165 | ||
166 | self.write_assoc_resolution(id, item); | 166 | self.write_assoc_resolution(id, item); |
167 | Some((def, Some(substs.into()))) | 167 | Some((def, Some(substs))) |
168 | } | 168 | } |
169 | 169 | ||
170 | fn resolve_ty_assoc_item( | 170 | fn resolve_ty_assoc_item( |
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs index b6ebee3b1..d161aa6b3 100644 --- a/crates/ra_hir/src/ty/infer/unify.rs +++ b/crates/ra_hir/src/ty/infer/unify.rs | |||
@@ -3,7 +3,8 @@ | |||
3 | use super::{InferenceContext, Obligation}; | 3 | use super::{InferenceContext, Obligation}; |
4 | use crate::db::HirDatabase; | 4 | use crate::db::HirDatabase; |
5 | use crate::ty::{ | 5 | use crate::ty::{ |
6 | Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty, TypeWalk, | 6 | Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, |
7 | TypeWalk, | ||
7 | }; | 8 | }; |
8 | 9 | ||
9 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 10 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
@@ -74,12 +75,9 @@ where | |||
74 | } | 75 | } |
75 | 76 | ||
76 | fn do_canonicalize_trait_ref(&mut self, trait_ref: TraitRef) -> TraitRef { | 77 | fn do_canonicalize_trait_ref(&mut self, trait_ref: TraitRef) -> TraitRef { |
77 | let substs = trait_ref | 78 | let substs = |
78 | .substs | 79 | trait_ref.substs.iter().map(|ty| self.do_canonicalize_ty(ty.clone())).collect(); |
79 | .iter() | 80 | TraitRef { trait_: trait_ref.trait_, substs: Substs(substs) } |
80 | .map(|ty| self.do_canonicalize_ty(ty.clone())) | ||
81 | .collect::<Vec<_>>(); | ||
82 | TraitRef { trait_: trait_ref.trait_, substs: substs.into() } | ||
83 | } | 81 | } |
84 | 82 | ||
85 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { | 83 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { |
@@ -90,12 +88,9 @@ where | |||
90 | } | 88 | } |
91 | 89 | ||
92 | fn do_canonicalize_projection_ty(&mut self, projection_ty: ProjectionTy) -> ProjectionTy { | 90 | fn do_canonicalize_projection_ty(&mut self, projection_ty: ProjectionTy) -> ProjectionTy { |
93 | let params = projection_ty | 91 | let params = |
94 | .parameters | 92 | projection_ty.parameters.iter().map(|ty| self.do_canonicalize_ty(ty.clone())).collect(); |
95 | .iter() | 93 | ProjectionTy { associated_ty: projection_ty.associated_ty, parameters: Substs(params) } |
96 | .map(|ty| self.do_canonicalize_ty(ty.clone())) | ||
97 | .collect::<Vec<_>>(); | ||
98 | ProjectionTy { associated_ty: projection_ty.associated_ty, parameters: params.into() } | ||
99 | } | 94 | } |
100 | 95 | ||
101 | fn do_canonicalize_projection_predicate( | 96 | fn do_canonicalize_projection_predicate( |
@@ -153,8 +148,7 @@ impl<T> Canonicalized<T> { | |||
153 | solution: Canonical<Vec<Ty>>, | 148 | solution: Canonical<Vec<Ty>>, |
154 | ) { | 149 | ) { |
155 | // the solution may contain new variables, which we need to convert to new inference vars | 150 | // the solution may contain new variables, which we need to convert to new inference vars |
156 | let new_vars = | 151 | let new_vars = Substs((0..solution.num_vars).map(|_| ctx.new_type_var()).collect()); |
157 | (0..solution.num_vars).map(|_| ctx.new_type_var()).collect::<Vec<_>>().into(); | ||
158 | for (i, ty) in solution.value.into_iter().enumerate() { | 152 | for (i, ty) in solution.value.into_iter().enumerate() { |
159 | let var = self.free_vars[i]; | 153 | let var = self.free_vars[i]; |
160 | ctx.unify(&Ty::Infer(var), &ty.subst_bound_vars(&new_vars)); | 154 | ctx.unify(&Ty::Infer(var), &ty.subst_bound_vars(&new_vars)); |
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index dd503d771..4b67c82e7 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -239,14 +239,10 @@ impl Ty { | |||
239 | let traits = traits_from_env.flat_map(|t| t.all_super_traits(db)); | 239 | let traits = traits_from_env.flat_map(|t| t.all_super_traits(db)); |
240 | for t in traits { | 240 | for t in traits { |
241 | if let Some(associated_ty) = t.associated_type_by_name(db, &segment.name) { | 241 | if let Some(associated_ty) = t.associated_type_by_name(db, &segment.name) { |
242 | let generics = t.generic_params(db); | 242 | let substs = |
243 | let mut substs = Vec::new(); | 243 | Substs::build_for_def(db, t).push(self_ty.clone()).fill_with_unknown().build(); |
244 | substs.push(self_ty.clone()); | ||
245 | substs.extend( | ||
246 | iter::repeat(Ty::Unknown).take(generics.count_params_including_parent() - 1), | ||
247 | ); | ||
248 | // FIXME handle type parameters on the segment | 244 | // FIXME handle type parameters on the segment |
249 | return Ty::Projection(ProjectionTy { associated_ty, parameters: substs.into() }); | 245 | return Ty::Projection(ProjectionTy { associated_ty, parameters: substs }); |
250 | } | 246 | } |
251 | } | 247 | } |
252 | Ty::Unknown | 248 | Ty::Unknown |
@@ -766,6 +762,16 @@ pub enum CallableDef { | |||
766 | } | 762 | } |
767 | impl_froms!(CallableDef: Function, Struct, EnumVariant); | 763 | impl_froms!(CallableDef: Function, Struct, EnumVariant); |
768 | 764 | ||
765 | impl CallableDef { | ||
766 | pub fn krate(self, db: &impl HirDatabase) -> Option<crate::Crate> { | ||
767 | match self { | ||
768 | CallableDef::Function(f) => f.krate(db), | ||
769 | CallableDef::Struct(s) => s.krate(db), | ||
770 | CallableDef::EnumVariant(e) => e.parent_enum(db).krate(db), | ||
771 | } | ||
772 | } | ||
773 | } | ||
774 | |||
769 | impl From<CallableDef> for GenericDef { | 775 | impl From<CallableDef> for GenericDef { |
770 | fn from(def: CallableDef) -> GenericDef { | 776 | fn from(def: CallableDef) -> GenericDef { |
771 | match def { | 777 | match def { |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 4b71b376f..ad2ab560d 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -10,7 +10,6 @@ use rustc_hash::FxHashMap; | |||
10 | use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; | 10 | use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; |
11 | use crate::{ | 11 | use crate::{ |
12 | db::HirDatabase, | 12 | db::HirDatabase, |
13 | generics::HasGenericParams, | ||
14 | impl_block::{ImplBlock, ImplId}, | 13 | impl_block::{ImplBlock, ImplId}, |
15 | nameres::CrateModuleId, | 14 | nameres::CrateModuleId, |
16 | resolve::Resolver, | 15 | resolve::Resolver, |
@@ -331,20 +330,13 @@ fn generic_implements_goal( | |||
331 | trait_: Trait, | 330 | trait_: Trait, |
332 | self_ty: Canonical<Ty>, | 331 | self_ty: Canonical<Ty>, |
333 | ) -> Canonical<InEnvironment<super::Obligation>> { | 332 | ) -> Canonical<InEnvironment<super::Obligation>> { |
334 | let mut substs = Vec::new(); | ||
335 | let generics = trait_.generic_params(db); | ||
336 | let num_vars = self_ty.num_vars; | 333 | let num_vars = self_ty.num_vars; |
337 | substs.push(self_ty.value); | 334 | let substs = super::Substs::build_for_def(db, trait_) |
338 | substs.extend( | 335 | .push(self_ty.value) |
339 | generics | 336 | .fill_with_bound_vars(num_vars as u32) |
340 | .params_including_parent() | 337 | .build(); |
341 | .into_iter() | ||
342 | .skip(1) | ||
343 | .enumerate() | ||
344 | .map(|(i, _p)| Ty::Bound((i + num_vars) as u32)), | ||
345 | ); | ||
346 | let num_vars = substs.len() - 1 + self_ty.num_vars; | 338 | let num_vars = substs.len() - 1 + self_ty.num_vars; |
347 | let trait_ref = TraitRef { trait_, substs: substs.into() }; | 339 | let trait_ref = TraitRef { trait_, substs }; |
348 | let obligation = super::Obligation::Trait(trait_ref); | 340 | let obligation = super::Obligation::Trait(trait_ref); |
349 | Canonical { num_vars, value: InEnvironment::new(env, obligation) } | 341 | Canonical { num_vars, value: InEnvironment::new(env, obligation) } |
350 | } | 342 | } |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index bd2b07755..4df39c191 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -3354,7 +3354,6 @@ fn test() { S2.into()<|>; } | |||
3354 | 3354 | ||
3355 | #[test] | 3355 | #[test] |
3356 | fn method_resolution_encountering_fn_type() { | 3356 | fn method_resolution_encountering_fn_type() { |
3357 | covers!(trait_resolution_on_fn_type); | ||
3358 | type_at( | 3357 | type_at( |
3359 | r#" | 3358 | r#" |
3360 | //- /main.rs | 3359 | //- /main.rs |
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 538b4d3ec..2642a54bf 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -10,17 +10,13 @@ use chalk_ir::{ | |||
10 | use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum}; | 10 | use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum}; |
11 | 11 | ||
12 | use ra_db::salsa::{InternId, InternKey}; | 12 | use ra_db::salsa::{InternId, InternKey}; |
13 | use test_utils::tested_by; | ||
14 | 13 | ||
15 | use super::{Canonical, ChalkContext, Impl, Obligation}; | 14 | use super::{Canonical, ChalkContext, Impl, Obligation}; |
16 | use crate::{ | 15 | use crate::{ |
17 | db::HirDatabase, | 16 | db::HirDatabase, |
18 | generics::GenericDef, | 17 | generics::GenericDef, |
19 | ty::display::HirDisplay, | 18 | ty::display::HirDisplay, |
20 | ty::{ | 19 | ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk}, |
21 | ApplicationTy, CallableDef, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | ||
22 | TypeWalk, | ||
23 | }, | ||
24 | AssocItem, Crate, HasGenericParams, ImplBlock, Trait, TypeAlias, | 20 | AssocItem, Crate, HasGenericParams, ImplBlock, Trait, TypeAlias, |
25 | }; | 21 | }; |
26 | 22 | ||
@@ -124,14 +120,15 @@ impl ToChalk for Substs { | |||
124 | } | 120 | } |
125 | 121 | ||
126 | fn from_chalk(db: &impl HirDatabase, parameters: Vec<chalk_ir::Parameter>) -> Substs { | 122 | fn from_chalk(db: &impl HirDatabase, parameters: Vec<chalk_ir::Parameter>) -> Substs { |
127 | parameters | 123 | let tys = parameters |
128 | .into_iter() | 124 | .into_iter() |
129 | .map(|p| match p { | 125 | .map(|p| match p { |
130 | chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty), | 126 | chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty), |
131 | chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(), | 127 | chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(), |
132 | }) | 128 | }) |
133 | .collect::<Vec<_>>() | 129 | .collect::<Vec<_>>() |
134 | .into() | 130 | .into(); |
131 | Substs(tys) | ||
135 | } | 132 | } |
136 | } | 133 | } |
137 | 134 | ||
@@ -539,60 +536,18 @@ pub(crate) fn struct_datum_query( | |||
539 | struct_id: chalk_ir::StructId, | 536 | struct_id: chalk_ir::StructId, |
540 | ) -> Arc<StructDatum> { | 537 | ) -> Arc<StructDatum> { |
541 | debug!("struct_datum {:?}", struct_id); | 538 | debug!("struct_datum {:?}", struct_id); |
542 | let type_ctor = from_chalk(db, struct_id); | 539 | let type_ctor: TypeCtor = from_chalk(db, struct_id); |
543 | debug!("struct {:?} = {:?}", struct_id, type_ctor); | 540 | debug!("struct {:?} = {:?}", struct_id, type_ctor); |
544 | // FIXME might be nicer if we can create a fake GenericParams for the TypeCtor | 541 | let num_params = type_ctor.num_ty_params(db); |
545 | // FIXME extract this to a method on Ty | 542 | let upstream = type_ctor.krate(db) != Some(krate); |
546 | let (num_params, where_clauses, upstream) = match type_ctor { | 543 | let where_clauses = type_ctor |
547 | TypeCtor::Bool | 544 | .as_generic_def() |
548 | | TypeCtor::Char | 545 | .map(|generic_def| { |
549 | | TypeCtor::Int(_) | ||
550 | | TypeCtor::Float(_) | ||
551 | | TypeCtor::Never | ||
552 | | TypeCtor::Str => (0, vec![], true), | ||
553 | TypeCtor::Slice | TypeCtor::Array | TypeCtor::RawPtr(_) | TypeCtor::Ref(_) => { | ||
554 | (1, vec![], true) | ||
555 | } | ||
556 | TypeCtor::FnPtr { num_args } => (num_args as usize + 1, vec![], true), | ||
557 | TypeCtor::Tuple { cardinality } => (cardinality as usize, vec![], true), | ||
558 | TypeCtor::FnDef(callable) => { | ||
559 | tested_by!(trait_resolution_on_fn_type); | ||
560 | let upstream = match callable { | ||
561 | CallableDef::Function(f) => f.module(db).krate(db), | ||
562 | CallableDef::Struct(s) => s.module(db).krate(db), | ||
563 | CallableDef::EnumVariant(v) => v.parent_enum(db).module(db).krate(db), | ||
564 | } != Some(krate); | ||
565 | let generic_def: GenericDef = callable.into(); | ||
566 | let generic_params = generic_def.generic_params(db); | 546 | let generic_params = generic_def.generic_params(db); |
567 | let bound_vars = Substs::bound_vars(&generic_params); | 547 | let bound_vars = Substs::bound_vars(&generic_params); |
568 | let where_clauses = convert_where_clauses(db, generic_def, &bound_vars); | 548 | convert_where_clauses(db, generic_def, &bound_vars) |
569 | (generic_params.count_params_including_parent(), where_clauses, upstream) | 549 | }) |
570 | } | 550 | .unwrap_or_else(Vec::new); |
571 | TypeCtor::Adt(adt) => { | ||
572 | let generic_params = adt.generic_params(db); | ||
573 | let bound_vars = Substs::bound_vars(&generic_params); | ||
574 | let where_clauses = convert_where_clauses(db, adt.into(), &bound_vars); | ||
575 | ( | ||
576 | generic_params.count_params_including_parent(), | ||
577 | where_clauses, | ||
578 | adt.krate(db) != Some(krate), | ||
579 | ) | ||
580 | } | ||
581 | TypeCtor::AssociatedType(type_alias) => { | ||
582 | let generic_params = type_alias.generic_params(db); | ||
583 | let bound_vars = Substs::bound_vars(&generic_params); | ||
584 | let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); | ||
585 | ( | ||
586 | generic_params.count_params_including_parent(), | ||
587 | where_clauses, | ||
588 | type_alias.krate(db) != Some(krate), | ||
589 | ) | ||
590 | } | ||
591 | TypeCtor::Closure { def, .. } => { | ||
592 | let upstream = def.krate(db) != Some(krate); | ||
593 | (1, vec![], upstream) | ||
594 | } | ||
595 | }; | ||
596 | let flags = chalk_rust_ir::StructFlags { | 551 | let flags = chalk_rust_ir::StructFlags { |
597 | upstream, | 552 | upstream, |
598 | // FIXME set fundamental flag correctly | 553 | // FIXME set fundamental flag correctly |
@@ -729,17 +684,20 @@ fn closure_fn_trait_impl_datum( | |||
729 | 684 | ||
730 | let arg_ty = Ty::apply( | 685 | let arg_ty = Ty::apply( |
731 | TypeCtor::Tuple { cardinality: num_args }, | 686 | TypeCtor::Tuple { cardinality: num_args }, |
732 | (0..num_args).map(|i| Ty::Bound(i.into())).collect::<Vec<_>>().into(), | 687 | Substs::builder(num_args as usize).fill_with_bound_vars(0).build(), |
733 | ); | 688 | ); |
734 | let output_ty = Ty::Bound(num_args.into()); | 689 | let output_ty = Ty::Bound(num_args.into()); |
735 | let sig_ty = Ty::apply( | 690 | let sig_ty = Ty::apply( |
736 | TypeCtor::FnPtr { num_args }, | 691 | TypeCtor::FnPtr { num_args }, |
737 | (0..num_args + 1).map(|i| Ty::Bound(i.into())).collect::<Vec<_>>().into(), | 692 | Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(), |
738 | ); | 693 | ); |
739 | 694 | ||
740 | let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty); | 695 | let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty); |
741 | 696 | ||
742 | let trait_ref = TraitRef { trait_, substs: vec![self_ty, arg_ty].into() }; | 697 | let trait_ref = TraitRef { |
698 | trait_, | ||
699 | substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), | ||
700 | }; | ||
743 | 701 | ||
744 | let output_ty_id = fn_once_trait.associated_type_by_name(db, &crate::name::OUTPUT_TYPE)?; | 702 | let output_ty_id = fn_once_trait.associated_type_by_name(db, &crate::name::OUTPUT_TYPE)?; |
745 | 703 | ||
diff --git a/crates/ra_ide_api/src/line_index.rs b/crates/ra_ide_api/src/line_index.rs index 71de8a928..5fedad696 100644 --- a/crates/ra_ide_api/src/line_index.rs +++ b/crates/ra_ide_api/src/line_index.rs | |||
@@ -278,5 +278,4 @@ const C: char = \"メ メ\"; | |||
278 | 278 | ||
279 | assert_eq!(col_index.utf16_to_utf8_col(2, 15), TextUnit::from_usize(15)); | 279 | assert_eq!(col_index.utf16_to_utf8_col(2, 15), TextUnit::from_usize(15)); |
280 | } | 280 | } |
281 | |||
282 | } | 281 | } |
diff --git a/crates/ra_ide_api/src/runnables.rs b/crates/ra_ide_api/src/runnables.rs index 095ca56c4..8cf58fe79 100644 --- a/crates/ra_ide_api/src/runnables.rs +++ b/crates/ra_ide_api/src/runnables.rs | |||
@@ -229,5 +229,4 @@ mod tests { | |||
229 | let runnables = analysis.runnables(pos.file_id).unwrap(); | 229 | let runnables = analysis.runnables(pos.file_id).unwrap(); |
230 | assert!(runnables.is_empty()) | 230 | assert!(runnables.is_empty()) |
231 | } | 231 | } |
232 | |||
233 | } | 232 | } |
diff --git a/crates/ra_lsp_server/src/markdown.rs b/crates/ra_lsp_server/src/markdown.rs index c1eb0236a..3659edf8e 100644 --- a/crates/ra_lsp_server/src/markdown.rs +++ b/crates/ra_lsp_server/src/markdown.rs | |||
@@ -70,5 +70,4 @@ let a = 1; | |||
70 | "```rust\nfn main(){}\n```\nSome comment.\n```rust\nlet a = 1;\n```" | 70 | "```rust\nfn main(){}\n```\nSome comment.\n```rust\nlet a = 1;\n```" |
71 | ); | 71 | ); |
72 | } | 72 | } |
73 | |||
74 | } | 73 | } |
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs index e2355aff9..6e9e212b7 100644 --- a/crates/ra_parser/src/grammar.rs +++ b/crates/ra_parser/src/grammar.rs | |||
@@ -135,7 +135,6 @@ pub(crate) mod fragments { | |||
135 | 135 | ||
136 | m.complete(p, MACRO_STMTS); | 136 | m.complete(p, MACRO_STMTS); |
137 | } | 137 | } |
138 | |||
139 | } | 138 | } |
140 | 139 | ||
141 | pub(crate) fn reparser( | 140 | pub(crate) fn reparser( |
diff --git a/crates/ra_syntax/Cargo.toml b/crates/ra_syntax/Cargo.toml index 724c38e17..9bc85404a 100644 --- a/crates/ra_syntax/Cargo.toml +++ b/crates/ra_syntax/Cargo.toml | |||
@@ -12,6 +12,8 @@ itertools = "0.8.0" | |||
12 | rowan = "0.6.1" | 12 | rowan = "0.6.1" |
13 | rustc_lexer = "0.1.0" | 13 | rustc_lexer = "0.1.0" |
14 | rustc-hash = "1.0.1" | 14 | rustc-hash = "1.0.1" |
15 | arrayvec = "0.4.10" | ||
16 | once_cell = "1.2.0" | ||
15 | 17 | ||
16 | # ideally, `serde` should be enabled by `ra_lsp_server`, but we enable it here | 18 | # ideally, `serde` should be enabled by `ra_lsp_server`, but we enable it here |
17 | # to reduce number of compilations | 19 | # to reduce number of compilations |
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index f464d6534..fdffd8cb1 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs | |||
@@ -5,6 +5,7 @@ mod traits; | |||
5 | mod tokens; | 5 | mod tokens; |
6 | mod extensions; | 6 | mod extensions; |
7 | mod expr_extensions; | 7 | mod expr_extensions; |
8 | mod edit; | ||
8 | pub mod make; | 9 | pub mod make; |
9 | 10 | ||
10 | use std::marker::PhantomData; | 11 | use std::marker::PhantomData; |
diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs new file mode 100644 index 000000000..c65899812 --- /dev/null +++ b/crates/ra_syntax/src/ast/edit.rs | |||
@@ -0,0 +1,52 @@ | |||
1 | //! This module contains functions for editing syntax trees. As the trees are | ||
2 | //! immutable, all function here return a fresh copy of the tree, instead of | ||
3 | //! doing an in-place modification. | ||
4 | |||
5 | use arrayvec::ArrayVec; | ||
6 | use std::ops::RangeInclusive; | ||
7 | |||
8 | use crate::{ | ||
9 | algo, | ||
10 | ast::{self, make, AstNode}, | ||
11 | InsertPosition, SyntaxElement, | ||
12 | }; | ||
13 | |||
14 | impl ast::FnDef { | ||
15 | #[must_use] | ||
16 | pub fn with_body(&self, body: ast::Block) -> ast::FnDef { | ||
17 | let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new(); | ||
18 | let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() { | ||
19 | old_body.syntax().clone().into() | ||
20 | } else if let Some(semi) = self.semicolon_token() { | ||
21 | to_insert.push(make::tokens::single_space().into()); | ||
22 | semi.into() | ||
23 | } else { | ||
24 | to_insert.push(make::tokens::single_space().into()); | ||
25 | to_insert.push(body.syntax().clone().into()); | ||
26 | return insert_children(self, InsertPosition::Last, to_insert.into_iter()); | ||
27 | }; | ||
28 | to_insert.push(body.syntax().clone().into()); | ||
29 | let replace_range = RangeInclusive::new(old_body_or_semi.clone(), old_body_or_semi); | ||
30 | replace_children(self, replace_range, to_insert.into_iter()) | ||
31 | } | ||
32 | } | ||
33 | |||
34 | #[must_use] | ||
35 | fn insert_children<N: AstNode>( | ||
36 | parent: &N, | ||
37 | position: InsertPosition<SyntaxElement>, | ||
38 | mut to_insert: impl Iterator<Item = SyntaxElement>, | ||
39 | ) -> N { | ||
40 | let new_syntax = algo::insert_children(parent.syntax(), position, &mut to_insert); | ||
41 | N::cast(new_syntax).unwrap() | ||
42 | } | ||
43 | |||
44 | #[must_use] | ||
45 | fn replace_children<N: AstNode>( | ||
46 | parent: &N, | ||
47 | to_replace: RangeInclusive<SyntaxElement>, | ||
48 | mut to_insert: impl Iterator<Item = SyntaxElement>, | ||
49 | ) -> N { | ||
50 | let new_syntax = algo::replace_children(parent.syntax(), to_replace, &mut to_insert); | ||
51 | N::cast(new_syntax).unwrap() | ||
52 | } | ||
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index c06c62b3b..287a40bee 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs | |||
@@ -133,3 +133,51 @@ fn ast_from_text<N: AstNode>(text: &str) -> N { | |||
133 | let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); | 133 | let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); |
134 | res | 134 | res |
135 | } | 135 | } |
136 | |||
137 | pub mod tokens { | ||
138 | use crate::{AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken, T}; | ||
139 | use once_cell::sync::Lazy; | ||
140 | |||
141 | static SOURCE_FILE: Lazy<Parse<SourceFile>> = Lazy::new(|| SourceFile::parse(",\n; ;")); | ||
142 | |||
143 | pub fn comma() -> SyntaxToken { | ||
144 | SOURCE_FILE | ||
145 | .tree() | ||
146 | .syntax() | ||
147 | .descendants_with_tokens() | ||
148 | .filter_map(|it| it.into_token()) | ||
149 | .find(|it| it.kind() == T![,]) | ||
150 | .unwrap() | ||
151 | } | ||
152 | |||
153 | pub fn single_space() -> SyntaxToken { | ||
154 | SOURCE_FILE | ||
155 | .tree() | ||
156 | .syntax() | ||
157 | .descendants_with_tokens() | ||
158 | .filter_map(|it| it.into_token()) | ||
159 | .find(|it| it.kind() == WHITESPACE && it.text().as_str() == " ") | ||
160 | .unwrap() | ||
161 | } | ||
162 | |||
163 | pub fn single_newline() -> SyntaxToken { | ||
164 | SOURCE_FILE | ||
165 | .tree() | ||
166 | .syntax() | ||
167 | .descendants_with_tokens() | ||
168 | .filter_map(|it| it.into_token()) | ||
169 | .find(|it| it.kind() == WHITESPACE && it.text().as_str() == "\n") | ||
170 | .unwrap() | ||
171 | } | ||
172 | |||
173 | pub struct WsBuilder(SourceFile); | ||
174 | |||
175 | impl WsBuilder { | ||
176 | pub fn new(text: &str) -> WsBuilder { | ||
177 | WsBuilder(SourceFile::parse(text).ok().unwrap()) | ||
178 | } | ||
179 | pub fn ws(&self) -> SyntaxToken { | ||
180 | self.0.syntax().first_child_or_token().unwrap().into_token().unwrap() | ||
181 | } | ||
182 | } | ||
183 | } | ||