+2009-05-27 Marek Safar <marek.safar@gmail.com>
+
+ * 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 <rkumpera@novell.com>
Marek Safar <marek.safar@gmail.com>
GenericTypeExpr ct = iface as GenericTypeExpr;
if (ct != null) {
- if (!ct.CheckConstraints (this) || !ct.VerifyVariantTypeParameters ())
+ if (!ct.CheckConstraints (this) || !ct.VerifyVariantTypeParameters (this))
return false;
}
}
"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 ()
: 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
{
}
| 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;
}
;
}
} 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;
}
}
+ 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);
}
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
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":
// TODO: silent flag is ignored
ct.CheckConstraints (ec);
- ct.VerifyVariantTypeParameters ();
+ ct.VerifyVariantTypeParameters (ec);
}
return te;
{
throw new NotImplementedException ();
}
+
+ public void ErrorInvalidVariance (MemberCore mc, Variance v)
+ {
+ }
//
// MemberContainer
get { throw new NotImplementedException (); }
}
- public bool VerifyVariantTypeParameters ()
+ public bool VerifyVariantTypeParameters (IResolveContext rc)
{
throw new NotImplementedException ();
}
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 {
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);
+ }
+
/// <summary>
/// This is the second method which is called during the resolving
/// process - in case of class type parameters, we're called from
{
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;
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;
+ }
+ }
+
/// <summary>
/// Check whether `a' and `b' may become equal generic types.
/// The algorithm to do that is a little bit complicated.
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;
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);
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