public bool PeekDereferencableExpectedType(int n, TypeRef expType, bool canBeStruct, BoolRef changed) { expType = expType.ToRunTimeType(RootEnv, false); var type = PeekType(n); var s = type.Style(RootEnv); if (s is NullTypeStyle) { // Stack entry will remain a referece type (and thus never a pointer). // 'null' can be statically dereferenced if we are expecting a reference type, though // of course this will cause a null reference exception at runtime if (!(expType.Style(RootEnv) is ReferenceTypeStyle)) { throw new InvalidOperationException("expected type is not a referece type"); } // Stack type cannot be refined above expected reference type SetUpperBound(n, expType, changed); // Not dereferencing a pointer return(false); } else if (s is UnmanagedPointerTypeStyle) { throw new InvalidOperationException("unmananaged pointer"); } else if (s is ManagedPointerTypeStyle) { // Stack entry will remain a pointer of this type, so no need to impose upper bound if (!type.Arguments[0].IsAssignableTo(RootEnv, expType)) { throw new InvalidOperationException ("managed pointer element type is not assignable to expected type"); } // Dereferencing a pointer return(true); } else { // If stack entry is a value type it will remain a value type, so test is stable under generalization if (!canBeStruct && s is ValueTypeStyle) { throw new InvalidOperationException ("stack entry is a value type, but value types cannot be the target of field pointers"); } // Values and objects can be dereferenced if they are compatible with expected type // Parameter types are not allowed if (!(s is ReferenceTypeStyle) && !(s is ValueTypeStyle)) { throw new InvalidOperationException("stack entry is not a value or reference type"); } // Stack type cannot be refined above expected type SetUpperBound(n, expType, changed); // Not dereferencing a pointer return(false); } }
public override CST.InvalidInfo ImplementableTypeRef(MessageContext ctxt, CST.RootEnvironment rootEnv, CST.TypeRef typeRef) { var s = typeRef.Style(rootEnv); if (s is CST.UnmanagedPointerTypeStyle) { Log(new CST.InvalidTypeRef(ctxt, typeRef, "Unmanaged pointers are not supported")); return(new CST.InvalidInfo(CST.MessageContextBuilders.Type(Global, typeRef))); } return(null); }
public void PeekBoxedType(int n, TypeRef expType, BoolRef changed) { var type = PeekType(n); var s = type.Style(RootEnv); if (s is NullTypeStyle) { // No-op. // Will fail at runtime, but still ok. // If stack entry is generalized, it must go directly to Object. } else if (s is ReferenceTypeStyle) { if (s is ObjectTypeStyle) { // This stack entry can never be refined away from object return; } if (!(s is BoxTypeStyle)) { // Parameter types not allowed throw new InvalidOperationException("stack entry is not object or a boxed type"); } if (expType.Style(RootEnv) is NullableTypeStyle) { // Account for null -> no-value coercion expType = expType.Arguments[0]; } expType = expType.ToRunTimeType(RootEnv, false); if (!type.Arguments[0].IsEquivalentTo(RootEnv, expType)) { throw new InvalidOperationException("boxed element type is not equivalent to expected type"); } // Box types are NOT invariant, so need to impose upper bound SetUpperBound(n, RootEnv.Global.BoxTypeConstructorRef.ApplyTo(expType), changed); } else { // Parameter types not allowed throw new InvalidOperationException("stack entry is not object or a boxed type"); } }
public void SetUpperBound(RootEnvironment rootEnv, TypeRef type, BoolRef changed) { var s = type.Style(rootEnv); if (s is ValueTypeStyle || s is PointerTypeStyle || s is CodePointerTypeStyle) { // These types are only assignable to themselves, so no need to remember // the upper bound, just check it if (!Type.IsAssignableTo(rootEnv, type)) { if (s is UnmanagedPointerTypeStyle) { throw new InvalidOperationException("unmanaged pointer"); } else { throw new InvalidOperationException("stack entry cannot be generalized"); } } } else { var upperBound = UpperBound == null ? type : UpperBound.Glb(rootEnv, type, changed); if (!Type.IsAssignableTo(rootEnv, upperBound)) { throw new InvalidOperationException("stack entry cannot be generalized"); } if (!upperBound.IsEquivalentTo(rootEnv, rootEnv.Global.ObjectRef)) { if (UpperBound == null) { changed.Set(); } UpperBound = upperBound; } } }