infer_expression_type types a FieldReference from the first segment alone: type_inference.py returns schema.types[segment.struct_field.field] and never follows StructField.child. A nested reference such as row.f0.f0 is therefore typed as the outer struct, not the inner field.
This applies to every root type. Since #292 it is also reachable through lambda parameters: the spec's lambda_param_nested_struct.textproto example (person.address.city) with its parameter typed as the documented Person struct, infers the whole person struct, where it should infer city's string.
Reproducer
import substrait.algebra_pb2 as stalg, substrait.type_pb2 as stt
from substrait.type_inference import infer_expression_type
R, N = stt.Type.NULLABILITY_REQUIRED, stt.Type.NULLABILITY_NULLABLE
SF = stalg.Expression.ReferenceSegment.StructField
ref = stalg.Expression(selection=stalg.Expression.FieldReference(
root_reference=stalg.Expression.FieldReference.RootReference(),
direct_reference=stalg.Expression.ReferenceSegment(struct_field=SF(
field=0, child=stalg.Expression.ReferenceSegment(struct_field=SF(field=0)))),
))
row = stt.Type.Struct(nullability=R, types=[stt.Type(struct=stt.Type.Struct(
nullability=R, types=[stt.Type(string=stt.Type.String(nullability=N))]))])
print(infer_expression_type(ref, row).WhichOneof("kind")) # struct; expected string
Measured on main at 35cab19. The bug predates #292; main at bcfad64 gives the same result.
infer_expression_typetypes aFieldReferencefrom the first segment alone:type_inference.pyreturnsschema.types[segment.struct_field.field]and never followsStructField.child. A nested reference such asrow.f0.f0is therefore typed as the outer struct, not the inner field.This applies to every root type. Since #292 it is also reachable through lambda parameters: the spec's
lambda_param_nested_struct.textprotoexample (person.address.city) with its parameter typed as the documentedPersonstruct, infers the wholepersonstruct, where it should infercity'sstring.Reproducer
Measured on
mainat 35cab19. The bug predates #292;mainat bcfad64 gives the same result.