Skip to content

Commit 9157115

Browse files
jnthntatumcopybara-github
authored andcommitted
Minor type check changes for consistency with Java implementation:
- add support for preserving original type name in struct create expressions - adjust error message in a few cases PiperOrigin-RevId: 689149479
1 parent 1c19916 commit 9157115

4 files changed

Lines changed: 47 additions & 8 deletions

File tree

checker/checker_options.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ struct CheckerOptions {
3333
// TODO: Need a concrete plan for updating existing CEL
3434
// expressions that depend on the old behavior.
3535
bool enable_legacy_null_assignment = true;
36+
37+
// Enable updating parsed struct type names to the fully qualified type name
38+
// when resolved.
39+
//
40+
// Enabled by default, but can be disabled to preserve the original type name
41+
// as parsed.
42+
bool update_struct_type_names = true;
3643
};
3744

3845
#endif // THIRD_PARTY_CEL_CPP_CHECKER_CHECKER_OPTIONS_H_

checker/internal/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ cc_test(
161161
"//checker:validation_result",
162162
"//common:ast",
163163
"//common:decl",
164+
"//common:expr",
164165
"//common:source",
165166
"//common:type",
166167
"//extensions/protobuf:value",

checker/internal/type_checker_impl.cc

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "absl/types/span.h"
3535
#include "base/ast_internal/ast_impl.h"
3636
#include "base/ast_internal/expr.h"
37+
#include "checker/checker_options.h"
3738
#include "checker/internal/namespace_generator.h"
3839
#include "checker/internal/type_check_env.h"
3940
#include "checker/internal/type_inference_context.h"
@@ -613,7 +614,7 @@ void ResolveVisitor::PostVisitMap(const Expr& expr, const MapExpr& map) {
613614
if (value_type.IsOptional()) {
614615
value_type = value_type.GetOptional().GetParameter();
615616
} else {
616-
ReportTypeMismatch(entry.id(), OptionalType(arena_, value_type),
617+
ReportTypeMismatch(entry.value().id(), OptionalType(arena_, value_type),
617618
value_type);
618619
continue;
619620
}
@@ -829,7 +830,7 @@ void ResolveVisitor::PostVisitComprehensionSubexpression(
829830
break;
830831
default:
831832
issues_->push_back(TypeCheckIssue::CreateError(
832-
ComputeSourceLocation(*ast_, expr.id()),
833+
ComputeSourceLocation(*ast_, comprehension.iter_range().id()),
833834
absl::StrCat(
834835
"expression of type '",
835836
inference_context_->FinalizeType(range_type).DebugString(),
@@ -898,12 +899,12 @@ void ResolveVisitor::ResolveFunctionOverloads(const Expr& expr,
898899
issues_->push_back(TypeCheckIssue::CreateError(
899900
ComputeSourceLocation(*ast_, expr.id()),
900901
absl::StrCat("found no matching overload for '", decl.name(),
901-
"' applied to (",
902+
"' applied to '(",
902903
absl::StrJoin(arg_types, ", ",
903904
[](std::string* out, const Type& type) {
904905
out->append(type.DebugString());
905906
}),
906-
")")));
907+
")'")));
907908
return;
908909
}
909910

@@ -1135,12 +1136,14 @@ class ResolveRewriter : public AstRewriterBase {
11351136
public:
11361137
explicit ResolveRewriter(const ResolveVisitor& visitor,
11371138
const TypeInferenceContext& inference_context,
1139+
const CheckerOptions& options,
11381140
AstImpl::ReferenceMap& references,
11391141
AstImpl::TypeMap& types)
11401142
: visitor_(visitor),
11411143
inference_context_(inference_context),
11421144
reference_map_(references),
1143-
type_map_(types) {}
1145+
type_map_(types),
1146+
options_(options) {}
11441147
bool PostVisitRewrite(Expr& expr) override {
11451148
bool rewritten = false;
11461149
if (auto iter = visitor_.attributes().find(&expr);
@@ -1172,7 +1175,7 @@ class ResolveRewriter : public AstRewriterBase {
11721175
iter != visitor_.struct_types().end()) {
11731176
auto& ast_ref = reference_map_[expr.id()];
11741177
ast_ref.set_name(iter->second);
1175-
if (expr.has_struct_expr()) {
1178+
if (expr.has_struct_expr() && options_.update_struct_type_names) {
11761179
expr.mutable_struct_expr().set_name(iter->second);
11771180
}
11781181
rewritten = true;
@@ -1202,6 +1205,7 @@ class ResolveRewriter : public AstRewriterBase {
12021205
const TypeInferenceContext& inference_context_;
12031206
AstImpl::ReferenceMap& reference_map_;
12041207
AstImpl::TypeMap& type_map_;
1208+
const CheckerOptions& options_;
12051209
};
12061210

12071211
} // namespace
@@ -1237,7 +1241,7 @@ absl::StatusOr<ValidationResult> TypeCheckerImpl::Check(
12371241
// Apply updates as needed.
12381242
// Happens in a second pass to simplify validating that pointers haven't
12391243
// been invalidated by other updates.
1240-
ResolveRewriter rewriter(visitor, type_inference_context,
1244+
ResolveRewriter rewriter(visitor, type_inference_context, options_,
12411245
ast_impl.reference_map(), ast_impl.type_map());
12421246
AstRewrite(ast_impl.root_expr(), rewriter);
12431247

checker/internal/type_checker_impl_test.cc

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "checker/validation_result.h"
3939
#include "common/ast.h"
4040
#include "common/decl.h"
41+
#include "common/expr.h"
4142
#include "common/source.h"
4243
#include "common/type.h"
4344
#include "common/type_introspector.h"
@@ -1133,7 +1134,7 @@ TEST(TypeCheckerImplTest, BasicOvlResolutionNoMatch) {
11331134
EXPECT_THAT(result.GetIssues(),
11341135
Contains(IsIssueWithSubstring(Severity::kError,
11351136
"no matching overload for '_+_'"
1136-
" applied to (int, string)")));
1137+
" applied to '(int, string)'")));
11371138
}
11381139

11391140
TEST(TypeCheckerImplTest, ParmeterizedOvlResolutionMatch) {
@@ -1250,6 +1251,32 @@ TEST(TypeCheckerImplTest, ContainerLookupForMessageCreation) {
12501251
"google.protobuf.Int32Value"))));
12511252
}
12521253

1254+
TEST(TypeCheckerImplTest, ContainerLookupForMessageCreationNoRewrite) {
1255+
TypeCheckEnv env;
1256+
env.set_container("google.protobuf");
1257+
env.AddTypeProvider(std::make_unique<TypeIntrospector>());
1258+
1259+
CheckerOptions options;
1260+
options.update_struct_type_names = false;
1261+
TypeCheckerImpl impl(std::move(env), options);
1262+
ASSERT_OK_AND_ASSIGN(auto ast, MakeTestParsedAst("Int32Value{value: 10}"));
1263+
ASSERT_OK_AND_ASSIGN(ValidationResult result, impl.Check(std::move(ast)));
1264+
1265+
ASSERT_OK_AND_ASSIGN(std::unique_ptr<Ast> checked_ast, result.ReleaseAst());
1266+
1267+
const auto& ast_impl = AstImpl::CastFromPublicAst(*checked_ast);
1268+
EXPECT_THAT(ast_impl.type_map(),
1269+
Contains(Pair(ast_impl.root_expr().id(),
1270+
Eq(AstType(ast_internal::PrimitiveTypeWrapper(
1271+
ast_internal::PrimitiveType::kInt64))))));
1272+
EXPECT_THAT(ast_impl.reference_map(),
1273+
Contains(Pair(ast_impl.root_expr().id(),
1274+
Property(&ast_internal::Reference::name,
1275+
"google.protobuf.Int32Value"))));
1276+
EXPECT_THAT(ast_impl.root_expr().struct_expr(),
1277+
Property(&StructExpr::name, "Int32Value"));
1278+
}
1279+
12531280
TEST(TypeCheckerImplTest, EnumValueCopiedToReferenceMap) {
12541281
TypeCheckEnv env;
12551282
env.set_container("google.api.expr.test.v1.proto3");

0 commit comments

Comments
 (0)