public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl) { if (!expl && IsLiteral && BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (target) && BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (type)) { ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'", GetValueAsLiteral (), target.GetSignatureForError ()); } else { base.Error_ValueCannotBeConverted (ec, target, expl); } }
public FieldSpec CreateField (FieldInfo fi, TypeSpec declaringType) { Modifiers mod = 0; var fa = fi.Attributes; switch (fa & FieldAttributes.FieldAccessMask) { case FieldAttributes.Public: mod = Modifiers.PUBLIC; break; case FieldAttributes.Assembly: mod = Modifiers.INTERNAL; break; case FieldAttributes.Family: mod = Modifiers.PROTECTED; break; case FieldAttributes.FamORAssem: mod = Modifiers.PROTECTED | Modifiers.INTERNAL; break; default: // Ignore private fields (even for error reporting) to not require extra dependencies if ((IgnorePrivateMembers && !declaringType.IsStruct) || HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "CompilerGeneratedAttribute", CompilerServicesNamespace)) return null; mod = Modifiers.PRIVATE; break; } TypeSpec field_type; try { field_type = ImportType (fi.FieldType, new DynamicTypeReader (fi)); } catch (Exception e) { // TODO: I should construct fake TypeSpec based on TypeRef signature // but there is no way to do it with System.Reflection throw new InternalErrorException (e, "Cannot import field `{0}.{1}' referenced in assembly `{2}'", declaringType.GetSignatureForError (), fi.Name, declaringType.MemberDefinition.DeclaringAssembly); } var definition = new ImportedMemberDefinition (fi, field_type, this); if ((fa & FieldAttributes.Literal) != 0) { var c = Constant.CreateConstantFromValue (field_type, fi.GetRawConstantValue (), Location.Null); return new ConstSpec (declaringType, definition, field_type, fi, mod, c); } if ((fa & FieldAttributes.InitOnly) != 0) { if (field_type.BuiltinType == BuiltinTypeSpec.Type.Decimal) { var dc = ReadDecimalConstant (CustomAttributeData.GetCustomAttributes (fi)); if (dc != null) return new ConstSpec (declaringType, definition, field_type, fi, mod, dc); } mod |= Modifiers.READONLY; } else { var req_mod = fi.GetRequiredCustomModifiers (); if (req_mod.Length > 0 && HasVolatileModifier (req_mod)) mod |= Modifiers.VOLATILE; } if ((fa & FieldAttributes.Static) != 0) { mod |= Modifiers.STATIC; } else { // Fixed buffers cannot be static if (declaringType.IsStruct && field_type.IsStruct && field_type.IsNested && HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "FixedBufferAttribute", CompilerServicesNamespace)) { // TODO: Sanity check on field_type (only few types are allowed) var element_field = CreateField (fi.FieldType.GetField (FixedField.FixedElementName), declaringType); return new FixedFieldSpec (declaringType, definition, fi, element_field, mod); } } return new FieldSpec (declaringType, definition, field_type, fi, mod); }
protected bool VerifyParameterCompatibility (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type, AParametersCollection invoke_pd, bool ignore_errors) { if (Parameters.Count != invoke_pd.Count) { if (ignore_errors) return false; ec.Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments", delegate_type.GetSignatureForError (), Parameters.Count.ToString ()); return false; } bool has_implicit_parameters = !HasExplicitParameters; bool error = false; for (int i = 0; i < Parameters.Count; ++i) { Parameter.Modifier p_mod = invoke_pd.FixedParameters [i].ModFlags; if (Parameters.FixedParameters [i].ModFlags != p_mod && p_mod != Parameter.Modifier.PARAMS) { if (ignore_errors) return false; if (p_mod == Parameter.Modifier.NONE) ec.Report.Error (1677, Parameters[i].Location, "Parameter `{0}' should not be declared with the `{1}' keyword", (i + 1).ToString (), Parameter.GetModifierSignature (Parameters [i].ModFlags)); else ec.Report.Error (1676, Parameters[i].Location, "Parameter `{0}' must be declared with the `{1}' keyword", (i+1).ToString (), Parameter.GetModifierSignature (p_mod)); error = true; } if (has_implicit_parameters) continue; TypeSpec type = invoke_pd.Types [i]; if (tic != null) type = tic.InflateGenericArgument (ec, type); if (!TypeSpecComparer.IsEqual (type, Parameters.Types [i])) { if (ignore_errors) return false; ec.Report.Error (1678, Parameters [i].Location, "Parameter `{0}' is declared as type `{1}' but should be `{2}'", (i+1).ToString (), Parameters.Types [i].GetSignatureForError (), invoke_pd.Types [i].GetSignatureForError ()); error = true; } } return !error; }
protected bool VerifyExplicitParameters (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type, AParametersCollection parameters) { if (VerifyParameterCompatibility (ec, tic, delegate_type, parameters, ec.IsInProbingMode)) return true; if (!ec.IsInProbingMode) ec.Report.Error (1661, loc, "Cannot convert `{0}' to delegate type `{1}' since there is a parameter mismatch", GetSignatureForError (), delegate_type.GetSignatureForError ()); return false; }
static void CheckConversion (IMemberContext mc, MemberSpec context, TypeSpec atype, TypeParameterSpec tparam, TypeSpec ttype, Location loc) { var expr = new EmptyExpression (atype); if (!Convert.ImplicitStandardConversionExists (expr, ttype)) { mc.Compiler.Report.SymbolRelatedToPreviousError (tparam); if (TypeManager.IsValueType (atype)) { mc.Compiler.Report.Error (315, loc, "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no boxing conversion from `{0}' to `{3}'", atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ()); } else if (atype.IsGenericParameter) { mc.Compiler.Report.Error (314, loc, "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no boxing or type parameter conversion from `{0}' to `{3}'", atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ()); } else { mc.Compiler.Report.Error (311, loc, "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no implicit reference conversion from `{0}' to `{3}'", atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ()); } } }
protected virtual ParametersCompiled ResolveParameters (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type) { var delegate_parameters = Delegate.GetParameters (delegate_type); if (Parameters == ParametersCompiled.Undefined) { // // We provide a set of inaccessible parameters // Parameter[] fixedpars = new Parameter[delegate_parameters.Count]; for (int i = 0; i < delegate_parameters.Count; i++) { Parameter.Modifier i_mod = delegate_parameters.FixedParameters [i].ModFlags; if ((i_mod & Parameter.Modifier.OUT) != 0) { if (!ec.IsInProbingMode) { ec.Report.Error (1688, loc, "Cannot convert anonymous method block without a parameter list to delegate type `{0}' because it has one or more `out' parameters", delegate_type.GetSignatureForError ()); } return null; } fixedpars[i] = new Parameter ( new TypeExpression (delegate_parameters.Types [i], loc), null, delegate_parameters.FixedParameters [i].ModFlags, null, loc); } return ParametersCompiled.CreateFullyResolved (fixedpars, delegate_parameters.Types); } if (!VerifyExplicitParameters (ec, delegate_type, delegate_parameters)) { return null; } return Parameters; }
// // Attempts to do a compile-time folding of a constant cast and handles // error reporting for constant overlows only, on normal conversion // errors returns null // public Constant Reduce (ResolveContext ec, TypeSpec target_type) { try { return TryReduceConstant (ec, target_type); } catch (OverflowException) { if (ec.ConstantCheckState && Type.BuiltinType != BuiltinTypeSpec.Type.Decimal) { ec.Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)", GetValueAsLiteral (), target_type.GetSignatureForError ()); } else { Error_ValueCannotBeConverted (ec, target_type, false); } return New.Constantify (target_type, loc); } }
public static void Error1599 (Location loc, TypeSpec t, Report Report) { Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", t.GetSignatureForError ()); }
public virtual Constant ConvertImplicitly (TypeSpec type) { if (this.type == type) return this; if (!Convert.ImplicitNumericConversionExists (this.type, type)) return null; bool fail; object constant_value = ChangeType (GetValue (), type, out fail); if (fail){ // // We should always catch the error before this is ever // reached, by calling Convert.ImplicitStandardConversionExists // throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'", Type.GetSignatureForError (), type.GetSignatureForError ()); } return CreateConstantFromValue (type, constant_value, loc); }
void Error_AmbiguousIEnumerable (ResolveContext rc, TypeSpec type) { rc.Report.SymbolRelatedToPreviousError (type); rc.Report.Error (1640, loc, "foreach statement cannot operate on variables of type `{0}' because it contains multiple implementation of `{1}'. Try casting to a specific implementation", type.GetSignatureForError (), TypeManager.generic_ienumerable_type.GetSignatureForError ()); }
public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl) { try { ConvertExplicitly (true, target); base.Error_ValueCannotBeConverted (ec, target, expl); } catch { ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'", GetValue ().ToString (), target.GetSignatureForError ()); } }
protected void Error_ValueCannotBeConvertedCore(ResolveContext ec, Location loc, TypeSpec target, bool expl) { // The error was already reported as CS1660 if (type == InternalType.AnonymousMethod) return; /* if (TypeManager.IsGenericParameter (Type) && TypeManager.IsGenericParameter (target) && type.Name == target.Name) { string sig1 = type.DeclaringMethod == null ? TypeManager.CSharpName (type.DeclaringType) : TypeManager.CSharpSignature (type.DeclaringMethod); string sig2 = target.DeclaringMethod == null ? TypeManager.CSharpName (target.DeclaringType) : TypeManager.CSharpSignature (target.DeclaringMethod); ec.Report.ExtraInformation (loc, String.Format ( "The generic parameter `{0}' of `{1}' cannot be converted to the generic parameter `{0}' of `{2}' (in the previous ", Type.Name, sig1, sig2)); } else if (Type.MetaInfo.FullName == target.MetaInfo.FullName) { ec.Report.ExtraInformation (loc, String.Format ( "The type `{0}' has two conflicting definitions, one comes from `{1}' and the other from `{2}' (in the previous ", Type.MetaInfo.FullName, Type.Assembly.FullName, target.Assembly.FullName)); } */ if (expl) { ec.Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'", TypeManager.CSharpName (type), TypeManager.CSharpName (target)); return; } ec.Report.DisableReporting (); bool expl_exists = Convert.ExplicitConversion (ec, this, target, Location.Null) != null; ec.Report.EnableReporting (); if (expl_exists) { ec.Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. " + "An explicit conversion exists (are you missing a cast?)", TypeManager.CSharpName (Type), TypeManager.CSharpName (target)); return; } ec.Report.Error (29, loc, "Cannot implicitly convert type `{0}' to `{1}'", type.GetSignatureForError (), target.GetSignatureForError ()); }
// // User-defined conversions // public static Expression UserDefinedConversion (ResolveContext rc, Expression source, TypeSpec target, UserConversionRestriction restr, Location loc) { List<MethodSpec> candidates = null; // // If S or T are nullable types, source_type and target_type are their underlying types // otherwise source_type and target_type are equal to S and T respectively. // TypeSpec source_type = source.Type; TypeSpec target_type = target; Expression source_type_expr; bool nullable_source = false; var implicitOnly = (restr & UserConversionRestriction.ImplicitOnly) != 0; if (source_type.IsNullableType) { // No unwrapping conversion S? -> T for non-reference types if (implicitOnly && !TypeSpec.IsReferenceType (target_type) && !target_type.IsNullableType) { source_type_expr = source; } else { source_type_expr = Nullable.Unwrap.CreateUnwrapped (source); source_type = source_type_expr.Type; nullable_source = true; } } else { source_type_expr = source; } if (target_type.IsNullableType) target_type = Nullable.NullableInfo.GetUnderlyingType (target_type); // Only these containers can contain a user defined implicit or explicit operators const MemberKind user_conversion_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.TypeParameter; if ((source_type.Kind & user_conversion_kinds) != 0 && source_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) { bool declared_only = source_type.IsStruct; var operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Implicit, declared_only); if (operators != null) { FindApplicableUserDefinedConversionOperators (rc, operators, source_type_expr, target_type, restr, ref candidates); } if (!implicitOnly) { operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Explicit, declared_only); if (operators != null) { FindApplicableUserDefinedConversionOperators (rc, operators, source_type_expr, target_type, restr, ref candidates); } } } if ((target.Kind & user_conversion_kinds) != 0 && target_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) { bool declared_only = target.IsStruct || implicitOnly; var operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Implicit, declared_only); if (operators != null) { FindApplicableUserDefinedConversionOperators (rc, operators, source_type_expr, target_type, restr, ref candidates); } if (!implicitOnly) { operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Explicit, declared_only); if (operators != null) { FindApplicableUserDefinedConversionOperators (rc, operators, source_type_expr, target_type, restr, ref candidates); } } } if (candidates == null) return null; // // Find the most specific conversion operator // MethodSpec most_specific_operator; TypeSpec s_x, t_x; if (candidates.Count == 1) { most_specific_operator = candidates[0]; s_x = most_specific_operator.Parameters.Types[0]; t_x = most_specific_operator.ReturnType; } else { // // Pass original source type to find the best match against input type and // not the unwrapped expression // s_x = FindMostSpecificSource (rc, candidates, source.Type, source_type_expr, !implicitOnly); if (s_x == null) return null; t_x = FindMostSpecificTarget (candidates, target, !implicitOnly); if (t_x == null) return null; most_specific_operator = null; for (int i = 0; i < candidates.Count; ++i) { if (candidates[i].ReturnType == t_x && candidates[i].Parameters.Types[0] == s_x) { most_specific_operator = candidates[i]; break; } } if (most_specific_operator == null) { // // Unless running in probing more // if ((restr & UserConversionRestriction.ProbingOnly) == 0) { MethodSpec ambig_arg = candidates [0]; most_specific_operator = candidates [1]; /* foreach (var candidate in candidates) { if (candidate.ReturnType == t_x) most_specific_operator = candidate; else if (candidate.Parameters.Types[0] == s_x) ambig_arg = candidate; } */ rc.Report.Error (457, loc, "Ambiguous user defined operators `{0}' and `{1}' when converting from `{2}' to `{3}'", ambig_arg.GetSignatureForError (), most_specific_operator.GetSignatureForError (), source.Type.GetSignatureForError (), target.GetSignatureForError ()); } return ErrorExpression.Instance; } } // // Convert input type when it's different to best operator argument // if (s_x != source_type) { var c = source as Constant; if (c != null) { source = c.Reduce (rc, s_x); if (source == null) c = null; } if (c == null) { source = implicitOnly ? ImplicitConversionStandard (rc, source_type_expr, s_x, loc) : ExplicitConversionStandard (rc, source_type_expr, s_x, loc); } } else { source = source_type_expr; } source = new UserCast (most_specific_operator, source, loc).Resolve (rc); // // Convert result type when it's different to best operator return type // if (t_x != target_type) { // // User operator is of T? // if (t_x.IsNullableType && (target.IsNullableType || !implicitOnly)) { // // User operator return type does not match target type we need // yet another conversion. This should happen for promoted numeric // types only // if (t_x != target) { var unwrap = Nullable.Unwrap.CreateUnwrapped (source); source = implicitOnly ? ImplicitConversionStandard (rc, unwrap, target_type, loc) : ExplicitConversionStandard (rc, unwrap, target_type, loc); if (source == null) return null; if (target.IsNullableType) source = new Nullable.LiftedConversion (source, unwrap, target).Resolve (rc); } } else { source = implicitOnly ? ImplicitConversionStandard (rc, source, target_type, loc) : ExplicitConversionStandard (rc, source, target_type, loc); if (source == null) return null; } } // // Source expression is of nullable type and underlying conversion returns // only non-nullable type we need to lift it manually // if (nullable_source && !s_x.IsNullableType) return new Nullable.LiftedConversion (source, source_type_expr, target).Resolve (rc); // // Target is of nullable type but source type is not, wrap the result expression // if (target.IsNullableType && !t_x.IsNullableType) source = Nullable.Wrap.Create (source, target); return source; }
bool CheckConflictingInheritedConstraint (TypeSpec ba, TypeSpec bb, IMemberContext context, Location loc) { if (!TypeManager.IsSubclassOf (ba, bb) && !TypeManager.IsSubclassOf (bb, ba)) { context.Compiler.Report.Error (455, loc, "Type parameter `{0}' inherits conflicting constraints `{1}' and `{2}'", tparam.Value, ba.GetSignatureForError (), bb.GetSignatureForError ()); return false; } return true; }
public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache) { // // Not interested in members of nested private types unless the importer needs them // if (declaringType.IsPrivate && importer.IgnorePrivateMembers) { cache = MemberCache.Empty; return; } var loading_type = (MetaType) provider; const BindingFlags all_members = BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; const MethodAttributes explicit_impl = MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.Final; Dictionary<MethodBase, MethodSpec> possible_accessors = null; List<EventSpec> imported_events = null; EventSpec event_spec; MemberSpec imported; MethodInfo m; MemberInfo[] all; try { all = loading_type.GetMembers (all_members); } catch (Exception e) { throw new InternalErrorException (e, "Could not import type `{0}' from `{1}'", declaringType.GetSignatureForError (), declaringType.MemberDefinition.DeclaringAssembly.FullName); } if (cache == null) { cache = new MemberCache (all.Length); // // Do the types first as they can be referenced by the members before // they are found or inflated // foreach (var member in all) { if (member.MemberType != MemberTypes.NestedType) continue; var t = (MetaType) member; // Ignore compiler generated types, mostly lambda containers if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate && importer.IgnorePrivateMembers) continue; try { imported = importer.CreateNestedType (t, declaringType); } catch (Exception e) { throw new InternalErrorException (e, "Could not import nested type `{0}' from `{1}'", t.FullName, declaringType.MemberDefinition.DeclaringAssembly.FullName); } cache.AddMemberImported (imported); } foreach (var member in all) { if (member.MemberType != MemberTypes.NestedType) continue; var t = (MetaType) member; if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate && importer.IgnorePrivateMembers) continue; importer.ImportTypeBase (t); } } // // Load base interfaces first to minic behaviour of compiled members // if (declaringType.IsInterface && declaringType.Interfaces != null) { foreach (var iface in declaringType.Interfaces) { cache.AddInterface (iface); } } if (!onlyTypes) { // // The logic here requires methods to be returned first which seems to work for both Mono and .NET // foreach (var member in all) { switch (member.MemberType) { case MemberTypes.Constructor: case MemberTypes.Method: MethodBase mb = (MethodBase) member; var attrs = mb.Attributes; if ((attrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Private) { if (importer.IgnorePrivateMembers) continue; // Ignore explicitly implemented members if ((attrs & explicit_impl) == explicit_impl) continue; // Ignore compiler generated methods if (MetadataImporter.HasAttribute (CustomAttributeData.GetCustomAttributes (mb), "CompilerGeneratedAttribute", MetadataImporter.CompilerServicesNamespace)) continue; } imported = importer.CreateMethod (mb, declaringType); if (imported.Kind == MemberKind.Method && !imported.IsGeneric) { if (possible_accessors == null) possible_accessors = new Dictionary<MethodBase, MethodSpec> (ReferenceEquality<MethodBase>.Default); // There are no metadata rules for accessors, we have to consider any method as possible candidate possible_accessors.Add (mb, (MethodSpec) imported); } break; case MemberTypes.Property: if (possible_accessors == null) continue; var p = (PropertyInfo) member; // // Links possible accessors with property // MethodSpec get, set; m = p.GetGetMethod (true); if (m == null || !possible_accessors.TryGetValue (m, out get)) get = null; m = p.GetSetMethod (true); if (m == null || !possible_accessors.TryGetValue (m, out set)) set = null; // No accessors registered (e.g. explicit implementation) if (get == null && set == null) continue; imported = importer.CreateProperty (p, declaringType, get, set); if (imported == null) continue; break; case MemberTypes.Event: if (possible_accessors == null) continue; var e = (EventInfo) member; // // Links accessors with event // MethodSpec add, remove; m = e.GetAddMethod (true); if (m == null || !possible_accessors.TryGetValue (m, out add)) add = null; m = e.GetRemoveMethod (true); if (m == null || !possible_accessors.TryGetValue (m, out remove)) remove = null; // Both accessors are required if (add == null || remove == null) continue; event_spec = importer.CreateEvent (e, declaringType, add, remove); if (!importer.IgnorePrivateMembers) { if (imported_events == null) imported_events = new List<EventSpec> (); imported_events.Add (event_spec); } imported = event_spec; break; case MemberTypes.Field: var fi = (FieldInfo) member; imported = importer.CreateField (fi, declaringType); if (imported == null) continue; // // For dynamic binder event has to be fully restored to allow operations // within the type container to work correctly // if (imported_events != null) { // The backing event field should be private but it may not int i; for (i = 0; i < imported_events.Count; ++i) { var ev = imported_events[i]; if (ev.Name == fi.Name) { ev.BackingField = (FieldSpec) imported; imported_events.RemoveAt (i); i = -1; break; } } if (i < 0) continue; } break; case MemberTypes.NestedType: // Already in the cache from the first pass continue; default: throw new NotImplementedException (member.ToString ()); } cache.AddMemberImported (imported); } } }
// // Returns AnonymousMethod container if this anonymous method // expression can be implicitly converted to the delegate type `delegate_type' // public Expression Compatible (ResolveContext ec, TypeSpec type) { Expression am; if (compatibles.TryGetValue (type, out am)) return am; TypeSpec delegate_type = CompatibleChecks (ec, type); if (delegate_type == null) return null; // // At this point its the first time we know the return type that is // needed for the anonymous method. We create the method here. // var invoke_mb = Delegate.GetInvokeMethod (delegate_type); TypeSpec return_type = invoke_mb.ReturnType; // // Second: the return type of the delegate must be compatible with // the anonymous type. Instead of doing a pass to examine the block // we satisfy the rule by setting the return type on the EmitContext // to be the delegate type return type. // var body = CompatibleMethodBody (ec, null, return_type, delegate_type); if (body == null) return null; bool etree_conversion = delegate_type != type; try { if (etree_conversion) { if (ec.HasSet (ResolveContext.Options.ExpressionTreeConversion)) { // // Nested expression tree lambda use same scope as parent // lambda, this also means no variable capturing between this // and parent scope // am = body.Compatible (ec, ec.CurrentAnonymousMethod); // // Quote nested expression tree // if (am != null) am = new Quote (am); } else { int errors = ec.Report.Errors; using (ec.Set (ResolveContext.Options.ExpressionTreeConversion)) { am = body.Compatible (ec); } // // Rewrite expressions into expression tree when targeting Expression<T> // if (am != null && errors == ec.Report.Errors) am = CreateExpressionTree (ec, delegate_type); } } else { if (Block.IsAsync) { var rt = body.ReturnType; if (rt.Kind != MemberKind.Void && rt != ec.Module.PredefinedTypes.Task.TypeSpec && !rt.IsGenericTask) { ec.Report.Error (4010, loc, "Cannot convert async {0} to delegate type `{1}'", GetSignatureForError (), type.GetSignatureForError ()); } AsyncInitializer.Create (ec, body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, rt, loc); } am = body.Compatible (ec); } } catch (CompletionResult) { throw; } catch (Exception e) { throw new InternalErrorException (e, loc); } if (!ec.IsInProbingMode) { compatibles.Add (type, am ?? EmptyExpression.Null); } return am; }
// <summary> // Resolve is used in method definitions // </summary> public virtual TypeSpec Resolve (IMemberContext rc, int index) { if (parameter_type != null) return parameter_type; if (attributes != null) attributes.AttachTo (this, rc); var ctor = rc.CurrentMemberDefinition as Constructor; if (ctor != null && ctor.IsPrimaryConstructor) primary_constructor = ctor; parameter_type = texpr.ResolveAsType (rc); if (parameter_type == null) return null; this.idx = index; if ((modFlags & Parameter.Modifier.RefOutMask) != 0 && parameter_type.IsSpecialRuntimeType) { rc.Module.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'", GetSignatureForError ()); return null; } VarianceDecl.CheckTypeVariance (parameter_type, (modFlags & Parameter.Modifier.RefOutMask) != 0 ? Variance.None : Variance.Contravariant, rc); if (parameter_type.IsStatic) { rc.Module.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters", texpr.GetSignatureForError ()); return parameter_type; } if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)) { rc.Module.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'", parameter_type.GetSignatureForError ()); } return parameter_type; }
/// <summary> /// Returns the C# name of a type if possible, or the full type name otherwise /// </summary> static public string CSharpName (TypeSpec t) { return t.GetSignatureForError (); }
public static Constant CreateConstantFromValue (TypeSpec t, object v, Location loc) { switch (t.BuiltinType) { case BuiltinTypeSpec.Type.Int: return new IntConstant (t, (int) v, loc); case BuiltinTypeSpec.Type.String: return new StringConstant (t, (string) v, loc); case BuiltinTypeSpec.Type.UInt: return new UIntConstant (t, (uint) v, loc); case BuiltinTypeSpec.Type.Long: return new LongConstant (t, (long) v, loc); case BuiltinTypeSpec.Type.ULong: return new ULongConstant (t, (ulong) v, loc); case BuiltinTypeSpec.Type.Float: return new FloatConstant (t, (float) v, loc); case BuiltinTypeSpec.Type.Double: return new DoubleConstant (t, (double) v, loc); case BuiltinTypeSpec.Type.Short: return new ShortConstant (t, (short) v, loc); case BuiltinTypeSpec.Type.UShort: return new UShortConstant (t, (ushort) v, loc); case BuiltinTypeSpec.Type.SByte: return new SByteConstant (t, (sbyte) v, loc); case BuiltinTypeSpec.Type.Byte: return new ByteConstant (t, (byte) v, loc); case BuiltinTypeSpec.Type.Char: return new CharConstant (t, (char) v, loc); case BuiltinTypeSpec.Type.Bool: return new BoolConstant (t, (bool) v, loc); case BuiltinTypeSpec.Type.Decimal: return new DecimalConstant (t, (decimal) v, loc); } if (t.IsEnum) { var real_type = EnumSpec.GetUnderlyingType (t); return new EnumConstant (CreateConstantFromValue (real_type, v, loc), t); } if (v == null) { if (t.IsNullableType) return Nullable.LiftedNull.Create (t, loc); if (TypeSpec.IsReferenceType (t)) return new NullConstant (t, loc); } #if STATIC throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'", v, t.GetSignatureForError ()); #else return null; #endif }
// // User-defined conversions // static Expression UserDefinedConversion (ResolveContext ec, Expression source, TypeSpec target, bool implicitOnly, Location loc) { List<MethodSpec> candidates = null; // // If S or T are nullable types, source_type and target_type are their underlying types // otherwise source_type and target_type are equal to S and T respectively. // TypeSpec source_type = source.Type; TypeSpec target_type = target; Expression source_type_expr; if (source_type.IsNullableType) { // No implicit conversion S? -> T for non-reference types if (implicitOnly && !TypeSpec.IsReferenceType (target_type) && !target_type.IsNullableType) return null; source_type_expr = Nullable.Unwrap.Create (source); source_type = source_type_expr.Type; } else { source_type_expr = source; } if (target_type.IsNullableType) target_type = Nullable.NullableInfo.GetUnderlyingType (target_type); // Only these containers can contain a user defined implicit or explicit operators const MemberKind user_conversion_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.TypeParameter; if ((source_type.Kind & user_conversion_kinds) != 0 && source_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) { bool declared_only = source_type.IsStruct; var operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Implicit, declared_only); if (operators != null) { FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, implicitOnly, ref candidates); } if (!implicitOnly) { operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Explicit, declared_only); if (operators != null) { FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, false, ref candidates); } } } if ((target.Kind & user_conversion_kinds) != 0 && target_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) { bool declared_only = target.IsStruct || implicitOnly; var operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Implicit, declared_only); if (operators != null) { FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, implicitOnly, ref candidates); } if (!implicitOnly) { operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Explicit, declared_only); if (operators != null) { FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, false, ref candidates); } } } if (candidates == null) return null; // // Find the most specific conversion operator // MethodSpec most_specific_operator; TypeSpec s_x, t_x; if (candidates.Count == 1) { most_specific_operator = candidates[0]; s_x = most_specific_operator.Parameters.Types[0]; t_x = most_specific_operator.ReturnType; } else { // // Pass original source type to find the best match against input type and // not the unwrapped expression // s_x = FindMostSpecificSource (candidates, source.Type, source_type_expr, !implicitOnly); if (s_x == null) return null; t_x = FindMostSpecificTarget (candidates, target, !implicitOnly); if (t_x == null) return null; most_specific_operator = null; for (int i = 0; i < candidates.Count; ++i) { if (candidates[i].ReturnType == t_x && candidates[i].Parameters.Types[0] == s_x) { most_specific_operator = candidates[i]; break; } } if (most_specific_operator == null) { MethodSpec ambig_arg = null; foreach (var candidate in candidates) { if (candidate.ReturnType == t_x) most_specific_operator = candidate; else if (candidate.Parameters.Types[0] == s_x) ambig_arg = candidate; } ec.Report.Error (457, loc, "Ambiguous user defined operators `{0}' and `{1}' when converting from `{2}' to `{3}'", ambig_arg.GetSignatureForError (), most_specific_operator.GetSignatureForError (), source.Type.GetSignatureForError (), target.GetSignatureForError ()); return ErrorExpression.Instance; } } // // Convert input type when it's different to best operator argument // if (s_x != source_type) { var c = source as Constant; if (c != null) { source = c.TryReduce (ec, s_x, loc); } else { source = implicitOnly ? ImplicitConversionStandard (ec, source_type_expr, s_x, loc) : ExplicitConversionStandard (ec, source_type_expr, s_x, loc); } } else { source = source_type_expr; } source = new UserCast (most_specific_operator, source, loc).Resolve (ec); // // Convert result type when it's different to best operator return type // if (t_x != target_type) { // // User operator is of T?, no need to lift it // if (t_x == target && t_x.IsNullableType) return source; source = implicitOnly ? ImplicitConversionStandard (ec, source, target_type, loc) : ExplicitConversionStandard (ec, source, target_type, loc); if (source == null) return null; } // // Source expression is of nullable type, lift the result in the case it's null and // not nullable/lifted user operator is used // if (source_type_expr is Nullable.Unwrap && !s_x.IsNullableType && (TypeSpec.IsReferenceType (target) || target_type != target)) source = new Nullable.Lifted (source, source_type_expr, target).Resolve (ec); else if (target_type != target) source = Nullable.Wrap.Create (source, target); return source; }
public override bool Define () { if (IsInterface) { ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW)); flags = MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual; } else { Parent.PartialContainer.MethodModifiersValid (this); flags = ModifiersExtensions.MethodAttr (ModFlags); } if (IsExplicitImpl) { InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent); if (InterfaceType == null) return false; if ((ModFlags & Modifiers.PARTIAL) != 0) { Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface", GetSignatureForError ()); } if (!InterfaceType.IsInterface) { Report.SymbolRelatedToPreviousError (InterfaceType); Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface", InterfaceType.GetSignatureForError ()); } else { Parent.PartialContainer.VerifyImplements (this); } ModifiersExtensions.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location, Report); } return base.Define (); }
TypeSpec CompatibleChecks (ResolveContext ec, TypeSpec delegate_type) { if (delegate_type.IsDelegate) return delegate_type; if (delegate_type.IsExpressionTreeType) { delegate_type = delegate_type.TypeArguments [0]; if (delegate_type.IsDelegate) return delegate_type; ec.Report.Error (835, loc, "Cannot convert `{0}' to an expression tree of non-delegate type `{1}'", GetSignatureForError (), delegate_type.GetSignatureForError ()); return null; } ec.Report.Error (1660, loc, "Cannot convert `{0}' to non-delegate type `{1}'", GetSignatureForError (), delegate_type.GetSignatureForError ()); return null; }
AnonymousMethodBody CompatibleMethodBody (ResolveContext ec, TypeInferenceContext tic, TypeSpec return_type, TypeSpec delegate_type) { ParametersCompiled p = ResolveParameters (ec, tic, delegate_type); if (p == null) return null; ParametersBlock b = ec.IsInProbingMode ? (ParametersBlock) Block.PerformClone () : Block; if (b.IsAsync) { var rt = return_type; if (rt != null && rt.Kind != MemberKind.Void && rt != ec.Module.PredefinedTypes.Task.TypeSpec && !rt.IsGenericTask) { ec.Report.Error (4010, loc, "Cannot convert async {0} to delegate type `{1}'", GetSignatureForError (), delegate_type.GetSignatureForError ()); return null; } b = b.ConvertToAsyncTask (ec, ec.CurrentMemberDefinition.Parent.PartialContainer, p, return_type, loc); } return CompatibleMethodFactory (return_type ?? InternalType.Arglist, delegate_type, p, b); }
static bool CheckConstraint (IMemberContext mc, MemberSpec context, TypeSpec atype, TypeParameterSpec tparam, Location loc) { // // First, check the `class' and `struct' constraints. // if (tparam.HasSpecialClass && !TypeManager.IsReferenceType (atype)) { mc.Compiler.Report.Error (452, loc, "The type `{0}' must be a reference type in order to use it as type parameter `{1}' in the generic type or method `{2}'", TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ()); return false; } if (tparam.HasSpecialStruct && (!TypeManager.IsValueType (atype) || TypeManager.IsNullableType (atype))) { mc.Compiler.Report.Error (453, loc, "The type `{0}' must be a non-nullable value type in order to use it as type parameter `{1}' in the generic type or method `{2}'", TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ()); return false; } // // The class constraint comes next. // if (tparam.HasTypeConstraint) { CheckConversion (mc, context, atype, tparam, tparam.BaseType, loc); } // // Now, check the interfaces and type parameters constraints // if (tparam.Interfaces != null) { if (TypeManager.IsNullableType (atype)) { mc.Compiler.Report.Error (313, loc, "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. The nullable type `{0}' never satisfies interface constraint", atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError ()); } else { foreach (TypeSpec iface in tparam.Interfaces) { CheckConversion (mc, context, atype, tparam, iface, loc); } } } // // Finally, check the constructor constraint. // if (!tparam.HasSpecialConstructor) return true; if (!HasDefaultConstructor (atype)) { mc.Compiler.Report.SymbolRelatedToPreviousError (atype); mc.Compiler.Report.Error (310, loc, "The type `{0}' must have a public parameterless constructor in order to use it as parameter `{1}' in the generic type or method `{2}'", TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ()); return false; } return true; }