getRuntimeType method
Implementation
RuntimeType? getRuntimeType(Object? value) {
if (value is InterpretedInstance) {
return value.klass; // InterpretedClass is a RuntimeType
}
if (value is BridgedInstance) {
return value.bridgedClass; // BridgedClass is a RuntimeType
}
// G-DOV2-7 FIX: Handle InterpretedEnumValue - return its parent enum as the type
if (value is InterpretedEnumValue) {
return value.parentEnum; // InterpretedEnum is a RuntimeType
}
// Bucket #4 fix: Handle BridgedEnumValue so extension lookups against the
// enum's parent BridgedEnum can succeed (e.g. WidgetStateOperators on a
// WidgetState value).
if (value is BridgedEnumValue) {
return value.enumType;
}
// Handle Dart primitive/core types by looking them up in the environment
// Assumes core types (String, int, bool, List, Map, etc.) are registered as BridgedClass
String? typeName;
if (value == null) typeName = 'Null';
if (value is String) typeName = 'String';
if (value is int) typeName = 'int';
if (value is double) typeName = 'double';
if (value is bool) typeName = 'bool';
if (value is List) typeName = 'List';
if (value is Map) typeName = 'Map';
if (typeName != null) {
// Cluster C26 FIX: For List/Map, prefer a more-specific bridged class
// (e.g. Uint8List, Int32List) registered for the actual runtime type.
// `value is List` matches typed-data subclasses, which previously
// collapsed their runtime type to plain `List` and broke return-type
// checks on functions declared to return `Uint8List` and friends.
// If `toBridgedClass` resolves to a more specific bridge, return it;
// otherwise fall through to the generic lookup below.
if (value != null && (typeName == 'List' || typeName == 'Map')) {
try {
final specific = toBridgedClass(value.runtimeType);
if (specific.name != typeName) {
return specific;
}
} on RuntimeD4rtException {
// No specific bridge — fall through to generic typeName lookup.
}
}
try {
final typeObj = get(typeName); // Look up the type name
if (typeObj is RuntimeType) {
return typeObj;
} else {
Logger.warn(
"[getRuntimeType] Found symbol '$typeName' but it's not a RuntimeType (${typeObj?.runtimeType})",
);
}
} on RuntimeD4rtException {
Logger.warn(
"[getRuntimeType] RuntimeType for primitive '$typeName' not found in environment.",
);
}
}
// For other native objects (e.g., DateTime, Duration, etc.), try to find their BridgedClass
if (value != null) {
try {
final bridgedClass = toBridgedClass(value.runtimeType);
return bridgedClass;
} on RuntimeD4rtException {
// No bridged class found for this type
Logger.debug(
"[getRuntimeType] No BridgedClass found for native type ${value.runtimeType}",
);
}
// C20a fix: When the runtime type isn't a registered bridge (e.g.
// private impl types returned by extension operators like
// `WidgetState.a | WidgetState.b` returning a `_WidgetStateOr`),
// fall back to `isAssignable` iteration so we can recover the
// bridged interface (e.g. `WidgetStatesConstraint`) it implements.
// This lets subsequent operator dispatch (e.g. `& ~WidgetState.x`
// applied to the OR result) reach the right extension.
Environment? current = this;
BridgedClass? bestMatch;
while (current != null) {
for (final entry in current._bridgedClassesLookupByType.entries) {
final bridge = entry.value;
if (bridge.isAssignable != null && bridge.isAssignable!(value)) {
bestMatch = bridge;
}
}
current = current._enclosing;
}
if (bestMatch != null) {
Logger.debug(
"[getRuntimeType] Resolved native ${value.runtimeType} via "
"isAssignable to BridgedClass(${bestMatch.name})",
);
return bestMatch;
}
}
return null; // Type couldn't be determined
}