From ceb13a0494bed37b233bcaaeee70bfae5fefeccc Mon Sep 17 00:00:00 2001 From: Marco Groppo Date: Sun, 24 Nov 2019 19:02:04 +0100 Subject: Fix panic during the expansion of `column!` --- crates/ra_hir_expand/src/builtin_macro.rs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'crates/ra_hir_expand') diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index c0e0436c0..9b5305a80 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -57,16 +57,21 @@ fn to_line_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize let text = db.file_text(file_id); let mut line_num = 1; + let pos = pos.to_usize(); + if pos > text.len() { + // FIXME: `pos` at the moment could be an offset inside the "wrong" file + // in this case, when we know it's wrong, we return a dummy value + return 0; + } // Count line end for (i, c) in text.chars().enumerate() { - if i == pos.to_usize() { + if i == pos { break; } if c == '\n' { line_num += 1; } } - line_num } @@ -118,15 +123,21 @@ fn to_col_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize // FIXME: Use expansion info let file_id = file.original_file(db); let text = db.file_text(file_id); - let mut col_num = 1; - for c in text[..pos.to_usize()].chars().rev() { + let pos = pos.to_usize(); + if pos > text.len() { + // FIXME: `pos` at the moment could be an offset inside the "wrong" file + // in this case we return a dummy value so that we don't `panic!` + return 0; + } + + let mut col_num = 1; + for c in text[..pos].chars().rev() { if c == '\n' { break; } col_num = col_num + 1; } - col_num } -- cgit v1.2.3 From 67d3600f59684b4fe3eabe7036fe7e7ce4db3257 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Sun, 24 Nov 2019 19:01:51 -0500 Subject: Expand compile_error! --- crates/ra_hir_expand/src/builtin_macro.rs | 38 +++++++++++++++++++++++++++++++ crates/ra_hir_expand/src/name.rs | 1 + 2 files changed, 39 insertions(+) (limited to 'crates/ra_hir_expand') diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index c0e0436c0..ffd796ae2 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -46,6 +46,7 @@ macro_rules! register_builtin { register_builtin! { (COLUMN_MACRO, Column) => column_expand, + (COMPILE_ERROR_MACRO, CompileError) => compile_error_expand, (FILE_MACRO, File) => file_expand, (LINE_MACRO, Line) => line_expand, (STRINGIFY_MACRO, Stringify) => stringify_expand @@ -172,6 +173,26 @@ fn file_expand( Ok(expanded) } +fn compile_error_expand( + _db: &dyn AstDatabase, + _id: MacroCallId, + tt: &tt::Subtree, +) -> Result { + if tt.count() == 1 { + match &tt.token_trees[0] { + tt::TokenTree::Leaf(tt::Leaf::Literal(it)) => { + let s = it.text.as_str(); + if s.contains(r#"""#) { + return Ok(quote! { loop { #it }}); + } + } + _ => {} + }; + } + + Err(mbe::ExpandError::BindingError("Must be a string".into())) +} + #[cfg(test)] mod tests { use super::*; @@ -259,4 +280,21 @@ mod tests { assert_eq!(expanded, "\"\""); } + + #[test] + fn test_compile_error_expand() { + let expanded = expand_builtin_macro( + r#" + #[rustc_builtin_macro] + macro_rules! compile_error { + ($msg:expr) => ({ /* compiler built-in */ }); + ($msg:expr,) => ({ /* compiler built-in */ }) + } + compile_error!("error!"); +"#, + BuiltinFnLikeExpander::CompileError, + ); + + assert_eq!(expanded, r#"loop{"error!"}"#); + } } diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index eaea7a6a8..7824489d7 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs @@ -144,5 +144,6 @@ pub const BOX_TYPE: Name = Name::new_inline_ascii(3, b"Box"); // Builtin Macros pub const FILE_MACRO: Name = Name::new_inline_ascii(4, b"file"); pub const COLUMN_MACRO: Name = Name::new_inline_ascii(6, b"column"); +pub const COMPILE_ERROR_MACRO: Name = Name::new_inline_ascii(13, b"compile_error"); pub const LINE_MACRO: Name = Name::new_inline_ascii(4, b"line"); pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(9, b"stringify"); -- cgit v1.2.3