Repository navigation
rustc crashes when attempting to match a &str #3222
Description
Activity
#3316 (since it's not obvious what pull request the commit is from).
@nikomatsakis , @brson said you had reservations about the pull request? I'm not even sure if the code should compile or not.
About the code: I think it must compile. The following code compile and execute well:
fn f(s: &str) { if s == "a" {} }You must be able to match a borrowed string with constant. Of course, the syntax may be different but, first, this one is consistent with a if test, second, the syntax is understood by the compiler, only the generation has a problem.
About the reservations: I'm absolutely sure that my analysis of the problem is good and that what I did will work. However, there are two problems.
A first minor one is that I had a test in compile_submatch to see if the match expression is or is not a borrowed string. It's not orthogonal but it works.
A second more serious problem is that I substitute:
rslt(bcx, consts::const_expr(ccx, l))
by
trans_temp_expr(bcx, l)
I did that to be consistent with a if test. However, I think that the generated LLVM bytecode is slightly different from the previous one for other cases (for example when you match unique strings). I wonder if the solution could be to modify const_expr instead of calling trans_temp_expr.
For someone which didn't write the LLVM generation it's quite difficult to be sure to write something consistent.
The major problem is that when you infer the abstract syntax tree, you didn't generate an inferred tree. Doing this, some of the job did during the inference must be done again during the LLVM generation: you must test a lot of special cases when you generate. That's why, for someone who discover your LLVM generation, it's quite difficult to be sure that a patch is consistent with the former code.About the strings: during one week, I really wonder why you used such a syntax. I finally understood that strings can be modified. Even if the characters are not mutable, a string can grow. I think that most the problems come from that. Most of the time, a string is never modified. You can concatenate strings, take sub strings, ... Each time you generate a new string and you don't modify existing strings. In Java, you have the StringBuffer class to build dynamically a string. For all other cases, you use a String which is constant.
Now, the string syntax is not orthogonal nor consistent. If you write:
@int
you define a shared box which held an integer but if you write:
@str
you define a shared string. The integer can be deferenced but not the string. It's not easy to use and, most of all, it's not orthogonal.
I think that a good solution should be to define a new type: str which would hold a constant string and would replace most of the ~str, @str and &str. Then you could add an other new type str_buf (or something like that). This type would nearly behave like a [mut u8]. The only difference would be that when you add one UTF8 character, several bytes would be added. The other advantage of this is that the generated LLVM code would be more efficient.
I insist a lot because Rust is very well designed. It may be the only new language I would like to use but only if the string model become consistent.With a consistent string syntax, this issue may has never appeared.
- added a commit that references this issue
on Sep 5, 2012 The reason why
@strcannot be dereferenced is thatstris dynamically sized. If we allowed strings to be copied to the stack like ints can, then we'd have to add dynamic allocas and that would break the segmented stacks model. Other than that,@intand@strare intended to be conceptually very similar.Your proposal would basically rename
stras it exists today tostr_bufand make it mutable. Remember,[mut u8]is also a dynamically sized type, so it's really~[mut u8],@[mut u8], and&[mut u8]; thus there would be three str_bufs,~str_buf,@str_buf, and&str_buf. Your new typestrwould be equivalent to&static/strtoday. All of this would add complexity to the language for little gain, as I see it. I also don't see how the generated code would be more efficient; adding to a~[mut u8]is exactly the same operation as adding to a~str.That said, you're right that building up a unique string by appending to it is confusing. We should add a
StringBuffertype to the standard library.- added a commit that references this issue
on Sep 5, 2012 #3316 closes this. If you want to suggest additional enhancements to strings, please open a separate issue for it :-) (And thanks for the patch!)
- added a commit that references this issue
on May 15, 2021 - added a commit that references this issue
on Dec 17, 2023 - added a commit that references this issue
on Jul 29, 2024 - added a commit that references this issue
on Aug 21, 2026
Given this test case:
rustc fails with:
I have no idea if this code should work or not. If it shouldn't work, I think rustc should emit a nicer error message.