Пример #1
0
		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);
			}
		}
Пример #2
0
		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);
		}
Пример #3
0
		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;
		}
Пример #4
0
		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;
		}
Пример #5
0
		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 ());
				}
			}
		}
Пример #6
0
		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;
		}
Пример #7
0
		//
		// 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);
			}
		}
Пример #8
0
		public static void Error1599 (Location loc, TypeSpec t, Report Report)
		{
			Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", t.GetSignatureForError ());
		}
Пример #9
0
		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);
		}
Пример #10
0
			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 ());
			}
Пример #11
0
		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 ());
			}
		}
Пример #12
0
        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 ());
        }
Пример #13
0
		//
		// 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;
		}
Пример #14
0
		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;
		}
Пример #15
0
		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);
				}
			}
		}
Пример #16
0
		//
		// 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;
		}
Пример #17
0
		// <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;
		}
Пример #18
0
	/// <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 ();
	}
Пример #19
0
		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
		}
Пример #20
0
		//
		// 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;
		}
Пример #21
0
		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 ();
		}
Пример #22
0
		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;
		}
Пример #23
0
		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);
		}
Пример #24
0
		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;
		}