You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
let ... else if definitely isn't something the RFC specifies, and I don't think we should. A better error message might make sense, though ("cannot use else if with let ... else").
I personally disagree with "and I don't think we should". For me this not working was fairly surprising and conflicts with my intuition of let else as a shorthand for
letSome(var) = expr else{return;}let var = ifletSome(var) = expr {
var
}else{return}
or as stated in the RFC
This is a counterpart to if let expressions, and the pattern matching works identically, except that the value from the pattern match is assigned to the surrounding scope rather than the block's scope.
I would like to add support for this myself or mentor someone adding this. I am not sure what process is required here. If not desired, please FCP close this.
let path = ifletSome((path, _)) = &used_crate_source.rlib{
path
}elseif used_crate_source.rmeta.is_some(){
returnErr(format!(
"could not find rlib for: `{}`, found rmeta (metadata) file",
name
));
}else{
returnErr(format!("could not find rlib for: `{}`", name));
};
Nowadays it's an if let but one could imagine code afterwards that one doesn't want to be affected by rightward drift.
IMO it's a good idea to have it, but back when let else was still unstable it was definitely better to have shipped without it to keep the feature minimal.
It also has low conflict potential with other extension proposals for let else. The worst I could think of is confusion potential with extensions that look (but not are) very close:
letFoo::BarA(foo) = hi
elseifletFoo::BarB(foo){return;}// We could theoretically allow dropping the expr here and just match on the `hi` exprelseifletFoo::BarC(foo, foo2){return;}elseiftrue{// Is this tail if confusing? It does *not* try to do something with the `hi` exprpanic!()}else{return;};
or the match equivalent:
letFoo::BarA(foo) = hi
else match {Foo::BarC(foo) => panic!(),Foo::BarD(foo, foo2) => panic!(),
_ => panic!(),};
Personally, I'm not inclined to do this. We generally don't have "remove one level of extra indentation" features, and (more importantly) I think that if we're going to extend this, it would be something that more directly integrates with the pattern behaviour. Like there was the previous discussion of something like let Ok(x) = ... else match { Err(e) => ... };, for example, which is intimately connected with the core let-else feature, and not something that would work already by just putting it inside the else braces.
(I consider normal else if to be linearly less nesting because of chaining, but a let-else-if isn't chainable, so doesn't get that extra mountain-range-avoidance bonus.)
to me this is not about "remove one level of extra indentation" but much rather that else if and else are part of the same language construct. else without else if fundamentally feels inconsistent to me. Other features, like else match however introduce a new construct, as currently else match is not supported anywhere.
I'm similarly not inclined to do this; else if doesn't seem like an inherent part of let-else, and it doesn't feel like it adds new functionality (since you must diverge). If this added or unlocked functionality you couldn't get otherwise, that'd make it more appealing. But as it stands, it seems like a minor syntax tweak.
this is a discussion about syntactic sugar, it can never unlock functionality you couldn't get otherwise. let-else itself is a minor syntax tweak.
Looking at #111910 (comment) as an example where this might be useful:
letSome((path, _)) = &used_crate_source.rlibelseif used_crate_source.rmeta.is_some(){returnErr(format!("could not find rlib for: `{}`, found rmeta (metadata) file",
name
));}else{returnErr(format!("could not find rlib for: `{}`", name));};
vs
letSome((path, _)) = &used_crate_source.rlibelse{if used_crate_source.rmeta.is_some(){returnErr(format!("could not find rlib for: `{}`, found rmeta (metadata) file",
name
));}else{returnErr(format!("could not find rlib for: `{}`", name));}};
I think the formatting required for else if is worse than the formatting with else { ... } here. having let PAT = EXPR else if COND { on one line feels fairly hard to read, even if it could fit on one line.
I still think having the option to use else if if the else is forced to be on a separate line anyways is nice, but 🤷 experimenting with the formatting of it does make the argument less convincing.
Going to drop the nomination because this issue doesn't feel important enough to stay nominated for months.
Activity
fee1-dead commentedon May 24, 2023
I'd be willing to work on this if this is desired.
est31 commentedon May 24, 2023
FTR this is the real world code that my comment in the let else tracking issue was referring to (the link bitrotted):
rust/compiler/rustc_codegen_ssa/src/back/link.rs
Lines 189 to 198 in 72d6606
Nowadays it's an if let but one could imagine code afterwards that one doesn't want to be affected by rightward drift.
IMO it's a good idea to have it, but back when
let elsewas still unstable it was definitely better to have shipped without it to keep the feature minimal.It also has low conflict potential with other extension proposals for
let else. The worst I could think of is confusion potential with extensions that look (but not are) very close:or the match equivalent:
c410-f3r commentedon May 24, 2023
Hum, it is unrelated but I would like to chime-in to also mention the possibility of using
let_elsewithlet_chains.ast::StmtKind::LetElseto allow the usage oflet_elsewithlet_chains#93437scottmcm commentedon Jun 20, 2023
(Not speaking for the team)
Personally, I'm not inclined to do this. We generally don't have "remove one level of extra indentation" features, and (more importantly) I think that if we're going to extend this, it would be something that more directly integrates with the pattern behaviour. Like there was the previous discussion of something like
let Ok(x) = ... else match { Err(e) => ... };, for example, which is intimately connected with the core let-else feature, and not something that would work already by just putting it inside the else braces.(I consider normal
else ifto be linearly less nesting because of chaining, but a let-else-if isn't chainable, so doesn't get that extra mountain-range-avoidance bonus.)lcnr commentedon Jun 20, 2023
to me this is not about "remove one level of extra indentation" but much rather that
else ifandelseare part of the same language construct.elsewithoutelse iffundamentally feels inconsistent to me. Other features, likeelse matchhowever introduce a new construct, as currentlyelse matchis not supported anywhere.scottmcm commentedon Jun 22, 2023
I guess I don't see it that way as there's no
ifin the first place. To me,else ifis going withif, not because of theelse, I guess.(For example,
for-elsein Python doesn't supportelif, as far as I know, sinceelifis part ofif, not part ofelse.)joshtriplett commentedon Aug 1, 2023
I'm similarly not inclined to do this;
else ifdoesn't seem like an inherent part oflet-else, and it doesn't feel like it adds new functionality (since you must diverge). If this added or unlocked functionality you couldn't get otherwise, that'd make it more appealing. But as it stands, it seems like a minor syntax tweak.lcnr commentedon Aug 2, 2023
this is a discussion about syntactic sugar, it can never unlock functionality you couldn't get otherwise.
let-elseitself is a minor syntax tweak.Looking at #111910 (comment) as an example where this might be useful:
vs
I think the formatting required for
else ifis worse than the formatting withelse { ... }here. havinglet PAT = EXPR else if COND {on one line feels fairly hard to read, even if it could fit on one line.I still think having the option to use
else ifif theelseis forced to be on a separate line anyways is nice, but 🤷 experimenting with the formatting of it does make the argument less convincing.Going to drop the nomination because this issue doesn't feel important enough to stay nominated for months.