diff options
-rw-r--r-- | crates/hir_def/src/nameres/mod_resolution.rs | 13 | ||||
-rw-r--r-- | crates/hir_expand/src/builtin_macro.rs | 66 | ||||
-rw-r--r-- | crates/hir_expand/src/eager.rs | 13 | ||||
-rw-r--r-- | crates/hir_expand/src/lib.rs | 23 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 6 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/pat.rs | 32 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/macros.rs | 23 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/patterns.rs | 22 | ||||
-rw-r--r-- | crates/ide_db/src/helpers/insert_use.rs | 4 | ||||
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 3 | ||||
-rw-r--r-- | crates/rust-analyzer/src/to_proto.rs | 6 | ||||
-rw-r--r-- | docs/dev/README.md | 3 | ||||
-rw-r--r-- | docs/user/manual.adoc | 14 |
13 files changed, 184 insertions, 44 deletions
diff --git a/crates/hir_def/src/nameres/mod_resolution.rs b/crates/hir_def/src/nameres/mod_resolution.rs index d5de9899c..d9cec0e27 100644 --- a/crates/hir_def/src/nameres/mod_resolution.rs +++ b/crates/hir_def/src/nameres/mod_resolution.rs | |||
@@ -62,7 +62,7 @@ impl ModDir { | |||
62 | name: &Name, | 62 | name: &Name, |
63 | attr_path: Option<&SmolStr>, | 63 | attr_path: Option<&SmolStr>, |
64 | ) -> Result<(FileId, bool, ModDir), String> { | 64 | ) -> Result<(FileId, bool, ModDir), String> { |
65 | let file_id = file_id.original_file(db.upcast()); | 65 | let orig_file_id = file_id.original_file(db.upcast()); |
66 | 66 | ||
67 | let mut candidate_files = Vec::new(); | 67 | let mut candidate_files = Vec::new(); |
68 | match attr_path { | 68 | match attr_path { |
@@ -70,13 +70,18 @@ impl ModDir { | |||
70 | candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner)) | 70 | candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner)) |
71 | } | 71 | } |
72 | None => { | 72 | None => { |
73 | candidate_files.push(format!("{}{}.rs", self.dir_path.0, name)); | 73 | if file_id.is_include_macro(db.upcast()) { |
74 | candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name)); | 74 | candidate_files.push(format!("{}.rs", name)); |
75 | candidate_files.push(format!("{}/mod.rs", name)); | ||
76 | } else { | ||
77 | candidate_files.push(format!("{}{}.rs", self.dir_path.0, name)); | ||
78 | candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name)); | ||
79 | } | ||
75 | } | 80 | } |
76 | }; | 81 | }; |
77 | 82 | ||
78 | for candidate in candidate_files.iter() { | 83 | for candidate in candidate_files.iter() { |
79 | let path = AnchoredPath { anchor: file_id, path: candidate.as_str() }; | 84 | let path = AnchoredPath { anchor: orig_file_id, path: candidate.as_str() }; |
80 | if let Some(file_id) = db.resolve_path(path) { | 85 | if let Some(file_id) = db.resolve_path(path) { |
81 | let is_mod_rs = candidate.ends_with("/mod.rs"); | 86 | let is_mod_rs = candidate.ends_with("/mod.rs"); |
82 | 87 | ||
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index 8529b43b6..4d52904b9 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -43,7 +43,7 @@ macro_rules! register_builtin { | |||
43 | db: &dyn AstDatabase, | 43 | db: &dyn AstDatabase, |
44 | arg_id: EagerMacroId, | 44 | arg_id: EagerMacroId, |
45 | tt: &tt::Subtree, | 45 | tt: &tt::Subtree, |
46 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 46 | ) -> ExpandResult<Option<ExpandedEager>> { |
47 | let expander = match *self { | 47 | let expander = match *self { |
48 | $( EagerExpander::$e_kind => $e_expand, )* | 48 | $( EagerExpander::$e_kind => $e_expand, )* |
49 | }; | 49 | }; |
@@ -61,6 +61,20 @@ macro_rules! register_builtin { | |||
61 | }; | 61 | }; |
62 | } | 62 | } |
63 | 63 | ||
64 | #[derive(Debug)] | ||
65 | pub struct ExpandedEager { | ||
66 | pub(crate) subtree: tt::Subtree, | ||
67 | pub(crate) fragment: FragmentKind, | ||
68 | /// The included file ID of the include macro. | ||
69 | pub(crate) included_file: Option<FileId>, | ||
70 | } | ||
71 | |||
72 | impl ExpandedEager { | ||
73 | fn new(subtree: tt::Subtree, fragment: FragmentKind) -> Self { | ||
74 | ExpandedEager { subtree, fragment, included_file: None } | ||
75 | } | ||
76 | } | ||
77 | |||
64 | pub fn find_builtin_macro( | 78 | pub fn find_builtin_macro( |
65 | ident: &name::Name, | 79 | ident: &name::Name, |
66 | krate: CrateId, | 80 | krate: CrateId, |
@@ -280,7 +294,7 @@ fn compile_error_expand( | |||
280 | _db: &dyn AstDatabase, | 294 | _db: &dyn AstDatabase, |
281 | _id: EagerMacroId, | 295 | _id: EagerMacroId, |
282 | tt: &tt::Subtree, | 296 | tt: &tt::Subtree, |
283 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 297 | ) -> ExpandResult<Option<ExpandedEager>> { |
284 | let err = match &*tt.token_trees { | 298 | let err = match &*tt.token_trees { |
285 | [tt::TokenTree::Leaf(tt::Leaf::Literal(it))] => { | 299 | [tt::TokenTree::Leaf(tt::Leaf::Literal(it))] => { |
286 | let text = it.text.as_str(); | 300 | let text = it.text.as_str(); |
@@ -294,14 +308,14 @@ fn compile_error_expand( | |||
294 | _ => mbe::ExpandError::BindingError("`compile_error!` argument must be a string".into()), | 308 | _ => mbe::ExpandError::BindingError("`compile_error!` argument must be a string".into()), |
295 | }; | 309 | }; |
296 | 310 | ||
297 | ExpandResult { value: Some((quote! {}, FragmentKind::Items)), err: Some(err) } | 311 | ExpandResult { value: Some(ExpandedEager::new(quote! {}, FragmentKind::Items)), err: Some(err) } |
298 | } | 312 | } |
299 | 313 | ||
300 | fn concat_expand( | 314 | fn concat_expand( |
301 | _db: &dyn AstDatabase, | 315 | _db: &dyn AstDatabase, |
302 | _arg_id: EagerMacroId, | 316 | _arg_id: EagerMacroId, |
303 | tt: &tt::Subtree, | 317 | tt: &tt::Subtree, |
304 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 318 | ) -> ExpandResult<Option<ExpandedEager>> { |
305 | let mut err = None; | 319 | let mut err = None; |
306 | let mut text = String::new(); | 320 | let mut text = String::new(); |
307 | for (i, t) in tt.token_trees.iter().enumerate() { | 321 | for (i, t) in tt.token_trees.iter().enumerate() { |
@@ -325,7 +339,7 @@ fn concat_expand( | |||
325 | } | 339 | } |
326 | } | 340 | } |
327 | } | 341 | } |
328 | ExpandResult { value: Some((quote!(#text), FragmentKind::Expr)), err } | 342 | ExpandResult { value: Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr)), err } |
329 | } | 343 | } |
330 | 344 | ||
331 | fn relative_file( | 345 | fn relative_file( |
@@ -361,21 +375,27 @@ fn include_expand( | |||
361 | db: &dyn AstDatabase, | 375 | db: &dyn AstDatabase, |
362 | arg_id: EagerMacroId, | 376 | arg_id: EagerMacroId, |
363 | tt: &tt::Subtree, | 377 | tt: &tt::Subtree, |
364 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 378 | ) -> ExpandResult<Option<ExpandedEager>> { |
365 | let res = (|| { | 379 | let res = (|| { |
366 | let path = parse_string(tt)?; | 380 | let path = parse_string(tt)?; |
367 | let file_id = relative_file(db, arg_id.into(), &path, false)?; | 381 | let file_id = relative_file(db, arg_id.into(), &path, false)?; |
368 | 382 | ||
369 | Ok(parse_to_token_tree(&db.file_text(file_id)) | 383 | let subtree = parse_to_token_tree(&db.file_text(file_id)) |
370 | .ok_or_else(|| mbe::ExpandError::ConversionError)? | 384 | .ok_or_else(|| mbe::ExpandError::ConversionError)? |
371 | .0) | 385 | .0; |
386 | Ok((subtree, file_id)) | ||
372 | })(); | 387 | })(); |
373 | 388 | ||
374 | match res { | 389 | match res { |
375 | Ok(res) => { | 390 | Ok((subtree, file_id)) => { |
376 | // FIXME: | 391 | // FIXME: |
377 | // Handle include as expression | 392 | // Handle include as expression |
378 | ExpandResult::ok(Some((res, FragmentKind::Items))) | 393 | |
394 | ExpandResult::ok(Some(ExpandedEager { | ||
395 | subtree, | ||
396 | fragment: FragmentKind::Items, | ||
397 | included_file: Some(file_id), | ||
398 | })) | ||
379 | } | 399 | } |
380 | Err(e) => ExpandResult::only_err(e), | 400 | Err(e) => ExpandResult::only_err(e), |
381 | } | 401 | } |
@@ -385,7 +405,7 @@ fn include_bytes_expand( | |||
385 | _db: &dyn AstDatabase, | 405 | _db: &dyn AstDatabase, |
386 | _arg_id: EagerMacroId, | 406 | _arg_id: EagerMacroId, |
387 | tt: &tt::Subtree, | 407 | tt: &tt::Subtree, |
388 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 408 | ) -> ExpandResult<Option<ExpandedEager>> { |
389 | if let Err(e) = parse_string(tt) { | 409 | if let Err(e) = parse_string(tt) { |
390 | return ExpandResult::only_err(e); | 410 | return ExpandResult::only_err(e); |
391 | } | 411 | } |
@@ -398,14 +418,14 @@ fn include_bytes_expand( | |||
398 | id: tt::TokenId::unspecified(), | 418 | id: tt::TokenId::unspecified(), |
399 | }))], | 419 | }))], |
400 | }; | 420 | }; |
401 | ExpandResult::ok(Some((res, FragmentKind::Expr))) | 421 | ExpandResult::ok(Some(ExpandedEager::new(res, FragmentKind::Expr))) |
402 | } | 422 | } |
403 | 423 | ||
404 | fn include_str_expand( | 424 | fn include_str_expand( |
405 | db: &dyn AstDatabase, | 425 | db: &dyn AstDatabase, |
406 | arg_id: EagerMacroId, | 426 | arg_id: EagerMacroId, |
407 | tt: &tt::Subtree, | 427 | tt: &tt::Subtree, |
408 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 428 | ) -> ExpandResult<Option<ExpandedEager>> { |
409 | let path = match parse_string(tt) { | 429 | let path = match parse_string(tt) { |
410 | Ok(it) => it, | 430 | Ok(it) => it, |
411 | Err(e) => return ExpandResult::only_err(e), | 431 | Err(e) => return ExpandResult::only_err(e), |
@@ -418,14 +438,14 @@ fn include_str_expand( | |||
418 | let file_id = match relative_file(db, arg_id.into(), &path, true) { | 438 | let file_id = match relative_file(db, arg_id.into(), &path, true) { |
419 | Ok(file_id) => file_id, | 439 | Ok(file_id) => file_id, |
420 | Err(_) => { | 440 | Err(_) => { |
421 | return ExpandResult::ok(Some((quote!(""), FragmentKind::Expr))); | 441 | return ExpandResult::ok(Some(ExpandedEager::new(quote!(""), FragmentKind::Expr))); |
422 | } | 442 | } |
423 | }; | 443 | }; |
424 | 444 | ||
425 | let text = db.file_text(file_id); | 445 | let text = db.file_text(file_id); |
426 | let text = &*text; | 446 | let text = &*text; |
427 | 447 | ||
428 | ExpandResult::ok(Some((quote!(#text), FragmentKind::Expr))) | 448 | ExpandResult::ok(Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr))) |
429 | } | 449 | } |
430 | 450 | ||
431 | fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> { | 451 | fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> { |
@@ -437,7 +457,7 @@ fn env_expand( | |||
437 | db: &dyn AstDatabase, | 457 | db: &dyn AstDatabase, |
438 | arg_id: EagerMacroId, | 458 | arg_id: EagerMacroId, |
439 | tt: &tt::Subtree, | 459 | tt: &tt::Subtree, |
440 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 460 | ) -> ExpandResult<Option<ExpandedEager>> { |
441 | let key = match parse_string(tt) { | 461 | let key = match parse_string(tt) { |
442 | Ok(it) => it, | 462 | Ok(it) => it, |
443 | Err(e) => return ExpandResult::only_err(e), | 463 | Err(e) => return ExpandResult::only_err(e), |
@@ -461,14 +481,14 @@ fn env_expand( | |||
461 | }); | 481 | }); |
462 | let expanded = quote! { #s }; | 482 | let expanded = quote! { #s }; |
463 | 483 | ||
464 | ExpandResult { value: Some((expanded, FragmentKind::Expr)), err } | 484 | ExpandResult { value: Some(ExpandedEager::new(expanded, FragmentKind::Expr)), err } |
465 | } | 485 | } |
466 | 486 | ||
467 | fn option_env_expand( | 487 | fn option_env_expand( |
468 | db: &dyn AstDatabase, | 488 | db: &dyn AstDatabase, |
469 | arg_id: EagerMacroId, | 489 | arg_id: EagerMacroId, |
470 | tt: &tt::Subtree, | 490 | tt: &tt::Subtree, |
471 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 491 | ) -> ExpandResult<Option<ExpandedEager>> { |
472 | let key = match parse_string(tt) { | 492 | let key = match parse_string(tt) { |
473 | Ok(it) => it, | 493 | Ok(it) => it, |
474 | Err(e) => return ExpandResult::only_err(e), | 494 | Err(e) => return ExpandResult::only_err(e), |
@@ -479,7 +499,7 @@ fn option_env_expand( | |||
479 | Some(s) => quote! { std::option::Some(#s) }, | 499 | Some(s) => quote! { std::option::Some(#s) }, |
480 | }; | 500 | }; |
481 | 501 | ||
482 | ExpandResult::ok(Some((expanded, FragmentKind::Expr))) | 502 | ExpandResult::ok(Some(ExpandedEager::new(expanded, FragmentKind::Expr))) |
483 | } | 503 | } |
484 | 504 | ||
485 | #[cfg(test)] | 505 | #[cfg(test)] |
@@ -553,16 +573,18 @@ mod tests { | |||
553 | subtree: Arc::new(parsed_args.clone()), | 573 | subtree: Arc::new(parsed_args.clone()), |
554 | krate, | 574 | krate, |
555 | call: call_id, | 575 | call: call_id, |
576 | included_file: None, | ||
556 | } | 577 | } |
557 | }); | 578 | }); |
558 | 579 | ||
559 | let (subtree, fragment) = expander.expand(&db, arg_id, &parsed_args).value.unwrap(); | 580 | let expanded = expander.expand(&db, arg_id, &parsed_args).value.unwrap(); |
560 | let eager = EagerCallLoc { | 581 | let eager = EagerCallLoc { |
561 | def, | 582 | def, |
562 | fragment, | 583 | fragment: expanded.fragment, |
563 | subtree: Arc::new(subtree), | 584 | subtree: Arc::new(expanded.subtree), |
564 | krate, | 585 | krate, |
565 | call: call_id, | 586 | call: call_id, |
587 | included_file: expanded.included_file, | ||
566 | }; | 588 | }; |
567 | 589 | ||
568 | let id: MacroCallId = db.intern_eager_expansion(eager).into(); | 590 | let id: MacroCallId = db.intern_eager_expansion(eager).into(); |
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs index 04f374a29..9eedc8461 100644 --- a/crates/hir_expand/src/eager.rs +++ b/crates/hir_expand/src/eager.rs | |||
@@ -124,6 +124,7 @@ pub fn expand_eager_macro( | |||
124 | subtree: Arc::new(parsed_args.clone()), | 124 | subtree: Arc::new(parsed_args.clone()), |
125 | krate, | 125 | krate, |
126 | call: call_id, | 126 | call: call_id, |
127 | included_file: None, | ||
127 | } | 128 | } |
128 | }); | 129 | }); |
129 | let arg_file_id: MacroCallId = arg_id.into(); | 130 | let arg_file_id: MacroCallId = arg_id.into(); |
@@ -143,9 +144,15 @@ pub fn expand_eager_macro( | |||
143 | if let MacroDefKind::BuiltInEager(eager, _) = def.kind { | 144 | if let MacroDefKind::BuiltInEager(eager, _) = def.kind { |
144 | let res = eager.expand(db, arg_id, &subtree); | 145 | let res = eager.expand(db, arg_id, &subtree); |
145 | 146 | ||
146 | let (subtree, fragment) = diagnostic_sink.expand_result_option(res)?; | 147 | let expanded = diagnostic_sink.expand_result_option(res)?; |
147 | let eager = | 148 | let eager = EagerCallLoc { |
148 | EagerCallLoc { def, fragment, subtree: Arc::new(subtree), krate, call: call_id }; | 149 | def, |
150 | fragment: expanded.fragment, | ||
151 | subtree: Arc::new(expanded.subtree), | ||
152 | krate, | ||
153 | call: call_id, | ||
154 | included_file: expanded.included_file, | ||
155 | }; | ||
149 | 156 | ||
150 | Ok(db.intern_eager_expansion(eager)) | 157 | Ok(db.intern_eager_expansion(eager)) |
151 | } else { | 158 | } else { |
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs index f49fd4fda..b8045fda9 100644 --- a/crates/hir_expand/src/lib.rs +++ b/crates/hir_expand/src/lib.rs | |||
@@ -84,7 +84,11 @@ impl HirFileId { | |||
84 | } | 84 | } |
85 | MacroCallId::EagerMacro(id) => { | 85 | MacroCallId::EagerMacro(id) => { |
86 | let loc = db.lookup_intern_eager_expansion(id); | 86 | let loc = db.lookup_intern_eager_expansion(id); |
87 | loc.call.file_id | 87 | if let Some(included_file) = loc.included_file { |
88 | return included_file; | ||
89 | } else { | ||
90 | loc.call.file_id | ||
91 | } | ||
88 | } | 92 | } |
89 | }; | 93 | }; |
90 | file_id.original_file(db) | 94 | file_id.original_file(db) |
@@ -188,6 +192,21 @@ impl HirFileId { | |||
188 | } | 192 | } |
189 | } | 193 | } |
190 | } | 194 | } |
195 | |||
196 | /// Return whether this file is an include macro | ||
197 | pub fn is_include_macro(&self, db: &dyn db::AstDatabase) -> bool { | ||
198 | match self.0 { | ||
199 | HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id { | ||
200 | MacroCallId::EagerMacro(id) => { | ||
201 | let loc = db.lookup_intern_eager_expansion(id); | ||
202 | return loc.included_file.is_some(); | ||
203 | } | ||
204 | _ => {} | ||
205 | }, | ||
206 | _ => {} | ||
207 | } | ||
208 | false | ||
209 | } | ||
191 | } | 210 | } |
192 | 211 | ||
193 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 212 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -315,6 +334,8 @@ pub struct EagerCallLoc { | |||
315 | pub(crate) subtree: Arc<tt::Subtree>, | 334 | pub(crate) subtree: Arc<tt::Subtree>, |
316 | pub(crate) krate: CrateId, | 335 | pub(crate) krate: CrateId, |
317 | pub(crate) call: AstId<ast::MacroCall>, | 336 | pub(crate) call: AstId<ast::MacroCall>, |
337 | // The included file ID of the include macro. | ||
338 | pub(crate) included_file: Option<FileId>, | ||
318 | } | 339 | } |
319 | 340 | ||
320 | /// ExpansionInfo mainly describes how to map text range between src and expanded macro | 341 | /// ExpansionInfo mainly describes how to map text range between src and expanded macro |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 17849d552..05cbde4e3 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -514,10 +514,10 @@ impl<'a> InferenceContext<'a> { | |||
514 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); | 514 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); |
515 | if let Some(box_) = self.resolve_boxed_box() { | 515 | if let Some(box_) = self.resolve_boxed_box() { |
516 | let mut sb = | 516 | let mut sb = |
517 | Substitution::builder(generics(self.db.upcast(), box_.into()).len()); | 517 | Substitution::build_for_generics(&generics(self.db.upcast(), box_.into())); |
518 | sb = sb.push(inner_ty); | 518 | sb = sb.push(inner_ty); |
519 | match self.db.generic_defaults(box_.into()).as_ref() { | 519 | match self.db.generic_defaults(box_.into()).get(1) { |
520 | [_, alloc_ty, ..] if !alloc_ty.value.is_unknown() => { | 520 | Some(alloc_ty) if !alloc_ty.value.is_unknown() && sb.remaining() > 0 => { |
521 | sb = sb.push(alloc_ty.value.clone()); | 521 | sb = sb.push(alloc_ty.value.clone()); |
522 | } | 522 | } |
523 | _ => (), | 523 | _ => (), |
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index ec491648f..474363709 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs | |||
@@ -13,7 +13,9 @@ use hir_expand::name::Name; | |||
13 | 13 | ||
14 | use super::{BindingMode, Expectation, InferenceContext}; | 14 | use super::{BindingMode, Expectation, InferenceContext}; |
15 | use crate::{ | 15 | use crate::{ |
16 | lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substitution, Ty, TyKind, | 16 | lower::lower_to_chalk_mutability, |
17 | utils::{generics, variant_data}, | ||
18 | Interner, Substitution, Ty, TyKind, | ||
17 | }; | 19 | }; |
18 | 20 | ||
19 | impl<'a> InferenceContext<'a> { | 21 | impl<'a> InferenceContext<'a> { |
@@ -233,13 +235,31 @@ impl<'a> InferenceContext<'a> { | |||
233 | Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())), | 235 | Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())), |
234 | Pat::Box { inner } => match self.resolve_boxed_box() { | 236 | Pat::Box { inner } => match self.resolve_boxed_box() { |
235 | Some(box_adt) => { | 237 | Some(box_adt) => { |
236 | let inner_expected = match expected.as_adt() { | 238 | let (inner_ty, alloc_ty) = match expected.as_adt() { |
237 | Some((adt, substs)) if adt == box_adt => substs.as_single().clone(), | 239 | Some((adt, subst)) if adt == box_adt => { |
238 | _ => self.result.standard_types.unknown.clone(), | 240 | (subst[0].clone(), subst.get(1).cloned()) |
241 | } | ||
242 | _ => (self.result.standard_types.unknown.clone(), None), | ||
239 | }; | 243 | }; |
240 | 244 | ||
241 | let inner_ty = self.infer_pat(*inner, &inner_expected, default_bm); | 245 | let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm); |
242 | Ty::adt_ty(box_adt, Substitution::single(inner_ty)) | 246 | let mut sb = Substitution::build_for_generics(&generics( |
247 | self.db.upcast(), | ||
248 | box_adt.into(), | ||
249 | )); | ||
250 | sb = sb.push(inner_ty); | ||
251 | if sb.remaining() == 1 { | ||
252 | sb = sb.push(match alloc_ty { | ||
253 | Some(alloc_ty) if !alloc_ty.is_unknown() => alloc_ty, | ||
254 | _ => match self.db.generic_defaults(box_adt.into()).get(1) { | ||
255 | Some(alloc_ty) if !alloc_ty.value.is_unknown() => { | ||
256 | alloc_ty.value.clone() | ||
257 | } | ||
258 | _ => self.table.new_type_var(), | ||
259 | }, | ||
260 | }); | ||
261 | } | ||
262 | Ty::adt_ty(box_adt, sb.build()) | ||
243 | } | 263 | } |
244 | None => self.err_ty(), | 264 | None => self.err_ty(), |
245 | }, | 265 | }, |
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs index c1e605740..12951fb16 100644 --- a/crates/hir_ty/src/tests/macros.rs +++ b/crates/hir_ty/src/tests/macros.rs | |||
@@ -607,6 +607,29 @@ fn bar() -> u32 {0} | |||
607 | } | 607 | } |
608 | 608 | ||
609 | #[test] | 609 | #[test] |
610 | fn infer_builtin_macros_include_child_mod() { | ||
611 | check_types( | ||
612 | r#" | ||
613 | //- /main.rs | ||
614 | #[rustc_builtin_macro] | ||
615 | macro_rules! include {() => {}} | ||
616 | |||
617 | include!("f/foo.rs"); | ||
618 | |||
619 | fn main() { | ||
620 | bar::bar(); | ||
621 | } //^ u32 | ||
622 | |||
623 | //- /f/foo.rs | ||
624 | pub mod bar; | ||
625 | |||
626 | //- /f/bar.rs | ||
627 | pub fn bar() -> u32 {0} | ||
628 | "#, | ||
629 | ); | ||
630 | } | ||
631 | |||
632 | #[test] | ||
610 | fn infer_builtin_macros_include_str() { | 633 | fn infer_builtin_macros_include_str() { |
611 | check_types( | 634 | check_types( |
612 | r#" | 635 | r#" |
diff --git a/crates/hir_ty/src/tests/patterns.rs b/crates/hir_ty/src/tests/patterns.rs index 5da19ba5f..85a28e76b 100644 --- a/crates/hir_ty/src/tests/patterns.rs +++ b/crates/hir_ty/src/tests/patterns.rs | |||
@@ -658,6 +658,28 @@ fn slice_tail_pattern() { | |||
658 | fn box_pattern() { | 658 | fn box_pattern() { |
659 | check_infer( | 659 | check_infer( |
660 | r#" | 660 | r#" |
661 | pub struct Global; | ||
662 | #[lang = "owned_box"] | ||
663 | pub struct Box<T, A = Global>(T); | ||
664 | |||
665 | fn foo(params: Box<i32>) { | ||
666 | match params { | ||
667 | box integer => {} | ||
668 | } | ||
669 | } | ||
670 | "#, | ||
671 | expect![[r#" | ||
672 | 83..89 'params': Box<i32, Global> | ||
673 | 101..155 '{ ... } }': () | ||
674 | 107..153 'match ... }': () | ||
675 | 113..119 'params': Box<i32, Global> | ||
676 | 130..141 'box integer': Box<i32, Global> | ||
677 | 134..141 'integer': i32 | ||
678 | 145..147 '{}': () | ||
679 | "#]], | ||
680 | ); | ||
681 | check_infer( | ||
682 | r#" | ||
661 | #[lang = "owned_box"] | 683 | #[lang = "owned_box"] |
662 | pub struct Box<T>(T); | 684 | pub struct Box<T>(T); |
663 | 685 | ||
diff --git a/crates/ide_db/src/helpers/insert_use.rs b/crates/ide_db/src/helpers/insert_use.rs index 9e0cb91c3..37acf95f0 100644 --- a/crates/ide_db/src/helpers/insert_use.rs +++ b/crates/ide_db/src/helpers/insert_use.rs | |||
@@ -14,10 +14,12 @@ use syntax::{ | |||
14 | AstToken, InsertPosition, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken, | 14 | AstToken, InsertPosition, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | pub use hir::PrefixKind; | ||
18 | |||
17 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] | 19 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
18 | pub struct InsertUseConfig { | 20 | pub struct InsertUseConfig { |
19 | pub merge: Option<MergeBehavior>, | 21 | pub merge: Option<MergeBehavior>, |
20 | pub prefix_kind: hir::PrefixKind, | 22 | pub prefix_kind: PrefixKind, |
21 | pub group: bool, | 23 | pub group: bool, |
22 | } | 24 | } |
23 | 25 | ||
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 8f541976e..5c88c3a9b 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -10,10 +10,9 @@ | |||
10 | use std::{ffi::OsString, iter, path::PathBuf}; | 10 | use std::{ffi::OsString, iter, path::PathBuf}; |
11 | 11 | ||
12 | use flycheck::FlycheckConfig; | 12 | use flycheck::FlycheckConfig; |
13 | use hir::PrefixKind; | ||
14 | use ide::{AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig}; | 13 | use ide::{AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig}; |
15 | use ide_db::helpers::{ | 14 | use ide_db::helpers::{ |
16 | insert_use::{InsertUseConfig, MergeBehavior}, | 15 | insert_use::{InsertUseConfig, MergeBehavior, PrefixKind}, |
17 | SnippetCap, | 16 | SnippetCap, |
18 | }; | 17 | }; |
19 | use lsp_types::{ClientCapabilities, MarkupKind}; | 18 | use lsp_types::{ClientCapabilities, MarkupKind}; |
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 1ddea9278..c1ca7ff9b 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -1073,9 +1073,11 @@ pub(crate) fn rename_error(err: RenameError) -> crate::LspError { | |||
1073 | mod tests { | 1073 | mod tests { |
1074 | use std::sync::Arc; | 1074 | use std::sync::Arc; |
1075 | 1075 | ||
1076 | use hir::PrefixKind; | ||
1077 | use ide::Analysis; | 1076 | use ide::Analysis; |
1078 | use ide_db::helpers::{insert_use::InsertUseConfig, SnippetCap}; | 1077 | use ide_db::helpers::{ |
1078 | insert_use::{InsertUseConfig, PrefixKind}, | ||
1079 | SnippetCap, | ||
1080 | }; | ||
1079 | 1081 | ||
1080 | use super::*; | 1082 | use super::*; |
1081 | 1083 | ||
diff --git a/docs/dev/README.md b/docs/dev/README.md index b91013f13..57162a47d 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md | |||
@@ -226,6 +226,9 @@ If the GitHub Actions release fails because of a transient problem like a timeou | |||
226 | If it fails because of something that needs to be fixed, remove the release tag (if needed), fix the problem, then start over. | 226 | If it fails because of something that needs to be fixed, remove the release tag (if needed), fix the problem, then start over. |
227 | Make sure to remove the new changelog post created when running `cargo xtask release` a second time. | 227 | Make sure to remove the new changelog post created when running `cargo xtask release` a second time. |
228 | 228 | ||
229 | We release "nightly" every night automatically and promote the latest nightly to "stable" manually, every week. | ||
230 | We don't do "patch" releases, unless something truly egregious comes up. | ||
231 | |||
229 | # Permissions | 232 | # Permissions |
230 | 233 | ||
231 | There are three sets of people with extra permissions: | 234 | There are three sets of people with extra permissions: |
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc index dba2197de..8656dd1da 100644 --- a/docs/user/manual.adoc +++ b/docs/user/manual.adoc | |||
@@ -516,6 +516,20 @@ See https://github.com/rust-analyzer/rust-project.json-example for a small examp | |||
516 | 516 | ||
517 | You can set `RA_LOG` environmental variable to `rust_analyzer=info` to inspect how rust-analyzer handles config and project loading. | 517 | You can set `RA_LOG` environmental variable to `rust_analyzer=info` to inspect how rust-analyzer handles config and project loading. |
518 | 518 | ||
519 | == Security | ||
520 | |||
521 | At the moment, rust-analyzer assumes that all code is trusted. | ||
522 | Here is a **non-exhaustive** list of ways to make rust-analyzer execute arbitrary code: | ||
523 | |||
524 | * proc macros and build scripts are executed by default | ||
525 | * `.cargo/config` can override `rustc` with an arbitrary executable | ||
526 | * VS Code plugin reads configuration from project directory, and that can be used to override paths to various executables, like `rustfmt` or `rust-analyzer` itself. | ||
527 | * rust-analyzer's syntax trees library uses a lot of `unsafe` and hasn't been properly audited for memory safety. | ||
528 | |||
529 | rust-analyzer itself doesn't access the network. | ||
530 | The VS Code plugin doesn't access the network unless the nightly channel is selected in the settings. | ||
531 | In that case, the plugin uses the GitHub API to check for and download updates. | ||
532 | |||
519 | == Features | 533 | == Features |
520 | 534 | ||
521 | include::./generated_features.adoc[] | 535 | include::./generated_features.adoc[] |