Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -327,11 +327,11 @@ protected override void ProcessRecord()
}
}

provider.WriteEvent(ref ed, _payload);
provider.WriteEvent(in ed, _payload);
}
else
{
provider.WriteEvent(ref ed);
provider.WriteEvent(in ed);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ public PSObject AttachNotes(PSObject content)
/// A struct to hold the path information and the content readers/writers
/// for an item.
/// </summary>
internal struct ContentHolder
internal readonly struct ContentHolder
{
internal ContentHolder(
PathInfo pathInfo,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ protected override void ProcessRecord()
/// true if no error occured
/// false if there was an error
/// </returns>
private bool ScanForwardsForTail(ContentHolder holder, CmdletProviderContext currentContext)
private bool ScanForwardsForTail(in ContentHolder holder, CmdletProviderContext currentContext)
{
var fsReader = holder.Reader as FileSystemContentReaderWriter;
Dbg.Diagnostics.Assert(fsReader != null, "Tail is only supported for FileSystemContentReaderWriter");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ internal static class ComInterfaces
/// string fields at all, nothing is lost.
/// </remarks>
[StructLayout(LayoutKind.Sequential)]
internal struct StartUpInfo
internal readonly struct StartUpInfo
{
public readonly UInt32 cb;
private readonly IntPtr lpReserved;
Expand Down Expand Up @@ -141,7 +141,7 @@ internal interface IPropertyStore
/// <param name="pv"></param>
/// <returns></returns>
[PreserveSig]
HResult GetValue([In] ref PropertyKey key, [Out] PropVariant pv);
HResult GetValue([In] in PropertyKey key, [Out] PropVariant pv);

/// <summary>
/// Sets the value of a property in the store.
Expand All @@ -150,7 +150,7 @@ internal interface IPropertyStore
/// <param name="pv"></param>
/// <returns></returns>
[PreserveSig]
HResult SetValue([In] ref PropertyKey key, [In] PropVariant pv);
HResult SetValue([In] in PropertyKey key, [In] PropVariant pv);

/// <summary>
/// Commits the changes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Microsoft.PowerShell
/// Defines a unique key for a Shell Property.
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct PropertyKey : IEquatable<PropertyKey>
internal readonly struct PropertyKey : IEquatable<PropertyKey>
{
#region Public Properties
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ private static void CreateElevatedEntry(string title)
flags |= 0x00002000; // SLDF_RUNAS_USER
shellLinkDataList.SetFlags(flags);
var PKEY_TITLE = new PropertyKey(new Guid("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 2);
hResult = nativePropertyStore.SetValue(ref PKEY_TITLE, new PropVariant(title));
hResult = nativePropertyStore.SetValue(in PKEY_TITLE, new PropVariant(title));
if (hResult < 0)
{
pCustDestList.AbortList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
namespace System.Diagnostics.Eventing
{
[StructLayout(LayoutKind.Explicit, Size = 16)]
public struct EventDescriptor
public readonly struct EventDescriptor
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about changing public structs to readonly -- existing code that relies on the previous form may be affected

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This struct is immutable by design.

{
[FieldOffset(0)]
private readonly ushort _id;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -488,9 +488,9 @@ public bool WriteMessageEvent(string eventMessage)
/// </param>
/// <param name="eventPayload">
/// </param>
public bool WriteEvent(ref EventDescriptor eventDescriptor, params object[] eventPayload)
public bool WriteEvent(in EventDescriptor eventDescriptor, params object[] eventPayload)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing the signature on a public method like this is a breaking change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The compiler doesn't permit overloading on ref/out/in differences, so this change is non-breaking.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically the issue isn't with the compiler, but with the runtime. Modules compiled against the old API surface must continue to work after any changes are made to the API.

But I tested it out with a toy project (an exe and a lib, where I built an in version of the lib and then changed it so the exe is compiled against a ref version) and it seems to work.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that's still C# compiler rules, where the compiler statically decides which overload to resolve for a call. My concern was that the resolved method call in the IL might not match what the library was originally compiled against when its loaded at runtime (so even though the original program isn't broken it still requires recompilation, which is a dealbreaker for modules). It makes sense that that's not the case though.

{
return WriteTransferEvent(ref eventDescriptor, Guid.Empty, eventPayload);
return WriteTransferEvent(in eventDescriptor, Guid.Empty, eventPayload);
}

/// <summary>
Expand All @@ -504,7 +504,7 @@ public bool WriteEvent(ref EventDescriptor eventDescriptor, params object[] even
/// </param>
[System.Security.SecurityCritical]
[SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")]
public bool WriteEvent(ref EventDescriptor eventDescriptor, string data)
public bool WriteEvent(in EventDescriptor eventDescriptor, string data)
{
uint status = 0;

Expand Down Expand Up @@ -534,7 +534,7 @@ public bool WriteEvent(ref EventDescriptor eventDescriptor, string data)
userData.DataPointer = (ulong)pdata;

status = UnsafeNativeMethods.EventWriteTransfer(_regHandle,
ref eventDescriptor,
in eventDescriptor,
(activityId == Guid.Empty) ? null : &activityId,
null,
1,
Expand Down Expand Up @@ -565,7 +565,7 @@ public bool WriteEvent(ref EventDescriptor eventDescriptor, string data)
/// pointer do the event data
/// </param>
[System.Security.SecurityCritical]
protected bool WriteEvent(ref EventDescriptor eventDescriptor, int dataCount, IntPtr data)
protected bool WriteEvent(in EventDescriptor eventDescriptor, int dataCount, IntPtr data)
{
uint status = 0;

Expand All @@ -575,7 +575,7 @@ protected bool WriteEvent(ref EventDescriptor eventDescriptor, int dataCount, In

status = UnsafeNativeMethods.EventWriteTransfer(
_regHandle,
ref eventDescriptor,
in eventDescriptor,
(activityId == Guid.Empty) ? null : &activityId,
null,
(uint)dataCount,
Expand All @@ -602,7 +602,7 @@ protected bool WriteEvent(ref EventDescriptor eventDescriptor, int dataCount, In
/// <param name="eventPayload">
/// </param>
[System.Security.SecurityCritical]
public bool WriteTransferEvent(ref EventDescriptor eventDescriptor, Guid relatedActivityId, params object[] eventPayload)
public bool WriteTransferEvent(in EventDescriptor eventDescriptor, Guid relatedActivityId, params object[] eventPayload)
{
uint status = 0;

Expand Down Expand Up @@ -719,7 +719,7 @@ public bool WriteTransferEvent(ref EventDescriptor eventDescriptor, Guid related
}

status = UnsafeNativeMethods.EventWriteTransfer(_regHandle,
ref eventDescriptor,
in eventDescriptor,
(activityId == Guid.Empty) ? null : &activityId,
(relatedActivityId == Guid.Empty) ? null : &relatedActivityId,
(uint)argCount,
Expand All @@ -737,7 +737,7 @@ public bool WriteTransferEvent(ref EventDescriptor eventDescriptor, Guid related
}

[System.Security.SecurityCritical]
protected bool WriteTransferEvent(ref EventDescriptor eventDescriptor, Guid relatedActivityId, int dataCount, IntPtr data)
protected bool WriteTransferEvent(in EventDescriptor eventDescriptor, Guid relatedActivityId, int dataCount, IntPtr data)
{
uint status = 0;

Expand All @@ -747,7 +747,7 @@ protected bool WriteTransferEvent(ref EventDescriptor eventDescriptor, Guid rela
{
status = UnsafeNativeMethods.EventWriteTransfer(
_regHandle,
ref eventDescriptor,
in eventDescriptor,
(activityId == Guid.Empty) ? null : &activityId,
&relatedActivityId,
(uint)dataCount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ [In][Out] ref long registrationHandle
// Control (Is Enabled) APIs
[DllImport(EventProviderDllName, ExactSpelling = true, EntryPoint = "EventEnabled", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
[SecurityCritical]
internal static extern int EventEnabled([In] long registrationHandle, [In] ref System.Diagnostics.Eventing.EventDescriptor eventDescriptor);
internal static extern int EventEnabled([In] long registrationHandle, [In] in System.Diagnostics.Eventing.EventDescriptor eventDescriptor);

[DllImport(EventProviderDllName, ExactSpelling = true, EntryPoint = "EventProviderEnabled", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
[SecurityCritical]
Expand All @@ -143,7 +143,7 @@ [In][Out] ref long registrationHandle
[SecurityCritical]
internal static extern unsafe uint EventWrite(
[In] long registrationHandle,
[In] ref EventDescriptor eventDescriptor,
[In] in EventDescriptor eventDescriptor,
[In] uint userDataCount,
[In] void* userData
);
Expand All @@ -162,7 +162,7 @@ [In] void* userData
[SecurityCritical]
internal static extern unsafe uint EventWriteTransfer(
[In] long registrationHandle,
[In] ref EventDescriptor eventDescriptor,
[In] in EventDescriptor eventDescriptor,
[In] Guid* activityId,
[In] Guid* relatedActivityId,
[In] uint userDataCount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public int ExpiringInDays
/// The structure contains punycode name and unicode name.
/// </summary>
[SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")]
public struct DnsNameRepresentation
public readonly struct DnsNameRepresentation
{
/// <summary>
/// Punycode version of DNS name.
Expand Down Expand Up @@ -3064,7 +3064,7 @@ public X509StoreLocation(StoreLocation location)
/// The structure contains friendly name and EKU oid.
/// </summary>
[SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")]
public struct EnhancedKeyUsageRepresentation
public readonly struct EnhancedKeyUsageRepresentation
{
/// <summary>
/// Localized friendly name of EKU.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,7 @@ private static bool PSv2IsCommandLikeCmdlet(string lastWord, out bool isSnapinSp
return false;
}

private struct CommandAndName
private readonly struct CommandAndName
{
internal readonly PSObject Command;
internal readonly PSSnapinQualifiedName CommandName;
Expand Down Expand Up @@ -1067,7 +1067,7 @@ private static bool PSv2ShouldFullyQualifyPathsPath(PowerShellExecutionHelper he
return isAbsolute;
}

private struct PathItemAndConvertedPath
private readonly struct PathItemAndConvertedPath
{
internal readonly string Path;
internal readonly PSObject Item;
Expand Down
4 changes: 2 additions & 2 deletions src/System.Management.Automation/engine/CommandInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -904,7 +904,7 @@ public override string ToString()
}

[DebuggerDisplay("{PSTypeName} {Name}")]
internal struct PSMemberNameAndType
internal readonly struct PSMemberNameAndType
{
public readonly string Name;

Expand Down Expand Up @@ -960,7 +960,7 @@ private PSSyntheticTypeName(string typeName, Type type, IList<PSMemberNameAndTyp
}
}

private static bool IsPSTypeName(PSMemberNameAndType member) => member.Name.Equals(nameof(PSTypeName), StringComparison.OrdinalIgnoreCase);
private static bool IsPSTypeName(in PSMemberNameAndType member) => member.Name.Equals(nameof(PSTypeName), StringComparison.OrdinalIgnoreCase);

private static string GetMemberTypeProjection(string typename, IList<PSMemberNameAndType> members)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5104,7 +5104,7 @@ private static IConversionData FigureLanguageConversion(Type fromType, Type toTy
return null;
}

private struct SignatureComparator
private readonly struct SignatureComparator
{
private enum TypeMatchingContext
{
Expand Down
2 changes: 1 addition & 1 deletion src/System.Management.Automation/engine/MshCmdlet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public interface IDynamicParameters
/// Type used to define a parameter on a cmdlet script of function that
/// can only be used as a switch.
/// </summary>
public struct SwitchParameter
public readonly struct SwitchParameter
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one could be an issue -- SwitchParameter is a very widely used public API

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But SwitchParameter is immutable by design, and adding the readonly-modifier doesn't cause any overload resolution changes [1], so I think this is not a breaking change.

[1] https://blog.paranoidcoding.com/2019/03/27/readonly-struct-breaking-change.html

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I'm fairly convinced by this

{
private readonly bool _isPresent;
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

namespace System.Management.Automation.Interpreter
{
internal struct RuntimeLabel
internal readonly struct RuntimeLabel
{
public readonly int Index;
public readonly int StackDepth;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace System.Management.Automation.Interpreter
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")]
[DebuggerTypeProxy(typeof(InstructionArray.DebugView))]
internal struct InstructionArray
internal readonly struct InstructionArray
{
internal readonly int MaxStackDepth;
internal readonly int MaxContinuationDepth;
Expand Down Expand Up @@ -156,7 +156,7 @@ internal static InstructionView[] GetInstructionViews(IList<Instruction> instruc
}

[DebuggerDisplay("{GetValue(),nq}", Name = "{GetName(),nq}", Type = "{GetDisplayType(), nq}")]
internal struct InstructionView
internal readonly struct InstructionView
{
private readonly int _index;
private readonly int _stackDepth;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ public override string ToString()
// TODO:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")]
[Serializable]
internal struct InterpretedFrameInfo
internal readonly struct InterpretedFrameInfo
{
public readonly string MethodName;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public override string ToString()
}
}

internal struct LocalDefinition
internal readonly struct LocalDefinition
{
private readonly int _index;
private readonly ParameterExpression _parameter;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ public TValue this[TKey key]
}
}

private struct KeyInfo
private readonly struct KeyInfo
{
internal readonly TValue Value;
internal readonly LinkedListNode<TKey> List;
Expand Down
2 changes: 1 addition & 1 deletion src/System.Management.Automation/engine/regex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1264,7 +1264,7 @@ protected override void EndBracketExpression()
}
}

private struct CharacterNormalizer
private readonly struct CharacterNormalizer
{
private readonly CultureInfo _cultureInfo;
private readonly bool _caseInsensitive;
Expand Down
16 changes: 8 additions & 8 deletions src/System.Management.Automation/security/nativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1955,18 +1955,18 @@ internal struct SIP_INDIRECT_DATA
}

[StructLayout(LayoutKind.Sequential)]
internal struct CRYPTCATCDF
internal readonly struct CRYPTCATCDF
{
private DWORD _cbStruct;
private IntPtr _hFile;
private DWORD _dwCurFilePos;
private DWORD _dwLastMemberOffset;
private BOOL _fEOF;
private readonly DWORD _cbStruct;
private readonly IntPtr _hFile;
private readonly DWORD _dwCurFilePos;
private readonly DWORD _dwLastMemberOffset;
private readonly BOOL _fEOF;

[MarshalAs(UnmanagedType.LPWStr)]
private string _pwszResultDir;
private readonly string _pwszResultDir;

private IntPtr _hCATStore;
private readonly IntPtr _hCATStore;
}

[StructLayout(LayoutKind.Sequential)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,7 @@ private bool Trace(PowerShellTraceEvent traceEvent, PowerShellTraceLevel level,
}
}

return _provider.WriteEvent(ref ed, args);
return _provider.WriteEvent(in ed, args);
}

/// <summary>
Expand Down
6 changes: 3 additions & 3 deletions src/System.Management.Automation/utils/tracing/EtwActivity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ public void Callback(IAsyncResult asyncResult)
private static readonly Dictionary<Guid, EventProvider> providers = new Dictionary<Guid, EventProvider>();
private static readonly object syncLock = new object();

private static EventDescriptor _WriteTransferEvent = new EventDescriptor(0x1f05, 0x1, 0x11, 0x5, 0x14, 0x0, (long)0x4000000000000000);
private static readonly EventDescriptor _WriteTransferEvent = new EventDescriptor(0x1f05, 0x1, 0x11, 0x5, 0x14, 0x0, (long)0x4000000000000000);

private EventProvider currentProvider;

Expand Down Expand Up @@ -328,7 +328,7 @@ public void CorrelateWithActivity(Guid parentActivityId)
if (parentActivityId != Guid.Empty)
{
EventDescriptor transferEvent = TransferEvent;
provider.WriteTransferEvent(ref transferEvent, parentActivityId, activityId, parentActivityId);
provider.WriteTransferEvent(in transferEvent, parentActivityId, activityId, parentActivityId);
}
}

Expand Down Expand Up @@ -473,7 +473,7 @@ protected void WriteEvent(EventDescriptor ed, params object[] payload)
}
}

bool success = provider.WriteEvent(ref ed, payload);
bool success = provider.WriteEvent(in ed, payload);
if (EventWritten != null)
{
EventWritten.Invoke(this, new EtwEventArgs(ed, success, payload));
Expand Down
Loading