void ConvertConstraints(NRefactoryAST.TemplateDefinition template, DefaultTypeParameter typeParameter) { foreach (NRefactoryAST.TypeReference typeRef in template.Bases) { if (typeRef == NRefactoryAST.TypeReference.NewConstraint) { typeParameter.HasConstructableConstraint = true; } else if (typeRef == NRefactoryAST.TypeReference.ClassConstraint) { typeParameter.HasReferenceTypeConstraint = true; } else if (typeRef == NRefactoryAST.TypeReference.StructConstraint) { typeParameter.HasValueTypeConstraint = true; } else { IReturnType rt = CreateReturnType(typeRef, typeParameter.Method, TypeVisitor.ReturnTypeOptions.None); if (rt != null) { typeParameter.Constraints.Add(rt); } } } }
DefaultTypeParameter ConvertConstraints(AST.TemplateDefinition template, DefaultTypeParameter typeParameter) { foreach (AST.TypeReference typeRef in template.Bases) { if (typeRef == AST.TypeReference.NewConstraint) { typeParameter.HasConstructableConstraint = true; } else if (typeRef == AST.TypeReference.ClassConstraint) { typeParameter.HasReferenceTypeConstraint = true; } else if (typeRef == AST.TypeReference.StructConstraint) { typeParameter.HasValueTypeConstraint = true; } else { IReturnType rt = CreateReturnType(typeRef); if (rt != null) { typeParameter.Constraints.Add(rt); } } } return(typeParameter); }
public void TypeParameterWithValueTypeConstraint() { ITypeParameter t = new DefaultTypeParameter(compilation, EntityType.TypeDefinition, 0, "T", hasValueTypeConstraint: true); Assert.AreEqual(C.None, conversions.ImplicitConversion(SpecialType.NullType, t)); Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object))); Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, SpecialType.Dynamic)); Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType)))); }
public void TypeParameterWithValueTypeConstraint() { DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); t.HasValueTypeConstraint = true; Assert.IsFalse(conversions.ImplicitConversion(SharedTypes.Null, t)); Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic)); Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); }
public void TypeParameterWithReferenceTypeConstraint() { DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); t.HasReferenceTypeConstraint = true; Assert.AreEqual(C.NullLiteralConversion, conversions.ImplicitConversion(SharedTypes.Null, t)); Assert.AreEqual(C.ImplicitReferenceConversion, conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); Assert.AreEqual(C.ImplicitReferenceConversion, conversions.ImplicitConversion(t, SharedTypes.Dynamic)); Assert.AreEqual(C.None, conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); }
public void TypeParameterWithClassConstraint() { DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); t.Constraints.Add(ctx.GetTypeDefinition(typeof(StringComparer))); Assert.IsTrue(conversions.ImplicitConversion(SharedTypes.Null, t)); Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic)); Assert.IsFalse(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(StringComparer)))); Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IComparer)))); Assert.IsFalse(conversions.ImplicitConversion(t, typeof(IComparer <int>).ToTypeReference().Resolve(ctx))); Assert.IsTrue(conversions.ImplicitConversion(t, typeof(IComparer <string>).ToTypeReference().Resolve(ctx))); }
public void InferFromObjectAndFromNullLiteral() { // M<T>(T a, T b); ITypeParameter tp = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T"); // M(new object(), null); bool success; Assert.AreEqual( new [] { compilation.FindType(KnownTypeCode.Object) }, ti.InferTypeArguments(new [] { tp }, new [] { new ResolveResult(compilation.FindType(KnownTypeCode.Object)), new ResolveResult(SpecialType.NullType) }, new [] { tp, tp }, out success)); Assert.IsTrue(success); }
public void ArrayToEnumerable() { ITypeParameter tp = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T"); IType stringType = compilation.FindType(KnownTypeCode.String); ITypeDefinition enumerableType = compilation.FindType(KnownTypeCode.IEnumerableOfT).GetDefinition(); bool success; Assert.AreEqual( new [] { stringType }, ti.InferTypeArguments(new [] { tp }, new [] { new ResolveResult(new ArrayType(compilation, stringType)) }, new [] { new ParameterizedType(enumerableType, new [] { tp }) }, out success)); Assert.IsTrue(success); }
public void ArrayToEnumerable() { ITypeParameter tp = new DefaultTypeParameter(EntityType.Method, 0, "T"); IType stringType = KnownTypeReference.String.Resolve(ctx); ITypeDefinition enumerableType = ctx.GetTypeDefinition(typeof(IEnumerable <>)); bool success; Assert.AreEqual( new [] { stringType }, ti.InferTypeArguments(new [] { tp }, new [] { new ResolveResult(new ArrayType(stringType)) }, new [] { new ParameterizedType(enumerableType, new [] { tp }) }, out success)); Assert.IsTrue(success); }
public void UnconstrainedTypeParameter() { ITypeParameter t = new DefaultTypeParameter(compilation, EntityType.TypeDefinition, 0, "T"); ITypeParameter t2 = new DefaultTypeParameter(compilation, EntityType.TypeDefinition, 1, "T2"); ITypeParameter tm = new DefaultTypeParameter(compilation, EntityType.Method, 0, "TM"); Assert.AreEqual(C.None, conversions.ImplicitConversion(SpecialType.NullType, t)); Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object))); Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, SpecialType.Dynamic)); Assert.AreEqual(C.None, conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType)))); Assert.AreEqual(C.IdentityConversion, conversions.ImplicitConversion(t, t)); Assert.AreEqual(C.None, conversions.ImplicitConversion(t2, t)); Assert.AreEqual(C.None, conversions.ImplicitConversion(t, t2)); Assert.AreEqual(C.None, conversions.ImplicitConversion(t, tm)); Assert.AreEqual(C.None, conversions.ImplicitConversion(tm, t)); }
public void TypeParameterWithInterfaceConstraint() { DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); t.Constraints.Add(ctx.GetTypeDefinition(typeof(IList))); Assert.AreEqual(C.None, conversions.ImplicitConversion(SharedTypes.Null, t)); Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, SharedTypes.Dynamic)); Assert.AreEqual(C.None, conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IList)))); Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IEnumerable)))); }
public void UnconstrainedTypeParameter() { DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); DefaultTypeParameter t2 = new DefaultTypeParameter(EntityType.TypeDefinition, 1, "T2"); DefaultTypeParameter tm = new DefaultTypeParameter(EntityType.Method, 0, "TM"); Assert.IsFalse(conversions.ImplicitConversion(SharedTypes.Null, t)); Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic)); Assert.IsFalse(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); Assert.IsTrue(conversions.ImplicitConversion(t, t)); Assert.IsFalse(conversions.ImplicitConversion(t2, t)); Assert.IsFalse(conversions.ImplicitConversion(t, t2)); Assert.IsFalse(conversions.ImplicitConversion(t, tm)); Assert.IsFalse(conversions.ImplicitConversion(tm, t)); }
public void CannotInferFromMethodParameterTypes() { // static void M<A, B>(Func<A, B> f) {} // M(int.Parse); // type inference fails var A = new DefaultTypeParameter(compilation, EntityType.Method, 0, "A"); var B = new DefaultTypeParameter(compilation, EntityType.Method, 1, "B"); IType declType = compilation.FindType(typeof(int)); var methods = new MethodListWithDeclaringType(declType, declType.GetMethods(m => m.Name == "Parse")); var argument = new MethodGroupResolveResult(new TypeResolveResult(declType), "Parse", new[] { methods }, new IType[0]); bool success; ti.InferTypeArguments(new [] { A, B }, new [] { argument }, new [] { new ParameterizedType(compilation.FindType(typeof(Func <,>)).GetDefinition(), new[] { A, B }) }, out success); Assert.IsFalse(success); }
public void EnumerableToArrayInContravariantType() { ITypeParameter tp = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T"); IType stringType = compilation.FindType(KnownTypeCode.String); ITypeDefinition enumerableType = compilation.FindType(typeof(IEnumerable <>)).GetDefinition(); ITypeDefinition comparerType = compilation.FindType(typeof(IComparer <>)).GetDefinition(); var comparerOfIEnumerableOfString = new ParameterizedType(comparerType, new [] { new ParameterizedType(enumerableType, new [] { stringType }) }); var comparerOfTpArray = new ParameterizedType(comparerType, new [] { new ArrayType(compilation, tp) }); bool success; Assert.AreEqual( new [] { stringType }, ti.InferTypeArguments(new [] { tp }, new [] { new ResolveResult(comparerOfIEnumerableOfString) }, new [] { comparerOfTpArray }, out success)); Assert.IsTrue(success); }
public void TypeParameterWithClassConstraint() { ITypeParameter t = new DefaultTypeParameter(compilation, EntityType.TypeDefinition, 0, "T", constraints: new[] { compilation.FindType(typeof(StringComparer)) }); Assert.AreEqual(C.NullLiteralConversion, conversions.ImplicitConversion(SpecialType.NullType, t)); Assert.AreEqual(C.ImplicitReferenceConversion, conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object))); Assert.AreEqual(C.ImplicitReferenceConversion, conversions.ImplicitConversion(t, SpecialType.Dynamic)); Assert.AreEqual(C.None, conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType)))); Assert.AreEqual(C.ImplicitReferenceConversion, conversions.ImplicitConversion(t, compilation.FindType(typeof(StringComparer)))); Assert.AreEqual(C.ImplicitReferenceConversion, conversions.ImplicitConversion(t, compilation.FindType(typeof(IComparer)))); Assert.AreEqual(C.None, conversions.ImplicitConversion(t, compilation.FindType(typeof(IComparer <int>)))); Assert.AreEqual(C.ImplicitReferenceConversion, conversions.ImplicitConversion(t, compilation.FindType(typeof(IComparer <string>)))); }
public void InferFromMethodReturnType() { // static void M<T>(Func<T> f) {} // M(Console.ReadKey); // type inference produces ConsoleKeyInfo var T = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T"); IType declType = compilation.FindType(typeof(Console)); var methods = new MethodListWithDeclaringType(declType, declType.GetMethods(m => m.Name == "ReadKey")); var argument = new MethodGroupResolveResult(new TypeResolveResult(declType), "ReadKey", new[] { methods }, new IType[0]); bool success; Assert.AreEqual( new [] { compilation.FindType(typeof(ConsoleKeyInfo)) }, ti.InferTypeArguments(new [] { T }, new [] { argument }, new [] { new ParameterizedType(compilation.FindType(typeof(Func <>)).GetDefinition(), new[] { T }) }, out success)); Assert.IsTrue(success); }
public void ArrayToReadOnlyList() { ITypeParameter tp = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T"); IType stringType = compilation.FindType(KnownTypeCode.String); ITypeDefinition readOnlyListType = compilation.FindType(KnownTypeCode.IReadOnlyListOfT).GetDefinition(); if (readOnlyListType == null) { Assert.Ignore(".NET 4.5 IReadOnlyList not available"); } bool success; Assert.AreEqual( new [] { stringType }, ti.InferTypeArguments(new [] { tp }, new [] { new ResolveResult(new ArrayType(compilation, stringType)) }, new [] { new ParameterizedType(readOnlyListType, new [] { tp }) }, out success)); Assert.IsTrue(success); }
public void ArrayToListWithArrayCovariance() { ITypeParameter tp = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T"); IType objectType = compilation.FindType(KnownTypeCode.Object); IType stringType = compilation.FindType(KnownTypeCode.String); ITypeDefinition listType = compilation.FindType(KnownTypeCode.IListOfT).GetDefinition(); // void M<T>(IList<T> a, T b); // M(new string[0], new object()); bool success; Assert.AreEqual( new [] { objectType }, ti.InferTypeArguments( new [] { tp }, new [] { new ResolveResult(new ArrayType(compilation, stringType)), new ResolveResult(objectType) }, new [] { new ParameterizedType(listType, new [] { tp }), (IType)tp }, out success)); Assert.IsTrue(success); }
public ITypeParameter Register(GenericParameter parameter, IEntity owner, int index) { if (store.TryGetValue(parameter.Id, out var existingP)) { if (!existingP.Owner.Equals(owner)) { throw new Exception($"There is collision in the usage of generic parameter {parameter}: both {existingP.Owner} and {owner} use it."); } if (existingP.Index != index) { throw new Exception($"There is collision in the usage of generic parameter {parameter} on {existingP.Owner}. It is used at index {existingP.Index} and {index}."); } return(existingP); } var newP = new DefaultTypeParameter(owner, index, name: NameSanitizer.SanitizeCsharpName(parameter.Name, lowerCase: null)); SymbolLoader.RegisterTypeParameter(newP, parameter); store.TryAdd(parameter.Id, newP); return(Register(parameter, owner, index)); }
void ConvertTemplates(DefaultClass outerClass, IList <AST.TemplateDefinition> templateList, DefaultClass c) { int outerClassTypeParameterCount = outerClass != null ? outerClass.TypeParameters.Count : 0; if (templateList.Count == 0 && outerClassTypeParameterCount == 0) { c.TypeParameters = DefaultTypeParameter.EmptyTypeParameterList; } else { Debug.Assert(c.TypeParameters.Count == 0); int index = 0; if (outerClassTypeParameterCount > 0) { foreach (DefaultTypeParameter outerTypeParamter in outerClass.TypeParameters) { DefaultTypeParameter p = new DefaultTypeParameter(c, outerTypeParamter.Name, index++); p.HasConstructableConstraint = outerTypeParamter.HasConstructableConstraint; p.HasReferenceTypeConstraint = outerTypeParamter.HasReferenceTypeConstraint; p.HasValueTypeConstraint = outerTypeParamter.HasValueTypeConstraint; p.Attributes.AddRange(outerTypeParamter.Attributes); p.Constraints.AddRange(outerTypeParamter.Constraints); c.TypeParameters.Add(p); } } foreach (AST.TemplateDefinition template in templateList) { c.TypeParameters.Add(new DefaultTypeParameter(c, template.Name, index++)); } // converting the constraints requires that the type parameters are already present for (int i = 0; i < templateList.Count; i++) { ConvertConstraints(templateList[i], (DefaultTypeParameter)c.TypeParameters[i + outerClassTypeParameterCount]); } } }
public void ExpansiveInheritance() { SimpleProjectContent pc = new SimpleProjectContent(); DefaultTypeDefinition a = new DefaultTypeDefinition(pc, string.Empty, "A"); DefaultTypeDefinition b = new DefaultTypeDefinition(pc, string.Empty, "B"); // interface A<in U> a.Kind = TypeKind.Interface; a.TypeParameters.Add(new DefaultTypeParameter(EntityType.TypeDefinition, 0, "U") { Variance = VarianceModifier.Contravariant }); // interface B<X> : A<A<B<X>>> { } DefaultTypeParameter x = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "X"); b.TypeParameters.Add(x); b.BaseTypes.Add(new ParameterizedType(a, new[] { new ParameterizedType(a, new [] { new ParameterizedType(b, new [] { x }) }) })); IType type1 = new ParameterizedType(b, new[] { KnownTypeReference.Double.Resolve(ctx) }); IType type2 = new ParameterizedType(a, new [] { new ParameterizedType(b, new[] { KnownTypeReference.String.Resolve(ctx) }) }); Assert.IsFalse(conversions.ImplicitConversion(type1, type2)); }
public void IEnumerableCovarianceWithDynamic() { ITypeParameter tp = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T"); var ienumerableOfT = new ParameterizedType(compilation.FindType(typeof(IEnumerable <>)).GetDefinition(), new[] { tp }); var ienumerableOfString = compilation.FindType(typeof(IEnumerable <string>)); var ienumerableOfDynamic = compilation.FindType(typeof(IEnumerable <ReflectionHelper.Dynamic>)); // static T M<T>(IEnumerable<T> x, IEnumerable<T> y) {} // M(IEnumerable<dynamic>, IEnumerable<string>); -> should infer T=dynamic, no ambiguity // See http://blogs.msdn.com/b/cburrows/archive/2010/04/01/errata-dynamic-conversions-and-overload-resolution.aspx // for details. bool success; Assert.AreEqual( new [] { SpecialType.Dynamic }, ti.InferTypeArguments( new [] { tp }, new [] { new ResolveResult(ienumerableOfDynamic), new ResolveResult(ienumerableOfString) }, new [] { ienumerableOfT, ienumerableOfT }, out success)); Assert.IsTrue(success); }
GenericReturnType CreateT() { ITypeParameter tp = new DefaultTypeParameter(methodForGenericCalls, "T", 0); return(new GenericReturnType(tp)); }
void ConvertConstraints(AST.TemplateDefinition template, DefaultTypeParameter typeParameter) { foreach (AST.TypeReference typeRef in template.Bases) { if (typeRef == AST.TypeReference.NewConstraint) { typeParameter.HasConstructableConstraint = true; } else if (typeRef == AST.TypeReference.ClassConstraint) { typeParameter.HasReferenceTypeConstraint = true; } else if (typeRef == AST.TypeReference.StructConstraint) { typeParameter.HasValueTypeConstraint = true; } else { IReturnType rt = CreateReturnType(typeRef, typeParameter.Method, TypeVisitor.ReturnTypeOptions.None); if (rt != null) { typeParameter.Constraints.Add(rt); } } } }
void ConvertTemplates(DefaultClass outerClass, IList<AST.TemplateDefinition> templateList, DefaultClass c) { int outerClassTypeParameterCount = outerClass != null ? outerClass.TypeParameters.Count : 0; if (templateList.Count == 0 && outerClassTypeParameterCount == 0) { c.TypeParameters = DefaultTypeParameter.EmptyTypeParameterList; } else { Debug.Assert(c.TypeParameters.Count == 0); int index = 0; if (outerClassTypeParameterCount > 0) { foreach (DefaultTypeParameter outerTypeParamter in outerClass.TypeParameters) { DefaultTypeParameter p = new DefaultTypeParameter(c, outerTypeParamter.Name, index++); p.HasConstructableConstraint = outerTypeParamter.HasConstructableConstraint; p.HasReferenceTypeConstraint = outerTypeParamter.HasReferenceTypeConstraint; p.HasValueTypeConstraint = outerTypeParamter.HasValueTypeConstraint; p.Attributes.AddRange(outerTypeParamter.Attributes); p.Constraints.AddRange(outerTypeParamter.Constraints); c.TypeParameters.Add(p); } } foreach (AST.TemplateDefinition template in templateList) { c.TypeParameters.Add(new DefaultTypeParameter(c, template.Name, index++)); } // converting the constraints requires that the type parameters are already present for (int i = 0; i < templateList.Count; i++) { ConvertConstraints(templateList[i], (DefaultTypeParameter)c.TypeParameters[i + outerClassTypeParameterCount]); } } }