Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upBetter diagnostics when concatenating strings #39018
Comments
Manishearth
added
the
A-diagnostics
label
Jan 12, 2017
This comment has been minimized.
This comment has been minimized.
|
I'd like to take a stab at this if I could get some guidance as to where things in the compiler need to be changed and how. |
Manishearth
added
the
E-easy
label
Jan 12, 2017
This comment has been minimized.
This comment has been minimized.
|
Sure! What you need to do is find the place in the code which emits the error on Somewhere there you'll want to add an if checking that the operation is add, and then check that the LHS and RHS are both Then, |
This comment has been minimized.
This comment has been minimized.
|
I'll be home soon so I'll get working on it then |
This comment has been minimized.
This comment has been minimized.
|
Cool. You can ask me (or others) for help in #rust-internals if you need it. |
This comment has been minimized.
This comment has been minimized.
|
I found where after a bit of prodding so I think I have this part but if I run into problems I'll definitely jump on #rust-internals |
This comment has been minimized.
This comment has been minimized.
|
For the It could even apply to anything that wants |
This comment has been minimized.
This comment has been minimized.
|
Yeah. It's just that the concatenation stuff is handled separately. I was planning on investigating this (or help someone investigate this) after this bug is fixed, by refactoring the functionality introduced here into a separate function that gets used in multiple error cases. |
This comment has been minimized.
This comment has been minimized.
|
@Manishearth here's the WIP that I have now: mgattozzi@007d459 Here's the output though:
It seems the |
This comment has been minimized.
This comment has been minimized.
|
Hmm, You also might want to restructure the code so that the "an implementation of |
This comment has been minimized.
This comment has been minimized.
|
Let me try it out with string literals to see if I get something different. |
This comment has been minimized.
This comment has been minimized.
|
No it doesn't work. It looks like unless we identify what |
This comment has been minimized.
This comment has been minimized.
|
ugh. You could check the AST if it's a literal but that's not so great. Would there be a way of extracting this info? @eddyb ? |
This comment has been minimized.
This comment has been minimized.
|
Checking for a literal is okay-ish. You might be able to type-check the RHS before emitting the error, giving you the missing information. cc @nikomatsakis |
This comment has been minimized.
This comment has been minimized.
|
Yeah, type checking the RHS is what I want to do, but I don't know how |
This comment has been minimized.
This comment has been minimized.
|
It's this call. If I were you I would keep an |
This comment has been minimized.
This comment has been minimized.
|
@eddyb thanks for the tip. I'm going to work out a rough (but somewhat naive) implementation that works and then hopefully get that refined from there with some guidance. |
This comment has been minimized.
This comment has been minimized.
|
@Manishearth My most recent commit got it working now. While it's a bit naive (we could return early) it's doing what's needed for now. I think we can move from here into the next few parts of the issue. |
This comment has been minimized.
This comment has been minimized.
|
Okay, now try to suggest using Make the error message mention explicitly that the first operand must be a |
This comment has been minimized.
This comment has been minimized.
|
I've got it outputting a message but I'd like it to be the string literal with
How would I get it so that only the "Hello" part prints? Also having it underlined or with more spaces on the line for readability would be nice as well, but I think that's secondary compared to getting this part done right. |
This comment has been minimized.
This comment has been minimized.
|
Don't extract the string literal at all. There might not be one. Just use
|
This comment has been minimized.
This comment has been minimized.
|
Ahhh okay I see what you're saying after digging through some other code for examples. When I get this part working I'll let you know. |
This comment has been minimized.
This comment has been minimized.
|
@Manishearth This gets it working to output the proper help message and works regardless of how many uses of Not sure what to put for the error message when it's destructured in the match statement there. I think next would also be matching on things like |
This comment has been minimized.
This comment has been minimized.
|
Yeah, probably. Refactoring this into a method might help. It's also okay to land with just this one suggestion with a compile-fail test and fix the rest in a separate PR. Regardless, you probably should clean it up a bit and make a WIP PR so that it's easier to leave inline comments.
I don't know what you mean here? |
This comment has been minimized.
This comment has been minimized.
|
Okay sounds good. If you look here it's just a blank string. I'm not sure what to place here in the case where span_to_snippet would fail. |
This comment has been minimized.
This comment has been minimized.
|
Oh. Use a |
This comment has been minimized.
This comment has been minimized.
|
Ahhhh okay got it. I've split it all out into a separate method that just checks for the use of |
This comment has been minimized.
This comment has been minimized.
|
src/tests/compile-fail. Look at other tests in that folder, basically you can annotate errors and suggestions and stuff with |
This comment has been minimized.
This comment has been minimized.
|
Alright I'll play around with it! |
mgattozzi
added a commit
to mgattozzi/rust
that referenced
this issue
Jan 17, 2017
mgattozzi
referenced this issue
Jan 17, 2017
Merged
Add clearer error message using `&str + &str` #39116
This comment has been minimized.
This comment has been minimized.
|
@Manishearth I've cleaned it up and put in a test case. The PR is here #39116 |
This comment has been minimized.
This comment has been minimized.
|
Nice work @mgattozzi! I have to ask though -- maybe we should just make adding strings work like people expect? I think the "fear of allocations" is the only reason not to? If so, it seems a bit overblown to me personally. I feel like I often get annoyed at places that we've made it less convenient to concatenate and manipulate strings because of the cost of allocation -- but usually the code where I'm manipulating strings is not in my hot path, or even if it is I often find I need the allocations anyway, I just have to express them differently. That said, the only major example of this I can come up with something around the way that |
This comment has been minimized.
This comment has been minimized.
|
I am .... conflicted about that. I would not oppose it however. Diagnostics is the path of least resistance here; not contingent on an rfc (I think this would be) and not controversial, so I went that path Similarly, #39029 can be replaced by a language change, I just am not as convinced if I want that language change to want to make an rfc for it. |
This comment has been minimized.
This comment has been minimized.
I thought coherence was the main problem, not the fear? (You can't |
This comment has been minimized.
This comment has been minimized.
|
Thank you @nikomatsakis! Personally I like that Rust is explicit. Sure it's inconvenient to have to add a |
This comment has been minimized.
This comment has been minimized.
Ah, this may be true. I feel like the inability to extend coherence to cover a set of crates is an annoyance I would like to overcome. :(
Certainly there is something of a trade-off involved. |
This comment has been minimized.
This comment has been minimized.
I've often wanted the ability to forward-declare an impl, saying something like #[forward_declare(StringAddition)]
impl Add<str> for str {
type Target = _;
fn add(&self, other: &str) -> Self::Target;
}This generates an instance of a new kind of item with item name and later, #[fills_declaration(core::StringAddition)]
impl Add<str> for str {
type Target = String;
fn add(&self, other: &str) -> String { /* body */}
}The system works the same way lang items do; these forward-declared impls are left dangling and can't be used until someone defines them, and you can only have one definition active (much like how redefining lang items doesn't work). However, from the point of view of coherence and conflict resolution, these impls do exist even if not defined (I'm not sure if any situation arises where this matters outside of Thus, the impl exists in two places at once. From the POV of coherence, it exists in libcore, but from the POV of codegen and type resolution, it exists in libstd. The main purpose is to handle cases like these where you have multiple separate crates that are nevertheless maintained as a single unit. Coherence exists so that I, a Servo developer, am not forced to deal with error messages that must be fixed in, say, hyper (e.g. when I include some other crate and now we have conflicting impls that can't be fixed on the servo-side). But in this case the developers of libstd and libcore are the same and it's fine to punch through coherence for this. Similarly, Servo itself is split into crates for maintainability and compile times, but being able to punch through coherence in the context of servo is pretty useful. Being able to say "I know that this can break if upstream-crate-X changes things, but I am upstream-crate-X and want to do it anyway" is useful. We've had to merge crates before because coherence was making things problematic. |
This comment has been minimized.
This comment has been minimized.
You don't have to do that, just don't mention it, and might as well do the same with the method. |
This comment has been minimized.
This comment has been minimized.
You will have to do something for inherent impls though. I guess you can just define the item name and leave it at that. |
This comment has been minimized.
This comment has been minimized.
|
Well... inherent impls don't do anything other than wrap the items inside, so each one would have to be annotated, and it'd be a bit of a mess. |
This comment has been minimized.
This comment has been minimized.
rocallahan
commented
Jan 17, 2017
|
FWIW I think suggesting |
This comment has been minimized.
This comment has been minimized.
|
It feels to me like That does mean that people might end up doing |
This comment has been minimized.
This comment has been minimized.
|
pre-rfc'd the forward declaration thing in https://internals.rust-lang.org/t/pre-rfc-forward-impls/4628 |
mgattozzi
added a commit
to mgattozzi/rust
that referenced
this issue
Jan 25, 2017
bors
added a commit
that referenced
this issue
Jan 25, 2017
mgattozzi
added a commit
to mgattozzi/rust
that referenced
this issue
Jan 28, 2017
mgattozzi
added a commit
to mgattozzi/rust
that referenced
this issue
Jan 28, 2017
bors
added a commit
that referenced
this issue
Feb 2, 2017
king6cong
added a commit
to king6cong/rust
that referenced
this issue
Feb 3, 2017
This comment has been minimized.
This comment has been minimized.
|
Fixed in #39116 |
Manishearth commentedJan 12, 2017
A lot of people come from other languages and expect
"a" + "b"to work, orx + ywherexandyare bothStrings.We should be suggesting
"a".to_string() + "b"in the first place,x + &yin the second, and in both cases also recommend usingformat!()instead.Context: https://www.reddit.com/r/rust/comments/5nl3fk/rust_severely_disappoints_me/dccdi17/