Labeled questionmark


#1

It would be useful to be able to label questionmarks, primarily for use with loops:

fn foo<T: Into<i32>>(op: fn(i8, i8) -> Option<T>) {
    for i in (0i8..=9i8) {
        'a: for j in (0i8..=9i8) {
            let k: i32 = op(i, j) 'a?.into();
            // do stuff with k
        }
    }
}

This labeled questionmark would cause the loop to continue/go to the next iteration if the result of op(i, j) is None - or anything that can be considered Into<()>. (is NoneError an Into<()>? I don’t remember)


#2

There’s already such feature in the language: https://github.com/rust-lang/rust/issues/50412, specifically https://github.com/rust-lang/rust/issues/31436


#3

I believe that still adds another depth of indentation, which is really bad for readability. It also doesn’t tie in with the loops very well and you don’t have much control over where it goes (it just goes to the nearest, literally no control).


#4

This is interesting because with labeled break value it could be a good alternative to try blocks:

// With `try` blocks
let z = try {
    let x = foo()?;
    let y = bar()?;
    x + y
}

// With this proposal
let z = 'a: {
    let x = foo() 'a ?;
    let y = bar() 'a ?;
    Ok(x + y)
}

I definitely would prefer this over try, since it seems to be easier to implement, easier to understand, and I’ve never seen too much use cases that worth to introduce try syntax.

Additionally, it seems to be more flexible:

let z = 'a: {
    let x = foo() 'a ?;
    let y = bar() 'a ?;
    validate(x, y)?;
    Ok(x + y)
}

#5

This was discussed in:

try (formerly catch) has been through 2 RFCs, unless new compelling arguments are presented I see no reason to go with 'label?.


#6

To be honest, now I don’t even see why both features should be conflicting when instead they could complement each other!


First we must update current implementation of ? operator:

  • It should by default bubble up errors to the nearest block prefixed with 'try: label
  • All functions should be implicitly marked with that label
  • But it’s still shouldn’t be possible to specify manually because try is a reserved keyword

Then we must allow ? operator to work on named blocks:

  • This is what been proposed in current and preceding threads
  • It also shouldn’t permit try label because it’s a reserved keyword

And finally we must allow to specify 'try: label using try keyword

  • This introduces similar syntax to try expression RFC
  • Except it shouldn’t provide implicit Ok wrapping (I see it as feature, through)
  • Rationale to use try keyword is that implicit return to 'try: would be ugly and confusing

And how it would look:

fn example() -> Result<(), Box<Error>> 'a: {
    let z = try {
        let x = foo()?;
        let y = bar()?;
        validate(x, y) 'a ?;
        Ok(x + y)
    }
    ...
}

#7

I see “reducing indentation” as a huge new compelling arguments.


#8

It might be helpful to link to those 2 RFCs.


#9

#10

Thank you.

As someone who would have more use for a more general solution, I find it encouraging that other people are looking for it as well. It does keep coming up so I hope at some point something will come along, and that people keep discussing possibilities.