From d87c6385b1af4e42a515a901916de6876d36c64a Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Wed, 27 May 2009 14:11:59 +0000 Subject: [PATCH] 2009-05-27 Marek Safar * generic.cs, parameter.cs, decl.cs, ecore.cs, class.cs, delegate.cs cs-parser.jay, generic-mcs.cs: Report wrong variant types declarations. * driver.cs, rootcontext.cs, report.cs: Add 3.0 language version filter. svn path=/trunk/mcs/; revision=134832 --- mcs/mcs/ChangeLog | 9 +++++ mcs/mcs/class.cs | 11 +++---- mcs/mcs/cs-parser.jay | 7 ++-- mcs/mcs/decl.cs | 11 +++++-- mcs/mcs/delegate.cs | 9 ++--- mcs/mcs/driver.cs | 5 ++- mcs/mcs/ecore.cs | 2 +- mcs/mcs/generic-mcs.cs | 6 +++- mcs/mcs/generic.cs | 75 +++++++++++++++++++++++++----------------- mcs/mcs/parameter.cs | 41 ++++++++++------------- mcs/mcs/report.cs | 3 ++ mcs/mcs/rootcontext.cs | 13 +++++--- 12 files changed, 111 insertions(+), 81 deletions(-) diff --git a/mcs/mcs/ChangeLog b/mcs/mcs/ChangeLog index 12e756fcba8..4fc1c06abb1 100644 --- a/mcs/mcs/ChangeLog +++ b/mcs/mcs/ChangeLog @@ -1,3 +1,12 @@ +2009-05-27 Marek Safar + + * generic.cs, parameter.cs, decl.cs, ecore.cs, class.cs, delegate.cs + cs-parser.jay, generic-mcs.cs: Report wrong variant types + declarations. + + * driver.cs, rootcontext.cs, report.cs: Add 3.0 language version + filter. + 2009-05-26 Rodrigo Kumpera Marek Safar diff --git a/mcs/mcs/class.cs b/mcs/mcs/class.cs index 0a829a5629f..551d5c6e6d3 100644 --- a/mcs/mcs/class.cs +++ b/mcs/mcs/class.cs @@ -1289,7 +1289,7 @@ namespace Mono.CSharp { GenericTypeExpr ct = iface as GenericTypeExpr; if (ct != null) { - if (!ct.CheckConstraints (this) || !ct.VerifyVariantTypeParameters ()) + if (!ct.CheckConstraints (this) || !ct.VerifyVariantTypeParameters (this)) return false; } } @@ -5286,11 +5286,10 @@ namespace Mono.CSharp { "accessible than field `" + GetSignatureForError () + "'"); } } -#if GMCS_SOURCE - if (MemberType.IsGenericParameter && (MemberType.GenericParameterAttributes & GenericParameterAttributes.Contravariant) != 0) { - Report.Error (-33, Location, "Contravariant type parameters can only be used in input positions"); - } -#endif + + var tp = TypeManager.LookupTypeParameter (MemberType); + if (tp != null && tp.Variance == Variance.Contravariant) + tp.ErrorInvalidVariance (this, Variance.Covariant); } protected bool IsTypePermitted () diff --git a/mcs/mcs/cs-parser.jay b/mcs/mcs/cs-parser.jay index c7a5aa16f86..9b535d7e5dc 100644 --- a/mcs/mcs/cs-parser.jay +++ b/mcs/mcs/cs-parser.jay @@ -2769,7 +2769,7 @@ type_parameter : opt_attributes opt_type_parameter_variance IDENTIFIER { LocatedToken lt = (LocatedToken)$3; - $$ = new TypeParameterName (lt.Value, (Attributes)$1, (Variance)$2, lt.Location); + $$ = new TypeParameterName (lt.Value, (Attributes)$1, (Variance) $2, lt.Location); } | error { @@ -4237,8 +4237,9 @@ opt_type_parameter_variance } | type_parameter_variance { - if (RootContext.Version < LanguageVersion.Future) - Report.FeatureIsNotAvailable (lexer.Location, "generic variance"); + if (RootContext.Version <= LanguageVersion.V_3) + Report.FeatureIsNotAvailable (lexer.Location, "generic type variance"); + $$ = $1; } ; diff --git a/mcs/mcs/decl.cs b/mcs/mcs/decl.cs index d49d0641e85..13065b52be7 100644 --- a/mcs/mcs/decl.cs +++ b/mcs/mcs/decl.cs @@ -349,7 +349,7 @@ namespace Mono.CSharp { } } else { if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN | Modifiers.PARTIAL)) == 0) { - if (RootContext.Version >= LanguageVersion.LINQ) { + if (RootContext.Version >= LanguageVersion.V_3) { Property.PropertyMethod pm = this as Property.PropertyMethod; if (pm is Indexer.GetIndexerMethod || pm is Indexer.SetIndexerMethod) pm = null; @@ -1334,9 +1334,14 @@ namespace Mono.CSharp { } } + var variance = name.Variance; + if (name.Variance != Variance.None && !(this is Delegate || this is Interface)) { + Report.Error (1960, name.Location, "Variant type parameters can only be used with interfaces and delegates"); + variance = Variance.None; + } + type_params [i] = new TypeParameter ( - Parent, this, name.Name, constraints, name.OptAttributes, name.Variance, - Location); + Parent, this, name.Name, constraints, name.OptAttributes, variance, Location); AddToContainer (type_params [i], name.Name); } diff --git a/mcs/mcs/delegate.cs b/mcs/mcs/delegate.cs index 24fe57e9120..8a5a7df610f 100644 --- a/mcs/mcs/delegate.cs +++ b/mcs/mcs/delegate.cs @@ -229,12 +229,9 @@ namespace Mono.CSharp { return false; } -#if GMCS_SOURCE - if (ret_type.IsGenericParameter && (ret_type.GenericParameterAttributes & GenericParameterAttributes.Contravariant) != 0) { - Report.Error (-33, Location, "Contravariant type parameters can only be used in input positions"); - return false; - } -#endif + var tp = TypeManager.LookupTypeParameter (ret_type); + if (tp != null && tp.Variance == Variance.Contravariant) + tp.ErrorInvalidVariance (this, Variance.Covariant); // // We don't have to check any others because they are all diff --git a/mcs/mcs/driver.cs b/mcs/mcs/driver.cs index 8c365456a9a..1408000d27f 100644 --- a/mcs/mcs/driver.cs +++ b/mcs/mcs/driver.cs @@ -1506,12 +1506,15 @@ namespace Mono.CSharp case "iso-2": RootContext.Version = LanguageVersion.ISO_2; return true; + case "3": + RootContext.Version = LanguageVersion.V_3; + return true; case "future": RootContext.Version = LanguageVersion.Future; return true; #endif } - Report.Error (1617, "Invalid option `{0}' for /langversion. It must be either `ISO-1', `ISO-2' or `Default'", value); + Report.Error (1617, "Invalid -langversion option `{0}'. It must be `ISO-1', `ISO-2', `3' or `Default'", value); return true; case "/codepage": diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index b465ee56f7f..0248dec0e76 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -294,7 +294,7 @@ namespace Mono.CSharp { // TODO: silent flag is ignored ct.CheckConstraints (ec); - ct.VerifyVariantTypeParameters (); + ct.VerifyVariantTypeParameters (ec); } return te; diff --git a/mcs/mcs/generic-mcs.cs b/mcs/mcs/generic-mcs.cs index 4cb0639ce5b..cba46aabd5d 100644 --- a/mcs/mcs/generic-mcs.cs +++ b/mcs/mcs/generic-mcs.cs @@ -124,6 +124,10 @@ namespace Mono.CSharp { throw new NotImplementedException (); } + + public void ErrorInvalidVariance (MemberCore mc, Variance v) + { + } // // MemberContainer @@ -310,7 +314,7 @@ namespace Mono.CSharp get { throw new NotImplementedException (); } } - public bool VerifyVariantTypeParameters () + public bool VerifyVariantTypeParameters (IResolveContext rc) { throw new NotImplementedException (); } diff --git a/mcs/mcs/generic.cs b/mcs/mcs/generic.cs index 850a1709d04..5495a2421b5 100644 --- a/mcs/mcs/generic.cs +++ b/mcs/mcs/generic.cs @@ -656,9 +656,6 @@ namespace Mono.CSharp { this.decl = decl; this.constraints = constraints; this.variance = variance; - if (variance != Variance.None && !(decl is Interface) && !(decl is Delegate)) { - Report.Error (-36, loc, "Generic variance can only be used with interfaces and delegates"); - } } public GenericConstraints GenericConstraints { @@ -699,6 +696,22 @@ namespace Mono.CSharp { TypeManager.AddTypeParameter (type, this); } + public void ErrorInvalidVariance (MemberCore mc, Variance expected) + { + Report.SymbolRelatedToPreviousError (mc); + string input_variance = Variance == Variance.Contravariant ? "contravariant" : "covariant"; + string gtype_variance; + switch (expected) { + case Variance.Contravariant: gtype_variance = "contravariantly"; break; + case Variance.Covariant: gtype_variance = "covariantly"; break; + default: gtype_variance = "invariantly"; break; + } + + Report.Error (1961, Location, + "The {2} type parameter `{0}' must be {3} valid on `{1}'", + GetSignatureForError (), mc.GetSignatureForError (), input_variance, gtype_variance); + } + /// /// This is the second method which is called during the resolving /// process - in case of class type parameters, we're called from @@ -1364,37 +1377,21 @@ namespace Mono.CSharp { { return ConstraintChecker.CheckConstraints (ec, open_type, gen_params, args.Arguments, loc); } - - static bool IsVariant (Type type) - { - return (type.GenericParameterAttributes & GenericParameterAttributes.VarianceMask) != 0; - } - - static bool IsCovariant (Type type) - { - return (type.GenericParameterAttributes & GenericParameterAttributes.Covariant) != 0; - } - - static bool IsContravariant (Type type) - { - return (type.GenericParameterAttributes & GenericParameterAttributes.Contravariant) != 0; - } - public bool VerifyVariantTypeParameters () + public bool VerifyVariantTypeParameters (IResolveContext rc) { for (int i = 0; i < args.Count; i++) { - Type argument = args.Arguments[i]; - if (argument.IsGenericParameter && IsVariant (argument)) { - if (IsContravariant (argument) && !IsContravariant (gen_params[i])) { - Report.Error (-34, loc, "Contravariant type parameters can only be used " + - "as type arguments in contravariant positions"); - return false; - } - else if (IsCovariant (argument) && !IsCovariant (gen_params[i])) { - Report.Error (-35, loc, "Covariant type parameters can only be used " + - "as type arguments in covariant positions"); - return false; - } + var argument = args.Arguments [i]; + TypeParameter tparam = TypeManager.LookupTypeParameter (argument); + if (tparam == null) + continue; + + if (tparam.Variance == Variance.None) + continue; + + if (tparam.Variance != TypeManager.GetTypeParameterVariance (gen_params [i])) { + var mc = (MemberCore) rc; + tparam.ErrorInvalidVariance (mc, TypeManager.GetTypeParameterVariance (gen_params[i])); } } return true; @@ -1879,6 +1876,22 @@ namespace Mono.CSharp { return LookupTypeContainer (t); } + public static Variance GetTypeParameterVariance (Type type) + { + TypeParameter tparam = LookupTypeParameter (type); + if (tparam != null) + return tparam.Variance; + + switch (type.GenericParameterAttributes & GenericParameterAttributes.VarianceMask) { + case GenericParameterAttributes.Covariant: + return Variance.Covariant; + case GenericParameterAttributes.Contravariant: + return Variance.Contravariant; + default: + return Variance.None; + } + } + /// /// Check whether `a' and `b' may become equal generic types. /// The algorithm to do that is a little bit complicated. diff --git a/mcs/mcs/parameter.cs b/mcs/mcs/parameter.cs index 13969294673..d1b4eada89e 100644 --- a/mcs/mcs/parameter.cs +++ b/mcs/mcs/parameter.cs @@ -361,32 +361,25 @@ namespace Mono.CSharp { return null; } -#if GMCS_SOURCE - if (parameter_type.IsGenericParameter) { - AbstractPropertyEventMethod accessor = ec as AbstractPropertyEventMethod; - if (accessor == null || !accessor.IsDummy) { - if ((parameter_type.GenericParameterAttributes & GenericParameterAttributes.Covariant) != 0) { - Report.Error (-38, Location, "Covariant type parameters cannot be used as method parameters"); - return null; - } else if ((ModFlags & Modifier.ISBYREF) != 0 && - (parameter_type.GenericParameterAttributes & GenericParameterAttributes.Contravariant) != 0) { - Report.Error (-37, Location, "Contravariant type parameters cannot be used in output positions"); - return null; - } + var tp = TypeManager.LookupTypeParameter (parameter_type); + if (tp != null) { + if ((modFlags & Parameter.Modifier.ISBYREF) != 0) { + if (tp.Variance != Variance.None) + tp.ErrorInvalidVariance ((MemberCore) ec, Variance.None); + } else if (tp.Variance == Variance.Covariant) { + tp.ErrorInvalidVariance ((MemberCore) ec, Variance.Contravariant); + } + } else { + if ((parameter_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) { + Report.Error (721, Location, "`{0}': static types cannot be used as parameters", + texpr.GetSignatureForError ()); + return parameter_type; } - return parameter_type; - } -#endif - - if ((parameter_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) { - 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) { - Report.Error (1103, Location, "The type of extension method cannot be `{0}'", - TypeManager.CSharpName (parameter_type)); + if ((modFlags & Modifier.This) != 0 && parameter_type.IsPointer) { + Report.Error (1103, Location, "The type of extension method cannot be `{0}'", + TypeManager.CSharpName (parameter_type)); + } } return parameter_type; diff --git a/mcs/mcs/report.cs b/mcs/mcs/report.cs index cd938eeec63..d8a90577092 100644 --- a/mcs/mcs/report.cs +++ b/mcs/mcs/report.cs @@ -587,6 +587,9 @@ namespace Mono.CSharp { case LanguageVersion.ISO_2: version = "2.0"; break; + case LanguageVersion.V_3: + version = "3.0"; + break; case LanguageVersion.Default_MCS: Report.Error (1644, loc, "Feature `{0}' is not available in Mono mcs1 compiler. Consider using the `gmcs' compiler instead", feature); diff --git a/mcs/mcs/rootcontext.cs b/mcs/mcs/rootcontext.cs index e6c2c4b2f1d..1e50adb5634 100644 --- a/mcs/mcs/rootcontext.cs +++ b/mcs/mcs/rootcontext.cs @@ -24,11 +24,14 @@ namespace Mono.CSharp { ISO_1 = 1, Default_MCS = 2, ISO_2 = 3, - LINQ = 4, - Future = 5, - -#if GMCS_SOURCE - Default = LINQ + V_3 = 4, + V_4 = 5, + Future = 100, + +#if NET_4_0 + Default = V_4, +#elif GMCS_SOURCE + Default = V_3 #else Default = Default_MCS #endif -- 2.25.1