-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Champion "utf8 string literals" #184
Comments
UTF-8 encodings come with a lot of issues for non-english languages and developers. So this feature might only be a good thing for english developers and a bad idea for everybody else. It might be useful for interop with non-unicode applications, but then I prefer to have an explicit encoding conversation using |
@MovGP0 I think this is related to https://github.com/dotnet/corefxlab/blob/master/docs/specs/parsing.md . UTF8 strings are very common and if you don't have to convert to UTF16 (== .NET strings) and back again you save memory and CPU. |
When UTF-8 string literals are added it would be nice to have UTF-8 version of StringBuilder as well. |
I am quite curious about how it is going to handle the index operator. Does it mean the class need to enumerate and decode bytes to utf8characters inside until it finds the sixth character? Or, are you disallowing the index operator on the UTF8String? Here are the similar questions:
If there no support or optimization for this, I would probably say probably we just need a syntax sugar for converting a string to a byte array with a UTF8 encoding. |
Those questions are better suited for corefx. |
@sumtec and @MovGP0 .NET Micro Framework always had UTF-8 string implementation only, transparent to the developer. It does support trimming and substrings and indexing, although the reverse looping is not optimized (source). It saved memory. You could, however, have the same arguments around "normal" strings with surrogate pairs. |
See #2911 for a minimal specification for this feature. |
Will there be a type that represents potentially invalid UTF-8 strings, like Linux file paths? |
I'm not a fan of this approach as it treats utf8 strings as something other that then needs to be brought in through a side-channel. It seems this fundamentally could not be picked up by a library author. i.e. if i have a library and i'm already using System.String (highly highly likely), i can't switch to utf8 strings because it will break all my consumers. And, if i don't use utf8 strings, similarly my consumers will be less likely to as well since they would not want the costs marshalling to/from all libs. -- I talked to @jcouv about this and the approach that feels like it would be most likely to succeed would be to provide a way to switch the .net runtime to/from utf8 mode (on a process boundary most likely). The benefits here are:
There is a downside in this that often gets brought up. Namely that utf8 strings do have different perf behavior for some ops over strings (namely indexing). However, this doesn't actually seem like a critical problem to me. First, remember that what i'm proposing involves a switch (either opt-in or opt-out) to use ut8 across the board. As such, if someone is in a domain where they index heavily and get a perf hit, they can not use utf8 until they address that problem. Second, i think the problem seems somewhat overblown in terms of how bad it is. We can likely break string indexing up into two domains:
Basically, it feels like there is a path that can get us to a future where almost everyone (final consumers and libraries alike) are on utf8 and the entire ecosystem gets the massive memory savings. It comes at the complexity of having opt-in/out and potentially needing some analyzers/classes for the people using strings in uncommon ways today. However, it seems much better to me than introducing a new utf8 string type that is highly unlikely to be picked up. |
As an example of how we have a problem, take a look at Roslyn itself, including the entire Roslyn API we ship.
How could Roslyn itself possibly get the benefits of utf8 strings?
Effectively, afaict, a project like Roslyn could never move to utf8. And we're one of the projects that would benefit the most here. We likely would save gigabytes of memory on real projects on user boxes. So, as mentioned in teh start, this overall approach seems highly limited and constraining. it will only help projects that are isolated and can completely switch over without having to worry about dependencies. The overall ecosystem will find it nearly impossible to switch. Conversely, the approach I outlined gives a path forward that allows big saving immediately across the board, with appropriate mechanisms for people to deal with rare problems if they arise. Then, if problems do occur in some places, they can be fixed up without holding the rest of the ecosystem back. |
@CyrusNajmabadi Ist there an ongoing discussion on your "side-channel" proposal without introducing a new UTF8String type? I share your concerns about the fragmentation problem a new UTF8String type would bring. |
No clue. @jcouv @gafter is there any hope of this being not a side-channel type? note: personally, i think this is an appropriate hill to die on. It is that important. |
@CyrusNajmabadi That is a question for @orthoxerox Re "Will there be a type that represents potentially invalid UTF-8 strings, like Linux file paths?". Are you asking about |
@gafter will Like, |
@orthoxerox You would have to ask the folks designing those APIs. |
I keep going back and forth on this... @CyrusNajmabadi's concerns are absolutely what I have felt to be the biggest downside, and I share the opinion that indexing into the string is not a major concern: I don't see indexing UTF-16 code units as being much different from indexing UTF-8 code units, as both encodings are variable-length, and so one code unit does not always represent one code point (nevermind that one code point does not always represent one character, depending on what the developer has in mind when they talk about "the third character in this string"). I mean, if you were to ask me, "hey @airbreather, if you were designing C# / .NET from scratch, what encoding would you use to store character data in I'm also not terribly optimistic that this will really bear fruit without also investing significantly in CoreFX to add comprehensive first-class support, like what was done for Ultimately, however, I've settled on a 👍 for this. I personally have a phobia about wasting CPU cycles and virtual memory bytes, so if LDT thinks that, in spite of the concerns raised here, this is something that has a realistic chance of making UTF-8 more of a first-class member of our ecosystem, then I'd be delighted to see this next important step towards breaking the chicken-and-egg feedback loop of:
@CyrusNajmabadi in this example, would it be viable for Roslyn to use
Admittedly, the prospect of ~doubling the public API surface alone may be enough to kill this idea... |
Yes. It seems like it would just be awful :-/ |
DataTips are more interesting - when you hover you might want to immediately see the string for u8 literals, not the bytes. Since data tips rely on presence of source code I think we should be able to analyze the relevant source and infer that a string should be displayed. |
I think you're going to find that this strategy leads to numerous false positives. Just within dotnet/runtime, this strategy would result in false positives in:
The use of heuristics to solve this problem is interesting, but that's subject to the whims of the disassembler author and would necessarily treat some languages (Chinese/Japanese/Korean being the likely candidate) as more user-hostile than English, which is a bad experience. My experience has been that heuristics aren't a good substitute for an agent (the compiler) embedding correct information at build time. |
I guess i don't understand the concept of 'correct'. They're equally correct to me. What it sounds like is more around what the author wrote. But that's not relevant to me as the consumer (for all the other reasons that style are not relevant). If i care about those details, i'll just look at the original source. If i'm working with an arbitrary compiled down representation, then my preference is to follow the style I want, not what the original code was. Indeed, that's more important to me in case a user doesn't use this feature, but i would still like the clarity in the decompiled code for my own readability purposes. |
My point of view is that it is not a goal of IL to accurately represent the original source code, there are other tools for that (like PDBs and Source Link). Also, I can't think of another case where the compiler chooses IL representation based on the needs of decompilers and I don't see a reason why it should start here. |
Aren't the implicit operators introducing a breaking change? Take for example the following code, which with C# 10 compiles fine, but will fail to compile if C# 11 is used. using System;
var helper = new Helper();
helper.Add( "key", "value" );
class Helper
{
public void Add(string key, ReadOnlySpan<char> data) { }
public void Add(string key, ReadOnlySpan<byte> data) { }
} |
@zlatanov there shouldnt be since plain strings should remain utf-16 and to make |
As I am writing this, it seems not to be the case. Check this out: https://sharplab.io/#v2:EYLgtghglgdgPgAQEwEYCwAoTA3CAnAAgAsBTAGwAcTCBeAmEgdwIAlyq8AKASgG5NSlagDoAggBNxnAgCIA1iQCeMgDSzcZAK4kZBPpkzJW7apgDemAlYIIAzDYAsBCVIQoADAQWK1AJRIQ4gDyMGSKAMoUEDAAPADGRPgAfATiEAAuENwEZgQAvpbWdo7Okpxunt5+AcGhEVGxwIrpJClpmdm5BRh5QA== It fails to compile and gives an |
@zlatanov probably preview bug since utf8 suffix also isnt implemented in this branch (gives syntax error) so i wouldnt worry too much they still have about half a year before final release |
@BreyerW This compiles just fine: using System;
var helper = new Helper();
helper.Add( "key", "value"u8 );
class Helper
{
public void Add(string key, ReadOnlySpan<char> data) { }
public void Add(string key, ReadOnlySpan<byte> data) { }
} |
@zlatanov ah i was mistakenly using |
The problem is, that string has now an implicit conversion operator to |
Implicit operator to |
This issue seems to be fixed in the spec / proposal: https://github.com/dotnet/csharplang/blob/main/proposals/utf8-string-literals.md#resolved-overload-resolution-breaks This fix is just not implemented: using System;
using static App;
M1("");
class App{
public static void M1(ReadOnlySpan<char> charArray) => Console.WriteLine(charArray.Length);
public static void M1(byte[] byteArray) => Console.WriteLine(byteArray.Length);
} |
I got a problem when I update the SDK, it breaks my previous code Error message:
Failed CI:
Sample code: https://github.com/WeihanLi/SamplesInPractice/tree/63795cd961dc64ff3b92473a09eb90a59792db19/MiniAspNetCore |
Will UTF-8 string literals support raw string literals?
|
Regular raw strings already work on SharpLab, verbatim strings too. But it doesn't appear that interpolated strings are supported, in any flavor. |
Will interpolated UTF8 work with Interpolated String Handler ? |
As HaloFour said, there are no interpolated UTF-8 strings. |
Yeah, sorry, I missed the |
Proposal: https://github.com/dotnet/csharplang/blob/main/proposals/csharp-11.0/utf8-string-literals.md
Old draft proposal: #2911
Design Review
https://github.com/dotnet/csharplang/blob/main/meetings/2021/LDM-2021-10-27.md#utf-8-string-literals
https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-01-26.md#open-questions-in-utf-8-string-literals
https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-06-29.md#utf-8-literal-concatenation-operator
The text was updated successfully, but these errors were encountered: