-
Notifications
You must be signed in to change notification settings - Fork 151
Add missing contracts in System.Linq.Expressions.Expression and derived types #171
Changes from all commits
7ff6fee
ecdaabe
e8f2e7e
24192e6
693f570
eb1ce00
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,11 +15,13 @@ | |
| #if NETFRAMEWORK_4_0 || SILVERLIGHT_4_0 || SILVERLIGHT_5_0 | ||
| // File System.Linq.Expressions.DynamicExpression.cs | ||
| // Automatically generated contract file. | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Collections.ObjectModel; | ||
| using System.Diagnostics.Contracts; | ||
| using System.IO; | ||
| using System.Runtime.CompilerServices; | ||
| using System.Text; | ||
| using System.Diagnostics.Contracts; | ||
| using System; | ||
|
|
||
| // Disable the "this variable is not used" warning as every field would imply it. | ||
| #pragma warning disable 0414 | ||
|
|
@@ -49,34 +51,39 @@ protected internal override Expression Accept (ExpressionVisitor visitor) | |
| return default(Expression); | ||
| } | ||
|
|
||
| [Pure] | ||
| public DynamicExpression Update (IEnumerable<Expression> arguments) | ||
| { | ||
| Contract.Ensures(Contract.Result<DynamicExpression>() != null); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 The current implementation does not require arguments to be non-null, but I'm not sure that was the intended behavior. It's not intuitive or mentioned in the documentation, and isn't consistent with other In particular, the following statement in the documentation is not true if we allow
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, this was a great source of confusion to me. It appears that as a general rule they promote nulls to empty collections, unless that collection is expected to be non-empty. If that's the case they require it be non-null. There are many methods in Expression that don't require non-null on IEnumerable<> and params arrays for that reason. Should those be changed as well?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'd like to discuss this after I finish reviewing it, and we can make a decision on whether to leave them all as-is or change them all.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @sharwell I don't think we can and should add this precondition. You may find this code: http://referencesource.microsoft.com/#System.Core/Microsoft/Scripting/Ast/DynamicExpression.cs,710 This code means that
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
➡️ I think this is the answer. For construction and transformation, the library treats null collections as empty collections, which means null is valid anywhere that empty is. Since the fastest path through 💭 In a world where System.Collections.Immutable preceded System.Linq.Expressions, it's likely that all of these parameters would be |
||
| return default(DynamicExpression); | ||
| } | ||
| #endregion | ||
|
|
||
| #region Properties and indexers | ||
| public System.Collections.ObjectModel.ReadOnlyCollection<Expression> Arguments | ||
| public ReadOnlyCollection<Expression> Arguments | ||
| { | ||
| get | ||
| { | ||
| return default(System.Collections.ObjectModel.ReadOnlyCollection<Expression>); | ||
| Contract.Ensures(Contract.Result<ReadOnlyCollection<Expression>>() != null); | ||
| return default(ReadOnlyCollection<Expression>); | ||
| } | ||
| } | ||
|
|
||
| public System.Runtime.CompilerServices.CallSiteBinder Binder | ||
| public CallSiteBinder Binder | ||
| { | ||
| get | ||
| { | ||
| return default(System.Runtime.CompilerServices.CallSiteBinder); | ||
| Contract.Ensures(Contract.Result<CallSiteBinder>() != null); | ||
| return default(CallSiteBinder); | ||
| } | ||
| } | ||
|
|
||
| public System.Type DelegateType | ||
| public Type DelegateType | ||
| { | ||
| get | ||
| { | ||
| return default(System.Type); | ||
| Contract.Ensures(Contract.Result<Type>() != null); | ||
| return default(Type); | ||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it mean that arguments could be null?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, it seems that
argumentcould be null. This is a valid case.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💭 Just because the implementation doesn't crash when
argumentsis null doesn't mean the contract needs to allow null.