public static MethodSpec GetConstructor(TypeSpec nullableType) { return((MethodSpec)MemberCache.FindMember(nullableType, MemberFilter.Constructor(ParametersCompiled.CreateFullyResolved(GetUnderlyingType(nullableType))), BindingRestriction.DeclaredOnly)); }
public static MethodSpec GetHasValue(TypeSpec nullableType) { return((MethodSpec)MemberCache.FindMember(nullableType, MemberFilter.Method("get_HasValue", 0, ParametersCompiled.EmptyReadOnlyParameters, null), BindingRestriction.None)); }
public override bool Resolve(BlockContext bc) { if (bc.CurrentBlock is Linq.QueryBlock) { bc.Report.Error(1995, loc, "The `await' operator may only be used in a query expression within the first collection expression of the initial `from' clause or within the collection expression of a `join' clause"); return(false); } if (!base.Resolve(bc)) { return(false); } Arguments args = new Arguments(0); type = expr.Type; // // The await expression is of dynamic type // if (type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { result_type = type; expr = new Invocation(new MemberAccess(expr, "GetAwaiter"), args).Resolve(bc); return(true); } // // Check whether the expression is awaitable // Expression ama = new AwaitableMemberAccess(expr).Resolve(bc); if (ama == null) { return(false); } var errors_printer = new SessionReportPrinter(); var old = bc.Report.SetPrinter(errors_printer); ama = new Invocation(ama, args).Resolve(bc); bc.Report.SetPrinter(old); if (errors_printer.ErrorsCount > 0 || !MemberAccess.IsValidDotExpression(ama.Type)) { bc.Report.Error(1986, expr.Location, "The `await' operand type `{0}' must have suitable GetAwaiter method", expr.Type.GetSignatureForError()); return(false); } var awaiter_type = ama.Type; expr = ama; // // Predefined: bool IsCompleted { get; } // is_completed = MemberCache.FindMember(awaiter_type, MemberFilter.Property("IsCompleted", bc.Module.Compiler.BuiltinTypes.Bool), BindingRestriction.InstanceOnly) as PropertySpec; if (is_completed == null || !is_completed.HasGet) { Error_WrongAwaiterPattern(bc, awaiter_type); return(false); } // // Predefined: GetResult () // // The method return type is also result type of await expression // get_result = MemberCache.FindMember(awaiter_type, MemberFilter.Method("GetResult", 0, ParametersCompiled.EmptyReadOnlyParameters, null), BindingRestriction.InstanceOnly) as MethodSpec; if (get_result == null) { Error_WrongAwaiterPattern(bc, awaiter_type); return(false); } // // Predefined: INotifyCompletion.OnCompleted (System.Action) // var nc = bc.Module.PredefinedTypes.INotifyCompletion; if (nc.Define() && !awaiter_type.ImplementsInterface(nc.TypeSpec, false)) { bc.Report.Error(4027, loc, "The awaiter type `{0}' must implement interface `{1}'", awaiter_type.GetSignatureForError(), nc.GetSignatureForError()); return(false); } result_type = get_result.ReturnType; return(true); }
public static MethodSpec GetConstructor(TypeSpec delType) { var ctor = MemberCache.FindMember(delType, MemberFilter.Constructor(null), BindingRestriction.DeclaredOnly); return((MethodSpec)ctor); }
void EmitActionLoad(EmitContext ec) { ec.EmitThis(); ec.Emit(OpCodes.Ldftn, StateMachineMethod.Spec); ec.Emit(OpCodes.Newobj, (MethodSpec)MemberCache.FindMember(action, MemberFilter.Constructor(null), BindingRestriction.DeclaredOnly)); }
public override bool Resolve(BlockContext bc) { if (!base.Resolve(bc)) { return(false); } Arguments args = new Arguments(0); type = expr.Type; // // The await expression is of dynamic type // if (type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { result_type = type; awaiter = ((AsyncTaskStorey)machine_initializer.Storey).AddAwaiter(type, loc); expr = new Invocation(new MemberAccess(expr, "GetAwaiter"), args).Resolve(bc); return(true); } // // Check whether the expression is awaitable // Expression ama = new AwaitableMemberAccess(expr).Resolve(bc); if (ama == null) { return(false); } var errors_printer = new SessionReportPrinter(); var old = bc.Report.SetPrinter(errors_printer); ama = new Invocation(ama, args).Resolve(bc); bc.Report.SetPrinter(old); if (errors_printer.ErrorsCount > 0 || !MemberAccess.IsValidDotExpression(ama.Type)) { bc.Report.Error(1986, expr.Location, "The `await' operand type `{0}' must have suitable GetAwaiter method", expr.Type.GetSignatureForError()); return(false); } var awaiter_type = ama.Type; awaiter = ((AsyncTaskStorey)machine_initializer.Storey).AddAwaiter(awaiter_type, loc); expr = ama; // // Predefined: bool IsCompleted { get; } // is_completed = MemberCache.FindMember(awaiter_type, MemberFilter.Property("IsCompleted", bc.Module.Compiler.BuiltinTypes.Bool), BindingRestriction.InstanceOnly) as PropertySpec; if (is_completed == null || !is_completed.HasGet) { Error_WrongAwaiterPattern(bc, awaiter_type); return(false); } // // Predefined: OnCompleted (Action) // if (bc.Module.PredefinedTypes.Action.Define()) { on_completed = MemberCache.FindMember(awaiter_type, MemberFilter.Method("OnCompleted", 0, ParametersCompiled.CreateFullyResolved(bc.Module.PredefinedTypes.Action.TypeSpec), bc.Module.Compiler.BuiltinTypes.Void), BindingRestriction.InstanceOnly) as MethodSpec; if (on_completed == null) { Error_WrongAwaiterPattern(bc, awaiter_type); return(false); } } // // Predefined: GetResult () // // The method return type is also result type of await expression // get_result = MemberCache.FindMember(awaiter_type, MemberFilter.Method("GetResult", 0, ParametersCompiled.EmptyReadOnlyParameters, null), BindingRestriction.InstanceOnly) as MethodSpec; if (get_result == null) { Error_WrongAwaiterPattern(bc, awaiter_type); return(false); } result_type = get_result.ReturnType; return(true); }
/// <summary> /// This function tells whether one of our base classes implements /// the given method (which turns out, it is valid to have an interface /// implementation in a base /// </summary> bool BaseImplements(TypeSpec iface_type, MethodSpec mi, out MethodSpec base_method) { base_method = null; bool base_can_implement = true; TypeSpec lookup_type; // // Special handling for properties/indexers which cannot have accessors // implementing an interface found in different types (e.g. current and base) // if (mi.IsAccessor && container.Interfaces != null) { bool new_implementation = false; foreach (var iface in container.Interfaces) { if (TypeSpecComparer.IsEqual(iface, iface_type)) { new_implementation = true; break; } } if (new_implementation) { MemberFilter filter; bool getter = mi.Name [0] == 'g'; if (mi.Parameters.Count > (getter ? 0 : 1)) { var indexer_params = getter ? mi.Parameters : IndexerSpec.CreateParametersFromSetter(mi, mi.Parameters.Count - 1); var ptype = getter ? mi.ReturnType : mi.Parameters.Types [mi.Parameters.Count - 1]; filter = new MemberFilter(MemberCache.IndexerNameAlias, 0, MemberKind.Indexer, indexer_params, ptype); } else { var pname = mi.Name.Substring(4); var ptype = getter ? mi.ReturnType : mi.Parameters.Types [0]; filter = MemberFilter.Property(pname, ptype); } var prop = MemberCache.FindMember(container.CurrentType, filter, BindingRestriction.DeclaredOnly | BindingRestriction.InstanceOnly); if (prop != null && (prop.Modifiers & Modifiers.NEW) != 0) { base_can_implement = false; } } } if (base_can_implement) { lookup_type = container.BaseType; if (lookup_type.ImplementsInterface(iface_type, false)) { return(true); } } else { lookup_type = container.CurrentType; } // // Setup filter with no return type to give better error message // about mismatch at return type when the check bellow rejects them // var parameters = mi.Parameters; MethodSpec close_match = null; while (true) { var candidates = MemberCache.FindMembers(lookup_type, mi.Name, !base_can_implement); if (candidates == null) { base_method = close_match; return(false); } MethodSpec similar_candidate = null; foreach (var candidate in candidates) { if (candidate.Kind != MemberKind.Method) { continue; } if (candidate.Arity != mi.Arity) { continue; } var candidate_param = ((MethodSpec)candidate).Parameters; if (!TypeSpecComparer.Override.IsEqual(parameters.Types, candidate_param.Types)) { continue; } bool modifiers_match = true; for (int i = 0; i < parameters.Count; ++i) { // // First check exact ref/out match // if ((parameters.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) == (candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask)) { continue; } modifiers_match = false; // // Different in ref/out only // if ((parameters.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != (candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask)) { if (similar_candidate == null) { if (!candidate.IsPublic) { break; } if (!TypeSpecComparer.Override.IsEqual(mi.ReturnType, ((MethodSpec)candidate).ReturnType)) { break; } // It's used for ref/out ambiguity overload check similar_candidate = (MethodSpec)candidate; } continue; } similar_candidate = null; break; } if (!modifiers_match) { continue; } // // From this point the candidate is used for detailed error reporting // because it's very close match to what we are looking for // var m = (MethodSpec)candidate; if (!m.IsPublic) { if (close_match == null) { close_match = m; } continue; } if (!TypeSpecComparer.Override.IsEqual(mi.ReturnType, m.ReturnType)) { if (close_match == null) { close_match = m; } continue; } base_method = m; if (mi.IsGeneric && !Method.CheckImplementingMethodConstraints(container, m, mi)) { return(true); } } if (base_method != null) { if (similar_candidate != null) { Report.SymbolRelatedToPreviousError(similar_candidate); Report.SymbolRelatedToPreviousError(mi); Report.SymbolRelatedToPreviousError(container); Report.Warning(1956, 1, ((MemberCore)base_method.MemberDefinition).Location, "The interface method `{0}' implementation is ambiguous between following methods: `{1}' and `{2}' in type `{3}'", mi.GetSignatureForError(), base_method.GetSignatureForError(), similar_candidate.GetSignatureForError(), container.GetSignatureForError()); } break; } if (!base_can_implement) { return(false); } lookup_type = candidates[0].DeclaringType.BaseType; if (lookup_type == null) { base_method = close_match; return(false); } } if (!base_method.IsVirtual) { #if STATIC var base_builder = base_method.GetMetaInfo() as MethodBuilder; if (base_builder != null) { // // We can avoid creating a proxy if base_method can be marked 'final virtual'. This can // be done for all methods from compiled assembly // base_builder.__SetAttributes(base_builder.Attributes | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot); return(true); } #endif DefineProxy(iface_type, base_method, mi); } return(true); }
public override bool Resolve(BlockContext bc) { if (!base.Resolve(bc)) { return(false); } type = expr.Type; // // The task result is of dynamic type // if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { throw new NotImplementedException("dynamic await"); } // // Check whether the expression is awaitable // Expression ama = new AwaitableMemberAccess(expr).Resolve(bc); if (ama == null) { return(false); } Arguments args = new Arguments(0); var errors_printer = new SessionReportPrinter(); var old = bc.Report.SetPrinter(errors_printer); ama = new Invocation(ama, args).Resolve(bc); if (errors_printer.ErrorsCount > 0 || !MemberAccess.IsValidDotExpression(ama.Type)) { bc.Report.SetPrinter(old); Error_WrongGetAwaiter(bc, loc, expr.Type); return(false); } var awaiter_type = ama.Type; awaiter = ((AsyncTaskStorey)machine_initializer.Storey).AddAwaiter(awaiter_type, loc); expr = ama; // // Predefined: bool IsCompleted { get; } // var is_completed_ma = new MemberAccess(expr, "IsCompleted").Resolve(bc); if (is_completed_ma != null) { is_completed = is_completed_ma as PropertyExpr; if (is_completed != null && is_completed.Type.BuiltinType == BuiltinTypeSpec.Type.Bool && is_completed.IsInstance && is_completed.Getter != null) { // valid } else { bc.Report.SetPrinter(old); Error_WrongAwaiterPattern(bc, awaiter_type); return(false); } } bc.Report.SetPrinter(old); if (errors_printer.ErrorsCount > 0) { Error_WrongAwaiterPattern(bc, awaiter_type); return(false); } // // Predefined: OnCompleted (Action) // if (bc.Module.PredefinedTypes.Action.Define()) { on_completed = MemberCache.FindMember(awaiter_type, MemberFilter.Method("OnCompleted", 0, ParametersCompiled.CreateFullyResolved(bc.Module.PredefinedTypes.Action.TypeSpec), bc.Module.Compiler.BuiltinTypes.Void), BindingRestriction.InstanceOnly) as MethodSpec; if (on_completed == null) { Error_WrongAwaiterPattern(bc, awaiter_type); return(false); } } // // Predefined: GetResult () // // The method return type is also result type of await expression // get_result = MemberCache.FindMember(awaiter_type, MemberFilter.Method("GetResult", 0, ParametersCompiled.EmptyReadOnlyParameters, null), BindingRestriction.InstanceOnly) as MethodSpec; if (get_result == null) { Error_WrongAwaiterPattern(bc, awaiter_type); return(false); } return(true); }
public static MethodSpec GetGetValueOrDefault(TypeSpec nullableType) { return (MethodSpec) MemberCache.FindMember (nullableType, MemberFilter.Method ("GetValueOrDefault", 0, ParametersCompiled.EmptyReadOnlyParameters, null), BindingRestriction.None); }