Pre-RFC: Raw identifiers

This looks great!

Personally, I was happy when I saw the r#catch syntax. It’s reasonably short, fits decently with other syntax, and doesn’t take up a new sigil that I’d rather keep for a more important use.

I think that having a short syntax is far more important in C# because of reflection and anonymous struct literals. Razor uses things like new { @class = "errorbox" } all over the place as an inefficient associative container, with the field names appearing in the output. I hope Rust doesn’t develop such a pattern.

A possible extension: this could allow both identifier#catch and keyword#catch (probably with shorter prefixes) as a way to also expose catch in Rust 1.0 (or multi-version) code.

Anything except r#… and br#… will break Macros 1.0.

macro_rules! x {
    ($a:ident # $b:ident) => {};
    ($c:ident) => { should error };
}
x!(identifier#catch);
x!(keyword#catch);

Hmm, that macro example also rules out @catch, but \catch and `catch` should still be OK because those characters aren’t yet found in legal tokens. (error: unknown start of token: \)

1 Like

Many C dialects support $ as a character in identifiers (probably for compatibility with VMS), so this might help with FFI if someone uses this particular C feature.

So any new literal kind? That’s a shame, and blocks things like s"foo" for Strings too, I guess.

I often feel like every possible syntax addition is breaking for macros…

If possible, I’d like to keep ` unused so writing docs and posts here stays easy :smile:

2 Likes
#[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
struct s;

impl std::ops::Div<&'static str> for s {
    type Output = String;
    fn div(self, literal: &'static str) -> String {
        literal.to_owned()
    }
}

fn main() {
    let _strings: &[String] = &[s/"hello", s/"we", s/"are", s/"strings", s/"😛"];
}

But seriously, the syntax "foo"s (a suffix s) is reserved and can be used for this.

6 Likes

True, but you can also rename it locally, like #[link_name = "foo$bar"] fn foo_bar().

Having struggled with it here a few times, I’m with you on that. :slight_smile:

Lisp and Ruby use a leading colon for symbols (e.g. :catch), so maybe that would help make it easier to learn for people who have seen that pattern before?

Stealing @cuviper’s example:

use foo:::catch::bar;
let foo = :catch { bar: 42 };
let foo = Foo { :catch: 42 };
foo.:catch = 42;
foo.:catch(42);

Personally I think the `catch` variant isn’t as visually distracting as @catch or r#catch. Although using a delimited string for idents means a function name can now contain spaces, which looks odd after all these years of only allowing alphanumeric and underscores in an identifier.

Lisp uses them for keyword symbols, which are symbols in a special namespace. Symbol quoting uses |…| quoting.

1 Like

Question: how important is the catch problem in practice? How many crates out there indeed use catch as a name of a field or method?

Unknown – maybe not at all. I think the only reason catch couldn’t be a contextual keyword was for the possibility of a struct catch (which already defies naming conventions) and thus catch { ... } constructing it. But that was enough of a blocker that we now have do catch { ... } for the expression, and the keyword breaking change was discussed in the epoch proposal.

I’ve been reminded (by renewed activity) that there is a competing proposal, Infix notation for function call / invocation, that wants to use \foo for something else.

Thanks, then we can also look at raw identifiers used as such infix operators:

  • a \r#catch b
  • a \`catch` b

(in the realm of “silly but syntactically allowable”)

Among 10165 crates from crates.io, 28 use catch identifier for some definition. At least some of them use catch in public API. Full report is here: https://gist.github.com/matklad/acebc3579fc7c70d02056cd8b3d2bf0a.

5 Likes

As a data point, Dart uses #ident - it also has it for operators, so #+ refers to the method defined as operator+ (borrowed from C++), equivalent to our Add::add.

1 Like

We need to do something like this to ever be able to create new reserved words (necessary for the catch syntax for example). I think @cuviper’s proposed syntax strikes a good balance between sugar and salt, and the point about r# or br# being the only syntaxes that don’t break 1.0 macros seems compelling also.

I’d encourage someone to post an RFC.

1 Like

Ok, I’ll get all the feedback here incorporated and post that soon.

3 Likes

@cuviper Do you have an update on this? We’d love to get an RFC into FCP before the impl block

I apologize for my tardiness, but here it is:

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.