Add support for unsafe as operator to the toolchain. (#5993)

Following the direction of #5913, add support for parsing an `unsafe as`
operator. For now, we allow one additional conversion using `unsafe as`
beyond the conversions supported by `as`: we permit pointer conversions
that remove qualifiers, such as `const T*` -> `T*`.
This commit is contained in:
Richard Smith
2025-08-28 23:00:53 +00:00
committed by GitHub
parent 1d0f30df3a
commit 50e5476ee3
20 changed files with 330 additions and 57 deletions
+32 -3
View File
@@ -278,12 +278,24 @@ auto HandleExprLoop(Context& context) -> void {
auto operator_kind = context.PositionKind();
auto trailing_operator = PrecedenceGroup::ForTrailing(
operator_kind, context.IsTrailingOperatorInfix());
if (!trailing_operator) {
if (state.has_error) {
context.ReturnErrorOnState();
// TODO: Generalize this to handle a sequence of operator modifiers once we
// have more than one.
if (context.PositionIs(Lex::TokenKind::Unsafe)) {
operator_kind = context.PositionKind(Lookahead::NextToken);
trailing_operator = PrecedenceGroup::ForTrailing(
operator_kind, context.IsTrailingOperatorInfix());
}
if (!trailing_operator) {
if (state.has_error) {
context.ReturnErrorOnState();
}
return;
}
return;
}
auto [operator_precedence, is_binary] = *trailing_operator;
// TODO: If this operator is ambiguous with either the ambient precedence
@@ -323,6 +335,23 @@ auto HandleExprLoop(Context& context) -> void {
: Context::OperatorFixity::Postfix);
}
// For operator modifiers, wrap the first operand in the modifier.
if (context.PositionIs(Lex::TokenKind::Unsafe)) {
if (context.PositionIs(Lex::TokenKind::As, Lookahead::NextToken)) {
context.AddNode<NodeKind::UnsafeModifier>(context.Consume(),
state.has_error);
} else {
CARBON_DIAGNOSTIC(ModifierNotAllowedOnOperator, Error,
"`{0}` not allowed on operator `{1}`", Lex::TokenKind,
Lex::TokenKind);
context.emitter().Emit(*context.position(), ModifierNotAllowedOnOperator,
context.PositionKind(),
context.PositionKind(Lookahead::NextToken));
context.Consume();
state.has_error = true;
}
}
state.token = context.Consume();
state.lhs_precedence = operator_precedence;