diff --git a/docs/design/coreclr/botr/readytorun-format.md b/docs/design/coreclr/botr/readytorun-format.md index 24dd4454496dac..fa6bb18b114c9d 100644 --- a/docs/design/coreclr/botr/readytorun-format.md +++ b/docs/design/coreclr/botr/readytorun-format.md @@ -797,6 +797,7 @@ enum ReadyToRunHelper READYTORUN_HELPER_GenericGcTlsBase = 0x66, READYTORUN_HELPER_GenericNonGcTlsBase = 0x67, READYTORUN_HELPER_VirtualFuncPtr = 0x68, + READYTORUN_HELPER_IsInstanceOfException = 0x69, // Long mul/div/shift ops READYTORUN_HELPER_LMul = 0xC0, diff --git a/docs/project/list-of-diagnostics.md b/docs/project/list-of-diagnostics.md index 21100607e17312..63d28d5989674f 100644 --- a/docs/project/list-of-diagnostics.md +++ b/docs/project/list-of-diagnostics.md @@ -179,6 +179,18 @@ The diagnostic id values reserved for .NET Libraries analyzer warnings are `SYSL | __`SYSLIB1067`__ | *_`SYSLIB1063`-`SYSLIB1069` reserved for Microsoft.Interop.LibraryImportGenerator._* | | __`SYSLIB1068`__ | *_`SYSLIB1063`-`SYSLIB1069` reserved for Microsoft.Interop.LibraryImportGenerator._* | | __`SYSLIB1069`__ | *_`SYSLIB1063`-`SYSLIB1069` reserved for Microsoft.Interop.LibraryImportGenerator._* | +| __`SYSLIB1070`__ | Invalid 'JSImportAttribute' usage | +| __`SYSLIB1071`__ | Invalid 'JSExportAttribute' usage | +| __`SYSLIB1072`__ | Specified type is not supported by source-generated JavaScript interop | +| __`SYSLIB1073`__ | Specified configuration is not supported by source-generated JavaScript interop | +| __`SYSLIB1074`__ | JSImportAttribute requires unsafe code | +| __`SYSLIB1075`__ | JSExportAttribute requires unsafe code | +| __`SYSLIB1076`__ | *_`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator.* | +| __`SYSLIB1077`__ | *_`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator.* | +| __`SYSLIB1078`__ | *_`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator.* | +| __`SYSLIB1079`__ | *_`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator.* | +| __`SYSLIB1080`__ | *_`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator.* | + ### Diagnostic Suppressions (`SYSLIBSUPPRESS****`) diff --git a/eng/common/native/init-compiler.sh b/eng/common/native/init-compiler.sh index 4b99a9cad3b772..41a26d802a93f8 100644 --- a/eng/common/native/init-compiler.sh +++ b/eng/common/native/init-compiler.sh @@ -71,7 +71,7 @@ if [[ -z "$CLR_CC" ]]; then # Set default versions if [[ -z "$majorVersion" ]]; then # note: gcc (all versions) and clang versions higher than 6 do not have minor version in file name, if it is zero. - if [[ "$compiler" == "clang" ]]; then versions=( 14 13 12 11 10 9 8 7 6.0 5.0 4.0 3.9 3.8 3.7 3.6 3.5 ) + if [[ "$compiler" == "clang" ]]; then versions=( 15 14 13 12 11 10 9 8 7 6.0 5.0 4.0 3.9 3.8 3.7 3.6 3.5 ) elif [[ "$compiler" == "gcc" ]]; then versions=( 12 11 10 9 8 7 6 5 4.9 ); fi for version in "${versions[@]}"; do diff --git a/eng/pipelines/runtime-extra-platforms-other.yml b/eng/pipelines/runtime-extra-platforms-other.yml index c201d118b62db8..a3b0116b30c8b2 100644 --- a/eng/pipelines/runtime-extra-platforms-other.yml +++ b/eng/pipelines/runtime-extra-platforms-other.yml @@ -91,7 +91,7 @@ jobs: isSingleFile: true nameSuffix: NativeAOT_Libs_Passing buildArgs: -s clr.aot+libs+libs.tests -c $(_BuildConfig) /p:TestNativeAot=true /p:ArchiveTests=true - timeoutInMinutes: 180 + timeoutInMinutes: 240 # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: diff --git a/src/coreclr/System.Private.CoreLib/src/System/ArgIterator.cs b/src/coreclr/System.Private.CoreLib/src/System/ArgIterator.cs index 10ede24a6573c5..37a75996c0322d 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/ArgIterator.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/ArgIterator.cs @@ -123,7 +123,7 @@ public unsafe RuntimeTypeHandle GetNextArgType() public override int GetHashCode() { - return ValueType.GetHashCodeOfPtr(ArgCookie); + return RuntimeHelpers.GetHashCodeOfPtr(ArgCookie); } // Inherited from object diff --git a/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs b/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs index 259bfc90070cf2..4746430b5139fb 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs @@ -460,7 +460,7 @@ public sealed override Delegate[] GetInvocationList() public sealed override int GetHashCode() { if (IsUnmanagedFunctionPtr()) - return ValueType.GetHashCodeOfPtr(_methodPtr) ^ ValueType.GetHashCodeOfPtr(_methodPtrAux); + return RuntimeHelpers.GetHashCodeOfPtr(_methodPtr) ^ RuntimeHelpers.GetHashCodeOfPtr(_methodPtrAux); if (_invocationCount != (IntPtr)0) { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs index cdc15dc8fb6e08..f945f3c7352e94 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs @@ -206,7 +206,7 @@ internal readonly struct MetadataImport public override int GetHashCode() { - return ValueType.GetHashCodeOfPtr(m_metadataImport2); + return RuntimeHelpers.GetHashCodeOfPtr(m_metadataImport2); } public override bool Equals(object? obj) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs index 229e2981bb6f25..8878b27db60dde 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs @@ -161,7 +161,7 @@ public override int GetHashCode() { // See RuntimeMethodInfo.Equals() below. if (IsGenericMethod) - return ValueType.GetHashCodeOfPtr(m_handle); + return RuntimeHelpers.GetHashCodeOfPtr(m_handle); else return base.GetHashCode(); } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs index 196f43f4f63f8a..9465e62cba063b 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs @@ -8,11 +8,14 @@ using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; +using System.Threading; namespace System.Runtime.CompilerServices { public static partial class RuntimeHelpers { + private static int s_pointerHashSeed; + [Intrinsic] [MethodImpl(MethodImplOptions.InternalCall)] public static extern void InitializeArray(Array array, RuntimeFieldHandle fldHandle); @@ -397,6 +400,31 @@ public GCFrameRegistration(void* allocation, uint elemCount, bool areByRefs = tr [MethodImpl(MethodImplOptions.InternalCall)] internal static extern unsafe void UnregisterForGCReporting(GCFrameRegistration* pRegistration); + + internal static int GetHashCodeOfPtr(IntPtr ptr) + { + int hashCode = (int)ptr; + + if (hashCode == 0) + { + return 0; + } + + int seed = s_pointerHashSeed; + + // Initialize s_pointerHashSeed lazily + if (seed == 0) + { + // We use the first non-0 pointer as the seed, all hashcodes will be based off that. + // This is to make sure that we only reveal relative memory addresses and never absolute ones. + seed = hashCode; + Interlocked.CompareExchange(ref s_pointerHashSeed, seed, 0); + seed = s_pointerHashSeed; + } + + Debug.Assert(s_pointerHashSeed != 0); + return hashCode - seed; + } } // Helper class to assist with unsafe pinning of arbitrary objects. // It's used by VM code. diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs index 49b1b5ac0f7f13..6b7d2425135cc0 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -873,7 +873,7 @@ public void GetObjectData(SerializationInfo info, StreamingContext context) public override int GetHashCode() { - return ValueType.GetHashCodeOfPtr(Value); + return RuntimeHelpers.GetHashCodeOfPtr(Value); } public override bool Equals(object? obj) @@ -1226,7 +1226,7 @@ internal bool IsNullHandle() public override int GetHashCode() { - return ValueType.GetHashCodeOfPtr(Value); + return RuntimeHelpers.GetHashCodeOfPtr(Value); } public override bool Equals(object? obj) diff --git a/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs b/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs index 64b547b699fb7f..880de9ac6af953 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs @@ -10,11 +10,9 @@ ** ===========================================================*/ -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; -using System.Threading; namespace System { @@ -84,33 +82,6 @@ ref RuntimeHelpers.GetRawData(obj), [MethodImpl(MethodImplOptions.InternalCall)] public extern override int GetHashCode(); - private static int s_seed; - - internal static int GetHashCodeOfPtr(IntPtr ptr) - { - int hashCode = (int)ptr; - - if (hashCode == 0) - { - return 0; - } - - int seed = s_seed; - - // Initialize s_seed lazily - if (seed == 0) - { - // We use the first non-0 pointer as the seed, all hashcodes will be based off that. - // This is to make sure that we only reveal relative memory addresses and never absolute ones. - seed = hashCode; - Interlocked.CompareExchange(ref s_seed, seed, 0); - seed = s_seed; - } - - Debug.Assert(s_seed != 0); - return hashCode - seed; - } - public override string? ToString() { return this.GetType().ToString(); diff --git a/src/coreclr/debug/di/rspriv.h b/src/coreclr/debug/di/rspriv.h index ba78099c3df402..0568fdfff72ebe 100644 --- a/src/coreclr/debug/di/rspriv.h +++ b/src/coreclr/debug/di/rspriv.h @@ -1193,17 +1193,6 @@ class CordbCommonBase : public IUnknown static LONG s_CordbObjectUID; // Unique ID for each object. static LONG s_TotalObjectCount; // total number of outstanding objects. - - void ValidateObject() - { - if( !IsValidObject() ) - { - STRESS_LOG1(LF_ASSERT, LL_ALWAYS, "CordbCommonBase::IsValidObject() failed: %x\n", this); - _ASSERTE(!"CordbCommonBase::IsValidObject() failed"); - FreeBuildDebugBreak(); - } - } - bool IsValidObject() { return (m_signature == CORDB_COMMON_BASE_SIGNATURE); diff --git a/src/coreclr/debug/di/rspriv.inl b/src/coreclr/debug/di/rspriv.inl index 221bc87091e089..d918cae3ee5428 100644 --- a/src/coreclr/debug/di/rspriv.inl +++ b/src/coreclr/debug/di/rspriv.inl @@ -703,9 +703,6 @@ inline void CordbSafeHashTable::NeuterAndClear(RSLock * pLock) { T * pCordbBase = FindFirst(&find); _ASSERTE(pCordbBase != NULL); - - // Using this Validate to help track down bug DevDiv bugs 739406 - pCordbBase->ValidateObject(); pCordbBase->Neuter(); idx++; diff --git a/src/coreclr/dlls/mscoree/exports.cpp b/src/coreclr/dlls/mscoree/exports.cpp index c6ef09efbcc8a1..e8ee88275df8eb 100644 --- a/src/coreclr/dlls/mscoree/exports.cpp +++ b/src/coreclr/dlls/mscoree/exports.cpp @@ -20,7 +20,7 @@ #include "bundle.h" #include "pinvokeoverride.h" -#define ASSERTE_ALL_BUILDS(expr) _ASSERTE_ALL_BUILDS(__FILE__, (expr)) +#define ASSERTE_ALL_BUILDS(expr) _ASSERTE_ALL_BUILDS((expr)) // Holder for const wide strings typedef NewArrayHolder ConstWStringHolder; diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index e8604300220470..5c5970d30ef2ad 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -241,7 +241,8 @@ gc_oh_num gen_to_oh(int gen) case poh_generation: return gc_oh_num::poh; default: - return gc_oh_num::none; + assert(false); + return gc_oh_num::unknown; } } @@ -2198,7 +2199,7 @@ CLRCriticalSection gc_heap::check_commit_cs; size_t gc_heap::current_total_committed = 0; -size_t gc_heap::committed_by_oh[total_oh_count] = {0, 0, 0, 0}; +size_t gc_heap::committed_by_oh[recorded_committed_bucket_counts]; size_t gc_heap::current_total_committed_bookkeeping = 0; @@ -2275,7 +2276,7 @@ uint64_t gc_heap::entry_available_physical_mem = 0; size_t gc_heap::heap_hard_limit = 0; -size_t gc_heap::heap_hard_limit_oh[total_oh_count - 1] = {0, 0, 0}; +size_t gc_heap::heap_hard_limit_oh[total_oh_count]; #ifdef USE_REGIONS size_t gc_heap::regions_range = 0; @@ -2370,7 +2371,7 @@ oom_history gc_heap::oomhist_per_heap[max_oom_history_count]; fgm_history gc_heap::fgm_result; -size_t gc_heap::allocated_since_last_gc[gc_oh_num::total_oh_count - 1]; +size_t gc_heap::allocated_since_last_gc[total_oh_count]; BOOL gc_heap::ro_segments_in_range; @@ -2412,7 +2413,7 @@ uint8_t* gc_heap::last_gen1_pin_end; gen_to_condemn_tuning gc_heap::gen_to_condemn_reasons; -size_t gc_heap::etw_allocation_running_amount[gc_oh_num::total_oh_count - 1]; +size_t gc_heap::etw_allocation_running_amount[total_oh_count]; uint64_t gc_heap::total_alloc_bytes_soh = 0; @@ -5627,7 +5628,7 @@ gc_heap::soh_get_segment_to_expand() heap_segment* gc_heap::get_segment (size_t size, gc_oh_num oh) { - assert(oh != gc_oh_num::none); + assert(oh != gc_oh_num::unknown); BOOL uoh_p = (oh == gc_oh_num::loh) || (oh == gc_oh_num::poh); if (heap_hard_limit) return NULL; @@ -6809,20 +6810,26 @@ bool gc_heap::virtual_alloc_commit_for_heap (void* addr, size_t size, int h_numb return GCToOSInterface::VirtualCommit(addr, size); } -bool gc_heap::virtual_commit (void* address, size_t size, gc_oh_num oh, int h_number, bool* hard_limit_exceeded_p) +bool gc_heap::virtual_commit (void* address, size_t size, int bucket, int h_number, bool* hard_limit_exceeded_p) { #ifndef HOST_64BIT assert (heap_hard_limit == 0); #endif //!HOST_64BIT + assert(0 <= bucket && bucket < recorded_committed_bucket_counts); + assert(bucket < total_oh_count || h_number == -1); + assert(bucket != recorded_committed_free_bucket); + + dprintf(3, ("commit-accounting: commit in %d [%Ix, %Ix) for heap %d", bucket, address, ((uint8_t*)address + size), h_number)); + if (heap_hard_limit) { check_commit_cs.Enter(); bool exceeded_p = false; - if (heap_hard_limit_oh[oh] != 0) + if (heap_hard_limit_oh[bucket] != 0) { - if ((oh != gc_oh_num::none) && (committed_by_oh[oh] + size) > heap_hard_limit_oh[oh]) + if ((bucket < total_oh_count) && (committed_by_oh[bucket] + size) > heap_hard_limit_oh[bucket]) { exceeded_p = true; } @@ -6839,7 +6846,13 @@ bool gc_heap::virtual_commit (void* address, size_t size, gc_oh_num oh, int h_nu if (!exceeded_p) { - committed_by_oh[oh] += size; +#if defined(_DEBUG) && defined(MULTIPLE_HEAPS) + if (bucket < total_oh_count) + { + g_heaps[h_number]->committed_by_oh_per_heap[bucket] += size; + } +#endif // _DEBUG && MULTIPLE_HEAPS + committed_by_oh[bucket] += size; current_total_committed += size; if (h_number < 0) current_total_committed_bookkeeping += size; @@ -6866,8 +6879,14 @@ bool gc_heap::virtual_commit (void* address, size_t size, gc_oh_num oh, int h_nu if (!commit_succeeded_p && heap_hard_limit) { check_commit_cs.Enter(); - committed_by_oh[oh] -= size; - + committed_by_oh[bucket] -= size; +#if defined(_DEBUG) && defined(MULTIPLE_HEAPS) + if (bucket < total_oh_count) + { + assert (g_heaps[h_number]->committed_by_oh_per_heap[bucket] >= size); + g_heaps[h_number]->committed_by_oh_per_heap[bucket] -= size; + } +#endif // _DEBUG && MULTIPLE_HEAPS dprintf (1, ("commit failed, updating %Id to %Id", current_total_committed, (current_total_committed - size))); current_total_committed -= size; @@ -6879,18 +6898,31 @@ bool gc_heap::virtual_commit (void* address, size_t size, gc_oh_num oh, int h_nu return commit_succeeded_p; } -bool gc_heap::virtual_decommit (void* address, size_t size, gc_oh_num oh, int h_number) +bool gc_heap::virtual_decommit (void* address, size_t size, int bucket, int h_number) { #ifndef HOST_64BIT assert (heap_hard_limit == 0); #endif //!HOST_64BIT + assert(0 <= bucket && bucket < recorded_committed_bucket_counts); + assert(bucket < total_oh_count || h_number == -1); + bool decommit_succeeded_p = GCToOSInterface::VirtualDecommit (address, size); + dprintf(3, ("commit-accounting: decommit in %d [%Ix, %Ix) for heap %d", bucket, address, ((uint8_t*)address + size), h_number)); + if (decommit_succeeded_p && heap_hard_limit) { check_commit_cs.Enter(); - committed_by_oh[oh] -= size; + assert (committed_by_oh[bucket] >= size); + committed_by_oh[bucket] -= size; +#if defined(_DEBUG) && defined(MULTIPLE_HEAPS) + if (bucket < total_oh_count) + { + assert (g_heaps[h_number]->committed_by_oh_per_heap[bucket] >= size); + g_heaps[h_number]->committed_by_oh_per_heap[bucket] -= size; + } +#endif // _DEBUG && MULTIPLE_HEAPS current_total_committed -= size; if (h_number < 0) current_total_committed_bookkeeping -= size; @@ -8720,7 +8752,7 @@ bool gc_heap::inplace_commit_card_table (uint8_t* from, uint8_t* to) bool succeed; if (commit_sizes[i] > 0) { - succeed = virtual_commit (commit_begins[i], commit_sizes[i], gc_oh_num::none); + succeed = virtual_commit (commit_begins[i], commit_sizes[i], recorded_committed_bookkeeping_bucket); if (!succeed) { failed_commit = i; @@ -8742,7 +8774,7 @@ bool gc_heap::inplace_commit_card_table (uint8_t* from, uint8_t* to) bool succeed; if (commit_sizes[i] > 0) { - succeed = virtual_decommit (commit_begins[i], commit_sizes[i], gc_oh_num::none); + succeed = virtual_decommit (commit_begins[i], commit_sizes[i], recorded_committed_bookkeeping_bucket); assert (succeed); } } @@ -8795,7 +8827,7 @@ uint32_t* gc_heap::make_card_table (uint8_t* start, uint8_t* end) // in case of background gc, the mark array will be committed separately (per segment). size_t commit_size = card_table_element_layout[seg_mapping_table_element + 1]; - if (!virtual_commit (mem, commit_size, gc_oh_num::none)) + if (!virtual_commit (mem, commit_size, recorded_committed_bookkeeping_bucket)) { dprintf (1, ("Card table commit failed")); GCToOSInterface::VirtualRelease (mem, alloc_size); @@ -8964,7 +8996,7 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, // in case of background gc, the mark array will be committed separately (per segment). size_t commit_size = card_table_element_layout[seg_mapping_table_element + 1]; - if (!virtual_commit (mem, commit_size, gc_oh_num::none)) + if (!virtual_commit (mem, commit_size, recorded_committed_bookkeeping_bucket)) { dprintf (GC_TABLE_LOG, ("Table commit failed")); set_fgm_result (fgm_commit_table, commit_size, uoh_p); @@ -11117,6 +11149,24 @@ void gc_heap::clear_region_info (heap_segment* region) // REGIONS PERF TODO: should decommit if needed. void gc_heap::return_free_region (heap_segment* region) { + gc_oh_num oh = heap_segment_oh (region); + dprintf(3, ("commit-accounting: from %d to free [%Ix, %Ix) for heap %d", oh, get_region_start (region), heap_segment_committed (region), heap_number)); + if (heap_hard_limit_oh[soh]) + { + size_t committed = heap_segment_committed (region) - get_region_start (region); + if (committed > 0) + { + check_commit_cs.Enter(); + assert (committed_by_oh[oh] >= committed); + committed_by_oh[oh] -= committed; + committed_by_oh[recorded_committed_free_bucket] += committed; +#if defined(_DEBUG) && defined(MULTIPLE_HEAPS) + assert (committed_by_oh_per_heap[oh] >= committed); + committed_by_oh_per_heap[oh] -= committed; +#endif // _DEBUG && MULTIPLE_HEAPS + check_commit_cs.Leave(); + } + } clear_region_info (region); region_free_list::add_region_descending (region, free_regions); @@ -11184,6 +11234,25 @@ heap_segment* gc_heap::get_free_region (int gen_number, size_t size) init_heap_segment (region, __this, region_start, (region_end - region_start), gen_number); + + gc_oh_num oh = gen_to_oh (gen_number); + dprintf(3, ("commit-accounting: from free to %d [%Ix, %Ix) for heap %d", oh, get_region_start (region), heap_segment_committed (region), heap_number)); + if (heap_hard_limit_oh[soh]) + { + size_t committed = heap_segment_committed (region) - get_region_start (region); + if (committed > 0) + { + check_commit_cs.Enter(); + committed_by_oh[oh] += committed; + assert (committed_by_oh[recorded_committed_free_bucket] >= committed); + committed_by_oh[recorded_committed_free_bucket] -= committed; +#if defined(_DEBUG) && defined(MULTIPLE_HEAPS) + committed_by_oh_per_heap[oh] += committed; +#endif // _DEBUG && MULTIPLE_HEAPS + check_commit_cs.Leave(); + } + } + dprintf (REGIONS_LOG, ("h%d GFR get region %Ix (%Ix-%Ix) for gen%d", heap_number, (size_t)region, region_start, region_end, @@ -13746,14 +13815,16 @@ void gc_heap::add_saved_spinlock_info ( } int -gc_heap::init_gc_heap (int h_number) +gc_heap::init_gc_heap (int h_number) { #ifdef MULTIPLE_HEAPS +#ifdef _DEBUG + memset (committed_by_oh_per_heap, 0, sizeof (committed_by_oh_per_heap)); +#endif - time_bgc_last = 0; + g_heaps [h_number] = this; - for (int oh_index = 0; oh_index < (gc_oh_num::total_oh_count - 1); oh_index++) - allocated_since_last_gc[oh_index] = 0; + time_bgc_last = 0; #ifdef SPINLOCK_HISTORY spinlock_info_index = 0; @@ -13850,6 +13921,8 @@ gc_heap::init_gc_heap (int h_number) heap_number = h_number; #endif //MULTIPLE_HEAPS + memset (etw_allocation_running_amount, 0, sizeof (etw_allocation_running_amount)); + memset (allocated_since_last_gc, 0, sizeof (allocated_since_last_gc)); memset (&oom_info, 0, sizeof (oom_info)); memset (&fgm_result, 0, sizeof (fgm_result)); memset (oomhist_per_heap, 0, sizeof (oomhist_per_heap)); @@ -14002,9 +14075,6 @@ gc_heap::init_gc_heap (int h_number) generation_of (loh_generation)->free_list_allocator = allocator(NUM_LOH_ALIST, BASE_LOH_ALIST_BITS, loh_alloc_list); generation_of (poh_generation)->free_list_allocator = allocator(NUM_POH_ALIST, BASE_POH_ALIST_BITS, poh_alloc_list); - for (int oh_index = 0; oh_index < (gc_oh_num::total_oh_count - 1); oh_index++) - etw_allocation_running_amount[oh_index] = 0; - total_alloc_bytes_soh = 0; total_alloc_bytes_uoh = 0; @@ -14061,8 +14131,6 @@ gc_heap::init_gc_heap (int h_number) if (!create_gc_thread ()) return 0; - g_heaps [heap_number] = this; - #endif //MULTIPLE_HEAPS #ifdef FEATURE_PREMORTEM_FINALIZATION @@ -22616,6 +22684,18 @@ heap_segment* gc_heap::unlink_first_rw_region (int gen_idx) assert (!heap_segment_read_only_p (region)); dprintf (REGIONS_LOG, ("unlink_first_rw_region on heap: %d gen: %d region: %Ix", heap_number, gen_idx, heap_segment_mem (region))); +#ifdef _DEBUG + int old_oh = heap_segment_oh (region); + int old_heap = heap_segment_heap (region)->heap_number; + dprintf(3, ("commit-accounting: from %d to temp [%Ix, %Ix) for heap %d", old_oh, get_region_start (region), heap_segment_committed (region), old_heap)); + + size_t committed = heap_segment_committed (region) - get_region_start (region); + check_commit_cs.Enter(); + assert (g_heaps[old_heap]->committed_by_oh_per_heap[old_oh] >= committed); + g_heaps[old_heap]->committed_by_oh_per_heap[old_oh] -= committed; + check_commit_cs.Leave(); +#endif // _DEBUG + set_heap_for_contained_basic_regions (region, nullptr); return region; @@ -22638,6 +22718,18 @@ void gc_heap::thread_rw_region_front (int gen_idx, heap_segment* region) } dprintf (REGIONS_LOG, ("thread_rw_region_front on heap: %d gen: %d region: %Ix", heap_number, gen_idx, heap_segment_mem (region))); +#ifdef _DEBUG + int new_oh = gen_to_oh (gen_idx); + int new_heap = this->heap_number; + dprintf(3, ("commit-accounting: from temp to %d [%Ix, %Ix) for heap %d", new_oh, get_region_start (region), heap_segment_committed (region), new_heap)); + + size_t committed = heap_segment_committed (region) - get_region_start (region); + check_commit_cs.Enter(); + assert (heap_segment_heap (region) == nullptr); + g_heaps[new_heap]->committed_by_oh_per_heap[new_oh] += committed; + check_commit_cs.Leave(); +#endif // _DEBUG + set_heap_for_contained_basic_regions (region, this); } #endif // MULTIPLE_HEAPS @@ -29838,6 +29930,59 @@ void gc_heap::plan_phase (int condemned_gen_number) } #endif //FEATURE_EVENT_TRACE +#if defined(_DEBUG) && defined(USE_REGIONS) + if (heap_hard_limit_oh[soh]) + { + size_t committed = 0; + for (int i = 0; i < total_generation_count; i++) + { + int oh = i - max_generation; +#ifdef MULTIPLE_HEAPS + for (int hn = 0; hn < gc_heap::n_heaps; hn++) + { + gc_heap* hp = gc_heap::g_heaps[hn]; +#else + { + gc_heap* hp = pGenGCHeap; +#endif // MULTIPLE_HEAPS + heap_segment* region = generation_start_segment (hp->generation_of (i)); + while (region) + { + committed += heap_segment_committed (region) - get_region_start (region); + region = heap_segment_next (region); + } + + if (oh == soh) + { + heap_segment* freeable = hp->freeable_soh_segment; + while (freeable) + { + committed += (heap_segment_committed (freeable) - get_region_start (freeable)); + freeable = heap_segment_next (freeable); + } + } + else + { + heap_segment* freeable = hp->freeable_uoh_segment; + while (freeable) + { + if (heap_segment_oh (freeable) == oh) + { + committed += (heap_segment_committed (freeable) - get_region_start (freeable)); + } + freeable = heap_segment_next (freeable); + } + } + } + if (i >= max_generation) + { + assert (committed_by_oh[oh] == committed); + committed = 0; + } + } + } +#endif // _DEBUG && USE_REGIONS + #ifdef MULTIPLE_HEAPS //join all threads to make sure they are synchronized dprintf(3, ("Restarting after Promotion granted")); @@ -33560,7 +33705,7 @@ BOOL gc_heap::commit_mark_array_by_range (uint8_t* begin, uint8_t* end, uint32_t size)); #endif //SIMPLE_DPRINTF - if (virtual_commit (commit_start, size, gc_oh_num::none)) + if (virtual_commit (commit_start, size, recorded_committed_bookkeeping_bucket)) { // We can only verify the mark array is cleared from begin to end, the first and the last // page aren't necessarily all cleared 'cause they could be used by other segments or @@ -33785,7 +33930,7 @@ void gc_heap::decommit_mark_array_by_seg (heap_segment* seg) if (decommit_start < decommit_end) { - if (!virtual_decommit (decommit_start, size, gc_oh_num::none)) + if (!virtual_decommit (decommit_start, size, recorded_committed_bookkeeping_bucket)) { dprintf (GC_TABLE_LOG, ("decommit on %Ix for %Id bytes failed", decommit_start, size)); @@ -39895,7 +40040,7 @@ bool gc_heap::decommit_step () bool decommit_succeeded_p = false; if (!use_large_pages_p) { - decommit_succeeded_p = virtual_decommit(page_start, size, heap_segment_oh(region), 0); + decommit_succeeded_p = virtual_decommit(page_start, size, recorded_committed_free_bucket); dprintf(REGIONS_LOG, ("decommitted region %Ix(%Ix-%Ix) (%Iu bytes) - success: %d", region, page_start, @@ -43138,7 +43283,7 @@ gc_heap::verify_free_lists () } } -void gc_heap::verify_regions (int gen_number, bool can_verify_gen_num, bool can_verify_tail) +void gc_heap::verify_regions (int gen_number, bool can_verify_gen_num, bool can_verify_tail, size_t* p_total_committed) { #ifdef USE_REGIONS // For the given generation, verify that @@ -43157,6 +43302,10 @@ void gc_heap::verify_regions (int gen_number, bool can_verify_gen_num, bool can_ while (seg_in_gen) { + if (p_total_committed) + { + *p_total_committed += (heap_segment_committed (seg_in_gen) - get_region_start (seg_in_gen)); + } if (can_verify_gen_num) { if (heap_segment_gen_num (seg_in_gen) != min (gen_number, max_generation)) @@ -43220,10 +43369,56 @@ inline bool is_user_alloc_gen (int gen_number) void gc_heap::verify_regions (bool can_verify_gen_num, bool concurrent_p) { #ifdef USE_REGIONS + size_t total_committed = 0; for (int i = 0; i < total_generation_count; i++) { bool can_verify_tail = (concurrent_p ? !is_user_alloc_gen (i) : true); - verify_regions (i, can_verify_gen_num, can_verify_tail); + verify_regions (i, can_verify_gen_num, can_verify_tail, &total_committed); + + if (can_verify_gen_num && + can_verify_tail && + (i >= max_generation) && + (heap_hard_limit_oh[soh] > 0)) + { + int oh = i - max_generation; + if (oh == soh) + { + heap_segment* freeable = freeable_soh_segment; + while (freeable) + { + total_committed += (heap_segment_committed (freeable) - get_region_start (freeable)); + freeable = heap_segment_next (freeable); + } + } + else + { + heap_segment* freeable = freeable_uoh_segment; + while (freeable) + { + if (heap_segment_oh (freeable) == oh) + { + total_committed += (heap_segment_committed (freeable) - get_region_start (freeable)); + } + freeable = heap_segment_next (freeable); + } + } +#ifdef MULTIPLE_HEAPS +#ifdef _DEBUG + size_t total_accounted = committed_by_oh_per_heap[i - max_generation]; +#else // _DEBUG + size_t total_accounted = total_committed; +#endif // _DEBUG +#else // MULTIPLE_HEAPS + size_t total_accounted = committed_by_oh[i - max_generation]; +#endif // MULTIPLE_HEAPS + if (total_committed != total_accounted) + { + FATAL_GC_ERROR(); + } + dprintf(3, ("commit-accounting: checkpoint for %d for heap %d", oh, heap_number)); + total_committed = 0; + } + } #endif //USE_REGIONS } @@ -43882,6 +44077,8 @@ HRESULT GCHeap::Initialize() gc_heap::heap_hard_limit_oh[loh] = (size_t)GCConfig::GetGCHeapHardLimitLOH(); gc_heap::heap_hard_limit_oh[poh] = (size_t)GCConfig::GetGCHeapHardLimitPOH(); + memset (gc_heap::committed_by_oh, 0, sizeof (gc_heap::committed_by_oh)); + gc_heap::use_large_pages_p = GCConfig::GetGCLargePages(); if (gc_heap::heap_hard_limit_oh[soh] || gc_heap::heap_hard_limit_oh[loh] || gc_heap::heap_hard_limit_oh[poh]) diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index c146f31cbfd3c3..54d909a5260794 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -419,10 +419,14 @@ enum gc_oh_num soh = 0, loh = 1, poh = 2, - none = 3, - total_oh_count = 4 + unknown = -1, }; +const int total_oh_count = gc_oh_num::poh + 1; +const int recorded_committed_free_bucket = total_oh_count; +const int recorded_committed_bookkeeping_bucket = recorded_committed_free_bucket + 1; +const int recorded_committed_bucket_counts = recorded_committed_bookkeeping_bucket + 1; + gc_oh_num gen_to_oh (int gen); #if defined(TRACE_GC) && defined(BACKGROUND_GC) @@ -1296,7 +1300,7 @@ class gc_heap PER_HEAP void verify_free_lists(); PER_HEAP - void verify_regions (int gen_number, bool can_verify_gen_num, bool can_verify_tail); + void verify_regions (int gen_number, bool can_verify_gen_num, bool can_verify_tail, size_t* p_total_committed = nullptr); PER_HEAP void verify_regions (bool can_verify_gen_num, bool concurrent_p); PER_HEAP_ISOLATED @@ -2033,9 +2037,9 @@ class gc_heap PER_HEAP_ISOLATED bool virtual_alloc_commit_for_heap (void* addr, size_t size, int h_number); PER_HEAP_ISOLATED - bool virtual_commit (void* address, size_t size, gc_oh_num oh, int h_number=-1, bool* hard_limit_exceeded_p=NULL); + bool virtual_commit (void* address, size_t size, int bucket, int h_number=-1, bool* hard_limit_exceeded_p=NULL); PER_HEAP_ISOLATED - bool virtual_decommit (void* address, size_t size, gc_oh_num oh, int h_number=-1); + bool virtual_decommit (void* address, size_t size, int bucket, int h_number=-1); PER_HEAP_ISOLATED void virtual_free (void* add, size_t size, heap_segment* sg=NULL); PER_HEAP @@ -3803,7 +3807,7 @@ class gc_heap gen_to_condemn_tuning gen_to_condemn_reasons; PER_HEAP - size_t etw_allocation_running_amount[gc_oh_num::total_oh_count - 1]; + size_t etw_allocation_running_amount[total_oh_count]; PER_HEAP uint64_t total_alloc_bytes_soh; @@ -4007,7 +4011,7 @@ class gc_heap size_t heap_hard_limit; PER_HEAP_ISOLATED - size_t heap_hard_limit_oh[total_oh_count - 1]; + size_t heap_hard_limit_oh[total_oh_count]; PER_HEAP_ISOLATED CLRCriticalSection check_commit_cs; @@ -4016,7 +4020,12 @@ class gc_heap size_t current_total_committed; PER_HEAP_ISOLATED - size_t committed_by_oh[total_oh_count]; + size_t committed_by_oh[recorded_committed_bucket_counts]; + +#if defined (_DEBUG) && defined (MULTIPLE_HEAPS) + PER_HEAP + size_t committed_by_oh_per_heap[total_oh_count]; +#endif // _DEBUG && MULTIPLE_HEAPS // This is what GC uses for its own bookkeeping. PER_HEAP_ISOLATED @@ -4818,7 +4827,7 @@ class gc_heap size_t num_provisional_triggered; PER_HEAP - size_t allocated_since_last_gc[gc_oh_num::total_oh_count - 1]; + size_t allocated_since_last_gc[total_oh_count]; #ifdef BACKGROUND_GC PER_HEAP_ISOLATED diff --git a/src/coreclr/ilasm/main.cpp b/src/coreclr/ilasm/main.cpp index 4e4b789107587c..767154b5b8a68d 100644 --- a/src/coreclr/ilasm/main.cpp +++ b/src/coreclr/ilasm/main.cpp @@ -12,7 +12,7 @@ #include "shimload.h" #include "strsafe.h" -#define ASSERTE_ALL_BUILDS(expr) _ASSERTE_ALL_BUILDS(__FILE__, (expr)) +#define ASSERTE_ALL_BUILDS(expr) _ASSERTE_ALL_BUILDS((expr)) WCHAR* EqualOrColon(_In_ __nullterminated WCHAR* szArg) { diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h index 105a6504db4d01..147d03f957cfc3 100644 --- a/src/coreclr/inc/clrconfigvalues.h +++ b/src/coreclr/inc/clrconfigvalues.h @@ -151,9 +151,7 @@ CONFIG_STRING_INFO(INTERNAL_BreakOnInteropStubSetup, W("BreakOnInteropStubSetup" CONFIG_STRING_INFO(INTERNAL_BreakOnInteropVTableBuild, W("BreakOnInteropVTableBuild"), "Specifies a type name for which an assert should be thrown when building interop v-table.") CONFIG_STRING_INFO(INTERNAL_BreakOnMethodName, W("BreakOnMethodName"), "Very useful for debugging method override placement code.") CONFIG_DWORD_INFO(INTERNAL_BreakOnNotify, W("BreakOnNotify"), 0, "") -RETAIL_CONFIG_DWORD_INFO(INTERNAL_BreakOnRetailAssert, W("BreakOnRetailAssert"), 0, "Used for debugging \"retail\" asserts (fatal errors)") CONFIG_DWORD_INFO(INTERNAL_BreakOnSecondPass, W("BreakOnSecondPass"), 0, "") -RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_BreakOnSO, W("BreakOnSO"), 0, "") CONFIG_STRING_INFO(INTERNAL_BreakOnStructMarshalSetup, W("BreakOnStructMarshalSetup"), "Throws an assert when field marshalers for the given type with layout are about to be created.") CONFIG_DWORD_INFO(INTERNAL_BreakOnUEF, W("BreakOnUEF"), 0, "") CONFIG_DWORD_INFO(INTERNAL_BreakOnUncaughtException, W("BreakOnUncaughtException"), 0, "") @@ -207,7 +205,6 @@ CONFIG_DWORD_INFO(INTERNAL_DbgTrapOnSkip, W("DbgTrapOnSkip"), 0, "Allows breakin CONFIG_DWORD_INFO(INTERNAL_DbgWaitTimeout, W("DbgWaitTimeout"), 1, "Specifies the timeout value for waits") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_DbgWFDETimeout, W("DbgWFDETimeout"), 25, "Specifies the timeout value for wait when waiting for a debug event") CONFIG_DWORD_INFO(INTERNAL_RaiseExceptionOnAssert, W("RaiseExceptionOnAssert"), 0, "Raise a first chance (if set to 1) or second chance (if set to 2) exception on asserts.") -CONFIG_DWORD_INFO(INTERNAL_DebugBreakOnAssert, W("DebugBreakOnAssert"), 0, "If DACCESS_COMPILE is defined, break on asserts.") CONFIG_DWORD_INFO(INTERNAL_DebugBreakOnVerificationFailure, W("DebugBreakOnVerificationFailure"), 0, "Halts the jit on verification failure") CONFIG_STRING_INFO(INTERNAL_DebuggerBreakPoint, W("DebuggerBreakPoint"), "Allows counting various debug events") CONFIG_STRING_INFO(INTERNAL_DebugVerify, W("DebugVerify"), "Control for tracing in peverify") @@ -456,10 +453,6 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_Monitor_SpinCount, W("Monitor_SpinCount"), 0x1 /// Native Binder /// -CONFIG_DWORD_INFO(INTERNAL_NgenBind_ZapForbid, W("NgenBind_ZapForbid"), 0, "Assert if an assembly succeeds in binding to a native image") -CONFIG_STRING_INFO(INTERNAL_NgenBind_ZapForbidExcludeList, W("NgenBind_ZapForbidExcludeList"), "") -CONFIG_STRING_INFO(INTERNAL_NgenBind_ZapForbidList, W("NgenBind_ZapForbidList"), "") - CONFIG_DWORD_INFO(INTERNAL_SymDiffDump, W("SymDiffDump"), 0, "Used to create the map file while binding the assembly. Used by SemanticDiffer") /// diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index d3ccc3bb3a162b..80ef9c127733df 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -438,6 +438,8 @@ enum CorInfoHelpFunc CORINFO_HELP_CHKCASTCLASS_SPECIAL, // Optimized helper for classes. Assumes that the trivial cases // has been taken care of by the inlined check + CORINFO_HELP_ISINSTANCEOF_EXCEPTION, + CORINFO_HELP_BOX, // Fast box helper. Only possible exception is OutOfMemory CORINFO_HELP_BOX_NULLABLE, // special form of boxing for Nullable CORINFO_HELP_UNBOX, diff --git a/src/coreclr/inc/debugmacros.h b/src/coreclr/inc/debugmacros.h index aa99719399e16e..da88e15f12a07a 100644 --- a/src/coreclr/inc/debugmacros.h +++ b/src/coreclr/inc/debugmacros.h @@ -30,9 +30,6 @@ bool _DbgBreakCheck(LPCSTR szFile, int iLine, LPCSTR szExpr, BOOL fConstrained = extern VOID ANALYZER_NORETURN DbgAssertDialog(const char *szFile, int iLine, const char *szExpr); -#define TRACE_BUFF_SIZE (cchMaxAssertStackLevelStringLen * cfrMaxAssertStackLevels + cchMaxAssertExprLen + 1) -extern char g_szExprWithStack[TRACE_BUFF_SIZE]; - #define PRE_ASSERTE /* if you need to change modes before doing asserts override */ #define POST_ASSERTE /* put it back */ @@ -54,9 +51,7 @@ extern char g_szExprWithStack[TRACE_BUFF_SIZE]; #define VERIFY(stmt) _ASSERTE((stmt)) -#define _ASSERTE_ALL_BUILDS(file, expr) _ASSERTE((expr)) - -#define FreeBuildDebugBreak() DebugBreak() +#define _ASSERTE_ALL_BUILDS(expr) _ASSERTE((expr)) #else // !_DEBUG @@ -64,11 +59,6 @@ extern char g_szExprWithStack[TRACE_BUFF_SIZE]; #define _ASSERTE_MSG(expr, msg) ((void)0) #define VERIFY(stmt) (void)(stmt) -void __FreeBuildDebugBreak(); -void DECLSPEC_NORETURN __FreeBuildAssertFail(const char *szFile, int iLine, const char *szExpr); - -#define FreeBuildDebugBreak() __FreeBuildDebugBreak() - // At this point, EEPOLICY_HANDLE_FATAL_ERROR may or may not be defined. It will be defined // if we are building the VM folder, but outside VM, its not necessarily defined. // @@ -76,11 +66,11 @@ void DECLSPEC_NORETURN __FreeBuildAssertFail(const char *szFile, int iLine, cons // but if it is defined, we will use it. // // Failing here implies an error in the runtime - hence we use COR_E_EXECUTIONENGINE. - #ifdef EEPOLICY_HANDLE_FATAL_ERROR -#define _ASSERTE_ALL_BUILDS(file, expr) if (!(expr)) EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); +#define _ASSERTE_ALL_BUILDS(expr) if (!(expr)) EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); #else // !EEPOLICY_HANDLE_FATAL_ERROR -#define _ASSERTE_ALL_BUILDS(file, expr) if (!(expr)) __FreeBuildAssertFail(file, __LINE__, #expr); +void DECLSPEC_NORETURN __FreeBuildAssertFail(const char *szFile, int iLine, const char *szExpr); +#define _ASSERTE_ALL_BUILDS(expr) if (!(expr)) __FreeBuildAssertFail(__FILE__, __LINE__, #expr); #endif // EEPOLICY_HANDLE_FATAL_ERROR #endif @@ -98,9 +88,6 @@ void DECLSPEC_NORETURN __FreeBuildAssertFail(const char *szFile, int iLine, cons #ifdef _DEBUG_IMPL -// A macro to execute a statement only in _DEBUG_IMPL. -#define DEBUG_IMPL_STMT(stmt) stmt - #define _ASSERTE_IMPL(expr) _ASSERTE((expr)) #if defined(_M_IX86) @@ -115,7 +102,6 @@ void DECLSPEC_NORETURN __FreeBuildAssertFail(const char *szFile, int iLine, cons #define _DbgBreak() DebugBreak() #endif -extern VOID DebBreak(); extern VOID DebBreakHr(HRESULT hr); #ifndef IfFailGoto @@ -150,8 +136,6 @@ do { hr = (EXPR); if(hr != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(hr); DebBrea #define _DbgBreak() {} -#define DEBUG_IMPL_STMT(stmt) - #define _ASSERTE_IMPL(expr) #define IfFailGoto(EXPR, LABEL) \ @@ -210,14 +194,12 @@ unsigned DbgGetEXETimeStamp(); (((DbgGetEXETimeStamp() * __LINE__ * ((hash) ? (hash) : 1)) % 9973) < \ unsigned((fractionOn) * 9973)) #define DbgRandomOnExe(fractionOn) DbgRandomOnHashAndExe(0, fractionOn) -#define DbgRandomOnStringAndExe(string, fractionOn) DbgRandomOnHashAndExe(HashStringA(string), fractionOn) #else #define DbgGetEXETimeStamp() 0 #define DbgRandomOnHashAndExe(hash, fractionOn) 0 #define DbgRandomOnExe(fractionOn) 0 -#define DbgRandomOnStringAndExe(fractionOn) 0 #endif // _DEBUG && !FEATUREPAL diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 2a9fc7d7b044b0..dedd71fc3ea134 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* 0d853657-7a01-421f-b1b0-d22a8e691441 */ - 0x0d853657, - 0x7a01, - 0x421f, - {0xb1, 0xb0, 0xd2, 0x2a, 0x8e, 0x69, 0x14, 0x41} +constexpr GUID JITEEVersionIdentifier = { /* 4efa8fe2-8489-4b61-aac9-b4df74af15b7 */ + 0x4efa8fe2, + 0x8489, + 0x4b61, + {0xaa, 0xc9, 0xb4, 0xdf, 0x74, 0xaf, 0x15, 0xb7} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/inc/jithelpers.h b/src/coreclr/inc/jithelpers.h index a500c298978b67..e897d592322e69 100644 --- a/src/coreclr/inc/jithelpers.h +++ b/src/coreclr/inc/jithelpers.h @@ -99,6 +99,8 @@ DYNAMICJITHELPER(CORINFO_HELP_CHKCASTANY, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_CHKCASTCLASS_SPECIAL, NULL, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_ISINSTANCEOF_EXCEPTION, JIT_IsInstanceOfException, CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_BOX, JIT_Box, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_BOX_NULLABLE, JIT_Box, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_UNBOX, NULL, CORINFO_HELP_SIG_REG_ONLY) diff --git a/src/coreclr/inc/readytorun.h b/src/coreclr/inc/readytorun.h index e453dde1970a45..0934f2ea627481 100644 --- a/src/coreclr/inc/readytorun.h +++ b/src/coreclr/inc/readytorun.h @@ -16,7 +16,7 @@ // Keep these in sync with src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs #define READYTORUN_MAJOR_VERSION 0x0007 -#define READYTORUN_MINOR_VERSION 0x0000 +#define READYTORUN_MINOR_VERSION 0x0001 #define MINIMUM_READYTORUN_MAJOR_VERSION 0x006 @@ -329,6 +329,7 @@ enum ReadyToRunHelper READYTORUN_HELPER_GenericGcTlsBase = 0x66, READYTORUN_HELPER_GenericNonGcTlsBase = 0x67, READYTORUN_HELPER_VirtualFuncPtr = 0x68, + READYTORUN_HELPER_IsInstanceOfException = 0x69, // Long mul/div/shift ops READYTORUN_HELPER_LMul = 0xC0, diff --git a/src/coreclr/inc/readytorunhelpers.h b/src/coreclr/inc/readytorunhelpers.h index 66e2d4a3b164e3..b9d904b9c41935 100644 --- a/src/coreclr/inc/readytorunhelpers.h +++ b/src/coreclr/inc/readytorunhelpers.h @@ -54,6 +54,7 @@ HELPER(READYTORUN_HELPER_GenericGcTlsBase, CORINFO_HELP_GETGENERICS_GCT HELPER(READYTORUN_HELPER_GenericNonGcTlsBase, CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE,) HELPER(READYTORUN_HELPER_VirtualFuncPtr, CORINFO_HELP_VIRTUAL_FUNC_PTR, ) +HELPER(READYTORUN_HELPER_IsInstanceOfException, CORINFO_HELP_ISINSTANCEOF_EXCEPTION, ) HELPER(READYTORUN_HELPER_LMul, CORINFO_HELP_LMUL, ) HELPER(READYTORUN_HELPER_LMulOfv, CORINFO_HELP_LMUL_OVF, ) diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index d0f775b9efc157..23e279f47e1528 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -6677,8 +6677,7 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, if (compHasBackwardJump && (reason == nullptr) && (JitConfig.TC_OnStackReplacement() > 0)) { - const char* noPatchpointReason = nullptr; - bool canEscapeViaOSR = compCanHavePatchpoints(&reason); + bool canEscapeViaOSR = compCanHavePatchpoints(&reason); #ifdef DEBUG if (canEscapeViaOSR) @@ -6703,7 +6702,7 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, } else { - JITDUMP("\nOSR disabled for this method: %s\n", noPatchpointReason); + JITDUMP("\nOSR disabled for this method: %s\n", reason); assert(reason != nullptr); } } diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index f80271a95a86c8..a69148d93d5ef2 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -2216,6 +2216,8 @@ class Compiler bool fgNormalizeEHCase2(); bool fgNormalizeEHCase3(); + void fgCreateFiltersForGenericExceptions(); + void fgCheckForLoopsInHandlers(); #ifdef DEBUG diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index ae3da0f8b0d9c9..d353807493f5a1 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -4703,6 +4703,10 @@ inline bool Compiler::compCanHavePatchpoints(const char** reason) { whyNot = "OSR can't handle reverse pinvoke"; } + else if (!info.compIsStatic && !lvaIsOriginalThisReadOnly()) + { + whyNot = "OSR can't handle modifiable this"; + } #else whyNot = "OSR feature not defined in build"; #endif diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index b724c0a2c6302c..288c0e788255ea 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -2590,6 +2590,10 @@ void Compiler::fgAddInternal() { noway_assert(!compIsForInlining()); + // For runtime determined Exception types we're going to emit a fake EH filter with isinst for this + // type with a runtime lookup + fgCreateFiltersForGenericExceptions(); + // The backend requires a scratch BB into which it can safely insert a P/Invoke method prolog if one is // required. Similarly, we need a scratch BB for poisoning. Create it here. if (compMethodRequiresPInvokeFrame() || compShouldPoisonFrame()) diff --git a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp index df8cc0111a7f25..107705fa5e5729 100644 --- a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp @@ -1425,7 +1425,6 @@ void CodeGen::genSSE42Intrinsic(GenTreeHWIntrinsic* node) } else { - assert(op1->TypeGet() == op2->TypeGet()); assert((targetType == TYP_INT) || (targetType == TYP_LONG)); genHWIntrinsic_R_RM(node, INS_crc32, emitTypeSize(targetType), targetReg, op2); } diff --git a/src/coreclr/jit/jiteh.cpp b/src/coreclr/jit/jiteh.cpp index 66a2d65d8d68d6..278723442c3161 100644 --- a/src/coreclr/jit/jiteh.cpp +++ b/src/coreclr/jit/jiteh.cpp @@ -2506,6 +2506,93 @@ bool Compiler::fgNormalizeEHCase2() return modified; } +//------------------------------------------------------------------------ +// fgCreateFiltersForGenericExceptions: +// For Exception types which require runtime lookup it creates a "fake" single-block +// EH filter that performs "catchArg isinst T!!" and in case of success forwards to the +// original EH handler. +// + +void Compiler::fgCreateFiltersForGenericExceptions() +{ + for (unsigned ehNum = 0; ehNum < compHndBBtabCount; ehNum++) + { + EHblkDsc* eh = ehGetDsc(ehNum); + if (eh->ebdHandlerType == EH_HANDLER_CATCH) + { + // Resolve Exception type and check if it needs a runtime lookup + CORINFO_RESOLVED_TOKEN resolvedToken; + resolvedToken.tokenContext = impTokenLookupContextHandle; + resolvedToken.tokenScope = info.compScopeHnd; + resolvedToken.token = eh->ebdTyp; + resolvedToken.tokenType = CORINFO_TOKENKIND_Casting; + info.compCompHnd->resolveToken(&resolvedToken); + + CORINFO_GENERICHANDLE_RESULT embedInfo; + info.compCompHnd->embedGenericHandle(&resolvedToken, true, &embedInfo); + if (!embedInfo.lookup.lookupKind.needsRuntimeLookup) + { + // Exception type does not need runtime lookup + continue; + } + + // Create a new bb for the fake filter + BasicBlock* filterBb = bbNewBasicBlock(BBJ_EHFILTERRET); + BasicBlock* handlerBb = eh->ebdHndBeg; + + // Now we need to spill CATCH_ARG (it should be the first thing evaluated) + GenTree* arg = new (this, GT_CATCH_ARG) GenTree(GT_CATCH_ARG, TYP_REF); + arg->gtFlags |= GTF_ORDER_SIDEEFF; + unsigned tempNum = lvaGrabTemp(false DEBUGARG("SpillCatchArg")); + lvaTable[tempNum].lvType = TYP_REF; + GenTree* argAsg = gtNewTempAssign(tempNum, arg); + arg = gtNewLclvNode(tempNum, TYP_REF); + fgInsertStmtAtBeg(filterBb, gtNewStmt(argAsg, handlerBb->firstStmt()->GetDebugInfo())); + + // Create "catchArg is TException" tree + GenTree* runtimeLookup; + if (embedInfo.lookup.runtimeLookup.indirections == CORINFO_USEHELPER) + { + GenTree* ctxTree = getRuntimeContextTree(embedInfo.lookup.lookupKind.runtimeLookupKind); + runtimeLookup = impReadyToRunHelperToTree(&resolvedToken, CORINFO_HELP_READYTORUN_GENERIC_HANDLE, + TYP_I_IMPL, &embedInfo.lookup.lookupKind, ctxTree); + } + else + { + runtimeLookup = getTokenHandleTree(&resolvedToken, true); + } + GenTree* isInstOfT = gtNewHelperCallNode(CORINFO_HELP_ISINSTANCEOF_EXCEPTION, TYP_INT, runtimeLookup, arg); + GenTree* retFilt = gtNewOperNode(GT_RETFILT, TYP_INT, isInstOfT); + + // Insert it right before the handler (and make it a pred of the handler) + fgInsertBBbefore(handlerBb, filterBb); + fgAddRefPred(handlerBb, filterBb); + fgNewStmtAtEnd(filterBb, retFilt, handlerBb->firstStmt()->GetDebugInfo()); + + filterBb->bbCatchTyp = BBCT_FILTER; + filterBb->bbCodeOffs = handlerBb->bbCodeOffs; + filterBb->bbHndIndex = handlerBb->bbHndIndex; + filterBb->bbTryIndex = handlerBb->bbTryIndex; + filterBb->bbJumpDest = handlerBb; + filterBb->bbSetRunRarely(); + filterBb->bbFlags |= BBF_INTERNAL | BBF_DONT_REMOVE; + + handlerBb->bbCatchTyp = BBCT_FILTER_HANDLER; + eh->ebdHandlerType = EH_HANDLER_FILTER; + eh->ebdFilter = filterBb; + +#ifdef DEBUG + if (verbose) + { + JITDUMP("EH%d: Adding EH filter block " FMT_BB " in front of generic handler " FMT_BB ":\n", ehNum, + filterBb->bbNum, handlerBb->bbNum); + fgDumpBlock(filterBb); + } +#endif // DEBUG + } + } +} + bool Compiler::fgNormalizeEHCase3() { bool modified = false; diff --git a/src/coreclr/jit/lower.h b/src/coreclr/jit/lower.h index 46e1accf726cb3..b8b5686133efc2 100644 --- a/src/coreclr/jit/lower.h +++ b/src/coreclr/jit/lower.h @@ -377,17 +377,36 @@ class Lowering final : public Phase // Otherwise, it returns the underlying operation that was being casted GenTree* TryRemoveCastIfPresent(var_types expectedType, GenTree* op) { - if (!op->OperIs(GT_CAST)) + if (!op->OperIs(GT_CAST) || !comp->opts.OptimizationEnabled()) { return op; } - GenTree* castOp = op->AsCast()->CastOp(); + GenTreeCast* cast = op->AsCast(); - if (genTypeSize(castOp->gtType) >= genTypeSize(expectedType)) + // FP <-> INT casts should be kept + if (varTypeIsFloating(cast->CastFromType()) ^ varTypeIsFloating(expectedType)) { + return op; + } + + // Keep casts which can overflow + if (cast->gtOverflow()) + { + return op; + } + + if (genTypeSize(cast->CastToType()) >= genTypeSize(expectedType)) + { +#ifndef TARGET_64BIT + // Don't expose TYP_LONG on 32bit + if (varTypeIsLong(cast->CastFromType())) + { + return op; + } +#endif BlockRange().Remove(op); - return castOp; + return cast->CastOp(); } return op; diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs index 4483386fd9f27c..9e576853a44cb1 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs @@ -847,7 +847,7 @@ private static bool ShouldTypedClauseCatchThisException(object exception, Method AssertNotRuntimeObject(pClauseType); #endif - return TypeCast.IsInstanceOfClass(pClauseType, exception) != null; + return TypeCast.IsInstanceOfException(pClauseType, exception); } private static void InvokeSecondPass(ref ExInfo exInfo, uint idxStart) diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs index 1c27761fedc7e0..83c4f141a3d633 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs @@ -908,6 +908,43 @@ public static unsafe object IsInstanceOf(MethodTable* pTargetType, object obj) return IsInstanceOfClass(pTargetType, obj); } + [RuntimeExport("RhTypeCast_IsInstanceOfException")] + public static unsafe bool IsInstanceOfException(MethodTable* pTargetType, object? obj) + { + // Based on IsInstanceOfClass_Helper + + if (obj == null) + return false; + + MethodTable* pObjType = obj.GetMethodTable(); + + if (pTargetType->IsCloned) + pTargetType = pTargetType->CanonicalEEType; + + if (pObjType->IsCloned) + pObjType = pObjType->CanonicalEEType; + + if (pObjType == pTargetType) + return true; + + // arrays can be cast to System.Object and System.Array + if (pObjType->IsArray) + return WellKnownEETypes.IsSystemObject(pTargetType) || WellKnownEETypes.IsSystemArray(pTargetType); + + while (true) + { + pObjType = pObjType->NonClonedNonArrayBaseType; + if (pObjType == null) + return false; + + if (pObjType->IsCloned) + pObjType = pObjType->CanonicalEEType; + + if (pObjType == pTargetType) + return true; + } + } + [RuntimeExport("RhTypeCast_CheckCast")] public static unsafe object CheckCast(MethodTable* pTargetType, object obj) { diff --git a/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp b/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp index 064da7e74f03d7..381079d2079a6e 100644 --- a/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp @@ -48,6 +48,12 @@ COOP_PINVOKE_HELPER(void, RhDebugBreak, ()) // Busy spin for the given number of iterations. EXTERN_C NATIVEAOT_API void __cdecl RhSpinWait(int32_t iterations) { + ASSERT(iterations > 0); + + // limit the spin count in coop mode. + ASSERT_MSG(iterations <= 10000 || !ThreadStore::GetCurrentThread()->IsCurrentThreadInCooperativeMode(), + "This is too long wait for coop mode. You must p/invoke with GC transition."); + YieldProcessorNormalizationInfo normalizationInfo; YieldProcessorNormalizedForPreSkylakeCount(normalizationInfo, iterations); } diff --git a/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h b/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h index 8600b4c5913c1e..57aac4fc8d00d7 100644 --- a/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h +++ b/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h @@ -11,7 +11,7 @@ struct ReadyToRunHeaderConstants static const uint32_t Signature = 0x00525452; // 'RTR' static const uint32_t CurrentMajorVersion = 7; - static const uint32_t CurrentMinorVersion = 0; + static const uint32_t CurrentMinorVersion = 1; }; struct ReadyToRunHeader diff --git a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp index 0c776a204dc57f..506c645d71d244 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp @@ -1200,6 +1200,7 @@ extern "C" uint64_t PalGetCurrentThreadIdForLogging() #if defined(HOST_X86) || defined(HOST_AMD64) +#if !__has_builtin(__cpuid) REDHAWK_PALEXPORT void __cpuid(int cpuInfo[4], int function_id) { // Based on the Clang implementation provided in cpuid.h: @@ -1210,7 +1211,9 @@ REDHAWK_PALEXPORT void __cpuid(int cpuInfo[4], int function_id) : "0"(function_id) ); } +#endif +#if !__has_builtin(__cpuidex) REDHAWK_PALEXPORT void __cpuidex(int cpuInfo[4], int function_id, int subFunction_id) { // Based on the Clang implementation provided in cpuid.h: @@ -1221,6 +1224,7 @@ REDHAWK_PALEXPORT void __cpuidex(int cpuInfo[4], int function_id, int subFunctio : "0"(function_id), "2"(subFunction_id) ); } +#endif REDHAWK_PALEXPORT uint32_t REDHAWK_PALAPI xmmYmmStateSupport() { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.NativeAot.cs index 319f48a9003ac2..3e68bc3c75c1f6 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.NativeAot.cs @@ -614,7 +614,7 @@ internal static IntPtr ComInterfaceForObject(object instance) { if (s_globalInstanceForMarshalling == null) { - throw new InvalidOperationException(SR.InvalidOperation_ComInteropRequireComWrapperInstance); + throw new NotSupportedException(SR.InvalidOperation_ComInteropRequireComWrapperInstance); } return s_globalInstanceForMarshalling.GetOrCreateComInterfaceForObject(instance, CreateComInterfaceFlags.None); @@ -640,7 +640,7 @@ internal static object ComObjectForInterface(IntPtr externalComObject) { if (s_globalInstanceForMarshalling == null) { - throw new InvalidOperationException(SR.InvalidOperation_ComInteropRequireComWrapperInstance); + throw new NotSupportedException(SR.InvalidOperation_ComInteropRequireComWrapperInstance); } return s_globalInstanceForMarshalling.GetOrCreateObjectForComInstance(externalComObject, CreateObjectFlags.Unwrap); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Com.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Com.cs index 12666933852d5d..37a2728dfb5bd1 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Com.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Com.cs @@ -28,14 +28,14 @@ public static int GetHRForException(Exception? e) [EditorBrowsable(EditorBrowsableState.Never)] public static IntPtr CreateAggregatedObject(IntPtr pOuter, object o) { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); } [RequiresUnreferencedCode("Built-in COM support is not trim compatible", Url = "https://aka.ms/dotnet-illink/com")] [SupportedOSPlatform("windows")] public static object BindToMoniker(string monikerName) { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); } public static void CleanupUnusedObjectsInCurrentContext() @@ -45,32 +45,32 @@ public static void CleanupUnusedObjectsInCurrentContext() [SupportedOSPlatform("windows")] public static IntPtr CreateAggregatedObject(IntPtr pOuter, T o) where T : notnull { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); } [SupportedOSPlatform("windows")] [EditorBrowsable(EditorBrowsableState.Never)] public static object? CreateWrapperOfType(object? o, Type t) { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); } [SupportedOSPlatform("windows")] public static TWrapper CreateWrapperOfType(T? o) { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); } [SupportedOSPlatform("windows")] public static void ChangeWrapperHandleStrength(object otp, bool fIsWeak) { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); } [SupportedOSPlatform("windows")] public static int FinalReleaseComObject(object o) { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); } [SupportedOSPlatform("windows")] @@ -94,7 +94,7 @@ public static IntPtr GetComInterfaceForObject(object o, Type T) [EditorBrowsable(EditorBrowsableState.Never)] public static IntPtr GetComInterfaceForObject(object o, Type T, CustomQueryInterfaceMode mode) { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); } [SupportedOSPlatform("windows")] @@ -106,7 +106,7 @@ public static IntPtr GetComInterfaceForObject([DisallowNull] T o) [SupportedOSPlatform("windows")] public static object? GetComObjectData(object obj, object key) { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); } [SupportedOSPlatform("windows")] @@ -302,7 +302,7 @@ public static void GetNativeVariantForObject(T? obj, IntPtr pDstNativeVariant [SupportedOSPlatform("windows")] public static object GetTypedObjectForIUnknown(IntPtr pUnk, Type t) { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); } [SupportedOSPlatform("windows")] @@ -364,33 +364,33 @@ public static object GetObjectForIUnknown(IntPtr pUnk) [EditorBrowsable(EditorBrowsableState.Never)] public static T GetObjectForNativeVariant(IntPtr pSrcNativeVariant) { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); } [SupportedOSPlatform("windows")] [EditorBrowsable(EditorBrowsableState.Never)] public static object?[] GetObjectsForNativeVariants(IntPtr aSrcNativeVariant, int cVars) { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); } [SupportedOSPlatform("windows")] [EditorBrowsable(EditorBrowsableState.Never)] public static T[] GetObjectsForNativeVariants(IntPtr aSrcNativeVariant, int cVars) { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); } [SupportedOSPlatform("windows")] public static int GetStartComSlot(Type t) { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); } [SupportedOSPlatform("windows")] public static int GetEndComSlot(Type t) { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); } internal static Type? GetTypeFromCLSID(Guid clsid, string? server, bool throwOnError) @@ -401,13 +401,13 @@ public static int GetEndComSlot(Type t) [SupportedOSPlatform("windows")] public static string GetTypeInfoName(ITypeInfo typeInfo) { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); } [SupportedOSPlatform("windows")] public static object GetUniqueObjectForIUnknown(IntPtr unknown) { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); } public static bool IsComObject(object o) @@ -432,13 +432,13 @@ public static bool IsTypeVisibleFromCom(Type t) [SupportedOSPlatform("windows")] public static int ReleaseComObject(object o) { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); } [SupportedOSPlatform("windows")] public static bool SetComObjectData(object obj, object key, object? data) { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); } } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs index 287e80b34de9ac..35077dc025b3e3 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -327,6 +327,10 @@ internal static unsafe object IsInstanceOf(EETypePtr pTargetType, object obj) [RuntimeImport(RuntimeLibrary, "RhTypeCast_IsInstanceOfInterface")] internal static extern unsafe object IsInstanceOfInterface(MethodTable* pTargetType, object obj); + [MethodImpl(MethodImplOptions.InternalCall)] + [RuntimeImport(RuntimeLibrary, "RhTypeCast_IsInstanceOfException")] + internal static extern unsafe bool IsInstanceOfException(MethodTable* pTargetType, object obj); + internal static unsafe object IsInstanceOfInterface(EETypePtr pTargetType, object obj) => IsInstanceOfInterface(pTargetType.ToPointer(), obj); @@ -388,6 +392,11 @@ internal static unsafe void RhUnbox(object? obj, ref byte data, EETypePtr pUnbox [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] internal static partial void RhSpinWait(int iterations); + // Call RhSpinWait with a GC transition + [LibraryImport(RuntimeLibrary, EntryPoint = "RhSpinWait")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial void RhLongSpinWait(int iterations); + // Yield the cpu to another thread ready to process, if one is available. [LibraryImport(RuntimeLibrary, EntryPoint = "RhYield")] [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.cs index 2564eec546c229..543ba774c39a99 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.cs @@ -322,7 +322,30 @@ public bool Join(int millisecondsTimeout) /// internal const int OptimalMaxSpinWaitsPerSpinIteration = 64; - public static void SpinWait(int iterations) => RuntimeImports.RhSpinWait(iterations); + [MethodImpl(MethodImplOptions.NoInlining)] + private static void LongSpinWait(int iterations) + { + RuntimeImports.RhLongSpinWait(iterations); + } + + public static void SpinWait(int iterations) + { + if (iterations <= 0) + return; + + // Max iterations to be done in RhSpinWait. + // RhSpinWait does not switch GC modes and we want to avoid native spinning in coop mode for too long. + const int spinWaitCoopThreshold = 10000; + + if (iterations > spinWaitCoopThreshold) + { + LongSpinWait(iterations); + } + else + { + RuntimeImports.RhSpinWait(iterations); + } + } [MethodImpl(MethodImplOptions.NoInlining)] // Slow path method. Make sure that the caller frame does not pay for PInvoke overhead. public static bool Yield() => RuntimeImports.RhYield(); diff --git a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs index ea705d1f6f34af..c73467fab3b0fc 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs @@ -15,7 +15,7 @@ internal struct ReadyToRunHeaderConstants public const uint Signature = 0x00525452; // 'RTR' public const ushort CurrentMajorVersion = 7; - public const ushort CurrentMinorVersion = 0; + public const ushort CurrentMinorVersion = 1; } #pragma warning disable 0169 diff --git a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs index 0bea2c3d326a83..193b0f3814a483 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs @@ -255,6 +255,7 @@ public enum ReadyToRunHelper GenericGcTlsBase = 0x66, GenericNonGcTlsBase = 0x67, VirtualFuncPtr = 0x68, + IsInstanceOfException = 0x69, // Long mul/div/shift ops LMul = 0xC0, diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs b/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs index fd178769a1883d..b0a53c8232e566 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs @@ -84,6 +84,8 @@ which is the right helper to use to allocate an object of a given type. */ CORINFO_HELP_CHKCASTCLASS_SPECIAL, // Optimized helper for classes. Assumes that the trivial cases // has been taken care of by the inlined check + CORINFO_HELP_ISINSTANCEOF_EXCEPTION, + CORINFO_HELP_BOX, // Fast box helper. Only possible exception is OutOfMemory CORINFO_HELP_BOX_NULLABLE, // special form of boxing for Nullable CORINFO_HELP_UNBOX, diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 37fe38ad7965f1..752b80e8b3b99a 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -737,24 +737,6 @@ private bool Get_CORINFO_METHOD_INFO(MethodDesc method, MethodIL methodIL, CORIN Get_CORINFO_SIG_INFO(method, sig: &methodInfo->args, methodIL); Get_CORINFO_SIG_INFO(methodIL.GetLocals(), &methodInfo->locals); -#if READYTORUN - if ((methodInfo->options & CorInfoOptions.CORINFO_GENERICS_CTXT_MASK) != 0) - { - foreach (var region in exceptionRegions) - { - if (region.Kind == ILExceptionRegionKind.Catch) - { - TypeDesc catchType = (TypeDesc)methodIL.GetObject(region.ClassToken); - if (catchType.IsCanonicalSubtype(CanonicalFormKind.Any)) - { - methodInfo->options |= CorInfoOptions.CORINFO_GENERICS_CTXT_KEEP_ALIVE; - break; - } - } - } - } -#endif - return true; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunGenericHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunGenericHelperNode.cs index 5857cee6588eb1..d126ad038c86d5 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunGenericHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunGenericHelperNode.cs @@ -36,6 +36,17 @@ protected void EmitDictionaryLookup(NodeFactory factory, ref ARM64Emitter encode // Load the generic dictionary cell encoder.EmitLDR(result, context, dictionarySlot * factory.Target.PointerSize); + // If there's any invalid entries, we need to test for them + // + // Only do this in relocsOnly to make it easier to weed out bugs - the _hasInvalidEntries + // flag can change over the course of compilation and the bad slot helper dependency + // should be reported by someone else - the system should not rely on it coming from here. + if (!relocsOnly && _hasInvalidEntries) + { + encoder.EmitCMP(result, 0); + encoder.EmitJE(GetBadSlotHelper(factory)); + } + switch (lookup.LookupResultReferenceType(factory)) { case GenericLookupResultReferenceType.Indirect: diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs index a4ae4c40a66877..3cbd44db0b3892 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs @@ -248,6 +248,9 @@ public static void GetEntryPoint(TypeSystemContext context, ReadyToRunHelper id, case ReadyToRunHelper.CheckInstanceAny: mangledName = "RhTypeCast_IsInstanceOf"; break; + case ReadyToRunHelper.IsInstanceOfException: + mangledName = "RhTypeCast_IsInstanceOfException"; + break; case ReadyToRunHelper.CheckCastInterface: mangledName = "RhTypeCast_CheckCastInterface"; break; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs index 3f561a850444fd..9f9c877fbed5db 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs @@ -196,15 +196,15 @@ private void StartImportingBasicBlock(BasicBlock basicBlock) if (region.Kind == ILExceptionRegionKind.Filter) MarkBasicBlock(_basicBlocks[region.FilterOffset]); - // Once https://github.com/dotnet/corert/issues/3460 is done, this should be deleted. - // Throwing InvalidProgram is not great, but we want to do *something* if this happens - // because doing nothing means problems at runtime. This is not worth piping a - // a new exception with a fancy message for. if (region.Kind == ILExceptionRegionKind.Catch) { TypeDesc catchType = (TypeDesc)_methodIL.GetObject(region.ClassToken); if (catchType.IsRuntimeDeterminedSubtype) - ThrowHelper.ThrowInvalidProgramException(); + { + // For runtime determined Exception types we're going to emit a fake EH filter with isinst for this + // type with a runtime lookup + _dependencies.Add(GetGenericLookupHelper(ReadyToRunHelperId.TypeHandleForCasting, catchType), "EH filter"); + } } } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs index dea0974db53572..dce751e370c76b 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -775,6 +775,9 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) id = ReadyToRunHelper.GetRuntimeTypeHandle; break; + case CorInfoHelpFunc.CORINFO_HELP_ISINSTANCEOF_EXCEPTION: + id = ReadyToRunHelper.IsInstanceOfException; + break; case CorInfoHelpFunc.CORINFO_HELP_BOX: id = ReadyToRunHelper.Box; break; diff --git a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs index ee33514878293c..ab88c0ce03e607 100644 --- a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs +++ b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs @@ -1782,6 +1782,10 @@ private void ParseHelper(StringBuilder builder) builder.Append("CHECK_INSTANCE_ANY"); break; + case ReadyToRunHelper.IsInstanceOfException: + builder.Append("SIMPLE_ISINSTANCE_OF"); + break; + case ReadyToRunHelper.GenericGcStaticBase: builder.Append("GENERIC_GC_STATIC_BASE"); break; diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 8dcbc88db42d4a..e54366f91906f8 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -543,6 +543,9 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) id = ReadyToRunHelper.AreTypesEquivalent; break; + case CorInfoHelpFunc.CORINFO_HELP_ISINSTANCEOF_EXCEPTION: + id = ReadyToRunHelper.IsInstanceOfException; + break; case CorInfoHelpFunc.CORINFO_HELP_BOX: id = ReadyToRunHelper.Box; break; @@ -906,13 +909,6 @@ private ObjectNode.ObjectData EncodeEHInfo() var methodIL = (MethodIL)HandleToObject((IntPtr)_methodScope); var type = (TypeDesc)methodIL.GetObject((int)clause.ClassTokenOrOffset); - // Once https://github.com/dotnet/corert/issues/3460 is done, this should be an assert. - // Throwing InvalidProgram is not great, but we want to do *something* if this happens - // because doing nothing means problems at runtime. This is not worth piping a - // a new exception with a fancy message for. - if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) - ThrowHelper.ThrowInvalidProgramException(); - var typeSymbol = _compilation.NecessaryTypeSymbolIfPossible(type); RelocType rel = (_compilation.NodeFactory.Target.IsWindows) ? diff --git a/src/coreclr/utilcode/debug.cpp b/src/coreclr/utilcode/debug.cpp index dc772a32136859..eadce8075bdaf4 100644 --- a/src/coreclr/utilcode/debug.cpp +++ b/src/coreclr/utilcode/debug.cpp @@ -46,38 +46,22 @@ static void GetExecutableFileNameUtf8(SString& value) tmp.ConvertToUTF8(value); } -#ifdef _DEBUG - - -//***************************************************************************** -// This struct tracks the asserts we want to ignore in the rest of this -// run of the application. -//***************************************************************************** -struct _DBGIGNOREDATA -{ - char rcFile[_MAX_PATH]; - int iLine; - bool bIgnore; -}; - -typedef CDynArray<_DBGIGNOREDATA> DBGIGNORE; -static BYTE grIgnoreMemory[sizeof(DBGIGNORE)]; -inline DBGIGNORE* GetDBGIGNORE() +static void DECLSPEC_NORETURN FailFastOnAssert() { - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; + WRAPPER_NO_CONTRACT; // If we're calling this, we're well past caring about contract consistency! - static bool fInit; // = false; - if (!fInit) - { - SCAN_IGNORE_THROW; // Doesn't really throw here. - new (grIgnoreMemory) CDynArray<_DBGIGNOREDATA>(); - fInit = true; - } + FlushLogging(); // make certain we get the last part of the log + _flushall(); - return (DBGIGNORE*)grIgnoreMemory; + ShutdownLogging(); +#ifdef HOST_WINDOWS + CreateCrashDumpIfEnabled(); +#endif + RaiseFailFastException(NULL, NULL, 0); } +#ifdef _DEBUG + // Continue the app on an assert. Still output the assert, but // Don't throw up a GUI. This is useful for testing fatal error // paths (like FEEE) where the runtime asserts. @@ -157,50 +141,6 @@ BOOL RaiseExceptionOnAssert(RaiseOnAssertOptions option = rTestAndRaise) return fRet != 0; } -BOOL DebugBreakOnAssert() -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_DEBUG_ONLY; - STATIC_CONTRACT_FORBID_FAULT; - STATIC_CONTRACT_SUPPORTS_DAC; - - // ok for debug-only code to take locks - CONTRACT_VIOLATION(TakesLockViolation); - - BOOL fRet = FALSE; - -#ifndef DACCESS_COMPILE - static ConfigDWORD fDebugBreak; - // - // we don't want this config key to affect mscordacwks as well! - // - EX_TRY - { - fRet = fDebugBreak.val(CLRConfig::INTERNAL_DebugBreakOnAssert); - } - EX_CATCH - { - } - EX_END_CATCH(SwallowAllExceptions); -#endif // DACCESS_COMPILE - - return fRet; -} - -VOID DECLSPEC_NORETURN TerminateOnAssert() -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_DEBUG_ONLY; - - ShutdownLogging(); -#ifdef HOST_WINDOWS - CreateCrashDumpIfEnabled(); -#endif - RaiseFailFastException(NULL, NULL, 0); -} - VOID LogAssert( LPCSTR szFile, int iLine, @@ -222,8 +162,8 @@ VOID LogAssert( GetSystemTime(&st); #endif - PathString exename; - WszGetModuleFileName(NULL, exename); + SString exename; + GetExecutableFileNameUtf8(exename); LOG((LF_ASSERT, LL_FATALERROR, @@ -242,60 +182,9 @@ VOID LogAssert( szFile, iLine, szExpr)); - LOG((LF_ASSERT, LL_FATALERROR, "RUNNING EXE: %ws\n", exename.GetUnicode())); -} - -//***************************************************************************** - -BOOL LaunchJITDebugger() -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_DEBUG_ONLY; - - BOOL fSuccess = FALSE; -#ifndef TARGET_UNIX - EX_TRY - { - SString debugger; - GetDebuggerSettingInfo(debugger, NULL); - - SECURITY_ATTRIBUTES sa; - sa.nLength = sizeof(sa); - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = TRUE; - - // We can leave this event as it is since it is inherited by a child process. - // We will block one scheduler, but the process is asking a user if they want to attach debugger. - HandleHolder eventHandle = WszCreateEvent(&sa, TRUE, FALSE, NULL); - if (eventHandle == NULL) - ThrowOutOfMemory(); - - SString cmdLine; - cmdLine.Printf(debugger, GetCurrentProcessId(), eventHandle.GetValue()); - - STARTUPINFO StartupInfo; - memset(&StartupInfo, 0, sizeof(StartupInfo)); - StartupInfo.cb = sizeof(StartupInfo); - StartupInfo.lpDesktop = const_cast(W("Winsta0\\Default")); - - PROCESS_INFORMATION ProcessInformation; - if (WszCreateProcess(NULL, cmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &StartupInfo, &ProcessInformation)) - { - WaitForSingleObject(eventHandle.GetValue(), INFINITE); - } - - fSuccess = TRUE; - } - EX_CATCH - { - } - EX_END_CATCH(SwallowAllExceptions); -#endif // !TARGET_UNIX - return fSuccess; + LOG((LF_ASSERT, LL_FATALERROR, "RUNNING EXE: %s\n", exename.GetUTF8())); } - //***************************************************************************** // This function is called in order to ultimately return an out of memory // failed hresult. But this code will check what environment you are running @@ -330,19 +219,6 @@ bool _DbgBreakCheck( STATIC_CONTRACT_FORBID_FAULT; STATIC_CONTRACT_DEBUG_ONLY; - DBGIGNORE* pDBGIFNORE = GetDBGIGNORE(); - _DBGIGNOREDATA *psData; - int i; - - // Check for ignore all. - for (i = 0, psData = pDBGIFNORE->Ptr(); i < pDBGIFNORE->Count(); i++, psData++) - { - if (psData->iLine == iLine && SString::_stricmp(psData->rcFile, szFile) == 0 && psData->bIgnore == true) - { - return false; - } - } - CONTRACT_VIOLATION(FaultNotFatal | GCViolation | TakesLockViolation); char formatBuffer[4096]; @@ -398,20 +274,18 @@ bool _DbgBreakCheck( } LogAssert(szFile, iLine, szExpr); - FlushLogging(); // make certain we get the last part of the log - _flushall(); if (ContinueOnAssert()) { return false; // don't stop debugger. No gui. } - if (IsDebuggerPresent() || DebugBreakOnAssert()) + if (IsDebuggerPresent()) { return true; // like a retry } - TerminateOnAssert(); + FailFastOnAssert(); UNREACHABLE(); } @@ -472,15 +346,6 @@ unsigned DbgGetEXETimeStamp() } #endif // TARGET_UNIX -// Called from within the IfFail...() macros. Set a breakpoint here to break on -// errors. -VOID DebBreak() -{ - STATIC_CONTRACT_LEAF; - static int i = 0; // add some code here so that we'll be able to set a BP - i++; -} - VOID DebBreakHr(HRESULT hr) { STATIC_CONTRACT_LEAF; @@ -643,39 +508,14 @@ bool GetStackTraceAtContext(SString & s, CONTEXT * pContext) #endif // !defined(DACCESS_COMPILE) #endif // _DEBUG -/**************************************************************************** - The following two functions are defined to allow Free builds to call - DebugBreak or to Assert with a stack trace for unexpected fatal errors. - Typically these paths are enabled via a registry key in a Free Build -*****************************************************************************/ - -VOID __FreeBuildDebugBreak() -{ - WRAPPER_NO_CONTRACT; // If we're calling this, we're well past caring about contract consistency! - - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_BreakOnRetailAssert)) - { - DebugBreak(); - } -} - -void *freForceToMemory; // dummy pointer that pessimises enregistration - void DECLSPEC_NORETURN __FreeBuildAssertFail(const char *szFile, int iLine, const char *szExpr) { WRAPPER_NO_CONTRACT; // If we're calling this, we're well past caring about contract consistency! - freForceToMemory = &szFile; //make certain these args are available in the debugger - freForceToMemory = &iLine; - freForceToMemory = &szExpr; - - __FreeBuildDebugBreak(); - - SString buffer; SString modulePath; - GetExecutableFileNameUtf8(modulePath); + SString buffer; buffer.Printf("CLR: Assert failure(PID %d [0x%08x], Thread: %d [0x%x]): %s\n" " File: %s, Line: %d Image:\n%s\n", GetCurrentProcessId(), GetCurrentProcessId(), @@ -690,16 +530,6 @@ void DECLSPEC_NORETURN __FreeBuildAssertFail(const char *szFile, int iLine, cons // may not be a string literal (particularly for formatt-able asserts). STRESS_LOG2(LF_ASSERT, LL_ALWAYS, "ASSERT:%s, line:%d\n", szFile, iLine); - FlushLogging(); // make certain we get the last part of the log - - _flushall(); - - ShutdownLogging(); - -#ifdef HOST_WINDOWS - CreateCrashDumpIfEnabled(); -#endif - RaiseFailFastException(NULL, NULL, 0); - + FailFastOnAssert(); UNREACHABLE(); } diff --git a/src/coreclr/vm/amd64/cgenamd64.cpp b/src/coreclr/vm/amd64/cgenamd64.cpp index ec0f890071c7ac..09b3f64612f038 100644 --- a/src/coreclr/vm/amd64/cgenamd64.cpp +++ b/src/coreclr/vm/amd64/cgenamd64.cpp @@ -713,7 +713,7 @@ DWORD GetOffsetAtEndOfFunction(ULONGLONG uImageBase, DWORD* pOffset = (DWORD*) (pEndOfFunction) - offsetNum; DWORD offsetInFunc = *pOffset; - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/cGenAMD64.cpp", (offsetInFunc >= 0) && (offsetInFunc < functionSize)); + _ASSERTE_ALL_BUILDS((offsetInFunc >= 0) && (offsetInFunc < functionSize)); return offsetInFunc; } diff --git a/src/coreclr/vm/amd64/jitinterfaceamd64.cpp b/src/coreclr/vm/amd64/jitinterfaceamd64.cpp index d4ab7437d4a050..cb97d03f66a600 100644 --- a/src/coreclr/vm/amd64/jitinterfaceamd64.cpp +++ b/src/coreclr/vm/amd64/jitinterfaceamd64.cpp @@ -122,33 +122,33 @@ void WriteBarrierManager::Validate() pLowerBoundImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_PreGrow64, Patch_Label_Lower, 2); pCardTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_PreGrow64, Patch_Label_CardTable, 2); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pLowerBoundImmediate) & 0x7) == 0); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pCardTableImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pLowerBoundImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pCardTableImmediate) & 0x7) == 0); #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES pCardBundleTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_PreGrow64, Patch_Label_CardBundleTable, 2); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pCardBundleTableImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pCardBundleTableImmediate) & 0x7) == 0); #endif pLowerBoundImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_PostGrow64, Patch_Label_Lower, 2); pUpperBoundImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_PostGrow64, Patch_Label_Upper, 2); pCardTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_PostGrow64, Patch_Label_CardTable, 2); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pLowerBoundImmediate) & 0x7) == 0); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pUpperBoundImmediate) & 0x7) == 0); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pCardTableImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pLowerBoundImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pUpperBoundImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pCardTableImmediate) & 0x7) == 0); #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES pCardBundleTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_PostGrow64, Patch_Label_CardBundleTable, 2); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pCardBundleTableImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pCardBundleTableImmediate) & 0x7) == 0); #endif #ifdef FEATURE_SVR_GC pCardTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_SVR64, PatchLabel_CardTable, 2); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pCardTableImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pCardTableImmediate) & 0x7) == 0); #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES pCardBundleTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_SVR64, PatchLabel_CardBundleTable, 2); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pCardBundleTableImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pCardBundleTableImmediate) & 0x7) == 0); #endif // FEATURE_MANUALLY_MANAGED_CARD_BUNDLES #endif // FEATURE_SVR_GC @@ -159,13 +159,13 @@ void WriteBarrierManager::Validate() pLowerBoundImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_WriteWatch_PreGrow64, Patch_Label_Lower, 2); pCardTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_WriteWatch_PreGrow64, Patch_Label_CardTable, 2); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pWriteWatchTableImmediate) & 0x7) == 0); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pLowerBoundImmediate) & 0x7) == 0); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pCardTableImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pWriteWatchTableImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pLowerBoundImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pCardTableImmediate) & 0x7) == 0); #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES pCardBundleTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_WriteWatch_PreGrow64, Patch_Label_CardBundleTable, 2); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pCardBundleTableImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pCardBundleTableImmediate) & 0x7) == 0); #endif pWriteWatchTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_WriteWatch_PostGrow64, Patch_Label_WriteWatchTable, 2); @@ -173,25 +173,25 @@ void WriteBarrierManager::Validate() pUpperBoundImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_WriteWatch_PostGrow64, Patch_Label_Upper, 2); pCardTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_WriteWatch_PostGrow64, Patch_Label_CardTable, 2); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pWriteWatchTableImmediate) & 0x7) == 0); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pLowerBoundImmediate) & 0x7) == 0); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pUpperBoundImmediate) & 0x7) == 0); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pCardTableImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pWriteWatchTableImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pLowerBoundImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pUpperBoundImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pCardTableImmediate) & 0x7) == 0); #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES pCardBundleTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_WriteWatch_PostGrow64, Patch_Label_CardBundleTable, 2); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pCardBundleTableImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pCardBundleTableImmediate) & 0x7) == 0); #endif #ifdef FEATURE_SVR_GC pWriteWatchTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_WriteWatch_SVR64, PatchLabel_WriteWatchTable, 2); pCardTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_WriteWatch_SVR64, PatchLabel_CardTable, 2); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pWriteWatchTableImmediate) & 0x7) == 0); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pCardTableImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pWriteWatchTableImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pCardTableImmediate) & 0x7) == 0); #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES pCardBundleTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_WriteWatch_SVR64, PatchLabel_CardBundleTable, 2); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (reinterpret_cast(pCardBundleTableImmediate) & 0x7) == 0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pCardBundleTableImmediate) & 0x7) == 0); #endif // FEATURE_MANUALLY_MANAGED_CARD_BUNDLES #endif // FEATURE_SVR_GC #endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP @@ -272,7 +272,7 @@ size_t WriteBarrierManager::GetCurrentWriteBarrierSize() PBYTE WriteBarrierManager::CalculatePatchLocation(LPVOID base, LPVOID label, int offset) { // the label should always come after the entrypoint for this funtion - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", (LPBYTE)label > (LPBYTE)base); + _ASSERTE_ALL_BUILDS((LPBYTE)label > (LPBYTE)base); return (GetWriteBarrierCodeLocation((void*)JIT_WriteBarrier) + ((LPBYTE)GetEEFuncEntryPoint(label) - (LPBYTE)GetEEFuncEntryPoint(base) + offset)); } @@ -306,12 +306,12 @@ int WriteBarrierManager::ChangeWriteBarrierTo(WriteBarrierType newWriteBarrier, m_pCardTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_PreGrow64, Patch_Label_CardTable, 2); // Make sure that we will be bashing the right places (immediates should be hardcoded to 0x0f0f0f0f0f0f0f0f0). - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pLowerBoundImmediate); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardTableImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pLowerBoundImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardTableImmediate); #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES m_pCardBundleTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_PreGrow64, Patch_Label_CardBundleTable, 2); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardBundleTableImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardBundleTableImmediate); #endif break; } @@ -323,13 +323,13 @@ int WriteBarrierManager::ChangeWriteBarrierTo(WriteBarrierType newWriteBarrier, m_pCardTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_PostGrow64, Patch_Label_CardTable, 2); // Make sure that we will be bashing the right places (immediates should be hardcoded to 0x0f0f0f0f0f0f0f0f0). - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pLowerBoundImmediate); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardTableImmediate); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pUpperBoundImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pLowerBoundImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardTableImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pUpperBoundImmediate); #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES m_pCardBundleTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_PostGrow64, Patch_Label_CardBundleTable, 2); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardBundleTableImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardBundleTableImmediate); #endif break; } @@ -340,11 +340,11 @@ int WriteBarrierManager::ChangeWriteBarrierTo(WriteBarrierType newWriteBarrier, m_pCardTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_SVR64, PatchLabel_CardTable, 2); // Make sure that we will be bashing the right places (immediates should be hardcoded to 0x0f0f0f0f0f0f0f0f0). - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardTableImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardTableImmediate); #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES m_pCardBundleTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_SVR64, PatchLabel_CardBundleTable, 2); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardBundleTableImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardBundleTableImmediate); #endif break; } @@ -358,13 +358,13 @@ int WriteBarrierManager::ChangeWriteBarrierTo(WriteBarrierType newWriteBarrier, m_pCardTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_WriteWatch_PreGrow64, Patch_Label_CardTable, 2); // Make sure that we will be bashing the right places (immediates should be hardcoded to 0x0f0f0f0f0f0f0f0f0). - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pWriteWatchTableImmediate); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pLowerBoundImmediate); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardTableImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pWriteWatchTableImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pLowerBoundImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardTableImmediate); #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES m_pCardBundleTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_WriteWatch_PreGrow64, Patch_Label_CardBundleTable, 2); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardBundleTableImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardBundleTableImmediate); #endif break; } @@ -377,14 +377,14 @@ int WriteBarrierManager::ChangeWriteBarrierTo(WriteBarrierType newWriteBarrier, m_pCardTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_WriteWatch_PostGrow64, Patch_Label_CardTable, 2); // Make sure that we will be bashing the right places (immediates should be hardcoded to 0x0f0f0f0f0f0f0f0f0). - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pWriteWatchTableImmediate); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pLowerBoundImmediate); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardTableImmediate); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pUpperBoundImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pWriteWatchTableImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pLowerBoundImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardTableImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pUpperBoundImmediate); #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES m_pCardBundleTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_WriteWatch_PostGrow64, Patch_Label_CardBundleTable, 2); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardBundleTableImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardBundleTableImmediate); #endif break; } @@ -396,12 +396,12 @@ int WriteBarrierManager::ChangeWriteBarrierTo(WriteBarrierType newWriteBarrier, m_pCardTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_WriteWatch_SVR64, PatchLabel_CardTable, 2); // Make sure that we will be bashing the right places (immediates should be hardcoded to 0x0f0f0f0f0f0f0f0f0). - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pWriteWatchTableImmediate); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardTableImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pWriteWatchTableImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardTableImmediate); #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES m_pCardBundleTableImmediate = CALC_PATCH_LOCATION(JIT_WriteBarrier_WriteWatch_SVR64, PatchLabel_CardBundleTable, 2); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", 0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardBundleTableImmediate); + _ASSERTE_ALL_BUILDS(0xf0f0f0f0f0f0f0f0 == *(UINT64*)m_pCardBundleTableImmediate); #endif break; } @@ -435,16 +435,16 @@ void WriteBarrierManager::Initialize() // write barrier implementations. size_t cbWriteBarrierBuffer = GetSpecificWriteBarrierSize(WRITE_BARRIER_BUFFER); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", cbWriteBarrierBuffer >= GetSpecificWriteBarrierSize(WRITE_BARRIER_PREGROW64)); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", cbWriteBarrierBuffer >= GetSpecificWriteBarrierSize(WRITE_BARRIER_POSTGROW64)); + _ASSERTE_ALL_BUILDS(cbWriteBarrierBuffer >= GetSpecificWriteBarrierSize(WRITE_BARRIER_PREGROW64)); + _ASSERTE_ALL_BUILDS(cbWriteBarrierBuffer >= GetSpecificWriteBarrierSize(WRITE_BARRIER_POSTGROW64)); #ifdef FEATURE_SVR_GC - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", cbWriteBarrierBuffer >= GetSpecificWriteBarrierSize(WRITE_BARRIER_SVR64)); + _ASSERTE_ALL_BUILDS(cbWriteBarrierBuffer >= GetSpecificWriteBarrierSize(WRITE_BARRIER_SVR64)); #endif // FEATURE_SVR_GC #ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", cbWriteBarrierBuffer >= GetSpecificWriteBarrierSize(WRITE_BARRIER_WRITE_WATCH_PREGROW64)); - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", cbWriteBarrierBuffer >= GetSpecificWriteBarrierSize(WRITE_BARRIER_WRITE_WATCH_POSTGROW64)); + _ASSERTE_ALL_BUILDS(cbWriteBarrierBuffer >= GetSpecificWriteBarrierSize(WRITE_BARRIER_WRITE_WATCH_PREGROW64)); + _ASSERTE_ALL_BUILDS(cbWriteBarrierBuffer >= GetSpecificWriteBarrierSize(WRITE_BARRIER_WRITE_WATCH_POSTGROW64)); #ifdef FEATURE_SVR_GC - _ASSERTE_ALL_BUILDS("clr/src/VM/AMD64/JITinterfaceAMD64.cpp", cbWriteBarrierBuffer >= GetSpecificWriteBarrierSize(WRITE_BARRIER_WRITE_WATCH_SVR64)); + _ASSERTE_ALL_BUILDS(cbWriteBarrierBuffer >= GetSpecificWriteBarrierSize(WRITE_BARRIER_WRITE_WATCH_SVR64)); #endif // FEATURE_SVR_GC #endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP diff --git a/src/coreclr/vm/amd64/unixstubs.cpp b/src/coreclr/vm/amd64/unixstubs.cpp index 517eea98f6b6a2..09d2568a9273b4 100644 --- a/src/coreclr/vm/amd64/unixstubs.cpp +++ b/src/coreclr/vm/amd64/unixstubs.cpp @@ -10,6 +10,7 @@ extern "C" PORTABILITY_ASSERT("Implement for PAL"); } +#if !__has_builtin(__cpuid) void __cpuid(int cpuInfo[4], int function_id) { // Based on the Clang implementation provided in cpuid.h: @@ -20,7 +21,9 @@ extern "C" : "0"(function_id) ); } +#endif +#if !__has_builtin(__cpuidex) void __cpuidex(int cpuInfo[4], int function_id, int subFunction_id) { // Based on the Clang implementation provided in cpuid.h: @@ -31,6 +34,7 @@ extern "C" : "0"(function_id), "2"(subFunction_id) ); } +#endif DWORD xmmYmmStateSupport() { diff --git a/src/coreclr/vm/codeman.cpp b/src/coreclr/vm/codeman.cpp index 296943addfd93e..6c2e15fe7a82fa 100644 --- a/src/coreclr/vm/codeman.cpp +++ b/src/coreclr/vm/codeman.cpp @@ -3476,36 +3476,6 @@ TypeHandle EEJitManager::ResolveEHClause(EE_ILEXCEPTION_CLAUSE* pEHClause, PREFIX_ASSUME(pModule != NULL); SigTypeContext typeContext(pMD); - VarKind k = hasNoVars; - - // In the vast majority of cases the code under the "if" below - // will not be executed. - // - // First grab the representative instantiations. For code - // shared by multiple generic instantiations these are the - // canonical (representative) instantiation. - if (TypeFromToken(typeTok) == mdtTypeSpec) - { - PCCOR_SIGNATURE pSig; - ULONG cSig; - IfFailThrow(pModule->GetMDImport()->GetTypeSpecFromToken(typeTok, &pSig, &cSig)); - - SigPointer psig(pSig, cSig); - k = psig.IsPolyType(&typeContext); - - // Grab the active class and method instantiation. This exact instantiation is only - // needed in the corner case of "generic" exception catching in shared - // generic code. We don't need the exact instantiation if the token - // doesn't contain E_T_VAR or E_T_MVAR. - if ((k & hasSharableVarsMask) != 0) - { - Instantiation classInst; - Instantiation methodInst; - pCf->GetExactGenericInstantiations(&classInst, &methodInst); - SigTypeContext::InitTypeContext(pMD,classInst, methodInst,&typeContext); - } - } - return ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pModule, typeTok, &typeContext, ClassLoader::ReturnNullIfNotFound); } @@ -6001,38 +5971,7 @@ TypeHandle ReadyToRunJitManager::ResolveEHClause(EE_ILEXCEPTION_CLAUSE* pEHClaus PREFIX_ASSUME(pModule != NULL); SigTypeContext typeContext(pMD); - VarKind k = hasNoVars; - mdToken typeTok = pEHClause->ClassToken; - - // In the vast majority of cases the code un der the "if" below - // will not be executed. - // - // First grab the representative instantiations. For code - // shared by multiple generic instantiations these are the - // canonical (representative) instantiation. - if (TypeFromToken(typeTok) == mdtTypeSpec) - { - PCCOR_SIGNATURE pSig; - ULONG cSig; - IfFailThrow(pModule->GetMDImport()->GetTypeSpecFromToken(typeTok, &pSig, &cSig)); - - SigPointer psig(pSig, cSig); - k = psig.IsPolyType(&typeContext); - - // Grab the active class and method instantiation. This exact instantiation is only - // needed in the corner case of "generic" exception catching in shared - // generic code. We don't need the exact instantiation if the token - // doesn't contain E_T_VAR or E_T_MVAR. - if ((k & hasSharableVarsMask) != 0) - { - Instantiation classInst; - Instantiation methodInst; - pCf->GetExactGenericInstantiations(&classInst,&methodInst); - SigTypeContext::InitTypeContext(pMD,classInst, methodInst,&typeContext); - } - } - return ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pModule, typeTok, &typeContext, ClassLoader::ReturnNullIfNotFound); } diff --git a/src/coreclr/vm/comthreadpool.cpp b/src/coreclr/vm/comthreadpool.cpp index 6c3f82f4fdc42b..88094ff5323555 100644 --- a/src/coreclr/vm/comthreadpool.cpp +++ b/src/coreclr/vm/comthreadpool.cpp @@ -205,7 +205,7 @@ FCIMPLEND FCIMPL1(FC_BOOL_RET, ThreadPoolNative::CorCanSetMinIOCompletionThreads, DWORD ioCompletionThreads) { FCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, ThreadpoolMgr::UsePortableThreadPool()); + _ASSERTE_ALL_BUILDS(ThreadpoolMgr::UsePortableThreadPool()); BOOL result = ThreadpoolMgr::CanSetMinIOCompletionThreads(ioCompletionThreads); FC_RETURN_BOOL(result); @@ -216,7 +216,7 @@ FCIMPLEND FCIMPL1(FC_BOOL_RET, ThreadPoolNative::CorCanSetMaxIOCompletionThreads, DWORD ioCompletionThreads) { FCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, ThreadpoolMgr::UsePortableThreadPool()); + _ASSERTE_ALL_BUILDS(ThreadpoolMgr::UsePortableThreadPool()); BOOL result = ThreadpoolMgr::CanSetMaxIOCompletionThreads(ioCompletionThreads); FC_RETURN_BOOL(result); @@ -227,7 +227,7 @@ FCIMPLEND FCIMPL2(FC_BOOL_RET, ThreadPoolNative::CorSetMaxThreads,DWORD workerThreads, DWORD completionPortThreads) { FCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, !ThreadpoolMgr::UsePortableThreadPoolForIO()); + _ASSERTE_ALL_BUILDS(!ThreadpoolMgr::UsePortableThreadPoolForIO()); BOOL bRet = FALSE; HELPER_METHOD_FRAME_BEGIN_RET_0(); @@ -242,7 +242,7 @@ FCIMPLEND FCIMPL2(VOID, ThreadPoolNative::CorGetMaxThreads,DWORD* workerThreads, DWORD* completionPortThreads) { FCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, !ThreadpoolMgr::UsePortableThreadPoolForIO()); + _ASSERTE_ALL_BUILDS(!ThreadpoolMgr::UsePortableThreadPoolForIO()); ThreadpoolMgr::GetMaxThreads(workerThreads,completionPortThreads); return; @@ -253,7 +253,7 @@ FCIMPLEND FCIMPL2(FC_BOOL_RET, ThreadPoolNative::CorSetMinThreads,DWORD workerThreads, DWORD completionPortThreads) { FCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, !ThreadpoolMgr::UsePortableThreadPoolForIO()); + _ASSERTE_ALL_BUILDS(!ThreadpoolMgr::UsePortableThreadPoolForIO()); BOOL bRet = FALSE; HELPER_METHOD_FRAME_BEGIN_RET_0(); @@ -268,7 +268,7 @@ FCIMPLEND FCIMPL2(VOID, ThreadPoolNative::CorGetMinThreads,DWORD* workerThreads, DWORD* completionPortThreads) { FCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, !ThreadpoolMgr::UsePortableThreadPoolForIO()); + _ASSERTE_ALL_BUILDS(!ThreadpoolMgr::UsePortableThreadPoolForIO()); ThreadpoolMgr::GetMinThreads(workerThreads,completionPortThreads); return; @@ -279,7 +279,7 @@ FCIMPLEND FCIMPL2(VOID, ThreadPoolNative::CorGetAvailableThreads,DWORD* workerThreads, DWORD* completionPortThreads) { FCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, !ThreadpoolMgr::UsePortableThreadPoolForIO()); + _ASSERTE_ALL_BUILDS(!ThreadpoolMgr::UsePortableThreadPoolForIO()); ThreadpoolMgr::GetAvailableThreads(workerThreads,completionPortThreads); return; @@ -290,7 +290,7 @@ FCIMPLEND FCIMPL0(INT32, ThreadPoolNative::GetThreadCount) { FCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, !ThreadpoolMgr::UsePortableThreadPoolForIO()); + _ASSERTE_ALL_BUILDS(!ThreadpoolMgr::UsePortableThreadPoolForIO()); return ThreadpoolMgr::GetThreadCount(); } @@ -300,7 +300,7 @@ FCIMPLEND extern "C" INT64 QCALLTYPE ThreadPool_GetCompletedWorkItemCount() { QCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, !ThreadpoolMgr::UsePortableThreadPoolForIO()); + _ASSERTE_ALL_BUILDS(!ThreadpoolMgr::UsePortableThreadPoolForIO()); INT64 result = 0; @@ -316,7 +316,7 @@ extern "C" INT64 QCALLTYPE ThreadPool_GetCompletedWorkItemCount() FCIMPL0(INT64, ThreadPoolNative::GetPendingUnmanagedWorkItemCount) { FCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, !ThreadpoolMgr::UsePortableThreadPool()); + _ASSERTE_ALL_BUILDS(!ThreadpoolMgr::UsePortableThreadPool()); return PerAppDomainTPCountList::GetUnmanagedTPCount()->GetNumRequests(); } @@ -327,7 +327,7 @@ FCIMPLEND FCIMPL0(VOID, ThreadPoolNative::NotifyRequestProgress) { FCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, !ThreadpoolMgr::UsePortableThreadPool()); + _ASSERTE_ALL_BUILDS(!ThreadpoolMgr::UsePortableThreadPool()); _ASSERTE(ThreadpoolMgr::IsInitialized()); // can't be here without requesting a thread first ThreadpoolMgr::NotifyWorkItemCompleted(); @@ -352,7 +352,7 @@ FCIMPLEND FCIMPL1(VOID, ThreadPoolNative::ReportThreadStatus, CLR_BOOL isWorking) { FCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, !ThreadpoolMgr::UsePortableThreadPool()); + _ASSERTE_ALL_BUILDS(!ThreadpoolMgr::UsePortableThreadPool()); ThreadpoolMgr::ReportThreadStatus(isWorking); } @@ -361,7 +361,7 @@ FCIMPLEND FCIMPL0(FC_BOOL_RET, ThreadPoolNative::NotifyRequestComplete) { FCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, !ThreadpoolMgr::UsePortableThreadPool()); + _ASSERTE_ALL_BUILDS(!ThreadpoolMgr::UsePortableThreadPool()); _ASSERTE(ThreadpoolMgr::IsInitialized()); // can't be here without requesting a thread first ThreadpoolMgr::NotifyWorkItemCompleted(); @@ -423,7 +423,7 @@ FCIMPLEND FCIMPL0(FC_BOOL_RET, ThreadPoolNative::GetEnableWorkerTracking) { FCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, !ThreadpoolMgr::UsePortableThreadPool()); + _ASSERTE_ALL_BUILDS(!ThreadpoolMgr::UsePortableThreadPool()); BOOL result = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ThreadPool_EnableWorkerTracking) ? TRUE : FALSE; FC_RETURN_BOOL(result); @@ -511,7 +511,7 @@ FCIMPL5(LPVOID, ThreadPoolNative::CorRegisterWaitForSingleObject, Object* registeredWaitObjectUNSAFE) { FCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, !ThreadpoolMgr::UsePortableThreadPool()); + _ASSERTE_ALL_BUILDS(!ThreadpoolMgr::UsePortableThreadPool()); HANDLE handle = 0; struct _gc @@ -586,7 +586,7 @@ extern "C" BOOL QCALLTYPE ThreadPool_RequestWorkerThread() BEGIN_QCALL; - _ASSERTE_ALL_BUILDS(__FILE__, !ThreadpoolMgr::UsePortableThreadPool()); + _ASSERTE_ALL_BUILDS(!ThreadpoolMgr::UsePortableThreadPool()); ThreadpoolMgr::EnsureInitialized(); ThreadpoolMgr::SetAppDomainRequestsActive(); @@ -615,7 +615,7 @@ extern "C" BOOL QCALLTYPE ThreadPool_PerformGateActivities(INT32 cpuUtilization) BEGIN_QCALL; - _ASSERTE_ALL_BUILDS(__FILE__, ThreadpoolMgr::UsePortableThreadPool() && !ThreadpoolMgr::UsePortableThreadPoolForIO()); + _ASSERTE_ALL_BUILDS(ThreadpoolMgr::UsePortableThreadPool() && !ThreadpoolMgr::UsePortableThreadPoolForIO()); ThreadpoolMgr::PerformGateActivities(cpuUtilization); needGateThread = ThreadpoolMgr::NeedGateThreadForIOCompletions(); @@ -630,7 +630,7 @@ extern "C" BOOL QCALLTYPE ThreadPool_PerformGateActivities(INT32 cpuUtilization) FCIMPL2(FC_BOOL_RET, ThreadPoolNative::CorUnregisterWait, LPVOID WaitHandle, Object* objectToNotify) { FCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, !ThreadpoolMgr::UsePortableThreadPool()); + _ASSERTE_ALL_BUILDS(!ThreadpoolMgr::UsePortableThreadPool()); BOOL retVal = false; SAFEHANDLEREF refSH = (SAFEHANDLEREF) ObjectToOBJECTREF(objectToNotify); @@ -686,7 +686,7 @@ FCIMPLEND FCIMPL1(void, ThreadPoolNative::CorWaitHandleCleanupNative, LPVOID WaitHandle) { FCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, !ThreadpoolMgr::UsePortableThreadPool()); + _ASSERTE_ALL_BUILDS(!ThreadpoolMgr::UsePortableThreadPool()); HELPER_METHOD_FRAME_BEGIN_0(); @@ -791,7 +791,7 @@ void WINAPI BindIoCompletionCallbackStub(DWORD ErrorCode, FCIMPL1(FC_BOOL_RET, ThreadPoolNative::CorBindIoCompletionCallback, HANDLE fileHandle) { FCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, !ThreadpoolMgr::UsePortableThreadPoolForIO()); + _ASSERTE_ALL_BUILDS(!ThreadpoolMgr::UsePortableThreadPoolForIO()); BOOL retVal = FALSE; @@ -823,7 +823,7 @@ FCIMPLEND FCIMPL1(FC_BOOL_RET, ThreadPoolNative::CorPostQueuedCompletionStatus, LPOVERLAPPED lpOverlapped) { FCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, !ThreadpoolMgr::UsePortableThreadPoolForIO()); + _ASSERTE_ALL_BUILDS(!ThreadpoolMgr::UsePortableThreadPoolForIO()); OVERLAPPEDDATAREF overlapped = ObjectToOVERLAPPEDDATAREF(OverlappedDataObject::GetOverlapped(lpOverlapped)); diff --git a/src/coreclr/vm/eetwain.cpp b/src/coreclr/vm/eetwain.cpp index 71a2efafbef1cc..6c66213d97ddbb 100644 --- a/src/coreclr/vm/eetwain.cpp +++ b/src/coreclr/vm/eetwain.cpp @@ -2763,7 +2763,7 @@ unsigned scanArgRegTableI(PTR_CBYTE table, if (argOfs >= MAX_PTRARG_OFS) { - _ASSERTE_ALL_BUILDS("clr/src/VM/eetwain.cpp", !"scanArgRegTableI: args pushed 'too deep'"); + _ASSERTE_ALL_BUILDS(!"scanArgRegTableI: args pushed 'too deep'"); } else { diff --git a/src/coreclr/vm/gchelpers.cpp b/src/coreclr/vm/gchelpers.cpp index 0b3d6ca29d5239..99954015166fbc 100644 --- a/src/coreclr/vm/gchelpers.cpp +++ b/src/coreclr/vm/gchelpers.cpp @@ -1112,7 +1112,7 @@ extern "C" HCIMPL2_RAW(VOID, JIT_CheckedWriteBarrier, Object **dst, Object *ref) break; default: // It should be some member of the enumeration. - _ASSERTE_ALL_BUILDS(__FILE__, false); + _ASSERTE_ALL_BUILDS(false); break; } #endif // FEATURE_COUNT_GC_WRITE_BARRIERS diff --git a/src/coreclr/vm/i386/excepx86.cpp b/src/coreclr/vm/i386/excepx86.cpp index c473d8ee38ea96..c5c909721f83bc 100644 --- a/src/coreclr/vm/i386/excepx86.cpp +++ b/src/coreclr/vm/i386/excepx86.cpp @@ -639,18 +639,6 @@ CPFH_RealFirstPassHandler( // ExceptionContinueSearch, etc. DWORD exceptionCode = pExceptionRecord->ExceptionCode; Thread *pThread = GetThread(); -#ifdef _DEBUG - static int breakOnSO = -1; - - if (breakOnSO == -1) - breakOnSO = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_BreakOnSO); - - if (breakOnSO != 0 && exceptionCode == STATUS_STACK_OVERFLOW) - { - DebugBreak(); // ASSERTing will overwrite the guard region - } -#endif - // We always want to be in co-operative mode when we run this function and whenever we return // from it, want to go to pre-emptive mode because are returning to OS. _ASSERTE(pThread->PreemptiveGCDisabled()); diff --git a/src/coreclr/vm/i386/jitinterfacex86.cpp b/src/coreclr/vm/i386/jitinterfacex86.cpp index 82782d86c2bf62..24e436f1ac11c9 100644 --- a/src/coreclr/vm/i386/jitinterfacex86.cpp +++ b/src/coreclr/vm/i386/jitinterfacex86.cpp @@ -1034,8 +1034,8 @@ void InitJITHelpers1() // All write barrier helpers should fit into one page. // If you hit this assert on retail build, there is most likely problem with BBT script. - _ASSERTE_ALL_BUILDS("clr/src/VM/i386/JITinterfaceX86.cpp", (BYTE*)JIT_WriteBarrierGroup_End - (BYTE*)JIT_WriteBarrierGroup < (ptrdiff_t)GetOsPageSize()); - _ASSERTE_ALL_BUILDS("clr/src/VM/i386/JITinterfaceX86.cpp", (BYTE*)JIT_PatchedWriteBarrierGroup_End - (BYTE*)JIT_PatchedWriteBarrierGroup < (ptrdiff_t)GetOsPageSize()); + _ASSERTE_ALL_BUILDS((BYTE*)JIT_WriteBarrierGroup_End - (BYTE*)JIT_WriteBarrierGroup < (ptrdiff_t)GetOsPageSize()); + _ASSERTE_ALL_BUILDS((BYTE*)JIT_PatchedWriteBarrierGroup_End - (BYTE*)JIT_PatchedWriteBarrierGroup < (ptrdiff_t)GetOsPageSize()); // Copy the write barriers to their final resting place. for (int iBarrier = 0; iBarrier < NUM_WRITE_BARRIERS; iBarrier++) @@ -1136,35 +1136,35 @@ void ValidateWriteBarrierHelpers() // ephemeral region DWORD* pLocation = reinterpret_cast(&pWriteBarrierFunc[AnyGrow_EphemeralLowerBound]); - _ASSERTE_ALL_BUILDS("clr/src/VM/i386/JITinterfaceX86.cpp", (reinterpret_cast(pLocation) & 0x3) == 0); - _ASSERTE_ALL_BUILDS("clr/src/VM/i386/JITinterfaceX86.cpp", *pLocation == 0xf0f0f0f0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pLocation) & 0x3) == 0); + _ASSERTE_ALL_BUILDS(*pLocation == 0xf0f0f0f0); // card table pLocation = reinterpret_cast(&pWriteBarrierFunc[PreGrow_CardTableFirstLocation]); - _ASSERTE_ALL_BUILDS("clr/src/VM/i386/JITinterfaceX86.cpp", (reinterpret_cast(pLocation) & 0x3) == 0); - _ASSERTE_ALL_BUILDS("clr/src/VM/i386/JITinterfaceX86.cpp", *pLocation == 0xf0f0f0f0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pLocation) & 0x3) == 0); + _ASSERTE_ALL_BUILDS(*pLocation == 0xf0f0f0f0); pLocation = reinterpret_cast(&pWriteBarrierFunc[PreGrow_CardTableSecondLocation]); - _ASSERTE_ALL_BUILDS("clr/src/VM/i386/JITinterfaceX86.cpp", (reinterpret_cast(pLocation) & 0x3) == 0); - _ASSERTE_ALL_BUILDS("clr/src/VM/i386/JITinterfaceX86.cpp", *pLocation == 0xf0f0f0f0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pLocation) & 0x3) == 0); + _ASSERTE_ALL_BUILDS(*pLocation == 0xf0f0f0f0); // now validate the PostGrow helper pWriteBarrierFunc = reinterpret_cast(JIT_WriteBarrierReg_PostGrow); // ephemeral region pLocation = reinterpret_cast(&pWriteBarrierFunc[AnyGrow_EphemeralLowerBound]); - _ASSERTE_ALL_BUILDS("clr/src/VM/i386/JITinterfaceX86.cpp", (reinterpret_cast(pLocation) & 0x3) == 0); - _ASSERTE_ALL_BUILDS("clr/src/VM/i386/JITinterfaceX86.cpp", *pLocation == 0xf0f0f0f0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pLocation) & 0x3) == 0); + _ASSERTE_ALL_BUILDS(*pLocation == 0xf0f0f0f0); pLocation = reinterpret_cast(&pWriteBarrierFunc[PostGrow_EphemeralUpperBound]); - _ASSERTE_ALL_BUILDS("clr/src/VM/i386/JITinterfaceX86.cpp", (reinterpret_cast(pLocation) & 0x3) == 0); - _ASSERTE_ALL_BUILDS("clr/src/VM/i386/JITinterfaceX86.cpp", *pLocation == 0xf0f0f0f0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pLocation) & 0x3) == 0); + _ASSERTE_ALL_BUILDS(*pLocation == 0xf0f0f0f0); // card table pLocation = reinterpret_cast(&pWriteBarrierFunc[PostGrow_CardTableFirstLocation]); - _ASSERTE_ALL_BUILDS("clr/src/VM/i386/JITinterfaceX86.cpp", (reinterpret_cast(pLocation) & 0x3) == 0); - _ASSERTE_ALL_BUILDS("clr/src/VM/i386/JITinterfaceX86.cpp", *pLocation == 0xf0f0f0f0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pLocation) & 0x3) == 0); + _ASSERTE_ALL_BUILDS(*pLocation == 0xf0f0f0f0); pLocation = reinterpret_cast(&pWriteBarrierFunc[PostGrow_CardTableSecondLocation]); - _ASSERTE_ALL_BUILDS("clr/src/VM/i386/JITinterfaceX86.cpp", (reinterpret_cast(pLocation) & 0x3) == 0); - _ASSERTE_ALL_BUILDS("clr/src/VM/i386/JITinterfaceX86.cpp", *pLocation == 0xf0f0f0f0); + _ASSERTE_ALL_BUILDS((reinterpret_cast(pLocation) & 0x3) == 0); + _ASSERTE_ALL_BUILDS(*pLocation == 0xf0f0f0f0); } #endif //CODECOVERAGE diff --git a/src/coreclr/vm/interpreter.cpp b/src/coreclr/vm/interpreter.cpp index 373184cd0f58fb..63a93c18b75f79 100644 --- a/src/coreclr/vm/interpreter.cpp +++ b/src/coreclr/vm/interpreter.cpp @@ -428,7 +428,7 @@ void InterpreterMethodInfo::InitArgInfo(CEEInfo* comp, CORINFO_METHOD_INFO* meth break; default: - _ASSERTE_ALL_BUILDS(__FILE__, false); // shouldn't get here + _ASSERTE_ALL_BUILDS(false); // shouldn't get here } } @@ -1095,7 +1095,7 @@ CorJitResult Interpreter::GenerateInterpreterStub(CEEInfo* comp, case CORINFO_TYPE_UNDEF: case CORINFO_TYPE_VOID: case CORINFO_TYPE_VAR: - _ASSERTE_ALL_BUILDS(__FILE__, false); // Should not happen; + _ASSERTE_ALL_BUILDS(false); // Should not happen; break; // One integer slot arguments: @@ -1363,7 +1363,7 @@ CorJitResult Interpreter::GenerateInterpreterStub(CEEInfo* comp, break; default: - _ASSERTE_ALL_BUILDS(__FILE__, false); // shouldn't get here + _ASSERTE_ALL_BUILDS(false); // shouldn't get here } delete[] argPerm; diff --git a/src/coreclr/vm/interpreter.h b/src/coreclr/vm/interpreter.h index 7e5b2f76f252a8..3eab503ae446b4 100644 --- a/src/coreclr/vm/interpreter.h +++ b/src/coreclr/vm/interpreter.h @@ -60,7 +60,7 @@ typedef SIZE_T NativePtr; #define NYI_INTERP(msg) _ASSERTE_MSG(false, msg) // I wanted to define NYI_INTERP as the following in retail: -// #define NYI_INTERP(msg) _ASSERTE_ALL_BUILDS(__FILE__, false) +// #define NYI_INTERP(msg) _ASSERTE_ALL_BUILDS(false) // but doing so gave a very odd unreachable code error. diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index 9a7be8a9e70863..8fdc43493bd41d 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -2832,7 +2832,6 @@ HCIMPL2_IV(LPVOID, JIT_GetRefAny, CORINFO_CLASS_HANDLE type, TypedByRef typedByR FCALL_CONTRACT; TypeHandle clsHnd(type); - // @TODO right now we check for precisely the correct type. // do we want to allow inheritance? (watch out since value // classes inherit from object but do not normal object layout). @@ -2845,6 +2844,16 @@ HCIMPL2_IV(LPVOID, JIT_GetRefAny, CORINFO_CLASS_HANDLE type, TypedByRef typedByR HCIMPLEND +/*************************************************************/ +HCIMPL2(BOOL, JIT_IsInstanceOfException, CORINFO_CLASS_HANDLE type, Object* obj) +{ + FCALL_CONTRACT; + TypeHandle clsHnd(type); + return ExceptionIsOfRightType(clsHnd, obj->GetTypeHandle()); +} +HCIMPLEND + + //======================================================================== // // GENERICS HELPERS @@ -4789,8 +4798,7 @@ HCIMPL1_RAW(Object*, JIT_CheckObj, Object* obj) if (obj != 0) { MethodTable* pMT = obj->GetMethodTable(); if (!pMT->ValidateWithPossibleAV()) { - _ASSERTE(!"Bad Method Table"); - FreeBuildDebugBreak(); + _ASSERTE_ALL_BUILDS(!"Bad Method Table"); } } return obj; diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 51aee7dcfbe108..87161faf38304c 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -7514,49 +7514,7 @@ getMethodInfoHelper( { methInfo->options = CorInfoOptions(methInfo->options|CORINFO_GENERICS_CTXT_KEEP_ALIVE); } - else #endif // defined(PROFILING_SUPPORTED) - { - // Check all the exception clauses - - if (ftn->IsDynamicMethod()) - { - // @TODO: how do we detect the need to mark this flag? - } - else - { - COR_ILMETHOD_SECT_EH_CLAUSE_FAT ehClause; - - for (unsigned i = 0; i < methInfo->EHcount; i++) - { - const COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehInfo = - (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)header->EH->EHClause(i, &ehClause); - - // Is it a typed catch clause? - if (ehInfo->GetFlags() != COR_ILEXCEPTION_CLAUSE_NONE) - continue; - - // Check if we catch "C" ? - - DWORD catchTypeToken = ehInfo->GetClassToken(); - if (TypeFromToken(catchTypeToken) != mdtTypeSpec) - continue; - - PCCOR_SIGNATURE pSig; - ULONG cSig; - IfFailThrow(ftn->GetMDImport()->GetTypeSpecFromToken(catchTypeToken, &pSig, &cSig)); - - SigPointer psig(pSig, cSig); - - SigTypeContext sigTypeContext(ftn); - if (psig.IsPolyType(&sigTypeContext) & hasSharableVarsMask) - { - methInfo->options = CorInfoOptions(methInfo->options|CORINFO_GENERICS_CTXT_KEEP_ALIVE); - break; - } - } - } - } } PCCOR_SIGNATURE pSig = NULL; diff --git a/src/coreclr/vm/nativeoverlapped.cpp b/src/coreclr/vm/nativeoverlapped.cpp index 6c8f56a12acb96..c3b55ae130d429 100644 --- a/src/coreclr/vm/nativeoverlapped.cpp +++ b/src/coreclr/vm/nativeoverlapped.cpp @@ -28,7 +28,7 @@ FCIMPL3(void, CheckVMForIOPacket, LPOVERLAPPED* lpOverlapped, DWORD* errorCode, DWORD* numBytes) { FCALL_CONTRACT; - _ASSERTE_ALL_BUILDS(__FILE__, !ThreadpoolMgr::UsePortableThreadPoolForIO()); + _ASSERTE_ALL_BUILDS(!ThreadpoolMgr::UsePortableThreadPoolForIO()); #ifndef TARGET_UNIX Thread *pThread = GetThread(); diff --git a/src/coreclr/vm/siginfo.cpp b/src/coreclr/vm/siginfo.cpp index 68b0ec711f8590..c35e9148fec355 100644 --- a/src/coreclr/vm/siginfo.cpp +++ b/src/coreclr/vm/siginfo.cpp @@ -1869,121 +1869,6 @@ TypeHandle SigPointer::GetTypeVariable(CorElementType et, #ifndef DACCESS_COMPILE -// Does this type contain class or method type parameters whose instantiation cannot -// be determined at JIT-compile time from the instantiations in the method context? -// Return a combination of hasClassVar and hasMethodVar flags. -// See header file for more info. -VarKind SigPointer::IsPolyType(const SigTypeContext *pTypeContext) const -{ - CONTRACTL - { - INSTANCE_CHECK; - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END - - SigPointer psig = *this; - CorElementType typ; - - if (FAILED(psig.GetElemType(&typ))) - return hasNoVars; - - switch(typ) { - case ELEMENT_TYPE_VAR: - case ELEMENT_TYPE_MVAR: - { - VarKind res = (typ == ELEMENT_TYPE_VAR ? hasClassVar : hasMethodVar); - if (pTypeContext != NULL) - { - TypeHandle ty = psig.GetTypeVariable(typ, pTypeContext); - if (ty.IsCanonicalSubtype()) - res = (VarKind) (res | (typ == ELEMENT_TYPE_VAR ? hasSharableClassVar : hasSharableMethodVar)); - } - return (res); - } - - case ELEMENT_TYPE_U: - case ELEMENT_TYPE_I: - case ELEMENT_TYPE_STRING: - case ELEMENT_TYPE_OBJECT: - case ELEMENT_TYPE_I1: - case ELEMENT_TYPE_U1: - case ELEMENT_TYPE_BOOLEAN: - case ELEMENT_TYPE_I2: - case ELEMENT_TYPE_U2: - case ELEMENT_TYPE_CHAR: - case ELEMENT_TYPE_I4: - case ELEMENT_TYPE_U4: - case ELEMENT_TYPE_I8: - case ELEMENT_TYPE_U8: - case ELEMENT_TYPE_R4: - case ELEMENT_TYPE_R8: - case ELEMENT_TYPE_VOID: - case ELEMENT_TYPE_CLASS: - case ELEMENT_TYPE_VALUETYPE: - case ELEMENT_TYPE_TYPEDBYREF: - return(hasNoVars); - - case ELEMENT_TYPE_GENERICINST: - { - VarKind k = psig.IsPolyType(pTypeContext); - if (FAILED(psig.SkipExactlyOne())) - return hasNoVars; - - uint32_t ntypars; - if(FAILED(psig.GetData(&ntypars))) - return hasNoVars; - - for (uint32_t i = 0; i < ntypars; i++) - { - k = (VarKind) (psig.IsPolyType(pTypeContext) | k); - if (FAILED(psig.SkipExactlyOne())) - return hasNoVars; - } - return(k); - } - - case ELEMENT_TYPE_ARRAY: - case ELEMENT_TYPE_SZARRAY: - case ELEMENT_TYPE_PINNED: - case ELEMENT_TYPE_BYREF: - case ELEMENT_TYPE_PTR: - { - return(psig.IsPolyType(pTypeContext)); - } - - case ELEMENT_TYPE_FNPTR: - { - if (FAILED(psig.GetData(NULL))) - return hasNoVars; - - // Get arg count; - uint32_t cArgs; - if (FAILED(psig.GetData(&cArgs))) - return hasNoVars; - - VarKind k = psig.IsPolyType(pTypeContext); - if (FAILED(psig.SkipExactlyOne())) - return hasNoVars; - - for (unsigned i = 0; i < cArgs; i++) - { - k = (VarKind) (psig.IsPolyType(pTypeContext) | k); - if (FAILED(psig.SkipExactlyOne())) - return hasNoVars; - } - - return(k); - } - - default: - BAD_FORMAT_NOTHROW_ASSERT(!"Bad type"); - } - return(hasNoVars); -} - BOOL SigPointer::IsStringType(Module* pModule, const SigTypeContext *pTypeContext) const { WRAPPER_NO_CONTRACT; diff --git a/src/coreclr/vm/siginfo.hpp b/src/coreclr/vm/siginfo.hpp index 29f811e627a74b..585fdb2071ef19 100644 --- a/src/coreclr/vm/siginfo.hpp +++ b/src/coreclr/vm/siginfo.hpp @@ -52,19 +52,6 @@ class ArgDestination; typedef const struct HardCodedMetaSig *LPHARDCODEDMETASIG; -//@GENERICS: flags returned from IsPolyType indicating the presence or absence of class and -// method type parameters in a type whose instantiation cannot be determined at JIT-compile time -enum VarKind -{ - hasNoVars = 0x0000, - hasClassVar = 0x0001, - hasMethodVar = 0x0002, - hasSharableClassVar = 0x0004, - hasSharableMethodVar = 0x0008, - hasAnyVarsMask = 0x0003, - hasSharableVarsMask = 0x000c -}; - //--------------------------------------------------------------------------------------- struct ScanContext; @@ -256,21 +243,6 @@ class SigPointer : public SigParser MethodTable *pMTInterfaceMapOwner = NULL) const; public: - //------------------------------------------------------------------------ - // Does this type contain class or method type parameters whose instantiation cannot - // be determined at JIT-compile time from the instantiations in the method context? - // Return a combination of hasClassVar and hasMethodVar flags. - // - // Example: class C containing instance method m - // Suppose that the method context is C::m - // Then the type Dict is considered to have *no* "polymorphic" type parameters because - // !0 is known to be float and !!0 is known to be double - // But Dict has polymorphic class *and* method type parameters because both - // !1=string and !!1=object are reference types and so code using these can be shared with - // other reference instantiations. - //------------------------------------------------------------------------ - VarKind IsPolyType(const SigTypeContext *pTypeContext) const; - //------------------------------------------------------------------------ // Tests if the element type is a System.String. Accepts // either ELEMENT_TYPE_STRING or ELEMENT_TYPE_CLASS encoding. diff --git a/src/coreclr/vm/threads.cpp b/src/coreclr/vm/threads.cpp index ac248b11a739b3..d9e7cd33140050 100644 --- a/src/coreclr/vm/threads.cpp +++ b/src/coreclr/vm/threads.cpp @@ -1153,8 +1153,8 @@ void InitThreadManager() // All patched helpers should fit into one page. // If you hit this assert on retail build, there is most likely problem with BBT script. - _ASSERTE_ALL_BUILDS("clr/src/VM/threads.cpp", (BYTE*)JIT_PatchedCodeLast - (BYTE*)JIT_PatchedCodeStart > (ptrdiff_t)0); - _ASSERTE_ALL_BUILDS("clr/src/VM/threads.cpp", (BYTE*)JIT_PatchedCodeLast - (BYTE*)JIT_PatchedCodeStart < (ptrdiff_t)GetOsPageSize()); + _ASSERTE_ALL_BUILDS((BYTE*)JIT_PatchedCodeLast - (BYTE*)JIT_PatchedCodeStart > (ptrdiff_t)0); + _ASSERTE_ALL_BUILDS((BYTE*)JIT_PatchedCodeLast - (BYTE*)JIT_PatchedCodeStart < (ptrdiff_t)GetOsPageSize()); if (IsWriteBarrierCopyEnabled()) { @@ -8305,7 +8305,7 @@ void Thread::StaticInitialize() InitializeSpecialUserModeApc(); // When CET shadow stacks are enabled, support for special user-mode APCs with the necessary functionality is required - _ASSERTE_ALL_BUILDS(__FILE__, !AreCetShadowStacksEnabled() || UseSpecialUserModeApc()); + _ASSERTE_ALL_BUILDS(!AreCetShadowStacksEnabled() || UseSpecialUserModeApc()); #endif } diff --git a/src/coreclr/vm/win32threadpool.cpp b/src/coreclr/vm/win32threadpool.cpp index 398053336bbfa5..80e5e5db5d7855 100644 --- a/src/coreclr/vm/win32threadpool.cpp +++ b/src/coreclr/vm/win32threadpool.cpp @@ -898,7 +898,7 @@ BOOL ThreadpoolMgr::QueueUserWorkItem(LPTHREAD_START_ROUTINE Function, } CONTRACTL_END; - _ASSERTE_ALL_BUILDS(__FILE__, !UsePortableThreadPool()); + _ASSERTE_ALL_BUILDS(!UsePortableThreadPool()); EnsureInitialized(); @@ -1738,7 +1738,7 @@ DWORD WINAPI ThreadpoolMgr::WorkerThreadStart(LPVOID lpArgs) } CONTRACTL_END; - _ASSERTE_ALL_BUILDS(__FILE__, !UsePortableThreadPool()); + _ASSERTE_ALL_BUILDS(!UsePortableThreadPool()); Thread *pThread = NULL; DWORD dwSwitchCount = 0; @@ -2413,7 +2413,7 @@ DWORD WINAPI ThreadpoolMgr::WaitThreadStart(LPVOID lpArgs) ClrFlsSetThreadType (ThreadType_Wait); - _ASSERTE_ALL_BUILDS(__FILE__, !UsePortableThreadPool()); + _ASSERTE_ALL_BUILDS(!UsePortableThreadPool()); ThreadCB* threadCB = (ThreadCB*) lpArgs; Thread* pThread = SetupThreadNoThrow(); @@ -3070,7 +3070,7 @@ DWORD WINAPI ThreadpoolMgr::CompletionPortThreadStart(LPVOID lpArgs) } CONTRACTL_END; - _ASSERTE_ALL_BUILDS(__FILE__, !UsePortableThreadPoolForIO()); + _ASSERTE_ALL_BUILDS(!UsePortableThreadPoolForIO()); DWORD numBytes=0; size_t key=0; diff --git a/src/libraries/Common/src/Interop/Interop.Ldap.cs b/src/libraries/Common/src/Interop/Interop.Ldap.cs index 7aac37cc97deb2..478f5121c49962 100644 --- a/src/libraries/Common/src/Interop/Interop.Ldap.cs +++ b/src/libraries/Common/src/Interop/Interop.Ldap.cs @@ -263,6 +263,8 @@ public LdapReferralCallback ToManaged() } public void OnInvoked() => GC.KeepAlive(_managed); + + public void Free() {} } } #else diff --git a/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.PackageType.cs b/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.PackageType.cs new file mode 100644 index 00000000000000..d8d6073c3d04a7 --- /dev/null +++ b/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.PackageType.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +internal static partial class Interop +{ + internal static partial class NetSecurityNative + { + internal enum PackageType : uint + { + Negotiate = 0, + NTLM = 1, + Kerberos = 2, + } + } +} diff --git a/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs b/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs index 3ce98eb5d30769..84a31968d79378 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs @@ -61,7 +61,7 @@ internal static partial Status InitiateCredSpNego( [LibraryImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_InitiateCredWithPassword", StringMarshalling = StringMarshalling.Utf8)] internal static partial Status InitiateCredWithPassword( out Status minorStatus, - [MarshalAs(UnmanagedType.Bool)] bool isNtlm, + PackageType packageType, SafeGssNameHandle desiredName, string password, int passwordLen, @@ -77,7 +77,7 @@ private static partial Status InitSecContext( out Status minorStatus, SafeGssCredHandle initiatorCredHandle, ref SafeGssContextHandle contextHandle, - [MarshalAs(UnmanagedType.Bool)] bool isNtlmOnly, + PackageType packageType, SafeGssNameHandle? targetName, uint reqFlags, ref byte inputBytes, @@ -91,7 +91,7 @@ private static partial Status InitSecContext( out Status minorStatus, SafeGssCredHandle initiatorCredHandle, ref SafeGssContextHandle contextHandle, - [MarshalAs(UnmanagedType.Bool)] bool isNtlmOnly, + PackageType packageType, IntPtr cbt, int cbtSize, SafeGssNameHandle? targetName, @@ -106,7 +106,7 @@ internal static Status InitSecContext( out Status minorStatus, SafeGssCredHandle initiatorCredHandle, ref SafeGssContextHandle contextHandle, - bool isNtlmOnly, + PackageType packageType, SafeGssNameHandle? targetName, uint reqFlags, ReadOnlySpan inputBytes, @@ -118,7 +118,7 @@ internal static Status InitSecContext( out minorStatus, initiatorCredHandle, ref contextHandle, - isNtlmOnly, + packageType, targetName, reqFlags, ref MemoryMarshal.GetReference(inputBytes), @@ -132,7 +132,7 @@ internal static Status InitSecContext( out Status minorStatus, SafeGssCredHandle initiatorCredHandle, ref SafeGssContextHandle contextHandle, - bool isNtlmOnly, + PackageType packageType, IntPtr cbt, int cbtSize, SafeGssNameHandle? targetName, @@ -146,7 +146,7 @@ internal static Status InitSecContext( out minorStatus, initiatorCredHandle, ref contextHandle, - isNtlmOnly, + packageType, cbt, cbtSize, targetName, diff --git a/src/libraries/Common/src/Microsoft/Win32/SafeHandles/GssSafeHandles.cs b/src/libraries/Common/src/Microsoft/Win32/SafeHandles/GssSafeHandles.cs index 253e0548dea9d9..acc95913c863c5 100644 --- a/src/libraries/Common/src/Microsoft/Win32/SafeHandles/GssSafeHandles.cs +++ b/src/libraries/Common/src/Microsoft/Win32/SafeHandles/GssSafeHandles.cs @@ -91,9 +91,9 @@ public static SafeGssCredHandle CreateAcceptor() /// returns the handle for the given credentials. /// The method returns an invalid handle if the username is null or empty. /// - public static SafeGssCredHandle Create(string username, string password, bool isNtlmOnly) + public static SafeGssCredHandle Create(string username, string password, Interop.NetSecurityNative.PackageType packageType) { - if (isNtlmOnly && !s_IsNtlmInstalled.Value) + if (packageType == Interop.NetSecurityNative.PackageType.NTLM && !s_IsNtlmInstalled.Value) { throw new Interop.NetSecurityNative.GssApiException( Interop.NetSecurityNative.Status.GSS_S_BAD_MECH, @@ -117,7 +117,7 @@ public static SafeGssCredHandle Create(string username, string password, bool is } else { - status = Interop.NetSecurityNative.InitiateCredWithPassword(out minorStatus, isNtlmOnly, userHandle, password, Encoding.UTF8.GetByteCount(password), out retHandle); + status = Interop.NetSecurityNative.InitiateCredWithPassword(out minorStatus, packageType, userHandle, password, Encoding.UTF8.GetByteCount(password), out retHandle); } if (status != Interop.NetSecurityNative.Status.GSS_S_COMPLETE) diff --git a/src/libraries/Common/src/System/Net/Security/NegotiateStreamPal.Unix.cs b/src/libraries/Common/src/System/Net/Security/NegotiateStreamPal.Unix.cs index 73043391901aef..702167758da69c 100644 --- a/src/libraries/Common/src/System/Net/Security/NegotiateStreamPal.Unix.cs +++ b/src/libraries/Common/src/System/Net/Security/NegotiateStreamPal.Unix.cs @@ -134,7 +134,7 @@ private static SecurityStatusPal EstablishSecurityContext( out byte[]? resultBuffer, ref ContextFlagsPal outFlags) { - bool isNtlmOnly = credential.IsNtlmOnly; + Interop.NetSecurityNative.PackageType packageType = credential.PackageType; resultBuffer = null; @@ -142,7 +142,11 @@ private static SecurityStatusPal EstablishSecurityContext( { if (NetEventSource.Log.IsEnabled()) { - string protocol = isNtlmOnly ? "NTLM" : "SPNEGO"; + string protocol = packageType switch { + Interop.NetSecurityNative.PackageType.NTLM => "NTLM", + Interop.NetSecurityNative.PackageType.Kerberos => "Kerberos", + _ => "SPNEGO" + }; NetEventSource.Info(context, $"requested protocol = {protocol}, target = {targetName}"); } @@ -172,7 +176,7 @@ private static SecurityStatusPal EstablishSecurityContext( status = Interop.NetSecurityNative.InitSecContext(out minorStatus, credential.GssCredential, ref contextHandle, - isNtlmOnly, + packageType, cbtAppData, cbtAppDataSize, negoContext.TargetName, @@ -187,7 +191,7 @@ private static SecurityStatusPal EstablishSecurityContext( status = Interop.NetSecurityNative.InitSecContext(out minorStatus, credential.GssCredential, ref contextHandle, - isNtlmOnly, + packageType, negoContext.TargetName, (uint)inputFlags, incomingBlob, @@ -216,7 +220,11 @@ private static SecurityStatusPal EstablishSecurityContext( { if (NetEventSource.Log.IsEnabled()) { - string protocol = isNtlmOnly ? "NTLM" : isNtlmUsed ? "SPNEGO-NTLM" : "SPNEGO-Kerberos"; + string protocol = packageType switch { + Interop.NetSecurityNative.PackageType.NTLM => "NTLM", + Interop.NetSecurityNative.PackageType.Kerberos => "Kerberos", + _ => isNtlmUsed ? "SPNEGO-NTLM" : "SPNEGO-Kerberos" + }; NetEventSource.Info(context, $"actual protocol = {protocol}"); } @@ -441,24 +449,36 @@ internal static SafeFreeCredentials AcquireCredentialsHandle(string package, boo { bool isEmptyCredential = string.IsNullOrWhiteSpace(credential.UserName) || string.IsNullOrWhiteSpace(credential.Password); - bool ntlmOnly = string.Equals(package, NegotiationInfoClass.NTLM, StringComparison.OrdinalIgnoreCase); - if (ntlmOnly && isEmptyCredential && !isServer) + Interop.NetSecurityNative.PackageType packageType; + + if (string.Equals(package, NegotiationInfoClass.Negotiate, StringComparison.OrdinalIgnoreCase)) { - // NTLM authentication is not possible with default credentials which are no-op - throw new PlatformNotSupportedException(SR.net_ntlm_not_possible_default_cred); + packageType = Interop.NetSecurityNative.PackageType.Negotiate; } - - if (!ntlmOnly && !string.Equals(package, NegotiationInfoClass.Negotiate)) + else if (string.Equals(package, NegotiationInfoClass.NTLM, StringComparison.OrdinalIgnoreCase)) + { + packageType = Interop.NetSecurityNative.PackageType.NTLM; + if (isEmptyCredential && !isServer) + { + // NTLM authentication is not possible with default credentials which are no-op + throw new PlatformNotSupportedException(SR.net_ntlm_not_possible_default_cred); + } + } + else if (string.Equals(package, NegotiationInfoClass.Kerberos, StringComparison.OrdinalIgnoreCase)) + { + packageType = Interop.NetSecurityNative.PackageType.Kerberos; + } + else { - // Native shim currently supports only NTLM and Negotiate + // Native shim currently supports only NTLM, Negotiate and Kerberos throw new PlatformNotSupportedException(SR.net_securitypackagesupport); } try { return isEmptyCredential ? - new SafeFreeNegoCredentials(ntlmOnly, string.Empty, string.Empty, string.Empty) : - new SafeFreeNegoCredentials(ntlmOnly, credential.UserName, credential.Password, credential.Domain); + new SafeFreeNegoCredentials(packageType, string.Empty, string.Empty, string.Empty) : + new SafeFreeNegoCredentials(packageType, credential.UserName, credential.Password, credential.Domain); } catch (Exception ex) { diff --git a/src/libraries/Common/src/System/Net/Security/Unix/SafeFreeNegoCredentials.cs b/src/libraries/Common/src/System/Net/Security/Unix/SafeFreeNegoCredentials.cs index 58d1942829e524..ffbd46db32aaf4 100644 --- a/src/libraries/Common/src/System/Net/Security/Unix/SafeFreeNegoCredentials.cs +++ b/src/libraries/Common/src/System/Net/Security/Unix/SafeFreeNegoCredentials.cs @@ -12,7 +12,7 @@ namespace System.Net.Security internal sealed class SafeFreeNegoCredentials : SafeFreeCredentials { private SafeGssCredHandle _credential; - private readonly bool _isNtlmOnly; + private readonly Interop.NetSecurityNative.PackageType _packageType; private readonly string _userName; private readonly bool _isDefault; @@ -21,10 +21,10 @@ public SafeGssCredHandle GssCredential get { return _credential; } } - // Property represents if Ntlm Protocol is specfied or not. - public bool IsNtlmOnly + // Property represents which protocol is specfied (Negotiate, Ntlm or Kerberos). + public Interop.NetSecurityNative.PackageType PackageType { - get { return _isNtlmOnly; } + get { return _packageType; } } public string UserName @@ -37,7 +37,7 @@ public bool IsDefault get { return _isDefault; } } - public SafeFreeNegoCredentials(bool isNtlmOnly, string username, string password, string domain) + public SafeFreeNegoCredentials(Interop.NetSecurityNative.PackageType packageType, string username, string password, string domain) : base(IntPtr.Zero, true) { Debug.Assert(username != null && password != null, "Username and Password can not be null"); @@ -66,10 +66,10 @@ public SafeFreeNegoCredentials(bool isNtlmOnly, string username, string password } bool ignore = false; - _isNtlmOnly = isNtlmOnly; + _packageType = packageType; _userName = username; _isDefault = string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password); - _credential = SafeGssCredHandle.Create(username, password, isNtlmOnly); + _credential = SafeGssCredHandle.Create(username, password, packageType); _credential.DangerousAddRef(ref ignore); } diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFileProviderTests.netcoreapp.cs b/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFileProviderTests.netcoreapp.cs index 633e722702687c..34fab6206c2c18 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFileProviderTests.netcoreapp.cs +++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFileProviderTests.netcoreapp.cs @@ -107,7 +107,11 @@ public async Task UsePollingFileWatcher_UseActivePolling_HasChanged_SymbolicLink // Act - Change link target to file 2. File.Delete(linkPath); - File.CreateSymbolicLink(linkPath, file2Path); + + RetryHelper.Execute(() => + { + File.CreateSymbolicLink(linkPath, file2Path); // can fail, presumably due to some latency of delete of linkPath + }, maxAttempts: 10, retryWhen: e => e is UnauthorizedAccessException); // Assert - It should report the change regardless of the timestamp being older. Assert.True(await tcs.Task, diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.cs index b6f3fef8b1f5d4..ca4040f1b9912b 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.cs @@ -141,6 +141,8 @@ public void OnInvoked() { GC.KeepAlive(_managed); } + + public void Free() {} } } #endif diff --git a/src/libraries/System.Drawing.Primitives/tests/ColorTests.cs b/src/libraries/System.Drawing.Primitives/tests/ColorTests.cs index 956dcb7c85d5e6..c1267aac24008b 100644 --- a/src/libraries/System.Drawing.Primitives/tests/ColorTests.cs +++ b/src/libraries/System.Drawing.Primitives/tests/ColorTests.cs @@ -492,7 +492,7 @@ public void Equality(Color left, Color right, bool expected) Assert.Equal(!expected, right != left); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))] public void DebuggerAttributesAreValid() { DebuggerAttributes.ValidateDebuggerDisplayReferences(Color.Aquamarine); diff --git a/src/libraries/System.Drawing.Primitives/tests/DataContractSerializerTests.cs b/src/libraries/System.Drawing.Primitives/tests/DataContractSerializerTests.cs index 037e05a3f33e1f..b1c96b18f73706 100644 --- a/src/libraries/System.Drawing.Primitives/tests/DataContractSerializerTests.cs +++ b/src/libraries/System.Drawing.Primitives/tests/DataContractSerializerTests.cs @@ -12,6 +12,7 @@ namespace System.Drawing.Primitives.Tests { + [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBuiltWithAggressiveTrimming))] public class DataContractSerializerTests { [Fact] diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash32.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash32.cs index c4c7af69446804..04f7227a5d9f74 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash32.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash32.cs @@ -73,7 +73,7 @@ public override void Append(ReadOnlySpan source) { int remain = StripeSize - held; - if (source.Length > remain) + if (source.Length >= remain) { source.Slice(0, remain).CopyTo(_holdback.AsSpan(held)); _state.ProcessStripe(_holdback); diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash64.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash64.cs index 45105525be5744..ab20bdda634e04 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash64.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash64.cs @@ -63,8 +63,8 @@ public override void Reset() /// The data to process. public override void Append(ReadOnlySpan source) { - // Every time we've read 16 bytes, process the stripe. - // Data that isn't perfectly mod-16 gets stored in a holdback + // Every time we've read 32 bytes, process the stripe. + // Data that isn't perfectly mod-32 gets stored in a holdback // buffer. int held = _length & 0x1F; @@ -73,7 +73,7 @@ public override void Append(ReadOnlySpan source) { int remain = StripeSize - held; - if (source.Length > remain) + if (source.Length >= remain) { source.Slice(0, remain).CopyTo(_holdback.AsSpan(held)); _state.ProcessStripe(_holdback); diff --git a/src/libraries/System.IO.Hashing/tests/XxHash32Tests.007.cs b/src/libraries/System.IO.Hashing/tests/XxHash32Tests.007.cs index db17893ccca230..9d390438fd566f 100644 --- a/src/libraries/System.IO.Hashing/tests/XxHash32Tests.007.cs +++ b/src/libraries/System.IO.Hashing/tests/XxHash32Tests.007.cs @@ -38,6 +38,8 @@ public static IEnumerable TestCases private const string DotNetNCHashing3 = DotNetNCHashing + DotNetNCHashing + DotNetNCHashing; private const string SixteenBytes = ".NET Hashes This"; private const string SixteenBytes3 = SixteenBytes + SixteenBytes + SixteenBytes; + private const string EightBytes = "Hashing!"; + private const string EightBytes3 = EightBytes + EightBytes + EightBytes; protected static IEnumerable TestCaseDefinitions { get; } = new[] @@ -83,7 +85,11 @@ public static IEnumerable TestCases new TestCase( $"{SixteenBytes} (x3)", Encoding.ASCII.GetBytes(SixteenBytes3), - "AD98EBD3") + "AD98EBD3"), + new TestCase( + $"{EightBytes} (x3)", + Encoding.ASCII.GetBytes(EightBytes3), + "FC23CD03"), }; protected override NonCryptographicHashAlgorithm CreateInstance() => new XxHash32(Seed); diff --git a/src/libraries/System.IO.Hashing/tests/XxHash32Tests.cs b/src/libraries/System.IO.Hashing/tests/XxHash32Tests.cs index 9c6bad45f8d478..9cbd5653059bf8 100644 --- a/src/libraries/System.IO.Hashing/tests/XxHash32Tests.cs +++ b/src/libraries/System.IO.Hashing/tests/XxHash32Tests.cs @@ -36,6 +36,8 @@ public static IEnumerable TestCases private const string DotNetNCHashing3 = DotNetNCHashing + DotNetNCHashing + DotNetNCHashing; private const string SixteenBytes = ".NET Hashes This"; private const string SixteenBytes3 = SixteenBytes + SixteenBytes + SixteenBytes; + private const string EightBytes = "Hashing!"; + private const string EightBytes3 = EightBytes + EightBytes + EightBytes; protected static IEnumerable TestCaseDefinitions { get; } = new[] @@ -96,7 +98,12 @@ public static IEnumerable TestCases new TestCase( $"{SixteenBytes} (x3)", Encoding.ASCII.GetBytes(SixteenBytes3), - "29DA7472") + "29DA7472"), + // 8 * 3 bytes, filling the holdback buffer exactly on the second Append call. + new TestCase( + $"{EightBytes} (x3)", + Encoding.ASCII.GetBytes(EightBytes3), + "5DF7D6C0"), }; protected override NonCryptographicHashAlgorithm CreateInstance() => new XxHash32(); diff --git a/src/libraries/System.IO.Hashing/tests/XxHash32Tests.f00d.cs b/src/libraries/System.IO.Hashing/tests/XxHash32Tests.f00d.cs index edf94fb5cc4166..8a01bc8cd16935 100644 --- a/src/libraries/System.IO.Hashing/tests/XxHash32Tests.f00d.cs +++ b/src/libraries/System.IO.Hashing/tests/XxHash32Tests.f00d.cs @@ -38,6 +38,8 @@ public static IEnumerable TestCases private const string DotNetNCHashing3 = DotNetNCHashing + DotNetNCHashing + DotNetNCHashing; private const string SixteenBytes = ".NET Hashes This"; private const string SixteenBytes3 = SixteenBytes + SixteenBytes + SixteenBytes; + private const string EightBytes = "Hashing!"; + private const string EightBytes3 = EightBytes + EightBytes + EightBytes; protected static IEnumerable TestCaseDefinitions { get; } = new[] @@ -83,7 +85,11 @@ public static IEnumerable TestCases new TestCase( $"{SixteenBytes} (x3)", Encoding.ASCII.GetBytes(SixteenBytes3), - "B38A9A45") + "B38A9A45"), + new TestCase( + $"{EightBytes} (x3)", + Encoding.ASCII.GetBytes(EightBytes3), + "C7A3D1CB"), }; protected override NonCryptographicHashAlgorithm CreateInstance() => new XxHash32(Seed); diff --git a/src/libraries/System.IO.Hashing/tests/XxHash64Tests.007.cs b/src/libraries/System.IO.Hashing/tests/XxHash64Tests.007.cs index 6c902b8352da67..fb3c514343a159 100644 --- a/src/libraries/System.IO.Hashing/tests/XxHash64Tests.007.cs +++ b/src/libraries/System.IO.Hashing/tests/XxHash64Tests.007.cs @@ -40,6 +40,8 @@ public static IEnumerable TestCases private const string SixtyThreeBytes3 = SixtyThreeBytes + SixtyThreeBytes + SixtyThreeBytes; private const string ThirtyTwoBytes = "This string has 32 ASCII bytes.."; private const string ThirtyTwoBytes3 = ThirtyTwoBytes + ThirtyTwoBytes + ThirtyTwoBytes; + private const string SixteenBytes = "0123456789ABCDEF"; + private const string SixteenBytes3 = SixteenBytes + SixteenBytes + SixteenBytes; protected static IEnumerable TestCaseDefinitions { get; } = new[] @@ -93,7 +95,11 @@ public static IEnumerable TestCases new TestCase( $"{ThirtyTwoBytes} (x3)", Encoding.ASCII.GetBytes(ThirtyTwoBytes3), - "45116421CF932B1F") + "45116421CF932B1F"), + new TestCase( + $"{SixteenBytes} (x3)", + Encoding.ASCII.GetBytes(SixteenBytes3), + "E4697CD5013DC0AF"), }; protected override NonCryptographicHashAlgorithm CreateInstance() => new XxHash64(Seed); diff --git a/src/libraries/System.IO.Hashing/tests/XxHash64Tests.cs b/src/libraries/System.IO.Hashing/tests/XxHash64Tests.cs index 10485ba584ed82..197446d912cea8 100644 --- a/src/libraries/System.IO.Hashing/tests/XxHash64Tests.cs +++ b/src/libraries/System.IO.Hashing/tests/XxHash64Tests.cs @@ -38,6 +38,8 @@ public static IEnumerable TestCases private const string SixtyThreeBytes3 = SixtyThreeBytes + SixtyThreeBytes + SixtyThreeBytes; private const string ThirtyTwoBytes = "This string has 32 ASCII bytes.."; private const string ThirtyTwoBytes3 = ThirtyTwoBytes + ThirtyTwoBytes + ThirtyTwoBytes; + private const string SixteenBytes = "0123456789ABCDEF"; + private const string SixteenBytes3 = SixteenBytes + SixteenBytes + SixteenBytes; protected static IEnumerable TestCaseDefinitions { get; } = new[] @@ -109,7 +111,12 @@ public static IEnumerable TestCases new TestCase( $"{ThirtyTwoBytes} (x3)", Encoding.ASCII.GetBytes(ThirtyTwoBytes3), - "975E3E6FE7E67FBC") + "975E3E6FE7E67FBC"), + // 16 * 3 bytes, filling the holdback buffer exactly on the second Append call. + new TestCase( + $"{SixteenBytes} (x3)", + Encoding.ASCII.GetBytes(SixteenBytes3), + "BDD40F0FAC166EAA"), }; protected override NonCryptographicHashAlgorithm CreateInstance() => new XxHash64(); diff --git a/src/libraries/System.IO.Hashing/tests/XxHash64Tests.f00d.cs b/src/libraries/System.IO.Hashing/tests/XxHash64Tests.f00d.cs index 283f1922d1d291..71457595c324ca 100644 --- a/src/libraries/System.IO.Hashing/tests/XxHash64Tests.f00d.cs +++ b/src/libraries/System.IO.Hashing/tests/XxHash64Tests.f00d.cs @@ -40,6 +40,8 @@ public static IEnumerable TestCases private const string SixtyThreeBytes3 = SixtyThreeBytes + SixtyThreeBytes + SixtyThreeBytes; private const string ThirtyTwoBytes = "This string has 32 ASCII bytes.."; private const string ThirtyTwoBytes3 = ThirtyTwoBytes + ThirtyTwoBytes + ThirtyTwoBytes; + private const string SixteenBytes = "0123456789ABCDEF"; + private const string SixteenBytes3 = SixteenBytes + SixteenBytes + SixteenBytes; protected static IEnumerable TestCaseDefinitions { get; } = new[] @@ -93,7 +95,11 @@ public static IEnumerable TestCases new TestCase( $"{ThirtyTwoBytes} (x3)", Encoding.ASCII.GetBytes(ThirtyTwoBytes3), - "B358EB96B8E3E7AD") + "B358EB96B8E3E7AD"), + new TestCase( + $"{SixteenBytes} (x3)", + Encoding.ASCII.GetBytes(SixteenBytes3), + "C9B96062B49FEC42"), }; protected override NonCryptographicHashAlgorithm CreateInstance() => new XxHash64(Seed); diff --git a/src/libraries/System.Linq.Expressions/tests/Member/MemberAccessTests.cs b/src/libraries/System.Linq.Expressions/tests/Member/MemberAccessTests.cs index 2f0ef38c271fa1..ae9913e9753d2a 100644 --- a/src/libraries/System.Linq.Expressions/tests/Member/MemberAccessTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/Member/MemberAccessTests.cs @@ -398,7 +398,6 @@ public static void CheckMemberAccessClassInstanceIndexerNullReferenceTest(bool u [Theory] [ClassData(typeof(CompilationTypes))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/70012", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot), nameof(PlatformDetection.IsArm64Process))] public static void CheckMemberAccessClassInstanceIndexerAssignNullReferenceTest(bool useInterpreter) { Expression> e = diff --git a/src/libraries/System.Linq.Expressions/tests/Unary/UnaryUnboxTests.cs b/src/libraries/System.Linq.Expressions/tests/Unary/UnaryUnboxTests.cs index 3f7fac6f6a1160..2ec61247eab7fd 100644 --- a/src/libraries/System.Linq.Expressions/tests/Unary/UnaryUnboxTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/Unary/UnaryUnboxTests.cs @@ -29,7 +29,6 @@ public static void ToStringTest() #region Test verifiers - [ActiveIssue("https://github.com/dotnet/runtime/issues/70012", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot), nameof(PlatformDetection.IsArm64Process))] private static void VerifyUnbox(object value, Type type, bool shouldThrow, bool useInterpreter) { Expression> e = diff --git a/src/libraries/System.Linq.Queryable/ref/System.Linq.Queryable.cs b/src/libraries/System.Linq.Queryable/ref/System.Linq.Queryable.cs index f8282977280bf0..1f99c525352dc6 100644 --- a/src/libraries/System.Linq.Queryable/ref/System.Linq.Queryable.cs +++ b/src/libraries/System.Linq.Queryable/ref/System.Linq.Queryable.cs @@ -18,11 +18,11 @@ public abstract partial class EnumerableQuery { internal EnumerableQuery() { } } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Enumerating in-memory collections as IQueryable can require unreferenced code because expressions referencing IQueryable extension methods can get rebound to IEnumerable extension methods. The IEnumerable extension methods could be trimmed causing the application to fail at runtime.")] + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public partial class EnumerableQuery : System.Linq.EnumerableQuery, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Linq.IOrderedQueryable, System.Linq.IOrderedQueryable, System.Linq.IQueryable, System.Linq.IQueryable, System.Linq.IQueryProvider { - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Enumerating in-memory collections as IQueryable can require unreferenced code because expressions referencing IQueryable extension methods can get rebound to IEnumerable extension methods. The IEnumerable extension methods could be trimmed causing the application to fail at runtime.")] public EnumerableQuery(System.Collections.Generic.IEnumerable enumerable) { } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Enumerating in-memory collections as IQueryable can require unreferenced code because expressions referencing IQueryable extension methods can get rebound to IEnumerable extension methods. The IEnumerable extension methods could be trimmed causing the application to fail at runtime.")] public EnumerableQuery(System.Linq.Expressions.Expression expression) { } System.Type System.Linq.IQueryable.ElementType { get { throw null; } } System.Linq.Expressions.Expression System.Linq.IQueryable.Expression { get { throw null; } } @@ -37,16 +37,25 @@ public EnumerableQuery(System.Linq.Expressions.Expression expression) { } } public static partial class Queryable { + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource Aggregate(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> func) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TAccumulate Aggregate(this System.Linq.IQueryable source, TAccumulate seed, System.Linq.Expressions.Expression> func) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TResult Aggregate(this System.Linq.IQueryable source, TAccumulate seed, System.Linq.Expressions.Expression> func, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static bool All(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static bool Any(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static bool Any(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Append(this System.Linq.IQueryable source, TSource element) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Enumerating in-memory collections as IQueryable can require unreferenced code because expressions referencing IQueryable extension methods can get rebound to IEnumerable extension methods. The IEnumerable extension methods could be trimmed causing the application to fail at runtime.")] + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable AsQueryable(this System.Collections.IEnumerable source) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Enumerating in-memory collections as IQueryable can require unreferenced code because expressions referencing IQueryable extension methods can get rebound to IEnumerable extension methods. The IEnumerable extension methods could be trimmed causing the application to fail at runtime.")] + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable AsQueryable(this System.Collections.Generic.IEnumerable source) { throw null; } public static decimal Average(this System.Linq.IQueryable source) { throw null; } public static double Average(this System.Linq.IQueryable source) { throw null; } @@ -58,105 +67,205 @@ public static partial class Queryable public static double? Average(this System.Linq.IQueryable source) { throw null; } public static float? Average(this System.Linq.IQueryable source) { throw null; } public static float Average(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static decimal Average(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static double Average(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static double Average(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static double Average(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static decimal? Average(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static double? Average(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static double? Average(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static double? Average(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static float? Average(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static float Average(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Cast(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Chunk(this System.Linq.IQueryable source, int size) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Concat(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static bool Contains(this System.Linq.IQueryable source, TSource item) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static bool Contains(this System.Linq.IQueryable source, TSource item, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static int Count(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static int Count(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable DefaultIfEmpty(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable DefaultIfEmpty(this System.Linq.IQueryable source, TSource defaultValue) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable DistinctBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable DistinctBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Distinct(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Distinct(this System.Linq.IQueryable source, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource? ElementAtOrDefault(this System.Linq.IQueryable source, System.Index index) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource? ElementAtOrDefault(this System.Linq.IQueryable source, int index) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource ElementAt(this System.Linq.IQueryable source, System.Index index) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource ElementAt(this System.Linq.IQueryable source, int index) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable ExceptBy(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2, System.Linq.Expressions.Expression> keySelector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable ExceptBy(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2, System.Linq.Expressions.Expression> keySelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Except(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Except(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource? FirstOrDefault(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource? FirstOrDefault(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource FirstOrDefault(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate, TSource defaultValue) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource FirstOrDefault(this System.Linq.IQueryable source, TSource defaultValue) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource First(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource First(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable> GroupBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable> GroupBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable> GroupBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Linq.Expressions.Expression> elementSelector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable> GroupBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Linq.Expressions.Expression> elementSelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable GroupBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Linq.Expressions.Expression, TResult>> resultSelector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable GroupBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Linq.Expressions.Expression, TResult>> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable GroupBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Linq.Expressions.Expression> elementSelector, System.Linq.Expressions.Expression, TResult>> resultSelector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable GroupBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Linq.Expressions.Expression> elementSelector, System.Linq.Expressions.Expression, TResult>> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable GroupJoin(this System.Linq.IQueryable outer, System.Collections.Generic.IEnumerable inner, System.Linq.Expressions.Expression> outerKeySelector, System.Linq.Expressions.Expression> innerKeySelector, System.Linq.Expressions.Expression, TResult>> resultSelector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable GroupJoin(this System.Linq.IQueryable outer, System.Collections.Generic.IEnumerable inner, System.Linq.Expressions.Expression> outerKeySelector, System.Linq.Expressions.Expression> innerKeySelector, System.Linq.Expressions.Expression, TResult>> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable IntersectBy(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2, System.Linq.Expressions.Expression> keySelector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable IntersectBy(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2, System.Linq.Expressions.Expression> keySelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Intersect(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Intersect(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Join(this System.Linq.IQueryable outer, System.Collections.Generic.IEnumerable inner, System.Linq.Expressions.Expression> outerKeySelector, System.Linq.Expressions.Expression> innerKeySelector, System.Linq.Expressions.Expression> resultSelector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Join(this System.Linq.IQueryable outer, System.Collections.Generic.IEnumerable inner, System.Linq.Expressions.Expression> outerKeySelector, System.Linq.Expressions.Expression> innerKeySelector, System.Linq.Expressions.Expression> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource? LastOrDefault(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource? LastOrDefault(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource LastOrDefault(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate, TSource defaultValue) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource LastOrDefault(this System.Linq.IQueryable source, TSource defaultValue) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource Last(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource Last(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static long LongCount(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static long LongCount(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource? MaxBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource? MaxBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Collections.Generic.IComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource? Max(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource? Max(this System.Linq.IQueryable source, System.Collections.Generic.IComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TResult? Max(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource? MinBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource? MinBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Collections.Generic.IComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource? Min(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource? Min(this System.Linq.IQueryable source, System.Collections.Generic.IComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TResult? Min(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable OfType(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IOrderedQueryable OrderByDescending(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IOrderedQueryable OrderByDescending(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Collections.Generic.IComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IOrderedQueryable OrderBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IOrderedQueryable OrderBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Collections.Generic.IComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IOrderedQueryable OrderDescending(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IOrderedQueryable OrderDescending(this System.Linq.IQueryable source, System.Collections.Generic.IComparer comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IOrderedQueryable Order(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IOrderedQueryable Order(this System.Linq.IQueryable source, System.Collections.Generic.IComparer comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Prepend(this System.Linq.IQueryable source, TSource element) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Reverse(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable SelectMany(this System.Linq.IQueryable source, System.Linq.Expressions.Expression>> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable SelectMany(this System.Linq.IQueryable source, System.Linq.Expressions.Expression>> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable SelectMany(this System.Linq.IQueryable source, System.Linq.Expressions.Expression>> collectionSelector, System.Linq.Expressions.Expression> resultSelector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable SelectMany(this System.Linq.IQueryable source, System.Linq.Expressions.Expression>> collectionSelector, System.Linq.Expressions.Expression> resultSelector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Select(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Select(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static bool SequenceEqual(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static bool SequenceEqual(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource? SingleOrDefault(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource? SingleOrDefault(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource SingleOrDefault(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate, TSource defaultValue) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource SingleOrDefault(this System.Linq.IQueryable source, TSource defaultValue) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource Single(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static TSource Single(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable SkipLast(this System.Linq.IQueryable source, int count) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable SkipWhile(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable SkipWhile(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Skip(this System.Linq.IQueryable source, int count) { throw null; } public static decimal Sum(this System.Linq.IQueryable source) { throw null; } public static double Sum(this System.Linq.IQueryable source) { throw null; } @@ -168,33 +277,61 @@ public static partial class Queryable public static long? Sum(this System.Linq.IQueryable source) { throw null; } public static float? Sum(this System.Linq.IQueryable source) { throw null; } public static float Sum(this System.Linq.IQueryable source) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static decimal Sum(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static double Sum(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static int Sum(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static long Sum(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static decimal? Sum(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static double? Sum(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static int? Sum(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static long? Sum(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static float? Sum(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static float Sum(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable TakeLast(this System.Linq.IQueryable source, int count) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable TakeWhile(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable TakeWhile(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Take(this System.Linq.IQueryable source, int count) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Take(this System.Linq.IQueryable source, System.Range range) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IOrderedQueryable ThenByDescending(this System.Linq.IOrderedQueryable source, System.Linq.Expressions.Expression> keySelector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IOrderedQueryable ThenByDescending(this System.Linq.IOrderedQueryable source, System.Linq.Expressions.Expression> keySelector, System.Collections.Generic.IComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IOrderedQueryable ThenBy(this System.Linq.IOrderedQueryable source, System.Linq.Expressions.Expression> keySelector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IOrderedQueryable ThenBy(this System.Linq.IOrderedQueryable source, System.Linq.Expressions.Expression> keySelector, System.Collections.Generic.IComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable UnionBy(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2, System.Linq.Expressions.Expression> keySelector) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable UnionBy(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2, System.Linq.Expressions.Expression> keySelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Union(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Union(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Where(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Where(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable<(TFirst First, TSecond Second)> Zip(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable<(TFirst First, TSecond Second, TThird Third)> Zip(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2, System.Collections.Generic.IEnumerable source3) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public static System.Linq.IQueryable Zip(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2, System.Linq.Expressions.Expression> resultSelector) { throw null; } } } diff --git a/src/libraries/System.Linq.Queryable/src/System.Linq.Queryable.csproj b/src/libraries/System.Linq.Queryable/src/System.Linq.Queryable.csproj index 4d7656af1da60a..75fb21c085ac1c 100644 --- a/src/libraries/System.Linq.Queryable/src/System.Linq.Queryable.csproj +++ b/src/libraries/System.Linq.Queryable/src/System.Linq.Queryable.csproj @@ -1,6 +1,7 @@ $(NetCoreAppCurrent) + true diff --git a/src/libraries/System.Linq.Queryable/src/System/Linq/CachedReflection.cs b/src/libraries/System.Linq.Queryable/src/System/Linq/CachedReflection.cs index 99c98faf7ecbe3..514580fb334c0e 100644 --- a/src/libraries/System.Linq.Queryable/src/System/Linq/CachedReflection.cs +++ b/src/libraries/System.Linq.Queryable/src/System/Linq/CachedReflection.cs @@ -14,36 +14,42 @@ internal static class CachedReflectionInfo { private static MethodInfo? s_Aggregate_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Aggregate_TSource_2(Type TSource) => (s_Aggregate_TSource_2 ??= new Func, Expression>, object>(Queryable.Aggregate).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Aggregate_TSource_TAccumulate_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Aggregate_TSource_TAccumulate_3(Type TSource, Type TAccumulate) => (s_Aggregate_TSource_TAccumulate_3 ??= new Func, object, Expression>, object>(Queryable.Aggregate).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TAccumulate); private static MethodInfo? s_Aggregate_TSource_TAccumulate_TResult_4; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Aggregate_TSource_TAccumulate_TResult_4(Type TSource, Type TAccumulate, Type TResult) => (s_Aggregate_TSource_TAccumulate_TResult_4 ??= new Func, object, Expression>, Expression>, object>(Queryable.Aggregate).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TAccumulate, TResult); private static MethodInfo? s_All_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo All_TSource_2(Type TSource) => (s_All_TSource_2 ??= new Func, Expression>, bool>(Queryable.All).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Any_TSource_1; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Any_TSource_1(Type TSource) => (s_Any_TSource_1 ??= new Func, bool>(Queryable.Any).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Any_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Any_TSource_2(Type TSource) => (s_Any_TSource_2 ??= new Func, Expression>, bool>(Queryable.Any).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); @@ -100,588 +106,686 @@ public static MethodInfo Any_TSource_2(Type TSource) => private static MethodInfo? s_Average_Int32_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Average_Int32_TSource_2(Type TSource) => (s_Average_Int32_TSource_2 ??= new Func, Expression>, double>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Average_NullableInt32_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Average_NullableInt32_TSource_2(Type TSource) => (s_Average_NullableInt32_TSource_2 ??= new Func, Expression>, double?>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Average_Single_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Average_Single_TSource_2(Type TSource) => (s_Average_Single_TSource_2 ??= new Func, Expression>, float>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Average_NullableSingle_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Average_NullableSingle_TSource_2(Type TSource) => (s_Average_NullableSingle_TSource_2 ??= new Func, Expression>, float?>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Average_Int64_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Average_Int64_TSource_2(Type TSource) => (s_Average_Int64_TSource_2 ??= new Func, Expression>, double>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Average_NullableInt64_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Average_NullableInt64_TSource_2(Type TSource) => (s_Average_NullableInt64_TSource_2 ??= new Func, Expression>, double?>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Average_Double_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Average_Double_TSource_2(Type TSource) => (s_Average_Double_TSource_2 ??= new Func, Expression>, double>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Average_NullableDouble_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Average_NullableDouble_TSource_2(Type TSource) => (s_Average_NullableDouble_TSource_2 ??= new Func, Expression>, double?>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Average_Decimal_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Average_Decimal_TSource_2(Type TSource) => (s_Average_Decimal_TSource_2 ??= new Func, Expression>, decimal>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Average_NullableDecimal_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Average_NullableDecimal_TSource_2(Type TSource) => (s_Average_NullableDecimal_TSource_2 ??= new Func, Expression>, decimal?>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Cast_TResult_1; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Cast_TResult_1(Type TResult) => (s_Cast_TResult_1 ??= new Func>(Queryable.Cast).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TResult); private static MethodInfo? s_Chunk_TSource_1; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Chunk_TSource_1(Type TSource) => (s_Chunk_TSource_1 ??= new Func, int, IQueryable>(Queryable.Chunk).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Concat_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Concat_TSource_2(Type TSource) => (s_Concat_TSource_2 ??= new Func, IEnumerable, IQueryable>(Queryable.Concat).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Contains_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Contains_TSource_2(Type TSource) => (s_Contains_TSource_2 ??= new Func, object, bool>(Queryable.Contains).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Contains_TSource_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Contains_TSource_3(Type TSource) => (s_Contains_TSource_3 ??= new Func, object, IEqualityComparer, bool>(Queryable.Contains).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Count_TSource_1; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Count_TSource_1(Type TSource) => (s_Count_TSource_1 ??= new Func, int>(Queryable.Count).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Count_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Count_TSource_2(Type TSource) => (s_Count_TSource_2 ??= new Func, Expression>, int>(Queryable.Count).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_DefaultIfEmpty_TSource_1; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo DefaultIfEmpty_TSource_1(Type TSource) => (s_DefaultIfEmpty_TSource_1 ??= new Func, IQueryable>(Queryable.DefaultIfEmpty).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_DefaultIfEmpty_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo DefaultIfEmpty_TSource_2(Type TSource) => (s_DefaultIfEmpty_TSource_2 ??= new Func, object, IQueryable>(Queryable.DefaultIfEmpty).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Distinct_TSource_1; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Distinct_TSource_1(Type TSource) => (s_Distinct_TSource_1 ??= new Func, IQueryable>(Queryable.Distinct).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Distinct_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Distinct_TSource_2(Type TSource) => (s_Distinct_TSource_2 ??= new Func, IEqualityComparer, IQueryable>(Queryable.Distinct).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_DistinctBy_TSource_TKey_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo DistinctBy_TSource_TKey_2(Type TSource, Type TKey) => (s_DistinctBy_TSource_TKey_2 ??= new Func, Expression>, IQueryable>(Queryable.DistinctBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_DistinctBy_TSource_TKey_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo DistinctBy_TSource_TKey_3(Type TSource, Type TKey) => (s_DistinctBy_TSource_TKey_3 ??= new Func, Expression>, IEqualityComparer, IQueryable>(Queryable.DistinctBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_ElementAt_Int32_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo ElementAt_Int32_TSource_2(Type TSource) => (s_ElementAt_Int32_TSource_2 ??= new Func, int, object>(Queryable.ElementAt).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_ElementAt_Index_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo ElementAt_Index_TSource_2(Type TSource) => (s_ElementAt_Index_TSource_2 ??= new Func, Index, object>(Queryable.ElementAt).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_ElementAtOrDefault_Int32_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo ElementAtOrDefault_Int32_TSource_2(Type TSource) => (s_ElementAtOrDefault_Int32_TSource_2 ??= new Func, int, object?>(Queryable.ElementAtOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_ElementAtOrDefault_Index_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo ElementAtOrDefault_Index_TSource_2(Type TSource) => (s_ElementAtOrDefault_Index_TSource_2 ??= new Func, Index, object?>(Queryable.ElementAtOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Except_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Except_TSource_2(Type TSource) => (s_Except_TSource_2 ??= new Func, IEnumerable, IQueryable>(Queryable.Except).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Except_TSource_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Except_TSource_3(Type TSource) => (s_Except_TSource_3 ??= new Func, IEnumerable, IEqualityComparer, IQueryable>(Queryable.Except).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_ExceptBy_TSource_TKey_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo ExceptBy_TSource_TKey_3(Type TSource, Type TKey) => (s_ExceptBy_TSource_TKey_3 ??= new Func, IEnumerable, Expression>, IQueryable>(Queryable.ExceptBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_ExceptBy_TSource_TKey_4; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo ExceptBy_TSource_TKey_4(Type TSource, Type TKey) => (s_ExceptBy_TSource_TKey_4 ??= new Func, IEnumerable, Expression>, IEqualityComparer, IQueryable>(Queryable.ExceptBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_First_TSource_1; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo First_TSource_1(Type TSource) => (s_First_TSource_1 ??= new Func, object>(Queryable.First).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_First_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo First_TSource_2(Type TSource) => (s_First_TSource_2 ??= new Func, Expression>, object>(Queryable.First).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_FirstOrDefault_TSource_1; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo FirstOrDefault_TSource_1(Type TSource) => (s_FirstOrDefault_TSource_1 ??= new Func, object?>(Queryable.FirstOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_FirstOrDefault_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo FirstOrDefault_TSource_2(Type TSource) => (s_FirstOrDefault_TSource_2 ??= new Func, Expression>, object?>(Queryable.FirstOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_FirstOrDefault_TSource_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo FirstOrDefault_TSource_3(Type TSource) => (s_FirstOrDefault_TSource_3 ??= new Func, object, object>(Queryable.FirstOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_FirstOrDefault_TSource_4; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo FirstOrDefault_TSource_4(Type TSource) => (s_FirstOrDefault_TSource_4 ??= new Func, Expression>, object, object>(Queryable.FirstOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_GroupBy_TSource_TKey_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo GroupBy_TSource_TKey_2(Type TSource, Type TKey) => (s_GroupBy_TSource_TKey_2 ??= new Func, Expression>, IQueryable>>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_GroupBy_TSource_TKey_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo GroupBy_TSource_TKey_3(Type TSource, Type TKey) => (s_GroupBy_TSource_TKey_3 ??= new Func, Expression>, IEqualityComparer, IQueryable>>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_GroupBy_TSource_TKey_TElement_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo GroupBy_TSource_TKey_TElement_3(Type TSource, Type TKey, Type TElement) => (s_GroupBy_TSource_TKey_TElement_3 ??= new Func, Expression>, Expression>, IQueryable>>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey, TElement); private static MethodInfo? s_GroupBy_TSource_TKey_TElement_4; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo GroupBy_TSource_TKey_TElement_4(Type TSource, Type TKey, Type TElement) => (s_GroupBy_TSource_TKey_TElement_4 ??= new Func, Expression>, Expression>, IEqualityComparer, IQueryable>>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey, TElement); private static MethodInfo? s_GroupBy_TSource_TKey_TResult_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo GroupBy_TSource_TKey_TResult_3(Type TSource, Type TKey, Type TResult) => (s_GroupBy_TSource_TKey_TResult_3 ??= new Func, Expression>, Expression, object>>, IQueryable>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey, TResult); private static MethodInfo? s_GroupBy_TSource_TKey_TResult_4; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo GroupBy_TSource_TKey_TResult_4(Type TSource, Type TKey, Type TResult) => (s_GroupBy_TSource_TKey_TResult_4 ??= new Func, Expression>, Expression, object>>, IEqualityComparer, IQueryable>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey, TResult); private static MethodInfo? s_GroupBy_TSource_TKey_TElement_TResult_4; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo GroupBy_TSource_TKey_TElement_TResult_4(Type TSource, Type TKey, Type TElement, Type TResult) => (s_GroupBy_TSource_TKey_TElement_TResult_4 ??= new Func, Expression>, Expression>, Expression, object>>, IQueryable>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey, TElement, TResult); private static MethodInfo? s_GroupBy_TSource_TKey_TElement_TResult_5; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo GroupBy_TSource_TKey_TElement_TResult_5(Type TSource, Type TKey, Type TElement, Type TResult) => (s_GroupBy_TSource_TKey_TElement_TResult_5 ??= new Func, Expression>, Expression>, Expression, object>>, IEqualityComparer, IQueryable>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey, TElement, TResult); private static MethodInfo? s_GroupJoin_TOuter_TInner_TKey_TResult_5; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo GroupJoin_TOuter_TInner_TKey_TResult_5(Type TOuter, Type TInner, Type TKey, Type TResult) => (s_GroupJoin_TOuter_TInner_TKey_TResult_5 ??= new Func, IEnumerable, Expression>, Expression>, Expression, object>>, IQueryable>(Queryable.GroupJoin).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TOuter, TInner, TKey, TResult); private static MethodInfo? s_GroupJoin_TOuter_TInner_TKey_TResult_6; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo GroupJoin_TOuter_TInner_TKey_TResult_6(Type TOuter, Type TInner, Type TKey, Type TResult) => (s_GroupJoin_TOuter_TInner_TKey_TResult_6 ??= new Func, IEnumerable, Expression>, Expression>, Expression, object>>, IEqualityComparer, IQueryable>(Queryable.GroupJoin).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TOuter, TInner, TKey, TResult); private static MethodInfo? s_Intersect_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Intersect_TSource_2(Type TSource) => (s_Intersect_TSource_2 ??= new Func, IEnumerable, IQueryable>(Queryable.Intersect).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Intersect_TSource_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Intersect_TSource_3(Type TSource) => (s_Intersect_TSource_3 ??= new Func, IEnumerable, IEqualityComparer, IQueryable>(Queryable.Intersect).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_IntersectBy_TSource_TKey_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo IntersectBy_TSource_TKey_3(Type TSource, Type TKey) => (s_IntersectBy_TSource_TKey_3 ??= new Func, IEnumerable, Expression>, IQueryable>(Queryable.IntersectBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_IntersectBy_TSource_TKey_4; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo IntersectBy_TSource_TKey_4(Type TSource, Type TKey) => (s_IntersectBy_TSource_TKey_4 ??= new Func, IEnumerable, Expression>, IEqualityComparer, IQueryable>(Queryable.IntersectBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_Join_TOuter_TInner_TKey_TResult_5; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Join_TOuter_TInner_TKey_TResult_5(Type TOuter, Type TInner, Type TKey, Type TResult) => (s_Join_TOuter_TInner_TKey_TResult_5 ??= new Func, IEnumerable, Expression>, Expression>, Expression>, IQueryable>(Queryable.Join).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TOuter, TInner, TKey, TResult); private static MethodInfo? s_Join_TOuter_TInner_TKey_TResult_6; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Join_TOuter_TInner_TKey_TResult_6(Type TOuter, Type TInner, Type TKey, Type TResult) => (s_Join_TOuter_TInner_TKey_TResult_6 ??= new Func, IEnumerable, Expression>, Expression>, Expression>, IEqualityComparer, IQueryable>(Queryable.Join).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TOuter, TInner, TKey, TResult); private static MethodInfo? s_Last_TSource_1; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Last_TSource_1(Type TSource) => (s_Last_TSource_1 ??= new Func, object>(Queryable.Last).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Last_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Last_TSource_2(Type TSource) => (s_Last_TSource_2 ??= new Func, Expression>, object>(Queryable.Last).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_LastOrDefault_TSource_1; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo LastOrDefault_TSource_1(Type TSource) => (s_LastOrDefault_TSource_1 ??= new Func, object?>(Queryable.LastOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_LastOrDefault_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo LastOrDefault_TSource_2(Type TSource) => (s_LastOrDefault_TSource_2 ??= new Func, Expression>, object?>(Queryable.LastOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_LastOrDefault_TSource_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo LastOrDefault_TSource_3(Type TSource) => (s_LastOrDefault_TSource_3 ??= new Func, object, object>(Queryable.LastOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_LastOrDefault_TSource_4; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo LastOrDefault_TSource_4(Type TSource) => (s_LastOrDefault_TSource_4 ??= new Func, Expression>, object, object>(Queryable.LastOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_LongCount_TSource_1; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo LongCount_TSource_1(Type TSource) => (s_LongCount_TSource_1 ??= new Func, long>(Queryable.LongCount).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_LongCount_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo LongCount_TSource_2(Type TSource) => (s_LongCount_TSource_2 ??= new Func, Expression>, long>(Queryable.LongCount).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Max_TSource_1; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Max_TSource_1(Type TSource) => (s_Max_TSource_1 ??= new Func, object?>(Queryable.Max).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Max_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Max_TSource_2(Type TSource) => (s_Max_TSource_2 ??= new Func, IComparer, object?>(Queryable.Max).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Max_TSource_TResult_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Max_TSource_TResult_2(Type TSource, Type TResult) => (s_Max_TSource_TResult_2 ??= new Func, Expression>, object?>(Queryable.Max).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TResult); private static MethodInfo? s_MaxBy_TSource_TKey_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo MaxBy_TSource_TKey_2(Type TSource, Type TKey) => (s_MaxBy_TSource_TKey_2 ??= new Func, Expression>, object?>(Queryable.MaxBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_MaxBy_TSource_TKey_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo MaxBy_TSource_TKey_3(Type TSource, Type TKey) => (s_MaxBy_TSource_TKey_3 ??= new Func, Expression>, IComparer, object?>(Queryable.MaxBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_Min_TSource_1; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Min_TSource_1(Type TSource) => (s_Min_TSource_1 ??= new Func, object?>(Queryable.Min).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Min_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Min_TSource_2(Type TSource) => (s_Min_TSource_2 ??= new Func, IComparer, object?>(Queryable.Min).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Min_TSource_TResult_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Min_TSource_TResult_2(Type TSource, Type TResult) => (s_Min_TSource_TResult_2 ??= new Func, Expression>, object?>(Queryable.Min).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TResult); private static MethodInfo? s_MinBy_TSource_TKey_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo MinBy_TSource_TKey_2(Type TSource, Type TKey) => (s_MinBy_TSource_TKey_2 ??= new Func, Expression>, object?>(Queryable.MinBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_MinBy_TSource_TKey_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo MinBy_TSource_TKey_3(Type TSource, Type TKey) => (s_MinBy_TSource_TKey_3 ??= new Func, Expression>, IComparer, object?>(Queryable.MinBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_OfType_TResult_1; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo OfType_TResult_1(Type TResult) => (s_OfType_TResult_1 ??= new Func>(Queryable.OfType).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TResult); private static MethodInfo? s_Order_T_1; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Order_T_1(Type T) => (s_Order_T_1 ??= new Func, IOrderedQueryable>(Queryable.Order).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(T); private static MethodInfo? s_Order_T_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Order_T_2(Type T) => (s_Order_T_2 ??= new Func, IComparer, IOrderedQueryable>(Queryable.Order).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(T); private static MethodInfo? s_OrderBy_TSource_TKey_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo OrderBy_TSource_TKey_2(Type TSource, Type TKey) => (s_OrderBy_TSource_TKey_2 ??= new Func, Expression>, IOrderedQueryable>(Queryable.OrderBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_OrderDescending_T_1; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo OrderDescending_T_1(Type T) => (s_OrderDescending_T_1 ??= new Func, IOrderedQueryable>(Queryable.OrderDescending).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(T); private static MethodInfo? s_OrderDescending_T_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo OrderDescending_T_2(Type T) => (s_OrderDescending_T_2 ??= new Func, IComparer, IOrderedQueryable>(Queryable.OrderDescending).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(T); private static MethodInfo? s_OrderBy_TSource_TKey_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo OrderBy_TSource_TKey_3(Type TSource, Type TKey) => (s_OrderBy_TSource_TKey_3 ??= new Func, Expression>, IComparer, IOrderedQueryable>(Queryable.OrderBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_OrderByDescending_TSource_TKey_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo OrderByDescending_TSource_TKey_2(Type TSource, Type TKey) => (s_OrderByDescending_TSource_TKey_2 ??= new Func, Expression>, IOrderedQueryable>(Queryable.OrderByDescending).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_OrderByDescending_TSource_TKey_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo OrderByDescending_TSource_TKey_3(Type TSource, Type TKey) => (s_OrderByDescending_TSource_TKey_3 ??= new Func, Expression>, IComparer, IOrderedQueryable>(Queryable.OrderByDescending).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_Reverse_TSource_1; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Reverse_TSource_1(Type TSource) => (s_Reverse_TSource_1 ??= new Func, IQueryable>(Queryable.Reverse).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Select_TSource_TResult_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Select_TSource_TResult_2(Type TSource, Type TResult) => (s_Select_TSource_TResult_2 ??= new Func, Expression>, IQueryable>(Queryable.Select).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TResult); private static MethodInfo? s_Select_Index_TSource_TResult_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Select_Index_TSource_TResult_2(Type TSource, Type TResult) => (s_Select_Index_TSource_TResult_2 ??= new Func, Expression>, IQueryable>(Queryable.Select).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TResult); private static MethodInfo? s_SelectMany_TSource_TResult_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo SelectMany_TSource_TResult_2(Type TSource, Type TResult) => (s_SelectMany_TSource_TResult_2 ??= new Func, Expression>>, IQueryable>(Queryable.SelectMany).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TResult); private static MethodInfo? s_SelectMany_Index_TSource_TResult_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo SelectMany_Index_TSource_TResult_2(Type TSource, Type TResult) => (s_SelectMany_Index_TSource_TResult_2 ??= new Func, Expression>>, IQueryable>(Queryable.SelectMany).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TResult); private static MethodInfo? s_SelectMany_Index_TSource_TCollection_TResult_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo SelectMany_Index_TSource_TCollection_TResult_3(Type TSource, Type TCollection, Type TResult) => (s_SelectMany_Index_TSource_TCollection_TResult_3 ??= new Func, Expression>>, Expression>, IQueryable>(Queryable.SelectMany).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TCollection, TResult); private static MethodInfo? s_SelectMany_TSource_TCollection_TResult_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo SelectMany_TSource_TCollection_TResult_3(Type TSource, Type TCollection, Type TResult) => (s_SelectMany_TSource_TCollection_TResult_3 ??= new Func, Expression>>, Expression>, IQueryable>(Queryable.SelectMany).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TCollection, TResult); private static MethodInfo? s_SequenceEqual_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo SequenceEqual_TSource_2(Type TSource) => (s_SequenceEqual_TSource_2 ??= new Func, IEnumerable, bool>(Queryable.SequenceEqual).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_SequenceEqual_TSource_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo SequenceEqual_TSource_3(Type TSource) => (s_SequenceEqual_TSource_3 ??= new Func, IEnumerable, IEqualityComparer, bool>(Queryable.SequenceEqual).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Single_TSource_1; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Single_TSource_1(Type TSource) => (s_Single_TSource_1 ??= new Func, object>(Queryable.Single).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Single_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Single_TSource_2(Type TSource) => (s_Single_TSource_2 ??= new Func, Expression>, object>(Queryable.Single).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_SingleOrDefault_TSource_1; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo SingleOrDefault_TSource_1(Type TSource) => (s_SingleOrDefault_TSource_1 ??= new Func, object?>(Queryable.SingleOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_SingleOrDefault_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo SingleOrDefault_TSource_2(Type TSource) => (s_SingleOrDefault_TSource_2 ??= new Func, Expression>, object?>(Queryable.SingleOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_SingleOrDefault_TSource_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo SingleOrDefault_TSource_3(Type TSource) => (s_SingleOrDefault_TSource_3 ??= new Func, object, object>(Queryable.SingleOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_SingleOrDefault_TSource_4; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo SingleOrDefault_TSource_4(Type TSource) => (s_SingleOrDefault_TSource_4 ??= new Func, Expression>, object, object>(Queryable.SingleOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Skip_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Skip_TSource_2(Type TSource) => (s_Skip_TSource_2 ??= new Func, int, IQueryable>(Queryable.Skip).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_SkipWhile_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo SkipWhile_TSource_2(Type TSource) => (s_SkipWhile_TSource_2 ??= new Func, Expression>, IQueryable>(Queryable.SkipWhile).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_SkipWhile_Index_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo SkipWhile_Index_TSource_2(Type TSource) => (s_SkipWhile_Index_TSource_2 ??= new Func, Expression>, IQueryable>(Queryable.SkipWhile).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); @@ -738,162 +842,189 @@ public static MethodInfo SkipWhile_Index_TSource_2(Type TSource) => private static MethodInfo? s_Sum_NullableDecimal_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Sum_NullableDecimal_TSource_2(Type TSource) => (s_Sum_NullableDecimal_TSource_2 ??= new Func, Expression>, decimal?>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Sum_Int32_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Sum_Int32_TSource_2(Type TSource) => (s_Sum_Int32_TSource_2 ??= new Func, Expression>, int>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Sum_NullableInt32_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Sum_NullableInt32_TSource_2(Type TSource) => (s_Sum_NullableInt32_TSource_2 ??= new Func, Expression>, int?>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Sum_Int64_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Sum_Int64_TSource_2(Type TSource) => (s_Sum_Int64_TSource_2 ??= new Func, Expression>, long>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Sum_NullableInt64_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Sum_NullableInt64_TSource_2(Type TSource) => (s_Sum_NullableInt64_TSource_2 ??= new Func, Expression>, long?>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Sum_Single_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Sum_Single_TSource_2(Type TSource) => (s_Sum_Single_TSource_2 ??= new Func, Expression>, float>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Sum_NullableSingle_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Sum_NullableSingle_TSource_2(Type TSource) => (s_Sum_NullableSingle_TSource_2 ??= new Func, Expression>, float?>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Sum_Double_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Sum_Double_TSource_2(Type TSource) => (s_Sum_Double_TSource_2 ??= new Func, Expression>, double>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Sum_NullableDouble_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Sum_NullableDouble_TSource_2(Type TSource) => (s_Sum_NullableDouble_TSource_2 ??= new Func, Expression>, double?>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Sum_Decimal_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Sum_Decimal_TSource_2(Type TSource) => (s_Sum_Decimal_TSource_2 ??= new Func, Expression>, decimal>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Take_Int32_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Take_Int32_TSource_2(Type TSource) => (s_Take_Int32_TSource_2 ??= new Func, int, IQueryable>(Queryable.Take).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Take_Range_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Take_Range_TSource_2(Type TSource) => (s_Take_Range_TSource_2 ??= new Func, Range, IQueryable>(Queryable.Take).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_TakeWhile_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo TakeWhile_TSource_2(Type TSource) => (s_TakeWhile_TSource_2 ??= new Func, Expression>, IQueryable>(Queryable.TakeWhile).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_TakeWhile_Index_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo TakeWhile_Index_TSource_2(Type TSource) => (s_TakeWhile_Index_TSource_2 ??= new Func, Expression>, IQueryable>(Queryable.TakeWhile).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_ThenBy_TSource_TKey_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo ThenBy_TSource_TKey_2(Type TSource, Type TKey) => (s_ThenBy_TSource_TKey_2 ??= new Func, Expression>, IOrderedQueryable>(Queryable.ThenBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_ThenBy_TSource_TKey_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo ThenBy_TSource_TKey_3(Type TSource, Type TKey) => (s_ThenBy_TSource_TKey_3 ??= new Func, Expression>, IComparer, IOrderedQueryable>(Queryable.ThenBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_ThenByDescending_TSource_TKey_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo ThenByDescending_TSource_TKey_2(Type TSource, Type TKey) => (s_ThenByDescending_TSource_TKey_2 ??= new Func, Expression>, IOrderedQueryable>(Queryable.ThenByDescending).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_ThenByDescending_TSource_TKey_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo ThenByDescending_TSource_TKey_3(Type TSource, Type TKey) => (s_ThenByDescending_TSource_TKey_3 ??= new Func, Expression>, IComparer, IOrderedQueryable>(Queryable.ThenByDescending).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_Union_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Union_TSource_2(Type TSource) => (s_Union_TSource_2 ??= new Func, IEnumerable, IQueryable>(Queryable.Union).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Union_TSource_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Union_TSource_3(Type TSource) => (s_Union_TSource_3 ??= new Func, IEnumerable, IEqualityComparer, IQueryable>(Queryable.Union).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_UnionBy_TSource_TKey_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo UnionBy_TSource_TKey_3(Type TSource, Type TKey) => (s_UnionBy_TSource_TKey_3 ??= new Func, IEnumerable, Expression>, IQueryable>(Queryable.UnionBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_UnionBy_TSource_TKey_4; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo UnionBy_TSource_TKey_4(Type TSource, Type TKey) => (s_UnionBy_TSource_TKey_4 ??= new Func, IEnumerable, Expression>, IEqualityComparer, IQueryable>(Queryable.UnionBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_Where_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Where_TSource_2(Type TSource) => (s_Where_TSource_2 ??= new Func, Expression>, IQueryable>(Queryable.Where).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Where_Index_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Where_Index_TSource_2(Type TSource) => (s_Where_Index_TSource_2 ??= new Func, Expression>, IQueryable>(Queryable.Where).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Zip_TFirst_TSecond_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Zip_TFirst_TSecond_2(Type TFirst, Type TSecond) => (s_Zip_TFirst_TSecond_2 ??= new Func, IEnumerable, IQueryable<(object, object)>>(Queryable.Zip).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TFirst, TSecond); private static MethodInfo? s_Zip_TFirst_TSecond_TResult_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Zip_TFirst_TSecond_TResult_3(Type TFirst, Type TSecond, Type TResult) => (s_Zip_TFirst_TSecond_TResult_3 ??= new Func, IEnumerable, Expression>, IQueryable>(Queryable.Zip).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TFirst, TSecond, TResult); private static MethodInfo? s_Zip_TFirst_TSecond_TThird_3; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Zip_TFirst_TSecond_TThird_3(Type TFirst, Type TSecond, Type TThird) => (s_Zip_TFirst_TSecond_TThird_3 ??= new Func, IEnumerable, IEnumerable, IQueryable<(object, object, object)>>(Queryable.Zip).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TFirst, TSecond, TThird); @@ -901,24 +1032,28 @@ public static MethodInfo Zip_TFirst_TSecond_TThird_3(Type TFirst, Type TSecond, private static MethodInfo? s_SkipLast_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo SkipLast_TSource_2(Type TSource) => (s_SkipLast_TSource_2 ??= new Func, int, IQueryable>(Queryable.SkipLast).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_TakeLast_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo TakeLast_TSource_2(Type TSource) => (s_TakeLast_TSource_2 ??= new Func, int, IQueryable>(Queryable.TakeLast).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Append_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Append_TSource_2(Type TSource) => (s_Append_TSource_2 ??= new Func, object, IQueryable>(Queryable.Append).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Prepend_TSource_2; + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public static MethodInfo Prepend_TSource_2(Type TSource) => (s_Prepend_TSource_2 ??= new Func, object, IQueryable>(Queryable.Prepend).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); diff --git a/src/libraries/System.Linq.Queryable/src/System/Linq/EnumerableExecutor.cs b/src/libraries/System.Linq.Queryable/src/System/Linq/EnumerableExecutor.cs index 5ff04c6fdcc167..14a4935864c784 100644 --- a/src/libraries/System.Linq.Queryable/src/System/Linq/EnumerableExecutor.cs +++ b/src/libraries/System.Linq.Queryable/src/System/Linq/EnumerableExecutor.cs @@ -10,10 +10,12 @@ namespace System.Linq public abstract class EnumerableExecutor { [RequiresUnreferencedCode(Queryable.InMemoryQueryableExtensionMethodsRequiresUnreferencedCode)] + [RequiresDynamicCode(Queryable.InMemoryQueryableExtensionMethodsRequiresDynamicCode)] internal abstract object? ExecuteBoxed(); internal EnumerableExecutor() { } + [RequiresDynamicCode(Queryable.InMemoryQueryableExtensionMethodsRequiresDynamicCode)] internal static EnumerableExecutor Create(Expression expression) { Type execType = typeof(EnumerableExecutor<>).MakeGenericType(expression.Type); @@ -31,9 +33,11 @@ public EnumerableExecutor(Expression expression) } [RequiresUnreferencedCode(Queryable.InMemoryQueryableExtensionMethodsRequiresUnreferencedCode)] + [RequiresDynamicCode(Queryable.InMemoryQueryableExtensionMethodsRequiresDynamicCode)] internal override object? ExecuteBoxed() => Execute(); [RequiresUnreferencedCode(Queryable.InMemoryQueryableExtensionMethodsRequiresUnreferencedCode)] + [RequiresDynamicCode(Queryable.InMemoryQueryableExtensionMethodsRequiresDynamicCode)] internal T Execute() { EnumerableRewriter rewriter = new EnumerableRewriter(); diff --git a/src/libraries/System.Linq.Queryable/src/System/Linq/EnumerableQuery.cs b/src/libraries/System.Linq.Queryable/src/System/Linq/EnumerableQuery.cs index 97c4b0daeb75c3..222f030bb8f4d6 100644 --- a/src/libraries/System.Linq.Queryable/src/System/Linq/EnumerableQuery.cs +++ b/src/libraries/System.Linq.Queryable/src/System/Linq/EnumerableQuery.cs @@ -16,6 +16,7 @@ public abstract class EnumerableQuery internal EnumerableQuery() { } [RequiresUnreferencedCode(Queryable.InMemoryQueryableExtensionMethodsRequiresUnreferencedCode)] + [RequiresDynamicCode(Queryable.InMemoryQueryableExtensionMethodsRequiresDynamicCode)] internal static IQueryable Create(Type elementType, IEnumerable sequence) { Type seqType = typeof(EnumerableQuery<>).MakeGenericType(elementType); @@ -23,6 +24,7 @@ internal static IQueryable Create(Type elementType, IEnumerable sequence) } [RequiresUnreferencedCode(Queryable.InMemoryQueryableExtensionMethodsRequiresUnreferencedCode)] + [RequiresDynamicCode(Queryable.InMemoryQueryableExtensionMethodsRequiresDynamicCode)] internal static IQueryable Create(Type elementType, Expression expression) { Type seqType = typeof(EnumerableQuery<>).MakeGenericType(elementType); @@ -30,6 +32,8 @@ internal static IQueryable Create(Type elementType, Expression expression) } } + [RequiresDynamicCode(Queryable.InMemoryQueryableExtensionMethodsRequiresDynamicCode)] + [RequiresUnreferencedCode(Queryable.InMemoryQueryableExtensionMethodsRequiresUnreferencedCode)] public class EnumerableQuery : EnumerableQuery, IOrderedQueryable, IQueryProvider { private readonly Expression _expression; @@ -37,14 +41,12 @@ public class EnumerableQuery : EnumerableQuery, IOrderedQueryable, IQueryP IQueryProvider IQueryable.Provider => this; - [RequiresUnreferencedCode(Queryable.InMemoryQueryableExtensionMethodsRequiresUnreferencedCode)] public EnumerableQuery(IEnumerable enumerable) { _enumerable = enumerable; _expression = Expression.Constant(this); } - [RequiresUnreferencedCode(Queryable.InMemoryQueryableExtensionMethodsRequiresUnreferencedCode)] public EnumerableQuery(Expression expression) { _expression = expression; @@ -58,8 +60,6 @@ public EnumerableQuery(Expression expression) Type IQueryable.ElementType => typeof(T); - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Justification = "This class's ctor is annotated as RequiresUnreferencedCode.")] IQueryable IQueryProvider.CreateQuery(Expression expression) { ArgumentNullException.ThrowIfNull(expression); @@ -70,8 +70,6 @@ IQueryable IQueryProvider.CreateQuery(Expression expression) return Create(iqType.GetGenericArguments()[0], expression); } - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Justification = "This class's ctor is annotated as RequiresUnreferencedCode.")] IQueryable IQueryProvider.CreateQuery(Expression expression) { ArgumentNullException.ThrowIfNull(expression); @@ -83,8 +81,6 @@ IQueryable IQueryProvider.CreateQuery(Expression expression) return new EnumerableQuery(expression); } - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Justification = "This class's ctor is annotated as RequiresUnreferencedCode.")] object? IQueryProvider.Execute(Expression expression) { ArgumentNullException.ThrowIfNull(expression); @@ -92,8 +88,6 @@ IQueryable IQueryProvider.CreateQuery(Expression expression) return EnumerableExecutor.Create(expression).ExecuteBoxed(); } - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Justification = "This class's ctor is annotated as RequiresUnreferencedCode.")] TElement IQueryProvider.Execute(Expression expression) { ArgumentNullException.ThrowIfNull(expression); @@ -107,8 +101,6 @@ TElement IQueryProvider.Execute(Expression expression) IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Justification = "This class's ctor is annotated as RequiresUnreferencedCode.")] private IEnumerator GetEnumerator() { if (_enumerable == null) diff --git a/src/libraries/System.Linq.Queryable/src/System/Linq/EnumerableRewriter.cs b/src/libraries/System.Linq.Queryable/src/System/Linq/EnumerableRewriter.cs index 17cedfed6291f6..2490a787a90367 100644 --- a/src/libraries/System.Linq.Queryable/src/System/Linq/EnumerableRewriter.cs +++ b/src/libraries/System.Linq.Queryable/src/System/Linq/EnumerableRewriter.cs @@ -11,6 +11,8 @@ namespace System.Linq { + [RequiresUnreferencedCode(Queryable.InMemoryQueryableExtensionMethodsRequiresUnreferencedCode)] + [RequiresDynamicCode("Requires MakeGenericType")] internal sealed class EnumerableRewriter : ExpressionVisitor { // We must ensure that if a LabelTarget is rewritten that it is always rewritten to the same new target @@ -19,13 +21,10 @@ internal sealed class EnumerableRewriter : ExpressionVisitor // Finding equivalent types can be relatively expensive, and hitting with the same types repeatedly is quite likely. private Dictionary? _equivalentTypeCache; - [RequiresUnreferencedCode(Queryable.InMemoryQueryableExtensionMethodsRequiresUnreferencedCode)] public EnumerableRewriter() { } - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Justification = "This class's ctor is annotated as RequiresUnreferencedCode.")] protected override Expression VisitMethodCall(MethodCallExpression m) { Expression? obj = Visit(m.Object); @@ -196,38 +195,26 @@ private Type GetEquivalentType(Type type) } if (equiv == null) { - equiv = GetEquivalentTypeToEnumerables(pubType); - - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", - Justification = "The enumerable interface type (IOrderedQueryable<>, IOrderedEnumerable<>, IQueryable<> and IEnumerable<>) " + - "is kept since it's directly referenced here" + - "and so it will also be preserved in all places where it's implemented." + - "The GetInterfaces may return less after trimming but it will include" + - "the enumerable interface type if it was there before trimming, which is enough for this" + - "method to work.")] - static Type GetEquivalentTypeToEnumerables(Type sourceType) + var interfacesWithInfo = pubType.GetInterfaces(); + var singleTypeGenInterfacesWithGetType = interfacesWithInfo + .Where(i => i.IsGenericType && i.GenericTypeArguments.Length == 1) + .Select(i => new { Info = i, GenType = i.GetGenericTypeDefinition() }) + .ToArray(); + Type? typeArg = singleTypeGenInterfacesWithGetType + .Where(i => i.GenType == typeof(IOrderedQueryable<>) || i.GenType == typeof(IOrderedEnumerable<>)) + .Select(i => i.Info.GenericTypeArguments[0]) + .Distinct() + .SingleOrDefault(); + if (typeArg != null) + equiv = typeof(IOrderedEnumerable<>).MakeGenericType(typeArg); + else { - var interfacesWithInfo = sourceType.GetInterfaces(); - var singleTypeGenInterfacesWithGetType = interfacesWithInfo - .Where(i => i.IsGenericType && i.GenericTypeArguments.Length == 1) - .Select(i => new { Info = i, GenType = i.GetGenericTypeDefinition() }) - .ToArray(); - Type? typeArg = singleTypeGenInterfacesWithGetType - .Where(i => i.GenType == typeof(IOrderedQueryable<>) || i.GenType == typeof(IOrderedEnumerable<>)) + typeArg = singleTypeGenInterfacesWithGetType + .Where(i => i.GenType == typeof(IQueryable<>) || i.GenType == typeof(IEnumerable<>)) .Select(i => i.Info.GenericTypeArguments[0]) .Distinct() - .SingleOrDefault(); - if (typeArg != null) - return typeof(IOrderedEnumerable<>).MakeGenericType(typeArg); - else - { - typeArg = singleTypeGenInterfacesWithGetType - .Where(i => i.GenType == typeof(IQueryable<>) || i.GenType == typeof(IEnumerable<>)) - .Select(i => i.Info.GenericTypeArguments[0]) - .Distinct() - .Single(); - return typeof(IEnumerable<>).MakeGenericType(typeArg); - } + .Single(); + equiv = typeof(IEnumerable<>).MakeGenericType(typeArg); } } _equivalentTypeCache.Add(type, equiv); @@ -275,9 +262,7 @@ private static MethodInfo FindEnumerableMethodForQueryable(string name, ReadOnly "This is safe because all Queryable methods have a DynamicDependency to the corresponding Enumerable method.")] static MethodInfo[] GetEnumerableStaticMethods(Type type) => type.GetMethods(BindingFlags.Public | BindingFlags.Static); - - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060:MakeGenericMethod", - Justification = "Enumerable methods don't have trim annotations.")] + [RequiresDynamicCodeAttribute("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] MethodInfo ApplyTypeArgs(MethodInfo methodInfo) => typeArgs == null ? methodInfo : methodInfo.MakeGenericMethod(typeArgs); // In certain cases, there might be ambiguities when resolving matching overloads, for example between @@ -335,6 +320,7 @@ static bool AreAssignableFromStrict(ParameterInfo[] left, ParameterInfo[] right) } [RequiresUnreferencedCode(Queryable.InMemoryQueryableExtensionMethodsRequiresUnreferencedCode)] + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] private static MethodInfo FindMethod(Type type, string name, ReadOnlyCollection args, Type[]? typeArgs) { using (IEnumerator en = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).Where(m => m.Name == name).GetEnumerator()) @@ -372,9 +358,7 @@ private static bool ArgsMatch(MethodInfo m, ReadOnlyCollection args, return false; mParams = GetConstrutedGenericParameters(m, typeArgs); - - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060:MakeGenericMethod", - Justification = "MakeGenericMethod is only called to get the parameter types, which are only used to make a 'match' decision. The generic method is not invoked.")] + [RequiresDynamicCodeAttribute("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] static ParameterInfo[] GetConstrutedGenericParameters(MethodInfo method, Type[] genericTypes) => method.MakeGenericMethod(genericTypes).GetParameters(); } @@ -402,6 +386,7 @@ static ParameterInfo[] GetConstrutedGenericParameters(MethodInfo method, Type[] return true; } + [RequiresDynamicCode("Calls System.Type.MakeArrayType()")] private static Type StripExpression(Type type) { bool isArray = type.IsArray; diff --git a/src/libraries/System.Linq.Queryable/src/System/Linq/Queryable.cs b/src/libraries/System.Linq.Queryable/src/System/Linq/Queryable.cs index 48551411c89987..343899581156b8 100644 --- a/src/libraries/System.Linq.Queryable/src/System/Linq/Queryable.cs +++ b/src/libraries/System.Linq.Queryable/src/System/Linq/Queryable.cs @@ -11,8 +11,10 @@ namespace System.Linq public static class Queryable { internal const string InMemoryQueryableExtensionMethodsRequiresUnreferencedCode = "Enumerating in-memory collections as IQueryable can require unreferenced code because expressions referencing IQueryable extension methods can get rebound to IEnumerable extension methods. The IEnumerable extension methods could be trimmed causing the application to fail at runtime."; + internal const string InMemoryQueryableExtensionMethodsRequiresDynamicCode = "Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling."; [RequiresUnreferencedCode(InMemoryQueryableExtensionMethodsRequiresUnreferencedCode)] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable AsQueryable(this IEnumerable source) { ArgumentNullException.ThrowIfNull(source); @@ -21,6 +23,7 @@ public static IQueryable AsQueryable(this IEnumerable Where(this IQueryable source, Expression> predicate) { ArgumentNullException.ThrowIfNull(source); @@ -54,6 +58,7 @@ public static IQueryable Where(this IQueryable source } [DynamicDependency("Where`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Where(this IQueryable source, Expression> predicate) { ArgumentNullException.ThrowIfNull(source); @@ -68,6 +73,7 @@ public static IQueryable Where(this IQueryable source } [DynamicDependency("OfType`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable OfType(this IQueryable source) { ArgumentNullException.ThrowIfNull(source); @@ -79,6 +85,7 @@ public static IQueryable OfType(this IQueryable source) } [DynamicDependency("Cast`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Cast(this IQueryable source) { ArgumentNullException.ThrowIfNull(source); @@ -90,6 +97,7 @@ public static IQueryable Cast(this IQueryable source) } [DynamicDependency("Select`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Select(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -104,6 +112,7 @@ public static IQueryable Select(this IQueryable Select(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -118,6 +127,7 @@ public static IQueryable Select(this IQueryable SelectMany(this IQueryable source, Expression>> selector) { ArgumentNullException.ThrowIfNull(source); @@ -132,6 +142,7 @@ public static IQueryable SelectMany(this IQueryable SelectMany(this IQueryable source, Expression>> selector) { ArgumentNullException.ThrowIfNull(source); @@ -146,6 +157,7 @@ public static IQueryable SelectMany(this IQueryable SelectMany(this IQueryable source, Expression>> collectionSelector, Expression> resultSelector) { ArgumentNullException.ThrowIfNull(source); @@ -161,6 +173,7 @@ public static IQueryable SelectMany(this } [DynamicDependency("SelectMany`3", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable SelectMany(this IQueryable source, Expression>> collectionSelector, Expression> resultSelector) { ArgumentNullException.ThrowIfNull(source); @@ -182,6 +195,7 @@ private static Expression GetSourceExpression(IEnumerable sour } [DynamicDependency("Join`4", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Join(this IQueryable outer, IEnumerable inner, Expression> outerKeySelector, Expression> innerKeySelector, Expression> resultSelector) { ArgumentNullException.ThrowIfNull(outer); @@ -197,6 +211,7 @@ public static IQueryable Join(this IQuer } [DynamicDependency("Join`4", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Join(this IQueryable outer, IEnumerable inner, Expression> outerKeySelector, Expression> innerKeySelector, Expression> resultSelector, IEqualityComparer? comparer) { ArgumentNullException.ThrowIfNull(outer); @@ -212,6 +227,7 @@ public static IQueryable Join(this IQuer } [DynamicDependency("GroupJoin`4", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable GroupJoin(this IQueryable outer, IEnumerable inner, Expression> outerKeySelector, Expression> innerKeySelector, Expression, TResult>> resultSelector) { ArgumentNullException.ThrowIfNull(outer); @@ -227,6 +243,7 @@ public static IQueryable GroupJoin(this } [DynamicDependency("GroupJoin`4", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable GroupJoin(this IQueryable outer, IEnumerable inner, Expression> outerKeySelector, Expression> innerKeySelector, Expression, TResult>> resultSelector, IEqualityComparer? comparer) { ArgumentNullException.ThrowIfNull(outer); @@ -266,6 +283,7 @@ public static IQueryable GroupJoin(this /// The expected behavior is that it sorts the elements of by itself. /// [DynamicDependency("Order`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IOrderedQueryable Order(this IQueryable source) { ArgumentNullException.ThrowIfNull(source); @@ -304,6 +322,7 @@ public static IOrderedQueryable Order(this IQueryable source) /// The expected behavior is that it sorts the elements of by itself. /// [DynamicDependency("Order`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IOrderedQueryable Order(this IQueryable source, IComparer comparer) { ArgumentNullException.ThrowIfNull(source); @@ -317,6 +336,7 @@ public static IOrderedQueryable Order(this IQueryable source, IComparer } [DynamicDependency("OrderBy`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IOrderedQueryable OrderBy(this IQueryable source, Expression> keySelector) { ArgumentNullException.ThrowIfNull(source); @@ -331,6 +351,7 @@ public static IOrderedQueryable OrderBy(this IQueryable< } [DynamicDependency("OrderBy`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IOrderedQueryable OrderBy(this IQueryable source, Expression> keySelector, IComparer? comparer) { ArgumentNullException.ThrowIfNull(source); @@ -369,6 +390,7 @@ public static IOrderedQueryable OrderBy(this IQueryable< /// The expected behavior is that it sorts the elements of by itself. /// [DynamicDependency("OrderDescending`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IOrderedQueryable OrderDescending(this IQueryable source) { ArgumentNullException.ThrowIfNull(source); @@ -407,6 +429,7 @@ public static IOrderedQueryable OrderDescending(this IQueryable source) /// The expected behavior is that it sorts the elements of by itself. /// [DynamicDependency("OrderDescending`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IOrderedQueryable OrderDescending(this IQueryable source, IComparer comparer) { ArgumentNullException.ThrowIfNull(source); @@ -420,6 +443,7 @@ public static IOrderedQueryable OrderDescending(this IQueryable source, } [DynamicDependency("OrderByDescending`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IOrderedQueryable OrderByDescending(this IQueryable source, Expression> keySelector) { ArgumentNullException.ThrowIfNull(source); @@ -434,6 +458,7 @@ public static IOrderedQueryable OrderByDescending(this I } [DynamicDependency("OrderByDescending`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IOrderedQueryable OrderByDescending(this IQueryable source, Expression> keySelector, IComparer? comparer) { ArgumentNullException.ThrowIfNull(source); @@ -448,6 +473,7 @@ public static IOrderedQueryable OrderByDescending(this I } [DynamicDependency("ThenBy`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IOrderedQueryable ThenBy(this IOrderedQueryable source, Expression> keySelector) { ArgumentNullException.ThrowIfNull(source); @@ -462,6 +488,7 @@ public static IOrderedQueryable ThenBy(this IOrderedQuer } [DynamicDependency("ThenBy`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IOrderedQueryable ThenBy(this IOrderedQueryable source, Expression> keySelector, IComparer? comparer) { ArgumentNullException.ThrowIfNull(source); @@ -476,6 +503,7 @@ public static IOrderedQueryable ThenBy(this IOrderedQuer } [DynamicDependency("ThenByDescending`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IOrderedQueryable ThenByDescending(this IOrderedQueryable source, Expression> keySelector) { ArgumentNullException.ThrowIfNull(source); @@ -490,6 +518,7 @@ public static IOrderedQueryable ThenByDescending(this IO } [DynamicDependency("ThenByDescending`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IOrderedQueryable ThenByDescending(this IOrderedQueryable source, Expression> keySelector, IComparer? comparer) { ArgumentNullException.ThrowIfNull(source); @@ -504,6 +533,7 @@ public static IOrderedQueryable ThenByDescending(this IO } [DynamicDependency("Take`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Take(this IQueryable source, int count) { ArgumentNullException.ThrowIfNull(source); @@ -523,6 +553,7 @@ public static IQueryable Take(this IQueryable source, /// is . /// An that contains the specified of elements from the sequence. [DynamicDependency("Take`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Take(this IQueryable source, Range range) { ArgumentNullException.ThrowIfNull(source); @@ -536,6 +567,7 @@ public static IQueryable Take(this IQueryable source, } [DynamicDependency("TakeWhile`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable TakeWhile(this IQueryable source, Expression> predicate) { ArgumentNullException.ThrowIfNull(source); @@ -550,6 +582,7 @@ public static IQueryable TakeWhile(this IQueryable so } [DynamicDependency("TakeWhile`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable TakeWhile(this IQueryable source, Expression> predicate) { ArgumentNullException.ThrowIfNull(source); @@ -564,6 +597,7 @@ public static IQueryable TakeWhile(this IQueryable so } [DynamicDependency("Skip`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Skip(this IQueryable source, int count) { ArgumentNullException.ThrowIfNull(source); @@ -577,6 +611,7 @@ public static IQueryable Skip(this IQueryable source, } [DynamicDependency("SkipWhile`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable SkipWhile(this IQueryable source, Expression> predicate) { ArgumentNullException.ThrowIfNull(source); @@ -591,6 +626,7 @@ public static IQueryable SkipWhile(this IQueryable so } [DynamicDependency("SkipWhile`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable SkipWhile(this IQueryable source, Expression> predicate) { ArgumentNullException.ThrowIfNull(source); @@ -605,6 +641,7 @@ public static IQueryable SkipWhile(this IQueryable so } [DynamicDependency("GroupBy`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable> GroupBy(this IQueryable source, Expression> keySelector) { ArgumentNullException.ThrowIfNull(source); @@ -619,6 +656,7 @@ public static IQueryable> GroupBy(this I } [DynamicDependency("GroupBy`3", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable> GroupBy(this IQueryable source, Expression> keySelector, Expression> elementSelector) { ArgumentNullException.ThrowIfNull(source); @@ -634,6 +672,7 @@ public static IQueryable> GroupBy> GroupBy(this IQueryable source, Expression> keySelector, IEqualityComparer? comparer) { ArgumentNullException.ThrowIfNull(source); @@ -648,6 +687,7 @@ public static IQueryable> GroupBy(this I } [DynamicDependency("GroupBy`3", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable> GroupBy(this IQueryable source, Expression> keySelector, Expression> elementSelector, IEqualityComparer? comparer) { ArgumentNullException.ThrowIfNull(source); @@ -661,6 +701,7 @@ public static IQueryable> GroupBy GroupBy(this IQueryable source, Expression> keySelector, Expression> elementSelector, Expression, TResult>> resultSelector) { ArgumentNullException.ThrowIfNull(source); @@ -675,6 +716,7 @@ public static IQueryable GroupBy(this } [DynamicDependency("GroupBy`3", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable GroupBy(this IQueryable source, Expression> keySelector, Expression, TResult>> resultSelector) { ArgumentNullException.ThrowIfNull(source); @@ -690,6 +732,7 @@ public static IQueryable GroupBy(this IQueryabl } [DynamicDependency("GroupBy`3", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable GroupBy(this IQueryable source, Expression> keySelector, Expression, TResult>> resultSelector, IEqualityComparer? comparer) { ArgumentNullException.ThrowIfNull(source); @@ -703,6 +746,7 @@ public static IQueryable GroupBy(this IQueryabl } [DynamicDependency("GroupBy`4", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable GroupBy(this IQueryable source, Expression> keySelector, Expression> elementSelector, Expression, TResult>> resultSelector, IEqualityComparer? comparer) { ArgumentNullException.ThrowIfNull(source); @@ -717,6 +761,7 @@ public static IQueryable GroupBy(this } [DynamicDependency("Distinct`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Distinct(this IQueryable source) { ArgumentNullException.ThrowIfNull(source); @@ -728,6 +773,7 @@ public static IQueryable Distinct(this IQueryable sou } [DynamicDependency("Distinct`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Distinct(this IQueryable source, IEqualityComparer? comparer) { ArgumentNullException.ThrowIfNull(source); @@ -748,6 +794,7 @@ public static IQueryable Distinct(this IQueryable sou /// An that contains distinct elements from the source sequence. /// is . [DynamicDependency("DistinctBy`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable DistinctBy(this IQueryable source, Expression> keySelector) { ArgumentNullException.ThrowIfNull(source); @@ -770,6 +817,7 @@ public static IQueryable DistinctBy(this IQueryableAn that contains distinct elements from the source sequence. /// is . [DynamicDependency("DistinctBy`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable DistinctBy(this IQueryable source, Expression> keySelector, IEqualityComparer? comparer) { ArgumentNullException.ThrowIfNull(source); @@ -795,6 +843,7 @@ public static IQueryable DistinctBy(this IQueryableThe last chunk will contain the remaining elements and may be of a smaller size. /// [DynamicDependency("Chunk`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Chunk(this IQueryable source, int size) { ArgumentNullException.ThrowIfNull(source); @@ -808,6 +857,7 @@ public static IQueryable Chunk(this IQueryable sour } [DynamicDependency("Concat`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Concat(this IQueryable source1, IEnumerable source2) { ArgumentNullException.ThrowIfNull(source1); @@ -822,6 +872,7 @@ public static IQueryable Concat(this IQueryable sourc } [DynamicDependency("Zip`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable<(TFirst First, TSecond Second)> Zip(this IQueryable source1, IEnumerable source2) { ArgumentNullException.ThrowIfNull(source1); @@ -835,6 +886,7 @@ public static IQueryable Concat(this IQueryable sourc } [DynamicDependency("Zip`3", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Zip(this IQueryable source1, IEnumerable source2, Expression> resultSelector) { ArgumentNullException.ThrowIfNull(source1); @@ -860,6 +912,7 @@ public static IQueryable Zip(this IQueryable< /// The third sequence to merge. /// A sequence of tuples with elements taken from the first, second and third sequences, in that order. [DynamicDependency("Zip`3", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable<(TFirst First, TSecond Second, TThird Third)> Zip(this IQueryable source1, IEnumerable source2, IEnumerable source3) { ArgumentNullException.ThrowIfNull(source1); @@ -875,6 +928,7 @@ public static IQueryable Zip(this IQueryable< } [DynamicDependency("Union`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Union(this IQueryable source1, IEnumerable source2) { ArgumentNullException.ThrowIfNull(source1); @@ -889,6 +943,7 @@ public static IQueryable Union(this IQueryable source } [DynamicDependency("Union`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Union(this IQueryable source1, IEnumerable source2, IEqualityComparer? comparer) { ArgumentNullException.ThrowIfNull(source1); @@ -913,6 +968,7 @@ public static IQueryable Union(this IQueryable source /// An that contains the elements from both input sequences, excluding duplicates. /// or is . [DynamicDependency("UnionBy`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable UnionBy(this IQueryable source1, IEnumerable source2, Expression> keySelector) { ArgumentNullException.ThrowIfNull(source1); @@ -937,6 +993,7 @@ public static IQueryable UnionBy(this IQueryableAn that contains the elements from both input sequences, excluding duplicates. /// or is . [DynamicDependency("UnionBy`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable UnionBy(this IQueryable source1, IEnumerable source2, Expression> keySelector, IEqualityComparer? comparer) { ArgumentNullException.ThrowIfNull(source1); @@ -955,6 +1012,7 @@ public static IQueryable UnionBy(this IQueryable Intersect(this IQueryable source1, IEnumerable source2) { ArgumentNullException.ThrowIfNull(source1); @@ -969,6 +1027,7 @@ public static IQueryable Intersect(this IQueryable so } [DynamicDependency("Intersect`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Intersect(this IQueryable source1, IEnumerable source2, IEqualityComparer? comparer) { ArgumentNullException.ThrowIfNull(source1); @@ -993,6 +1052,7 @@ public static IQueryable Intersect(this IQueryable so /// A sequence that contains the elements that form the set intersection of two sequences. /// or is . [DynamicDependency("IntersectBy`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable IntersectBy(this IQueryable source1, IEnumerable source2, Expression> keySelector) { ArgumentNullException.ThrowIfNull(source1); @@ -1019,6 +1079,7 @@ public static IQueryable IntersectBy(this IQueryableA sequence that contains the elements that form the set intersection of two sequences. /// or is . [DynamicDependency("IntersectBy`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable IntersectBy(this IQueryable source1, IEnumerable source2, Expression> keySelector, IEqualityComparer? comparer) { ArgumentNullException.ThrowIfNull(source1); @@ -1037,6 +1098,7 @@ public static IQueryable IntersectBy(this IQueryable Except(this IQueryable source1, IEnumerable source2) { ArgumentNullException.ThrowIfNull(source1); @@ -1051,6 +1113,7 @@ public static IQueryable Except(this IQueryable sourc } [DynamicDependency("Except`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Except(this IQueryable source1, IEnumerable source2, IEqualityComparer? comparer) { ArgumentNullException.ThrowIfNull(source1); @@ -1076,6 +1139,7 @@ public static IQueryable Except(this IQueryable sourc /// A function to extract the key for each element. /// A that contains the set difference of the elements of two sequences. [DynamicDependency("ExceptBy`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable ExceptBy(this IQueryable source1, IEnumerable source2, Expression> keySelector) { ArgumentNullException.ThrowIfNull(source1); @@ -1103,6 +1167,7 @@ public static IQueryable ExceptBy(this IQueryableAn to compare keys. /// A that contains the set difference of the elements of two sequences. [DynamicDependency("ExceptBy`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable ExceptBy(this IQueryable source1, IEnumerable source2, Expression> keySelector, IEqualityComparer? comparer) { ArgumentNullException.ThrowIfNull(source1); @@ -1121,6 +1186,7 @@ public static IQueryable ExceptBy(this IQueryable(this IQueryable source) { ArgumentNullException.ThrowIfNull(source); @@ -1132,6 +1198,7 @@ public static TSource First(this IQueryable source) } [DynamicDependency("First`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource First(this IQueryable source, Expression> predicate) { ArgumentNullException.ThrowIfNull(source); @@ -1146,6 +1213,7 @@ public static TSource First(this IQueryable source, Expression } [DynamicDependency("FirstOrDefault`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource? FirstOrDefault(this IQueryable source) { ArgumentNullException.ThrowIfNull(source); @@ -1163,6 +1231,7 @@ public static TSource First(this IQueryable source, Expression /// if is empty; otherwise, the first element in . /// is . [DynamicDependency("FirstOrDefault`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource FirstOrDefault(this IQueryable source, TSource defaultValue) { ArgumentNullException.ThrowIfNull(source); @@ -1175,6 +1244,7 @@ public static TSource FirstOrDefault(this IQueryable source, T } [DynamicDependency("FirstOrDefault`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource? FirstOrDefault(this IQueryable source, Expression> predicate) { ArgumentNullException.ThrowIfNull(source); @@ -1196,6 +1266,7 @@ public static TSource FirstOrDefault(this IQueryable source, T /// if is empty or if no element passes the test specified by ; otherwise, the first element in that passes the test specified by . /// or is . [DynamicDependency("FirstOrDefault`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource FirstOrDefault(this IQueryable source, Expression> predicate, TSource defaultValue) { ArgumentNullException.ThrowIfNull(source); @@ -1210,6 +1281,7 @@ public static TSource FirstOrDefault(this IQueryable source, E } [DynamicDependency("Last`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource Last(this IQueryable source) { ArgumentNullException.ThrowIfNull(source); @@ -1221,6 +1293,7 @@ public static TSource Last(this IQueryable source) } [DynamicDependency("Last`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource Last(this IQueryable source, Expression> predicate) { ArgumentNullException.ThrowIfNull(source); @@ -1235,6 +1308,7 @@ public static TSource Last(this IQueryable source, Expression< } [DynamicDependency("LastOrDefault`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource? LastOrDefault(this IQueryable source) { ArgumentNullException.ThrowIfNull(source); @@ -1252,6 +1326,7 @@ public static TSource Last(this IQueryable source, Expression< /// if the source sequence is empty; otherwise, the last element in the . /// is . [DynamicDependency("LastOrDefault`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource LastOrDefault(this IQueryable source, TSource defaultValue) { ArgumentNullException.ThrowIfNull(source); @@ -1264,6 +1339,7 @@ public static TSource LastOrDefault(this IQueryable source, TS } [DynamicDependency("LastOrDefault`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource? LastOrDefault(this IQueryable source, Expression> predicate) { ArgumentNullException.ThrowIfNull(source); @@ -1285,6 +1361,7 @@ public static TSource LastOrDefault(this IQueryable source, TS /// if the sequence is empty or if no elements pass the test in the predicate function; otherwise, the last element that passes the test in the predicate function. /// or is . [DynamicDependency("LastOrDefault`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource LastOrDefault(this IQueryable source, Expression> predicate, TSource defaultValue) { ArgumentNullException.ThrowIfNull(source); @@ -1299,6 +1376,7 @@ public static TSource LastOrDefault(this IQueryable source, Ex } [DynamicDependency("Single`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource Single(this IQueryable source) { ArgumentNullException.ThrowIfNull(source); @@ -1310,6 +1388,7 @@ public static TSource Single(this IQueryable source) } [DynamicDependency("Single`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource Single(this IQueryable source, Expression> predicate) { ArgumentNullException.ThrowIfNull(source); @@ -1324,6 +1403,7 @@ public static TSource Single(this IQueryable source, Expressio } [DynamicDependency("SingleOrDefault`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource? SingleOrDefault(this IQueryable source) { ArgumentNullException.ThrowIfNull(source); @@ -1342,6 +1422,7 @@ public static TSource Single(this IQueryable source, Expressio /// is . /// The input sequence contains more than one element. [DynamicDependency("SingleOrDefault`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource SingleOrDefault(this IQueryable source, TSource defaultValue) { ArgumentNullException.ThrowIfNull(source); @@ -1354,6 +1435,7 @@ public static TSource SingleOrDefault(this IQueryable source, } [DynamicDependency("SingleOrDefault`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource? SingleOrDefault(this IQueryable source, Expression> predicate) { ArgumentNullException.ThrowIfNull(source); @@ -1376,6 +1458,7 @@ public static TSource SingleOrDefault(this IQueryable source, /// or is . /// More than one element satisfies the condition in . [DynamicDependency("SingleOrDefault`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource SingleOrDefault(this IQueryable source, Expression> predicate, TSource defaultValue) { ArgumentNullException.ThrowIfNull(source); @@ -1390,6 +1473,7 @@ public static TSource SingleOrDefault(this IQueryable source, } [DynamicDependency("ElementAt`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource ElementAt(this IQueryable source, int index) { ArgumentNullException.ThrowIfNull(source); @@ -1413,6 +1497,7 @@ public static TSource ElementAt(this IQueryable source, int in /// is outside the bounds of the sequence. /// The element at the specified position in the sequence. [DynamicDependency("ElementAt`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource ElementAt(this IQueryable source, Index index) { ArgumentNullException.ThrowIfNull(source); @@ -1429,6 +1514,7 @@ public static TSource ElementAt(this IQueryable source, Index } [DynamicDependency("ElementAtOrDefault`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource? ElementAtOrDefault(this IQueryable source, int index) { ArgumentNullException.ThrowIfNull(source); @@ -1448,6 +1534,7 @@ public static TSource ElementAt(this IQueryable source, Index /// is . /// if is outside the bounds of the sequence; otherwise, the element at the specified position in the sequence. [DynamicDependency("ElementAtOrDefault`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource? ElementAtOrDefault(this IQueryable source, Index index) { ArgumentNullException.ThrowIfNull(source); @@ -1461,6 +1548,7 @@ public static TSource ElementAt(this IQueryable source, Index } [DynamicDependency("DefaultIfEmpty`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable DefaultIfEmpty(this IQueryable source) { ArgumentNullException.ThrowIfNull(source); @@ -1472,6 +1560,7 @@ public static TSource ElementAt(this IQueryable source, Index } [DynamicDependency("DefaultIfEmpty`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable DefaultIfEmpty(this IQueryable source, TSource defaultValue) { ArgumentNullException.ThrowIfNull(source); @@ -1485,6 +1574,7 @@ public static IQueryable DefaultIfEmpty(this IQueryable(this IQueryable source, TSource item) { ArgumentNullException.ThrowIfNull(source); @@ -1498,6 +1588,7 @@ public static bool Contains(this IQueryable source, TSource it } [DynamicDependency("Contains`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static bool Contains(this IQueryable source, TSource item, IEqualityComparer? comparer) { ArgumentNullException.ThrowIfNull(source); @@ -1511,6 +1602,7 @@ public static bool Contains(this IQueryable source, TSource it } [DynamicDependency("Reverse`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Reverse(this IQueryable source) { ArgumentNullException.ThrowIfNull(source); @@ -1522,6 +1614,7 @@ public static IQueryable Reverse(this IQueryable sour } [DynamicDependency("SequenceEqual`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static bool SequenceEqual(this IQueryable source1, IEnumerable source2) { ArgumentNullException.ThrowIfNull(source1); @@ -1536,6 +1629,7 @@ public static bool SequenceEqual(this IQueryable source1, IEnu } [DynamicDependency("SequenceEqual`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static bool SequenceEqual(this IQueryable source1, IEnumerable source2, IEqualityComparer? comparer) { ArgumentNullException.ThrowIfNull(source1); @@ -1552,6 +1646,7 @@ public static bool SequenceEqual(this IQueryable source1, IEnu } [DynamicDependency("Any`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static bool Any(this IQueryable source) { ArgumentNullException.ThrowIfNull(source); @@ -1563,6 +1658,7 @@ public static bool Any(this IQueryable source) } [DynamicDependency("Any`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static bool Any(this IQueryable source, Expression> predicate) { ArgumentNullException.ThrowIfNull(source); @@ -1577,6 +1673,7 @@ public static bool Any(this IQueryable source, Expression(this IQueryable source, Expression> predicate) { ArgumentNullException.ThrowIfNull(source); @@ -1591,6 +1688,7 @@ public static bool All(this IQueryable source, Expression(this IQueryable source) { ArgumentNullException.ThrowIfNull(source); @@ -1602,6 +1700,7 @@ public static int Count(this IQueryable source) } [DynamicDependency("Count`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static int Count(this IQueryable source, Expression> predicate) { ArgumentNullException.ThrowIfNull(source); @@ -1616,6 +1715,7 @@ public static int Count(this IQueryable source, Expression(this IQueryable source) { ArgumentNullException.ThrowIfNull(source); @@ -1627,6 +1727,7 @@ public static long LongCount(this IQueryable source) } [DynamicDependency("LongCount`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static long LongCount(this IQueryable source, Expression> predicate) { ArgumentNullException.ThrowIfNull(source); @@ -1641,6 +1742,7 @@ public static long LongCount(this IQueryable source, Expressio } [DynamicDependency("Min`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource? Min(this IQueryable source) { ArgumentNullException.ThrowIfNull(source); @@ -1659,6 +1761,7 @@ public static long LongCount(this IQueryable source, Expressio /// is . /// No object in implements the or interface. [DynamicDependency("Min`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource? Min(this IQueryable source, IComparer? comparer) { ArgumentNullException.ThrowIfNull(source); @@ -1673,6 +1776,7 @@ public static long LongCount(this IQueryable source, Expressio } [DynamicDependency("Min`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TResult? Min(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -1695,6 +1799,7 @@ public static long LongCount(this IQueryable source, Expressio /// is . /// No key extracted from implements the or interface. [DynamicDependency("MinBy`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource? MinBy(this IQueryable source, Expression> keySelector) { ArgumentNullException.ThrowIfNull(source); @@ -1719,6 +1824,7 @@ public static long LongCount(this IQueryable source, Expressio /// is . /// No key extracted from implements the or interface. [DynamicDependency("MinBy`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource? MinBy(this IQueryable source, Expression> keySelector, IComparer? comparer) { ArgumentNullException.ThrowIfNull(source); @@ -1735,6 +1841,7 @@ public static long LongCount(this IQueryable source, Expressio } [DynamicDependency("Max`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource? Max(this IQueryable source) { ArgumentNullException.ThrowIfNull(source); @@ -1752,6 +1859,7 @@ public static long LongCount(this IQueryable source, Expressio /// The maximum value in the sequence. /// is . [DynamicDependency("Max`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource? Max(this IQueryable source, IComparer? comparer) { ArgumentNullException.ThrowIfNull(source); @@ -1766,6 +1874,7 @@ public static long LongCount(this IQueryable source, Expressio } [DynamicDependency("Max`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TResult? Max(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -1788,6 +1897,7 @@ public static long LongCount(this IQueryable source, Expressio /// is . /// No key extracted from implements the or interface. [DynamicDependency("MaxBy`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource? MaxBy(this IQueryable source, Expression> keySelector) { ArgumentNullException.ThrowIfNull(source); @@ -1812,6 +1922,7 @@ public static long LongCount(this IQueryable source, Expressio /// is . /// No key extracted from implements the or interface. [DynamicDependency("MaxBy`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource? MaxBy(this IQueryable source, Expression> keySelector, IComparer? comparer) { ArgumentNullException.ThrowIfNull(source); @@ -1938,6 +2049,7 @@ public static decimal Sum(this IQueryable source) } [DynamicDependency("Sum`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static int Sum(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -1952,6 +2064,7 @@ public static int Sum(this IQueryable source, Expression(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -1966,6 +2079,7 @@ public static int Sum(this IQueryable source, Expression(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -1980,6 +2094,7 @@ public static long Sum(this IQueryable source, Expression(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -1994,6 +2109,7 @@ public static long Sum(this IQueryable source, Expression(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -2008,6 +2124,7 @@ public static float Sum(this IQueryable source, Expression(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -2022,6 +2139,7 @@ public static float Sum(this IQueryable source, Expression(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -2036,6 +2154,7 @@ public static double Sum(this IQueryable source, Expression(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -2050,6 +2169,7 @@ public static double Sum(this IQueryable source, Expression(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -2064,6 +2184,7 @@ public static decimal Sum(this IQueryable source, Expression(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -2188,6 +2309,7 @@ public static decimal Average(this IQueryable source) } [DynamicDependency("Average`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static double Average(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -2202,6 +2324,7 @@ public static double Average(this IQueryable source, Expressio } [DynamicDependency("Average`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static double? Average(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -2216,6 +2339,7 @@ public static double Average(this IQueryable source, Expressio } [DynamicDependency("Average`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static float Average(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -2230,6 +2354,7 @@ public static float Average(this IQueryable source, Expression } [DynamicDependency("Average`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static float? Average(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -2244,6 +2369,7 @@ public static float Average(this IQueryable source, Expression } [DynamicDependency("Average`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static double Average(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -2258,6 +2384,7 @@ public static double Average(this IQueryable source, Expressio } [DynamicDependency("Average`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static double? Average(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -2272,6 +2399,7 @@ public static double Average(this IQueryable source, Expressio } [DynamicDependency("Average`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static double Average(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -2286,6 +2414,7 @@ public static double Average(this IQueryable source, Expressio } [DynamicDependency("Average`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static double? Average(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -2300,6 +2429,7 @@ public static double Average(this IQueryable source, Expressio } [DynamicDependency("Average`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static decimal Average(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -2314,6 +2444,7 @@ public static decimal Average(this IQueryable source, Expressi } [DynamicDependency("Average`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static decimal? Average(this IQueryable source, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -2328,6 +2459,7 @@ public static decimal Average(this IQueryable source, Expressi } [DynamicDependency("Aggregate`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TSource Aggregate(this IQueryable source, Expression> func) { ArgumentNullException.ThrowIfNull(source); @@ -2342,6 +2474,7 @@ public static TSource Aggregate(this IQueryable source, Expres } [DynamicDependency("Aggregate`2", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static TAccumulate Aggregate(this IQueryable source, TAccumulate seed, Expression> func) { ArgumentNullException.ThrowIfNull(source); @@ -2356,6 +2489,7 @@ public static TAccumulate Aggregate(this IQueryable(this IQueryable source, TAccumulate seed, Expression> func, Expression> selector) { ArgumentNullException.ThrowIfNull(source); @@ -2369,6 +2503,7 @@ public static TResult Aggregate(this IQueryable SkipLast(this IQueryable source, int count) { ArgumentNullException.ThrowIfNull(source); @@ -2382,6 +2517,7 @@ public static IQueryable SkipLast(this IQueryable sou } [DynamicDependency("TakeLast`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable TakeLast(this IQueryable source, int count) { ArgumentNullException.ThrowIfNull(source); @@ -2395,6 +2531,7 @@ public static IQueryable TakeLast(this IQueryable sou } [DynamicDependency("Append`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Append(this IQueryable source, TSource element) { ArgumentNullException.ThrowIfNull(source); @@ -2408,6 +2545,7 @@ public static IQueryable Append(this IQueryable sourc } [DynamicDependency("Prepend`1", typeof(Enumerable))] + [RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)] public static IQueryable Prepend(this IQueryable source, TSource element) { ArgumentNullException.ThrowIfNull(source); diff --git a/src/libraries/System.Net.NetworkInformation/ref/System.Net.NetworkInformation.cs b/src/libraries/System.Net.NetworkInformation/ref/System.Net.NetworkInformation.cs index df04b533cca1b0..da345adb5929c7 100644 --- a/src/libraries/System.Net.NetworkInformation/ref/System.Net.NetworkInformation.cs +++ b/src/libraries/System.Net.NetworkInformation/ref/System.Net.NetworkInformation.cs @@ -46,9 +46,25 @@ protected IcmpV4Statistics() { } public abstract long EchoRepliesSent { get; } public abstract long EchoRequestsReceived { get; } public abstract long EchoRequestsSent { get; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("freebsd")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("osx")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public abstract long ErrorsReceived { get; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("freebsd")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("osx")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public abstract long ErrorsSent { get; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("freebsd")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("osx")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public abstract long MessagesReceived { get; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("freebsd")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("osx")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public abstract long MessagesSent { get; } public abstract long ParameterProblemsReceived { get; } public abstract long ParameterProblemsSent { get; } @@ -72,7 +88,15 @@ protected IcmpV6Statistics() { } public abstract long EchoRepliesSent { get; } public abstract long EchoRequestsReceived { get; } public abstract long EchoRequestsSent { get; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("freebsd")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("osx")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public abstract long ErrorsReceived { get; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("freebsd")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("osx")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public abstract long ErrorsSent { get; } public abstract long MembershipQueriesReceived { get; } public abstract long MembershipQueriesSent { get; } @@ -80,7 +104,15 @@ protected IcmpV6Statistics() { } public abstract long MembershipReductionsSent { get; } public abstract long MembershipReportsReceived { get; } public abstract long MembershipReportsSent { get; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("freebsd")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("osx")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public abstract long MessagesReceived { get; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("freebsd")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("osx")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public abstract long MessagesSent { get; } public abstract long NeighborAdvertisementsReceived { get; } public abstract long NeighborAdvertisementsSent { get; } @@ -103,7 +135,9 @@ public abstract partial class IPAddressInformation { protected IPAddressInformation() { } public abstract System.Net.IPAddress Address { get; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public abstract bool IsDnsEligible { get; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public abstract bool IsTransient { get; } } public partial class IPAddressInformationCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable @@ -123,37 +157,41 @@ public virtual void CopyTo(System.Net.NetworkInformation.IPAddressInformation[] public abstract partial class IPGlobalProperties { protected IPGlobalProperties() { } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract string DhcpScopeName { get; } public abstract string DomainName { get; } public abstract string HostName { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract bool IsWinsProxy { get; } public abstract System.Net.NetworkInformation.NetBiosNodeType NodeType { get; } public virtual System.IAsyncResult BeginGetUnicastAddresses(System.AsyncCallback? callback, object? state) { throw null; } public virtual System.Net.NetworkInformation.UnicastIPAddressInformationCollection EndGetUnicastAddresses(System.IAsyncResult asyncResult) { throw null; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract System.Net.NetworkInformation.TcpConnectionInformation[] GetActiveTcpConnections(); - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract System.Net.IPEndPoint[] GetActiveTcpListeners(); - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract System.Net.IPEndPoint[] GetActiveUdpListeners(); - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract System.Net.NetworkInformation.IcmpV4Statistics GetIcmpV4Statistics(); - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract System.Net.NetworkInformation.IcmpV6Statistics GetIcmpV6Statistics(); - [System.Runtime.Versioning.UnsupportedOSPlatform("illumos")] - [System.Runtime.Versioning.UnsupportedOSPlatform("solaris")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("illumos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("solaris")] public static System.Net.NetworkInformation.IPGlobalProperties GetIPGlobalProperties() { throw null; } public abstract System.Net.NetworkInformation.IPGlobalStatistics GetIPv4GlobalStatistics(); + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("freebsd")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("osx")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public abstract System.Net.NetworkInformation.IPGlobalStatistics GetIPv6GlobalStatistics(); - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract System.Net.NetworkInformation.TcpStatistics GetTcpIPv4Statistics(); - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract System.Net.NetworkInformation.TcpStatistics GetTcpIPv6Statistics(); - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract System.Net.NetworkInformation.UdpStatistics GetUdpIPv4Statistics(); - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract System.Net.NetworkInformation.UdpStatistics GetUdpIPv6Statistics(); public virtual System.Net.NetworkInformation.UnicastIPAddressInformationCollection GetUnicastAddresses() { throw null; } public virtual System.Threading.Tasks.Task GetUnicastAddressesAsync() { throw null; } @@ -161,69 +199,81 @@ protected IPGlobalProperties() { } public abstract partial class IPGlobalStatistics { protected IPGlobalStatistics() { } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract int DefaultTtl { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract bool ForwardingEnabled { get; } public abstract int NumberOfInterfaces { get; } public abstract int NumberOfIPAddresses { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract int NumberOfRoutes { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract long OutputPacketRequests { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract long OutputPacketRoutingDiscards { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract long OutputPacketsDiscarded { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract long OutputPacketsWithNoRoute { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract long PacketFragmentFailures { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract long PacketReassembliesRequired { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract long PacketReassemblyFailures { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract long PacketReassemblyTimeout { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract long PacketsFragmented { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract long PacketsReassembled { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract long ReceivedPackets { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract long ReceivedPacketsDelivered { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract long ReceivedPacketsDiscarded { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract long ReceivedPacketsForwarded { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract long ReceivedPacketsWithAddressErrors { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract long ReceivedPacketsWithHeadersErrors { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract long ReceivedPacketsWithUnknownProtocol { get; } } public abstract partial class IPInterfaceProperties { protected IPInterfaceProperties() { } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public abstract System.Net.NetworkInformation.IPAddressInformationCollection AnycastAddresses { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("freebsd")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("osx")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public abstract System.Net.NetworkInformation.IPAddressCollection DhcpServerAddresses { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract System.Net.NetworkInformation.IPAddressCollection DnsAddresses { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract string DnsSuffix { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public abstract System.Net.NetworkInformation.GatewayIPAddressInformationCollection GatewayAddresses { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("freebsd")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("osx")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public abstract bool IsDnsEnabled { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public abstract bool IsDynamicDnsEnabled { get; } public abstract System.Net.NetworkInformation.MulticastIPAddressInformationCollection MulticastAddresses { get; } public abstract System.Net.NetworkInformation.UnicastIPAddressInformationCollection UnicastAddresses { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("freebsd")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("osx")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public abstract System.Net.NetworkInformation.IPAddressCollection WinsServersAddresses { get; } public abstract System.Net.NetworkInformation.IPv4InterfaceProperties GetIPv4Properties(); public abstract System.Net.NetworkInformation.IPv6InterfaceProperties GetIPv6Properties(); @@ -235,13 +285,15 @@ protected IPInterfaceStatistics() { } public abstract long BytesSent { get; } public abstract long IncomingPacketsDiscarded { get; } public abstract long IncomingPacketsWithErrors { get; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("linux")] public abstract long IncomingUnknownProtocolPackets { get; } public abstract long NonUnicastPacketsReceived { get; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("linux")] public abstract long NonUnicastPacketsSent { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("osx")] - [System.Runtime.Versioning.UnsupportedOSPlatform("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatform("tvos")] - [System.Runtime.Versioning.UnsupportedOSPlatform("freebsd")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("freebsd")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("osx")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public abstract long OutgoingPacketsDiscarded { get; } public abstract long OutgoingPacketsWithErrors { get; } public abstract long OutputQueueLength { get; } @@ -252,16 +304,18 @@ public abstract partial class IPv4InterfaceProperties { protected IPv4InterfaceProperties() { } public abstract int Index { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public abstract bool IsAutomaticPrivateAddressingActive { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public abstract bool IsAutomaticPrivateAddressingEnabled { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public abstract bool IsDhcpEnabled { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("linux")] public abstract bool IsForwardingEnabled { get; } public abstract int Mtu { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("linux")] public abstract bool UsesWins { get; } } public abstract partial class IPv4InterfaceStatistics @@ -274,10 +328,10 @@ protected IPv4InterfaceStatistics() { } public abstract long IncomingUnknownProtocolPackets { get; } public abstract long NonUnicastPacketsReceived { get; } public abstract long NonUnicastPacketsSent { get; } - [System.Runtime.Versioning.UnsupportedOSPlatform("osx")] - [System.Runtime.Versioning.UnsupportedOSPlatform("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatform("tvos")] - [System.Runtime.Versioning.UnsupportedOSPlatform("freebsd")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("freebsd")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("osx")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public abstract long OutgoingPacketsDiscarded { get; } public abstract long OutgoingPacketsWithErrors { get; } public abstract long OutputQueueLength { get; } @@ -289,16 +343,26 @@ public abstract partial class IPv6InterfaceProperties protected IPv6InterfaceProperties() { } public abstract int Index { get; } public abstract int Mtu { get; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("freebsd")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("osx")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public virtual long GetScopeId(System.Net.NetworkInformation.ScopeLevel scopeLevel) { throw null; } } public abstract partial class MulticastIPAddressInformation : System.Net.NetworkInformation.IPAddressInformation { protected MulticastIPAddressInformation() { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public abstract long AddressPreferredLifetime { get; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public abstract long AddressValidLifetime { get; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public abstract long DhcpLeaseLifetime { get; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public abstract System.Net.NetworkInformation.DuplicateAddressDetectionState DuplicateAddressDetectionState { get; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public abstract System.Net.NetworkInformation.PrefixOrigin PrefixOrigin { get; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public abstract System.Net.NetworkInformation.SuffixOrigin SuffixOrigin { get; } } public partial class MulticastIPAddressInformationCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable @@ -335,11 +399,11 @@ public partial class NetworkChange [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] [System.ObsoleteAttribute("This API supports the .NET Framework infrastructure and is not intended to be used directly from your code.", true)] public NetworkChange() { } - [System.Runtime.Versioning.UnsupportedOSPlatform("illumos")] - [System.Runtime.Versioning.UnsupportedOSPlatform("solaris")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("illumos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("solaris")] public static event System.Net.NetworkInformation.NetworkAddressChangedEventHandler? NetworkAddressChanged { add { } remove { } } - [System.Runtime.Versioning.UnsupportedOSPlatform("illumos")] - [System.Runtime.Versioning.UnsupportedOSPlatform("solaris")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("illumos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("solaris")] public static event System.Net.NetworkInformation.NetworkAvailabilityChangedEventHandler? NetworkAvailabilityChanged { add { } remove { } } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] [System.ObsoleteAttribute("This API supports the .NET Framework infrastructure and is not intended to be used directly from your code.", true)] @@ -357,28 +421,28 @@ public abstract partial class NetworkInterface protected NetworkInterface() { } public virtual string Description { get { throw null; } } public virtual string Id { get { throw null; } } - [System.Runtime.Versioning.UnsupportedOSPlatform("illumos")] - [System.Runtime.Versioning.UnsupportedOSPlatform("solaris")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("illumos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("solaris")] public static int IPv6LoopbackInterfaceIndex { get { throw null; } } public virtual bool IsReceiveOnly { get { throw null; } } - [System.Runtime.Versioning.UnsupportedOSPlatform("illumos")] - [System.Runtime.Versioning.UnsupportedOSPlatform("solaris")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("illumos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("solaris")] public static int LoopbackInterfaceIndex { get { throw null; } } public virtual string Name { get { throw null; } } public virtual System.Net.NetworkInformation.NetworkInterfaceType NetworkInterfaceType { get { throw null; } } public virtual System.Net.NetworkInformation.OperationalStatus OperationalStatus { get { throw null; } } public virtual long Speed { get { throw null; } } public virtual bool SupportsMulticast { get { throw null; } } - [System.Runtime.Versioning.UnsupportedOSPlatform("illumos")] - [System.Runtime.Versioning.UnsupportedOSPlatform("solaris")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("illumos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("solaris")] public static System.Net.NetworkInformation.NetworkInterface[] GetAllNetworkInterfaces() { throw null; } public virtual System.Net.NetworkInformation.IPInterfaceProperties GetIPProperties() { throw null; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public virtual System.Net.NetworkInformation.IPInterfaceStatistics GetIPStatistics() { throw null; } - [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] public virtual System.Net.NetworkInformation.IPv4InterfaceStatistics GetIPv4Statistics() { throw null; } - [System.Runtime.Versioning.UnsupportedOSPlatform("illumos")] - [System.Runtime.Versioning.UnsupportedOSPlatform("solaris")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("illumos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("solaris")] public static bool GetIsNetworkAvailable() { throw null; } public virtual System.Net.NetworkInformation.PhysicalAddress GetPhysicalAddress() { throw null; } public virtual bool Supports(System.Net.NetworkInformation.NetworkInterfaceComponent networkInterfaceComponent) { throw null; } @@ -433,14 +497,14 @@ public partial class PhysicalAddress { public static readonly System.Net.NetworkInformation.PhysicalAddress None; public PhysicalAddress(byte[] address) { } - public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] object? comparand) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? comparand) { throw null; } public byte[] GetAddressBytes() { throw null; } public override int GetHashCode() { throw null; } + public static System.Net.NetworkInformation.PhysicalAddress Parse(System.ReadOnlySpan address) { throw null; } public static System.Net.NetworkInformation.PhysicalAddress Parse(string? address) { throw null; } - public static System.Net.NetworkInformation.PhysicalAddress Parse(ReadOnlySpan address) { throw null; } - public static bool TryParse(string? address, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Net.NetworkInformation.PhysicalAddress? value) { throw null; } - public static bool TryParse(ReadOnlySpan address, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Net.NetworkInformation.PhysicalAddress? value) { throw null; } public override string ToString() { throw null; } + public static bool TryParse(System.ReadOnlySpan address, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Net.NetworkInformation.PhysicalAddress? value) { throw null; } + public static bool TryParse(string? address, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Net.NetworkInformation.PhysicalAddress? value) { throw null; } } public enum PrefixOrigin { @@ -523,13 +587,19 @@ protected UdpStatistics() { } public abstract partial class UnicastIPAddressInformation : System.Net.NetworkInformation.IPAddressInformation { protected UnicastIPAddressInformation() { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public abstract long AddressPreferredLifetime { get; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public abstract long AddressValidLifetime { get; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public abstract long DhcpLeaseLifetime { get; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public abstract System.Net.NetworkInformation.DuplicateAddressDetectionState DuplicateAddressDetectionState { get; } public abstract System.Net.IPAddress IPv4Mask { get; } public virtual int PrefixLength { get { throw null; } } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public abstract System.Net.NetworkInformation.PrefixOrigin PrefixOrigin { get; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public abstract System.Net.NetworkInformation.SuffixOrigin SuffixOrigin { get; } } public partial class UnicastIPAddressInformationCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPAddressInformation.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPAddressInformation.cs index 9369864d1315ba..87d0f7db9e4ad9 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPAddressInformation.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPAddressInformation.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.Versioning; + namespace System.Net.NetworkInformation { /// @@ -16,11 +18,13 @@ public abstract class IPAddressInformation /// /// Gets a bool value that indicates whether the Internet Protocol (IP) address is legal to appear in a Domain Name System (DNS) server database. /// + [SupportedOSPlatform("windows")] public abstract bool IsDnsEligible { get; } /// /// Gets a bool value that indicates whether the Internet Protocol (IP) address is transient. /// + [SupportedOSPlatform("windows")] public abstract bool IsTransient { get; } } } diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalProperties.cs index 1371a47d3ed945..1a78c1dd3e8b6b 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalProperties.cs @@ -106,6 +106,10 @@ public virtual UnicastIPAddressInformationCollection EndGetUnicastAddresses(IAsy /// public abstract IPGlobalStatistics GetIPv4GlobalStatistics(); + [UnsupportedOSPlatform("osx")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("freebsd")] public abstract IPGlobalStatistics GetIPv6GlobalStatistics(); public virtual UnicastIPAddressInformationCollection GetUnicastAddresses() diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPInterfaceProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPInterfaceProperties.cs index 863737ce18f6d3..33aa2ae654bc28 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPInterfaceProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPInterfaceProperties.cs @@ -15,6 +15,10 @@ public abstract class IPInterfaceProperties /// Gets a bool value that indicates whether this interface is configured to send name resolution queries to a Domain Name System (DNS) server. /// [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("osx")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("freebsd")] public abstract bool IsDnsEnabled { get; } /// @@ -26,7 +30,7 @@ public abstract class IPInterfaceProperties /// /// Gets a bool value that indicates whether this interface is configured to automatically register its IP address information with the Domain Name System (DNS). /// - [UnsupportedOSPlatform("android")] + [SupportedOSPlatform("windows")] public abstract bool IsDynamicDnsEnabled { get; } /// @@ -42,7 +46,7 @@ public abstract class IPInterfaceProperties /// /// The address identifies multiple computers. Packets sent to an anycast address are sent to one of the computers identified by the address. /// - [UnsupportedOSPlatform("android")] + [SupportedOSPlatform("windows")] public abstract IPAddressInformationCollection AnycastAddresses { get; } /// @@ -61,12 +65,20 @@ public abstract class IPInterfaceProperties /// Gets the addresses for Dynamic Host Configuration Protocol (DHCP) servers. /// [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("osx")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("freebsd")] public abstract IPAddressCollection DhcpServerAddresses { get; } /// /// Gets the list of Wins Servers registered with this interface /// [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("osx")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("freebsd")] public abstract IPAddressCollection WinsServersAddresses { get; } /// diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPInterfaceStatistics.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPInterfaceStatistics.cs index 4570a7b757ce29..85e5ef284430be 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPInterfaceStatistics.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPInterfaceStatistics.cs @@ -34,6 +34,7 @@ public abstract class IPInterfaceStatistics /// /// Gets the number of incoming packets with an unknown protocol. /// + [UnsupportedOSPlatform("linux")] public abstract long IncomingUnknownProtocolPackets { get; } /// @@ -44,6 +45,7 @@ public abstract class IPInterfaceStatistics /// /// Gets the number of non-unicast packets sent on the interface. /// + [UnsupportedOSPlatform("linux")] public abstract long NonUnicastPacketsSent { get; } /// diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPv4InterfaceProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPv4InterfaceProperties.cs index 9f9d0b1e3766dd..687902f08e6659 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPv4InterfaceProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPv4InterfaceProperties.cs @@ -13,25 +13,26 @@ public abstract class IPv4InterfaceProperties /// /// Gets a bool value that indicates whether an interface uses Windows Internet Name Service (WINS). /// - [UnsupportedOSPlatform("android")] + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("linux")] public abstract bool UsesWins { get; } /// /// Gets a bool value that indicates whether the interface is configured to use a dynamic host configuration protocol (DHCP) server to obtain an IP address. /// - [UnsupportedOSPlatform("android")] + [SupportedOSPlatform("windows")] public abstract bool IsDhcpEnabled { get; } /// /// Gets a bool value that indicates whether this interface has an automatic private IP addressing (APIPA) address. /// - [UnsupportedOSPlatform("android")] + [SupportedOSPlatform("windows")] public abstract bool IsAutomaticPrivateAddressingActive { get; } /// /// Gets a bool value that indicates whether this interface has automatic private IP addressing (APIPA) enabled. /// - [UnsupportedOSPlatform("android")] + [SupportedOSPlatform("windows")] public abstract bool IsAutomaticPrivateAddressingEnabled { get; } /// @@ -42,7 +43,8 @@ public abstract class IPv4InterfaceProperties /// /// Gets a bool value that indicates whether this interface can route packets. /// - [UnsupportedOSPlatform("android")] + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("linux")] public abstract bool IsForwardingEnabled { get; } /// diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPv6InterfaceProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPv6InterfaceProperties.cs index 534ac51e853409..1e6476017bb515 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPv6InterfaceProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPv6InterfaceProperties.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.Versioning; + namespace System.Net.NetworkInformation { /// @@ -23,6 +25,10 @@ public abstract class IPv6InterfaceProperties /// /// The scope level. /// The IPv6 scope identifier. + [UnsupportedOSPlatform("osx")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("freebsd")] public virtual long GetScopeId(ScopeLevel scopeLevel) { throw NotImplemented.ByDesignWithMessage(SR.net_MethodNotImplementedException); diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IcmpV4Statistics.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IcmpV4Statistics.cs index 2d677ef9fb5fe7..482db5808aec47 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IcmpV4Statistics.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IcmpV4Statistics.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.Versioning; + namespace System.Net.NetworkInformation { /// @@ -61,21 +63,37 @@ public abstract class IcmpV4Statistics /// /// Gets the number of Internet Control Message Protocol version 4 (ICMPv4) error messages received. /// + [UnsupportedOSPlatform("osx")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("freebsd")] public abstract long ErrorsReceived { get; } /// /// Gets the number of Internet Control Message Protocol version 4 (ICMPv4) Echo Request messages sent. /// + [UnsupportedOSPlatform("osx")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("freebsd")] public abstract long ErrorsSent { get; } /// /// Gets the number of Internet Control Message Protocol messages received. /// + [UnsupportedOSPlatform("osx")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("freebsd")] public abstract long MessagesReceived { get; } /// /// Gets the number of Internet Control Message Protocol version 4 (ICMPv4) messages sent. /// + [UnsupportedOSPlatform("osx")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("freebsd")] public abstract long MessagesSent { get; } /// diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IcmpV6Statistics.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IcmpV6Statistics.cs index 6f9d3e76b3dc5e..be51f70d9f296c 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IcmpV6Statistics.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IcmpV6Statistics.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.Versioning; + namespace System.Net.NetworkInformation { /// @@ -41,11 +43,19 @@ public abstract class IcmpV6Statistics /// /// Gets the number of Internet Control Message Protocol version 6 (ICMPv6) error messages received. /// + [UnsupportedOSPlatform("osx")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("freebsd")] public abstract long ErrorsReceived { get; } /// /// Gets the number of Internet Control Message Protocol version 6 (ICMPv6) error messages sent. /// + [UnsupportedOSPlatform("osx")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("freebsd")] public abstract long ErrorsSent { get; } /// @@ -81,11 +91,19 @@ public abstract class IcmpV6Statistics /// /// Gets the number of Internet Control Message Protocol version 6 (ICMPv6) messages received. /// + [UnsupportedOSPlatform("osx")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("freebsd")] public abstract long MessagesReceived { get; } /// /// Gets the number of Internet Control Message Protocol version 6 (ICMPv6) messages sent. /// + [UnsupportedOSPlatform("osx")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("freebsd")] public abstract long MessagesSent { get; } /// diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/MulticastIPAddressInformation.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/MulticastIPAddressInformation.cs index 9dfe8b5bfb0526..c16aae4febf6ff 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/MulticastIPAddressInformation.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/MulticastIPAddressInformation.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.Versioning; + namespace System.Net.NetworkInformation { /// @@ -11,31 +13,37 @@ public abstract class MulticastIPAddressInformation : IPAddressInformation /// /// Gets the number of seconds remaining during which this address is the preferred address. /// + [SupportedOSPlatform("windows")] public abstract long AddressPreferredLifetime { get; } /// /// Gets the number of seconds remaining during which this address is valid. /// + [SupportedOSPlatform("windows")] public abstract long AddressValidLifetime { get; } /// /// Specifies the amount of time remaining on the Dynamic Host Configuration Protocol (DHCP) lease for this IP address. /// + [SupportedOSPlatform("windows")] public abstract long DhcpLeaseLifetime { get; } /// /// Gets a value that indicates the state of the duplicate address detection algorithm. /// + [SupportedOSPlatform("windows")] public abstract DuplicateAddressDetectionState DuplicateAddressDetectionState { get; } /// /// Gets a value that identifies the source of a unicast IP address prefix. /// + [SupportedOSPlatform("windows")] public abstract PrefixOrigin PrefixOrigin { get; } /// /// Gets a value that identifies the source of a unicast IP address suffix. /// + [SupportedOSPlatform("windows")] public abstract SuffixOrigin SuffixOrigin { get; } } } diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnicastIPAddressInformation.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnicastIPAddressInformation.cs index 13199b927f2ed3..139dcc4dce867a 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnicastIPAddressInformation.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnicastIPAddressInformation.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Net.Sockets; +using System.Runtime.Versioning; namespace System.Net.NetworkInformation { @@ -14,31 +15,37 @@ public abstract class UnicastIPAddressInformation : IPAddressInformation /// /// Gets the number of seconds remaining during which this address is the preferred address. /// + [SupportedOSPlatform("windows")] public abstract long AddressPreferredLifetime { get; } /// /// Gets the number of seconds remaining during which this address is valid. /// + [SupportedOSPlatform("windows")] public abstract long AddressValidLifetime { get; } /// /// Specifies the amount of time remaining on the Dynamic Host Configuration Protocol (DHCP) lease for this IP address. /// + [SupportedOSPlatform("windows")] public abstract long DhcpLeaseLifetime { get; } /// /// Gets a value that indicates the state of the duplicate address detection algorithm. /// + [SupportedOSPlatform("windows")] public abstract DuplicateAddressDetectionState DuplicateAddressDetectionState { get; } /// /// Gets a value that identifies the source of a unicast IP address prefix. /// + [SupportedOSPlatform("windows")] public abstract PrefixOrigin PrefixOrigin { get; } /// /// Gets a value that identifies the source of a unicast IP address suffix. /// + [SupportedOSPlatform("windows")] public abstract SuffixOrigin SuffixOrigin { get; } public abstract IPAddress IPv4Mask { get; } diff --git a/src/libraries/System.Net.Security/src/System.Net.Security.csproj b/src/libraries/System.Net.Security/src/System.Net.Security.csproj index 372b716dc0506a..c586e4e9c9a758 100644 --- a/src/libraries/System.Net.Security/src/System.Net.Security.csproj +++ b/src/libraries/System.Net.Security/src/System.Net.Security.csproj @@ -254,6 +254,8 @@ Link="Common\Interop\Unix\Interop.Errors.cs" /> + + - + diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.sln b/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.sln index ba8120604e6eb8..0dc2fe9e6017d4 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.sln +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.sln @@ -11,7 +11,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.InteropServi EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JSImportGenerator.Unit.Tests", "tests\JSImportGenerator.UnitTest\JSImportGenerator.Unit.Tests.csproj", "{BFED925C-18F2-4C98-833E-66F205234598}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.InteropServices.JavaScript.Tests", "tests\System.Runtime.InteropServices.JavaScript.Tests.csproj", "{765B4AA5-723A-44FF-BC4E-EB0F03103F6D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.InteropServices.JavaScript.Tests", "tests\System.Runtime.InteropServices.JavaScript.UnitTests\System.Runtime.InteropServices.JavaScript.Tests.csproj", "{765B4AA5-723A-44FF-BC4E-EB0F03103F6D}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibraryImportGenerator", "..\System.Runtime.InteropServices\gen\LibraryImportGenerator\LibraryImportGenerator.csproj", "{09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}" EndProject diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/GeneratorDiagnostics.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/GeneratorDiagnostics.cs index 3c03ea366491f3..fea0a917cf5b1e 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/GeneratorDiagnostics.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/GeneratorDiagnostics.cs @@ -17,12 +17,14 @@ public class GeneratorDiagnostics : IGeneratorDiagnostics { public class Ids { - // SYSLIB1050-SYSLIB1059 are reserved for JSImportGenerator - public const string Prefix = "JS"; - public const string InvalidJSImportAttributeUsage = Prefix + "1050"; - public const string TypeNotSupported = Prefix + "1051"; - public const string ConfigurationNotSupported = Prefix + "1052"; - public const string CannotForwardToDllImport = Prefix + "1053"; + // SYSLIB1070-SYSLIB1089 are reserved for JSImportGenerator + public const string Prefix = "SYSLIB"; + public const string InvalidJSImportAttributeUsage = Prefix + "1070"; + public const string InvalidJSExportAttributeUsage = Prefix + "1071"; + public const string TypeNotSupported = Prefix + "1072"; + public const string ConfigurationNotSupported = Prefix + "1073"; + public const string JSImportRequiresAllowUnsafeBlocks = Prefix + "1074"; + public const string JSExportRequiresAllowUnsafeBlocks = Prefix + "1075"; } private const string Category = "JSImportGenerator"; @@ -268,7 +270,7 @@ public void ReportMarshallingNotSupported( public static readonly DiagnosticDescriptor InvalidExportAttributedMethodSignature = new DiagnosticDescriptor( - Ids.InvalidJSImportAttributeUsage, + Ids.InvalidJSExportAttributeUsage, GetResourceString(nameof(SR.InvalidJSExportAttributeUsageTitle)), GetResourceString(nameof(SR.InvalidJSExportAttributedMethodSignatureMessage)), Category, @@ -288,14 +290,34 @@ public void ReportMarshallingNotSupported( public static readonly DiagnosticDescriptor InvalidExportAttributedMethodContainingTypeMissingModifiers = new DiagnosticDescriptor( - Ids.InvalidJSImportAttributeUsage, - GetResourceString(nameof(SR.InvalidJSImportAttributeUsageTitle)), + Ids.InvalidJSExportAttributeUsage, + GetResourceString(nameof(SR.InvalidJSExportAttributeUsageTitle)), GetResourceString(nameof(SR.InvalidAttributedMethodContainingTypeMissingModifiersMessage)), Category, DiagnosticSeverity.Error, isEnabledByDefault: true, description: GetResourceString(nameof(SR.InvalidJSExportAttributedMethodDescription))); + public static readonly DiagnosticDescriptor JSImportRequiresAllowUnsafeBlocks = + new DiagnosticDescriptor( + Ids.JSImportRequiresAllowUnsafeBlocks, + GetResourceString(nameof(SR.JSImportRequiresAllowUnsafeBlocksTitle)), + GetResourceString(nameof(SR.JSImportRequiresAllowUnsafeBlocksMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.JSImportRequiresAllowUnsafeBlocksDescription))); + + public static readonly DiagnosticDescriptor JSExportRequiresAllowUnsafeBlocks = + new DiagnosticDescriptor( + Ids.JSExportRequiresAllowUnsafeBlocks, + GetResourceString(nameof(SR.JSExportRequiresAllowUnsafeBlocksTitle)), + GetResourceString(nameof(SR.JSExportRequiresAllowUnsafeBlocksMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.JSExportRequiresAllowUnsafeBlocksDescription))); + private static LocalizableResourceString GetResourceString(string resourceName) { return new LocalizableResourceString(resourceName, SR.ResourceManager, typeof(FxResources.Microsoft.Interop.JavaScript.JSImportGenerator.SR)); diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs index b1061760e13599..82fb93b871026b 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs @@ -53,6 +53,7 @@ public static class StepNames public void Initialize(IncrementalGeneratorInitializationContext context) { + // Collect all methods adorned with JSExportAttribute var attributedMethods = context.SyntaxProvider .CreateSyntaxProvider( static (node, ct) => ShouldVisitNode(node), @@ -70,6 +71,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .Where( static modelData => modelData is not null); + // Validate if attributed methods can have source generated var methodsWithDiagnostics = attributedMethods.Select(static (data, ct) => { Diagnostic? diagnostic = GetDiagnosticIfInvalidMethodForGeneration(data.Syntax, data.Symbol); @@ -79,16 +81,32 @@ public void Initialize(IncrementalGeneratorInitializationContext context) var methodsToGenerate = methodsWithDiagnostics.Where(static data => data.Diagnostic is null); var invalidMethodDiagnostics = methodsWithDiagnostics.Where(static data => data.Diagnostic is not null); + // Report diagnostics for invalid methods context.RegisterSourceOutput(invalidMethodDiagnostics, static (context, invalidMethod) => { context.ReportDiagnostic(invalidMethod.Diagnostic); }); + // Compute generator options IncrementalValueProvider stubOptions = context.AnalyzerConfigOptionsProvider .Select(static (options, ct) => new JSGeneratorOptions(options.GlobalOptions)); + IncrementalValueProvider stubEnvironment = context.CreateStubEnvironmentProvider(); + + // Validate environment that is being used to generate stubs. + context.RegisterDiagnostics(stubEnvironment.Combine(attributedMethods.Collect()).SelectMany((data, ct) => + { + if (data.Right.IsEmpty // no attributed methods + || data.Left.Compilation.Options is CSharpCompilationOptions { AllowUnsafe: true }) // Unsafe code enabled + { + return ImmutableArray.Empty; + } + + return ImmutableArray.Create(Diagnostic.Create(GeneratorDiagnostics.JSExportRequiresAllowUnsafeBlocks, null)); + })); + IncrementalValuesProvider<(MemberDeclarationSyntax, ImmutableArray)> generateSingleStub = methodsToGenerate - .Combine(context.CreateStubEnvironmentProvider()) + .Combine(stubEnvironment) .Combine(stubOptions) .Select(static (data, ct) => new { diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs index 37c86706cbbb8e..1d4ef3812b6401 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs @@ -58,6 +58,7 @@ public static class StepNames public void Initialize(IncrementalGeneratorInitializationContext context) { + // Collect all methods adorned with JSImportAttribute var attributedMethods = context.SyntaxProvider .CreateSyntaxProvider( static (node, ct) => ShouldVisitNode(node), @@ -75,6 +76,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .Where( static modelData => modelData is not null); + // Validate if attributed methods can have source generated var methodsWithDiagnostics = attributedMethods.Select(static (data, ct) => { Diagnostic? diagnostic = GetDiagnosticIfInvalidMethodForGeneration(data.Syntax, data.Symbol); @@ -84,16 +86,32 @@ public void Initialize(IncrementalGeneratorInitializationContext context) var methodsToGenerate = methodsWithDiagnostics.Where(static data => data.Diagnostic is null); var invalidMethodDiagnostics = methodsWithDiagnostics.Where(static data => data.Diagnostic is not null); + // Report diagnostics for invalid methods context.RegisterSourceOutput(invalidMethodDiagnostics, static (context, invalidMethod) => { context.ReportDiagnostic(invalidMethod.Diagnostic); }); + // Compute generator options IncrementalValueProvider stubOptions = context.AnalyzerConfigOptionsProvider .Select(static (options, ct) => new JSGeneratorOptions(options.GlobalOptions)); + IncrementalValueProvider stubEnvironment = context.CreateStubEnvironmentProvider(); + + // Validate environment that is being used to generate stubs. + context.RegisterDiagnostics(stubEnvironment.Combine(attributedMethods.Collect()).SelectMany((data, ct) => + { + if (data.Right.IsEmpty // no attributed methods + || data.Left.Compilation.Options is CSharpCompilationOptions { AllowUnsafe: true }) // Unsafe code enabled + { + return ImmutableArray.Empty; + } + + return ImmutableArray.Create(Diagnostic.Create(GeneratorDiagnostics.JSImportRequiresAllowUnsafeBlocks, null)); + })); + IncrementalValuesProvider<(MemberDeclarationSyntax, ImmutableArray)> generateSingleStub = methodsToGenerate - .Combine(context.CreateStubEnvironmentProvider()) + .Combine(stubEnvironment) .Combine(stubOptions) .Select(static (data, ct) => new { diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Resources/Strings.resx b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Resources/Strings.resx index 27660b58af60f6..b06ebce2260316 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Resources/Strings.resx +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Resources/Strings.resx @@ -208,4 +208,22 @@ Please annotate the argument with 'JSMarshalAsAttribute' to specify marshaling of {0}. {0} is a type of the argument + + JSImportAttribute requires unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. + + + JSImportAttribute requires unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. + + + JSImportAttribute requires unsafe code. + + + JSExportAttribute requires unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. + + + JSExportAttribute requires unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. + + + JSExportAttribute requires unsafe code. + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Compiles.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Compiles.cs index 003881e5c0102f..46a29d20650f57 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Compiles.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Compiles.cs @@ -32,7 +32,7 @@ public static IEnumerable CodeSnippetsToCompile() [MemberData(nameof(CodeSnippetsToCompile))] public async Task ValidateSnippets(string source) { - Compilation comp = await TestUtils.CreateCompilation(source); + Compilation comp = await TestUtils.CreateCompilation(source, allowUnsafe: true); TestUtils.AssertPreSourceGeneratorCompilation(comp); var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Fails.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Fails.cs index c7f98039414d29..29533c72dc60f0 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Fails.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Fails.cs @@ -55,7 +55,7 @@ public class Fails [MemberData(nameof(CodeSnippetsToFail))] public async Task ValidateFailSnippets(string source, string[]? generatorMessages, string[]? compilerMessages) { - Compilation comp = await TestUtils.CreateCompilation(source); + Compilation comp = await TestUtils.CreateCompilation(source, allowUnsafe: true); TestUtils.AssertPreSourceGeneratorCompilation(comp); var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, @@ -73,5 +73,21 @@ public async Task ValidateFailSnippets(string source, string[]? generatorMessage JSTestUtils.AssertMessages(compilationDiags, compilerMessages); } } + + [Fact] + public async Task ValidateRequireAllowUnsafeBlocksDiagnostic() + { + string source = CodeSnippets.TrivialClassDeclarations; + Compilation comp = await TestUtils.CreateCompilation(new[] { source }, allowUnsafe: false); + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, + new Microsoft.Interop.JavaScript.JSImportGenerator(), + new Microsoft.Interop.JavaScript.JSExportGenerator()); + + // The errors should indicate the AllowUnsafeBlocks is required. + Assert.True(generatorDiags.Single(d => d.Id == "SYSLIB1074") != null); + Assert.True(generatorDiags.Single(d => d.Id == "SYSLIB1075") != null); + } } } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Tests.csproj b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System.Runtime.InteropServices.JavaScript.Tests.csproj similarity index 100% rename from src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Tests.csproj rename to src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System.Runtime.InteropServices.JavaScript.Tests.csproj diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs rename to src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs rename to src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs similarity index 100% rename from src/libraries/System.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs rename to src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/Utils.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/Utils.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/Utils.cs rename to src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/Utils.cs diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs index c788d5db12115e..204709cf60c86c 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs @@ -8,7 +8,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; - +using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; using static Microsoft.Interop.Analyzers.AnalyzerDiagnostics; namespace Microsoft.Interop.Analyzers @@ -18,13 +18,6 @@ public class ConvertToLibraryImportAnalyzer : DiagnosticAnalyzer { private const string Category = "Interoperability"; - private static readonly string[] s_unsupportedTypeNames = new string[] - { - "System.Runtime.InteropServices.CriticalHandle", - "System.Runtime.InteropServices.HandleRef", - "System.Text.StringBuilder" - }; - public static readonly DiagnosticDescriptor ConvertToLibraryImport = new DiagnosticDescriptor( Ids.ConvertToLibraryImport, @@ -39,6 +32,14 @@ public class ConvertToLibraryImportAnalyzer : DiagnosticAnalyzer public const string CharSet = nameof(CharSet); public const string ExactSpelling = nameof(ExactSpelling); + public const string MayRequireAdditionalWork = nameof(MayRequireAdditionalWork); + + private static readonly HashSet s_unsupportedTypeNames = new() + { + "global::System.Runtime.InteropServices.CriticalHandle", + "global::System.Runtime.InteropServices.HandleRef", + "global::System.Text.StringBuilder" + }; public override void Initialize(AnalysisContext context) { @@ -49,27 +50,15 @@ public override void Initialize(AnalysisContext context) context => { // Nothing to do if the LibraryImportAttribute is not in the compilation - INamedTypeSymbol? libraryImportAttrType = context.Compilation.GetTypeByMetadataName(TypeNames.LibraryImportAttribute); + INamedTypeSymbol? libraryImportAttrType = context.Compilation.GetBestTypeByMetadataName(TypeNames.LibraryImportAttribute); if (libraryImportAttrType == null) return; - INamedTypeSymbol? marshalAsAttrType = context.Compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_MarshalAsAttribute); - - var knownUnsupportedTypes = new List(s_unsupportedTypeNames.Length); - foreach (string typeName in s_unsupportedTypeNames) - { - INamedTypeSymbol? unsupportedType = context.Compilation.GetTypeByMetadataName(typeName); - if (unsupportedType != null) - { - knownUnsupportedTypes.Add(unsupportedType); - } - } - - context.RegisterSymbolAction(symbolContext => AnalyzeSymbol(symbolContext, knownUnsupportedTypes, marshalAsAttrType, libraryImportAttrType), SymbolKind.Method); + context.RegisterSymbolAction(symbolContext => AnalyzeSymbol(symbolContext, libraryImportAttrType), SymbolKind.Method); }); } - private static void AnalyzeSymbol(SymbolAnalysisContext context, List knownUnsupportedTypes, INamedTypeSymbol? marshalAsAttrType, INamedTypeSymbol libraryImportAttrType) + private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol libraryImportAttrType) { var method = (IMethodSymbol)context.Symbol; @@ -88,54 +77,70 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context, List + { + if (s_unsupportedTypeNames.Contains(info.ManagedType.FullTypeName)) + { + anyExplicitlyUnsupportedInfo = true; + return forwarder; + } + if (HasUnsupportedMarshalAsInfo(info)) + { + anyExplicitlyUnsupportedInfo = true; + return forwarder; + } + try + { + return generatorFactoryKey.GeneratorFactory.Create(info, stubCodeContext); + } + catch (MarshallingNotSupportedException) + { + mayRequireAdditionalWork = true; + return forwarder; + } + }); + + if (anyExplicitlyUnsupportedInfo) + { + // If we have any parameters/return value with an explicitly unsupported marshal type or marshalling info, + // don't offer the fix. The amount of work for the user to get to pairity would be too expensive. return; + } ImmutableDictionary.Builder properties = ImmutableDictionary.CreateBuilder(); properties.Add(CharSet, dllImportData.CharacterSet.ToString()); properties.Add(ExactSpelling, dllImportData.ExactSpelling.ToString()); + properties.Add(MayRequireAdditionalWork, mayRequireAdditionalWork.ToString()); context.ReportDiagnostic(method.CreateDiagnostic(ConvertToLibraryImport, properties.ToImmutable(), method.Name)); } - private static bool HasUnsupportedUnmanagedTypeValue(ImmutableArray attributes, INamedTypeSymbol? marshalAsAttrType) + private static bool HasUnsupportedMarshalAsInfo(TypePositionInfo info) { - if (marshalAsAttrType == null) - return false; - - AttributeData? marshalAsAttr = null; - foreach (AttributeData attr in attributes) - { - if (SymbolEqualityComparer.Default.Equals(attr.AttributeClass, marshalAsAttrType)) - { - marshalAsAttr = attr; - break; - } - } - - if (marshalAsAttr == null || marshalAsAttr.ConstructorArguments.IsEmpty) + if (info.MarshallingAttributeInfo is not MarshalAsInfo(UnmanagedType unmanagedType, _)) return false; - object unmanagedTypeObj = marshalAsAttr.ConstructorArguments[0].Value!; - UnmanagedType unmanagedType = unmanagedTypeObj is short unmanagedTypeAsShort - ? (UnmanagedType)unmanagedTypeAsShort - : (UnmanagedType)unmanagedTypeObj; - return !System.Enum.IsDefined(typeof(UnmanagedType), unmanagedType) || unmanagedType == UnmanagedType.CustomMarshaler || unmanagedType == UnmanagedType.Interface @@ -144,5 +149,27 @@ private static bool HasUnsupportedUnmanagedTypeValue(ImmutableArray AnyDiagnostics = true; + public void ReportInvalidMarshallingAttributeInfo(AttributeData attributeData, string reasonResourceName, params string[] reasonArgs) => AnyDiagnostics = true; + } } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportFixer.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportFixer.cs index dab36a7cb49924..9ebbb56a339f21 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportFixer.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportFixer.cs @@ -15,6 +15,7 @@ using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.FindSymbols; using static Microsoft.Interop.Analyzers.AnalyzerDiagnostics; @@ -28,9 +29,10 @@ public sealed class ConvertToLibraryImportFixer : CodeFixProvider public override FixAllProvider GetFixAllProvider() => CustomFixAllProvider.Instance; - private const string ConvertToLibraryImportKey = "ConvertToLibraryImport"; - private const string ConvertToLibraryImportWithASuffixKey = "ConvertToLibraryImportA"; - private const string ConvertToLibraryImportWithWSuffixKey = "ConvertToLibraryImportW"; + private const string ConvertToLibraryImportKey = "ConvertToLibraryImport,"; + private static string AddSuffixKey(string baseKey, char suffix) => $"{baseKey}{suffix},"; + private static string AddUnsafeKey(string baseKey) => baseKey + "AddUnsafe,"; + private static string AddMayRequireAdditionalWorkKey(string baseKey) => baseKey + $"{ConvertToLibraryImportAnalyzer.MayRequireAdditionalWork},"; private static readonly string[] s_preferredAttributeArgumentOrder = { @@ -57,20 +59,19 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) if (root.FindNode(context.Span) is not MethodDeclarationSyntax methodSyntax) return; - // Register code fix - context.RegisterCodeFix( - CodeAction.Create( - SR.ConvertToLibraryImport, - cancelToken => ConvertToLibraryImport( - context.Document, - methodSyntax, - entryPointSuffix: null, - cancelToken), - equivalenceKey: ConvertToLibraryImportKey), - context.Diagnostics); + bool enableUnsafe = doc.Project.CompilationOptions is CSharpCompilationOptions { AllowUnsafe: false }; + + ICodeActionFactory codeActionFactory = enableUnsafe ? new AddUnsafeCodeActionFactory() : new DefaultCodeActionFactory(); foreach (Diagnostic diagnostic in context.Diagnostics) { + bool mayRequireAdditionalWork = bool.TryParse(diagnostic.Properties[ConvertToLibraryImportAnalyzer.MayRequireAdditionalWork], out bool mayRequireAdditionalWorkValue) + ? mayRequireAdditionalWorkValue + : false; + // Register code fix + context.RegisterCodeFix( + codeActionFactory.CreateConvertToLibraryImportCodeFix(doc, methodSyntax, mayRequireAdditionalWork), + context.Diagnostics); if (!bool.Parse(diagnostic.Properties[ConvertToLibraryImportAnalyzer.ExactSpelling])) { CharSet charSet = (CharSet)Enum.Parse(typeof(CharSet), diagnostic.Properties[ConvertToLibraryImportAnalyzer.CharSet]); @@ -81,96 +82,203 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) if (charSet is CharSet.None or CharSet.Ansi or CharSet.Auto) { context.RegisterCodeFix( - CodeAction.Create( - string.Format(SR.ConvertToLibraryImportWithSuffix, "A"), - cancelToken => ConvertToLibraryImport( - context.Document, - methodSyntax, - entryPointSuffix: 'A', - cancelToken), - equivalenceKey: ConvertToLibraryImportWithASuffixKey), + codeActionFactory.CreateConvertToLibraryImportWithSuffixCodeFix(doc, methodSyntax, 'A', mayRequireAdditionalWork), context.Diagnostics); } if (charSet is CharSet.Unicode or CharSet.Auto) { context.RegisterCodeFix( - CodeAction.Create( - string.Format(SR.ConvertToLibraryImportWithSuffix, "W"), - cancelToken => ConvertToLibraryImport( - context.Document, - methodSyntax, - entryPointSuffix: 'W', - cancelToken), - equivalenceKey: ConvertToLibraryImportWithWSuffixKey), + codeActionFactory.CreateConvertToLibraryImportWithSuffixCodeFix(doc, methodSyntax, 'W', mayRequireAdditionalWork), context.Diagnostics); } } } } - private sealed class CustomFixAllProvider : DocumentBasedFixAllProvider + internal interface ICodeActionFactory { - public static readonly CustomFixAllProvider Instance = new(); + CodeAction CreateConvertToLibraryImportCodeFix(Document document, MethodDeclarationSyntax methodSyntax, bool mayRequireAdditionalWork); + CodeAction CreateConvertToLibraryImportWithSuffixCodeFix(Document document, MethodDeclarationSyntax methodSyntax, char suffix, bool mayRequireAdditionalWork); + } - protected override async Task FixAllAsync(FixAllContext fixAllContext, Document document, ImmutableArray diagnostics) + private sealed class DefaultCodeActionFactory : ICodeActionFactory + { + public CodeAction CreateConvertToLibraryImportCodeFix(Document document, MethodDeclarationSyntax methodSyntax, bool mayRequireAdditionalWork) { - DocumentEditor editor = await DocumentEditor.CreateAsync(document, fixAllContext.CancellationToken).ConfigureAwait(false); - SyntaxGenerator generator = editor.Generator; + return CodeAction.Create( + SR.ConvertToLibraryImport, + cancelToken => ConvertToLibraryImport( + document, + methodSyntax, + mayRequireAdditionalWork, + entryPointSuffix: null, + cancelToken), + equivalenceKey: mayRequireAdditionalWork ? AddMayRequireAdditionalWorkKey(ConvertToLibraryImportKey) : ConvertToLibraryImportKey); + } - SyntaxNode? root = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); - if (root == null) - return document; + public CodeAction CreateConvertToLibraryImportWithSuffixCodeFix(Document document, MethodDeclarationSyntax methodSyntax, char suffix, bool mayRequireAdditionalWork) + { + return CodeAction.Create( + string.Format(SR.ConvertToLibraryImportWithSuffix, suffix), + cancelToken => ConvertToLibraryImport( + document, + methodSyntax, + mayRequireAdditionalWork, + entryPointSuffix: suffix, + cancelToken), + equivalenceKey: AddSuffixKey(mayRequireAdditionalWork ? AddMayRequireAdditionalWorkKey(ConvertToLibraryImportKey) : ConvertToLibraryImportKey, suffix)); + } + } - foreach (Diagnostic diagnostic in diagnostics) - { - // Get the syntax node tied to the diagnostic and check that it is a method declaration - if (root.FindNode(diagnostic.Location.SourceSpan) is not MethodDeclarationSyntax methodSyntax) - continue; - if (editor.SemanticModel.GetDeclaredSymbol(methodSyntax, fixAllContext.CancellationToken) is not IMethodSymbol methodSymbol) - continue; + private sealed class AddUnsafeCodeActionFactory : ICodeActionFactory + { + public CodeAction CreateConvertToLibraryImportCodeFix(Document document, MethodDeclarationSyntax methodSyntax, bool mayRequireAdditionalWork) + { + return CodeAction.Create( + SR.ConvertToLibraryImportAddUnsafe, + async cancelToken => + { + Solution solutionWithUnsafe = AddUnsafe(document.Project.Solution, document.Project); + SolutionEditor editor = new SolutionEditor(solutionWithUnsafe); + + await ConvertToLibraryImport( + await editor.GetDocumentEditorAsync(document.Id, cancelToken).ConfigureAwait(false), + methodSyntax, + mayRequireAdditionalWork, + entryPointSuffix: null, + cancelToken).ConfigureAwait(false); + return editor.GetChangedSolution(); + }, + equivalenceKey: AddUnsafeKey(mayRequireAdditionalWork ? AddMayRequireAdditionalWorkKey(ConvertToLibraryImportKey) : ConvertToLibraryImportKey)); + } - SyntaxNode generatedDeclaration = await ConvertMethodDeclarationToLibraryImport(methodSyntax, editor, generator, methodSymbol, GetSuffixFromEquivalenceKey(fixAllContext.CodeActionEquivalenceKey), fixAllContext.CancellationToken).ConfigureAwait(false); + public CodeAction CreateConvertToLibraryImportWithSuffixCodeFix(Document document, MethodDeclarationSyntax methodSyntax, char suffix, bool mayRequireAdditionalWork) + { + return CodeAction.Create( + string.Format(SR.ConvertToLibraryImportWithSuffixAddUnsafe, suffix), + async cancelToken => + { + Solution solutionWithUnsafe = AddUnsafe(document.Project.Solution, document.Project); + SolutionEditor editor = new SolutionEditor(solutionWithUnsafe); + + await ConvertToLibraryImport( + await editor.GetDocumentEditorAsync(document.Id, cancelToken).ConfigureAwait(false), + methodSyntax, + mayRequireAdditionalWork, + entryPointSuffix: suffix, + cancelToken).ConfigureAwait(false); + return editor.GetChangedSolution(); + }, + equivalenceKey: AddUnsafeKey(AddSuffixKey(mayRequireAdditionalWork ? AddMayRequireAdditionalWorkKey(ConvertToLibraryImportKey) : ConvertToLibraryImportKey, suffix))); + } + } - if (!methodSymbol.MethodImplementationFlags.HasFlag(System.Reflection.MethodImplAttributes.PreserveSig)) + private sealed class CustomFixAllProvider : FixAllProvider + { + public static readonly CustomFixAllProvider Instance = new(); + public override async Task GetFixAsync(FixAllContext fixAllContext) + { + bool addUnsafe = fixAllContext.CodeActionEquivalenceKey.Contains(",AddUnsafe,"); + bool includeFixesWithAdditionalWork = fixAllContext.CodeActionEquivalenceKey.Contains($",{ConvertToLibraryImportAnalyzer.MayRequireAdditionalWork},"); + ImmutableArray diagnosticsInScope = await fixAllContext.GetDiagnosticsInScopeAsync().ConfigureAwait(false); + + return CodeAction.Create(addUnsafe ? SR.ConvertToLibraryImportAddUnsafe : SR.ConvertToLibraryImport, + async ct => { - bool shouldWarn = await TransformCallersOfNoPreserveSigMethod(editor, methodSymbol, fixAllContext.CancellationToken).ConfigureAwait(false); - if (shouldWarn) + HashSet projectsToAddUnsafe = new(); + SolutionEditor solutionEditor = new SolutionEditor(fixAllContext.Solution); + + foreach (var diagnostic in diagnosticsInScope) { - generatedDeclaration = generatedDeclaration.WithAdditionalAnnotations(WarningAnnotation.Create(SR.ConvertNoPreserveSigDllImportToGeneratedMayProduceInvalidCode)); - } - } + bool mayRequireAdditionalWork = bool.TryParse(diagnostic.Properties[ConvertToLibraryImportAnalyzer.MayRequireAdditionalWork], out bool mayRequireAdditionalWorkValue) + ? mayRequireAdditionalWorkValue + : false; + if (mayRequireAdditionalWork && !includeFixesWithAdditionalWork) + { + // Don't fix any diagnostics that require additional work if the "fix all" command wasn't triggered from a location + // that was able to warn the user that additional work may be required. + continue; + } + DocumentId documentId = solutionEditor.OriginalSolution.GetDocumentId(diagnostic.Location.SourceTree)!; + DocumentEditor editor = await solutionEditor.GetDocumentEditorAsync(documentId, ct).ConfigureAwait(false); + SyntaxNode root = await diagnostic.Location.SourceTree.GetRootAsync(ct).ConfigureAwait(false); - // Replace the original method with the updated one - editor.ReplaceNode(methodSyntax, generatedDeclaration); + // Get the syntax node tied to the diagnostic and check that it is a method declaration + if (root.FindNode(diagnostic.Location.SourceSpan) is not MethodDeclarationSyntax methodSyntax) + continue; - MakeEnclosingTypesPartial(editor, methodSyntax); - } + await ConvertToLibraryImport(editor, methodSyntax, mayRequireAdditionalWork, GetSuffixFromEquivalenceKey(fixAllContext.CodeActionEquivalenceKey), ct).ConfigureAwait(false); + + // Record this project as a project we need to allow unsafe blocks in. + projectsToAddUnsafe.Add(solutionEditor.OriginalSolution.GetDocument(documentId).Project); + } + + Solution solutionWithUpdatedSources = solutionEditor.GetChangedSolution(); - return editor.GetChangedDocument(); + if (addUnsafe) + { + foreach (var project in projectsToAddUnsafe) + { + solutionWithUpdatedSources = AddUnsafe(solutionWithUpdatedSources, project); + } + } + return solutionWithUpdatedSources; + }, + equivalenceKey: fixAllContext.CodeActionEquivalenceKey); } - private static char? GetSuffixFromEquivalenceKey(string equivalenceKey) => equivalenceKey switch + + private static char? GetSuffixFromEquivalenceKey(string equivalenceKey) { - ConvertToLibraryImportWithASuffixKey => 'A', - ConvertToLibraryImportWithWSuffixKey => 'W', - _ => null - }; + if (equivalenceKey.Contains(",A,")) + { + return 'A'; + } + if (equivalenceKey.Contains(",W,")) + { + return 'W'; + } + return null; + } + } + + private static Solution AddUnsafe(Solution solution, Project project) + { + return solution.WithProjectCompilationOptions(project.Id, ((CSharpCompilationOptions)project.CompilationOptions).WithAllowUnsafe(true)); } private static async Task ConvertToLibraryImport( Document doc, MethodDeclarationSyntax methodSyntax, + bool warnForAdditionalWork, char? entryPointSuffix, CancellationToken cancellationToken) { DocumentEditor editor = await DocumentEditor.CreateAsync(doc, cancellationToken).ConfigureAwait(false); + await ConvertToLibraryImport(editor, methodSyntax, warnForAdditionalWork, entryPointSuffix, cancellationToken).ConfigureAwait(false); + return editor.GetChangedDocument(); + } + private static async Task ConvertToLibraryImport( + DocumentEditor editor, + MethodDeclarationSyntax methodSyntax, + bool warnForAdditionalWork, + char? entryPointSuffix, + CancellationToken cancellationToken) + { SyntaxGenerator generator = editor.Generator; if (editor.SemanticModel.GetDeclaredSymbol(methodSyntax, cancellationToken) is not IMethodSymbol methodSymbol) - return doc; + return; - SyntaxNode generatedDeclaration = await ConvertMethodDeclarationToLibraryImport(methodSyntax, editor, generator, methodSymbol, entryPointSuffix, cancellationToken).ConfigureAwait(false); + SyntaxNode generatedDeclaration = await ConvertMethodDeclarationToLibraryImport( + methodSyntax, + editor, + generator, + methodSymbol, + warnForAdditionalWork, + entryPointSuffix, + cancellationToken).ConfigureAwait(false); if (!methodSymbol.MethodImplementationFlags.HasFlag(System.Reflection.MethodImplAttributes.PreserveSig)) { @@ -185,8 +293,6 @@ private static async Task ConvertToLibraryImport( editor.ReplaceNode(methodSyntax, generatedDeclaration); MakeEnclosingTypesPartial(editor, methodSyntax); - - return editor.GetChangedDocument(); } private static async Task ConvertMethodDeclarationToLibraryImport( @@ -194,6 +300,7 @@ private static async Task ConvertMethodDeclarationToLibraryImport( DocumentEditor editor, SyntaxGenerator generator, IMethodSymbol methodSymbol, + bool warnForAdditionalWork, char? entryPointSuffix, CancellationToken cancellationToken) { @@ -221,8 +328,11 @@ private static async Task ConvertMethodDeclarationToLibraryImport( out SyntaxNode? unmanagedCallConvAttributeMaybe); // Add annotation about potential behavioural and compatibility changes - libraryImportSyntax = libraryImportSyntax.WithAdditionalAnnotations( - WarningAnnotation.Create(string.Format(SR.ConvertToLibraryImportWarning, "[TODO] Documentation link"))); + if (warnForAdditionalWork) + { + libraryImportSyntax = libraryImportSyntax.WithAdditionalAnnotations( + WarningAnnotation.Create(SR.ConvertToLibraryImportMayRequireCustomMarshalling)); + } // Replace DllImport with LibraryImport SyntaxNode generatedDeclaration = generator.ReplaceNode(methodSyntax, dllImportSyntax, libraryImportSyntax); @@ -475,15 +585,27 @@ private static SyntaxNode GetLibraryImportAttribute( { // For Unicode, we can translate the argument to StringMarshalling.Utf16 // TODO: Handle ANSI once we have a public marshaller type for ANSI strings that we can use with StringMarshallerCustomType - if (dllImportData.CharacterSet == CharSet.Unicode) + if (dllImportData.CharacterSet == CharSet.Unicode || (dllImportData.CharacterSet == CharSet.Auto && entryPointSuffix is 'W' or null)) { - ITypeSymbol stringMarshallingType = editor.SemanticModel.Compilation.GetTypeByMetadataName(TypeNames.StringMarshalling)!; + ITypeSymbol stringMarshallingType = editor.SemanticModel.Compilation.GetBestTypeByMetadataName(TypeNames.StringMarshalling)!; argumentsToAdd.Add(generator.AttributeArgument( nameof(StringMarshalling), generator.MemberAccessExpression( generator.TypeExpression(stringMarshallingType), generator.IdentifierName(nameof(StringMarshalling.Utf16))))); } + else if (dllImportData.CharacterSet == CharSet.Ansi || (dllImportData.CharacterSet == CharSet.Auto && entryPointSuffix == 'A')) + { + ITypeSymbol stringMarshallingType = editor.SemanticModel.Compilation.GetBestTypeByMetadataName(TypeNames.StringMarshalling)!; + argumentsToAdd.Add(generator.AttributeArgument( + nameof(StringMarshalling), + generator.MemberAccessExpression( + generator.TypeExpression(stringMarshallingType), + generator.IdentifierName(nameof(StringMarshalling.Custom))))); + argumentsToAdd.Add(generator.AttributeArgument( + "StringMarshallingCustomType", + generator.TypeOfExpression(generator.TypeExpression(editor.SemanticModel.Compilation.GetBestTypeByMetadataName(TypeNames.AnsiStringMarshaller))))); + } } argumentsToRemove.Add(argument); diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomMarshallerAttributeAnalyzer.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomMarshallerAttributeAnalyzer.cs index 44de00121bc775..9603ec32cbc2cd 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomMarshallerAttributeAnalyzer.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomMarshallerAttributeAnalyzer.cs @@ -64,6 +64,17 @@ public static ImmutableDictionary CreateDiagnosticPropertiesForM isEnabledByDefault: true, description: GetResourceString(nameof(SR.MarshallerTypeMustBeStaticClassOrStructDescription))); + /// + public static readonly DiagnosticDescriptor ElementMarshallerCannotBeStatefulRule = + new DiagnosticDescriptor( + Ids.InvalidMarshallerType, + GetResourceString(nameof(SR.InvalidMarshallerTypeTitle)), + GetResourceString(nameof(SR.ElementMarshallerCannotBeStatefulMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.ElementMarshallerCannotBeStatefulDescription))); + /// public static readonly DiagnosticDescriptor UnmanagedTypeMustBeUnmanagedRule = new DiagnosticDescriptor( @@ -196,27 +207,93 @@ public static ImmutableDictionary CreateDiagnosticPropertiesForM isEnabledByDefault: true, description: GetResourceString(nameof(SR.StatelessLinearCollectionRequiresTwoParameterAllocateContainerForManagedElementsDescription))); - /// - public static readonly DiagnosticDescriptor CallerAllocConstructorMustHaveBufferSizeRule = + /// + public static readonly DiagnosticDescriptor CallerAllocFromManagedMustHaveBufferSizeRule = + new DiagnosticDescriptor( + Ids.CustomMarshallerTypeMustHaveRequiredShape, + GetResourceString(nameof(SR.CustomMarshallerTypeMustHaveRequiredShapeTitle)), + GetResourceString(nameof(SR.CallerAllocFromManagedMustHaveBufferSizeMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.CallerAllocFromManagedMustHaveBufferSizeDescription))); + + /// + public static readonly DiagnosticDescriptor StatelessLinearCollectionCallerAllocFromManagedMustHaveBufferSizeRule = + new DiagnosticDescriptor( + Ids.CustomMarshallerTypeMustHaveRequiredShape, + GetResourceString(nameof(SR.CustomMarshallerTypeMustHaveRequiredShapeTitle)), + GetResourceString(nameof(SR.StatelessLinearCollectionCallerAllocFromManagedMustHaveBufferSizeMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.StatelessLinearCollectionCallerAllocFromManagedMustHaveBufferSizeDescription))); + + /// + public static readonly DiagnosticDescriptor StatefulMarshallerRequiresFromManagedRule = + new DiagnosticDescriptor( + Ids.CustomMarshallerTypeMustHaveRequiredShape, + GetResourceString(nameof(SR.CustomMarshallerTypeMustHaveRequiredShapeTitle)), + GetResourceString(nameof(SR.StatefulMarshallerRequiresFromManagedMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.StatefulMarshallerRequiresFromManagedDescription))); + + /// + public static readonly DiagnosticDescriptor StatefulMarshallerRequiresToUnmanagedRule = new DiagnosticDescriptor( Ids.CustomMarshallerTypeMustHaveRequiredShape, GetResourceString(nameof(SR.CustomMarshallerTypeMustHaveRequiredShapeTitle)), - GetResourceString(nameof(SR.CallerAllocConstructorMustHaveBufferSizeMessage)), + GetResourceString(nameof(SR.StatefulMarshallerRequiresToUnmanagedMessage)), Category, DiagnosticSeverity.Error, isEnabledByDefault: true, - description: GetResourceString(nameof(SR.CallerAllocConstructorMustHaveBufferSizeDescription))); + description: GetResourceString(nameof(SR.StatefulMarshallerRequiresToUnmanagedDescription))); - /// - public static readonly DiagnosticDescriptor StatelessLinearCollectionCallerAllocConstructorMustHaveBufferSizeRule = + /// + public static readonly DiagnosticDescriptor StatefulMarshallerRequiresToManagedRule = new DiagnosticDescriptor( Ids.CustomMarshallerTypeMustHaveRequiredShape, GetResourceString(nameof(SR.CustomMarshallerTypeMustHaveRequiredShapeTitle)), - GetResourceString(nameof(SR.StatelessLinearCollectionCallerAllocConstructorMustHaveBufferSizeMessage)), + GetResourceString(nameof(SR.StatefulMarshallerRequiresToManagedMessage)), Category, DiagnosticSeverity.Error, isEnabledByDefault: true, - description: GetResourceString(nameof(SR.StatelessLinearCollectionCallerAllocConstructorMustHaveBufferSizeDescription))); + description: GetResourceString(nameof(SR.StatefulMarshallerRequiresToManagedDescription))); + + /// + public static readonly DiagnosticDescriptor StatefulMarshallerRequiresFromUnmanagedRule = + new DiagnosticDescriptor( + Ids.CustomMarshallerTypeMustHaveRequiredShape, + GetResourceString(nameof(SR.CustomMarshallerTypeMustHaveRequiredShapeTitle)), + GetResourceString(nameof(SR.StatefulMarshallerRequiresFromUnmanagedMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.StatefulMarshallerRequiresFromUnmanagedDescription))); + + /// + public static readonly DiagnosticDescriptor StatefulMarshallerRequiresFreeRule = + new DiagnosticDescriptor( + Ids.CustomMarshallerTypeMustHaveRequiredShape, + GetResourceString(nameof(SR.CustomMarshallerTypeMustHaveRequiredShapeTitle)), + GetResourceString(nameof(SR.StatefulMarshallerRequiresFreeMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.StatefulMarshallerRequiresFreeDescription))); + + /// + public static readonly DiagnosticDescriptor FromUnmanagedOverloadsNotSupportedRule = + new DiagnosticDescriptor( + Ids.CustomMarshallerTypeMustHaveRequiredShape, + GetResourceString(nameof(SR.CustomMarshallerTypeMustHaveRequiredShapeTitle)), + GetResourceString(nameof(SR.FromUnmanagedOverloadsNotSupportedMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.FromUnmanagedOverloadsNotSupportedDescription))); /// public static readonly DiagnosticDescriptor MarshallerTypeMustBeClosedOrMatchArityRule = @@ -390,6 +467,50 @@ public static class DefaultMarshalModeDiagnostics isEnabledByDefault: true, description: GetResourceString(nameof(SR.StatelessLinearCollectionRequiresTwoParameterAllocateContainerForManagedElementsDescription))); + /// + public static readonly DiagnosticDescriptor StatefulMarshallerRequiresFromManagedRule = + new DiagnosticDescriptor( + Ids.CustomMarshallerTypeMustHaveRequiredShape, + GetResourceString(nameof(SR.CustomMarshallerTypeMustHaveRequiredShapeTitle)), + GetResourceString(nameof(SR.StatefulMarshallerRequiresFromManagedMessage)), + Category, + DiagnosticSeverity.Info, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.StatefulMarshallerRequiresFromManagedDescription))); + + /// + public static readonly DiagnosticDescriptor StatefulMarshallerRequiresToUnmanagedRule = + new DiagnosticDescriptor( + Ids.CustomMarshallerTypeMustHaveRequiredShape, + GetResourceString(nameof(SR.CustomMarshallerTypeMustHaveRequiredShapeTitle)), + GetResourceString(nameof(SR.StatefulMarshallerRequiresToUnmanagedMessage)), + Category, + DiagnosticSeverity.Info, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.StatefulMarshallerRequiresToUnmanagedDescription))); + + /// + public static readonly DiagnosticDescriptor StatefulMarshallerRequiresToManagedRule = + new DiagnosticDescriptor( + Ids.CustomMarshallerTypeMustHaveRequiredShape, + GetResourceString(nameof(SR.CustomMarshallerTypeMustHaveRequiredShapeTitle)), + GetResourceString(nameof(SR.StatefulMarshallerRequiresToManagedMessage)), + Category, + DiagnosticSeverity.Info, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.StatefulMarshallerRequiresToManagedDescription))); + + /// + public static readonly DiagnosticDescriptor StatefulMarshallerRequiresFromUnmanagedRule = + new DiagnosticDescriptor( + Ids.CustomMarshallerTypeMustHaveRequiredShape, + GetResourceString(nameof(SR.CustomMarshallerTypeMustHaveRequiredShapeTitle)), + GetResourceString(nameof(SR.StatefulMarshallerRequiresFromUnmanagedMessage)), + Category, + DiagnosticSeverity.Info, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.StatefulMarshallerRequiresFromUnmanagedDescription))); + internal static DiagnosticDescriptor GetDefaultMarshalModeDiagnostic(DiagnosticDescriptor errorDescriptor) { if (ReferenceEquals(errorDescriptor, CustomMarshallerAttributeAnalyzer.StatelessValueInRequiresConvertToUnmanagedRule)) @@ -416,6 +537,22 @@ internal static DiagnosticDescriptor GetDefaultMarshalModeDiagnostic(DiagnosticD { return StatelessLinearCollectionRequiresTwoParameterAllocateContainerForManagedElementsRule; } + if (ReferenceEquals(errorDescriptor, CustomMarshallerAttributeAnalyzer.StatefulMarshallerRequiresFromManagedRule)) + { + return StatefulMarshallerRequiresFromManagedRule; + } + if (ReferenceEquals(errorDescriptor, CustomMarshallerAttributeAnalyzer.StatefulMarshallerRequiresToUnmanagedRule)) + { + return StatefulMarshallerRequiresToUnmanagedRule; + } + if (ReferenceEquals(errorDescriptor, CustomMarshallerAttributeAnalyzer.StatefulMarshallerRequiresToManagedRule)) + { + return StatefulMarshallerRequiresToManagedRule; + } + if (ReferenceEquals(errorDescriptor, CustomMarshallerAttributeAnalyzer.StatefulMarshallerRequiresFromUnmanagedRule)) + { + return StatefulMarshallerRequiresFromUnmanagedRule; + } return errorDescriptor; } } @@ -437,7 +574,21 @@ internal static DiagnosticDescriptor GetDefaultMarshalModeDiagnostic(DiagnosticD LinearCollectionOutRequiresCollectionMethodsRule, StatelessLinearCollectionOutRequiresCollectionMethodsRule, StatelessLinearCollectionRequiresTwoParameterAllocateContainerForManagedElementsRule, - CallerAllocConstructorMustHaveBufferSizeRule, + StatefulMarshallerRequiresFromManagedRule, + StatefulMarshallerRequiresToUnmanagedRule, + StatefulMarshallerRequiresToManagedRule, + StatefulMarshallerRequiresFromUnmanagedRule, + DefaultMarshalModeDiagnostics.GetDefaultMarshalModeDiagnostic(StatelessValueInRequiresConvertToUnmanagedRule), + DefaultMarshalModeDiagnostics.GetDefaultMarshalModeDiagnostic(StatelessLinearCollectionRequiresTwoParameterAllocateContainerForUnmanagedElementsRule), + DefaultMarshalModeDiagnostics.GetDefaultMarshalModeDiagnostic(StatelessRequiresConvertToManagedRule), + DefaultMarshalModeDiagnostics.GetDefaultMarshalModeDiagnostic(StatelessLinearCollectionInRequiresCollectionMethodsRule), + DefaultMarshalModeDiagnostics.GetDefaultMarshalModeDiagnostic(StatelessLinearCollectionOutRequiresCollectionMethodsRule), + DefaultMarshalModeDiagnostics.GetDefaultMarshalModeDiagnostic(StatelessLinearCollectionRequiresTwoParameterAllocateContainerForManagedElementsRule), + DefaultMarshalModeDiagnostics.GetDefaultMarshalModeDiagnostic(StatefulMarshallerRequiresFromManagedRule), + DefaultMarshalModeDiagnostics.GetDefaultMarshalModeDiagnostic(StatefulMarshallerRequiresToUnmanagedRule), + DefaultMarshalModeDiagnostics.GetDefaultMarshalModeDiagnostic(StatefulMarshallerRequiresToManagedRule), + DefaultMarshalModeDiagnostics.GetDefaultMarshalModeDiagnostic(StatefulMarshallerRequiresFromUnmanagedRule), + CallerAllocFromManagedMustHaveBufferSizeRule, MarshallerTypeMustBeClosedOrMatchArityRule, FirstParameterMustMatchReturnTypeRule, ReturnTypesMustMatchRule, @@ -445,12 +596,9 @@ internal static DiagnosticDescriptor GetDefaultMarshalModeDiagnostic(DiagnosticD ElementTypesOfReturnTypesMustMatchRule, ManagedTypeMustBeClosedOrMatchArityRule, ManagedTypeMustBeNonNullRule, - DefaultMarshalModeDiagnostics.GetDefaultMarshalModeDiagnostic(StatelessValueInRequiresConvertToUnmanagedRule), - DefaultMarshalModeDiagnostics.GetDefaultMarshalModeDiagnostic(StatelessLinearCollectionRequiresTwoParameterAllocateContainerForUnmanagedElementsRule), - DefaultMarshalModeDiagnostics.GetDefaultMarshalModeDiagnostic(StatelessRequiresConvertToManagedRule), - DefaultMarshalModeDiagnostics.GetDefaultMarshalModeDiagnostic(StatelessLinearCollectionInRequiresCollectionMethodsRule), - DefaultMarshalModeDiagnostics.GetDefaultMarshalModeDiagnostic(StatelessLinearCollectionOutRequiresCollectionMethodsRule), - DefaultMarshalModeDiagnostics.GetDefaultMarshalModeDiagnostic(StatelessLinearCollectionRequiresTwoParameterAllocateContainerForManagedElementsRule)); + ElementMarshallerCannotBeStatefulRule, + StatefulMarshallerRequiresFreeRule, + FromUnmanagedOverloadsNotSupportedRule); public override void Initialize(AnalysisContext context) { @@ -580,7 +728,7 @@ void ReportDiagnosticsForMissingMembers(DiagnosticReporter diagnosticReporter) { CheckForBufferSizeMember( diagnosticReporter, - isLinearCollectionMarshaller ? StatelessLinearCollectionCallerAllocConstructorMustHaveBufferSizeRule : CallerAllocConstructorMustHaveBufferSizeRule, + isLinearCollectionMarshaller ? StatelessLinearCollectionCallerAllocFromManagedMustHaveBufferSizeRule : CallerAllocFromManagedMustHaveBufferSizeRule, marshallerType, methods.ToUnmanagedWithBuffer!); } @@ -836,10 +984,246 @@ private bool TryGetElementTypeFromSpanType(ITypeSymbol spanTypeMaybe, [NotNullWh return false; } -#pragma warning disable CA1822 // Mark members as static private void AnalyzeStatefulMarshallerType(DiagnosticReporter diagnosticReporter, ITypeSymbol managedType, MarshalMode mode, INamedTypeSymbol marshallerType, bool isLinearCollectionMarshaller) -#pragma warning restore CA1822 // Mark members as static { + if (mode is MarshalMode.ElementIn + or MarshalMode.ElementRef + or MarshalMode.ElementOut) + { + diagnosticReporter.CreateAndReportDiagnostic(ElementMarshallerCannotBeStatefulRule, marshallerType.ToDisplayString(), mode); + return; + } + + var (shape, methods) = StatefulMarshallerShapeHelper.GetShapeForType(marshallerType, managedType, isLinearCollectionMarshaller, _compilation); + var fromUnmanagedCandidates = StatefulMarshallerShapeHelper.GetFromUnmanagedMethodCandidates(marshallerType); + + bool reportedDiagnostics = false; + DiagnosticReporter trackingReporter = new DiagnosticReporter((descriptor, properties, args) => + { + reportedDiagnostics = true; + diagnosticReporter.CreateAndReportDiagnostic(descriptor, properties, args); + }); + trackingReporter = AdaptReporterForMarshalMode(trackingReporter, mode); + + ReportDiagnosticsForMissingMembers(trackingReporter); + + // If we encountered any missing-member diagnostics, then we'll stop checking for additional errors here. + if (reportedDiagnostics) + return; + + ReportDiagnosticsForMismatchedMemberSignatures(trackingReporter); + + void ReportDiagnosticsForMissingMembers(DiagnosticReporter diagnosticReporter) + { + // If a caller-allocated-buffer convert method exists, verify that the BufferSize property exists + if (shape.HasFlag(MarshallerShape.CallerAllocatedBuffer) && mode == MarshalMode.ManagedToUnmanagedIn) + { + CheckForBufferSizeMember( + diagnosticReporter, + CallerAllocFromManagedMustHaveBufferSizeRule, + marshallerType, + methods.FromManagedWithBuffer!); + } + + if (ManualTypeMarshallingHelper.ModeUsesManagedToUnmanagedShape(mode)) + { + // If the marshaller mode uses the managed->unmanaged shapes, + // verify that we have either a full managed-to-unmanaged shape + // or that our scenario supports the caller-allocated buffer managed-to-unmanaged shape + // and that the caller-allocated-buffer shape is present. + if (!(shape.HasFlag(MarshallerShape.ToUnmanaged) || (mode == MarshalMode.ManagedToUnmanagedIn && shape.HasFlag(MarshallerShape.CallerAllocatedBuffer)))) + { + // Verify that all of the following methods are present with valid shapes: + // - FromManaged + // - ToUnmanaged + if (methods.FromManaged is null && methods.FromManagedWithBuffer is null) + { + diagnosticReporter.CreateAndReportDiagnostic( + StatefulMarshallerRequiresFromManagedRule, + MissingMemberNames.CreateDiagnosticPropertiesForMissingMembersDiagnostic( + mode, + ShapeMemberNames.Value.Stateful.FromManaged), + marshallerType.ToDisplayString(), + mode, + managedType.ToDisplayString()); + } + if (methods.ToUnmanaged is null) + { + diagnosticReporter.CreateAndReportDiagnostic( + StatefulMarshallerRequiresToUnmanagedRule, + MissingMemberNames.CreateDiagnosticPropertiesForMissingMembersDiagnostic( + mode, + ShapeMemberNames.Value.Stateful.ToUnmanaged), + marshallerType.ToDisplayString(), + mode, + managedType.ToDisplayString()); + } + + if (isLinearCollectionMarshaller) + { + // Verify that all of the following methods are present with valid shapes: + // - GetManagedValuesSource + // - GetUnmanagedValuesDestination + List missingCollectionMethods = new(); + if (methods.ManagedValuesSource is null) + { + missingCollectionMethods.Add(ShapeMemberNames.LinearCollection.Stateful.GetManagedValuesSource); + } + if (methods.UnmanagedValuesDestination is null) + { + missingCollectionMethods.Add(ShapeMemberNames.LinearCollection.Stateful.GetUnmanagedValuesDestination); + } + if (missingCollectionMethods.Count > 0) + { + diagnosticReporter.CreateAndReportDiagnostic( + LinearCollectionInRequiresCollectionMethodsRule, + MissingMemberNames.CreateDiagnosticPropertiesForMissingMembersDiagnostic( + mode, + missingCollectionMethods), + marshallerType.ToDisplayString(), + mode, + managedType.ToDisplayString()); + } + } + } + } + + if (ManualTypeMarshallingHelper.ModeUsesUnmanagedToManagedShape(mode)) + { + // If the marshaller mode uses the unmanaged->managed shapes, + // verify that we have a full unmanaged-to-managed shape + if ((shape & (MarshallerShape.ToManaged | MarshallerShape.GuaranteedUnmarshal)) == 0) + { + // Verify that all of the following methods are present with valid shapes: + // - ToManaged or ToManagedFinally + // - FromUnmanaged + if (methods.ToManaged is null && methods.ToManagedGuaranteed is null) + { + diagnosticReporter.CreateAndReportDiagnostic( + StatefulMarshallerRequiresToManagedRule, + MissingMemberNames.CreateDiagnosticPropertiesForMissingMembersDiagnostic( + mode, + ShapeMemberNames.Value.Stateful.ToManaged), + marshallerType.ToDisplayString(), + mode, + managedType.ToDisplayString()); + } + + if (fromUnmanagedCandidates.Length == 0) + { + diagnosticReporter.CreateAndReportDiagnostic( + StatefulMarshallerRequiresFromUnmanagedRule, + MissingMemberNames.CreateDiagnosticPropertiesForMissingMembersDiagnostic( + mode, + ShapeMemberNames.Value.Stateful.FromUnmanaged), + marshallerType.ToDisplayString(), + mode, + managedType.ToDisplayString()); + } + + if (fromUnmanagedCandidates.Length > 1) + { + diagnosticReporter.CreateAndReportDiagnostic( + FromUnmanagedOverloadsNotSupportedRule, + marshallerType.ToDisplayString()); + } + + if (isLinearCollectionMarshaller) + { + // Verify that all of the following methods are present with valid shapes: + // - GetUnmanagedValuesSource + // - GetManagedValuesDestination + List missingCollectionMethods = new(); + if (methods.UnmanagedValuesSource is null) + { + missingCollectionMethods.Add(ShapeMemberNames.LinearCollection.Stateful.GetUnmanagedValuesSource); + } + if (methods.ManagedValuesDestination is null) + { + missingCollectionMethods.Add(ShapeMemberNames.LinearCollection.Stateful.GetManagedValuesDestination); + } + if (missingCollectionMethods.Count > 0) + { + diagnosticReporter.CreateAndReportDiagnostic( + LinearCollectionOutRequiresCollectionMethodsRule, + MissingMemberNames.CreateDiagnosticPropertiesForMissingMembersDiagnostic( + mode, + missingCollectionMethods), + marshallerType.ToDisplayString(), + mode, + managedType.ToDisplayString()); + } + } + } + } + + if (methods.Free is null) + { + diagnosticReporter.CreateAndReportDiagnostic( + StatefulMarshallerRequiresFreeRule, + MissingMemberNames.CreateDiagnosticPropertiesForMissingMembersDiagnostic( + mode, + ShapeMemberNames.Free), + marshallerType.ToDisplayString()); + } + } + + void ReportDiagnosticsForMismatchedMemberSignatures(DiagnosticReporter diagnosticReporter) + { + // Verify that the unmanaged type used by the marshaller is consistently + // the same in all of the methods that use the unmanaged type. + // Also, verify that the collection element types are consistent. + ITypeSymbol? unmanagedType = null; + if (ManualTypeMarshallingHelper.ModeUsesManagedToUnmanagedShape(mode)) + { + // First verify all usages in the managed->unmanaged shape. + unmanagedType = methods.ToUnmanaged.ReturnType; + if (!unmanagedType.IsUnmanagedType && !unmanagedType.IsStrictlyBlittable()) + { + diagnosticReporter.CreateAndReportDiagnostic(UnmanagedTypeMustBeUnmanagedRule, methods.ToUnmanaged.ToDisplayString()); + } + } + + if (ManualTypeMarshallingHelper.ModeUsesUnmanagedToManagedShape(mode)) + { + // Verify the unmanaged types match unmanaged->managed shape + IMethodSymbol fromUnmanagedMethod = fromUnmanagedCandidates[0]; + if (unmanagedType is not null && !SymbolEqualityComparer.Default.Equals(unmanagedType, fromUnmanagedMethod.Parameters[0].Type)) + { + // If both shapes are present, verify that the unmanaged types match + diagnosticReporter.CreateAndReportDiagnostic(FirstParameterMustMatchReturnTypeRule, fromUnmanagedMethod.ToDisplayString(), methods.ToUnmanaged.ToDisplayString()); + } + else + { + unmanagedType = fromUnmanagedMethod.Parameters[0].Type; + + if (!unmanagedType.IsUnmanagedType && !unmanagedType.IsStrictlyBlittable()) + { + diagnosticReporter.CreateAndReportDiagnostic(UnmanagedTypeMustBeUnmanagedRule, fromUnmanagedMethod.ToDisplayString()); + } + } + } + + // Verify that the managed collection element types match. + // Verify that the unmanaged collection types have the expected element types. + if (isLinearCollectionMarshaller) + { + if (methods.ManagedValuesSource is not null && methods.ManagedValuesDestination is not null) + { + if (TryGetElementTypeFromSpanType(methods.ManagedValuesSource.ReturnType, out ITypeSymbol sourceElementType) + && TryGetElementTypeFromSpanType(methods.ManagedValuesDestination.ReturnType, out ITypeSymbol destinationElementType) + && !SymbolEqualityComparer.Default.Equals(sourceElementType, destinationElementType)) + { + diagnosticReporter.CreateAndReportDiagnostic(ElementTypesOfReturnTypesMustMatchRule, methods.ManagedValuesSource.ToDisplayString(), methods.ManagedValuesDestination.ToDisplayString()); + } + } + + var (typeArguments, _) = marshallerType.GetAllTypeArgumentsIncludingInContainingTypes(); + ITypeSymbol expectedUnmanagedCollectionElementType = typeArguments[typeArguments.Length - 1]; + VerifyUnmanagedCollectionElementType(diagnosticReporter, methods.UnmanagedValuesSource, expectedUnmanagedCollectionElementType, _readOnlySpanOfT); + VerifyUnmanagedCollectionElementType(diagnosticReporter, methods.UnmanagedValuesDestination, expectedUnmanagedCollectionElementType, _spanOfT); + } + } } } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/FixAllContextExtensions.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/FixAllContextExtensions.cs new file mode 100644 index 00000000000000..b41ab483e5251f --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/FixAllContextExtensions.cs @@ -0,0 +1,75 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeFixes; + +namespace Microsoft.Interop.Analyzers +{ + internal static class FixAllContextExtensions + { + public static async Task> GetDiagnosticsInScopeAsync(this FixAllContext context) + { + switch (context.Scope) + { + case FixAllScope.Document: + return await context.GetDocumentDiagnosticsAsync(context.Document).ConfigureAwait(false); + case FixAllScope.Project: + return await context.GetAllDiagnosticsAsync(context.Project).ConfigureAwait(false); + case FixAllScope.Solution: + Solution solution = context.Solution; + ProjectDependencyGraph dependencyGraph = solution.GetProjectDependencyGraph(); + + // Walk through each project in topological order, determining and applying the diagnostics for each + // project. We do this in topological order so that the compilations for successive projects are readily + // available as we just computed them for dependent projects. If we were to do it out of order, we might + // start with a project that has a ton of dependencies, and we'd spend an inordinate amount of time just + // building the compilations for it before we could proceed. + // + // By processing one project at a time, we can also let go of a project once done with it, allowing us to + // reclaim lots of the memory so we don't overload the system while processing a large solution. + // + // Note: we have to filter down to projects of the same language as the FixAllContext points at a + // CodeFixProvider, and we can't call into providers of different languages with diagnostics from a + // different language. + IEnumerable sortedProjects = dependencyGraph.GetTopologicallySortedProjects(context.CancellationToken) + .Select(solution.GetProject) + .Where(p => p.Language == context.Project.Language); + return (await Task.WhenAll(sortedProjects.Select(context.GetAllDiagnosticsAsync)).ConfigureAwait(false)).SelectMany(diag => diag).ToImmutableArray(); + default: + return ImmutableArray.Empty; + } + } + + public static async Task> GetProjectsWithDiagnosticsAsync(this FixAllContext context) + { + switch (context.Scope) + { + case FixAllScope.ContainingMember: + case FixAllScope.ContainingType: + case FixAllScope.Document: + case FixAllScope.Project: + return ImmutableArray.Create(context.Project); + case FixAllScope.Solution: + ImmutableArray.Builder projectsWithDiagnostics = ImmutableArray.CreateBuilder(); + foreach (var project in context.Solution.Projects) + { + ImmutableArray diagnostics = await context.GetAllDiagnosticsAsync(project).ConfigureAwait(false); + if (diagnostics.Length != 0) + { + projectsWithDiagnostics.Add(project); + } + } + return projectsWithDiagnostics.ToImmutable(); + default: + return ImmutableArray.Empty; + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs index 27a44131d8dc1f..1da4dbd49afeca 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs @@ -327,65 +327,10 @@ private static IncrementalStubGenerationContext CalculateStubInformation( new MethodSignatureDiagnosticLocations(originalSyntax), additionalAttributes.ToImmutableArray(), libraryImportData, - CreateGeneratorFactory(environment, options), + LibraryImportGeneratorHelpers.CreateGeneratorFactory(environment, options), generatorDiagnostics.Diagnostics.ToImmutableArray()); } - private static MarshallingGeneratorFactoryKey<(TargetFramework, Version, LibraryImportGeneratorOptions)> CreateGeneratorFactory(StubEnvironment env, LibraryImportGeneratorOptions options) - { - IMarshallingGeneratorFactory generatorFactory; - - if (options.GenerateForwarders) - { - generatorFactory = new ForwarderMarshallingGeneratorFactory(); - } - else - { - if (env.TargetFramework != TargetFramework.Net || env.TargetFrameworkVersion.Major < 7) - { - // If we're using our downstream support, fall back to the Forwarder marshaller when the TypePositionInfo is unhandled. - generatorFactory = new ForwarderMarshallingGeneratorFactory(); - } - else - { - // If we're in a "supported" scenario, then emit a diagnostic as our final fallback. - generatorFactory = new UnsupportedMarshallingFactory(); - } - - generatorFactory = new NoMarshallingInfoErrorMarshallingFactory(generatorFactory); - - // The presence of System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute is tied to TFM, - // so we use TFM in the generator factory key instead of the Compilation as the compilation changes on every keystroke. - IAssemblySymbol coreLibraryAssembly = env.Compilation.GetSpecialType(SpecialType.System_Object).ContainingAssembly; - ITypeSymbol? disabledRuntimeMarshallingAttributeType = coreLibraryAssembly.GetTypeByMetadataName(TypeNames.System_Runtime_CompilerServices_DisableRuntimeMarshallingAttribute); - bool runtimeMarshallingDisabled = disabledRuntimeMarshallingAttributeType is not null - && env.Compilation.Assembly.GetAttributes().Any(attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, disabledRuntimeMarshallingAttributeType)); - - // Since the char type can go into the P/Invoke signature here, we can only use it when - // runtime marshalling is disabled. - generatorFactory = new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: runtimeMarshallingDisabled); - - InteropGenerationOptions interopGenerationOptions = new(options.UseMarshalType); - generatorFactory = new MarshalAsMarshallingGeneratorFactory(interopGenerationOptions, generatorFactory); - - IMarshallingGeneratorFactory elementFactory = new AttributedMarshallingModelGeneratorFactory( - // Since the char type in an array will not be part of the P/Invoke signature, we can - // use the regular blittable marshaller in all cases. - new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: true), - new AttributedMarshallingModelOptions(runtimeMarshallingDisabled, MarshalMode.ElementIn, MarshalMode.ElementRef, MarshalMode.ElementOut)); - // We don't need to include the later generator factories for collection elements - // as the later generator factories only apply to parameters. - generatorFactory = new AttributedMarshallingModelGeneratorFactory( - generatorFactory, - elementFactory, - new AttributedMarshallingModelOptions(runtimeMarshallingDisabled, MarshalMode.ManagedToUnmanagedIn, MarshalMode.ManagedToUnmanagedRef, MarshalMode.ManagedToUnmanagedOut)); - - generatorFactory = new ByValueContentsMarshalKindValidator(generatorFactory); - } - - return MarshallingGeneratorFactoryKey.Create((env.TargetFramework, env.TargetFrameworkVersion, options), generatorFactory); - } - private static (MemberDeclarationSyntax, ImmutableArray) GenerateSource( IncrementalStubGenerationContext pinvokeStub, LibraryImportGeneratorOptions options) diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGeneratorHelpers.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGeneratorHelpers.cs new file mode 100644 index 00000000000000..80e48ed6510c64 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGeneratorHelpers.cs @@ -0,0 +1,69 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.CodeAnalysis; + +namespace Microsoft.Interop +{ + internal static class LibraryImportGeneratorHelpers + { + public static MarshallingGeneratorFactoryKey<(TargetFramework, Version, LibraryImportGeneratorOptions)> CreateGeneratorFactory(StubEnvironment env, LibraryImportGeneratorOptions options) + { + IMarshallingGeneratorFactory generatorFactory; + + if (options.GenerateForwarders) + { + generatorFactory = new ForwarderMarshallingGeneratorFactory(); + } + else + { + if (env.TargetFramework != TargetFramework.Net || env.TargetFrameworkVersion.Major < 7) + { + // If we're using our downstream support, fall back to the Forwarder marshaller when the TypePositionInfo is unhandled. + generatorFactory = new ForwarderMarshallingGeneratorFactory(); + } + else + { + // If we're in a "supported" scenario, then emit a diagnostic as our final fallback. + generatorFactory = new UnsupportedMarshallingFactory(); + } + + generatorFactory = new NoMarshallingInfoErrorMarshallingFactory(generatorFactory); + + // The presence of System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute is tied to TFM, + // so we use TFM in the generator factory key instead of the Compilation as the compilation changes on every keystroke. + IAssemblySymbol coreLibraryAssembly = env.Compilation.GetSpecialType(SpecialType.System_Object).ContainingAssembly; + ITypeSymbol? disabledRuntimeMarshallingAttributeType = coreLibraryAssembly.GetTypeByMetadataName(TypeNames.System_Runtime_CompilerServices_DisableRuntimeMarshallingAttribute); + bool runtimeMarshallingDisabled = disabledRuntimeMarshallingAttributeType is not null + && env.Compilation.Assembly.GetAttributes().Any(attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, disabledRuntimeMarshallingAttributeType)); + + // Since the char type can go into the P/Invoke signature here, we can only use it when + // runtime marshalling is disabled. + generatorFactory = new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: runtimeMarshallingDisabled); + + InteropGenerationOptions interopGenerationOptions = new(options.UseMarshalType); + generatorFactory = new MarshalAsMarshallingGeneratorFactory(interopGenerationOptions, generatorFactory); + + IMarshallingGeneratorFactory elementFactory = new AttributedMarshallingModelGeneratorFactory( + // Since the char type in an array will not be part of the P/Invoke signature, we can + // use the regular blittable marshaller in all cases. + new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: true), + new AttributedMarshallingModelOptions(runtimeMarshallingDisabled, MarshalMode.ElementIn, MarshalMode.ElementRef, MarshalMode.ElementOut)); + // We don't need to include the later generator factories for collection elements + // as the later generator factories only apply to parameters. + generatorFactory = new AttributedMarshallingModelGeneratorFactory( + generatorFactory, + elementFactory, + new AttributedMarshallingModelOptions(runtimeMarshallingDisabled, MarshalMode.ManagedToUnmanagedIn, MarshalMode.ManagedToUnmanagedRef, MarshalMode.ManagedToUnmanagedOut)); + + generatorFactory = new ByValueContentsMarshalKindValidator(generatorFactory); + } + + return MarshallingGeneratorFactoryKey.Create((env.TargetFramework, env.TargetFrameworkVersion, options), generatorFactory); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/Strings.resx b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/Strings.resx index 8ffbfe9aaa35ca..8224ad74f4b73f 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/Strings.resx +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/Strings.resx @@ -117,16 +117,16 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing a 'FromManaged' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has a FromManaged method that takes a caller-allocated 'Span<{1}>' - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' @@ -174,10 +174,6 @@ Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time - - Conversion to 'LibraryImport' may change behavior and compatibility. See {0} for more information. - {0} is a documentation link - Convert to 'LibraryImport' with '{0}' suffix @@ -379,7 +375,7 @@ Overloading the 'FromUnmanaged' method is unuspported as some shapes are unable to distinguish between overloads. - Overloading the 'FromUnmanaged' method is not supported in custom marshallers + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers The return type of 'ConvertToUnmanaged' and the parameter type of 'ConvertToManaged' must be the same. @@ -447,6 +443,12 @@ The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. + + A marshaller for an element scenario cannot be stateful. + + + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + LibraryImportAttribute requires unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. @@ -456,4 +458,43 @@ LibraryImportAttribute requires unsafe code. - \ No newline at end of file + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + + + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + + + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + + + Convert to 'LibraryImport' and enable unsafe code + + + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + + + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + + diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.cs.xlf b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.cs.xlf index f764acb2021ffe..533d6cfcc411b9 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.cs.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.cs.xlf @@ -7,12 +7,12 @@ Přidat chybějící vlastní typu zařazovacích členů - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing a 'FromManaged' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. Pokud se obrazec „Ze spravovaných na nespravované s vyrovnávací pamětí přidělenou volajícímu“ používá metodou FromManaged, která přebírá Span<T> u zařazovacího typu, musí typ poskytovat statickou vlastnost BufferSize, která určuje počet elementů ve vyrovnávací paměti přidělené volajícímu. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has a FromManaged method that takes a caller-allocated 'Span<{1}>' Zařazovací typ {0} musí obsahovat statickou celočíselnou vlastnost BufferSize určenou jen pro čtení, která určuje velikost vyrovnávací paměti přidělené volajícímu, protože obsahuje metodu FromManaged, která přebírá Span<{1}> přidělený volajícímu. @@ -77,11 +77,21 @@ Převést na LibraryImport + + Convert to 'LibraryImport' and enable unsafe code + Convert to 'LibraryImport' and enable unsafe code + + Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time K vygenerování kódu zařazování P/Invoke v době kompilace použijte LibraryImportAttribute místo DllImportAttribute + + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + + Mark the method '{0}' with 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time Označit metodu {0} pomocí LibraryImportAttribute místo DllImportAttribute, aby došlo k vygenerování kódu zařazování volání P/Invoke za kompilace. @@ -92,21 +102,31 @@ K vygenerování kódu zařazování P/Invoke v době kompilace použijte LibraryImportAttribute místo DllImportAttribute - - Conversion to 'LibraryImport' may change behavior and compatibility. See {0} for more information. - Převod na LibraryImport může vést ke změně chování a kompatibility. Zjistěte více informací přechodem na {0}. - {0} is a documentation link - Convert to 'LibraryImport' with '{0}' suffix Převést na LibraryImport s příponou {0} + + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + + Marshaller type does not have the required shape Zařazovací typ nemá požadovaný tvar + + A marshaller for an element scenario cannot be stateful. + A marshaller for an element scenario cannot be stateful. + + + + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + + The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. @@ -153,8 +173,8 @@ - Overloading the 'FromUnmanaged' method is not supported in custom marshallers - Přetížení metody FromUnmanaged není u vlastního zařazování podporováno. + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers @@ -377,12 +397,62 @@ The return type of '{0}' must be the same type as the return type of '{1}' - + + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + + + + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller + + + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.de.xlf b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.de.xlf index 437754bed8df13..8096f6b1edbcf0 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.de.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.de.xlf @@ -7,12 +7,12 @@ Hinzufügen fehlender benutzerdefinierter Marshallermember - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing a 'FromManaged' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. Wenn die Form "Verwaltet bis nicht verwaltet mit Caller-Allocated Buffer" verwendet wird, indem eine Methode "FromManaged" bereitgestellt wird, die eine "Span<T>" für den Marshallertyp akzeptiert, muss der Typ eine statische Eigenschaft "BufferSize" bereitstellen, um die Anzahl von Elementen im vom Aufrufer zugewiesenen Puffer anzugeben. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has a FromManaged method that takes a caller-allocated 'Span<{1}>' Der Marshallertyp "{0}" muss eine statische schreibgeschützte "int"-Eigenschaft "BufferSize" aufweisen, um die Größe des vom Aufrufer zugewiesenen Puffers anzugeben, da er eine FromManaged-Methode aufweist, die eine vom Aufrufer zugewiesene "Span<{1}>" akzeptiert @@ -77,11 +77,21 @@ In \"LibraryImport\" konvertieren + + Convert to 'LibraryImport' and enable unsafe code + Convert to 'LibraryImport' and enable unsafe code + + Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time Verwenden Sie \"LibraryImportAttribute\" anstelle von \"DllImportAttribute\", um P/Invoke-Marshallingcode zur Kompilierzeit zu generieren. + + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + + Mark the method '{0}' with 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time Markieren Sie die Methode \"{0}\" mit \"LibraryImportAttribute\" anstelle von \"DllImportAttribute\", um zur Kompilierzeit P/Invoke-Marshallingcode zu generieren. @@ -92,21 +102,31 @@ Verwenden Sie \"LibraryImportAttribute\" anstelle von \"DllImportAttribute\", um P/Invoke-Marshallingcode zur Kompilierzeit zu generieren. - - Conversion to 'LibraryImport' may change behavior and compatibility. See {0} for more information. - Die Konvertierung in \"LibraryImport\" kann das Verhalten und die Kompatibilität ändern. Weitere Informationen finden Sie unter {0}. - {0} is a documentation link - Convert to 'LibraryImport' with '{0}' suffix In \"LibraryImport\" mit Suffix \"{0}\" konvertieren + + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + + Marshaller type does not have the required shape Der Marshaller-Typ weist nicht die erforderliche Form auf + + A marshaller for an element scenario cannot be stateful. + A marshaller for an element scenario cannot be stateful. + + + + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + + The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. @@ -153,8 +173,8 @@ - Overloading the 'FromUnmanaged' method is not supported in custom marshallers - Das Überladen der Methode "FromUnmanaged" wird in benutzerdefinierten Marshallern nicht unterstützt + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers @@ -377,12 +397,62 @@ The return type of '{0}' must be the same type as the return type of '{1}' - + + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + + + + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller + + + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.es.xlf b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.es.xlf index 00e16441772de4..a35812f21c00a7 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.es.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.es.xlf @@ -7,12 +7,12 @@ Agregue los miembros de serializador de tipo personalizado que faltan - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing a 'FromManaged' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. Cuando la forma "Administrado a no administrado con búfer asignado por el llamador" se usa con un método "FromManaged" que toma un "Span<T>" en el tipo de serializador, el tipo debe proporcionar una propiedad estática "BufferSize" para proporcionar el número de elementos en el búfer asignado por el llamador. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has a FromManaged method that takes a caller-allocated 'Span<{1}>' El tipo de serializador "{0}" debe tener una propiedad "int" "BufferSize" estática de solo lectura para especificar el tamaño del búfer asignado por el autor de la llamada porque tiene un método FromManaged que toma una propiedad "Span<{1}>" asignada por el autor de la llamada. @@ -39,7 +39,7 @@ The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + La configuración de "{0}" no está admitida por P/Invokes de un generador de código fuente. Si se requiere la configuración, use un "DllImport" normal en su lugar. @@ -49,17 +49,17 @@ The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + La configuración de "{0}" especificada para el parámetro "{1}" no es compatible con P/Invokes de un generador de código fuente. Si se requiere la configuración especificada, use un "DllImport" normal en su lugar. The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + La configuración de "{0}" especificada para el valor devuelto del método "{1}" no es compatible con P/Invokes generados por origen. Si se requiere la configuración especificada, use un "DllImport" normal en su lugar. The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. - The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. + El valor especificado de "{0}" para "{1}" no es compatible con P/Invokes de un generador de código fuente. Si se requiere el valor especificado, use un "DllImport" normal en su lugar. @@ -77,11 +77,21 @@ Convertir en “LibraryImport” + + Convert to 'LibraryImport' and enable unsafe code + Convert to 'LibraryImport' and enable unsafe code + + Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time Use “LibraryImportAttribute” en lugar de “DllImportAttribute” para generar código de serialización P/Invoke en el tiempo de compilación + + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + + Mark the method '{0}' with 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time Marque el método “{0}” con “LibraryImportAttribute” en lugar de “DllImportAttribute” para generar código de serialización P/Invoke en el tiempo de compilación @@ -92,29 +102,39 @@ Use “LibraryImportAttribute” en lugar de “DllImportAttribute” para generar código de serialización P/Invoke en el tiempo de compilación - - Conversion to 'LibraryImport' may change behavior and compatibility. See {0} for more information. - La conversión a “LibraryImport” debe cambiar de comportamiento y compatibilidad. Vea {0} para obtener más información. - {0} is a documentation link - Convert to 'LibraryImport' with '{0}' suffix Convertir a “LibraryImport” con sufijo “{0}” + + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + + Marshaller type does not have the required shape El tipo de serializador no tiene la forma necesaria + + A marshaller for an element scenario cannot be stateful. + A marshaller for an element scenario cannot be stateful. + + + + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + + The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. - The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. + El tipo de elemento del intervalo devuelto por el primer método debe ser del mismo tipo que el tipo de elemento del intervalo devuelto por el segundo método. The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. - The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. + El tipo de elemento del intervalo devuelto por "{0}" debe ser del mismo tipo que el tipo de elemento del intervalo devuelto por "{1}". @@ -129,22 +149,22 @@ The first parameter of the first method must be the same type as the return types of the second method. - The first parameter of the first method must be the same type as the return types of the second method. + El primer parámetro del primer método debe ser del mismo tipo que los tipos devueltos del segundo método. The first parameter of '{0}' must be the same type as the return type of '{1}' - The first parameter of '{0}' must be the same type as the return type of '{1}' + El primer parámetro de "{0}" debe ser del mismo tipo que el tipo de valor devuelto de "{1}" The first parameters of the two methods must be the same type. - The first parameters of the two methods must be the same type. + Los primeros parámetros de los dos métodos deben ser del mismo tipo. The first parameter of '{0}' and '{1}' must be the same type - The first parameter of '{0}' and '{1}' must be the same type + El primer parámetro de "{0}" y "{1}" deben ser del mismo tipo @@ -153,8 +173,8 @@ - Overloading the 'FromUnmanaged' method is not supported in custom marshallers - No se admite la sobrecarga del método "FromUnmanaged" en los serializadores personalizados + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers @@ -184,7 +204,7 @@ Invalid 'CustomMarshallerAttribute' usage - Invalid 'CustomMarshallerAttribute' usage + Uso de "CustomMarshallerAttribute" no válido @@ -204,7 +224,7 @@ Invalid 'NativeMarshallingAttribute' usage - Invalid 'NativeMarshallingAttribute' usage + Uso de "NativeMarshallingAttribute" no válido @@ -254,22 +274,22 @@ A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. + Un serializador de colección contigua que admita la serialización de administrado a no administrado debe proporcionar un "GetManagedValuesSource" que devuelva un valor de "ReadOnlySpan<>" y un método "GetUnmanagedValuesDestination" que devuelva un valor de "Span<>". The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' + El tipo "{0}" especifica que admite el modo de serialización "{1}", pero no proporciona un "GetManagedValuesSource" que devuelva un "ReadOnlySpan<>" y un método "GetNativeValuesDestination" que devuelva un "Span<>" A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. + Un serializador de colección contigua que admita serializaciones de no administrado a administrado debe proporcionar un método 'GetManagedValuesDestination' que tome "int" y devuelva un "Span<>" y un método "GetUnmanagedValuesSource" que tome "int" y devuelva "ReadOnlySpan<>". The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' + El tipo "{0}" especifica que admite el modo de serialización "{1}", pero no proporciona un "GetManagedValuesDestination" que tome un "int" y devuelva un "Span<>" y un método "GetUnmanagedValuesSource" que tome un "int" y devuelva un "ReadOnlySpan<>" @@ -314,12 +334,12 @@ A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. - A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. + Un tipo de serializador debe ser una clase estática sin estado o un tipo de valor con estado. No se permite una clase no estática. The type '{0}' must be a static class or a value type - The type '{0}' must be a static class or a value type + El tipo "{0}" debe ser una clase estática o un tipo de valor @@ -359,92 +379,142 @@ The return type the two method must be the expected type. - The return type the two method must be the expected type. + El tipo de valor devuelto por el que ambos métodos deben ser del tipo esperado. The return type of '{0}' must be '{1}' - The return type of '{0}' must be '{1}' + El tipo de valor devuelto de "{0}" debe ser "{1}" The return types of the two methods must be the same type. - The return types of the two methods must be the same type. + Los tipos devueltos de los dos métodos deben ser del mismo tipo. The return type of '{0}' must be the same type as the return type of '{1}' - The return type of '{0}' must be the same type as the return type of '{1}' + El tipo de valor devuelto de "{0}" debe ser del mismo tipo que el tipo de valor devuelto de "{1}" + + + + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + + + + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. - When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. + Cuando la forma "Administrado a no administrado con búfer asignado por el llamador" se usa con un método "AllocateContainerForUnmanagedElements" que toma un "Span<T>" en el tipo de serializador, el tipo debe proporcionar una propiedad estática "BufferSize" para proporcionar el número de elementos en el búfer asignado por el llamador. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' - The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' + El tipo de serializador "{0}" debe tener una propiedad "int" "BufferSize" estática de solo lectura para especificar el tamaño del búfer asignado por el autor de la llamada porque tiene un método "AllocateContainerForUnmanagedElements" que toma una propiedad "Span<{1}>" A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + Un serializador de colección contigua que admita serializaciones de administrado a administrado debe proporcionar un método "GetManagedValuesSource" que tome el valor administrado y devuelva un "'ReadOnlySpan<>" y un método "GetUnmanagedValuesDestination" que tome el valor no administrado como perámetro y devuelva "Span<>" The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + El tipo "{0}" especifica que admite el modo de serialización "{1}", pero no proporciona un "GetManagedValuesSource" que tome como parámetro un "{2}" y devuelva un "ReadOnlySpan<>" y un método "GetUnmanagedValuesDestination" que tome como parámetro un valor no administrado y devuelva un "Span<>" A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. + Un serializador de colección contigua que admita serializaciones de no administrado a administrado debe proporcionar un método "GetManagedValuesDestination" que tome el valor administrado y devuelva un "Span<>" y un método "GetUnmanagedValuesSource" que tome el valor no administrado y "int" y devuelva "ReadOnlySpan<>". The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' + El tipo "{0}" especifica que admite el modo de serialización "{1}", pero no proporciona un "GetManagedValuesDestination" que tome un "{2}" y devuelva un "Span<>" y un método "GetUnmanagedValuesSource" que tome el valor no administrado y un "int" y devuelva un "ReadOnlySpan<>" A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter + Un serializador de colección contigua sin estado que admita serializaciones de administrado a no administrado debe proporcionar un método "AllocateContainerForManagedElements" que tome el tipo no administrado como primer parámetro y el número de elementos como parámetro "int" The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter + El tipo "{0}" especifica que admite el modo de serialización "{1}" para "{2}", pero no proporciona un método "AllocateContainerForUnmanagedElements" de dos parámetros que toma el tipo no administrado como primer parámetro y "int" como segundo parámetro A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter + Un serializador de colección contigua sin estado que admita serializaciones de administrado a no administrado debe proporcionar un método "AllocateContainerForManagedElements" que tome el tipo administrado como primer parámetro y que proporcione el número de elementos como parámetro "out int" The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter + El tipo "{0}" especifica que admite el modo de serialización "{1}" para "{2}", pero no proporciona un método "AllocateContainerForUnmanagedElements" de dos parámetros que toma "{2}" como primer parámetro y "out int" como segundo parámetro A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. - A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. + Un serializador de valores sin estado que admita la serialización de no administrado a administrado debe proporcionar un método "ConvertToManaged" que tome el tipo no administrado como parámetro y devuelva el tipo administrado. The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' - The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' + El tipo "{0}" especifica que admite el modo de serialización "{1}", pero no proporciona un método "ConvertToManaged" que toma el tipo no administrado como parámetro y devuelve "{2}" A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. - A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. + Un serializador de valores sin estado que admita la serialización de administrado a no administrado debe proporcionar un método "ConvertToUnmanaged" de un parámetro que tome el valor administrado como parámetro y devuelva un valor del tipo "no administrado". The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type + El tipo "{0}" especifica que admite el modo de serialización "{1}" para "{2}" pero no proporciona un método "ConvertToUnmanaged" de un solo parámetro que toma un "{2}" como parámetro y devuelve un valor de un tipo "no administrado". @@ -459,12 +529,12 @@ The unmanaged type for a custom marshaller must be a C# unmanaged type. - The unmanaged type for a custom marshaller must be a C# unmanaged type. + El tipo no administrado de un serializador personalizado debe ser un tipo no administrado de C#. The return type of '{0}' must be unmanaged - The return type of '{0}' must be unmanaged + El tipo de valor devuelto de "{0}" debe ser no administrado diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.fr.xlf b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.fr.xlf index 6b40f33ddb9901..1b5c292a026a6e 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.fr.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.fr.xlf @@ -7,12 +7,12 @@ Ajouter les membres du marshaleur de type personnalisé manquants - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing a 'FromManaged' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. Lorsque la forme « Managée à non managée avec mémoire tampon allouée par l’appelant » est utilisée en fournissant une méthode « FromManaged » qui prend un « Span<T> » sur le type marshaler, le type doit fournir une propriété « BufferSize » statique pour fournir le nombre d’éléments dans la mémoire tampon allouée par l’appelant. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has a FromManaged method that takes a caller-allocated 'Span<{1}>' Le type de marshaleur « {0} » doit avoir une propriété « BufferSize » en lecture seule « int » statique pour spécifier la taille de la mémoire tampon allouée par l’appelant, car elle a une méthode FromManaged qui accepte un « Span<{1}> » alloué par l’appelant @@ -39,7 +39,7 @@ The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + La configuration '{0}' n’est pas prise en charge par les appels/P générés par la source. Si la configuration spécifiée est requise, utilisez plutôt un 'DllImport' standard. @@ -49,17 +49,17 @@ The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + La configuration '{0}' spécifiée pour le paramètre '{1}' n’est pas prise en charge par les P/Invokes générés par la source. Si la configuration spécifiée est requise, utilisez plutôt un 'DllImport' standard. The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + La configuration '{0}' spécifiée pour la valeur de retour de la méthode '{1}' n’est pas prise en charge par les P/Invokes générés par la source. Si la configuration spécifiée est requise, utilisez plutôt un 'DllImport' standard. The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. - The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. + La valeur spécifiée '{0}' pour '{1}' n’est pas prise en charge par les P/Invokes générés par la source. Si la valeur spécifiée est requise, utilisez un 'DllImport' standard à la place. @@ -77,11 +77,21 @@ Convertir en « LibraryImport » + + Convert to 'LibraryImport' and enable unsafe code + Convert to 'LibraryImport' and enable unsafe code + + Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time Utilisez « LibraryImportAttribute » à la place de « DllImportAttribute » pour générer du code de marshaling P/Invoke au moment de la compilation + + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + + Mark the method '{0}' with 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time Marquer la méthode « {0} » avec « LibraryImportAttribute » à la place de « DllImportAttribute » pour générer du code de marshaling P/Invoke au moment de la compilation @@ -92,29 +102,39 @@ Utilisez « LibraryImportAttribute » à la place de « DllImportAttribute » pour générer du code de marshaling P/Invoke au moment de la compilation - - Conversion to 'LibraryImport' may change behavior and compatibility. See {0} for more information. - La conversion en « LibraryImport » peut modifier le comportement et la compatibilité. Pour plus d’informations, consultez {0}. - {0} is a documentation link - Convert to 'LibraryImport' with '{0}' suffix Convertir en « LibraryImport » avec suffixe « {0} » + + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + + Marshaller type does not have the required shape Le type Marshaller n’a pas la forme requise + + A marshaller for an element scenario cannot be stateful. + A marshaller for an element scenario cannot be stateful. + + + + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + + The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. - The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. + Le type d’élément de l’étendue retournée par la première méthode doit être du même type que le type d’élément de l’étendue retournée par la deuxième méthode. The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. - The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. + Le type d’élément de l’étendue retournée par '{0}' doit être du même type que le type d’élément de l’étendue retournée par '{1}'. @@ -129,22 +149,22 @@ The first parameter of the first method must be the same type as the return types of the second method. - The first parameter of the first method must be the same type as the return types of the second method. + Le premier paramètre de la première méthode doit être du même type que les types de retour de la deuxième méthode. The first parameter of '{0}' must be the same type as the return type of '{1}' - The first parameter of '{0}' must be the same type as the return type of '{1}' + Le premier paramètre de '{0}' doit être du même type que le type de retour de '{1}' The first parameters of the two methods must be the same type. - The first parameters of the two methods must be the same type. + Les premiers paramètres des deux méthodes doivent être du même type. The first parameter of '{0}' and '{1}' must be the same type - The first parameter of '{0}' and '{1}' must be the same type + Le premier paramètre de '{0}' et '{1}' doit être du même type @@ -153,8 +173,8 @@ - Overloading the 'FromUnmanaged' method is not supported in custom marshallers - La surcharge de la méthode « FromUnmanaged » n’est pas prise en charge dans les marshaleurs personnalisés + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers @@ -184,7 +204,7 @@ Invalid 'CustomMarshallerAttribute' usage - Invalid 'CustomMarshallerAttribute' usage + Utilisation de 'CustomMarshallerAttribute' non valide @@ -204,7 +224,7 @@ Invalid 'NativeMarshallingAttribute' usage - Invalid 'NativeMarshallingAttribute' usage + Utilisation de 'NativeMarstribuingAttribute' non valide @@ -254,22 +274,22 @@ A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. + Un marshaleur de collection contigu qui prend en charge le marshaling de managé à non managé doit fournir un 'GetManagedValuesSource' qui retourne un 'ReadOnlySpan<>' et une méthode 'GetUnmanagedValuesDestination' qui retourne un 'Span<>'. The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' + Le type '{0}' spécifie qu’il prend en charge le mode marshal '{1}', mais il ne fournit pas de 'GetManagedValuesSource' qui retourne un 'ReadOnlySpan<>' et une méthode 'GetUnmanagedValuesDestination' qui retourne 'Span<>' A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. + Un marshaleur de collection contigu qui prend en charge le marshaling de non managé à managé doit fournir un 'GetManagedValuesDestination' qui prend un 'int' et retourne 'Span<>' et une méthode 'GetUnmanagedValuesSource' qui prend un 'int' et retourne un 'ReadOnlySpan<>'. The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' + Le type '{0}' spécifie qu’il prend en charge le mode marshal '{1}', mais il ne fournit pas de 'GetManagedValuesDestination' qui prend un 'int' et retourne 'Span<>' et une méthode 'GetUnmanagedValuesSource' qui prend un 'int' et retourne un 'ReadOnlySpan<>' @@ -314,12 +334,12 @@ A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. - A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. + Un type de marshaleur doit être une classe statique sans état ou un type valeur avec état. Une classe non statique n’est pas autorisée. The type '{0}' must be a static class or a value type - The type '{0}' must be a static class or a value type + Le type '{0}' doit être une classe statique ou un type valeur @@ -359,92 +379,142 @@ The return type the two method must be the expected type. - The return type the two method must be the expected type. + Le type de retour de la méthode deux doit être le type attendu. The return type of '{0}' must be '{1}' - The return type of '{0}' must be '{1}' + Le type de retour '{0}' doit être '{1}' The return types of the two methods must be the same type. - The return types of the two methods must be the same type. + Les types de retour des deux méthodes doivent être du même type. The return type of '{0}' must be the same type as the return type of '{1}' - The return type of '{0}' must be the same type as the return type of '{1}' + Le type de retour de '{0}' doit être le même que le type de retour de '{1}' + + + + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + + + + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. - When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. + Lorsque la forme 'Managée à non managée avec mémoire tampon allouée par l’appelant' est utilisée en fournissant une méthode 'AllocateContainerForUnmanagedElements' qui prend un 'Span<T>' sur le type marshaler, le type doit fournir une propriété 'BufferSize' statique pour fournir le nombre d’éléments dans la mémoire tampon allouée par l’appelant. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' - The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' + Le type marshaleur '{0}' doit avoir une propriété 'int' 'BufferSize' statique en lecture seule pour spécifier la taille de la mémoire tampon allouée par l’appelant, car elle a une méthode 'AllocateContainerForUnmanagedElements' qui accepte un 'Span<{1}>' alloué par l’appelant A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + Un marshaleur de collection contigu qui prend en charge le marshaling de managé à non managé doit fournir un 'GetManagedValuesSource' qui prend la valeur managée en tant que paramètre et retourne un 'ReadOnlySpan<>' et une méthode 'GetUnmanagedValuesDestination' qui prend la valeur non managée comme paramètre et retourne un 'Span<>' The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + Le type '{0}' spécifie qu’il prend en charge le mode marshal '{1}', mais il ne fournit pas de 'GetManagedValuesSource' qui prend '{2}' comme paramètre et retourne 'ReadOnlySpan<>' et une méthode 'GetUnmanagedValuesDestination' qui prend la valeur non managée comme paramètre et retourne 'Span<>' A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. + Un marshaleur de collection contigu qui prend en charge le marshaling de non managé à managé doit fournir un 'GetManagedValuesDestination' qui prend la valeur managée et retourne un 'Span<>' et une méthode 'GetUnmanagedValuesSource' qui prend la valeur non managée et un 'int' et retourne un 'ReadOnlySpan<>'. The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' + Le type '{0}' spécifie qu’il prend en charge le mode marshal '{1}', mais il ne fournit pas de 'GetManagedValuesDestination' qui prend '{2}' et retourne 'Span<>' et une méthode 'GetUnmanagedValuesSource' qui prend la valeur non managée et un 'int' et retourne un 'ReadOnlySpan<>' A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter + Un marshaleur de collection contigu sans état qui prend en charge le marshaling de managé à non managé doit fournir une méthode 'AllocateContainerForManagedElements' prenant le type non managé comme premier paramètre et le nombre d’éléments en tant que paramètre 'int' The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter + Le type '{0}' spécifie qu’il prend en charge le mode marshal '{1}' pour '{2}', mais ne fournit pas de méthode 'AllocateContainerForManagedElements' à deux paramètres qui prend le type non managé comme premier paramètre et un 'int' comme second paramètre A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter + Un marshaleur de collection contigu sans état qui prend en charge le marshaling de managé à non managé doit fournir une méthode 'AllocateContainerForUnmanagedElements' prenant le type managé comme premier paramètre et en fournissant le nombre d’éléments en tant que paramètre 'out int' The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter + Le type '{0}' spécifie qu’il prend en charge le mode marshal '{1}' pour '{2}', mais ne fournit pas de méthode 'AllocateContainerForUnmanagedElements' à deux paramètres qui accepte '{2}' comme premier paramètre et 'out int' comme second paramètre A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. - A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. + Un marshaleur de valeurs sans état qui prend en charge le marshaling d’un marshaling non managé à managé doit fournir une méthode 'ConvertToManaged' qui prend le type non managé en tant que paramètre et retourne le type managé. The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' - The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' + Le type '{0}' spécifie qu’il prend en charge le mode marshal '{1}', mais il ne fournit pas de méthode 'ConvertToManaged' qui accepte le type non managé comme paramètre et retourne '{2}' A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. - A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. + Un marshaleur de valeurs sans état qui prend en charge le marshaling de managé à non managé doit fournir une méthode 'ConvertToUnmanaged' à paramètre unique qui accepte la valeur managée comme paramètre et retourne une valeur du type 'unmanaged'. The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type + Le type '{0}' spécifie qu’il prend en charge le mode marshal '{1}' pour '{2}' mais ne fournit pas de méthode 'ConvertToUnmanaged' à un paramètre qui accepte un '{2}' comme paramètre et retourne une valeur de type 'unmanaged' @@ -459,12 +529,12 @@ The unmanaged type for a custom marshaller must be a C# unmanaged type. - The unmanaged type for a custom marshaller must be a C# unmanaged type. + Le type non managé d’un marshaleur personnalisé doit être un type non managé C#. The return type of '{0}' must be unmanaged - The return type of '{0}' must be unmanaged + Le type de retour '{0}' doit être non managé diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.it.xlf b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.it.xlf index 2b1955e1573b29..1a9361432ac473 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.it.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.it.xlf @@ -7,12 +7,12 @@ Aggiungi membri mancanti del gestore del marshalling di tipi personalizzato mancanti - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing a 'FromManaged' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. Quando si usa la forma 'Managed to Unmanaged with Caller-Allocated Buffer', fornendo un metodo "FromManaged" che accetta un elemento "Span<T>" per il tipo di marshaller, il tipo deve fornire una proprietà statica "BufferSize" per fornire il numero di elementi nel buffer allocato dal chiamante. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has a FromManaged method that takes a caller-allocated 'Span<{1}>' Il tipo di marshaller '{0}' deve avere una proprietà 'int' 'BufferSize' di sola lettura statica per specificare le dimensioni del buffer allocato dal chiamante perché dispone di un metodo FromManaged che accetta un elemento 'Span<{1}>' allocato dal chiamante @@ -39,7 +39,7 @@ The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + La configurazione '{0}' non è supportata dai P/Invoke generati dall'origine. Se la configurazione specificata è obbligatoria, usa un attributo `DllImport` normale. @@ -49,17 +49,17 @@ The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + La configurazione '{0}' specificata per il parametro '{1}' non è supportata dai P/Invoke generati dall'origine. Se la configurazione specificata è obbligatoria, us un attributo `DllImport` normale. The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + La configurazione '{0}' specificata per il valore restituito del metodo '{1}' non è supportata dai P/Invoke generati dall'origine. Se la configurazione specificata è obbligatoria, usa un attributo `DllImport` normale. The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. - The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. + Il valore specificato '{0}' per '{1}' non è supportato da P/Invoke generati dall'origine. Se il valore specificato è obbligatorio, usa un 'DllImport' normale. @@ -77,11 +77,21 @@ Converti in 'LibraryImport' + + Convert to 'LibraryImport' and enable unsafe code + Convert to 'LibraryImport' and enable unsafe code + + Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time Usare 'LibraryImportAttribute' invece di 'DllImportAttribute' per generare codice di marshalling di P/Invoke in fase di compilazione + + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + + Mark the method '{0}' with 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time Contrassegnare il metodo '{0}' con 'LibraryImportAttribute' invece di 'DllImportAttribute' per generare codice di marshalling di P/Invoke in fase di compilazione @@ -92,29 +102,39 @@ Usare 'LibraryImportAttribute' invece di 'DllImportAttribute' per generare codice di marshalling di P/Invoke in fase di compilazione - - Conversion to 'LibraryImport' may change behavior and compatibility. See {0} for more information. - La conversione in 'LibraryImport' può modificare il comportamento e la compatibilità. Per altre informazioni, vedere {0}. - {0} is a documentation link - Convert to 'LibraryImport' with '{0}' suffix Converti in 'LibraryImport' con il suffisso '{0}' + + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + + Marshaller type does not have the required shape Il tipo di marshaller non ha la forma richiesta + + A marshaller for an element scenario cannot be stateful. + A marshaller for an element scenario cannot be stateful. + + + + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + + The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. - The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. + Il tipo di elemento dell'intervallo restituito dal primo metodo deve essere dello stesso tipo del tipo di elemento dell'intervallo restituito dal secondo metodo. The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. - The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. + Il tipo di elemento dell'intervallo restituito da '{0}' deve essere dello stesso tipo del tipo di elemento dell'intervallo restituito da '{1}'. @@ -129,22 +149,22 @@ The first parameter of the first method must be the same type as the return types of the second method. - The first parameter of the first method must be the same type as the return types of the second method. + Il primo parametro del primo metodo deve essere dello stesso tipo dei tipi restituiti del secondo metodo. The first parameter of '{0}' must be the same type as the return type of '{1}' - The first parameter of '{0}' must be the same type as the return type of '{1}' + Il primo parametro di '{0}' deve essere dello stesso tipo restituito di '{1}' The first parameters of the two methods must be the same type. - The first parameters of the two methods must be the same type. + I primi parametri dei due metodi devono essere dello stesso tipo. The first parameter of '{0}' and '{1}' must be the same type - The first parameter of '{0}' and '{1}' must be the same type + Il primo parametro di '{0}' e '{1}' deve essere dello stesso tipo @@ -153,8 +173,8 @@ - Overloading the 'FromUnmanaged' method is not supported in custom marshallers - L'overload del metodo 'FromUnmanaged' non è supportato nei marshaller personalizzati + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers @@ -184,7 +204,7 @@ Invalid 'CustomMarshallerAttribute' usage - Invalid 'CustomMarshallerAttribute' usage + Utilizzo di 'CustomMarshallerAttribute' non valido @@ -204,7 +224,7 @@ Invalid 'NativeMarshallingAttribute' usage - Invalid 'NativeMarshallingAttribute' usage + Utilizzo di 'NativeMarshallingAttribute' non valido @@ -254,22 +274,22 @@ A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. + Un marshaller di raccolta contiguo che supporta il marshalling da gestito a non gestito deve fornire un 'GetManagedValuesSource' che restituisce 'ReadOnlySpan<>' e un metodo 'GetUnmanagedValuesDestination' che restituisce un 'Span<>'. The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' + Il tipo '{0}' specifica che supporta la modalità di marshalling '{1}', ma non fornisce 'GetManagedValuesSource' che restituisce 'ReadOnlySpan<>' e un metodo 'GetUnmanagedValuesDestination' che restituisce un 'Span<>' A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. + Un marshaller di raccolta contiguo che supporta il marshalling da non gestito a gestito deve fornire un 'GetManagedValuesDestination' che accetta un 'int' e restituisce un 'Span<>' e un metodo 'GetUnmanagedValuesSource' che accetta 'int' e restituisce 'ReadOnlySpan<>'. The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' + Il tipo '{0}' specifica che supporta la modalità di marshalling '{1}', ma non fornisce un 'GetManagedValuesDestination' che accetta 'int' e restituisce 'Span<>' e un metodo 'GetUnmanagedValuesSource' che accetta 'int' e restituisce 'ReadOnlySpan<>' @@ -314,12 +334,12 @@ A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. - A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. + Un tipo di marshaller deve essere una classe statica senza stato o un tipo di valore con stato. Una classe non statica non è consentita. The type '{0}' must be a static class or a value type - The type '{0}' must be a static class or a value type + Il tipo '{0}' deve essere una classe statica o un tipo valore @@ -359,92 +379,142 @@ The return type the two method must be the expected type. - The return type the two method must be the expected type. + Tipo restituito il due metodo deve essere il tipo previsto. The return type of '{0}' must be '{1}' - The return type of '{0}' must be '{1}' + Il tipo restituito di '{0}' deve essere '{1}' The return types of the two methods must be the same type. - The return types of the two methods must be the same type. + I tipi restituiti dei due metodi devono essere dello stesso tipo. The return type of '{0}' must be the same type as the return type of '{1}' - The return type of '{0}' must be the same type as the return type of '{1}' + Il tipo restituito di '{0}' deve essere dello stesso tipo restituito di '{1}' + + + + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + + + + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. - When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. + Quando si usa la forma 'Managed to Unmanaged with Caller-Allocated Buffer', fornendo un metodo 'AllocateContainerForUnmanagedElements' che accetta un elemento "Span<T>" per il tipo di marshaller, il tipo deve fornire una proprietà statica "BufferSize" per fornire il numero di elementi nel buffer allocato dal chiamante. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' - The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' + Il tipo di marshaller '{0}' deve avere una proprietà 'int' 'BufferSize' di sola lettura statica per specificare le dimensioni del buffer allocato dal chiamante perché dispone di un metodo 'AllocateContainerForUnmanagedElements' che accetta un elemento 'Span<{1}>' allocato dal chiamante A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + Un marshaller di raccolta contiguo che supporta il marshalling da gestito a non gestito deve fornire 'GetManagedValuesSource' che accetta il valore gestito come parametro e restituisce 'ReadOnlySpan<>' e un metodo 'GetUnmanagedValuesDestination' che accetta il valore non gestito come parametro e restituisce un 'Span<>' The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + Il tipo '{0}' specifica che supporta la modalità di marshalling '{1}', ma non fornisce 'GetManagedValuesSource' che accetta '{2}' come parametro e restituisce 'ReadOnlySpan<>' e un metodo 'GetUnmanagedValuesDestination' che accetta il valore non gestito come parametro e restituisce un 'Span<>' A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. + Un marshaller di raccolta contiguo che supporta il marshalling da non gestito a gestito deve fornire un 'GetManagedValuesDestination' che accetta il valore gestito e restituisce 'Span<>' e un metodo 'GetUnmanagedValuesSource' che accetta il valore non gestito e un 'int' e restituisce un 'ReadOnlySpan<>'. The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' + Il tipo '{0}' specifica che supporta la modalità di marshalling '{1}', ma non fornisce 'GetManagedValuesDestination' che accetta '{2}' e restituisce 'Span<>' e un metodo 'GetUnmanagedValuesSource' che accetta il valore non gestito e un 'int' e restituisce 'ReadOnlySpan<>' A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter + Un marshaller di raccolta contiguo senza stato che supporta il marshalling da gestito a non gestito deve fornire un metodo 'AllocateContainerForManagedElements' che accetta il tipo non gestito come primo parametro e il numero di elementi come parametro 'int' The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter + Il tipo '{0}' specifica che supporta la modalità di marshalling '{1}' per '{2}' ma non fornisce un metodo 'AllocateContainerForManagedElements' con due parametri che accetta il tipo non gestito come primo parametro e un 'int' come secondo parametro A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter + Un marshaller di raccolta contiguo senza stato che supporta il marshalling da gestito a non gestito deve fornire un metodo 'AllocateContainerForUnmanagedElements' che accetta il tipo gestito come primo parametro e fornisce il numero di elementi come parametro 'out int' The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter + Il tipo '{0}' specifica che supporta la modalità di marshalling '{1}' per '{2}' ma non fornisce un metodo 'AllocateContainerForUnmanagedElements' con due parametri che accetta '{2}' come primo parametro e 'out int' come secondo parametro A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. - A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. + Un marshaller di valori senza stato che supporta il marshalling da non gestito a gestito deve fornire un metodo 'ConvertToManaged' che accetta il tipo non gestito come parametro e restituisce il tipo gestito. The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' - The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' + Il tipo '{0}' specifica che supporta la modalità di marshalling '{1}', ma non fornisce un metodo 'ConvertToManaged' che accetta il tipo non gestito come parametro e restituisce '{2}' A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. - A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. + Un marshaller di valori senza stato che supporta il marshalling da gestito a non gestito deve fornire un metodo 'ConvertToUnmanaged' con un solo parametro che accetta il valore gestito come parametro e restituisce un valore del tipo 'non gestito'. The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type + Il tipo '{0}' specifica che supporta la modalità di marshalling '{1}' per '{2}' ma non fornisce un metodo 'ConvertToUnmanaged' con un solo parametro che accetta un '{2}' come parametro e restituisce un valore di tipo 'non gestito' @@ -459,12 +529,12 @@ The unmanaged type for a custom marshaller must be a C# unmanaged type. - The unmanaged type for a custom marshaller must be a C# unmanaged type. + Il tipo non gestito per un marshaller personalizzato deve essere un tipo non gestito C#. The return type of '{0}' must be unmanaged - The return type of '{0}' must be unmanaged + Il tipo restituito di '{0}' deve essere non gestito diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.ja.xlf b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.ja.xlf index 26b0ecc642e67a..d19c78a0f97fc8 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.ja.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.ja.xlf @@ -7,12 +7,12 @@ 不足しているカスタム型マーシャラー メンバーの追加 - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing a 'FromManaged' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. マーシャラー型で 'Span<T>' を取る 'FromManaged' メソッドを指定して 'Managed to Unmanaged with Caller-Allocated Buffer' 図形を使用する場合、呼び出し元に割り当てられたバッファー内の要素の数を提供するには、静的な 'BufferSize' プロパティを型で指定する必要があります。 - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has a FromManaged method that takes a caller-allocated 'Span<{1}>' マーシャラー型 '{0}' には、呼び出し元が割り当てた 'Span<{1}>' を受け取る FromManaged メソッドがあるため、呼び出し元が割り当てたバッファーのサイズを指定するには、静的な読み取り専用の 'int' 'BufferSize' プロパティが必要です @@ -39,7 +39,7 @@ The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + '{0}' 構成は、ソース生成 P/Invokes ではサポートされていません。指定した構成が必要な場合は、代わりに通常の 'DllImport' を使用してください。 @@ -49,17 +49,17 @@ The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + パラメーター '{1}' に指定された構成 '{0}' は、ソース生成 P/Invokes ではサポートされていません。指定した構成が必要な場合は、代わりに通常の 'DllImport' を使用してください。 The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + メソッド '{1}' の戻り値に指定された '{0}' 構成は、ソース生成 P/Invokes ではサポートされていません。指定した構成が必要な場合は、代わりに通常の 'DllImport' を使用してください。 The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. - The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. + '{1}' に指定された値 '{0}' は、ソース生成 P/Invokes ではサポートされていません。指定した値が必要な場合は、代わりに通常の 'DllImport' を使用してください。 @@ -77,11 +77,21 @@ 'LibraryImport' への変換 + + Convert to 'LibraryImport' and enable unsafe code + Convert to 'LibraryImport' and enable unsafe code + + Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time コンパイル時に P/Invoke マーシャリング コードを生成するには、'DllImportAttribute' の代わりに 'LibraryImportAttribute' を使用します + + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + + Mark the method '{0}' with 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time コンパイル時に P/Invoke マーシャリング コードを生成するには、'DllImportAttribute' の代わりに 'LibraryImportAttribute' を持つメソッド '{0}' をマークします @@ -92,29 +102,39 @@ コンパイル時に P/Invoke マーシャリング コードを生成するには、'DllImportAttribute' の代わりに 'LibraryImportAttribute' を使用します - - Conversion to 'LibraryImport' may change behavior and compatibility. See {0} for more information. - 'LibraryImport' に変換すると、動作と互換性が変更される場合があります。詳細については、「{0}」を参照してください。 - {0} is a documentation link - Convert to 'LibraryImport' with '{0}' suffix '{0}' サフィックスを持つ 'LibraryImport' への変換 + + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + + Marshaller type does not have the required shape マーシャラー型に必要な図形がありません + + A marshaller for an element scenario cannot be stateful. + A marshaller for an element scenario cannot be stateful. + + + + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + + The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. - The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. + 最初のメソッドによって返されるスパンの要素型は、2 番目のメソッドによって返されるスパンの要素型と同じ型である必要があります。 The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. - The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. + '{0}' によって返されるスパンの要素型は、'{1}' によって返されるスパンの要素型と同じ型である必要があります。 @@ -129,22 +149,22 @@ The first parameter of the first method must be the same type as the return types of the second method. - The first parameter of the first method must be the same type as the return types of the second method. + 最初のメソッドの最初のパラメーターは、2 番目のメソッドの戻り値の型と同じ型である必要があります。 The first parameter of '{0}' must be the same type as the return type of '{1}' - The first parameter of '{0}' must be the same type as the return type of '{1}' + '{0}' の最初のパラメーターは、戻り値の型 '{1}' と同じ型である必要があります The first parameters of the two methods must be the same type. - The first parameters of the two methods must be the same type. + 2 つのメソッドの最初のパラメーターは同じ型である必要があります。 The first parameter of '{0}' and '{1}' must be the same type - The first parameter of '{0}' and '{1}' must be the same type + '{0}' の最初のパラメーターと '{1}' は同じ型である必要があります @@ -153,8 +173,8 @@ - Overloading the 'FromUnmanaged' method is not supported in custom marshallers - 'FromUnmanaged' メソッドのオーバーロードは、カスタム マーシャラーではサポートされていません + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers @@ -184,7 +204,7 @@ Invalid 'CustomMarshallerAttribute' usage - Invalid 'CustomMarshallerAttribute' usage + 'CustomMarshallerAttribute' の使用状況が無効です @@ -204,7 +224,7 @@ Invalid 'NativeMarshallingAttribute' usage - Invalid 'NativeMarshallingAttribute' usage + 'NativeMarshallingAttribute' の使用状況が無効です @@ -254,22 +274,22 @@ A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. + マネージドからアンマネージドへのマーシャリングをサポートする連続したコレクション マーシャラーは、'ReadOnlySpan<>' を返す 'GetManagedValuesSource' と 'Span<>' を返す 'GetUnmanagedValuesDestination' メソッドを提供する必要があります。 The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' + 型 '{0}' は、'{1}' マーシャリング モードをサポートすることを指定しますが、'ReadOnlySpan<>' を返す 'GetManagedValuesSource' と 'Span<>' を返す 'GetUnmanagedValuesDestination' メソッドを提供しません A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. + アンマネージドからマネージドへのマーシャリングをサポートする連続したコレクション マーシャラーは、'int' を受け取り、'Span<>' を返す 'GetManagedValuesDestination' メソッドと、'int' を受け取って 'ReadOnlySpan<>' を返す 'GetUnmanagedValuesSource' メソッドを提供する必要があります。 The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' + 型 '{0}' は、マーシャリング モード '{1}' をサポートすることを指定しますが、'int' を受け取り、'Span<>' を返す 'GetManagedValuesDestination' メソッドと、'Int' を受け取って 'ReadOnlySpan<>' を返す 'GetUnmanagedValuesSource' メソッドを提供しません。 @@ -314,12 +334,12 @@ A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. - A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. + マーシャラー型は、ステートレスな静的クラスまたはステートフルな値の型である必要があります。非静的クラスは使用できません。 The type '{0}' must be a static class or a value type - The type '{0}' must be a static class or a value type + 型 '{0}' は静的クラスまたは値の型である必要があります @@ -359,92 +379,143 @@ The return type the two method must be the expected type. - The return type the two method must be the expected type. + 戻り値の型は、2 つのメソッドが期待する型である必要があります。 The return type of '{0}' must be '{1}' - The return type of '{0}' must be '{1}' + 戻り値の型 '{0}' は '{1}' でなければなりません The return types of the two methods must be the same type. - The return types of the two methods must be the same type. + 2 つのメソッドの戻り値の型は同じ型である必要があります。 The return type of '{0}' must be the same type as the return type of '{1}' - The return type of '{0}' must be the same type as the return type of '{1}' + 戻り値の型 '{0}' は、戻り値の型 '{1}' と同じである必要があります + + + + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + + + + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. - When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. + マーシャラー型の 'Span<T>' を受け取る 'AllocateContainerForUnmanagedElements' メソッドを指定して 'Managed to Unmanaged with Caller-Allocated Buffer' シェイプを使用する場合、型は静的な 'BufferSize' プロパティを提供して、発信元が割り当てたバッファー内の要素数を提供する必要があります。 - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' - The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' + マーシャラー型 '{0}' には、発信元が割り当てたバッファーのサイズを指定するために、静的な読み取り専用の 'int' 'BufferSize' プロパティが必要です、なぜなら +発信元が割り当てた 'Span<{1}>' を受け取る 'AllocateContainerForUnmanagedElements' メソッドがあるからです A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + マネージドからアンマネージドへのマーシャリングをサポートする連続したコレクション マーシャラーは、マネージド値をパラメーターとして受け取り、'ReadOnlySpan<>' を返す 'GetManagedValuesSource' メソッドを提供する必要があり、またアンマネージド値をパラメーターとして受け取り、'Span<>' を返す 'GetUnmanagedValuesDestination' メソッドを提供する必要があります。 The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + 型 '{0}' は、マーシャリング モード '{1}' をサポートすることを指定しますが、パラメーターとして '{2}' を受け取り、'ReadOnlySpan<>' を返す 'GetManagedValuesSource' メソッドと、アンマネージド値をパラメーターとして受け取り、'Span<>' を返す 'GetUnmanagedValuesDestination' メソッドを提供しません。 A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. + アンマネージドからマネージドへのマーシャリングをサポートする連続したコレクション マーシャラーは、マネージド値を受け取り、'Span<>' を返す 'GetUnmanagedValuesSource' メソッドと、アンマネージド値と 'int' を受け取り、'ReadOnlySpan<>' を返す 'GetManagedValuesDestination' メソッドを提供する必要があります。 The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' + 型 '{0}' は、マーシャリング モード '{1}' をサポートすることを指定しますが、'{2}' を受け取り、'Span<>' を返す 'GetManagedValuesDestination' メソッドと、アンマネージ値と 'int' を受け取って 'ReadOnlySpan<>' を返す 'GetUnmanagedValuesSource' メソッドを提供しません A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter + マネージドからアンマネージドへのマーシャリングをサポートするステートレスな連続したコレクション マーシャラーは、アンマネージド型を最初のパラメーターとして受け取り、要素数を 'int' パラメーターとして受け取る 'AllocateContainerForManagedElements' メソッドを提供する必要があります The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter + 型 '{0}' は、'{2}' のためのマーシャリング モード '{1}' をサポートすることを指定しますが、アンマネージ型を最初のパラメーターとして受け取り、2 番目のパラメーターとして 'int' を受け取る 2 パラメーター の 'AllocateContainerForManagedElements' メソッドを提供しません A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter + マネージドからアンマネージドへのマーシャリングをサポートするステートレスな連続したコレクション マーシャラーは、マネージド型を最初のパラメーターとして受け取り、要素数を 'int' パラメーターとして受け取る 'AllocateContainerForManagedElements' メソッドを提供する必要があります The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter + 型 '{0}' は '{2}' のためのマーシャリング モード '{1}' をサポートすることを指定しますが、最初のパラメーターとして '{2}' を受け取り、2 番目のパラメーターとして 'out int' を受け取る 2 パラメーターの 'AllocateContainerForUnmanagedElements' メソッドを提供しません A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. - A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. + アンマネージドからマネージドへのマーシャリングをサポートするステートレスな値マーシャラーは、アンマネージ型をパラメーターとして受け取り、マネージド型を返す 'ConvertToManaged' メソッドを提供する必要があります。 The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' - The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' + 型 '{0}' は、マーシャリング モード '{1}' をサポートすることを指定しますが、アンマネージド型をパラメーターとして受け取り、'{2}' を返す 'ConvertToManaged' メソッドを提供しません A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. - A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. + マネージドからアンマネージドへのマーシャリングをサポートするステートレスなバリュー マーシャラーは、マネージド値をパラメーターとして受け取り、'unmanaged' 型の値を返す 1 パラメーター 'ConvertToUnmanaged' メソッドを提供する必要があります。 The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type + 型 '{0}' は、'{2}' のマーシャリング モード '{1}' をサポートすることを指定しますが、'{2}' をパラメーターとして受け取り、'unmanaged' 型の値を返す 1 つのパラメーター 'ConvertToUnmanaged' メソッドを提供しません @@ -459,12 +530,12 @@ The unmanaged type for a custom marshaller must be a C# unmanaged type. - The unmanaged type for a custom marshaller must be a C# unmanaged type. + カスタム マーシャラーのアンマネージド型は、C# アンマネージド型である必要があります。 The return type of '{0}' must be unmanaged - The return type of '{0}' must be unmanaged + '{0}' の戻り値の型はアンマネージドである必要があります diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.ko.xlf b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.ko.xlf index 6657bc5fca3f34..ee546a11bd2e0f 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.ko.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.ko.xlf @@ -7,12 +7,12 @@ 누락된 사용자 지정 형식 마샬러 구성원 추가 - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing a 'FromManaged' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. 마샬러 형식에서 'Span<T>'을 사용하는 'FromManaged' 메서드를 제공하여 '호출자 할당 버퍼로 관리되지 않음' 셰이프를 사용하는 경우 형식은 숫자를 제공하기 위해 정적 'BufferSize' 속성을 제공해야 합니다. 호출자 할당 버퍼의 요소 수 - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has a FromManaged method that takes a caller-allocated 'Span<{1}>' 마샬러 유형 '{0}'에는 호출자 할당 'Span<{1}>'를 사용하는 FromManaged 메서드가 있으므로 호출자 할당 버퍼의 크기를 지정하려면 정적 읽기 전용 'int' 'BufferSize' 속성이 있어야 합니다. @@ -24,7 +24,7 @@ '{0}' has no equivalent in 'DllImportAttribute' and will not be forwarded - '{0}' has no equivalent in 'DllImportAttribute' and will not be forwarded + '{0}'에는 'DllImportAttribute'에 해당하는 항목이 없으며 전달되지 않습니다. @@ -39,7 +39,7 @@ The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + '{0}' 구성은 소스 생성 P/Invoke에서 지원되지 않습니다. 지정된 구성이 필요한 경우 일반 'DllImport'를 대신 사용하세요. @@ -49,17 +49,17 @@ The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + 매개 변수 '{1}'에 대해 지정된 '{0}' 구성이 소스 생성 P/Invoke에서 지원되지 않습니다. 지정된 구성이 필요한 경우 일반 'DllImport'를 대신 사용하세요. The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + 메서드 '{0}'의 반환 값에 대해 지정된 '{1}' 구성은 소스 생성 P/Invoke에서 지원되지 않습니다. 지정된 구성이 필요한 경우 일반 'DllImport'를 대신 사용하세요. The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. - The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. + '{1}'에 대해 지정된 값 '{0}'은(는) 소스 생성 P/Invoke에서 지원되지 않습니다. 지정된 값이 필요한 경우 일반 ‘DllImport’를 대신 사용하세요. @@ -77,11 +77,21 @@ 'LibraryImport'로 변환 + + Convert to 'LibraryImport' and enable unsafe code + Convert to 'LibraryImport' and enable unsafe code + + Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time 컴파일 타임에 P/Invoke 마샬링 코드를 생성하려면 'DllImportAttribute' 대신 'LibraryImportAttribute'를 사용하세요. + + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + + Mark the method '{0}' with 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time 컴파일 타임에 P/Invoke 마샬링 코드를 생성하려면 'DllImportAttribute' 대신 'LibraryImportAttribute'를 사용하여 '{0}' 메서드를 표시하세요. @@ -92,29 +102,39 @@ 컴파일 타임에 P/Invoke 마샬링 코드를 생성하려면 'DllImportAttribute' 대신 'LibraryImportAttribute'를 사용하세요. - - Conversion to 'LibraryImport' may change behavior and compatibility. See {0} for more information. - 'LibraryImport'로 변환하면 동작과 호환성이 변경될 수 있습니다. 자세한 내용은 {0}을(를) 참조하세요. - {0} is a documentation link - Convert to 'LibraryImport' with '{0}' suffix '{0}' 접미사가 있는 'LibraryImport'로 변환 + + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + + Marshaller type does not have the required shape 마샬러 형식에 필요한 셰이프가 없습니다. + + A marshaller for an element scenario cannot be stateful. + A marshaller for an element scenario cannot be stateful. + + + + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + + The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. - The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. + 첫 번째 메서드에서 반환된 범위의 요소 형식은 두 번째 메서드에서 반환된 범위의 요소 형식과 같은 형식이어야 합니다. The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. - The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. + '{0}'에서 반환된 범위의 요소 형식은 '{1}'에서 반환된 범위의 요소 형식과 동일한 형식이어야 합니다. @@ -129,22 +149,22 @@ The first parameter of the first method must be the same type as the return types of the second method. - The first parameter of the first method must be the same type as the return types of the second method. + 첫 번째 메서드의 첫 번째 매개 변수는 두 번째 메서드의 반환 형식과 같은 형식이어야 합니다. The first parameter of '{0}' must be the same type as the return type of '{1}' - The first parameter of '{0}' must be the same type as the return type of '{1}' + '{0}'의 첫 번째 매개 변수는 '{1}'의 반환 형식과 동일해야 합니다. The first parameters of the two methods must be the same type. - The first parameters of the two methods must be the same type. + 두 메서드의 첫 번째 매개 변수는 동일한 형식이어야 합니다. The first parameter of '{0}' and '{1}' must be the same type - The first parameter of '{0}' and '{1}' must be the same type + '{0}' 및 '{1}'의 첫 번째 매개 변수는 동일한 형식이어야 합니다. @@ -153,8 +173,8 @@ - Overloading the 'FromUnmanaged' method is not supported in custom marshallers - 사용자 지정 마샬러에서는 'FromUnmanaged' 메서드 오버로드가 지원되지 않습니다. + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers @@ -184,7 +204,7 @@ Invalid 'CustomMarshallerAttribute' usage - Invalid 'CustomMarshallerAttribute' usage + 잘못된 'CustomMarshallerAttribute' 사용 @@ -204,7 +224,7 @@ Invalid 'NativeMarshallingAttribute' usage - Invalid 'NativeMarshallingAttribute' usage + 잘못된 'NativeMarshallingAttribute' 사용 @@ -254,22 +274,22 @@ A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. + 관리형 컬렉션부터 비관리형까지 마샬링까지 지원하는 연속 컬렉션 마샬러는 'ReadOnlySpan<>'을 반환하는 'GetManagedValuesSource'와 'Span<>'을 반환하는 'GetUnmanagedValuesDestination' 메서드를 제공해야 합니다. The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' + 형식 '{0}'은(는) '{1}' 마샬 모드를 지원하지만 'Span<>'을 반환하는 'ReadOnlySpan<>' 및 'GetUnmanagedValuesDestination' 메서드를 반환하는 'GetManagedValuesSource'를 제공하지 않습니다. A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. + 비관리형부터 관리형까지 마샬링을 지원하는 연속 컬렉션 마샬러는 'int'를 입력하면 'Span<>'을 반환하는 'GetManagedValuesDestination'과 'Int'를 입력하면 'ReadOnlySpan<>'을 반환하는 'GetUnmanagedValuesSource' 메서드를 제공해야 합니다. The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' + '{0}' 형식은 '{1}' 마샬 모드를 지원하지만 'int'를 입력하면 'Span<>'을 반환하는 'GetManagedValuesDestination' 메서드 및 ‘int’를 입력하면 'ReadOnlySpan<>'을 반환하는 'GetUnmanagedValuesSource'을 제공하지 않습니다. @@ -314,12 +334,12 @@ A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. - A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. + 마샬러 형식은 상태 비저장 정적 클래스 또는 상태 저장 값 형식이어야 합니다. 비정적 클래스는 사용할 수 없습니다. The type '{0}' must be a static class or a value type - The type '{0}' must be a static class or a value type + '{0}' 형식은 정적 클래스 또는 값 형식이어야 합니다. @@ -359,92 +379,142 @@ The return type the two method must be the expected type. - The return type the two method must be the expected type. + 두 메서드가 필요한 형식이어야 하는 반환 형식입니다. The return type of '{0}' must be '{1}' - The return type of '{0}' must be '{1}' + '{0}'의 반환 형식은 '{1}'이어야 합니다. The return types of the two methods must be the same type. - The return types of the two methods must be the same type. + 두 메서드의 반환 형식은 같아야 합니다. The return type of '{0}' must be the same type as the return type of '{1}' - The return type of '{0}' must be the same type as the return type of '{1}' + '{0}' 반환 형식은 '{1}' 반환 형식과 같아야 합니다. + + + + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + + + + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. - When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. + 마샬러 형식에서 'Span<T>'을 사용하는 'AllocateContainerForUnmanagedElements' 메서드를 제공하여 '호출자 할당 버퍼로 관리되지 않음' 셰이프를 사용하는 경우 형식은 호출자 할당 버퍼의 요소 수를 제공하기 위해 정적 'BufferSize' 속성을 제공해야 합니다. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' - The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' + 마샬러 유형 '{0}'에는 호출자 할당 'Span<{1}>'을 사용하는 'AllocateContainerForUnmanagedElements' 메서드가 있으므로 호출자 할당 버퍼의 크기를 지정하려면 정적 읽기 전용 'int' 'BufferSize' 속성이 있어야 합니다. A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + 관리형부터 비관리형 마샬링까지 지원하는 연속 컬렉션 마샬러는 관리되는 값을 매개 변수로 입력하면 'ReadOnlySpan<>'을 반환하는 'GetManagedValuesSource'와 비관리형 값을 매개 변수로 입력하면 'Span<>'을 반환하는 'GetUnmanagedValuesDestination' 메서드를 제공해야 합니다. The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + '{0}' 형식은 '{1}' 마샬링 모드를 지원하지만 '{2}' 매개 변수로 사용하고 'ReadOnlySpan<>' 및 'GetUnmanagedValuesDestination' 메서드를 반환하는 'GetManagedValuesSource'를 제공하지 않습니다. 이 메서드는 비관리형 값을 매개 변수를 입력하면 'Span<>'을 반환합니다. A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. + 비관리형부터 관리형 마샬링까지 지원하는 연속 컬렉션 마샬러는 관리되는 값을 입력하면 'Span<>'을 반환하는 'GetManagedValuesDestination'과 관리되지 않는 값을 입력하면 'ReadOnlySpan<>'을 반환하는 'GetUnmanagedValuesSource' 메서드를 제공해야 합니다. The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' + '{0}' 형식은 '{1}' 마샬 모드를 지원하지만 '{2}'을(를) 입력하면 'Span<>'을 반환하는 'GetManagedValuesDestination' 메서드 및 관리되지 않는 값과 ‘int’를 입력하면 'ReadOnlySpan<>'을 반환하는 'GetUnmanagedValuesSource'을 제공하지 않습니다. A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter + 관리형 컬렉션부터 비관리형까지 마샬링까지 지원하는 상태 비저장 연속 컬렉션 마샬러는 비관리형 형식을 첫 번째 매개 변수로 사용하고 요소 수를 'int' 매개 변수로 사용하는 'AllocateContainerForManagedElements' 메서드를 제공해야 합니다. The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter + '{0}' 형식은 '{2}'에 대해 '{1}' 마샬 모드를 지원하지만 비관리형 형식을 첫 번째 매개 변수로 사용하고 두 번째 매개 변수로 'out int'를 사용하는 이중 변수 'AllocateContainerForManagedElements' 메서드를 제공하지 않습니다. A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter + 관리형부터 비관리형 마샬링까지 지원하는 상태 비저장 연속 컬렉션 마샬러는 비관리형 형식을 첫 번째 매개 변수를 사용하고 요소 수를 'out int' 매개 변수로 사용하는 'AllocateContainerForUnmanagedElements' 메서드를 제공해야 합니다. The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter + '{0}' 형식은 '{2}'에 대해 '{1}' 마샬 모드를 지원하지만 '{2}'을 첫 번째 매개 변수로 사용하고 두 번째 매개 변수로 'out int'를 사용하는 이중 변수 'AllocateContainerForUnmanagedElements' 메서드를 제공하지 않습니다. A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. - A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. + 비관리형 형식부터 관리형 형식까지 마샬링을 지원하는 상태 비저장 값 마샬러는 비관리형 형식을 매개 변수로 사용하고 관리형 형식을 반환하는 'ConvertToManaged' 메서드를 제공해야 합니다. The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' - The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' + '{0}' 형식은 '{1}' 마샬 모드를 지원하지만 비관리형을 매개 변수로 입력하면 '{2}'을(를) 반환하는 'ConvertToManaged' 메서드를 제공하지 않습니다. A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. - A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. + 관리형부터 비관리형 마샬링까지 지원하는 상태 비저장 값 마샬러는 관리형 값을 매개 변수로 사용하고 '비관리형' 형식의 값을 반환하는 단일 매개 변수 'ConvertToUnmanaged' 메서드를 제공해야 합니다. The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type + '{0}' 형식은 '{2}'에 대해 '{1}' 마샬링 모드를 지원하지만 '{2}'을 매개 변수로 입력하면 '비관리형' 형식의 값을 반환하는 단일 매개 변수 'ConvertToUnmanaged' 메서드를 제공하지 않습니다. @@ -459,12 +529,12 @@ The unmanaged type for a custom marshaller must be a C# unmanaged type. - The unmanaged type for a custom marshaller must be a C# unmanaged type. + 사용자 지정 마샬러의 비관리형 형식은 C# 비관리형 형식이어야 합니다. The return type of '{0}' must be unmanaged - The return type of '{0}' must be unmanaged + '{0}'의 반환 형식은 비관리형이어야 합니다. diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.pl.xlf b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.pl.xlf index 8d693ba662681e..2a31b0db547b06 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.pl.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.pl.xlf @@ -7,12 +7,12 @@ Dodaj brakujące składowe elementu przeprowadzającego marshalling typu niestandardowego - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing a 'FromManaged' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. Gdy kształt „Zarządzane do niezarządzanego za pomocą buforu przydzielonego przez wywołującego” jest używany przez podanie metody „FromManaged”, która przyjmuje element „Span< T>” w typie marshallera, typ musi udostępniać statyczną właściwość „BufferSize”, aby podać liczbę elementów w buforze przydzielonym przez wywołującego. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has a FromManaged method that takes a caller-allocated 'Span<{1}>' Typ marshallera „{0}” musi mieć statyczną właściwość „int” „BufferSize” tylko do odczytu, aby określić rozmiar buforu przydzielonego przez wywołującego, ponieważ ma metodę FromManaged, która przyjmuje przydzielony przez wywołującego element „Span<{1}>” @@ -24,7 +24,7 @@ '{0}' has no equivalent in 'DllImportAttribute' and will not be forwarded - '{0}' has no equivalent in 'DllImportAttribute' and will not be forwarded + Element „{0}” nie ma odpowiednika w atrybucie „DllImportAtttribute” i nie zostanie przekazany @@ -77,11 +77,21 @@ Konwertuj na element „LibraryImport” + + Convert to 'LibraryImport' and enable unsafe code + Convert to 'LibraryImport' and enable unsafe code + + Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time Użyj elementu „LibraryImportAttribute” zamiast elementu „DllImportAttribute”, aby wygenerować kod skierowania funkcji P/Invoke w czasie kompilacji + + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + + Mark the method '{0}' with 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time Oznacz metodę „{0}” za pomocą elementu „LibraryImportAttribute” zamiast elementu „DllImportAttribute”, aby wygenerować kod skierowania funkcji P/Invoke w czasie kompilacji @@ -92,21 +102,31 @@ Użyj elementu „LibraryImportAttribute” zamiast elementu „DllImportAttribute”, aby wygenerować kod skierowania funkcji P/Invoke w czasie kompilacji - - Conversion to 'LibraryImport' may change behavior and compatibility. See {0} for more information. - Konwertowanie na element „LibraryImport” może zmienić zachowanie i zgodność. Zobacz link {0}, aby uzyskać więcej informacji. - {0} is a documentation link - Convert to 'LibraryImport' with '{0}' suffix Konwertuj na element „LibraryImport” z sufiksem „{0}” + + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + + Marshaller type does not have the required shape Typ marshallera nie ma wymaganego kształtu + + A marshaller for an element scenario cannot be stateful. + A marshaller for an element scenario cannot be stateful. + + + + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + + The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. @@ -153,8 +173,8 @@ - Overloading the 'FromUnmanaged' method is not supported in custom marshallers - Przeciążanie metody „FromUnmanaged” nie jest obsługiwane w niestandardowych marshallerach + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers @@ -377,12 +397,62 @@ The return type of '{0}' must be the same type as the return type of '{1}' - + + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + + + + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller + + + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.pt-BR.xlf b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.pt-BR.xlf index 14ebb123f708f4..be6f6e7e1ab215 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.pt-BR.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.pt-BR.xlf @@ -7,12 +7,12 @@ Adicionar membros marshaller de tipo personalizado ausentes - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing a 'FromManaged' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. Quando a forma 'Managed to Unmanaged com Caller-Allocated Buffer' é usada fornecendo um método 'FromManaged' que usa um 'Span<T>' no tipo de empacotador, o tipo deve fornecer uma propriedade estática 'BufferSize' para fornecer o número de elementos no buffer alocado pelo chamador. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has a FromManaged method that takes a caller-allocated 'Span<{1}>' O tipo de empacotador '{0}' deve ter uma propriedade estática somente leitura 'int' 'BufferSize' para especificar o tamanho do buffer alocado pelo chamador porque ele tem um método FromManaged que recebe um 'Span' alocado pelo chamador<{1}>' @@ -39,7 +39,7 @@ The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + A configuração “{0}” não é tem suporte para P/Invokes gerados pela origem. Se a configuração especificada for necessária, use um 'DllImport' regular. @@ -49,17 +49,17 @@ The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + A configuração “{0}” especificada para o parâmetro “{1}” não tem o suporte do P/Invokes gerados pela origem. Se a configuração especificada for necessária, use um 'DllImport' regular. The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + A configuração “{0}” especificada para o valor retornado do método “{1}” não tem suporte para P/Invokes gerados pela origem. Se a configuração especificada for necessária, use um 'DllImport' regular. The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. - The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. + O valor “{0}” especificado para “{1}” não tem suporte do P/Invokes gerados pela origem. Se o valor especificado for necessário, use um 'DllImport' regular. @@ -77,11 +77,21 @@ Converter em 'LibraryImport' + + Convert to 'LibraryImport' and enable unsafe code + Convert to 'LibraryImport' and enable unsafe code + + Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time Use 'LibraryImportAttribute' em vez de 'DllImportAttribute' para gerar código de marshalling P/Invoke no tempo de compilação + + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + + Mark the method '{0}' with 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time Marque o método '{0}' com 'LibraryImportAttribute' em vez de 'DllImportAttribute' para gerar código de marshaling P/Invoke em tempo de compilação @@ -92,29 +102,39 @@ Use 'LibraryImportAttribute' em vez de 'DllImportAttribute' para gerar código de marshalling P/Invoke no tempo de compilação - - Conversion to 'LibraryImport' may change behavior and compatibility. See {0} for more information. - A conversão para 'LibraryImport' pode alterar o comportamento e a compatibilidade. Consulte {0} para obter mais informações. - {0} is a documentation link - Convert to 'LibraryImport' with '{0}' suffix Converter em 'LibraryImport' com '{0}' sufixo + + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + + Marshaller type does not have the required shape O tipo de marshaller não tem a forma necessária + + A marshaller for an element scenario cannot be stateful. + A marshaller for an element scenario cannot be stateful. + + + + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + + The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. - The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. + O tipo de elemento do intervalo retornado pelo primeiro método deve ser do mesmo tipo que o tipo de elemento da extensão retornada pelo segundo método. The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. - The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. + O tipo de elemento do intervalo retornado por “{0}” deve ser do mesmo tipo que o tipo de elemento do intervalo retornado por “{1}”. @@ -129,22 +149,22 @@ The first parameter of the first method must be the same type as the return types of the second method. - The first parameter of the first method must be the same type as the return types of the second method. + O primeiro parâmetro do primeiro método deve ser do mesmo tipo que os tipos de retorno do segundo método. The first parameter of '{0}' must be the same type as the return type of '{1}' - The first parameter of '{0}' must be the same type as the return type of '{1}' + O primeiro parâmetro de “{0}” deve ser do mesmo tipo que o tipo de retorno “{1}” The first parameters of the two methods must be the same type. - The first parameters of the two methods must be the same type. + Os primeiros parâmetros dos dois métodos devem ser do mesmo tipo. The first parameter of '{0}' and '{1}' must be the same type - The first parameter of '{0}' and '{1}' must be the same type + O primeiro parâmetro de “{0}” e “{1}” deve ser do mesmo tipo @@ -153,8 +173,8 @@ - Overloading the 'FromUnmanaged' method is not supported in custom marshallers - A sobrecarga do método 'FromUnmanaged' não é compatível com empacotadores personalizados + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers @@ -184,7 +204,7 @@ Invalid 'CustomMarshallerAttribute' usage - Invalid 'CustomMarshallerAttribute' usage + Uso inválido de 'CustomMarshallerAttribute' @@ -204,7 +224,7 @@ Invalid 'NativeMarshallingAttribute' usage - Invalid 'NativeMarshallingAttribute' usage + Uso 'NativeMarshallingAttribute' inválido @@ -254,22 +274,22 @@ A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. + Um marshaller de coleção contíguo que dê suporte ao marshaling de gerenciado para não gerenciado deve fornecer um 'GetManagedValuesSource' que retorna um método 'ReadOnlySpan<>' e um método 'GetUnmanagedValuesDestination' que retorna um 'Span<>'. The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' + O tipo “{0}” especifica que é compatível com o modo marshal “{1},” mas não fornece um 'GetManagedValuesSource' que retorna um método 'ReadOnlySpan<>' e um método 'GetUnmanagedValuesDestination' que retorna um 'Span<>' A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. + Um marshaller de coleção contíguo que dê suporte ao marshaling de não gerenciado para gerenciado deve fornecer um método 'GetManagedValuesDestination' que aceita um 'int' e retorna um método 'Span<>' e um método 'GetUnmanagedValuesSource' que aceita um 'int' e retorna um 'ReadOnlySpan<>'. The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' + O tipo “{0}” especifica que dá suporte ao modo marshal “{1}”, mas não fornece um método 'GetManagedValuesDestination' que recebe um 'int' e retorna um método 'Span<>' e um método 'GetUnmanagedValuesSource' que usa um 'int' e retorna um 'ReadOnlySpan<>' @@ -314,12 +334,12 @@ A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. - A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. + Um tipo de marshaller deve ser uma classe estática sem estado ou um tipo de valor com estado. Uma classe não estática não é permitida. The type '{0}' must be a static class or a value type - The type '{0}' must be a static class or a value type + O tipo “{0}” deve ser uma classe estática ou um tipo de valor @@ -359,92 +379,142 @@ The return type the two method must be the expected type. - The return type the two method must be the expected type. + O tipo de retorno do método dois deve ser o tipo esperado. The return type of '{0}' must be '{1}' - The return type of '{0}' must be '{1}' + O tipo de retorno de “{0}” deve ser “{1}” The return types of the two methods must be the same type. - The return types of the two methods must be the same type. + Os tipos de retorno dos dois métodos devem ser do mesmo tipo. The return type of '{0}' must be the same type as the return type of '{1}' - The return type of '{0}' must be the same type as the return type of '{1}' + O tipo de retorno de “{0}” deve ser do mesmo tipo que o tipo de retorno “{1}” + + + + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + + + + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. - When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. + Quando a forma 'Managed to Unmanaged with Caller-Allocated Buffer' é usada fornecendo um método 'AllocateContainerForUnmanagedElements' que usa um 'Span<T>' no tipo de marshaller, o tipo deve fornecer uma propriedade estática 'BufferSize' para fornecer o número de elementos no buffer alocado pelo chamador. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' - The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' + O tipo de marshaller “{0}” deve ter uma propriedade estática somente leitura 'int' 'BufferSize' para especificar o tamanho do buffer alocado pelo chamador porque ele tem um método 'AllocateContainerForUnmanagedElements' que recebe um 'Span' alocado pelo chamador<{1}>' A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + Um marshaller de coleção contíguo que dê suporte ao marshaling de gerenciado para não gerenciado deve fornecer um método 'GetManagedValuesSource' que aceita o valor gerenciado como um parâmetro e retorna o método 'ReadOnlySpan<>' e um método 'GetUnmanagedValuesDestination' que aceita o valor não gerenciado como um parâmetro e retorna um 'Span<>' The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + O tipo “{0}” especifica que dá suporte ao modo marshal “{1}”, mas não fornece um método 'GetManagedValuesSource' que recebe um “{2}’’ como um parâmetro e retorna um método 'ReadOnlySpan<>' e um método 'GetUnmanagedValuesDestination' que usa o valor não gerenciado como um parâmetro e retorna um 'Span<>' A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. + Um marshaller de coleção contíguo que dê suporte ao marshaling de não gerenciado para gerenciado deve fornecer um método 'GetManagedValuesDestination' que aceita o valor gerenciado e retorna o método 'Span<>' e um método 'GetUnmanagedValuesSource' que aceita o valor não gerenciado e um 'int' e retorna um 'ReadOnlySpan<>'. The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' + O tipo “{0}” especifica que dá suporte ao modo marshal “{1}”, mas não fornece um método 'GetManagedValuesDestination' que recebe um “{2}” e retorna um método 'Span<>' e um método 'GetUnmanagedValuesSource' que usa um valor não gerenciado e um 'int' e retorna um 'ReadOnlySpan<>' A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter + Um marshaller de coleção contíguo sem estado que dê suporte ao marshalling de gerenciado para não gerenciado deve fornecer um método 'AllocateContainerForManagedElements' usando o tipo não gerenciado como o primeiro parâmetro e o número de elementos como um parâmetro 'int' The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter + O tipo “{0}” especifica que dá suporte ao modo marshal “{1}” para “{2}”, mas não fornece um método de dois parâmetros 'AllocateContainerForManagedElements' que usa o tipo não gerenciado como o primeiro parâmetro e um 'int' como o segundo parâmetro A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter + Um marshaller de coleção contíguo sem estado que dê suporte ao marshalling de gerenciado para não gerenciado deve fornecer um método 'AllocateContainerForManagedElements' usando o tipo não gerenciado como o primeiro parâmetro e fornecendo um número de elementos como um parâmetro 'out int' The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter + O tipo “{0}” especifica que dá suporte ao modo marshalling “{1}” para “{2}”, mas não fornece um método de dois parâmetros 'AllocateContainerForUnmanagedElements' que usa um “{2}” como o primeiro parâmetro e um 'out int' como o segundo parâmetro A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. - A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. + Um marshaller de valor sem estado que dê suporte ao marshalling de não gerenciado para gerenciado deve fornecer um método 'ConvertToManaged' que usa o tipo não gerenciado como um parâmetro e retorna o tipo gerenciado. The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' - The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' + O tipo “{0}” especifica que dá suporte ao modo marshal “{1}”, mas não fornece um método 'ConvertToManaged' que usa o tipo não gerenciado como um parâmetro e retorna “{2}” A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. - A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. + Um marshaller de valor sem estado que dê suporte ao marshalling de gerenciado para não gerenciado deve fornecer um método 'ConvertToUnmanaged' de um parâmetro que assume o valor gerenciado como parâmetro e retorna um valor do tipo 'unmanaged'. The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type + O tipo “{0}” especifica que dá suporte ao modo de marshaling “{1}” para “{2}”, mas não fornece um método 'ConvertToUnmanaged' de um parâmetro que usa um “{2}” como um parâmetro e retorna um valor de um tipo 'unmanaged' @@ -459,12 +529,12 @@ The unmanaged type for a custom marshaller must be a C# unmanaged type. - The unmanaged type for a custom marshaller must be a C# unmanaged type. + O tipo não gerenciado para um marshaller personalizado deve ser um tipo não gerenciado C#. The return type of '{0}' must be unmanaged - The return type of '{0}' must be unmanaged + O tipo de retorno de “{0}” deve ser não gerenciado diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.ru.xlf b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.ru.xlf index 7fdf08fce204a5..495696721027bf 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.ru.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.ru.xlf @@ -7,12 +7,12 @@ Добавить отсутствующие элементы маршалатора настраиваемого типа - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing a 'FromManaged' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. Если фигура "Из управляемого в неуправляемый с буфером, выделяемым вызывающим объектом" используется путем предоставления метода "FromManaged", выполняющего "Span<T>" для типа маршалера, этот тип должен предоставлять статическое свойство "BufferSize", чтобы предоставить количество элементов в буфере, выделенном вызывающим объектом. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has a FromManaged method that takes a caller-allocated 'Span<{1}>' У типа маршалера "{0}" должно быть статическое доступное только для чтения свойство "BufferSize" со значением типа "int", чтобы указывать размер буфера, выделенного вызывающим объектом, поскольку у этого типа есть метод FromManaged, выполняющий "Span<{1}>", выделяемый вызывающим объектом. @@ -39,7 +39,7 @@ The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + Конфигурация "{0}" не поддерживается P/Invokes, созданными источником. Если требуется указанная конфигурация, используйте вместо нее обычный "DllImport". @@ -49,17 +49,17 @@ The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + Указанная конфигурация "{0}" для параметра "{1}" не поддерживается P/Invokes, созданными источником. Если требуется указанная конфигурация, используйте вместо нее обычный "DllImport". The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + Указанная конфигурация "{0}" для возвращаемого значения метода "{1}" не поддерживается созданным источником P/Invokes. Если указанная конфигурация обязательна, используйте обычный метод "DllImport". The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. - The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. + Указанное значение "{0}" для "{1}" не поддерживается P/Invokes, сгенерированными источником. Если требуется указанное значение, используйте вместо него обычный "DllImport". @@ -77,11 +77,21 @@ Преобразовать в \"LibraryImport\" + + Convert to 'LibraryImport' and enable unsafe code + Convert to 'LibraryImport' and enable unsafe code + + Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time Используйте \"LibraryImportAttribute\" вместо \"DllImportAttribute\" для генерирования кода маршализации P/Invoke во время компиляции + + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + + Mark the method '{0}' with 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time Пометьте метод \"{0}\" атрибутом \"LibraryImportAttribute\" вместо \"DllImportAttribute\", чтобы генерировать код маршализации P/Invoke во время компиляции @@ -92,29 +102,39 @@ Используйте \"LibraryImportAttribute\" вместо \"DllImportAttribute\" для генерирования кода маршализации P/Invoke во время компиляции - - Conversion to 'LibraryImport' may change behavior and compatibility. See {0} for more information. - Преобразование в \"LibraryImport\" может изменить поведение и совместимость. Дополнительные сведения см. в {0}. - {0} is a documentation link - Convert to 'LibraryImport' with '{0}' suffix Преобразовать в \"LibraryImport\" с суффиксом \"{0}\" + + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + + Marshaller type does not have the required shape Тип маршалера не имеет требуемой фигуры + + A marshaller for an element scenario cannot be stateful. + A marshaller for an element scenario cannot be stateful. + + + + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + + The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. - The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. + Тип элемента диапазона, возвращаемого первым методом, должен быть того же типа, что и тип элемента диапазона, возвращаемого вторым методом. The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. - The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. + Тип диапазона, возвращаемого "{0}", должен быть того же типа, что и тип диапазона, возвращаемого "{1}". @@ -129,22 +149,22 @@ The first parameter of the first method must be the same type as the return types of the second method. - The first parameter of the first method must be the same type as the return types of the second method. + Первый параметр первого метода должен иметь тот же тип, что и возвращаемые типы второго метода. The first parameter of '{0}' must be the same type as the return type of '{1}' - The first parameter of '{0}' must be the same type as the return type of '{1}' + Первый параметр "{0}" должен иметь тот же тип, что и тип возвращаемого значения "{1}" The first parameters of the two methods must be the same type. - The first parameters of the two methods must be the same type. + Первые параметры двух методов должны быть одного типа. The first parameter of '{0}' and '{1}' must be the same type - The first parameter of '{0}' and '{1}' must be the same type + Первый параметр "{0}" и "{1}" должны быть одного типа @@ -153,8 +173,8 @@ - Overloading the 'FromUnmanaged' method is not supported in custom marshallers - Перегрузка метода "FromUnmanaged" не поддерживается в настраиваемых маршалерах + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers @@ -184,7 +204,7 @@ Invalid 'CustomMarshallerAttribute' usage - Invalid 'CustomMarshallerAttribute' usage + Недопустимое использование "CustomMarshallerAttribute" @@ -204,7 +224,7 @@ Invalid 'NativeMarshallingAttribute' usage - Invalid 'NativeMarshallingAttribute' usage + Недопустимое использование "NativeMarsingAttribute" @@ -254,22 +274,22 @@ A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. + Непрерывный маршалер коллекции, поддерживающий маршалинг из управляемого в неуправляемый, должен предоставлять метод "GetManagedValuesSource", который возвращает "ReadOnlySpan<>" и метод "GetUnmanagedValuesDestination", возвращающий "Span<>". The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' + Тип "{0}" указывает, что он поддерживает режим маршалирования "{1}", но не предоставляет метод "GetManagedValuesSource", возвращающий "ReadOnlySpan<>", и метод GetUnmanagedValuesDestination, возвращающий "Span<>". A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. + Непрерывный маршалер коллекции, поддерживающий маршалинг из управляемого в неуправляемый, должен предоставлять метод "GetManagedValuesDestination", который принимает "int" и возвращает "Span"<>, и метод "GetUnmanagedValuesSource", который принимает "int" и возвращает "ReadOnlySpan<>". The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' + Тип "{0}" указывает, что он поддерживает маршализацию "{1}"l, но не предоставляет "GetManagedValuesDestination", принимающий "int" и возвращающий "Span<>", и метод "GetUnmanagedValuesSource", принимающий "int" и возвращающий "ReadOnlySpan<>" @@ -314,12 +334,12 @@ A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. - A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. + Тип маршалера должен быть статическим классом без сохранения состояния или типом значения с отслеживанием состояния. Нестатический класс не допускается. The type '{0}' must be a static class or a value type - The type '{0}' must be a static class or a value type + Тип "{0}" должен быть статическим классом или типом значения @@ -359,92 +379,142 @@ The return type the two method must be the expected type. - The return type the two method must be the expected type. + Тип возвращаемого значения метода two должен быть ожидаемым. The return type of '{0}' must be '{1}' - The return type of '{0}' must be '{1}' + Тип возвращаемого значения "{0}" должен быть "{1}" The return types of the two methods must be the same type. - The return types of the two methods must be the same type. + Типы возвращаемого метода должны быть одинаковыми. The return type of '{0}' must be the same type as the return type of '{1}' - The return type of '{0}' must be the same type as the return type of '{1}' + Тип возвращаемого значения "{0}" должен быть тем же, что и тип возвращаемого значения "{1}" + + + + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + + + + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. - When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. + Когда форма "Управляемый в неуправляемый с буфером, выделенным вызывающим объектом" используется путем предоставления метода "AllocateContainerForUnmanagedElements", принимающим "Span<T>" для типа маршаллера, тип должен предоставлять статическое свойство "BufferSize", чтобы предоставить число элементов в выделенном вызывающей стороне буфере. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' - The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' + У типа маршалера "{0}" должно быть статическое свойство "int" "BufferSize" только для чтения, чтобы указать размер буфера, выделенного вызывающей стороной, поскольку он имеет метод "AllocateContainerForUnmanagedElements", принимающий выделенную вызывающей стороной область "Span<{1}>" A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + Непрерывный маршалер коллекций, поддерживающий маршаллинг от управляемого к неуправляемому, должен предоставить метод "GetManagedValuesSource", принимающий управляемое значение в качестве параметра и возвращающий метод ReadOnlySpan<>, и метод "GetUnmanagedValuesDestination", принимающий неуправляемое значение в качестве параметра и возвращающий "Span<>" The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + Тип "{0}" указывает, что он поддерживает маршалинг "{1}", но не предоставляет "GetManagedValuesSource", принимающий "{2}" в качестве параметра и возвращающий "ReadOnlySpan<>", а также метод "GetUnmanagedValuesDestination", принимающий неуправляемое значение как параметр и возвращающий "Span<>" A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. + Непрерывный маршалер коллекции, поддерживающий маршалирование из управляемого в неуправляемый, должен предоставить метод "GetManagedValuesDestination", принимающий управляемое значение и возвращающий "Span<>", и метод "GetUnmanagedValuesSource", принимающий неуправляемое значение и целое число и возвращающий значение "ReadOnlySpan<>". The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' + Тип "{0}" указывает, что он поддерживает маршалинг "{1}", но он не предоставляет "GetManagedValuesDestination", принимающий "{2}" и возвращающий "Span<>", а также метод "GetUnmanagedValuesSource", принимающий неуправляемое значение и "int" и возвращающий "ReadOnlySpan<>" A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter + Непрерывный маршаллер коллекций без сохранения состояния, который поддерживает маршалирование от управляемого к неуправляемому, должен предоставить метод "AllocateContainerForManagedElements", принимающий неуправляемый тип в качестве первого параметра и количество элементов в качестве параметра "int". The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter + Тип "{0}" указывает, что он поддерживает маршалирование "{1}" для {2}"', но не предоставляет метод с двумя параметрами "AllocateContainerForManagedElements", принимающий неуправляемый тип в качестве первого параметра и "int" в качестве второго параметра. A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter + Непрерывный маршаллер коллекций без сохранения состояния, который поддерживает маршалинг от управляемого к неуправляемому, должен предоставить метод "AllocateContainerForUnmanagedElements", принимающий управляемый тип в качестве первого параметра и предоставляющий количество элементов в качестве параметра "out int". The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter + Тип "{0}" указывает, что он поддерживает маршалирование "{1}" для "{2}"но не предоставляет метод "AllocateContainerForUnmanagedElements" с двумя параметрами, который принимает "{2}" в качестве первого параметра и "out int" в качестве второго параметра. A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. - A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. + Маршалер значений без отслеживания состояния, поддерживающий маршаллинг от управляемого к неуправляемому, должен предоставить метод с одним параметром "ConvertToManaged", принимающий неуправляемый тип в качестве параметра и возвращающий управляемый тип. The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' - The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' + Тип "{0}" указывает, что он поддерживает маршалирование "{1}", но он не предоставляет метод "ConvertToManaged", принимающий неуправляемый тип в качестве параметра и возвращающий "{2}" A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. - A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. + Маршалер значений без отслеживания состояния, поддерживающий маршаллинг от управляемого к неуправляемому, должен предоставить метод с одним параметром "ConvertToUnmanaged", принимающий управляемое значение в качестве параметра и возвращающий значение типа "unmanaged'". The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type + Тип "{0}" указывает, что он поддерживает маршалинг "{1}" для "{2}", но не предоставляет метод "ConvertToUnmanaged" с одним параметром, который принимает "{2}" в качестве параметра и возвращает значение типа "unmanaged" @@ -459,12 +529,12 @@ The unmanaged type for a custom marshaller must be a C# unmanaged type. - The unmanaged type for a custom marshaller must be a C# unmanaged type. + Неуправляемый тип для пользовательского маршаллера должен быть неуправляемым типом C#. The return type of '{0}' must be unmanaged - The return type of '{0}' must be unmanaged + Тип возвращаемого значения "{0}" должен быть неуправляемым diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.tr.xlf b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.tr.xlf index 17e0180aea5e00..498d1646572d11 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.tr.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.tr.xlf @@ -7,12 +7,12 @@ Eksik olan özel tür sıralayıcı üyelerini ekleyin - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing a 'FromManaged' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. Hazırlayıcı türünde 'Span<T>' alan bir 'FromManaged' yöntemi sağlanarak 'Çağıran Tarafından Ayrılan Arabellek ile Yönetilenden Yönetilmeyene' şekli kullanıldığında tür, çağıran tarafından ayrılan arabellekteki öğe sayısını sağlamak için statik bir 'BufferSize' özelliği belirtmelidir. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has a FromManaged method that takes a caller-allocated 'Span<{1}>' Hazırlayıcı türü '{0}', çağıran tarafından ayrılan arabelleğin boyutunu belirtmek için statik bir salt okunur 'int' 'BufferSize' özelliğine sahip olmalıdır çünkü çağıran tarafından ayrılan 'Span<{1}>' alan bir 'FromManaged' yöntemine sahiptir. @@ -39,7 +39,7 @@ The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + '{0}' yapılandırması, kaynak tarafından oluşturulan P/Invokes tarafından desteklenmiyor. Belirtilen yapılandırma gerekli ise, bunun yerine normal bir 'DllImport' kullanın. @@ -49,17 +49,17 @@ The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + '{1}' parametresi için belirtilen '{0}' yapılandırması, kaynak tarafından oluşturulan P/Invokes tarafından desteklenmiyor. Belirtilen yapılandırma gerekli ise, bunun yerine normal bir 'DllImport' kullanın. The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + '{0}' metodunun dönüş değeri için belirtilen '{1}' yapılandırması, kaynak tarafından oluşturulan P/Invokes tarafından desteklenmiyor. Belirtilen yapılandırma gerekli ise, bunun yerine normal bir 'DllImport' kullanın. The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. - The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. + '{1}' için belirtilen '{0}' değeri, kaynak tarafından oluşturulan P/Invokes tarafından desteklenmiyor. Belirtilen değer gerekli ise, bunun yerine normal bir 'DllImport' kullanın. @@ -77,11 +77,21 @@ 'LibraryImport' olarak dönüştür + + Convert to 'LibraryImport' and enable unsafe code + Convert to 'LibraryImport' and enable unsafe code + + Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time P/Invoke sıralama kodunu derleme zamanında oluşturmak için 'DllImportAttribute' yerine 'LibraryImportAttribute' kullanın + + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + + Mark the method '{0}' with 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time P/Invoke sıralama kodunu derleme zamanında oluşturmak için '{0}' metodunu, 'DllImportAttribute' yerine 'LibraryImportAttribute' ile işaretleyin @@ -92,29 +102,39 @@ P/Invoke sıralama kodunu derleme zamanında oluşturmak için 'DllImportAttribute' yerine 'LibraryImportAttribute' kullanın - - Conversion to 'LibraryImport' may change behavior and compatibility. See {0} for more information. - 'LibraryImport' olarak dönüştürme işlemi davranışı ve uyumluluğu değiştirebilir. Daha fazla bilgi için bkz. {0} - {0} is a documentation link - Convert to 'LibraryImport' with '{0}' suffix '{0}' soneki ile 'LibraryImport' olarak dönüştür + + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + + Marshaller type does not have the required shape Sıralayıcı türü gerekli şekle sahip değil + + A marshaller for an element scenario cannot be stateful. + A marshaller for an element scenario cannot be stateful. + + + + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + + The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. - The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. + İlk yöntem tarafından döndürülen yayılım öğe türü, ikinci metot tarafından döndürülen yayılım öğe türüyle aynı olmalıdır. The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. - The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. + '{0}' tarafından döndürülen yayılım öğe türü, '{1}'tarafından döndürülen yayılım öğe türüyle aynı olmalıdır. @@ -129,22 +149,22 @@ The first parameter of the first method must be the same type as the return types of the second method. - The first parameter of the first method must be the same type as the return types of the second method. + İlk metodun ilk parametresi, ikinci metodun dönüş türleriyle aynı olmalıdır. The first parameter of '{0}' must be the same type as the return type of '{1}' - The first parameter of '{0}' must be the same type as the return type of '{1}' + '{0}' öğesinin ilk parametresi, '{1}' dönüş türüyle aynı olmalıdır The first parameters of the two methods must be the same type. - The first parameters of the two methods must be the same type. + İki yöntemin ilk parametreleri aynı türde olmalıdır. The first parameter of '{0}' and '{1}' must be the same type - The first parameter of '{0}' and '{1}' must be the same type + '{0}' ve '{1}' öğelerinin ilk parametresi aynı türde olmalıdır @@ -153,8 +173,8 @@ - Overloading the 'FromUnmanaged' method is not supported in custom marshallers - 'FromUnmanaged' yönteminin aşırı yüklemesi özel hazırlayıcılarda desteklenmez. + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers @@ -184,7 +204,7 @@ Invalid 'CustomMarshallerAttribute' usage - Invalid 'CustomMarshallerAttribute' usage + Geçersiz 'CustomMarshallerAttribute' kullanımı @@ -204,7 +224,7 @@ Invalid 'NativeMarshallingAttribute' usage - Invalid 'NativeMarshallingAttribute' usage + Geçersiz 'NativeMarshallingAttribute' kullanımı @@ -254,22 +274,22 @@ A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. + Yönetilenden yönetilmeyene sıralamayı destekleyen bitişik bir koleksiyon sıralayıcı, 'ReadOnlySpan<>' döndüren bir 'GetManagedValuesSource' ve 'Span<>' döndüren bir 'GetUnmanagedValuesDestination' metodu sağlamalıdır. The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' + '{0}' türü, '{1}' sıralama modunu desteklediğini belirtiyor, ancak 'ReadOnlySpan<>' döndüren bir 'GetManagedValuesSource' ve 'Span<>' döndüren bir ''GetUnmanagedValuesDestination' metodu sağlamıyor. A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. + Yönetilmeyenden yönetilene sıralamayı destekleyen bitişik bir koleksiyon sıralayıcı, 'int' alan ve 'Span<>' döndüren bir 'GetManagedValuesDestination' ile 'int' alan ve 'ReadOnlySpan<>' döndüren bir 'GetUnmanagedValuesSource' metodu sağlamalıdır. The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' + '{0}' türü, '{1}' sıralama modunu desteklediğini belirtiyor, ancak 'int' alan ve 'Span<>' döndüren bir 'GetManagedValuesDestination' ile 'int' alan ve 'ReadOnlySpan<>' döndüren bir 'GetUnmanagedValuesSource' metodu sağlamıyor. @@ -314,12 +334,12 @@ A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. - A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. + Sıralayıcı türü ya durum bilgisi olmayan bir statik sınıf ya da durum bilgisi olan bir değer türü olmalıdır. Statik olmayan sınıfa izin verilmez. The type '{0}' must be a static class or a value type - The type '{0}' must be a static class or a value type + '{0}' türü statik bir sınıf veya değer türü olmalıdır @@ -359,92 +379,142 @@ The return type the two method must be the expected type. - The return type the two method must be the expected type. + İki metodun dönüş türü beklenen tür olmalıdır. The return type of '{0}' must be '{1}' - The return type of '{0}' must be '{1}' + '{0}' dönüş türü, '{1}' olmalıdır The return types of the two methods must be the same type. - The return types of the two methods must be the same type. + İki yöntemin dönüş türleri aynı olmalıdır. The return type of '{0}' must be the same type as the return type of '{1}' - The return type of '{0}' must be the same type as the return type of '{1}' + '{0}' öğesinin dönüş türü, '{1}' öğesinin dönüş türüyle aynı olmalıdır + + + + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + + + + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. - When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. + Sıralayıcı türünde 'Span<T>' alan bir 'AllocateContainerForUnmanagedElements' yöntemi sağlanarak 'Çağıran Tarafından Ayrılan Arabellek ile Yönetilenden Yönetilmeyene' şekli kullanıldığında tür, çağıran tarafından ayrılan arabellekteki öğe sayısını sağlamak için statik bir 'BufferSize' özelliği belirtmelidir. - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' - The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' + '{0}' sıralayıcı türü, çağıran tarafından ayrılan arabelleğin boyutunu belirtmek için statik bir salt okunur 'int' 'BufferSize' özelliğine sahip olmalıdır çünkü çağıran tarafından ayrılan 'Span<{1}>' alan bir 'AllocateContainerForUnmanagedElements' yöntemine sahiptir. A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + Yönetilenden yönetilmeyene sıralamayı destekleyen bitişik bir koleksiyon sıralayıcı, yönetilen değeri parametre olarak alan ve 'ReadOnlySpan<>' döndüren bir 'GetManagedValuesSource'' ile yönetilmeyen değeri parametre olarak alan ve 'Span<>' döndüren bir 'GetUnmanagedValuesDestination' metodu sağlamalıdır The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + '{0}' türü, '{1}' sıralama modunu desteklediğini belirtiyor, ancak '{2}' öğesini parametre olarak alan ve 'ReadOnlySpan<>' döndüren bir 'GetManagedValuesSource ile yönetilmeyen değeri parametre olarak' alan ve 'Span<>' döndüren bir 'GetUnmanagedValuesDestination' metodu sağlamıyor. A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. + Yönetilmeyenden yönetilene sıralamayı destekleyen bitişik bir koleksiyon sıralayıcı, yönetilen değeri alan ve 'Span<>' döndüren bir 'GetManagedValuesDestination' ile yönetilmeyen değeri ve 'int' alan ve 'ReadOnlySpan<>' döndüren bir 'GetUnmanagedValuesSource' metodu sağlamalıdır. The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' + '{0}' türü, '{1}' sıralama modunu desteklediğini belirtiyor, ancak '{2}' alan ve 'Span<>' döndüren bir 'GetManagedValuesDestination' ile yönetilmeyen değeri ve 'int' alan ve 'ReadOnlySpan<>' döndüren bir 'GetUnmanagedValuesSource' metodu sağlamıyor. A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter + Yönetilenden yönetilmeyene sıralamayı destekleyen, durum bilgisi olmayan bitişik bir koleksiyon sıralayıcı, yönetilmeyen türü ilk parametre olarak ve öğe sayısını 'int' parametresi olarak alan bir 'AllocateContainerForManagedElements' yöntemi sağlamalıdır. The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter + '{0}' türü, '{2}' için '{1}' sıralama modunu desteklediğini belirtiyor, ancak yönetilmeyen türü birinci parametre ve 'int' öğesini ikini parametre olarak alan iki parametreli bir 'AllocateContainerForManagedElements' metodu sağlamıyor A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter + Yönetilenden yönetilmeyene sıralamayı destekleyen, durum bilgisi olmayan bitişik bir koleksiyon sıralayıcı, yönetilen türü ilk parametre olarak ve öğe sayısını 'out int' parametresi olarak alan bir 'AllocateContainerForUnmanagedElements' yöntemi sağlamalıdır. The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter + '{0}' türü, '{2}' için '{1}' sıralama modunu desteklediğini belirtiyor, ancak '{2}' öğesini birinci parametre ve 'out int' öğesini ikini parametre olarak alan iki parametreli bir 'AllocateContainerForUnmanagedElements' metodu sağlamıyor. A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. - A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. + Yönetilmeyenden yönetilene sıralamayı destekleyen, durum bilgisi olmayan bir değer sıralayıcı, yönetilmeyen değeri parametre olarak alan ve yönetilen türünde bir değer döndüren 'ConvertToManaged' yöntemi sağlamalıdır. The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' - The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' + '{0}' türü, '{1}' sıralama modunu desteklediğini belirtiyor, ancak yönetilmeyen türü parametre olarak alan ve '{2}' döndüren bir 'ConvertToManaged' metodu sağlamıyor. A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. - A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. + Yönetilenden yönetilmeyene sıralamayı destekleyen, durum bilgisi olmayan bir değer sıralayıcı, yönetilen değeri parametre olarak alan ve 'unmanaged' türünde bir değer döndüren tek parametreli bir 'ConvertToUnmanaged' yöntemi sağlamalıdır. The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type + '{0}' türü, '{2}' için '{1}' sıralama modunu desteklediğini belirtiyor, ancak '{2}' öğesini parametre olarak alan ve 'unmanaged' türünde bir değer döndüren tek parametreli bir 'ConvertToUnmanaged' metodu sağlamıyor. @@ -459,12 +529,12 @@ The unmanaged type for a custom marshaller must be a C# unmanaged type. - The unmanaged type for a custom marshaller must be a C# unmanaged type. + Özel sıralayıcının yönetilmeyen türü, C# yönetilmeyen bir tür olmalıdır. The return type of '{0}' must be unmanaged - The return type of '{0}' must be unmanaged + '{0}' dönüş türü, yönetilmeyen olmalıdır diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.zh-Hans.xlf b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.zh-Hans.xlf index 41b6841aaafabb..5b8b64873d44a1 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.zh-Hans.xlf @@ -7,12 +7,12 @@ 添加缺少的自定义类型封送程序成员 - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing a 'FromManaged' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. 如果通过提供从封送处理程序类型提取“Span<T>”的“FromManaged”方法来使用“Managed to Unmanaged with Caller-Allocated Buffer”形状,则该类型必须提供一个静态的“BufferSize”属性才能提供已分配调用方缓冲。 - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has a FromManaged method that takes a caller-allocated 'Span<{1}>' 封送处理程序类型“{0}”必须拥有静态的只读“int”“BufferSize”属性,才能指定已分配调用方缓冲的大小,因为它具有提取已分配调用方“Span<{1}>”的 FromManaged 方法 @@ -39,7 +39,7 @@ The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + 源生成的 P/Invoke 不支持“{0}”配置。如果需要指定配置,请改用常规的“DllImport”。 @@ -49,17 +49,17 @@ The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + 源生成的 P/Invoke 不支持参数“{1}”的指定“{0}”配置。如果需要指定配置,请改用常规的“DllImport”。 The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + 源生成的 P/Invoke 不支持方法“{1}”返回值的指定“{0}”配置。如果需要指定配置,请改用常规的“DllImport”。 The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. - The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. + 源生成的 P/Invoke 不支持“{1}”的指定值“{0}”。如果需要指定值,请改用常规的“DllImport”。 @@ -77,11 +77,21 @@ 转换为 “LibraryImport” + + Convert to 'LibraryImport' and enable unsafe code + Convert to 'LibraryImport' and enable unsafe code + + Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time 使用 “LibraryImportAttribute” 而不是 “DllImportAttribute” 在编译时生成 P/Invoke 封送代码 + + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + + Mark the method '{0}' with 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time 使用 “LibraryImportAttribute” 而不是 “DllImportAttribute” 标记方法“{0}”,以便在编译时生成 P/Invoke 封送代码 @@ -92,29 +102,39 @@ 使用 “LibraryImportAttribute” 而不是 “DllImportAttribute” 在编译时生成 P/Invoke 封送代码 - - Conversion to 'LibraryImport' may change behavior and compatibility. See {0} for more information. - 转换为 “LibraryImport” 可能会更改行为和兼容性。有关详细信息,请参阅 {0}。 - {0} is a documentation link - Convert to 'LibraryImport' with '{0}' suffix 转换为带“{0}”后缀的 “LibraryImport” + + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + + Marshaller type does not have the required shape 封送程序类型没有必需的形状 + + A marshaller for an element scenario cannot be stateful. + A marshaller for an element scenario cannot be stateful. + + + + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + + The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. - The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. + 第一个方法返回的跨度的元素类型必须与第二个方法返回的跨度的元素类型为相同的类型。 The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. - The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. + “{0}”返回的跨度的元素类型必须与“{1}”返回的跨度的元素类型为相同的类型。 @@ -129,22 +149,22 @@ The first parameter of the first method must be the same type as the return types of the second method. - The first parameter of the first method must be the same type as the return types of the second method. + 第一个方法的第一个参数必须与第二个方法的返回类型为相同的类型。 The first parameter of '{0}' must be the same type as the return type of '{1}' - The first parameter of '{0}' must be the same type as the return type of '{1}' + “{0}”的第一个参数必须与“{1}”的返回类型为相同的类型 The first parameters of the two methods must be the same type. - The first parameters of the two methods must be the same type. + 这两种方法的第一个参数必须为相同的类型。 The first parameter of '{0}' and '{1}' must be the same type - The first parameter of '{0}' and '{1}' must be the same type + “{0}”和“{1}”的第一个参数必须为相同的类型 @@ -153,8 +173,8 @@ - Overloading the 'FromUnmanaged' method is not supported in custom marshallers - 自定义封送处理程序中不支持重载“FromUnmanaged”方法 + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers @@ -184,7 +204,7 @@ Invalid 'CustomMarshallerAttribute' usage - Invalid 'CustomMarshallerAttribute' usage + “CustomMarshallerAttribute”用法无效 @@ -204,7 +224,7 @@ Invalid 'NativeMarshallingAttribute' usage - Invalid 'NativeMarshallingAttribute' usage + “NativeMarshallingAttribute”用法无效 @@ -254,22 +274,22 @@ A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. + 支持从托管到非托管的封送的连续集合封送程序必须提供返回“ReadOnlySpan<>”的“GetManagedValuesSource”和返回“Span<>”的“GetUnmanagedValuesDestination”方法。 The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' + 类型“{0}”指定它支持“{1}”封送模式,但不提供返回“ReadOnlySpan<>”的“GetManagedValuesSource”和返回“Span<>”的“GetUnmanagedValuesDestination”方法 A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. + 支持从非托管封送封送到托管的连续集合封送程序必须提供采用“int”并返回“Span<>”的“GetManagedValuesDestination”和采用“int”并返回“ReadOnlySpan<>”的“GetUnmanagedValuesSource”方法。 The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' + 类型“{0}”指定它支持“{1}”封送模式,但不提供采用“int”并返回“Span<>”的“GetManagedValuesDestination”和采用“int”并返回“ReadOnlySpan<>”的“GetUnmanagedValuesSource”方法 @@ -314,12 +334,12 @@ A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. - A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. + 封送程序类型必须为无状态静态类或有状态值类型。不允许使用非静态类。 The type '{0}' must be a static class or a value type - The type '{0}' must be a static class or a value type + 类型“{0}”必须为静态类或值类型 @@ -359,92 +379,142 @@ The return type the two method must be the expected type. - The return type the two method must be the expected type. + 这两种方法的返回类型必须为预期类型。 The return type of '{0}' must be '{1}' - The return type of '{0}' must be '{1}' + “{0}”的返回类型必须为“{1}” The return types of the two methods must be the same type. - The return types of the two methods must be the same type. + 这两种方法的返回类型必须为相同的类型。 The return type of '{0}' must be the same type as the return type of '{1}' - The return type of '{0}' must be the same type as the return type of '{1}' + “{0}”的返回类型必须与“{1}”的返回类型为相同的类型 + + + + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + + + + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. - When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. + 如果在封送程序类型上提供采用“Span<T>”的“AllocateContainerForUnmanagedElements”方法以使用“通过调用方分配的缓冲区从托管到非托管”形状,则该类型必须提供静态“BufferSize”属性以提供调用方分配的缓冲区中的元素数。 - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' - The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' + 封送程序类型“{0}”必须具有静态只读“int”“BufferSize”属性以指定调用方分配的缓冲区的大小,因为它具有采用调用方分配的“Span<{1}>”的“AllocateContainerForUnmanagedElements”方法 A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + 支持从托管到非托管的封送的连续集合封送程序必须提供将托管值用作参数并返回“ReadOnlySpan<>”的“GetManagedValuesSource”和将非托管值用作参数并返回“Span<>”的“GetUnmanagedValuesDestination”方法 The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + 类型“{0}”指定它支持“{1}”封送模式,但不提供将“{2}”用作参数并返回“ReadOnlySpan<>”的“GetManagedValuesSource 和将非托管值用作参数并返回“Span<>”的“GetUnmanagedValuesDestination”方法 A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. + 支持从非托管到托管的封送的连续集合封送程序必须提供采用托管值并返回“Span<>”的“GetManagedValuesDestination”以及采用非托管值和“int”并返回“ReadOnlySpan<>”的“GetUnmanagedValuesSource”方法。 The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' + 类型“{0}”指定它支持“{1}”封送模式,但不提供采用“{2}”并返回“Span<>”的“GetManagedValuesDestination”以及采用非托管值和“int”并返回“ReadOnlySpan<>”的“GetManagedValuesSource”方法 A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter + 支持从托管到非托管的封送的无状态连续集合封送程序必须提供将非托管类型用作第一个参数并将元素数用作 “int” 参数的“AllocateContainerForManagedElements” 方法 The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter + 类型“{0}”指定它支持“{2}”的“{1}”封送模式,但不提供将非托管类型用作第一个参数并将“int”用作第二个参数的双参数“AllocateContainerForManagedElements”方法 A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter + 支持从托管到非托管的封送的无状态连续集合封送程序必须提供将托管类型用作第一个参数并将元素数作为 “out int” 参数提供的“AllocateContainerForUnmanagedElements” 方法 The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter + 类型“{0}”指定它支持“{2}”的“{1}”封送模式,但不提供将“{2}”用作第一个参数并将“out int”用作第二个参数的双参数“AllocateContainerForUnmanagedElements”方法 A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. - A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. + 支持从非托管到托管的封送的无状态值封送程序必须提供将非托管类型用作参数并返回托管类型的“ConvertToManaged”方法。 The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' - The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' + 类型“{0}”指定它支持“{1}”封送模式,但不提供将非托管类型用作参数并返回“{2}”的“ConvertToManaged”方法 A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. - A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. + 支持从托管到非托管的封送的无状态值封送程序必须提供将托管值用作参数并返回“非托管”类型的值的单参数“ConvertToUnmanaged”方法。 The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type + 类型“{0}”指定它支持“{2}”的“{1}”封送模式,但不提供将“{2}”用作参数并返回“非托管”类型的值的单参数“ConvertToUnmanaged”方法 @@ -459,12 +529,12 @@ The unmanaged type for a custom marshaller must be a C# unmanaged type. - The unmanaged type for a custom marshaller must be a C# unmanaged type. + 自定义封送程序的非托管类型必须为 C# 非托管类型。 The return type of '{0}' must be unmanaged - The return type of '{0}' must be unmanaged + “{0}”的返回类型必须为非托管 diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.zh-Hant.xlf b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.zh-Hant.xlf index 1d148d3c652701..5d4fcaabf218f4 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Resources/xlf/Strings.zh-Hant.xlf @@ -7,12 +7,12 @@ 新增遺漏的自訂類型排列器成員 - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing a 'FromManaged' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. 當透過提供在封送處理器類型上採用 'Span<T>' 的 'FromManaged' 方法來使用 'Managed to Unmanaged with Caller-Allocated Buffer' 圖形時,該類型必須提供靜態 'BufferSize' 屬性以提供 caller-allocated 緩衝區中的元素數字。 - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has a FromManaged method that takes a caller-allocated 'Span<{1}>' 封送處理器類型 '{0}' 必須有靜態唯讀 'int' 'BufferSize' 屬性,以指定 caller-allocated 緩衝區的大小,因為它具有採用 caller-allocated 'Span<{1}>' 的 FromManaged 方法 @@ -39,7 +39,7 @@ The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + 來源產生的 P/Invokes 不支援 '{0}' 設定。如果需要指定的設定,請改用一般 'DllImport'。 @@ -49,17 +49,17 @@ The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + 來源產生的 P/Invokes 不支援為參數 '{1}' 指定的 '{0}' 設定。如果需要指定的設定,請改用一般 'DllImport'。 The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. - The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular 'DllImport' instead. + 來源產生的 P/Invokes 不支援為方法 '{1}' 的傳回值指定 '{0}' 設定。如果需要指定的設定,請改用一般 'DllImport'。 The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. - The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified value is required, use a regular 'DllImport' instead. + 來源產生的 P/Invokes 不支援為 '{1}' 指定的值 '{0}'。如果需要指定的設定,請改用一般 'DllImport'。 @@ -77,11 +77,21 @@ 轉換為 'LibraryImport' + + Convert to 'LibraryImport' and enable unsafe code + Convert to 'LibraryImport' and enable unsafe code + + Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time 使用 'LibraryImportAttribute' 而非 'DllImportAttribute' 在編譯時間產生 P/Invoke 封送處理程式碼 + + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + Converting this API to 'LibraryImport' will require additional code to provide custom marshallers for some parameters. + + Mark the method '{0}' with 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time 以 'LibraryImportAttribute' 代替 'DllImportAttribute' 標示方法'{0}',以在編譯時間產生 P/Invoke 封送處理程式碼 @@ -92,29 +102,39 @@ 使用 'LibraryImportAttribute' 而非 'DllImportAttribute' 在編譯時間產生 P/Invoke 封送處理程式碼 - - Conversion to 'LibraryImport' may change behavior and compatibility. See {0} for more information. - 轉換為 'LibraryImport' 可能會變更行為和兼容性。如需詳細資訊,請參閱 {0}。 - {0} is a documentation link - Convert to 'LibraryImport' with '{0}' suffix 轉換為具有 '{0}'後綴的 'LibraryImport' + + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + Convert to 'LibraryImport' with '{0}' suffix and enable unsafe code + + Marshaller type does not have the required shape 封送處理器類型沒有必要的圖形 + + A marshaller for an element scenario cannot be stateful. + A marshaller for an element scenario cannot be stateful. + + + + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + The specified marshaller type '{0}' is a stateful marshaller, but stateful marshallers are not allowed in the provided marshal mode '{1}' + + The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. - The element type of the span returned by the first method must be the same type as the element type of the span returned by the second method. + 第一個方法傳回之跨距的元素類型必須與第二個方法傳回之跨距的元素類型相同類型。 The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. - The element type of the span returned by '{0}' must be the same type as the element type of the span returned by '{1}'. + '{0}' 傳回之跨距的元素類型必須與 '{1}' 傳回之跨距的元素類型相同類型。 @@ -129,22 +149,22 @@ The first parameter of the first method must be the same type as the return types of the second method. - The first parameter of the first method must be the same type as the return types of the second method. + 第一個方法的第一個參數必須與第二個方法的傳回類型相同類型。 The first parameter of '{0}' must be the same type as the return type of '{1}' - The first parameter of '{0}' must be the same type as the return type of '{1}' + '{0}' 的第一個參數必須與 '{1}' 的傳回類型相同 The first parameters of the two methods must be the same type. - The first parameters of the two methods must be the same type. + 兩種方法的第一個參數必須是相同的類型。 The first parameter of '{0}' and '{1}' must be the same type - The first parameter of '{0}' and '{1}' must be the same type + '{0}' 與 '{1}' 的第一個參數必須是相同的類型 @@ -153,8 +173,8 @@ - Overloading the 'FromUnmanaged' method is not supported in custom marshallers - 自訂封送處理器中不支援多載 'FromUnmanaged' 方法 + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers + The type '{0}' overloads the 'FromUnmanaged' method, which is not supported in custom marshallers @@ -184,7 +204,7 @@ Invalid 'CustomMarshallerAttribute' usage - Invalid 'CustomMarshallerAttribute' usage + `CustomMarshallerAttribute` 使用方式無效 @@ -204,7 +224,7 @@ Invalid 'NativeMarshallingAttribute' usage - Invalid 'NativeMarshallingAttribute' usage + 'NativeMarshallingAttribute' 使用方式無效 @@ -254,22 +274,22 @@ A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>'. + 支援從非受控到受控封送處理的連續集合封送處理程式必須提供傳回 'ReadOnlySpan<>' 的 'GetManagedValuesSource' 和傳回 'Span<>' 的 'GetNativeValuesDestination' 方法。 The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that returns a 'Span<>' + 類型 '{0}' 指定它支援 '{1}' 封送處理模式,但未提供傳回 'ReadOnlySpan<>' 的 'GetManagedValuesSource' 和傳回 'Span<>' 的 'GetNativeValuesDestination' 方法 A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>'. + 支援從非受控到受控封送處理的連續集合封送處理程式必須提供接受 'int' 和傳回 'Span<>' 的 'GetManagedValuesDestination',和接受 'int' 和傳回 'ReadOnlySpan<>' 的 'GetNativeValuesSource' 方法。 The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes an 'int' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes an 'int' and returns a 'ReadOnlySpan<>' + 類型 '{0}' 指定它支援 '{1}' 封送處理模式,但未提供接受 'int' 和傳回 'Span<>' 的 'GetManagedValuesDestination',和接受 'int' 和傳回 'ReadOnlySpan<>' 的 'GetNativeValuesSource' 方法 @@ -314,12 +334,12 @@ A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. - A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed. + 封送處理程式類型必須是無狀態靜態類型或具狀態的數值類型。不允許非靜態類型。 The type '{0}' must be a static class or a value type - The type '{0}' must be a static class or a value type + 類型 '{0}' 必須是靜態類別或數值類型 @@ -359,92 +379,142 @@ The return type the two method must be the expected type. - The return type the two method must be the expected type. + 兩種方法的傳回類型必須是預期的類型。 The return type of '{0}' must be '{1}' - The return type of '{0}' must be '{1}' + '{0}' 的傳回類型必須為 '{1}' The return types of the two methods must be the same type. - The return types of the two methods must be the same type. + 兩種方法的傳回類型必須是相同的類型。 The return type of '{0}' must be the same type as the return type of '{1}' - The return type of '{0}' must be the same type as the return type of '{1}' + '{0}' 的傳回類型必須與 '{1}' 的傳回類型相同 + + + + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + A stateful marshaller must have a zero-parameter void-returning instance method named 'Free'. + + + + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + The type '{0}' is a stateful marshaller and does not have a zero-parameter void-returning instance method named 'Free' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'FromManaged' instance method that takes the managed value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromManaged' that takes a '{2}' as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'FromUnmanaged' instance method that takes the unmanaged value as a parameter and returns 'void'. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a one-parameter instance method named 'FromUnmanaged' that takes the 'unmanaged' value as a parameter and returns 'void' + + + + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + A stateful marshaller that supports marshalling from unmanaged to managed must provide a 'ToManaged' instance method that takes no parameters and returns the managed type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToManaged' that returns '{2}' + + + + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + A stateful marshaller that supports marshalling from managed to unmanaged must provide a 'ToUnmanaged' instance method that takes no parameters and returns the 'unmanaged' type. + + + + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller + The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but it does not provide a zero-parameter instance method named 'ToUnmanaged' that returns the 'unmanaged' type for the marshaller - + When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. - When the 'Managed to Unmanaged with Caller-Allocated Buffer' shape is used by providing an 'AllocateContainerForUnmanagedElements' method that takes a 'Span<T>' on the marshaller type, the type must provide a static 'BufferSize' property to provide the number of elements in the caller-allocated buffer. + 當透過提供在封送處理程式類型上採用 'Span<T>' 的 'AllocateContainerForUnmanagedElements' 方法來使用 'Managed to Unmanaged with Caller-Allocated Buffer' 圖形時,該類型必須提供靜態 'BufferSize' 屬性以提供 caller-allocated 緩衝區中的元素數目。 - + The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' - The marshaller type '{0}' must have a static read-only 'int' 'BufferSize' property to specify the size of the caller-allocated buffer because it has an 'AllocateContainerForUnmanagedElements' method that takes a caller-allocated 'Span<{1}>' + 封送處理程式類型 '{0}' 必須有靜態唯讀 'int' 'BufferSize' 屬性,以指定 caller-allocated 緩衝區的大小,因為它具有採用 caller-allocated 'Span<{1}>' 的 'AllocateContainerForUnmanagedElements' 方法 A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - A contiguous collection marshaller that supports marshalling from managed to unmanaged must provide a 'GetManagedValuesSource' that takes the managed value as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + 支援從非受控到受控封送處理的連續集合封送處理程式必須提供接受受控值為參數並傳回 'ReadOnlySpan<>' 的 'GetManagedValuesDestination',和接受非受控值為參數並傳回 'Span<>' 的 'GetUnmanagedValuesSource' 方法。 The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesSource' that takes '{2}' as a parameter and returns a 'ReadOnlySpan<>' and a 'GetUnmanagedValuesDestination' method that takes the unmanaged value as a parameter and returns a 'Span<>' + 類型 '{0}' 指定它支援 '{1}' 封送處理模式,但未提供接受 '{2}' 為參數並傳回 'ReadOnlySpan<>' 的 'GetManagedValuesSource' ,和接受未受控值為參數並傳回 'Span<>' 的 'GetUnmanagedValuesDestination' 方法 A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. - A contiguous collection marshaller that supports marshalling from unmanaged to managed must provide a 'GetManagedValuesDestination' that takes the managed value and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>'. + 支援從非受控到受控封送處理的連續集合封送處理程式必須提供接受受控值並傳回 'Span<>' 的 'GetManagedValuesDestination',和接受非受控值及 'int' 並傳回 'ReadOnlySpan<>' 的 'GetUnmanagedValuesSource' 方法。 The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' - The type '{0}' specifies that it supports the '{1}' marshal mode, but it does not provide a 'GetManagedValuesDestination' that takes '{2}' and returns a 'Span<>' and a 'GetUnmanagedValuesSource' method that takes the unmanaged value and an 'int' and returns a 'ReadOnlySpan<>' + 類型 '{0}' 指定它支援 '{1}' 封送處理模式,但未提供接受 '{2}' 和傳回 'Span<>' 的 'GetManagedValuesDestination',和接受未受控值和傳回 'ReadOnlySpan<>' 的 'GetUnmanagedValuesSource' 方法 A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForManagedElements' method taking the unmanaged type as the first parameter and the number of elements as an 'int' parameter + 支援從受控到未受控封送處理的無狀態連續集合封送處理程式必須提供 'AllocateContainerForManagedElements' 方法,將未受控的類型作為第一個參數,以及元素數目作為 'int' 參數 The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForManagedElements' method that takes the unmanaged type as the first parameter and an 'int' as the second parameter + 類型 '{0}' 指定它支援 '{2}' 的 '{1}' 封送處理模式,但不提供接受未受控類型作爲第一個參數和 'int' 作為第二個參數的雙參數 'AllocateContainerForManagedElements' 方法 A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter - A stateless contiguous collection marshaller that supports marshalling from managed to unmanaged must provide an 'AllocateContainerForUnmanagedElements' method taking the managed type as the first parameter and providing the number of elements as an 'out int' parameter + 支援從受控到未受控封送處理的無狀態連續集合封送處理程式必須提供 'AllocateContainerForManagedElements' 方法,將受控類型作為第一個參數,以及提供元素數目作為 'out int' 參數 The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a two-parameter 'AllocateContainerForUnmanagedElements' method that takes a '{2}' as the first parameter and an 'out int' as the second parameter + 類型 '{0}' 指定它支援 '{2}' 的 '{1}' 封送處理模式,但不提供接受 '{2}' 作爲第一個參數和 'out int' 作為第二個參數的雙參數 'AllocateContainerForUnmanagedElements' 方法 A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. - A stateless value marshaller that supports marshalling from unmanaged to managed must provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns the the managed type. + 支援從受控到未受控封送處理的無狀態值封送處理程式必須提供接受未受控類型作為參數,並傳回受控類型的 'ConvertToManaged' 方法。 The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' - The type '{0}' specifies it supports the '{1}' marshal mode, but it does not provide a 'ConvertToManaged' method that takes the unmanaged type as a parameter and returns '{2}' + 類型 '{0}' 指定它支援 '{1}' 封送處理模式,但未提供將未受控的類型當做參數並傳回 '{2}' 的 'ConvertToManaged' 方法 A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. - A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type. + 支援從受控到未受控封送處理的無狀態值封送處理程式必須提供單一參數 'ConvertToUnmanaged' 方法,將受控值作為參數,並傳回 'unmanaged' 類型的值。 The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type - The type '{0}' specifies that it supports the '{1}' marshal mode for '{2}' but does not provide a one-parameter 'ConvertToUnmanaged' method that takes a '{2}' as a parameter and returns a value of an 'unmanaged' type + 類型 '{0}' 指定它支援 '{2}' 的 '{1}' 封送處理模式,但不提供以 '{2}' 為參數的單一參數 'ConvertToUnmanaged' 方法,並傳回 'unmanaged' 類型的值 @@ -459,12 +529,12 @@ The unmanaged type for a custom marshaller must be a C# unmanaged type. - The unmanaged type for a custom marshaller must be a C# unmanaged type. + 自訂封送處理程式的未受控類型必須是 C# 未受控類型。 The return type of '{0}' must be unmanaged - The return type of '{0}' must be unmanaged + '{0}' 的傳回類型必須為不受控 diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/CompilationExtensions.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/CompilationExtensions.cs new file mode 100644 index 00000000000000..570db386c5e98c --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/CompilationExtensions.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.CodeAnalysis; + +namespace Microsoft.Interop +{ + public static class CompilationExtensions + { + public static StubEnvironment CreateStubEnvironment(this Compilation compilation) + { + TargetFramework targetFramework = DetermineTargetFramework(compilation, out Version targetFrameworkVersion); + return new StubEnvironment( + compilation, + targetFramework, + targetFrameworkVersion, + compilation.SourceModule.GetAttributes().Any(attr => attr.AttributeClass?.ToDisplayString() == TypeNames.System_Runtime_CompilerServices_SkipLocalsInitAttribute)); + + static TargetFramework DetermineTargetFramework(Compilation compilation, out Version version) + { + IAssemblySymbol systemAssembly = compilation.GetSpecialType(SpecialType.System_Object).ContainingAssembly; + version = systemAssembly.Identity.Version; + + return systemAssembly.Identity.Name switch + { + // .NET Framework + "mscorlib" => TargetFramework.Framework, + // .NET Standard + "netstandard" => TargetFramework.Standard, + // .NET Core (when version < 5.0) or .NET + "System.Runtime" or "System.Private.CoreLib" => + (version.Major < 5) ? TargetFramework.Core : TargetFramework.Net, + _ => TargetFramework.Unknown, + }; + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IncrementalGeneratorInitializationContextExtensions.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IncrementalGeneratorInitializationContextExtensions.cs index d8593bc196cef4..0b008795884810 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IncrementalGeneratorInitializationContextExtensions.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IncrementalGeneratorInitializationContextExtensions.cs @@ -13,38 +13,7 @@ public static class IncrementalGeneratorInitializationContextExtensions { public static IncrementalValueProvider CreateStubEnvironmentProvider(this IncrementalGeneratorInitializationContext context) { - return context.CompilationProvider - .Select(static (compilation, ct) => - { - TargetFramework targetFramework = DetermineTargetFramework(compilation, out Version targetFrameworkVersion); - return (compilation, targetFramework, targetFrameworkVersion); - }) - .Select( - static (data, ct) => - new StubEnvironment( - data.compilation, - data.targetFramework, - data.targetFrameworkVersion, - data.compilation.SourceModule.GetAttributes().Any(attr => attr.AttributeClass?.ToDisplayString() == TypeNames.System_Runtime_CompilerServices_SkipLocalsInitAttribute)) - ); - - static TargetFramework DetermineTargetFramework(Compilation compilation, out Version version) - { - IAssemblySymbol systemAssembly = compilation.GetSpecialType(SpecialType.System_Object).ContainingAssembly; - version = systemAssembly.Identity.Version; - - return systemAssembly.Identity.Name switch - { - // .NET Framework - "mscorlib" => TargetFramework.Framework, - // .NET Standard - "netstandard" => TargetFramework.Standard, - // .NET Core (when version < 5.0) or .NET - "System.Runtime" or "System.Private.CoreLib" => - (version.Major < 5) ? TargetFramework.Core : TargetFramework.Net, - _ => TargetFramework.Unknown, - }; - } + return context.CompilationProvider.Select(static (comp, ct) => comp.CreateStubEnvironment()); } public static void RegisterDiagnostics(this IncrementalGeneratorInitializationContext context, IncrementalValuesProvider diagnostics) diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CollectionTests.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CollectionTests.cs index a991f6bea69404..48d592735280c5 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CollectionTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CollectionTests.cs @@ -165,6 +165,7 @@ public List ToManagedFinally() public Span GetManagedValuesDestination(int length) => default; public ReadOnlySpan GetUnmanagedValuesSource(int length) => default; public void FromUnmanaged(byte* value) { } + public void Free() {} } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CustomMarshallingTests.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CustomMarshallingTests.cs index 791f6d651d4eb8..4608a11b6a2d30 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CustomMarshallingTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CustomMarshallingTests.cs @@ -102,6 +102,8 @@ public int ToManagedFinally() } public void FromUnmanaged(int value) { } + + public void Free() {} } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/ConvertToLibraryImportFixerTests.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/ConvertToLibraryImportFixerTests.cs index b7a18015beb525..a080e3963b0661 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/ConvertToLibraryImportFixerTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/ConvertToLibraryImportFixerTests.cs @@ -5,6 +5,9 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.Interop.Analyzers; using Xunit; using static Microsoft.Interop.Analyzers.ConvertToLibraryImportFixer; @@ -17,7 +20,7 @@ namespace LibraryImportGenerator.UnitTests [ActiveIssue("https://github.com/dotnet/runtime/issues/60650", TestRuntimes.Mono)] public class ConvertToLibraryImportFixerTests { - private const string ConvertToLibraryImportKey = "ConvertToLibraryImport"; + private const string ConvertToLibraryImportKey = "ConvertToLibraryImport,"; [Fact] public async Task Basic() @@ -37,7 +40,7 @@ partial class Test [LibraryImport(""DoesNotExist"")] public static partial int {{|CS8795:Method|}}(out int ret); }}"; - await VerifyCS.VerifyCodeFixAsync( + await VerifyCodeFixAsync( source, fixedSource); } @@ -72,7 +75,7 @@ partial class Test // < ... > public static partial int {{|CS8795:Method2|}}(out int ret); }}"; - await VerifyCS.VerifyCodeFixAsync( + await VerifyCodeFixAsync( source, fixedSource); } @@ -105,7 +108,7 @@ partial class Test [return: MarshalAs(UnmanagedType.I4)] public static partial int {{|CS8795:Method2|}}(out int ret); }}"; - await VerifyCS.VerifyCodeFixAsync( + await VerifyCodeFixAsync( source, fixedSource); } @@ -134,7 +137,7 @@ partial class Test [LibraryImport(""DoesNotExist"", EntryPoint = ""Entry"", StringMarshalling = StringMarshalling.Utf16)] public static partial string {{|CS8795:Method2|}}(out int ret); }}"; - await VerifyCS.VerifyCodeFixAsync( + await VerifyCodeFixAsync( source, fixedSource); } @@ -181,7 +184,7 @@ partial class Test [LibraryImport(""DoesNotExist"")] public static partial int {{|CS8795:Method4|}}(out int ret); }}"; - await VerifyCS.VerifyCodeFixAsync( + await VerifyCodeFixAsync( source, fixedSource); } @@ -204,7 +207,7 @@ partial class Test [LibraryImport(""DoesNotExist"", EntryPoint = ""Entry"")] public static partial int {{|CS8795:Method1|}}(out int ret); }}"; - await VerifyCS.VerifyCodeFixAsync( + await VerifyCodeFixAsync( source, fixedSource); } @@ -232,7 +235,7 @@ partial class Test [UnmanagedCallConv(CallConvs = new System.Type[] {{ typeof({callConvType.FullName}) }})] public static partial int {{|CS8795:Method1|}}(out int ret); }}"; - await VerifyCS.VerifyCodeFixAsync( + await VerifyCodeFixAsync( source, fixedSource); } @@ -255,7 +258,7 @@ partial class Test [LibraryImport(""DoesNotExist"", EntryPoint = ""Entry"", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)] public static partial string {{|CS8795:Method|}}(out int ret); }}"; - await VerifyCS.VerifyCodeFixAsync( + await VerifyCodeFixAsync( source, fixedSource); } @@ -279,7 +282,7 @@ partial class Test [LibraryImport(""DoesNotExist"", EntryPoint = ""Entry"")] public static partial void {{|CS8795:Method|}}(); }}"; - await VerifyCS.VerifyCodeFixAsync(source, fixedSourceNoSuffix, ConvertToLibraryImportKey); + await VerifyCodeFixAsync(source, fixedSourceNoSuffix, ConvertToLibraryImportKey); string fixedSourceWithSuffix = $@" using System.Runtime.InteropServices; partial class Test @@ -287,7 +290,7 @@ partial class Test [LibraryImport(""DoesNotExist"", EntryPoint = ""Entry{suffix}"")] public static partial void {{|CS8795:Method|}}(); }}"; - await VerifyCS.VerifyCodeFixAsync(source, fixedSourceWithSuffix, $"{ConvertToLibraryImportKey}{suffix}"); + await VerifyCodeFixAsync(source, fixedSourceWithSuffix, $"{ConvertToLibraryImportKey}{suffix},"); } [Fact] @@ -307,7 +310,7 @@ partial class Test [LibraryImport(""DoesNotExist"", EntryPoint = ""Entry"")] public static partial void {{|CS8795:Method|}}(); }}"; - await VerifyCS.VerifyCodeFixAsync(source, fixedSourceNoSuffix, ConvertToLibraryImportKey); + await VerifyCodeFixAsync(source, fixedSourceNoSuffix, ConvertToLibraryImportKey); string fixedSourceWithASuffix = $@" using System.Runtime.InteropServices; partial class Test @@ -315,7 +318,7 @@ partial class Test [LibraryImport(""DoesNotExist"", EntryPoint = ""EntryA"")] public static partial void {{|CS8795:Method|}}(); }}"; - await VerifyCS.VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}A"); + await VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}A,"); string fixedSourceWithWSuffix = $@" using System.Runtime.InteropServices; partial class Test @@ -323,7 +326,7 @@ partial class Test [LibraryImport(""DoesNotExist"", EntryPoint = ""EntryW"")] public static partial void {{|CS8795:Method|}}(); }}"; - await VerifyCS.VerifyCodeFixAsync(source, fixedSourceWithWSuffix, $"{ConvertToLibraryImportKey}W"); + await VerifyCodeFixAsync(source, fixedSourceWithWSuffix, $"{ConvertToLibraryImportKey}W,"); } [Fact] @@ -343,7 +346,7 @@ partial class Test [LibraryImport(""DoesNotExist"", EntryPoint = ""Entry"")] public static partial void {{|CS8795:Method|}}(); }}"; - await VerifyCS.VerifyCodeFixAsync(source, fixedSourceNoSuffix, ConvertToLibraryImportKey); + await VerifyCodeFixAsync(source, fixedSourceNoSuffix, ConvertToLibraryImportKey); string fixedSourceWithASuffix = $@" using System.Runtime.InteropServices; partial class Test @@ -351,7 +354,7 @@ partial class Test [LibraryImport(""DoesNotExist"", EntryPoint = ""EntryA"")] public static partial void {{|CS8795:Method|}}(); }}"; - await VerifyCS.VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}A"); + await VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}A,"); } [Fact] @@ -373,7 +376,7 @@ partial class Test [LibraryImport(""DoesNotExist"", EntryPoint = EntryPoint + ""A"")] public static partial void {{|CS8795:Method|}}(); }}"; - await VerifyCS.VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}A"); + await VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}A,"); } [Fact] @@ -393,7 +396,7 @@ partial class Test [LibraryImport(""DoesNotExist"", EntryPoint = ""MethodA"")] public static partial void {{|CS8795:Method|}}(); }}"; - await VerifyCS.VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}A"); + await VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}A,"); } [Fact] @@ -415,7 +418,7 @@ partial class Test [LibraryImport(""DoesNotExist"", EntryPoint = nameof(Foo) + ""A"")] public static partial void {{|CS8795:Method|}}(); }}"; - await VerifyCS.VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}A"); + await VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}A,"); } [Fact] @@ -435,7 +438,7 @@ partial class Test [LibraryImport(""DoesNotExist"", EntryPoint = ""MethodA"")] public static partial void {{|CS8795:Method|}}(); }}"; - await VerifyCS.VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}A"); + await VerifyCodeFixAsync(source, fixedSourceWithASuffix, $"{ConvertToLibraryImportKey}A,"); } [Fact] @@ -476,7 +479,7 @@ public static void Code() Marshal.ThrowExceptionForHR(Test.Method(1, out value)); } }"; - await VerifyCS.VerifyCodeFixAsync( + await VerifyCodeFixAsync( source, fixedSource); } @@ -539,7 +542,7 @@ partial class Test public static partial int {|CS8795:Method3|}(out int ret); } }"; - await VerifyCS.VerifyCodeFixAsync( + await VerifyCodeFixAsync( source, fixedSource); } @@ -563,9 +566,320 @@ partial class Test [return: MarshalAs(UnmanagedType.Bool)] public static partial bool {{|CS8795:Method|}}([MarshalAs(UnmanagedType.Bool)] bool b); }}"; - await VerifyCS.VerifyCodeFixAsync( + await VerifyCodeFixAsync( source, fixedSource); } + + // There's not a good way today to add a unit test for any changes to project settings from a code fix. + // Roslyn does special testing for their cases. + [Fact] + public async Task FixThatAddsUnsafeToProjectUpdatesLibraryImport() + { + string source = @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [DllImport(""DoesNotExist"")] + public static extern int [|Method|](out int ret); +}}"; + // Fixed source will have CS8795 (Partial method must have an implementation) without generator run + string fixedSource = @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [LibraryImport(""DoesNotExist"")] + public static partial int {{|CS8795:Method|}}(out int ret); +}}"; + await VerifyCodeFixNoUnsafeAsync( + source, + fixedSource, + $"{ConvertToLibraryImportKey}AddUnsafe,"); + } + + [Fact] + public async Task UserBlittableStructConvertsWithNoWarningCodeAction() + { + string source = @$" +using System.Runtime.InteropServices; + +struct Blittable +{{ + private short s; + private short t; +}} + +partial class Test +{{ + [DllImport(""DoesNotExist"")] + public static extern void [|Method|](Blittable b); +}}"; + // Fixed source will have CS8795 (Partial method must have an implementation) without generator run + string fixedSource = @$" +using System.Runtime.InteropServices; + +struct Blittable +{{ + private short s; + private short t; +}} + +partial class Test +{{ + [LibraryImport(""DoesNotExist"")] + public static partial void {{|CS8795:Method|}}(Blittable b); +}}"; + await VerifyCodeFixAsync( + source, + fixedSource, + ConvertToLibraryImportKey); + } + + [Fact] + public async Task UserNonBlittableStructConvertsOnlyWithWarningCodeAction() + { + string source = @$" +using System.Runtime.InteropServices; + +struct NonBlittable +{{ + private string s; + private short t; +}} + +partial class Test +{{ + [DllImport(""DoesNotExist"")] + public static extern void [|Method|](NonBlittable b); +}}"; + // Fixed source will have CS8795 (Partial method must have an implementation) without generator run + string fixedSource = @$" +using System.Runtime.InteropServices; + +struct NonBlittable +{{ + private string s; + private short t; +}} + +partial class Test +{{ + [LibraryImport(""DoesNotExist"")] + public static partial void {{|CS8795:Method|}}(NonBlittable b); +}}"; + // Verify that we don't update this signature with the "no additional work required" action. + await VerifyCodeFixAsync( + source, + source, + ConvertToLibraryImportKey); + + await VerifyCodeFixAsync( + source, + fixedSource, + $"{ConvertToLibraryImportKey}{ConvertToLibraryImportAnalyzer.MayRequireAdditionalWork},"); + } + + [Fact] + public async Task UserBlittableStructFixAllConvertsOnlyNoWarningLocations() + { + string source = @$" +using System.Runtime.InteropServices; + +struct Blittable +{{ + private short s; + private short t; +}} + +struct NonBlittable +{{ + private string s; + private short t; +}} + +partial class Test +{{ + [DllImport(""DoesNotExist"")] + public static extern void [|Method|](int i); + [DllImport(""DoesNotExist"")] + public static extern void [|Method|](Blittable b); + [DllImport(""DoesNotExist"")] + public static extern void [|Method|](NonBlittable b); +}}"; + // Fixed sources will have CS8795 (Partial method must have an implementation) without generator run + string blittableOnlyFixedSource = @$" +using System.Runtime.InteropServices; + +struct Blittable +{{ + private short s; + private short t; +}} + +struct NonBlittable +{{ + private string s; + private short t; +}} + +partial class Test +{{ + [LibraryImport(""DoesNotExist"")] + public static partial void {{|CS8795:Method|}}(int i); + [LibraryImport(""DoesNotExist"")] + public static partial void {{|CS8795:Method|}}(Blittable b); + [DllImport(""DoesNotExist"")] + public static extern void [|Method|](NonBlittable b); +}}"; + // Verify that we only fix the blittable cases, not the non-blittable cases. + await VerifyCodeFixAsync( + source, + blittableOnlyFixedSource, + ConvertToLibraryImportKey); + } + + [Fact] + public async Task UserNonBlittableStructFixAllConvertsAllLocations() + { + string source = @$" +using System.Runtime.InteropServices; + +struct Blittable +{{ + private short s; + private short t; +}} + +struct NonBlittable +{{ + private string s; + private short t; +}} + +partial class Test +{{ + [DllImport(""DoesNotExist"")] + public static extern void [|Method|](int i); + [DllImport(""DoesNotExist"")] + public static extern void [|Method|](Blittable b); + [DllImport(""DoesNotExist"")] + public static extern void [|Method|](NonBlittable b); +}}"; + // Fixed sources will have CS8795 (Partial method must have an implementation) without generator run + string nonBlittableOnlyFixedSource = @$" +using System.Runtime.InteropServices; + +struct Blittable +{{ + private short s; + private short t; +}} + +struct NonBlittable +{{ + private string s; + private short t; +}} + +partial class Test +{{ + [DllImport(""DoesNotExist"")] + public static extern void [|Method|](int i); + [DllImport(""DoesNotExist"")] + public static extern void [|Method|](Blittable b); + [LibraryImport(""DoesNotExist"")] + public static partial void {{|CS8795:Method|}}(NonBlittable b); +}}"; + // Fixed sources will have CS8795 (Partial method must have an implementation) without generator run + string allFixedSource = @$" +using System.Runtime.InteropServices; + +struct Blittable +{{ + private short s; + private short t; +}} + +struct NonBlittable +{{ + private string s; + private short t; +}} + +partial class Test +{{ + [LibraryImport(""DoesNotExist"")] + public static partial void {{|CS8795:Method|}}(int i); + [LibraryImport(""DoesNotExist"")] + public static partial void {{|CS8795:Method|}}(Blittable b); + [LibraryImport(""DoesNotExist"")] + public static partial void {{|CS8795:Method|}}(NonBlittable b); +}}"; + + // Verify that we fix all cases when we do fix-all on a P/Invoke with a non-blittable user type which + // will require the user to write additional code. + await VerifyCodeFixAsync( + source, + nonBlittableOnlyFixedSource, + allFixedSource, + $"{ConvertToLibraryImportKey}{ConvertToLibraryImportAnalyzer.MayRequireAdditionalWork},"); + } + + private static async Task VerifyCodeFixAsync(string source, string fixedSource) + { + var test = new VerifyCS.Test + { + TestCode = source, + FixedCode = fixedSource, + }; + + await test.RunAsync(); + } + + private static async Task VerifyCodeFixAsync(string source, string fixedSource, string equivalenceKey) + { + var test = new VerifyCS.Test + { + TestCode = source, + FixedCode = fixedSource, + CodeActionEquivalenceKey = equivalenceKey, + }; + + test.FixedState.MarkupHandling = Microsoft.CodeAnalysis.Testing.MarkupMode.Allow; + + await test.RunAsync(); + } + + private static async Task VerifyCodeFixAsync(string source, string fixedSource, string batchFixedSource, string equivalenceKey) + { + var test = new VerifyCS.Test + { + TestCode = source, + FixedCode = fixedSource, + BatchFixedCode = batchFixedSource, + CodeActionEquivalenceKey = equivalenceKey, + }; + + test.FixedState.MarkupHandling = Microsoft.CodeAnalysis.Testing.MarkupMode.Allow; + + await test.RunAsync(); + } + + private static async Task VerifyCodeFixNoUnsafeAsync(string source, string fixedSource, string equivalenceKey) + { + var test = new TestNoUnsafe + { + TestCode = source, + FixedCode = fixedSource, + CodeActionEquivalenceKey = equivalenceKey, + }; + + await test.RunAsync(); + } + + class TestNoUnsafe : VerifyCS.Test + { + protected override CompilationOptions CreateCompilationOptions() => ((CSharpCompilationOptions)base.CreateCompilationOptions()).WithAllowUnsafe(false); + } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CustomMarshallerAttributeFixerTests_StatefulLinearCollectionShapeValidation.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CustomMarshallerAttributeFixerTests_StatefulLinearCollectionShapeValidation.cs new file mode 100644 index 00000000000000..0ad27bb6b2f8e8 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CustomMarshallerAttributeFixerTests_StatefulLinearCollectionShapeValidation.cs @@ -0,0 +1,457 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.Interop; +using System.Collections.Generic; +using System.Threading.Tasks; +using Xunit; +using static Microsoft.Interop.Analyzers.CustomMarshallerAttributeAnalyzer; + +using VerifyCS = LibraryImportGenerator.UnitTests.Verifiers.CSharpCodeFixVerifier< + Microsoft.Interop.Analyzers.CustomMarshallerAttributeAnalyzer, + Microsoft.Interop.Analyzers.CustomMarshallerAttributeFixer>; + +namespace LibraryImportGenerator.UnitTests +{ + [ActiveIssue("https://github.com/dotnet/runtime/issues/60650", TestRuntimes.Mono)] + public class CustomMarshallerAttributeAnalyzerTests_StatefulLinearCollectionShapeValidation + { + [Fact] + public async Task ModeThatUsesManagedToUnmanagedShape_Missing_AllMethods_ReportsDiagnostic() + { + string source = """ + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedIn, typeof({|#0:MarshallerType<>|}))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedOut, typeof({|#1:MarshallerType<>|}))] + [ContiguousCollectionMarshaller] + struct MarshallerType + { + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(StatefulMarshallerRequiresFreeRule).WithLocation(0).WithArguments("MarshallerType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresFromManagedRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedIn, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresFromManagedRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedOut, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresToUnmanagedRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedIn, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresToUnmanagedRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedOut, "ManagedType"), + VerifyCS.Diagnostic(LinearCollectionInRequiresCollectionMethodsRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedIn, "ManagedType"), + VerifyCS.Diagnostic(LinearCollectionInRequiresCollectionMethodsRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedOut, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresFreeRule).WithLocation(1).WithArguments("MarshallerType")); + } + + [Fact] + public async Task ModeThatUsesManagedToUnmanagedShape_Missing_ContainerMethods_ReportsDiagnostic() + { + string source = """ + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedIn, typeof({|#0:MarshallerType<>|}))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedOut, typeof({|#1:MarshallerType<>|}))] + [ContiguousCollectionMarshaller] + struct MarshallerType + { + public void FromManaged(ManagedType m) {} + public nint ToUnmanaged() => default; + public void Free() {} + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(LinearCollectionInRequiresCollectionMethodsRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedIn, "ManagedType"), + VerifyCS.Diagnostic(LinearCollectionInRequiresCollectionMethodsRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedOut, "ManagedType")); + } + + [Fact] + public async Task ModeThatUsesManagedToUnmanagedShape_Missing_GetManagedValuesSource_ReportsDiagnostic() + { + string source = """ + using System; + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedIn, typeof({|#0:MarshallerType<>|}))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedOut, typeof({|#1:MarshallerType<>|}))] + [ContiguousCollectionMarshaller] + struct MarshallerType + { + public void FromManaged(ManagedType m) {} + public nint ToUnmanaged() => default; + public void Free() {} + public Span GetUnmanagedValuesDestination() => default; + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(LinearCollectionInRequiresCollectionMethodsRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedIn, "ManagedType"), + VerifyCS.Diagnostic(LinearCollectionInRequiresCollectionMethodsRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedOut, "ManagedType")); + } + + [Fact] + public async Task ModeThatUsesManagedToUnmanagedShape_Missing_GetUnmanagedValuesDestination_ReportsDiagnostic() + { + string source = """ + using System; + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedIn, typeof({|#0:MarshallerType<>|}))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedOut, typeof({|#1:MarshallerType<>|}))] + [ContiguousCollectionMarshaller] + struct MarshallerType + { + public void FromManaged(ManagedType m) {} + public nint ToUnmanaged() => default; + public void Free() {} + public ReadOnlySpan GetManagedValuesSource() => default; + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(LinearCollectionInRequiresCollectionMethodsRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedOut, "ManagedType"), + VerifyCS.Diagnostic(LinearCollectionInRequiresCollectionMethodsRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedIn, "ManagedType")); + } + + [Fact] + public async Task ModeThatUsesManagedToUnmanagedShape_DoesNotReportDiagnostic() + { + string source = """ + using System; + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedIn, typeof(MarshallerType<>))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedOut, typeof(MarshallerType<>))] + [ContiguousCollectionMarshaller] + struct MarshallerType + { + public void FromManaged(ManagedType m) {} + public nint ToUnmanaged() => default; + public void Free() {} + public ReadOnlySpan GetManagedValuesSource() => default; + public Span GetUnmanagedValuesDestination() => default; + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source); + } + + + [Fact] + public async Task ModeThatUsesManagedToUnmanagedShape_InvalidCollectionElementType_DoesNotReportDiagnostic() + { + string source = """ + using System; + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedIn, typeof({|#0:MarshallerType<>|}))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedOut, typeof({|#1:MarshallerType<>|}))] + [ContiguousCollectionMarshaller] + struct MarshallerType + { + public void FromManaged(ManagedType m) {} + public nint ToUnmanaged() => default; + public void Free() {} + public ReadOnlySpan GetManagedValuesSource() => default; + public Span GetUnmanagedValuesDestination() => default; + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(ReturnTypeMustBeExpectedTypeRule).WithLocation(0).WithArguments("MarshallerType.GetUnmanagedValuesDestination()", "System.Span"), + VerifyCS.Diagnostic(ReturnTypeMustBeExpectedTypeRule).WithLocation(1).WithArguments("MarshallerType.GetUnmanagedValuesDestination()", "System.Span")); + } + + [Fact] + public async Task ModeThatUsesUnmanagedToManagedShape_Missing_AllMethods_ReportsDiagnostic() + { + string source = """ + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedOut, typeof({|#0:MarshallerType<>|}))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedIn, typeof({|#1:MarshallerType<>|}))] + [ContiguousCollectionMarshaller] + struct MarshallerType + { + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(StatefulMarshallerRequiresFreeRule).WithLocation(0).WithArguments("MarshallerType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresToManagedRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedOut, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresToManagedRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedIn, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresFromUnmanagedRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedOut, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresFromUnmanagedRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedIn, "ManagedType"), + VerifyCS.Diagnostic(LinearCollectionOutRequiresCollectionMethodsRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedOut, "ManagedType"), + VerifyCS.Diagnostic(LinearCollectionOutRequiresCollectionMethodsRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedIn, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresFreeRule).WithLocation(1).WithArguments("MarshallerType")); + } + + [Fact] + public async Task ModeThatUsesUnmanagedToManagedShape_Missing_ContainerMethods_ReportsDiagnostic() + { + string source = """ + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedOut, typeof({|#0:MarshallerType<>|}))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedIn, typeof({|#1:MarshallerType<>|}))] + [ContiguousCollectionMarshaller] + struct MarshallerType + { + public void FromUnmanaged(int f) {} + public ManagedType ToManaged() => default; + public void Free() {} + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(LinearCollectionOutRequiresCollectionMethodsRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedOut, "ManagedType"), + VerifyCS.Diagnostic(LinearCollectionOutRequiresCollectionMethodsRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedIn, "ManagedType")); + } + + [Fact] + public async Task ModeThatUsesUnmanagedToManagedShape_Missing_GetUnmanagedValuesSource_ReportsDiagnostic() + { + string source = """ + using System; + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedOut, typeof({|#0:MarshallerType<>|}))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedIn, typeof({|#1:MarshallerType<>|}))] + [ContiguousCollectionMarshaller] + struct MarshallerType + { + public void FromUnmanaged(int f) {} + public ManagedType ToManaged() => default; + public void Free() {} + public Span GetManagedValuesDestination(int numElements) => default; + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(LinearCollectionOutRequiresCollectionMethodsRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedOut, "ManagedType"), + VerifyCS.Diagnostic(LinearCollectionOutRequiresCollectionMethodsRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedIn, "ManagedType")); + } + + [Fact] + public async Task ModeThatUsesUnmanagedToManagedShape_Missing_GetManagedValuesDestination_ReportsDiagnostic() + { + string source = """ + using System; + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedOut, typeof({|#0:MarshallerType<>|}))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedIn, typeof({|#1:MarshallerType<>|}))] + [ContiguousCollectionMarshaller] + struct MarshallerType + { + public void FromUnmanaged(int f) {} + public ManagedType ToManaged() => default; + public void Free() {} + public ReadOnlySpan GetUnmanagedValuesSource(int numElements) => default; + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(LinearCollectionOutRequiresCollectionMethodsRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedIn, "ManagedType"), + VerifyCS.Diagnostic(LinearCollectionOutRequiresCollectionMethodsRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedOut, "ManagedType")); + } + + [Fact] + public async Task ModeThatUsesUnmanagedToManagedShape_DoesNotReportDiagnostic() + { + string source = """ + using System; + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedOut, typeof(MarshallerType<>))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedIn, typeof(MarshallerType<>))] + [ContiguousCollectionMarshaller] + struct MarshallerType + { + public void FromUnmanaged(int f) {} + public ManagedType ToManaged() => default; + public void Free() {} + public Span GetManagedValuesDestination(int numElements) => default; + public ReadOnlySpan GetUnmanagedValuesSource(int numElements) => default; + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source); + } + + [Fact] + public async Task ModeThatUsesUnmanagedToManagedShape_InvalidCollectionElementType_ReportsDiagnostic() + { + string source = """ + using System; + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedOut, typeof({|#0:MarshallerType<>|}))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedIn, typeof({|#1:MarshallerType<>|}))] + [ContiguousCollectionMarshaller] + struct MarshallerType + { + public void FromUnmanaged(int f) {} + public ManagedType ToManaged() => default; + public void Free() {} + public Span GetManagedValuesDestination(int numElements) => default; + public ReadOnlySpan GetUnmanagedValuesSource(int numElements) => default; + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(ReturnTypeMustBeExpectedTypeRule).WithLocation(0).WithArguments("MarshallerType.GetUnmanagedValuesSource(int)", "System.ReadOnlySpan"), + VerifyCS.Diagnostic(ReturnTypeMustBeExpectedTypeRule).WithLocation(1).WithArguments("MarshallerType.GetUnmanagedValuesSource(int)", "System.ReadOnlySpan")); + } + + [Fact] + public async Task CallerAllocatedBuffer_NoBufferSize_ReportsDiagnostic() + { + string source = """ + using System; + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedIn, typeof({|#0:MarshallerType<>|}))] + [ContiguousCollectionMarshaller] + struct MarshallerType + { + public void FromManaged(ManagedType m, Span buffer) {} + public nint ToUnmanaged() => default; + public void Free() {} + public ReadOnlySpan GetManagedValuesSource() => default; + public Span GetUnmanagedValuesDestination() => default; + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(CallerAllocFromManagedMustHaveBufferSizeRule).WithLocation(0).WithArguments("MarshallerType", "byte")); + } + + [Fact] + public async Task ModeThatUsesBidirectionalShape_DoesNotReportDiagnostic() + { + string source = """ + using System; + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedRef, typeof({|#0:MarshallerType<>|}))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedRef, typeof({|#1:MarshallerType<>|}))] + [ContiguousCollectionMarshaller] + struct MarshallerType + { + public void FromManaged(ManagedType m) {} + public nint ToUnmanaged() => default; + public ReadOnlySpan GetManagedValuesSource() => default; + public Span GetUnmanagedValuesDestination() => default; + public void FromUnmanaged(nint i) {} + public ManagedType ToManaged() => default; + public Span GetManagedValuesDestination(int numElements) => default; + public ReadOnlySpan GetUnmanagedValuesSource(int numElements) => default; + public void Free() {} + } + """; + + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task ModeThatUsesBidirectionalShape_MismatchedManagedElementTypes_ReportsDiagnostic() + { + string source = """ + using System; + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedRef, typeof({|#0:MarshallerType<>|}))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedRef, typeof({|#1:MarshallerType<>|}))] + [ContiguousCollectionMarshaller] + struct MarshallerType + { + public void FromManaged(ManagedType m) {} + public nint ToUnmanaged() => default; + public ReadOnlySpan GetManagedValuesSource() => default; + public Span GetUnmanagedValuesDestination() => default; + public void FromUnmanaged(nint i) {} + public ManagedType ToManaged() => default; + public Span GetManagedValuesDestination(int numElements) => default; + public ReadOnlySpan GetUnmanagedValuesSource(int numElements) => default; + public void Free() {} + } + """; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(ElementTypesOfReturnTypesMustMatchRule).WithLocation(0).WithArguments("MarshallerType.GetManagedValuesSource()", "MarshallerType.GetManagedValuesDestination(int)"), + VerifyCS.Diagnostic(ElementTypesOfReturnTypesMustMatchRule).WithLocation(1).WithArguments("MarshallerType.GetManagedValuesSource()", "MarshallerType.GetManagedValuesDestination(int)")); + } + + [Fact] + public async Task ModeThatUsesBidirectionalShape_ArrayTarget_DoesNotReportDiagnostic() + { + string source = """ + using System; + using System.Runtime.InteropServices.Marshalling; + + [CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder[]), MarshalMode.ManagedToUnmanagedRef, typeof({|#0:MarshallerType<,>|}))] + [CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder[]), MarshalMode.UnmanagedToManagedRef, typeof({|#1:MarshallerType<,>|}))] + [ContiguousCollectionMarshaller] + struct MarshallerType + { + public void FromManaged(T[] m) {} + public nint ToUnmanaged() => default; + public ReadOnlySpan GetManagedValuesSource() => default; + public Span GetUnmanagedValuesDestination() => default; + public void FromUnmanaged(nint i) {} + public T[] ToManaged() => default; + public Span GetManagedValuesDestination(int numElements) => default; + public ReadOnlySpan GetUnmanagedValuesSource(int numElements) => default; + public void Free() {} + } + """; + + await VerifyCS.VerifyAnalyzerAsync(source); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CustomMarshallerAttributeFixerTests_StatefulValueShapeValidation.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CustomMarshallerAttributeFixerTests_StatefulValueShapeValidation.cs new file mode 100644 index 00000000000000..f3e6710d8bf8c9 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CustomMarshallerAttributeFixerTests_StatefulValueShapeValidation.cs @@ -0,0 +1,249 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.Interop; +using System.Collections.Generic; +using System.Threading.Tasks; +using Xunit; +using static Microsoft.Interop.Analyzers.CustomMarshallerAttributeAnalyzer; + +using VerifyCS = LibraryImportGenerator.UnitTests.Verifiers.CSharpCodeFixVerifier< + Microsoft.Interop.Analyzers.CustomMarshallerAttributeAnalyzer, + Microsoft.Interop.Analyzers.CustomMarshallerAttributeFixer>; + +namespace LibraryImportGenerator.UnitTests +{ + [ActiveIssue("https://github.com/dotnet/runtime/issues/60650", TestRuntimes.Mono)] + public class CustomMarshallerAttributeAnalyzerTests_StatefulValueShapeValidation + { + [Fact] + public async Task ModeThatUsesManagedToUnmanagedShape_Missing_AllMethods_ReportsDiagnostic() + { + string source = """ + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedIn, typeof({|#0:MarshallerType|}))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedOut, typeof({|#1:MarshallerType|}))] + struct MarshallerType + { + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(StatefulMarshallerRequiresFromManagedRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedIn, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresFromManagedRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedOut, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresToUnmanagedRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedIn, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresToUnmanagedRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedOut, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresFreeRule).WithLocation(0).WithArguments("MarshallerType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresFreeRule).WithLocation(1).WithArguments("MarshallerType")); + } + + [Fact] + public async Task ModeThatUsesUnmanagedToManagedShape_Missing_AllMethods_ReportsDiagnostic() + { + string source = """ + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedOut, typeof({|#0:MarshallerType|}))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedIn, typeof({|#1:MarshallerType|}))] + struct MarshallerType + { + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(StatefulMarshallerRequiresFromUnmanagedRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedOut, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresFromUnmanagedRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedIn, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresToManagedRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedOut, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresToManagedRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedIn, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresFreeRule).WithLocation(0).WithArguments("MarshallerType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresFreeRule).WithLocation(1).WithArguments("MarshallerType")); + } + + [Fact] + public async Task Overloaded_FromUnmanaged_ReportsDiagnostic() + { + string source = """ + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedOut, typeof({|#0:MarshallerType|}))] + struct MarshallerType + { + public ManagedType ToManaged() => default; + public void FromUnmanaged(int i) {} + public void FromUnmanaged(float f) {} + public void Free() {} + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(FromUnmanagedOverloadsNotSupportedRule).WithLocation(0).WithArguments("MarshallerType")); + } + + [Fact] + public async Task ModeThatUsesBidirectionalShape_Missing_AllMethods_ReportsDiagnostic() + { + string source = """ + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedRef, typeof({|#0:MarshallerType|}))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedRef, typeof({|#1:MarshallerType|}))] + struct MarshallerType + { + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(StatefulMarshallerRequiresFreeRule).WithLocation(0).WithArguments("MarshallerType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresFromManagedRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedRef, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresFromManagedRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedRef, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresToUnmanagedRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedRef, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresToUnmanagedRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedRef, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresFromUnmanagedRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedRef, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresFromUnmanagedRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedRef, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresToManagedRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ManagedToUnmanagedRef, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresToManagedRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.UnmanagedToManagedRef, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresFreeRule).WithLocation(1).WithArguments("MarshallerType")); + } + + [Fact] + public async Task ModeThatUsesBidirectionalShape_MismatchedUnmanagedTypes_ReportsDiagnostic() + { + string source = """ + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedRef, typeof({|#0:MarshallerType|}))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedRef, typeof({|#1:MarshallerType|}))] + struct MarshallerType + { + public void FromManaged(ManagedType t) {} + public int ToUnmanaged() => default; + public void FromUnmanaged(float f) {} + public ManagedType ToManaged() => default; + public void Free() {} + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(FirstParameterMustMatchReturnTypeRule).WithLocation(0).WithArguments("MarshallerType.FromUnmanaged(float)", "MarshallerType.ToUnmanaged()"), + VerifyCS.Diagnostic(FirstParameterMustMatchReturnTypeRule).WithLocation(1).WithArguments("MarshallerType.FromUnmanaged(float)", "MarshallerType.ToUnmanaged()")); + } + + [Fact] + public async Task ModeThatUsesBidirectionalShape_DoesNotReportDiagnostic() + { + string source = """ + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedRef, typeof(MarshallerType))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedRef, typeof(MarshallerType))] + struct MarshallerType + { + public void FromManaged(ManagedType t) {} + public int ToUnmanaged() => default; + public void FromUnmanaged(int f) {} + public ManagedType ToManaged() => default; + public void Free() {} + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source); + } + + [Fact] + public async Task ModeThatUsesElementMode_ReportsDiagnostic() + { + string source = """ + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ElementIn, typeof({|#0:MarshallerType|}))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.ElementRef, typeof({|#1:MarshallerType|}))] + [CustomMarshaller(typeof(ManagedType), MarshalMode.ElementOut, typeof({|#2:MarshallerType|}))] + struct MarshallerType + { + public void FromManaged(ManagedType t) {} + public int ToUnmanaged() => default; + public void FromUnmanaged(int f) {} + public ManagedType ToManaged() => default; + public void Free() {} + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(ElementMarshallerCannotBeStatefulRule).WithLocation(0).WithArguments("MarshallerType", MarshalMode.ElementIn), + VerifyCS.Diagnostic(ElementMarshallerCannotBeStatefulRule).WithLocation(1).WithArguments("MarshallerType", MarshalMode.ElementRef), + VerifyCS.Diagnostic(ElementMarshallerCannotBeStatefulRule).WithLocation(2).WithArguments("MarshallerType", MarshalMode.ElementOut)); + } + + [Fact] + public async Task DefaultMode_Missing_AllMethods_ReportsDiagnostic() + { + string source = """ + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.Default, typeof({|#0:MarshallerType|}))] + struct MarshallerType + { + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(StatefulMarshallerRequiresFreeRule).WithLocation(0).WithArguments("MarshallerType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresFromManagedRule).WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithArguments("MarshallerType", MarshalMode.Default, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresToUnmanagedRule).WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithArguments("MarshallerType", MarshalMode.Default, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresFromUnmanagedRule).WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithArguments("MarshallerType", MarshalMode.Default, "ManagedType"), + VerifyCS.Diagnostic(StatefulMarshallerRequiresToManagedRule).WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithArguments("MarshallerType", MarshalMode.Default, "ManagedType")); + } + + [Fact] + public async Task CallerAllocatedBuffer_NoBufferSize_ReportsDiagnostic() + { + string source = """ + using System; + using System.Runtime.InteropServices.Marshalling; + + class ManagedType {} + + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedIn, typeof({|#0:MarshallerType|}))] + struct MarshallerType + { + public void FromManaged(ManagedType m, Span b) {} + + public int ToUnmanaged() => default; + + public void Free() {} + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(CallerAllocFromManagedMustHaveBufferSizeRule).WithLocation(0).WithArguments("MarshallerType", "byte")); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CustomMarshallerAttributeFixerTests_StatelessLinearCollectionShapeValidation.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CustomMarshallerAttributeFixerTests_StatelessLinearCollectionShapeValidation.cs index bff15a1a125ba4..5f1c0db2f4a28f 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CustomMarshallerAttributeFixerTests_StatelessLinearCollectionShapeValidation.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CustomMarshallerAttributeFixerTests_StatelessLinearCollectionShapeValidation.cs @@ -665,7 +665,7 @@ public static int BufferSize await VerifyCS.VerifyCodeFixAsync( source, fixedSource, - VerifyCS.Diagnostic(StatelessLinearCollectionCallerAllocConstructorMustHaveBufferSizeRule).WithLocation(0).WithArguments("MarshallerType", "byte")); + VerifyCS.Diagnostic(StatelessLinearCollectionCallerAllocFromManagedMustHaveBufferSizeRule).WithLocation(0).WithArguments("MarshallerType", "byte")); } [Fact] diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CustomMarshallerAttributeFixerTests_StatelessValueShapeValidation.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CustomMarshallerAttributeFixerTests_StatelessValueShapeValidation.cs index dab3f86e3da840..dbfe4d8d2e9e90 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CustomMarshallerAttributeFixerTests_StatelessValueShapeValidation.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CustomMarshallerAttributeFixerTests_StatelessValueShapeValidation.cs @@ -376,7 +376,7 @@ public static int BufferSize await VerifyCS.VerifyCodeFixAsync( source, fixedSource, - VerifyCS.Diagnostic(CallerAllocConstructorMustHaveBufferSizeRule).WithLocation(0).WithArguments("MarshallerType", "byte")); + VerifyCS.Diagnostic(CallerAllocFromManagedMustHaveBufferSizeRule).WithLocation(0).WithArguments("MarshallerType", "byte")); } [Fact] @@ -384,7 +384,7 @@ public async Task ModeThatUsesManagedToUnmanagedShape_Missing_ConvertToUnmanaged { string entryPointTypeSource = """ using System.Runtime.InteropServices.Marshalling; - + class ManagedType {} [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedIn, typeof({|SYSLIB1057:OtherMarshallerType|}))] @@ -427,9 +427,9 @@ public async Task ModeThatUsesManagedToUnmanagedShape_Missing_ConvertToUnmanaged { string entryPointTypeSource = """ using System.Runtime.InteropServices.Marshalling; - + class ManagedType {} - + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedIn, typeof({|SYSLIB1057:OtherMarshallerType|}))] [CustomMarshaller(typeof(ManagedType), MarshalMode.UnmanagedToManagedOut, typeof({|SYSLIB1057:OtherMarshallerType|}))] [CustomMarshaller(typeof(ManagedType), MarshalMode.ElementIn, typeof({|SYSLIB1057:OtherMarshallerType|}))] @@ -482,10 +482,10 @@ public async Task ModeThatUsesManagedToUnmanagedShape_Missing_ConvertToUnmanaged { string source = """ using System.Runtime.InteropServices.Marshalling; - + class ManagedType {} class ManagedType2 {} - + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedIn, typeof({|#0:MarshallerType|}))] [CustomMarshaller(typeof(ManagedType2), MarshalMode.ManagedToUnmanagedIn, typeof({|#1:MarshallerType|}))] static class MarshallerType @@ -495,10 +495,10 @@ static class MarshallerType string fixedSource = """ using System.Runtime.InteropServices.Marshalling; - + class ManagedType {} class ManagedType2 {} - + [CustomMarshaller(typeof(ManagedType), MarshalMode.ManagedToUnmanagedIn, typeof(MarshallerType))] [CustomMarshaller(typeof(ManagedType2), MarshalMode.ManagedToUnmanagedIn, typeof(MarshallerType))] static class MarshallerType diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.ComDisabled.UnitTests/System/Runtime/InteropServices/Marshal/MarshalComDisabledTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.ComDisabled.UnitTests/System/Runtime/InteropServices/Marshal/MarshalComDisabledTests.cs index 57a5887d4a2f75..fafcc5a3b919a6 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.ComDisabled.UnitTests/System/Runtime/InteropServices/Marshal/MarshalComDisabledTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.ComDisabled.UnitTests/System/Runtime/InteropServices/Marshal/MarshalComDisabledTests.cs @@ -10,6 +10,7 @@ namespace System.Runtime.InteropServices.Tests public partial class MarshalComDisabledTests { [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/72914", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))] public void GetTypeFromCLSID_ThrowsNotSupportedException() { Assert.Throws(() => Marshal.GetTypeFromCLSID(Guid.Empty)); @@ -67,12 +68,14 @@ public void CreateWrapperOfType_T_TWrapper_ThrowsNotSupportedException() } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/72911", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))] public void GetNativeVariantForObject_ThrowsNotSupportedException() { Assert.Throws(() => Marshal.GetNativeVariantForObject(99, IntPtr.Zero)); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/72911", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))] public void GetNativeVariantForObject_T_ThrowsNotSupportedException() { Assert.Throws(() => Marshal.GetNativeVariantForObject(99, IntPtr.Zero)); @@ -81,6 +84,7 @@ public void GetNativeVariantForObject_T_ThrowsNotSupportedException() public struct NativeVariant{} [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/72911", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))] public void GetObjectForNativeVariant_ThrowsNotSupportedException() { NativeVariant variant = new NativeVariant(); @@ -100,6 +104,7 @@ public void GetObjectForNativeVariant_ThrowsNotSupportedException() public struct NativeVariant_T{} [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/72911", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))] public void GetObjectForNativeVariant_T_ThrowsNotSupportedException() { NativeVariant_T variant = new NativeVariant_T(); diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index 53b4eebac73af5..ea3b1bfdef1a6c 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -2573,7 +2573,10 @@ public static void GetSystemTimeZones_AllTimeZonesHaveOffsetInValidRange() // 0x3E, 0x2C, 0x30, 0x2F, 0x30, 0x2C, 0x4A, 0x33, 0x36, 0x35, 0x2F, 0x32, 0x35, 0x0A }; - [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + // https://github.com/dotnet/runtime/issues/73031 is the tracking issue to investigate the test failure on Android. + private static bool CanRunNJulianRuleTest => !PlatformDetection.IsLinuxBionic && RemoteExecutor.IsSupported; + + [ConditionalTheory(nameof(CanRunNJulianRuleTest))] [PlatformSpecific(TestPlatforms.AnyUnix)] [InlineData("<+00>0<+01>,0/0,J365/25", 1, 1, true)] [InlineData("<+00>0<+01>,30/0,J365/25", 31, 1, true)] diff --git a/src/libraries/System.Text.Json/src/Resources/Strings.resx b/src/libraries/System.Text.Json/src/Resources/Strings.resx index f4f1cc96e76d51..01d0af8f556137 100644 --- a/src/libraries/System.Text.Json/src/Resources/Strings.resx +++ b/src/libraries/System.Text.Json/src/Resources/Strings.resx @@ -659,4 +659,13 @@ Parameter already associated with a different JsonTypeInfo instance. + + JsonPropertyInfo '{0}' defined in type '{1}' is marked required but does not specify a setter. + + + JsonPropertyInfo '{0}' defined in type '{1}' is marked both as required and as an extension data property. This combination is not supported. + + + JSON deserialization for type '{0}' was missing required properties, including the following: {1} + diff --git a/src/libraries/System.Text.Json/src/System/ReflectionExtensions.cs b/src/libraries/System.Text.Json/src/System/ReflectionExtensions.cs index 9a5d6f4bb610d9..e15e8993889e43 100644 --- a/src/libraries/System.Text.Json/src/System/ReflectionExtensions.cs +++ b/src/libraries/System.Text.Json/src/System/ReflectionExtensions.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; @@ -42,6 +43,32 @@ public static bool IsInSubtypeRelationshipWith(this Type type, Type other) => private static bool HasJsonConstructorAttribute(ConstructorInfo constructorInfo) => constructorInfo.GetCustomAttribute() != null; + public static bool HasRequiredMemberAttribute(this ICustomAttributeProvider memberInfo) + { + // For compiler related attributes we should only look at full type name rather than trying to do something different for version when attribute was introduced. + // I.e. library is targetting netstandard2.0 with polyfilled attributes and is being consumed by app targetting net7.0. + return memberInfo.HasCustomAttributeWithName("System.Runtime.CompilerServices.RequiredMemberAttribute", inherit: true); + } + + public static bool HasSetsRequiredMembersAttribute(this ICustomAttributeProvider memberInfo) + { + // See comment for HasRequiredMemberAttribute for why we need to always only look at full name + return memberInfo.HasCustomAttributeWithName("System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute", inherit: true); + } + + private static bool HasCustomAttributeWithName(this ICustomAttributeProvider memberInfo, string fullName, bool inherit) + { + foreach (object attribute in memberInfo.GetCustomAttributes(inherit)) + { + if (attribute.GetType().FullName == fullName) + { + return true; + } + } + + return false; + } + public static TAttribute? GetUniqueCustomAttribute(this MemberInfo memberInfo, bool inherit) where TAttribute : Attribute { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs index 0bdd85880bd0fa..6aced2cc4b9145 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Buffers; +using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; @@ -147,5 +148,19 @@ public static void ValidateInt32MaxArrayLength(uint length) ThrowHelper.ThrowOutOfMemoryException(length); } } + + public static bool AllBitsEqual(this BitArray bitArray, bool value) + { + // Optimize this when https://github.com/dotnet/runtime/issues/72999 is fixed + for (int i = 0; i < bitArray.Count; i++) + { + if (bitArray[i] != value) + { + return false; + } + } + + return true; + } } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/CastingConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/CastingConverter.cs index 72f8dd8d711379..0242cb2ab30ad2 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/CastingConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/CastingConverter.cs @@ -25,6 +25,7 @@ internal CastingConverter(JsonConverter sourceConverter) : base(initial IsInternalConverterForNumberType = sourceConverter.IsInternalConverterForNumberType; RequiresReadAhead = sourceConverter.RequiresReadAhead; CanUseDirectReadOrWrite = sourceConverter.CanUseDirectReadOrWrite; + CanBePolymorphic = sourceConverter.CanBePolymorphic; } public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) @@ -91,6 +92,11 @@ static void HandleFailure(TSource? source) private static TSource CastOnWrite(T source) { + if (default(TSource) is not null && default(T) is null && source is null) + { + ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(typeof(TSource)); + } + return (TSource)(object?)source!; } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonMetadataServicesConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonMetadataServicesConverter.cs index d921c7b6e8e988..fd8e6367cd4dd3 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonMetadataServicesConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonMetadataServicesConverter.cs @@ -70,13 +70,12 @@ internal override bool OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializer Debug.Assert(options == jsonTypeInfo.Options); if (!state.SupportContinuation && - jsonTypeInfo.HasSerializeHandler && - jsonTypeInfo is JsonTypeInfo info && - !state.CurrentContainsMetadata && // Do not use the fast path if state needs to write metadata. - info.Options.SerializerContext?.CanUseSerializationLogic == true) + jsonTypeInfo.CanUseSerializeHandler && + !state.CurrentContainsMetadata) // Do not use the fast path if state needs to write metadata. { - Debug.Assert(info.SerializeHandler != null); - info.SerializeHandler(writer, value); + Debug.Assert(jsonTypeInfo is JsonTypeInfo typeInfo && typeInfo.SerializeHandler != null); + Debug.Assert(options.SerializerContext?.CanUseSerializationLogic == true); + ((JsonTypeInfo)jsonTypeInfo).SerializeHandler!(writer, value); return true; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectDefaultConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectDefaultConverter.cs index 9871d76f83d5b0..365a8d2901279c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectDefaultConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectDefaultConverter.cs @@ -39,6 +39,7 @@ internal override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, obj = jsonTypeInfo.CreateObject()!; jsonTypeInfo.OnDeserializing?.Invoke(obj); + state.Current.InitializeRequiredPropertiesValidationState(jsonTypeInfo); // Process all properties. while (true) @@ -143,6 +144,7 @@ internal override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, state.Current.ReturnValue = obj; state.Current.ObjectState = StackFrameObjectState.CreatedObject; + state.Current.InitializeRequiredPropertiesValidationState(jsonTypeInfo); } else { @@ -250,6 +252,7 @@ internal override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, } jsonTypeInfo.OnDeserialized?.Invoke(obj); + state.Current.ValidateAllRequiredPropertiesAreRead(jsonTypeInfo); // Unbox Debug.Assert(obj != null); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs index a369e8a349bcf6..eabe8e6a62fec6 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs @@ -24,6 +24,9 @@ protected sealed override bool ReadAndCacheConstructorArgument(ref ReadStack sta if (success && !(arg == null && jsonParameterInfo.IgnoreNullTokensOnRead)) { ((object[])state.Current.CtorArgumentState!.Arguments)[jsonParameterInfo.ClrInfo.Position] = arg!; + + // if this is required property IgnoreNullTokensOnRead will always be false because we don't allow for both to be true + state.Current.MarkRequiredPropertyAsRead(jsonParameterInfo.MatchingProperty); } return success; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Small.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Small.cs index 913198dd364199..1482a32144ec4f 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Small.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Small.cs @@ -71,6 +71,11 @@ private static bool TryRead( ? (TArg?)info.DefaultValue! // Use default value specified on parameter, if any. : value!; + if (success) + { + state.Current.MarkRequiredPropertyAsRead(jsonParameterInfo.MatchingProperty); + } + return success; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.cs index 9a2b85469f9821..d0faaa3c3d238b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.cs @@ -184,7 +184,15 @@ internal sealed override bool OnTryRead(ref Utf8JsonReader reader, Type typeToCo if (dataExtKey == null) { - jsonPropertyInfo.SetExtensionDictionaryAsObject(obj, propValue); + Debug.Assert(jsonPropertyInfo.Set != null); + + if (propValue is not null || !jsonPropertyInfo.IgnoreNullTokensOnRead || default(T) is not null) + { + jsonPropertyInfo.Set(obj, propValue); + + // if this is required property IgnoreNullTokensOnRead will always be false because we don't allow for both to be true + state.Current.MarkRequiredPropertyAsRead(jsonPropertyInfo); + } } else { @@ -211,6 +219,7 @@ internal sealed override bool OnTryRead(ref Utf8JsonReader reader, Type typeToCo } jsonTypeInfo.OnDeserialized?.Invoke(obj); + state.Current.ValidateAllRequiredPropertiesAreRead(jsonTypeInfo); // Unbox Debug.Assert(obj != null); @@ -272,6 +281,7 @@ private void ReadConstructorArguments(ref ReadStack state, ref Utf8JsonReader re continue; } + Debug.Assert(jsonParameterInfo.MatchingProperty != null); ReadAndCacheConstructorArgument(ref state, ref reader, jsonParameterInfo); state.Current.EndConstructorParameter(); @@ -532,6 +542,8 @@ private void BeginRead(ref ReadStack state, ref Utf8JsonReader reader, JsonSeria ThrowHelper.ThrowInvalidOperationException_ConstructorParameterIncompleteBinding(TypeToConvert); } + state.Current.InitializeRequiredPropertiesValidationState(jsonTypeInfo); + // Set current JsonPropertyInfo to null to avoid conflicts on push. state.Current.JsonPropertyInfo = null; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.MetadataHandling.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.MetadataHandling.cs index 15181a2c229fe4..a507effee9556e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.MetadataHandling.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.MetadataHandling.cs @@ -80,6 +80,16 @@ public partial class JsonConverter case PolymorphicSerializationState.None: Debug.Assert(!state.IsContinuation); + if (state.IsPolymorphicRootValue && state.CurrentDepth == 0) + { + Debug.Assert(jsonTypeInfo.PolymorphicTypeResolver != null); + + // We're serializing a root-level object value whose runtime type uses type hierarchies. + // For consistency with nested value handling, we want to serialize as-is without emitting metadata. + state.Current.PolymorphicSerializationState = PolymorphicSerializationState.PolymorphicReEntryNotFound; + break; + } + Type runtimeType = value.GetType(); if (jsonTypeInfo.PolymorphicTypeResolver is PolymorphicTypeResolver resolver) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.ReadCore.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.ReadCore.cs index 9c91ac3d7fced4..c327ada5fee8f8 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.ReadCore.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.ReadCore.cs @@ -28,7 +28,7 @@ public partial class JsonConverter { if (state.SupportContinuation) { - // If a Stream-based scenaio, return the actual value previously found; + // If a Stream-based scenario, return the actual value previously found; // this may or may not be the final pass through here. state.BytesConsumed += reader.BytesConsumed; if (state.Current.ReturnValue == null) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.WriteCore.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.WriteCore.cs index 98fbbcb45b1e4d..7b003325d4daef 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.WriteCore.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.WriteCore.cs @@ -13,14 +13,14 @@ internal sealed override bool WriteCoreAsObject( { if ( #if NETCOREAPP - // Short-circuit the check against "is not null"; treated as a constant by recent versions of the JIT. + // Treated as a constant by recent versions of the JIT. typeof(T).IsValueType) #else IsValueType) #endif { // Value types can never have a null except for Nullable. - if (value == null && Nullable.GetUnderlyingType(TypeToConvert) == null) + if (default(T) is not null && value is null) { ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonResumableConverterOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonResumableConverterOfT.cs index 69287a57279e31..de61e597c2a3f1 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonResumableConverterOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonResumableConverterOfT.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Text.Json.Serialization.Metadata; + namespace System.Text.Json.Serialization { /// @@ -20,7 +22,9 @@ internal abstract class JsonResumableConverter : JsonConverter // Bridge from resumable to value converters. ReadStack state = default; - state.Initialize(typeToConvert, options, supportContinuation: false); + JsonTypeInfo jsonTypeInfo = options.GetTypeInfoInternal(typeToConvert); + state.Initialize(jsonTypeInfo); + TryRead(ref reader, typeToConvert, options, ref state, out T? value); return value; } @@ -33,9 +37,10 @@ public sealed override void Write(Utf8JsonWriter writer, T value, JsonSerializer } // Bridge from resumable to value converters. - WriteStack state = default; - state.Initialize(typeof(T), options, supportContinuation: false, supportAsync: false); + JsonTypeInfo typeInfo = options.GetTypeInfoInternal(typeof(T)); + state.Initialize(typeInfo); + try { TryWrite(writer, value, options, ref state); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Helpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Helpers.cs index c682b282ae711f..0e5c16b05bb653 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Helpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Helpers.cs @@ -15,31 +15,42 @@ public static partial class JsonSerializer [RequiresUnreferencedCode(SerializationUnreferencedCodeMessage)] [RequiresDynamicCode(SerializationRequiresDynamicCodeMessage)] - private static JsonTypeInfo GetTypeInfo(JsonSerializerOptions? options, Type runtimeType) + private static JsonTypeInfo GetTypeInfo(JsonSerializerOptions? options, Type inputType) { - Debug.Assert(runtimeType != null); + Debug.Assert(inputType != null); options ??= JsonSerializerOptions.Default; - if (!options.IsImmutable || !DefaultJsonTypeInfoResolver.IsDefaultInstanceRooted) + if (!options.IsInitializedForReflectionSerializer) { options.InitializeForReflectionSerializer(); } - return options.GetTypeInfoForRootType(runtimeType); + // In order to improve performance of polymorphic root-level object serialization, + // we bypass GetTypeInfoForRootType and cache JsonTypeInfo in a dedicated property. + // This lets any derived types take advantage of the cache in GetTypeInfoForRootType themselves. + return inputType == JsonTypeInfo.ObjectType + ? options.ObjectTypeInfo + : options.GetTypeInfoForRootType(inputType); } - private static JsonTypeInfo GetTypeInfo(JsonSerializerContext context, Type type) + [RequiresUnreferencedCode(SerializationUnreferencedCodeMessage)] + [RequiresDynamicCode(SerializationRequiresDynamicCodeMessage)] + private static JsonTypeInfo GetTypeInfo(JsonSerializerOptions? options) + => (JsonTypeInfo)GetTypeInfo(options, typeof(T)); + + private static JsonTypeInfo GetTypeInfo(JsonSerializerContext context, Type inputType) { Debug.Assert(context != null); - Debug.Assert(type != null); + Debug.Assert(inputType != null); - JsonTypeInfo? info = context.GetTypeInfo(type); + JsonTypeInfo? info = context.GetTypeInfo(inputType); if (info is null) { - ThrowHelper.ThrowInvalidOperationException_NoMetadataForType(type, context); + ThrowHelper.ThrowInvalidOperationException_NoMetadataForType(inputType, context); } + info.EnsureConfigured(); return info; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Document.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Document.cs index f49d96e04c23d6..58dd06cf6b0dec 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Document.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Document.cs @@ -105,6 +105,7 @@ public static partial class JsonSerializer ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo)); } + jsonTypeInfo.EnsureConfigured(); return ReadDocument(document, jsonTypeInfo); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Element.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Element.cs index f9cd108c47dccf..debacec0ec8b3d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Element.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Element.cs @@ -85,6 +85,7 @@ public static partial class JsonSerializer ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo)); } + jsonTypeInfo.EnsureConfigured(); return ReadUsingMetadata(element, jsonTypeInfo); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandlePropertyName.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandlePropertyName.cs index 598d7157542b84..f374fc70daf79c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandlePropertyName.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandlePropertyName.cs @@ -139,7 +139,8 @@ internal static void CreateExtensionDataProperty( } extensionData = createObjectForExtensionDataProp(); - jsonPropertyInfo.SetExtensionDictionaryAsObject(obj, extensionData); + Debug.Assert(jsonPropertyInfo.Set != null); + jsonPropertyInfo.Set(obj, extensionData); } // We don't add the value to the dictionary here because we need to support the read-ahead functionality for Streams. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Helpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Helpers.cs index 6a157f9ba3f733..f3cb5b762fa59a 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Helpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Helpers.cs @@ -9,45 +9,45 @@ namespace System.Text.Json { public static partial class JsonSerializer { - private static TValue? ReadCore(JsonConverter jsonConverter, ref Utf8JsonReader reader, JsonSerializerOptions options, ref ReadStack state) + private static TValue? ReadCore(ref Utf8JsonReader reader, JsonTypeInfo jsonTypeInfo, ref ReadStack state) { - if (jsonConverter is JsonConverter converter) + if (jsonTypeInfo is JsonTypeInfo typedInfo) { // Call the strongly-typed ReadCore that will not box structs. - return converter.ReadCore(ref reader, options, ref state); + return typedInfo.EffectiveConverter.ReadCore(ref reader, typedInfo.Options, ref state); } - // The non-generic API was called or we have a polymorphic case where TValue is not equal to the T in JsonConverter. - object? value = jsonConverter.ReadCoreAsObject(ref reader, options, ref state); - Debug.Assert(value == null || value is TValue); + // The non-generic API was called. + object? value = jsonTypeInfo.Converter.ReadCoreAsObject(ref reader, jsonTypeInfo.Options, ref state); + Debug.Assert(value is null or TValue); return (TValue?)value; } private static TValue? ReadFromSpan(ReadOnlySpan utf8Json, JsonTypeInfo jsonTypeInfo, int? actualByteCount = null) { + Debug.Assert(jsonTypeInfo.IsConfigured); + JsonSerializerOptions options = jsonTypeInfo.Options; var readerState = new JsonReaderState(options.GetReaderOptions()); var reader = new Utf8JsonReader(utf8Json, isFinalBlock: true, readerState); ReadStack state = default; - jsonTypeInfo.EnsureConfigured(); state.Initialize(jsonTypeInfo); TValue? value; - JsonConverter jsonConverter = jsonTypeInfo.Converter; // For performance, the code below is a lifted ReadCore() above. - if (jsonConverter is JsonConverter converter) + if (jsonTypeInfo is JsonTypeInfo typedInfo) { // Call the strongly-typed ReadCore that will not box structs. - value = converter.ReadCore(ref reader, options, ref state); + value = typedInfo.EffectiveConverter.ReadCore(ref reader, options, ref state); } else { - // The non-generic API was called or we have a polymorphic case where TValue is not equal to the T in JsonConverter. - object? objValue = jsonConverter.ReadCoreAsObject(ref reader, options, ref state); - Debug.Assert(objValue == null || objValue is TValue); + // The non-generic API was called. + object? objValue = jsonTypeInfo.Converter.ReadCoreAsObject(ref reader, options, ref state); + Debug.Assert(objValue is null or TValue); value = (TValue?)objValue; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Node.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Node.cs index 08f770349dac80..21a367264f54bc 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Node.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Node.cs @@ -84,6 +84,7 @@ public static partial class JsonSerializer ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo)); } + jsonTypeInfo.EnsureConfigured(); return ReadNode(node, jsonTypeInfo); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Span.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Span.cs index 8708f4a92debd9..2e0f50c260957b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Span.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Span.cs @@ -88,6 +88,7 @@ public static partial class JsonSerializer ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo)); } + jsonTypeInfo.EnsureConfigured(); return ReadFromSpan(utf8Json, jsonTypeInfo); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Stream.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Stream.cs index ae344a1831d3a3..833b391752db77 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Stream.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Stream.cs @@ -7,6 +7,7 @@ using System.IO; using System.Runtime.CompilerServices; using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Converters; using System.Text.Json.Serialization.Metadata; using System.Threading; using System.Threading.Tasks; @@ -51,7 +52,7 @@ public static partial class JsonSerializer } JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, typeof(TValue)); - return ReadAllAsync(utf8Json, jsonTypeInfo, cancellationToken); + return ReadFromStreamAsync(utf8Json, jsonTypeInfo, cancellationToken); } /// @@ -85,7 +86,8 @@ public static partial class JsonSerializer ThrowHelper.ThrowArgumentNullException(nameof(utf8Json)); } - return ReadAllUsingOptions(utf8Json, typeof(TValue), options); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, typeof(TValue)); + return ReadFromStream(utf8Json, jsonTypeInfo); } /// @@ -129,7 +131,7 @@ public static partial class JsonSerializer } JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, returnType); - return ReadAllAsync(utf8Json, jsonTypeInfo, cancellationToken); + return ReadFromStreamAsync(utf8Json, jsonTypeInfo, cancellationToken); } /// @@ -168,7 +170,8 @@ public static partial class JsonSerializer ThrowHelper.ThrowArgumentNullException(nameof(returnType)); } - return ReadAllUsingOptions(utf8Json, returnType, options); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, returnType); + return ReadFromStream(utf8Json, jsonTypeInfo); } /// @@ -208,7 +211,8 @@ public static partial class JsonSerializer ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo)); } - return ReadAllAsync(utf8Json, jsonTypeInfo, cancellationToken); + jsonTypeInfo.EnsureConfigured(); + return ReadFromStreamAsync(utf8Json, jsonTypeInfo, cancellationToken); } /// @@ -244,7 +248,8 @@ public static partial class JsonSerializer ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo)); } - return ReadAll(utf8Json, jsonTypeInfo); + jsonTypeInfo.EnsureConfigured(); + return ReadFromStream(utf8Json, jsonTypeInfo); } /// @@ -293,7 +298,8 @@ public static partial class JsonSerializer ThrowHelper.ThrowArgumentNullException(nameof(context)); } - return ReadAllAsync(utf8Json, GetTypeInfo(context, returnType), cancellationToken); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(context, returnType); + return ReadFromStreamAsync(utf8Json, jsonTypeInfo, cancellationToken); } /// @@ -338,7 +344,8 @@ public static partial class JsonSerializer ThrowHelper.ThrowArgumentNullException(nameof(context)); } - return ReadAll(utf8Json, GetTypeInfo(context, returnType)); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(context, returnType); + return ReadFromStream(utf8Json, jsonTypeInfo); } /// @@ -403,7 +410,7 @@ public static partial class JsonSerializer private static JsonTypeInfo> CreateQueueTypeInfo(JsonTypeInfo jsonTypeInfo) { - return JsonMetadataServices.CreateQueueInfo, TValue>( + JsonTypeInfo> queueTypeInfo = JsonMetadataServices.CreateQueueInfo, TValue>( options: jsonTypeInfo.Options, collectionInfo: new() { @@ -411,6 +418,9 @@ private static JsonTypeInfo> CreateQueueTypeInfo(JsonTypeI ElementInfo = jsonTypeInfo, NumberHandling = jsonTypeInfo.Options.NumberHandling }); + + queueTypeInfo.EnsureConfigured(); + return queueTypeInfo; } private static async IAsyncEnumerable CreateAsyncEnumerableDeserializer( @@ -418,11 +428,16 @@ private static async IAsyncEnumerable CreateAsyncEnumerableDeserializer< JsonTypeInfo> queueTypeInfo, [EnumeratorCancellation] CancellationToken cancellationToken) { - queueTypeInfo.EnsureConfigured(); + Debug.Assert(queueTypeInfo.IsConfigured); JsonSerializerOptions options = queueTypeInfo.Options; var bufferState = new ReadBufferState(options.DefaultBufferSize); - ReadStack readStack = default; - readStack.Initialize(queueTypeInfo, supportContinuation: true); + ReadStack readStack = new ReadStack + { + SupportContinuation = true + }; + + readStack.Initialize(queueTypeInfo); + var jsonReaderState = new JsonReaderState(options.GetReaderOptions()); try @@ -434,8 +449,7 @@ private static async IAsyncEnumerable CreateAsyncEnumerableDeserializer< ref bufferState, ref jsonReaderState, ref readStack, - queueTypeInfo.Converter, - options); + queueTypeInfo); if (readStack.Current.ReturnValue is Queue queue) { @@ -453,17 +467,19 @@ private static async IAsyncEnumerable CreateAsyncEnumerableDeserializer< } } - internal static async ValueTask ReadAllAsync( + internal static async ValueTask ReadFromStreamAsync( Stream utf8Json, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken) { + Debug.Assert(jsonTypeInfo.IsConfigured); JsonSerializerOptions options = jsonTypeInfo.Options; var bufferState = new ReadBufferState(options.DefaultBufferSize); - ReadStack readStack = default; - jsonTypeInfo.EnsureConfigured(); - readStack.Initialize(jsonTypeInfo, supportContinuation: true); - JsonConverter converter = readStack.Current.JsonPropertyInfo!.EffectiveConverter; + ReadStack readStack = new ReadStack + { + SupportContinuation = true + }; + readStack.Initialize(jsonTypeInfo); var jsonReaderState = new JsonReaderState(options.GetReaderOptions()); try @@ -471,11 +487,11 @@ private static async IAsyncEnumerable CreateAsyncEnumerableDeserializer< while (true) { bufferState = await bufferState.ReadFromStreamAsync(utf8Json, cancellationToken).ConfigureAwait(false); - TValue value = ContinueDeserialize(ref bufferState, ref jsonReaderState, ref readStack, converter, options); + TValue? value = ContinueDeserialize(ref bufferState, ref jsonReaderState, ref readStack, jsonTypeInfo); if (bufferState.IsFinalBlock) { - return value!; + return value; } } } @@ -485,16 +501,18 @@ private static async IAsyncEnumerable CreateAsyncEnumerableDeserializer< } } - internal static TValue? ReadAll( + internal static TValue? ReadFromStream( Stream utf8Json, JsonTypeInfo jsonTypeInfo) { + Debug.Assert(jsonTypeInfo.IsConfigured); JsonSerializerOptions options = jsonTypeInfo.Options; var bufferState = new ReadBufferState(options.DefaultBufferSize); - ReadStack readStack = default; - jsonTypeInfo.EnsureConfigured(); - readStack.Initialize(jsonTypeInfo, supportContinuation: true); - JsonConverter converter = readStack.Current.JsonPropertyInfo!.EffectiveConverter; + ReadStack readStack = new ReadStack + { + SupportContinuation = true + }; + readStack.Initialize(jsonTypeInfo); var jsonReaderState = new JsonReaderState(options.GetReaderOptions()); try @@ -502,11 +520,11 @@ private static async IAsyncEnumerable CreateAsyncEnumerableDeserializer< while (true) { bufferState.ReadFromStream(utf8Json); - TValue value = ContinueDeserialize(ref bufferState, ref jsonReaderState, ref readStack, converter, options); + TValue? value = ContinueDeserialize(ref bufferState, ref jsonReaderState, ref readStack, jsonTypeInfo); if (bufferState.IsFinalBlock) { - return value!; + return value; } } } @@ -516,59 +534,26 @@ private static async IAsyncEnumerable CreateAsyncEnumerableDeserializer< } } - internal static TValue ContinueDeserialize( + internal static TValue? ContinueDeserialize( ref ReadBufferState bufferState, ref JsonReaderState jsonReaderState, ref ReadStack readStack, - JsonConverter converter, - JsonSerializerOptions options) - { - // Process the data available - TValue value = ReadCore( - ref jsonReaderState, - bufferState.IsFinalBlock, - bufferState.Bytes, - options, - ref readStack, - converter); - - Debug.Assert(readStack.BytesConsumed <= bufferState.Bytes.Length); - bufferState.AdvanceBuffer((int)readStack.BytesConsumed); - - return value; - } - - [RequiresUnreferencedCode(SerializationUnreferencedCodeMessage)] - [RequiresDynamicCode(SerializationRequiresDynamicCodeMessage)] - private static TValue? ReadAllUsingOptions( - Stream utf8Json, - Type returnType, - JsonSerializerOptions? options) - { - JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, returnType); - return ReadAll(utf8Json, jsonTypeInfo); - } - - private static TValue ReadCore( - ref JsonReaderState readerState, - bool isFinalBlock, - ReadOnlySpan buffer, - JsonSerializerOptions options, - ref ReadStack state, - JsonConverter converterBase) + JsonTypeInfo jsonTypeInfo) { - var reader = new Utf8JsonReader(buffer, isFinalBlock, readerState); + var reader = new Utf8JsonReader(bufferState.Bytes, bufferState.IsFinalBlock, jsonReaderState); // If we haven't read in the entire stream's payload we'll need to signify that we want // to enable read ahead behaviors to ensure we have complete json objects and arrays // ({}, []) when needed. (Notably to successfully parse JsonElement via JsonDocument // to assign to object and JsonElement properties in the constructed .NET object.) - state.ReadAhead = !isFinalBlock; - state.BytesConsumed = 0; + readStack.ReadAhead = !bufferState.IsFinalBlock; + readStack.BytesConsumed = 0; - TValue? value = ReadCore(converterBase, ref reader, options, ref state); - readerState = reader.CurrentState; - return value!; + TValue? value = ReadCore(ref reader, jsonTypeInfo, ref readStack); + Debug.Assert(readStack.BytesConsumed <= bufferState.Bytes.Length); + bufferState.AdvanceBuffer((int)readStack.BytesConsumed); + jsonReaderState = reader.CurrentState; + return value; } } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs index e9bb1f1069d41a..1a307f31936c09 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Buffers; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; @@ -216,6 +217,7 @@ public static partial class JsonSerializer ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo)); } + jsonTypeInfo.EnsureConfigured(); return ReadFromSpan(json.AsSpan(), jsonTypeInfo); } @@ -257,6 +259,7 @@ public static partial class JsonSerializer ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo)); } + jsonTypeInfo.EnsureConfigured(); return ReadFromSpan(json, jsonTypeInfo); } @@ -366,7 +369,7 @@ public static partial class JsonSerializer private static TValue? ReadFromSpan(ReadOnlySpan json, JsonTypeInfo jsonTypeInfo) { - jsonTypeInfo.EnsureConfigured(); + Debug.Assert(jsonTypeInfo.IsConfigured); byte[]? tempArray = null; // For performance, avoid obtaining actual byte count unless memory usage is higher than the threshold. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Utf8JsonReader.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Utf8JsonReader.cs index 5fb3adb99ba6bf..b29d7d562b02ba 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Utf8JsonReader.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Utf8JsonReader.cs @@ -170,6 +170,7 @@ public static partial class JsonSerializer ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo)); } + jsonTypeInfo.EnsureConfigured(); return Read(ref reader, jsonTypeInfo); } @@ -238,8 +239,8 @@ public static partial class JsonSerializer private static TValue? Read(ref Utf8JsonReader reader, JsonTypeInfo jsonTypeInfo) { + Debug.Assert(jsonTypeInfo.IsConfigured); ReadStack state = default; - jsonTypeInfo.EnsureConfigured(); state.Initialize(jsonTypeInfo); JsonReaderState readerState = reader.CurrentState; @@ -422,8 +423,7 @@ public static partial class JsonSerializer var newReader = new Utf8JsonReader(rentedSpan, originalReaderOptions); - JsonConverter jsonConverter = state.Current.JsonPropertyInfo!.EffectiveConverter; - TValue? value = ReadCore(jsonConverter, ref newReader, jsonTypeInfo.Options, ref state); + TValue? value = ReadCore(ref newReader, jsonTypeInfo, ref state); // The reader should have thrown if we have remaining bytes. Debug.Assert(newReader.BytesConsumed == length); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.ByteArray.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.ByteArray.cs index dda1088e7acf99..49aa791c8dde90 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.ByteArray.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.ByteArray.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; @@ -25,9 +26,8 @@ public static byte[] SerializeToUtf8Bytes( TValue value, JsonSerializerOptions? options = null) { - Type runtimeType = GetRuntimeType(value); - JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, runtimeType); - return WriteBytesUsingSerializer(value, jsonTypeInfo); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(options); + return WriteBytes(value, jsonTypeInfo); } /// @@ -54,9 +54,9 @@ public static byte[] SerializeToUtf8Bytes( Type inputType, JsonSerializerOptions? options = null) { - Type runtimeType = GetRuntimeTypeAndValidateInputType(value, inputType); - JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, runtimeType); - return WriteBytesUsingSerializer(value, jsonTypeInfo); + ValidateInputType(value, inputType); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, inputType); + return WriteBytesAsObject(value, jsonTypeInfo); } /// @@ -79,7 +79,8 @@ public static byte[] SerializeToUtf8Bytes(TValue value, JsonTypeInfo @@ -110,34 +111,33 @@ public static byte[] SerializeToUtf8Bytes(object? value, Type inputType, JsonSer ThrowHelper.ThrowArgumentNullException(nameof(context)); } - Type runtimeType = GetRuntimeTypeAndValidateInputType(value, inputType); - JsonTypeInfo jsonTypeInfo = GetTypeInfo(context, runtimeType); - return WriteBytesUsingGeneratedSerializer(value!, jsonTypeInfo); + ValidateInputType(value, inputType); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(context, inputType); + return WriteBytesAsObject(value, jsonTypeInfo); } - private static byte[] WriteBytesUsingGeneratedSerializer(in TValue value, JsonTypeInfo jsonTypeInfo) + private static byte[] WriteBytes(in TValue value, JsonTypeInfo jsonTypeInfo) { + Debug.Assert(jsonTypeInfo.IsConfigured); + JsonSerializerOptions options = jsonTypeInfo.Options; using var output = new PooledByteBufferWriter(options.DefaultBufferSize); - using (var writer = new Utf8JsonWriter(output, options.GetWriterOptions())) - { - WriteUsingGeneratedSerializer(writer, value, jsonTypeInfo); - } + using var writer = new Utf8JsonWriter(output, options.GetWriterOptions()); + WriteCore(writer, value, jsonTypeInfo); return output.WrittenMemory.ToArray(); } - private static byte[] WriteBytesUsingSerializer(in TValue value, JsonTypeInfo jsonTypeInfo) + private static byte[] WriteBytesAsObject(object? value, JsonTypeInfo jsonTypeInfo) { + Debug.Assert(jsonTypeInfo.IsConfigured); + JsonSerializerOptions options = jsonTypeInfo.Options; using var output = new PooledByteBufferWriter(options.DefaultBufferSize); - using (var writer = new Utf8JsonWriter(output, options.GetWriterOptions())) - { - WriteUsingSerializer(writer, value, jsonTypeInfo); - } - + using var writer = new Utf8JsonWriter(output, options.GetWriterOptions()); + WriteCoreAsObject(writer, value, jsonTypeInfo); return output.WrittenMemory.ToArray(); } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Document.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Document.cs index 731dd0b46cb4a0..13ff63a2bc5369 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Document.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Document.cs @@ -25,9 +25,8 @@ public static partial class JsonSerializer [RequiresDynamicCode(SerializationRequiresDynamicCodeMessage)] public static JsonDocument SerializeToDocument(TValue value, JsonSerializerOptions? options = null) { - Type runtimeType = GetRuntimeType(value); - JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, runtimeType); - return WriteDocumentUsingSerializer(value, jsonTypeInfo); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(options); + return WriteDocument(value, jsonTypeInfo); } /// @@ -51,9 +50,9 @@ public static JsonDocument SerializeToDocument(TValue value, JsonSeriali [RequiresDynamicCode(SerializationRequiresDynamicCodeMessage)] public static JsonDocument SerializeToDocument(object? value, Type inputType, JsonSerializerOptions? options = null) { - Type runtimeType = GetRuntimeTypeAndValidateInputType(value, inputType); - JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, runtimeType); - return WriteDocumentUsingSerializer(value, jsonTypeInfo); + ValidateInputType(value, inputType); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, inputType); + return WriteDocumentAsObject(value, jsonTypeInfo); } /// @@ -77,7 +76,8 @@ public static JsonDocument SerializeToDocument(TValue value, JsonTypeInf ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo)); } - return WriteDocumentUsingGeneratedSerializer(value, jsonTypeInfo); + jsonTypeInfo.EnsureConfigured(); + return WriteDocument(value, jsonTypeInfo); } /// @@ -105,39 +105,35 @@ public static JsonDocument SerializeToDocument(object? value, Type inputType, Js ThrowHelper.ThrowArgumentNullException(nameof(context)); } - Type runtimeType = GetRuntimeTypeAndValidateInputType(value, inputType); - return WriteDocumentUsingGeneratedSerializer(value, GetTypeInfo(context, runtimeType)); + ValidateInputType(value, inputType); + return WriteDocumentAsObject(value, GetTypeInfo(context, inputType)); } - private static JsonDocument WriteDocumentUsingGeneratedSerializer(in TValue value, JsonTypeInfo jsonTypeInfo) + private static JsonDocument WriteDocument(in TValue value, JsonTypeInfo jsonTypeInfo) { + Debug.Assert(jsonTypeInfo.IsConfigured); JsonSerializerOptions options = jsonTypeInfo.Options; - Debug.Assert(options != null); // For performance, share the same buffer across serialization and deserialization. // The PooledByteBufferWriter is cleared and returned when JsonDocument.Dispose() is called. PooledByteBufferWriter output = new(options.DefaultBufferSize); - using (Utf8JsonWriter writer = new(output, options.GetWriterOptions())) - { - WriteUsingGeneratedSerializer(writer, value, jsonTypeInfo); - } + using Utf8JsonWriter writer = new(output, options.GetWriterOptions()); + WriteCore(writer, value, jsonTypeInfo); return JsonDocument.ParseRented(output, options.GetDocumentOptions()); } - private static JsonDocument WriteDocumentUsingSerializer(in TValue value, JsonTypeInfo jsonTypeInfo) + private static JsonDocument WriteDocumentAsObject(object? value, JsonTypeInfo jsonTypeInfo) { + Debug.Assert(jsonTypeInfo.IsConfigured); JsonSerializerOptions options = jsonTypeInfo.Options; - Debug.Assert(options != null); // For performance, share the same buffer across serialization and deserialization. // The PooledByteBufferWriter is cleared and returned when JsonDocument.Dispose() is called. PooledByteBufferWriter output = new(options.DefaultBufferSize); - using (Utf8JsonWriter writer = new(output, options.GetWriterOptions())) - { - WriteUsingSerializer(writer, value, jsonTypeInfo); - } + using Utf8JsonWriter writer = new(output, options.GetWriterOptions()); + WriteCoreAsObject(writer, value, jsonTypeInfo); return JsonDocument.ParseRented(output, options.GetDocumentOptions()); } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Element.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Element.cs index 3343f544a1c11f..ba35d4c4f91156 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Element.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Element.cs @@ -25,9 +25,8 @@ public static partial class JsonSerializer [RequiresDynamicCode(SerializationRequiresDynamicCodeMessage)] public static JsonElement SerializeToElement(TValue value, JsonSerializerOptions? options = null) { - Type runtimeType = GetRuntimeType(value); - JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, runtimeType); - return WriteElementUsingSerializer(value, jsonTypeInfo); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(options); + return WriteElement(value, jsonTypeInfo); } /// @@ -51,9 +50,9 @@ public static JsonElement SerializeToElement(TValue value, JsonSerialize [RequiresDynamicCode(SerializationRequiresDynamicCodeMessage)] public static JsonElement SerializeToElement(object? value, Type inputType, JsonSerializerOptions? options = null) { - Type runtimeType = GetRuntimeTypeAndValidateInputType(value, inputType); - JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, runtimeType); - return WriteElementUsingSerializer(value, jsonTypeInfo); + ValidateInputType(value, inputType); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, inputType); + return WriteElementAsObject(value, jsonTypeInfo); } /// @@ -77,7 +76,8 @@ public static JsonElement SerializeToElement(TValue value, JsonTypeInfo< ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo)); } - return WriteElementUsingGeneratedSerializer(value, jsonTypeInfo); + jsonTypeInfo.EnsureConfigured(); + return WriteElement(value, jsonTypeInfo); } /// @@ -105,38 +105,34 @@ public static JsonElement SerializeToElement(object? value, Type inputType, Json ThrowHelper.ThrowArgumentNullException(nameof(context)); } - Type type = GetRuntimeTypeAndValidateInputType(value, inputType); - JsonTypeInfo typeInfo = GetTypeInfo(context, type); - return WriteElementUsingGeneratedSerializer(value, typeInfo); + ValidateInputType(value, inputType); + JsonTypeInfo typeInfo = GetTypeInfo(context, inputType); + return WriteElementAsObject(value, typeInfo); } - private static JsonElement WriteElementUsingGeneratedSerializer(in TValue value, JsonTypeInfo jsonTypeInfo) + private static JsonElement WriteElement(in TValue value, JsonTypeInfo jsonTypeInfo) { + Debug.Assert(jsonTypeInfo.IsConfigured); JsonSerializerOptions options = jsonTypeInfo.Options; - Debug.Assert(options != null); // For performance, share the same buffer across serialization and deserialization. using var output = new PooledByteBufferWriter(options.DefaultBufferSize); - using (var writer = new Utf8JsonWriter(output, options.GetWriterOptions())) - { - WriteUsingGeneratedSerializer(writer, value, jsonTypeInfo); - } + using var writer = new Utf8JsonWriter(output, options.GetWriterOptions()); + WriteCore(writer, value, jsonTypeInfo); return JsonElement.ParseValue(output.WrittenMemory.Span, options.GetDocumentOptions()); } - private static JsonElement WriteElementUsingSerializer(in TValue value, JsonTypeInfo jsonTypeInfo) + private static JsonElement WriteElementAsObject(object? value, JsonTypeInfo jsonTypeInfo) { JsonSerializerOptions options = jsonTypeInfo.Options; Debug.Assert(options != null); // For performance, share the same buffer across serialization and deserialization. using var output = new PooledByteBufferWriter(options.DefaultBufferSize); - using (var writer = new Utf8JsonWriter(output, options.GetWriterOptions())) - { - WriteUsingSerializer(writer, value, jsonTypeInfo); - } + using var writer = new Utf8JsonWriter(output, options.GetWriterOptions()); + WriteCoreAsObject(writer, value, jsonTypeInfo); return JsonElement.ParseValue(output.WrittenMemory.Span, options.GetDocumentOptions()); } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs index d80d5fbc34ef29..1f688d480fabd1 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs @@ -2,98 +2,112 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Converters; using System.Text.Json.Serialization.Metadata; namespace System.Text.Json { public static partial class JsonSerializer { - private static bool WriteCore( - JsonConverter jsonConverter, + /// + /// Sync, strongly typed root value serialization helper. + /// + private static void WriteCore( Utf8JsonWriter writer, in TValue value, - JsonSerializerOptions options, - ref WriteStack state) + JsonTypeInfo jsonTypeInfo) { - Debug.Assert(writer != null); + if (jsonTypeInfo.CanUseSerializeHandler) + { + // Short-circuit calls into SerializeHandler, if supported. + // Even though this is already handled by JsonMetadataServicesConverter, + // we avoid instantiating a WriteStack and a couple of additional virtual calls. - bool success; + Debug.Assert(jsonTypeInfo.SerializeHandler != null); + Debug.Assert(jsonTypeInfo.Options.SerializerContext?.CanUseSerializationLogic == true); + Debug.Assert(jsonTypeInfo.Converter is JsonMetadataServicesConverter); - if (jsonConverter is JsonConverter converter) - { - // Call the strongly-typed WriteCore that will not box structs. - success = converter.WriteCore(writer, value, options, ref state); + jsonTypeInfo.SerializeHandler(writer, value); } else { - // The non-generic API was called or we have a polymorphic case where TValue is not equal to the T in JsonConverter. - success = jsonConverter.WriteCoreAsObject(writer, value, options, ref state); + WriteStack state = default; + JsonTypeInfo polymorphicTypeInfo = ResolvePolymorphicTypeInfo(value, jsonTypeInfo, out state.IsPolymorphicRootValue); + state.Initialize(polymorphicTypeInfo); + + bool success = + state.IsPolymorphicRootValue + ? polymorphicTypeInfo.Converter.WriteCoreAsObject(writer, value, jsonTypeInfo.Options, ref state) + : jsonTypeInfo.EffectiveConverter.WriteCore(writer, value, jsonTypeInfo.Options, ref state); + + Debug.Assert(success); } writer.Flush(); - return success; } - private static void WriteUsingGeneratedSerializer(Utf8JsonWriter writer, in TValue value, JsonTypeInfo jsonTypeInfo) + /// + /// Sync, untyped root value serialization helper. + /// + private static void WriteCoreAsObject( + Utf8JsonWriter writer, + object? value, + JsonTypeInfo jsonTypeInfo) { - Debug.Assert(writer != null); + WriteStack state = default; + JsonTypeInfo polymorphicTypeInfo = ResolvePolymorphicTypeInfo(value, jsonTypeInfo, out state.IsPolymorphicRootValue); + state.Initialize(polymorphicTypeInfo); - if (jsonTypeInfo.HasSerializeHandler && - jsonTypeInfo is JsonTypeInfo typedInfo && - typedInfo.Options.SerializerContext?.CanUseSerializationLogic == true) - { - Debug.Assert(typedInfo.SerializeHandler != null); - typedInfo.SerializeHandler(writer, value); - writer.Flush(); - } - else - { - WriteUsingSerializer(writer, value, jsonTypeInfo); - } + bool success = polymorphicTypeInfo.Converter.WriteCoreAsObject(writer, value, jsonTypeInfo.Options, ref state); + Debug.Assert(success); + writer.Flush(); } - private static void WriteUsingSerializer(Utf8JsonWriter writer, in TValue value, JsonTypeInfo jsonTypeInfo) + /// + /// Streaming root-level serialization helper. + /// + private static bool WriteCore(Utf8JsonWriter writer, in TValue value, JsonTypeInfo jsonTypeInfo, ref WriteStack state) { - Debug.Assert(writer != null); + Debug.Assert(state.SupportContinuation); - // TODO unify method with WriteUsingGeneratedSerializer - - WriteStack state = default; - jsonTypeInfo.EnsureConfigured(); - state.Initialize(jsonTypeInfo, supportContinuation: false, supportAsync: false); - - JsonConverter converter = jsonTypeInfo.Converter; - Debug.Assert(converter != null); - Debug.Assert(jsonTypeInfo.Options != null); - - // For performance, the code below is a lifted WriteCore() above. - if (converter is JsonConverter typedConverter) + bool isFinalBlock; + if (jsonTypeInfo is JsonTypeInfo typedInfo) { - // Call the strongly-typed WriteCore that will not box structs. - typedConverter.WriteCore(writer, value, jsonTypeInfo.Options, ref state); + isFinalBlock = typedInfo.EffectiveConverter.WriteCore(writer, value, jsonTypeInfo.Options, ref state); } else { - // The non-generic API was called or we have a polymorphic case where TValue is not equal to the T in JsonConverter. - converter.WriteCoreAsObject(writer, value, jsonTypeInfo.Options, ref state); + // The non-generic API was called. + isFinalBlock = jsonTypeInfo.Converter.WriteCoreAsObject(writer, value, jsonTypeInfo.Options, ref state); } writer.Flush(); + return isFinalBlock; } - private static Type GetRuntimeType(in TValue value) + private static JsonTypeInfo ResolvePolymorphicTypeInfo(in TValue value, JsonTypeInfo jsonTypeInfo, out bool isPolymorphicType) { - Type type = typeof(TValue); - if (type == JsonTypeInfo.ObjectType && value is not null) + if ( +#if NETCOREAPP + !typeof(TValue).IsValueType && +#endif + jsonTypeInfo.Converter.CanBePolymorphic && value is not null) { - type = value.GetType(); + Debug.Assert(typeof(TValue) == typeof(object)); + + Type runtimeType = value.GetType(); + if (runtimeType != jsonTypeInfo.Type) + { + isPolymorphicType = true; + return jsonTypeInfo.Options.GetTypeInfoForRootType(runtimeType); + } } - return type; + isPolymorphicType = false; + return jsonTypeInfo; } - private static Type GetRuntimeTypeAndValidateInputType(object? value, Type inputType) + private static void ValidateInputType(object? value, Type inputType) { if (inputType is null) { @@ -107,14 +121,7 @@ private static Type GetRuntimeTypeAndValidateInputType(object? value, Type input { ThrowHelper.ThrowArgumentException_DeserializeWrongType(inputType, value); } - - if (inputType == JsonTypeInfo.ObjectType) - { - return runtimeType; - } } - - return inputType; } } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Node.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Node.cs index 5f24f4f600a0c3..379b80409a53c1 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Node.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Node.cs @@ -26,9 +26,8 @@ public static partial class JsonSerializer [RequiresDynamicCode(SerializationRequiresDynamicCodeMessage)] public static JsonNode? SerializeToNode(TValue value, JsonSerializerOptions? options = null) { - Type runtimeType = GetRuntimeType(value); - JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, runtimeType); - return WriteNodeUsingSerializer(value, jsonTypeInfo); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(options); + return WriteNode(value, jsonTypeInfo); } /// @@ -52,9 +51,9 @@ public static partial class JsonSerializer [RequiresDynamicCode(SerializationRequiresDynamicCodeMessage)] public static JsonNode? SerializeToNode(object? value, Type inputType, JsonSerializerOptions? options = null) { - Type runtimeType = GetRuntimeTypeAndValidateInputType(value, inputType); - JsonTypeInfo typeInfo = GetTypeInfo(options, runtimeType); - return WriteNodeUsingSerializer(value, typeInfo); + ValidateInputType(value, inputType); + JsonTypeInfo typeInfo = GetTypeInfo(options, inputType); + return WriteNodeAsObject(value, typeInfo); } /// @@ -78,7 +77,8 @@ public static partial class JsonSerializer ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo)); } - return WriteNodeUsingGeneratedSerializer(value, jsonTypeInfo); + jsonTypeInfo.EnsureConfigured(); + return WriteNode(value, jsonTypeInfo); } /// @@ -106,38 +106,34 @@ public static partial class JsonSerializer ThrowHelper.ThrowArgumentNullException(nameof(context)); } - Type runtimeType = GetRuntimeTypeAndValidateInputType(value, inputType); - JsonTypeInfo jsonTypeInfo = GetTypeInfo(context, runtimeType); - return WriteNodeUsingGeneratedSerializer(value, jsonTypeInfo); + ValidateInputType(value, inputType); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(context, inputType); + return WriteNodeAsObject(value, jsonTypeInfo); } - private static JsonNode? WriteNodeUsingGeneratedSerializer(in TValue value, JsonTypeInfo jsonTypeInfo) + private static JsonNode? WriteNode(in TValue value, JsonTypeInfo jsonTypeInfo) { + Debug.Assert(jsonTypeInfo.IsConfigured); JsonSerializerOptions options = jsonTypeInfo.Options; - Debug.Assert(options != null); // For performance, share the same buffer across serialization and deserialization. using var output = new PooledByteBufferWriter(options.DefaultBufferSize); - using (var writer = new Utf8JsonWriter(output, options.GetWriterOptions())) - { - WriteUsingGeneratedSerializer(writer, value, jsonTypeInfo); - } + using var writer = new Utf8JsonWriter(output, options.GetWriterOptions()); + WriteCore(writer, value, jsonTypeInfo); return JsonNode.Parse(output.WrittenMemory.Span, options.GetNodeOptions(), options.GetDocumentOptions()); } - private static JsonNode? WriteNodeUsingSerializer(in TValue value, JsonTypeInfo jsonTypeInfo) + private static JsonNode? WriteNodeAsObject(object? value, JsonTypeInfo jsonTypeInfo) { + Debug.Assert(jsonTypeInfo.IsConfigured); JsonSerializerOptions options = jsonTypeInfo.Options; - Debug.Assert(options != null); // For performance, share the same buffer across serialization and deserialization. using var output = new PooledByteBufferWriter(options.DefaultBufferSize); - using (var writer = new Utf8JsonWriter(output, options.GetWriterOptions())) - { - WriteUsingSerializer(writer, value, jsonTypeInfo); - } + using var writer = new Utf8JsonWriter(output, options.GetWriterOptions()); + WriteCoreAsObject(writer, value, jsonTypeInfo); return JsonNode.Parse(output.WrittenMemory.Span, options.GetNodeOptions(), options.GetDocumentOptions()); } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Stream.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Stream.cs index 9fb7c5c8394218..d6c4734bfc5d02 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Stream.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Stream.cs @@ -50,9 +50,8 @@ public static Task SerializeAsync( ThrowHelper.ThrowArgumentNullException(nameof(utf8Json)); } - Type runtimeType = GetRuntimeType(value); - JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, runtimeType); - return WriteStreamAsync(utf8Json, value!, jsonTypeInfo, cancellationToken); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, typeof(TValue)); + return WriteStreamAsync(utf8Json, value, jsonTypeInfo, cancellationToken); } /// @@ -81,9 +80,8 @@ public static void Serialize( ThrowHelper.ThrowArgumentNullException(nameof(utf8Json)); } - Type runtimeType = GetRuntimeType(value); - JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, runtimeType); - WriteStream(utf8Json, value!, jsonTypeInfo); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, typeof(TValue)); + WriteStream(utf8Json, value, jsonTypeInfo); } /// @@ -119,9 +117,9 @@ public static Task SerializeAsync( ThrowHelper.ThrowArgumentNullException(nameof(utf8Json)); } - Type runtimeType = GetRuntimeTypeAndValidateInputType(value, inputType); - JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, runtimeType); - return WriteStreamAsync(utf8Json, value!, jsonTypeInfo, cancellationToken); + ValidateInputType(value, inputType); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, inputType); + return WriteStreamAsync(utf8Json, value, jsonTypeInfo, cancellationToken); } /// @@ -154,9 +152,9 @@ public static void Serialize( ThrowHelper.ThrowArgumentNullException(nameof(utf8Json)); } - Type runtimeType = GetRuntimeTypeAndValidateInputType(value, inputType); - JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, runtimeType); - WriteStream(utf8Json, value!, jsonTypeInfo); + ValidateInputType(value, inputType); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, inputType); + WriteStream(utf8Json, value, jsonTypeInfo); } /// @@ -259,11 +257,11 @@ public static Task SerializeAsync( ThrowHelper.ThrowArgumentNullException(nameof(context)); } - Type runtimeType = GetRuntimeTypeAndValidateInputType(value, inputType); + ValidateInputType(value, inputType); return WriteStreamAsync( utf8Json, - value!, - GetTypeInfo(context, runtimeType), + value, + GetTypeInfo(context, inputType), cancellationToken); } @@ -299,8 +297,8 @@ public static void Serialize( ThrowHelper.ThrowArgumentNullException(nameof(context)); } - Type runtimeType = GetRuntimeTypeAndValidateInputType(value, inputType); - WriteStream(utf8Json, value!, GetTypeInfo(context, runtimeType)); + ValidateInputType(value, inputType); + WriteStream(utf8Json, value, GetTypeInfo(context, inputType)); } private static async Task WriteStreamAsync( @@ -309,15 +307,22 @@ private static async Task WriteStreamAsync( JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken) { + jsonTypeInfo.EnsureConfigured(); JsonSerializerOptions options = jsonTypeInfo.Options; JsonWriterOptions writerOptions = options.GetWriterOptions(); using (var bufferWriter = new PooledByteBufferWriter(options.DefaultBufferSize)) using (var writer = new Utf8JsonWriter(bufferWriter, writerOptions)) { - WriteStack state = new WriteStack { CancellationToken = cancellationToken }; - jsonTypeInfo.EnsureConfigured(); - JsonConverter converter = state.Initialize(jsonTypeInfo, supportContinuation: true, supportAsync: true); + WriteStack state = new WriteStack + { + CancellationToken = cancellationToken, + SupportContinuation = true, + SupportAsync = true, + }; + + jsonTypeInfo = ResolvePolymorphicTypeInfo(value, jsonTypeInfo, out state.IsPolymorphicRootValue); + state.Initialize(jsonTypeInfo); bool isFinalBlock; @@ -329,7 +334,7 @@ private static async Task WriteStreamAsync( try { - isFinalBlock = WriteCore(converter, writer, value, options, ref state); + isFinalBlock = WriteCore(writer, value, jsonTypeInfo, ref state); if (state.SuppressFlush) { @@ -383,15 +388,20 @@ private static void WriteStream( in TValue value, JsonTypeInfo jsonTypeInfo) { + jsonTypeInfo.EnsureConfigured(); JsonSerializerOptions options = jsonTypeInfo.Options; JsonWriterOptions writerOptions = options.GetWriterOptions(); using (var bufferWriter = new PooledByteBufferWriter(options.DefaultBufferSize)) using (var writer = new Utf8JsonWriter(bufferWriter, writerOptions)) { - WriteStack state = default; - jsonTypeInfo.EnsureConfigured(); - JsonConverter converter = state.Initialize(jsonTypeInfo, supportContinuation: true, supportAsync: false); + WriteStack state = new WriteStack + { + SupportContinuation = true + }; + + jsonTypeInfo = ResolvePolymorphicTypeInfo(value, jsonTypeInfo, out state.IsPolymorphicRootValue); + state.Initialize(jsonTypeInfo); bool isFinalBlock; @@ -399,7 +409,7 @@ private static void WriteStream( { state.FlushThreshold = (int)(bufferWriter.Capacity * FlushThreshold); - isFinalBlock = WriteCore(converter, writer, value, options, ref state); + isFinalBlock = WriteCore(writer, value, jsonTypeInfo, ref state); bufferWriter.WriteToStream(utf8Json); bufferWriter.Clear(); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.String.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.String.cs index 674a3063956c70..451565a3d13ce2 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.String.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.String.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; @@ -28,9 +29,8 @@ public static partial class JsonSerializer [RequiresDynamicCode(SerializationRequiresDynamicCodeMessage)] public static string Serialize(TValue value, JsonSerializerOptions? options = null) { - Type runtimeType = GetRuntimeType(value); - JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, runtimeType); - return WriteStringUsingSerializer(value, jsonTypeInfo); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(options); + return WriteString(value, jsonTypeInfo); } /// @@ -61,9 +61,9 @@ public static string Serialize( Type inputType, JsonSerializerOptions? options = null) { - Type runtimeType = GetRuntimeTypeAndValidateInputType(value, inputType); - JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, runtimeType); - return WriteStringUsingSerializer(value, jsonTypeInfo); + ValidateInputType(value, inputType); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, inputType); + return WriteStringAsObject(value, jsonTypeInfo); } /// @@ -86,7 +86,13 @@ public static string Serialize( /// public static string Serialize(TValue value, JsonTypeInfo jsonTypeInfo) { - return WriteStringUsingGeneratedSerializer(value, jsonTypeInfo); + if (jsonTypeInfo is null) + { + ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo)); + } + + jsonTypeInfo.EnsureConfigured(); + return WriteString(value, jsonTypeInfo); } /// @@ -118,49 +124,35 @@ public static string Serialize(object? value, Type inputType, JsonSerializerCont ThrowHelper.ThrowArgumentNullException(nameof(context)); } - Type type = GetRuntimeTypeAndValidateInputType(value, inputType); - JsonTypeInfo jsonTypeInfo = GetTypeInfo(context, type); - return WriteStringUsingGeneratedSerializer(value, jsonTypeInfo); + ValidateInputType(value, inputType); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(context, inputType); + return WriteStringAsObject(value, jsonTypeInfo); } - private static string WriteStringUsingGeneratedSerializer(in TValue value, JsonTypeInfo jsonTypeInfo) + private static string WriteString(in TValue value, JsonTypeInfo jsonTypeInfo) { - if (jsonTypeInfo is null) - { - ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo)); - } + Debug.Assert(jsonTypeInfo.IsConfigured); JsonSerializerOptions options = jsonTypeInfo.Options; - using (var output = new PooledByteBufferWriter(options.DefaultBufferSize)) - { - using (var writer = new Utf8JsonWriter(output, options.GetWriterOptions())) - { - WriteUsingGeneratedSerializer(writer, value, jsonTypeInfo); - } + using var output = new PooledByteBufferWriter(options.DefaultBufferSize); + using var writer = new Utf8JsonWriter(output, options.GetWriterOptions()); - return JsonReaderHelper.TranscodeHelper(output.WrittenMemory.Span); - } + WriteCore(writer, value, jsonTypeInfo); + return JsonReaderHelper.TranscodeHelper(output.WrittenMemory.Span); } - private static string WriteStringUsingSerializer(in TValue value, JsonTypeInfo jsonTypeInfo) + private static string WriteStringAsObject(object? value, JsonTypeInfo jsonTypeInfo) { - if (jsonTypeInfo is null) - { - ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo)); - } + Debug.Assert(jsonTypeInfo.IsConfigured); JsonSerializerOptions options = jsonTypeInfo.Options; - using (var output = new PooledByteBufferWriter(options.DefaultBufferSize)) - { - using (var writer = new Utf8JsonWriter(output, options.GetWriterOptions())) - { - WriteUsingSerializer(writer, value, jsonTypeInfo); - } + using var output = new PooledByteBufferWriter(options.DefaultBufferSize); + using var writer = new Utf8JsonWriter(output, options.GetWriterOptions()); - return JsonReaderHelper.TranscodeHelper(output.WrittenMemory.Span); - } + WriteCoreAsObject(writer, value, jsonTypeInfo); + return JsonReaderHelper.TranscodeHelper(output.WrittenMemory.Span); } } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Utf8JsonWriter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Utf8JsonWriter.cs index 7f27dcdd50a2eb..20ffe8d767529c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Utf8JsonWriter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Utf8JsonWriter.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; @@ -35,9 +36,8 @@ public static void Serialize( ThrowHelper.ThrowArgumentNullException(nameof(writer)); } - Type runtimeType = GetRuntimeType(value); - JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, runtimeType); - WriteUsingSerializer(writer, value, jsonTypeInfo); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(options); + WriteCore(writer, value, jsonTypeInfo); } /// @@ -70,9 +70,9 @@ public static void Serialize( ThrowHelper.ThrowArgumentNullException(nameof(writer)); } - Type runtimeType = GetRuntimeTypeAndValidateInputType(value, inputType); - JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, runtimeType); - WriteUsingSerializer(writer, value, jsonTypeInfo); + ValidateInputType(value, inputType); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, inputType); + WriteCoreAsObject(writer, value, jsonTypeInfo); } /// @@ -100,7 +100,8 @@ public static void Serialize(Utf8JsonWriter writer, TValue value, JsonTy ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo)); } - WriteUsingGeneratedSerializer(writer, value, jsonTypeInfo); + jsonTypeInfo.EnsureConfigured(); + WriteCore(writer, value, jsonTypeInfo); } /// @@ -135,8 +136,9 @@ public static void Serialize(Utf8JsonWriter writer, object? value, Type inputTyp ThrowHelper.ThrowArgumentNullException(nameof(context)); } - Type runtimeType = GetRuntimeTypeAndValidateInputType(value, inputType); - WriteUsingGeneratedSerializer(writer, value, GetTypeInfo(context, runtimeType)); + ValidateInputType(value, inputType); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(context, inputType); + WriteCoreAsObject(writer, value, jsonTypeInfo); } } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs index cad93de17744dc..f0a7e71dbc965f 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs @@ -100,17 +100,29 @@ internal JsonTypeInfo GetTypeInfoForRootType(Type type) if (jsonTypeInfo?.Type != type) { - jsonTypeInfo = GetTypeInfoInternal(type); - _lastTypeInfo = jsonTypeInfo; + _lastTypeInfo = jsonTypeInfo = GetTypeInfoInternal(type); } return jsonTypeInfo; } + // Caches the resolved JsonTypeInfo for faster access during root-level object type serialization. + internal JsonTypeInfo ObjectTypeInfo + { + get + { + Debug.Assert(IsImmutable); + return _objectTypeInfo ??= GetTypeInfoInternal(JsonTypeInfo.ObjectType); + } + } + + private JsonTypeInfo? _objectTypeInfo; + internal void ClearCaches() { _cachingContext?.Clear(); _lastTypeInfo = null; + _objectTypeInfo = null; } private CachingContext? GetCachingContext() diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs index b6898db0868dc6..596a9c37bae488 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs @@ -630,8 +630,12 @@ internal void InitializeForReflectionSerializer() DefaultJsonTypeInfoResolver defaultResolver = DefaultJsonTypeInfoResolver.RootDefaultInstance(); _typeInfoResolver ??= defaultResolver; IsImmutable = true; + _isInitializedForReflectionSerializer = true; } + internal bool IsInitializedForReflectionSerializer => _isInitializedForReflectionSerializer; + private volatile bool _isInitializedForReflectionSerializer; + internal void InitializeForMetadataGeneration() { if (_typeInfoResolver is null) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfo.cs index 247f58db58cdc3..2f9ea58106e13c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfo.cs @@ -53,8 +53,11 @@ public JsonTypeInfo JsonTypeInfo public bool ShouldDeserialize { get; private set; } + public JsonPropertyInfo MatchingProperty { get; private set; } = null!; + public virtual void Initialize(JsonParameterInfoValues parameterInfo, JsonPropertyInfo matchingProperty, JsonSerializerOptions options) { + MatchingProperty = matchingProperty; ClrInfo = parameterInfo; Options = options; ShouldDeserialize = true; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs index 128ebf2356c813..7605421549e759 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs @@ -203,6 +203,18 @@ public bool IsExtensionData private bool _isExtensionDataProperty; + internal bool IsRequired + { + get => _isRequired; + set + { + VerifyMutable(); + _isRequired = value; + } + } + + private bool _isRequired; + internal JsonPropertyInfo(Type declaringType, Type propertyType, JsonTypeInfo? declaringTypeInfo, JsonSerializerOptions options) { Debug.Assert(declaringTypeInfo is null || declaringTypeInfo.Type == declaringType); @@ -279,6 +291,21 @@ internal void Configure() DetermineIgnoreCondition(); DetermineSerializationCapabilities(); } + + if (IsRequired) + { + if (!CanDeserialize) + { + ThrowHelper.ThrowInvalidOperationException_JsonPropertyRequiredAndNotDeserializable(this); + } + + if (IsExtensionData) + { + ThrowHelper.ThrowInvalidOperationException_JsonPropertyRequiredAndExtensionData(this); + } + + Debug.Assert(!IgnoreNullTokensOnRead); + } } private protected abstract void DetermineEffectiveConverter(JsonTypeInfo jsonTypeInfo); @@ -341,7 +368,7 @@ private void DetermineIgnoreCondition() Debug.Assert(Options.DefaultIgnoreCondition == JsonIgnoreCondition.Never); if (PropertyTypeCanBeNull) { - IgnoreNullTokensOnRead = !_isUserSpecifiedSetter; + IgnoreNullTokensOnRead = !_isUserSpecifiedSetter && !IsRequired; IgnoreDefaultValuesOnWrite = ShouldSerialize is null; } } @@ -477,6 +504,14 @@ private bool NumberHandingIsApplicable() potentialNumberType == JsonTypeInfo.ObjectType; } + private void DetermineIsRequired(MemberInfo memberInfo, bool shouldCheckForRequiredKeyword) + { + if (shouldCheckForRequiredKeyword && memberInfo.HasRequiredMemberAttribute()) + { + IsRequired = true; + } + } + internal abstract bool GetMemberAndWriteJson(object obj, ref WriteStack state, Utf8JsonWriter writer); internal abstract bool GetMemberAndWriteJsonExtensionData(object obj, ref WriteStack state, Utf8JsonWriter writer); @@ -504,7 +539,7 @@ internal string GetDebugInfo(int indent = 0) internal bool HasGetter => _untypedGet is not null; internal bool HasSetter => _untypedSet is not null; - internal void InitializeUsingMemberReflection(MemberInfo memberInfo, JsonConverter? customConverter, JsonIgnoreCondition? ignoreCondition) + internal void InitializeUsingMemberReflection(MemberInfo memberInfo, JsonConverter? customConverter, JsonIgnoreCondition? ignoreCondition, bool shouldCheckForRequiredKeyword) { Debug.Assert(AttributeProvider == null); @@ -531,6 +566,7 @@ internal void InitializeUsingMemberReflection(MemberInfo memberInfo, JsonConvert CustomConverter = customConverter; DeterminePoliciesFromMember(memberInfo); DeterminePropertyNameFromMember(memberInfo); + DetermineIsRequired(memberInfo, shouldCheckForRequiredKeyword); if (ignoreCondition != JsonIgnoreCondition.Always) { @@ -760,8 +796,6 @@ internal JsonTypeInfo JsonTypeInfo } } - internal abstract void SetExtensionDictionaryAsObject(object obj, object? extensionDict); - internal bool IsIgnored => _ignoreCondition == JsonIgnoreCondition.Always; /// @@ -823,6 +857,29 @@ public JsonNumberHandling? NumberHandling /// internal abstract object? DefaultValue { get; } + /// + /// Required property index on the list of JsonTypeInfo properties. + /// It is used as a unique identifier for required properties. + /// It is set just before property is configured and does not change afterward. + /// It is not equivalent to index on the properties list + /// + internal int RequiredPropertyIndex + { + get + { + Debug.Assert(_isConfigured); + Debug.Assert(IsRequired); + return _index; + } + set + { + Debug.Assert(!_isConfigured); + _index = value; + } + } + + private int _index; + [DebuggerBrowsable(DebuggerBrowsableState.Never)] private string DebuggerDisplay => $"PropertyType = {PropertyType}, Name = {Name}, DeclaringType = {DeclaringType}"; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs index 31d0e699ef78d8..d7ed57757927b1 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs @@ -342,6 +342,7 @@ internal override bool ReadJsonAndSetMember(object obj, ref ReadStack state, ref } success = true; + state.Current.MarkRequiredPropertyAsRead(this); } else if (TypedEffectiveConverter.CanUseDirectReadOrWrite && state.Current.NumberHandling == null) { @@ -356,6 +357,7 @@ internal override bool ReadJsonAndSetMember(object obj, ref ReadStack state, ref } success = true; + state.Current.MarkRequiredPropertyAsRead(this); } else { @@ -366,6 +368,7 @@ internal override bool ReadJsonAndSetMember(object obj, ref ReadStack state, ref if (success) { Set!(obj, value!); + state.Current.MarkRequiredPropertyAsRead(this); } } } @@ -408,13 +411,6 @@ internal override bool ReadJsonAsObject(ref ReadStack state, ref Utf8JsonReader return success; } - internal override void SetExtensionDictionaryAsObject(object obj, object? extensionDict) - { - Debug.Assert(HasSetter); - T typedValue = (T)extensionDict!; - Set!(obj, typedValue); - } - private protected override void ConfigureIgnoreCondition(JsonIgnoreCondition? ignoreCondition) { switch (ignoreCondition) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs index 99e75e28c6be70..b220ffd2da1f19 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs @@ -26,6 +26,11 @@ public abstract partial class JsonTypeInfo private JsonPropertyInfoList? _properties; + /// + /// Indices of required properties. + /// + internal int NumberOfRequiredProperties { get; private set; } + private Action? _onSerializing; private Action? _onSerialized; private Action? _onDeserializing; @@ -266,8 +271,8 @@ public JsonPolymorphismOptions? PolymorphismOptions // If enumerable or dictionary, the JsonTypeInfo for the element type. private JsonTypeInfo? _elementTypeInfo; - // Avoids having to perform an expensive cast to JsonTypeInfo to check if there is a Serialize method. - internal bool HasSerializeHandler { get; private protected set; } + // Flag indicating that JsonTypeInfo.SerializeHandler is populated and is compatible with the associated Options instance. + internal bool CanUseSerializeHandler { get; private protected set; } // Configure would normally have thrown why initializing properties for source gen but type had SerializeHandler // so it is allowed to be used for fast-path serialization but it will throw if used for metadata-based serialization @@ -535,6 +540,8 @@ internal void Configure() PropertyInfoForTypeInfo.EnsureChildOf(this); PropertyInfoForTypeInfo.EnsureConfigured(); + CanUseSerializeHandler &= Options.SerializerContext?.CanUseSerializationLogic == true; + JsonConverter converter = Converter; Debug.Assert(PropertyInfoForTypeInfo.ConverterStrategy == Converter.ConverterStrategy, $"ConverterStrategy from PropertyInfoForTypeInfo.ConverterStrategy ({PropertyInfoForTypeInfo.ConverterStrategy}) does not match converter's ({Converter.ConverterStrategy})"); @@ -878,13 +885,21 @@ internal void InitializePropertyCache() ExtensionDataProperty.EnsureConfigured(); } + int numberOfRequiredProperties = 0; foreach (KeyValuePair jsonPropertyInfoKv in PropertyCache.List) { JsonPropertyInfo jsonPropertyInfo = jsonPropertyInfoKv.Value; + if (jsonPropertyInfo.IsRequired) + { + jsonPropertyInfo.RequiredPropertyIndex = numberOfRequiredProperties++; + } + jsonPropertyInfo.EnsureChildOf(this); jsonPropertyInfo.EnsureConfigured(); } + + NumberOfRequiredProperties = numberOfRequiredProperties; } internal void InitializeConstructorParameters(JsonParameterInfoValues[] jsonParameters, bool sourceGenMode = false) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.cs index 005c67fe578e09..769ac7add4cd59 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.cs @@ -16,6 +16,8 @@ public abstract class JsonTypeInfo : JsonTypeInfo private Func? _typedCreateObject; + internal JsonConverter EffectiveConverter { get; } + /// /// Gets or sets a parameterless factory to be used on deserialization. /// @@ -81,7 +83,9 @@ private protected override void SetCreateObject(Delegate? createObject) internal JsonTypeInfo(JsonConverter converter, JsonSerializerOptions options) : base(typeof(T), converter, options) - { } + { + EffectiveConverter = converter is JsonConverter jsonConverter ? jsonConverter : converter.CreateCastingConverter(); + } /// /// Serializes an instance of using @@ -99,7 +103,7 @@ private protected set { Debug.Assert(!IsConfigured, "We should not mutate configured JsonTypeInfo"); _serialize = value; - HasSerializeHandler = value != null; + CanUseSerializeHandler = value != null; } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs index 89fe3eade4f775..f176e154011b85 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs @@ -1,10 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection; +using System.Runtime.CompilerServices; using System.Text.Json.Reflection; namespace System.Text.Json.Serialization.Metadata @@ -55,6 +57,11 @@ private void AddPropertiesAndParametersUsingReflection() Dictionary? ignoredMembers = null; bool propertyOrderSpecified = false; + // Compiler adds RequiredMemberAttribute to type if any of the members is marked with 'required' keyword. + // SetsRequiredMembersAttribute means that all required members are assigned by constructor and therefore there is no enforcement + bool shouldCheckMembersForRequiredMemberAttribute = + typeof(T).HasRequiredMemberAttribute() + && !(Converter.ConstructorInfo?.HasSetsRequiredMembersAttribute() ?? false); // Walk through the inheritance hierarchy, starting from the most derived type upward. for (Type? currentType = Type; currentType != null; currentType = currentType.BaseType) @@ -85,7 +92,8 @@ private void AddPropertiesAndParametersUsingReflection() typeToConvert: propertyInfo.PropertyType, memberInfo: propertyInfo, ref propertyOrderSpecified, - ref ignoredMembers); + ref ignoredMembers, + shouldCheckMembersForRequiredMemberAttribute); } else { @@ -117,7 +125,8 @@ private void AddPropertiesAndParametersUsingReflection() typeToConvert: fieldInfo.FieldType, memberInfo: fieldInfo, ref propertyOrderSpecified, - ref ignoredMembers); + ref ignoredMembers, + shouldCheckMembersForRequiredMemberAttribute); } } else @@ -144,9 +153,10 @@ private void CacheMember( Type typeToConvert, MemberInfo memberInfo, ref bool propertyOrderSpecified, - ref Dictionary? ignoredMembers) + ref Dictionary? ignoredMembers, + bool shouldCheckForRequiredKeyword) { - JsonPropertyInfo? jsonPropertyInfo = CreateProperty(typeToConvert, memberInfo, Options); + JsonPropertyInfo? jsonPropertyInfo = CreateProperty(typeToConvert, memberInfo, Options, shouldCheckForRequiredKeyword); if (jsonPropertyInfo == null) { // ignored invalid property @@ -166,7 +176,8 @@ private void CacheMember( private JsonPropertyInfo? CreateProperty( Type typeToConvert, MemberInfo memberInfo, - JsonSerializerOptions options) + JsonSerializerOptions options, + bool shouldCheckForRequiredKeyword) { JsonIgnoreCondition? ignoreCondition = memberInfo.GetCustomAttribute(inherit: false)?.Condition; @@ -191,7 +202,7 @@ private void CacheMember( } JsonPropertyInfo jsonPropertyInfo = CreatePropertyUsingReflection(typeToConvert); - jsonPropertyInfo.InitializeUsingMemberReflection(memberInfo, customConverter, ignoreCondition); + jsonPropertyInfo.InitializeUsingMemberReflection(memberInfo, customConverter, ignoreCondition, shouldCheckForRequiredKeyword); return jsonPropertyInfo; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs index b711b3d303d063..ee348f63aae552 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs @@ -93,13 +93,7 @@ private void EnsurePushCapacity() } } - public void Initialize(Type type, JsonSerializerOptions options, bool supportContinuation) - { - JsonTypeInfo jsonTypeInfo = options.GetTypeInfoForRootType(type); - Initialize(jsonTypeInfo, supportContinuation); - } - - internal void Initialize(JsonTypeInfo jsonTypeInfo, bool supportContinuation = false) + internal void Initialize(JsonTypeInfo jsonTypeInfo) { JsonSerializerOptions options = jsonTypeInfo.Options; if (options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.Preserve) @@ -108,7 +102,6 @@ internal void Initialize(JsonTypeInfo jsonTypeInfo, bool supportContinuation = f PreserveReferences = true; } - SupportContinuation = supportContinuation; Current.JsonTypeInfo = jsonTypeInfo; Current.JsonPropertyInfo = jsonTypeInfo.PropertyInfoForTypeInfo; Current.NumberHandling = Current.JsonPropertyInfo.EffectiveNumberHandling; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStackFrame.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStackFrame.cs index 253ebbbd170e6c..abf8aa0bd39b5f 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStackFrame.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStackFrame.cs @@ -1,8 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections; using System.Collections.Generic; using System.Diagnostics; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; @@ -66,6 +68,13 @@ public JsonTypeInfo BaseJsonTypeInfo // Whether to use custom number handling. public JsonNumberHandling? NumberHandling; + // Represents required properties which have value assigned. + // Each bit corresponds to a required property. + // False means that property is not set (not yet occured in the payload). + // Length of the BitArray is equal to number of required properties. + // Every required JsonPropertyInfo has RequiredPropertyIndex property which maps to an index in this BitArray. + public BitArray? RequiredPropertiesSet; + public void EndConstructorParameter() { CtorArgumentState!.JsonParameterInfo = null; @@ -107,6 +116,41 @@ public bool IsProcessingEnumerable() return (JsonTypeInfo.PropertyInfoForTypeInfo.ConverterStrategy & ConverterStrategy.Enumerable) != 0; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void MarkRequiredPropertyAsRead(JsonPropertyInfo propertyInfo) + { + if (propertyInfo.IsRequired) + { + Debug.Assert(RequiredPropertiesSet != null); + RequiredPropertiesSet[propertyInfo.RequiredPropertyIndex] = true; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void InitializeRequiredPropertiesValidationState(JsonTypeInfo typeInfo) + { + Debug.Assert(RequiredPropertiesSet == null); + + if (typeInfo.NumberOfRequiredProperties > 0) + { + RequiredPropertiesSet = new BitArray(typeInfo.NumberOfRequiredProperties); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void ValidateAllRequiredPropertiesAreRead(JsonTypeInfo typeInfo) + { + if (typeInfo.NumberOfRequiredProperties > 0) + { + Debug.Assert(RequiredPropertiesSet != null); + + if (!RequiredPropertiesSet.AllBitsEqual(true)) + { + ThrowHelper.ThrowJsonException_JsonRequiredPropertyMissing(typeInfo, RequiredPropertiesSet); + } + } + } + [DebuggerBrowsable(DebuggerBrowsableState.Never)] private string DebuggerDisplay => $"ConverterStrategy.{JsonTypeInfo?.PropertyInfoForTypeInfo.ConverterStrategy}, {JsonTypeInfo?.Type.Name}"; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs index 0e15cce45faed7..18a36d8680d7b1 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs @@ -93,6 +93,12 @@ public ref WriteStackFrame Parent /// public bool IsContinuation => _continuationCount != 0; + /// + /// Indicates that the root-level JsonTypeInfo is the result of + /// polymorphic dispatch from the internal System.Object converter. + /// + public bool IsPolymorphicRootValue; + // The bag of preservable references. public ReferenceResolver ReferenceResolver; @@ -133,18 +139,10 @@ private void EnsurePushCapacity() } } - /// - /// Initialize the state without delayed initialization of the JsonTypeInfo. - /// - public JsonConverter Initialize(Type type, JsonSerializerOptions options, bool supportContinuation, bool supportAsync) - { - JsonTypeInfo jsonTypeInfo = options.GetTypeInfoForRootType(type); - return Initialize(jsonTypeInfo, supportContinuation, supportAsync); - } - - internal JsonConverter Initialize(JsonTypeInfo jsonTypeInfo, bool supportContinuation, bool supportAsync) + internal void Initialize(JsonTypeInfo jsonTypeInfo) { - Debug.Assert(!supportAsync || supportContinuation, "supportAsync implies supportContinuation."); + Debug.Assert(!IsContinuation); + Debug.Assert(CurrentDepth == 0); Current.JsonTypeInfo = jsonTypeInfo; Current.JsonPropertyInfo = jsonTypeInfo.PropertyInfoForTypeInfo; @@ -156,11 +154,6 @@ internal JsonConverter Initialize(JsonTypeInfo jsonTypeInfo, bool supportContinu Debug.Assert(options.ReferenceHandler != null); ReferenceResolver = options.ReferenceHandler.CreateResolver(writing: true); } - - SupportContinuation = supportContinuation; - SupportAsync = supportAsync; - - return jsonTypeInfo.Converter; } /// diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs index dee7b47adaa160..66384b01b4ce97 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs @@ -2,8 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Buffers; +using System.Collections; +using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Text.Json.Serialization; @@ -200,6 +203,56 @@ public static void ThrowInvalidOperationException_SerializerPropertyNameNull(Jso throw new InvalidOperationException(SR.Format(SR.SerializerPropertyNameNull, jsonPropertyInfo.DeclaringType, jsonPropertyInfo.MemberName)); } + [DoesNotReturn] + public static void ThrowInvalidOperationException_JsonPropertyRequiredAndNotDeserializable(JsonPropertyInfo jsonPropertyInfo) + { + throw new InvalidOperationException(SR.Format(SR.JsonPropertyRequiredAndNotDeserializable, jsonPropertyInfo.Name, jsonPropertyInfo.DeclaringType)); + } + + [DoesNotReturn] + public static void ThrowInvalidOperationException_JsonPropertyRequiredAndExtensionData(JsonPropertyInfo jsonPropertyInfo) + { + throw new InvalidOperationException(SR.Format(SR.JsonPropertyRequiredAndExtensionData, jsonPropertyInfo.Name, jsonPropertyInfo.DeclaringType)); + } + + [DoesNotReturn] + public static void ThrowJsonException_JsonRequiredPropertyMissing(JsonTypeInfo parent, BitArray requiredPropertiesSet) + { + StringBuilder listOfMissingPropertiesBuilder = new(); + bool first = true; + + Debug.Assert(parent.PropertyCache != null); + + // Soft cut-off length - once message becomes longer than that we won't be adding more elements + const int CutOffLength = 50; + + for (int propertyIdx = 0; propertyIdx < parent.PropertyCache.List.Count; propertyIdx++) + { + JsonPropertyInfo property = parent.PropertyCache.List[propertyIdx].Value; + + if (!property.IsRequired || requiredPropertiesSet[property.RequiredPropertyIndex]) + { + continue; + } + + if (!first) + { + listOfMissingPropertiesBuilder.Append(CultureInfo.CurrentUICulture.TextInfo.ListSeparator); + listOfMissingPropertiesBuilder.Append(' '); + } + + listOfMissingPropertiesBuilder.Append(property.Name); + first = false; + + if (listOfMissingPropertiesBuilder.Length >= CutOffLength) + { + break; + } + } + + throw new JsonException(SR.Format(SR.JsonRequiredPropertiesMissing, parent.Type, listOfMissingPropertiesBuilder.ToString())); + } + [DoesNotReturn] public static void ThrowInvalidOperationException_NamingPolicyReturnNull(JsonNamingPolicy namingPolicy) { @@ -656,11 +709,18 @@ public static void ThrowInvalidOperationException_NoMetadataForType(Type type, I throw new InvalidOperationException(SR.Format(SR.NoMetadataForType, type, resolver?.GetType().FullName ?? "")); } + public static Exception GetInvalidOperationException_NoMetadataForTypeProperties(IJsonTypeInfoResolver? resolver, Type type) + { + return new InvalidOperationException(SR.Format(SR.NoMetadataForTypeProperties, resolver?.GetType().FullName ?? "", type)); + } + + [DoesNotReturn] public static void ThrowInvalidOperationException_NoMetadataForTypeProperties(IJsonTypeInfoResolver? resolver, Type type) { - throw new InvalidOperationException(SR.Format(SR.NoMetadataForTypeProperties, resolver?.GetType().FullName ?? "", type)); + throw GetInvalidOperationException_NoMetadataForTypeProperties(resolver, type); } + [DoesNotReturn] public static void ThrowInvalidOperationException_NoMetadataForTypeCtorParams(IJsonTypeInfoResolver? resolver, Type type) { throw new InvalidOperationException(SR.Format(SR.NoMetadataForTypeCtorParams, resolver?.GetType().FullName ?? "", type)); diff --git a/src/libraries/System.Text.Json/tests/Common/ReferenceHandlerTests/ReferenceHandlerTests.IgnoreCycles.cs b/src/libraries/System.Text.Json/tests/Common/ReferenceHandlerTests/ReferenceHandlerTests.IgnoreCycles.cs index 3a692ee98b5625..9e613a0e16c742 100644 --- a/src/libraries/System.Text.Json/tests/Common/ReferenceHandlerTests/ReferenceHandlerTests.IgnoreCycles.cs +++ b/src/libraries/System.Text.Json/tests/Common/ReferenceHandlerTests/ReferenceHandlerTests.IgnoreCycles.cs @@ -134,9 +134,6 @@ public async Task IgnoreCycles_OnDictionary(Type typeToSerialize) } [Fact] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("https://github.com/dotnet/runtime/issues/66421")] -#endif public async Task IgnoreCycles_OnRecursiveDictionary() { var root = new RecursiveDictionary(); @@ -183,9 +180,6 @@ public async Task IgnoreCycles_OnList(Type typeToSerialize) } [Fact] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("https://github.com/dotnet/runtime/issues/66421")] -#endif public async Task IgnoreCycles_OnRecursiveList() { var root = new RecursiveList(); @@ -240,9 +234,6 @@ public async Task IgnoreCycles_OnExtensionData() } [Fact] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("https://github.com/dotnet/runtime/issues/66421")] -#endif public async Task IgnoreCycles_DoesNotSupportPreserveSemantics() { // Object @@ -279,9 +270,6 @@ public async Task IgnoreCycles_DoesNotSupportPreserveSemantics() } [Fact] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("https://github.com/dotnet/runtime/issues/66421")] -#endif public async Task IgnoreCycles_DoesNotSupportPreserveSemantics_Polymorphic() { // Object diff --git a/src/libraries/System.Text.Json/tests/Common/ReferenceHandlerTests/ReferenceHandlerTests.cs b/src/libraries/System.Text.Json/tests/Common/ReferenceHandlerTests/ReferenceHandlerTests.cs index 562b92f990a6e7..34e2e159b3a6dc 100644 --- a/src/libraries/System.Text.Json/tests/Common/ReferenceHandlerTests/ReferenceHandlerTests.cs +++ b/src/libraries/System.Text.Json/tests/Common/ReferenceHandlerTests/ReferenceHandlerTests.cs @@ -242,9 +242,6 @@ public async Task UnicodePropertyNames() public class DictionaryWithGenericCycle : Dictionary { } [Fact] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("https://github.com/dotnet/runtime/issues/66421")] -#endif public async Task DictionaryLoop() { DictionaryWithGenericCycle root = new DictionaryWithGenericCycle(); @@ -261,9 +258,6 @@ public async Task DictionaryLoop() } [Fact] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("https://github.com/dotnet/runtime/issues/66421")] -#endif public async Task DictionaryPreserveDuplicateDictionaries() { DictionaryWithGenericCycle root = new DictionaryWithGenericCycle(); @@ -298,9 +292,6 @@ public async Task DictionaryObjectLoop() public class DictionaryWithGenericCycleWithinList : Dictionary> { } [Fact] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("https://github.com/dotnet/runtime/issues/66421")] -#endif public async Task DictionaryArrayLoop() { DictionaryWithGenericCycleWithinList root = new DictionaryWithGenericCycleWithinList(); @@ -316,9 +307,6 @@ public async Task DictionaryArrayLoop() } [Fact] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("https://github.com/dotnet/runtime/issues/66421")] -#endif public async Task DictionaryPreserveDuplicateArrays() { DictionaryWithGenericCycleWithinList root = new DictionaryWithGenericCycleWithinList(); @@ -449,9 +437,6 @@ public async Task UnicodeDictionaryKeys() public class ListWithGenericCycle : List { } [Fact] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("https://github.com/dotnet/runtime/issues/66421")] -#endif public async Task ArrayLoop() { ListWithGenericCycle root = new ListWithGenericCycle(); @@ -518,9 +503,6 @@ public async Task ArrayPreserveDuplicateObjects() public class ListWithGenericCycleWithinDictionary : List> { } [Fact] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("https://github.com/dotnet/runtime/issues/66421")] -#endif public async Task ArrayDictionaryLoop() { ListWithGenericCycleWithinDictionary root = new ListWithGenericCycleWithinDictionary(); @@ -536,9 +518,6 @@ public async Task ArrayDictionaryLoop() } [Fact] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("https://github.com/dotnet/runtime/issues/66421")] -#endif public async Task ArrayPreserveDuplicateDictionaries() { ListWithGenericCycleWithinDictionary root = new ListWithGenericCycleWithinDictionary diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Dynamic.Sample.Tests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Dynamic.Sample.Tests.cs index 5cdae55d648056..9ddd993d5e6923 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Dynamic.Sample.Tests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Dynamic.Sample.Tests.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Collections.Generic; -using System.Dynamic; using System.Globalization; using System.Tests; using System.Text.Json.Serialization.Samples; diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Dynamic.Sample.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Dynamic.Sample.cs index f5f417ea25c00b..f292e80249d94d 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Dynamic.Sample.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Dynamic.Sample.cs @@ -514,7 +514,7 @@ public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOp value = dynamicType.Value; } - JsonSerializer.Serialize(writer, value, options); + JsonSerializer.Serialize(writer, value, value.GetType(), options); } private void ReadList(JsonDynamicArray dynamicArray, ref Utf8JsonReader reader, JsonSerializerOptions options) diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Object.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Object.cs index 36309616eaf5f4..7e3f8247023f7c 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Object.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Object.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections.Generic; +using System.Text.Json.Serialization.Metadata; using Xunit; namespace System.Text.Json.Serialization.Tests @@ -8,7 +10,7 @@ namespace System.Text.Json.Serialization.Tests public static partial class CustomConverterTests { /// - /// A converter that uses Object as it's type. + /// A converter that uses Object as its type. /// private class ObjectToCustomerOrIntConverter : JsonConverter { @@ -307,9 +309,19 @@ public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonS public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) { - Assert.IsType(value); - writer.WriteStartObject(); - writer.WriteEndObject(); + if (value is null) + { + writer.WriteNullValue(); + } + else if (value.GetType() == typeof(object)) + { + writer.WriteStartObject(); + writer.WriteEndObject(); + } + else + { + JsonSerializer.Serialize(writer, value, value.GetType(), options); + } } } @@ -745,6 +757,33 @@ public static void CanCustomizeSystemObjectSerialization() Assert.Equal(expectedJson, actualJson); } + [Theory] + [InlineData(-2)] + [InlineData(false)] + [InlineData("string")] + [InlineData(3.1415926)] + public static void CustomSystemObjectConverter_DoesNotUsePolymorphismInAllContexts(object value) + { + // Regression test for https://github.com/dotnet/runtime/issues/72681 + + var options = new JsonSerializerOptions { Converters = { new CustomSystemObjectConverter() } }; + + TestValue(value, "42"); + TestValue(new { Value = value }, """{"Value":42}"""); + TestValue(new object[] { value }, "[42]"); + TestValue(new Dictionary { ["key"] = value }, """{"key":42}"""); + + void TestValue(T value, string expectedJson) + { + string json = JsonSerializer.Serialize(value, options); + Assert.Equal(expectedJson, json); + + JsonTypeInfo jsonTypeInfo = (JsonTypeInfo)options.GetTypeInfo(typeof(T)); + json = JsonSerializer.Serialize(value, jsonTypeInfo); + Assert.Equal(expectedJson, json); + } + } + private class CustomSystemObjectConverter : JsonConverter { public override object? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => throw new NotImplementedException(); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/PolymorphicTests.CustomTypeHierarchies.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/PolymorphicTests.CustomTypeHierarchies.cs index aff1af118432b2..13669fceaae318 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/PolymorphicTests.CustomTypeHierarchies.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/PolymorphicTests.CustomTypeHierarchies.cs @@ -935,7 +935,6 @@ public class DerivedClass2 : DerivedClass } [Theory] - [ActiveIssue("https://github.com/dotnet/runtime/issues/72187")] [MemberData(nameof(PolymorphicClass_WithBaseTypeDiscriminator.GetTestData), MemberType = typeof(PolymorphicClass_WithBaseTypeDiscriminator))] public async Task PolymorphicClass_BoxedSerialization_DoesNotUseTypeDiscriminators(PolymorphicClass_WithBaseTypeDiscriminator value, string expectedJson) { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/PolymorphicTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/PolymorphicTests.cs index 40ecc53a60925b..56158ea03b192e 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/PolymorphicTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/PolymorphicTests.cs @@ -4,6 +4,7 @@ using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; +using System.Text.Json.Serialization.Metadata; using System.Threading.Tasks; using Xunit; @@ -60,34 +61,23 @@ public PolymorphicTests(JsonSerializerWrapper serializer) : base(serializer) { } - [Fact] - public async Task PrimitivesAsRootObject() + [Theory] + [InlineData(1, "1")] + [InlineData("stringValue", @"""stringValue""")] + [InlineData(true, "true")] + [InlineData(null, "null")] + [InlineData(new int[] { 1, 2, 3}, "[1,2,3]")] + public async Task PrimitivesAsRootObject(object? value, string expectedJson) { - string json = await Serializer.SerializeWrapper(1); - Assert.Equal("1", json); - json = await Serializer.SerializeWrapper(1, typeof(object)); - Assert.Equal("1", json); - - json = await Serializer.SerializeWrapper("foo"); - Assert.Equal(@"""foo""", json); - json = await Serializer.SerializeWrapper("foo", typeof(object)); - Assert.Equal(@"""foo""", json); - - json = await Serializer.SerializeWrapper(true); - Assert.Equal(@"true", json); - json = await Serializer.SerializeWrapper(true, typeof(object)); - Assert.Equal(@"true", json); - - json = await Serializer.SerializeWrapper(null); - Assert.Equal(@"null", json); - json = await Serializer.SerializeWrapper((object)null, typeof(object)); - Assert.Equal(@"null", json); - - decimal pi = 3.1415926535897932384626433833m; - json = await Serializer.SerializeWrapper(pi); - Assert.Equal(@"3.1415926535897932384626433833", json); - json = await Serializer.SerializeWrapper(pi, typeof(object)); - Assert.Equal(@"3.1415926535897932384626433833", json); + string json = await Serializer.SerializeWrapper(value); + Assert.Equal(expectedJson, json); + json = await Serializer.SerializeWrapper(value, typeof(object)); + Assert.Equal(expectedJson, json); + + var options = new JsonSerializerOptions { TypeInfoResolver = new DefaultJsonTypeInfoResolver() }; + JsonTypeInfo objectTypeInfo = (JsonTypeInfo)options.GetTypeInfo(typeof(object)); + json = await Serializer.SerializeWrapper(value, objectTypeInfo); + Assert.Equal(expectedJson, json); } [Fact] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/RequiredKeywordTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/RequiredKeywordTests.cs new file mode 100644 index 00000000000000..9517d94c2ce1ad --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/RequiredKeywordTests.cs @@ -0,0 +1,521 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text.Json.Serialization.Metadata; +using Newtonsoft.Json; +using Xunit; + +namespace System.Text.Json.Serialization.Tests +{ + public class RequiredKeywordTests_Span : RequiredKeywordTests + { + public RequiredKeywordTests_Span() : base(JsonSerializerWrapper.SpanSerializer) { } + } + + public class RequiredKeywordTests_String : RequiredKeywordTests + { + public RequiredKeywordTests_String() : base(JsonSerializerWrapper.StringSerializer) { } + } + + public class RequiredKeywordTests_AsyncStream : RequiredKeywordTests + { + public RequiredKeywordTests_AsyncStream() : base(JsonSerializerWrapper.AsyncStreamSerializer) { } + } + + public class RequiredKeywordTests_AsyncStreamWithSmallBuffer : RequiredKeywordTests + { + public RequiredKeywordTests_AsyncStreamWithSmallBuffer() : base(JsonSerializerWrapper.AsyncStreamSerializerWithSmallBuffer) { } + } + + public class RequiredKeywordTests_SyncStream : RequiredKeywordTests + { + public RequiredKeywordTests_SyncStream() : base(JsonSerializerWrapper.SyncStreamSerializer) { } + } + + public class RequiredKeywordTests_Writer : RequiredKeywordTests + { + public RequiredKeywordTests_Writer() : base(JsonSerializerWrapper.ReaderWriterSerializer) { } + } + + public class RequiredKeywordTests_Document : RequiredKeywordTests + { + public RequiredKeywordTests_Document() : base(JsonSerializerWrapper.DocumentSerializer) { } + } + + public class RequiredKeywordTests_Element : RequiredKeywordTests + { + public RequiredKeywordTests_Element() : base(JsonSerializerWrapper.ElementSerializer) { } + } + + public class RequiredKeywordTests_Node : RequiredKeywordTests + { + public RequiredKeywordTests_Node() : base(JsonSerializerWrapper.NodeSerializer) { } + } + + public abstract class RequiredKeywordTests : SerializerTests + { + public RequiredKeywordTests(JsonSerializerWrapper serializer) : base(serializer) + { + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async void ClassWithRequiredKeywordDeserialization(bool ignoreNullValues) + { + JsonSerializerOptions options = new() + { + IgnoreNullValues = ignoreNullValues + }; + + var obj = new PersonWithRequiredMembers() + { + FirstName = "foo", + LastName = "bar" + }; + + string json = await Serializer.SerializeWrapper(obj, options); + Assert.Equal("""{"FirstName":"foo","MiddleName":"","LastName":"bar"}""", json); + + PersonWithRequiredMembers deserialized = await Serializer.DeserializeWrapper(json, options); + Assert.Equal(obj.FirstName, deserialized.FirstName); + Assert.Equal(obj.MiddleName, deserialized.MiddleName); + Assert.Equal(obj.LastName, deserialized.LastName); + + json = """{"LastName":"bar"}"""; + JsonException exception = await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, options)); + Assert.Contains("FirstName", exception.Message); + Assert.DoesNotContain("LastName", exception.Message); + Assert.DoesNotContain("MiddleName", exception.Message); + + json = """{"LastName":null}"""; + exception = await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, options)); + Assert.Contains("FirstName", exception.Message); + Assert.DoesNotContain("LastName", exception.Message); + Assert.DoesNotContain("MiddleName", exception.Message); + + json = "{}"; + exception = await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, options)); + Assert.Contains("FirstName", exception.Message); + Assert.Contains("LastName", exception.Message); + Assert.DoesNotContain("MiddleName", exception.Message); + } + + [Fact] + public async void RequiredPropertyOccuringTwiceInThePayloadWorksAsExpected() + { + string json = """{"FirstName":"foo","MiddleName":"","LastName":"bar","FirstName":"newfoo"}"""; + PersonWithRequiredMembers deserialized = await Serializer.DeserializeWrapper(json); + Assert.Equal("newfoo", deserialized.FirstName); + Assert.Equal("", deserialized.MiddleName); + Assert.Equal("bar", deserialized.LastName); + } + + private class PersonWithRequiredMembers + { + public required string FirstName { get; set; } + public string MiddleName { get; set; } = ""; + public required string LastName { get; set; } + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async void ClassWithRequiredKeywordAndSmallParametrizedCtorFailsDeserialization(bool ignoreNullValues) + { + JsonSerializerOptions options = new() + { + IgnoreNullValues = ignoreNullValues + }; + + var obj = new PersonWithRequiredMembersAndSmallParametrizedCtor("badfoo", "badbar") + { + // note: these must be set during initialize or otherwise we get compiler errors + FirstName = "foo", + LastName = "bar", + Info1 = "info1", + Info2 = "info2", + }; + + string json = await Serializer.SerializeWrapper(obj, options); + Assert.Equal("""{"FirstName":"foo","MiddleName":"","LastName":"bar","Info1":"info1","Info2":"info2"}""", json); + + var deserialized = await Serializer.DeserializeWrapper(json, options); + Assert.Equal(obj.FirstName, deserialized.FirstName); + Assert.Equal(obj.MiddleName, deserialized.MiddleName); + Assert.Equal(obj.LastName, deserialized.LastName); + Assert.Equal(obj.Info1, deserialized.Info1); + Assert.Equal(obj.Info2, deserialized.Info2); + + json = """{"FirstName":"foo","MiddleName":"","LastName":null,"Info1":null,"Info2":"info2"}"""; + deserialized = await Serializer.DeserializeWrapper(json, options); + Assert.Equal(obj.FirstName, deserialized.FirstName); + Assert.Equal(obj.MiddleName, deserialized.MiddleName); + Assert.Null(deserialized.LastName); + Assert.Null(deserialized.Info1); + Assert.Equal(obj.Info2, deserialized.Info2); + + json = """{"LastName":"bar","Info1":"info1"}"""; + JsonException exception = await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, options)); + Assert.Contains("FirstName", exception.Message); + Assert.DoesNotContain("LastName", exception.Message); + Assert.DoesNotContain("MiddleName", exception.Message); + Assert.DoesNotContain("Info1", exception.Message); + Assert.Contains("Info2", exception.Message); + + json = """{"LastName":null,"Info1":null}"""; + exception = await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, options)); + Assert.Contains("FirstName", exception.Message); + Assert.DoesNotContain("LastName", exception.Message); + Assert.DoesNotContain("MiddleName", exception.Message); + Assert.DoesNotContain("Info1", exception.Message); + Assert.Contains("Info2", exception.Message); + + json = "{}"; + exception = await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, options)); + Assert.Contains("FirstName", exception.Message); + Assert.Contains("LastName", exception.Message); + Assert.DoesNotContain("MiddleName", exception.Message); + Assert.Contains("Info1", exception.Message); + Assert.Contains("Info2", exception.Message); + } + + private class PersonWithRequiredMembersAndSmallParametrizedCtor + { + public required string FirstName { get; set; } + public string MiddleName { get; set; } = ""; + public required string LastName { get; set; } + public required string Info1 { get; set; } + public required string Info2 { get; set; } + + public PersonWithRequiredMembersAndSmallParametrizedCtor(string firstName, string lastName) + { + FirstName = firstName; + LastName = lastName; + } + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async void ClassWithRequiredKeywordAndLargeParametrizedCtorFailsDeserialization(bool ignoreNullValues) + { + JsonSerializerOptions options = new() + { + IgnoreNullValues = ignoreNullValues + }; + + var obj = new PersonWithRequiredMembersAndLargeParametrizedCtor("bada", "badb", "badc", "badd", "bade", "badf", "badg") + { + // note: these must be set during initialize or otherwise we get compiler errors + AProp = "a", + BProp = "b", + CProp = "c", + DProp = "d", + EProp = "e", + FProp = "f", + GProp = "g", + HProp = "h", + IProp = "i", + }; + + string json = await Serializer.SerializeWrapper(obj, options); + Assert.Equal("""{"AProp":"a","BProp":"b","CProp":"c","DProp":"d","EProp":"e","FProp":"f","GProp":"g","HProp":"h","IProp":"i"}""", json); + + var deserialized = await Serializer.DeserializeWrapper(json, options); + Assert.Equal(obj.AProp, deserialized.AProp); + Assert.Equal(obj.BProp, deserialized.BProp); + Assert.Equal(obj.CProp, deserialized.CProp); + Assert.Equal(obj.DProp, deserialized.DProp); + Assert.Equal(obj.EProp, deserialized.EProp); + Assert.Equal(obj.FProp, deserialized.FProp); + Assert.Equal(obj.GProp, deserialized.GProp); + Assert.Equal(obj.HProp, deserialized.HProp); + Assert.Equal(obj.IProp, deserialized.IProp); + + json = """{"AProp":"a","BProp":"b","CProp":"c","DProp":"d","EProp":null,"FProp":"f","GProp":"g","HProp":null,"IProp":"i"}"""; + deserialized = await Serializer.DeserializeWrapper(json, options); + Assert.Equal(obj.AProp, deserialized.AProp); + Assert.Equal(obj.BProp, deserialized.BProp); + Assert.Equal(obj.CProp, deserialized.CProp); + Assert.Equal(obj.DProp, deserialized.DProp); + Assert.Null(deserialized.EProp); + Assert.Equal(obj.FProp, deserialized.FProp); + Assert.Equal(obj.GProp, deserialized.GProp); + Assert.Null(deserialized.HProp); + Assert.Equal(obj.IProp, deserialized.IProp); + + json = """{"AProp":"a","IProp":"i"}"""; + JsonException exception = await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, options)); + Assert.DoesNotContain("AProp", exception.Message); + Assert.Contains("BProp", exception.Message); + Assert.Contains("CProp", exception.Message); + Assert.Contains("DProp", exception.Message); + Assert.Contains("EProp", exception.Message); + Assert.Contains("FProp", exception.Message); + Assert.Contains("GProp", exception.Message); + Assert.Contains("HProp", exception.Message); + Assert.DoesNotContain("IProp", exception.Message); + + json = """{"AProp":null,"IProp":null}"""; + exception = await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, options)); + Assert.DoesNotContain("AProp", exception.Message); + Assert.Contains("BProp", exception.Message); + Assert.Contains("CProp", exception.Message); + Assert.Contains("DProp", exception.Message); + Assert.Contains("EProp", exception.Message); + Assert.Contains("FProp", exception.Message); + Assert.Contains("GProp", exception.Message); + Assert.Contains("HProp", exception.Message); + Assert.DoesNotContain("IProp", exception.Message); + + json = """{"BProp":"b","CProp":"c","DProp":"d","EProp":"e","FProp":"f","HProp":"h"}"""; + exception = await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, options)); + Assert.Contains("AProp", exception.Message); + Assert.DoesNotContain("BProp", exception.Message); + Assert.DoesNotContain("CProp", exception.Message); + Assert.DoesNotContain("DProp", exception.Message); + Assert.DoesNotContain("EProp", exception.Message); + Assert.DoesNotContain("FProp", exception.Message); + Assert.Contains("GProp", exception.Message); + Assert.DoesNotContain("HProp", exception.Message); + Assert.Contains("IProp", exception.Message); + } + + private class PersonWithRequiredMembersAndLargeParametrizedCtor + { + // Using suffix for names so that checking if required property is missing can be done with simple string.Contains without false positives + public required string AProp { get; set; } + public required string BProp { get; set; } + public required string CProp { get; set; } + public required string DProp { get; set; } + public required string EProp { get; set; } + public required string FProp { get; set; } + public required string GProp { get; set; } + public required string HProp { get; set; } + public required string IProp { get; set; } + + public PersonWithRequiredMembersAndLargeParametrizedCtor(string aprop, string bprop, string cprop, string dprop, string eprop, string fprop, string gprop) + { + AProp = aprop; + BProp = bprop; + CProp = cprop; + DProp = dprop; + EProp = eprop; + FProp = fprop; + GProp = gprop; + } + } + + [Fact] + public async void ClassWithRequiredKeywordAndSetsRequiredMembersOnCtorWorks() + { + var obj = new PersonWithRequiredMembersAndSetsRequiredMembers() + { + FirstName = "foo", + LastName = "bar" + }; + + string json = await Serializer.SerializeWrapper(obj); + Assert.Equal("""{"FirstName":"foo","MiddleName":"","LastName":"bar"}""", json); + + json = """{"LastName":"bar"}"""; + var deserialized = await Serializer.DeserializeWrapper(json); + Assert.Equal("", deserialized.FirstName); + Assert.Equal("", deserialized.MiddleName); + Assert.Equal("bar", deserialized.LastName); + } + + private class PersonWithRequiredMembersAndSetsRequiredMembers + { + public required string FirstName { get; set; } + public string MiddleName { get; set; } = ""; + public required string LastName { get; set; } + + [SetsRequiredMembers] + public PersonWithRequiredMembersAndSetsRequiredMembers() + { + FirstName = ""; + LastName = ""; + } + } + + [Fact] + public async void ClassWithRequiredKeywordSmallParametrizedCtorAndSetsRequiredMembersOnCtorWorks() + { + var obj = new PersonWithRequiredMembersAndSmallParametrizedCtorAndSetsRequiredMembers("foo", "bar"); + + string json = await Serializer.SerializeWrapper(obj); + Assert.Equal("""{"FirstName":"foo","MiddleName":"","LastName":"bar"}""", json); + + var deserialized = await Serializer.DeserializeWrapper(json); + Assert.Equal("foo", deserialized.FirstName); + Assert.Equal("", deserialized.MiddleName); + Assert.Equal("bar", deserialized.LastName); + } + + private class PersonWithRequiredMembersAndSmallParametrizedCtorAndSetsRequiredMembers + { + public required string FirstName { get; init; } + public string MiddleName { get; init; } = ""; + public required string LastName { get; init; } + + [SetsRequiredMembers] + public PersonWithRequiredMembersAndSmallParametrizedCtorAndSetsRequiredMembers(string firstName, string lastName) + { + FirstName = firstName; + LastName = lastName; + } + } + + [Fact] + public async void ClassWithRequiredKeywordLargeParametrizedCtorAndSetsRequiredMembersOnCtorWorks() + { + var obj = new PersonWithRequiredMembersAndLargeParametrizedCtorndSetsRequiredMembers("a", "b", "c", "d", "e", "f", "g"); + + string json = await Serializer.SerializeWrapper(obj); + Assert.Equal("""{"A":"a","B":"b","C":"c","D":"d","E":"e","F":"f","G":"g"}""", json); + + var deserialized = await Serializer.DeserializeWrapper(json); + Assert.Equal("a", deserialized.A); + Assert.Equal("b", deserialized.B); + Assert.Equal("c", deserialized.C); + Assert.Equal("d", deserialized.D); + Assert.Equal("e", deserialized.E); + Assert.Equal("f", deserialized.F); + Assert.Equal("g", deserialized.G); + } + + private class PersonWithRequiredMembersAndLargeParametrizedCtorndSetsRequiredMembers + { + public required string A { get; set; } + public required string B { get; set; } + public required string C { get; set; } + public required string D { get; set; } + public required string E { get; set; } + public required string F { get; set; } + public required string G { get; set; } + + [SetsRequiredMembers] + public PersonWithRequiredMembersAndLargeParametrizedCtorndSetsRequiredMembers(string a, string b, string c, string d, string e, string f, string g) + { + A = a; + B = b; + C = c; + D = d; + E = e; + F = f; + G = g; + } + } + + [Fact] + public async void RemovingRequiredPropertiesAllowsDeserialization() + { + JsonSerializerOptions options = new() + { + TypeInfoResolver = new DefaultJsonTypeInfoResolver() + { + Modifiers = + { + (ti) => + { + for (int i = 0; i < ti.Properties.Count; i++) + { + if (ti.Properties[i].Name == nameof(PersonWithRequiredMembers.FirstName)) + { + JsonPropertyInfo property = ti.CreateJsonPropertyInfo(typeof(string), nameof(PersonWithRequiredMembers.FirstName)); + property.Get = (obj) => ((PersonWithRequiredMembers)obj).FirstName; + property.Set = (obj, val) => ((PersonWithRequiredMembers)obj).FirstName = (string)val; + ti.Properties[i] = property; + } + else if (ti.Properties[i].Name == nameof(PersonWithRequiredMembers.LastName)) + { + JsonPropertyInfo property = ti.CreateJsonPropertyInfo(typeof(string), nameof(PersonWithRequiredMembers.LastName)); + property.Get = (obj) => ((PersonWithRequiredMembers)obj).LastName; + property.Set = (obj, val) => ((PersonWithRequiredMembers)obj).LastName = (string)val; + ti.Properties[i] = property; + } + } + } + } + } + }; + + var obj = new PersonWithRequiredMembers() + { + FirstName = "foo", + LastName = "bar" + }; + + string json = await Serializer.SerializeWrapper(obj, options); + Assert.Equal("""{"FirstName":"foo","MiddleName":"","LastName":"bar"}""", json); + + json = """{"LastName":"bar"}"""; + PersonWithRequiredMembers deserialized = await Serializer.DeserializeWrapper(json, options); + Assert.Null(deserialized.FirstName); + Assert.Equal("", deserialized.MiddleName); + Assert.Equal("bar", deserialized.LastName); + } + + [Fact] + public async void RequiredNonDeserializablePropertyThrows() + { + JsonSerializerOptions options = new() + { + TypeInfoResolver = new DefaultJsonTypeInfoResolver() + { + Modifiers = + { + (ti) => + { + for (int i = 0; i < ti.Properties.Count; i++) + { + if (ti.Properties[i].Name == nameof(PersonWithRequiredMembers.FirstName)) + { + ti.Properties[i].Set = null; + } + } + } + } + } + }; + + string json = """{"FirstName":"foo","MiddleName":"","LastName":"bar"}"""; + InvalidOperationException exception = await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, options)); + Assert.Contains(nameof(PersonWithRequiredMembers.FirstName), exception.Message); + } + + [Fact] + public async void RequiredInitOnlyPropertyDoesNotThrow() + { + string json = """{"Prop":"foo"}"""; + ClassWithInitOnlyRequiredProperty deserialized = await Serializer.DeserializeWrapper(json); + Assert.Equal("foo", deserialized.Prop); + } + + private class ClassWithInitOnlyRequiredProperty + { + public required string Prop { get; init; } + } + + [Fact] + public async void RequiredExtensionDataPropertyThrows() + { + string json = """{"Foo":"foo","Bar":"bar"}"""; + InvalidOperationException exception = await Assert.ThrowsAsync( + async () => await Serializer.DeserializeWrapper(json)); + Assert.Contains(nameof(ClassWithRequiredExtensionDataProperty.TestExtensionData), exception.Message); + } + + private class ClassWithRequiredExtensionDataProperty + { + [JsonExtensionData] + public required Dictionary? TestExtensionData { get; set; } + } + } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj index d68f600d0ca832..2bd76ae43071f8 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj @@ -25,10 +25,6 @@ - - - - @@ -159,6 +155,7 @@ + @@ -236,10 +233,15 @@ - + + + + + + diff --git a/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.txt b/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.txt index 2d77a903d9f54e..93dd3423e9b827 100644 --- a/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.txt +++ b/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.txt @@ -43,6 +43,8 @@ CannotChangeAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatform CannotChangeAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' on 'System.Diagnostics.Process.MinWorkingSet.set(System.IntPtr)' changed from '[SupportedOSPlatformAttribute("freebsd")]' in the contract to '[SupportedOSPlatformAttribute("freebsd")]' in the implementation. CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.IO.FileStream.Lock(System.Int64, System.Int64)' changed from '[UnsupportedOSPlatformAttribute("ios")]' in the contract to '[UnsupportedOSPlatformAttribute("freebsd")]' in the implementation. CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.IO.FileStream.Unlock(System.Int64, System.Int64)' changed from '[UnsupportedOSPlatformAttribute("ios")]' in the contract to '[UnsupportedOSPlatformAttribute("freebsd")]' in the implementation. +CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute' exists on 'System.Linq.EnumerableQuery..ctor(System.Collections.Generic.IEnumerable)' in the contract but not the implementation. +CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute' exists on 'System.Linq.EnumerableQuery..ctor(System.Linq.Expressions.Expression)' in the contract but not the implementation. CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Net.Http.HttpClientHandler.Proxy' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Numerics.Vector.CopyTo(System.Span)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Numerics.Vector.CopyTo(System.Span)' in the contract but not the implementation. @@ -107,6 +109,8 @@ CannotChangeAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatform CannotChangeAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' on 'System.Diagnostics.Process.MinWorkingSet.set(System.IntPtr)' changed from '[SupportedOSPlatformAttribute("freebsd")]' in the contract to '[SupportedOSPlatformAttribute("freebsd")]' in the implementation. CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.X509Certificates.PublicKey.GetDSAPublicKey()' changed from '[UnsupportedOSPlatformAttribute("ios")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. Compat issues with assembly System.Core: +CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute' exists on 'System.Linq.EnumerableQuery..ctor(System.Collections.Generic.IEnumerable)' in the contract but not the implementation. +CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute' exists on 'System.Linq.EnumerableQuery..ctor(System.Linq.Expressions.Expression)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.Aes' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.AesManaged' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.ECCurve' in the contract but not the implementation. @@ -121,6 +125,9 @@ CannotChangeAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatform Compat issues with assembly System.IO.FileSystem: CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.IO.FileStream.Lock(System.Int64, System.Int64)' changed from '[UnsupportedOSPlatformAttribute("ios")]' in the contract to '[UnsupportedOSPlatformAttribute("freebsd")]' in the implementation. CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.IO.FileStream.Unlock(System.Int64, System.Int64)' changed from '[UnsupportedOSPlatformAttribute("ios")]' in the contract to '[UnsupportedOSPlatformAttribute("freebsd")]' in the implementation. +Compat issues with assembly System.Linq.Queryable: +CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute' exists on 'System.Linq.EnumerableQuery..ctor(System.Collections.Generic.IEnumerable)' in the contract but not the implementation. +CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute' exists on 'System.Linq.EnumerableQuery..ctor(System.Linq.Expressions.Expression)' in the contract but not the implementation. Compat issues with assembly System.Net.Http: CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Net.Http.HttpClientHandler.Proxy' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. Compat issues with assembly System.Net.Security: @@ -196,4 +203,4 @@ Compat issues with assembly System.Security.Cryptography.X509Certificates: CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.X509Certificates.PublicKey.GetDSAPublicKey()' changed from '[UnsupportedOSPlatformAttribute("ios")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. Compat issues with assembly System.Text.Json: CannotMakeTypeAbstract : Type 'System.Text.Json.Serialization.Metadata.JsonTypeInfo' is abstract in the implementation but is not abstract in the contract. -Total Issues: 184 +Total Issues: 190 diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index af3c4a5d6fe45a..18b04c046cf07f 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -414,12 +414,23 @@ + + + + + + + + + + + + - @@ -445,31 +456,19 @@ - - + + - - - - - - + + Condition="'$(TargetOS)' == 'linux' and '$(TargetArchitecture)' == 'arm64'" /> @@ -477,7 +476,6 @@ - @@ -524,7 +522,6 @@ - @@ -538,7 +535,6 @@ - @@ -546,10 +542,7 @@ - - - @@ -564,12 +557,6 @@ - - - - - - @@ -585,12 +572,11 @@ + - - + diff --git a/src/mono/mono/mini/cpu-ppc.mdesc b/src/mono/mono/mini/cpu-ppc.mdesc index 1edf5696dd7523..c92495c356fa51 100644 --- a/src/mono/mono/mini/cpu-ppc.mdesc +++ b/src/mono/mono/mini/cpu-ppc.mdesc @@ -348,4 +348,4 @@ atomic_cas_i4: src1:b src2:i src3:i dest:i len:38 liverange_start: len:0 liverange_end: len:0 -gc_safe_point: len:0 +gc_safe_point: clob:c src1:i len:40 diff --git a/src/mono/mono/mini/cpu-ppc64.mdesc b/src/mono/mono/mini/cpu-ppc64.mdesc index 8bc1fccaaa3049..4dca1bb3ab43cf 100644 --- a/src/mono/mono/mini/cpu-ppc64.mdesc +++ b/src/mono/mono/mini/cpu-ppc64.mdesc @@ -417,4 +417,4 @@ atomic_cas_i8: src1:b src2:i src3:i dest:i len:38 liverange_start: len:0 liverange_end: len:0 -gc_safe_point: len:0 +gc_safe_point: clob:c src1:i len:40 diff --git a/src/mono/mono/mini/mini-ppc.c b/src/mono/mono/mini/mini-ppc.c index 5f014f921145a3..30dc899ab6969b 100644 --- a/src/mono/mono/mini/mini-ppc.c +++ b/src/mono/mono/mini/mini-ppc.c @@ -4574,9 +4574,24 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) MONO_VARINFO (cfg, ins->inst_c0)->live_range_end = code - cfg->native_code; break; } - case OP_GC_SAFE_POINT: + case OP_GC_SAFE_POINT: { + guint8 *br; + ppc_ldr (code, ppc_r0, 0, ins->sreg1); + ppc_cmpi (code, 0, 0, ppc_r0, 0); + br = code; + ppc_bc (code, PPC_BR_TRUE, PPC_BR_EQ, 0); + mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ID, + GUINT_TO_POINTER (MONO_JIT_ICALL_mono_threads_state_poll)); + if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) { + ppc_load_func (code, PPC_CALL_REG, 0); + ppc_mtlr (code, PPC_CALL_REG); + ppc_blrl (code); + } else { + ppc_bl (code, 0); + } + ppc_patch (br, code); break; - + } default: g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__); g_assert_not_reached (); diff --git a/src/mono/sample/wasm/browser-eventpipe/Wasm.Browser.EventPipe.Sample.csproj b/src/mono/sample/wasm/browser-eventpipe/Wasm.Browser.EventPipe.Sample.csproj index 94253eaed38346..49f5718f12972a 100644 --- a/src/mono/sample/wasm/browser-eventpipe/Wasm.Browser.EventPipe.Sample.csproj +++ b/src/mono/sample/wasm/browser-eventpipe/Wasm.Browser.EventPipe.Sample.csproj @@ -14,7 +14,7 @@ - false + true diff --git a/src/mono/wasm/runtime/diagnostics/server_pthread/ipc-protocol/base-parser.ts b/src/mono/wasm/runtime/diagnostics/server_pthread/ipc-protocol/base-parser.ts index 6ac893185ac92a..2129fc76e601c7 100644 --- a/src/mono/wasm/runtime/diagnostics/server_pthread/ipc-protocol/base-parser.ts +++ b/src/mono/wasm/runtime/diagnostics/server_pthread/ipc-protocol/base-parser.ts @@ -113,6 +113,19 @@ const Parser = { result[i] = (buf[j + 2 * i + 1] << 8) | buf[j + 2 * i]; } advancePos(pos, length * 2); + + /* Trim trailing nul character(s) that are added by the protocol */ + let trailingNulStart = -1; + for (let i = result.length - 1; i >= 0; i--) { + if (result[i] === 0) { + trailingNulStart = i; + } else { + break; + } + } + if (trailingNulStart >= 0) + result.splice(trailingNulStart); + return String.fromCharCode.apply(null, result); } }; diff --git a/src/mono/wasm/runtime/diagnostics/server_pthread/streaming-session.ts b/src/mono/wasm/runtime/diagnostics/server_pthread/streaming-session.ts index 938db52bd29fb3..8d7209a98482c1 100644 --- a/src/mono/wasm/runtime/diagnostics/server_pthread/streaming-session.ts +++ b/src/mono/wasm/runtime/diagnostics/server_pthread/streaming-session.ts @@ -57,10 +57,17 @@ function providersStringFromObject(providers: EventPipeCollectTracingCommandProv function keywordsToHexString(k: [number, number]): string { const lo = k[0]; const hi = k[1]; - const lo_hex = lo.toString(16); - const hi_hex = hi.toString(16); + const lo_hex = leftPad(lo.toString(16), "0", 8); + const hi_hex = leftPad(hi.toString(16), "0", 8); return hi_hex + lo_hex; } + + function leftPad(s: string, fill: string, width: number): string { + if (s.length >= width) + return s; + const prefix = fill.repeat(width - s.length); + return prefix + s; + } } diff --git a/src/native/libs/System.Net.Security.Native/pal_gssapi.c b/src/native/libs/System.Net.Security.Native/pal_gssapi.c index 2430e540a5d191..a325b1ac5aec84 100644 --- a/src/native/libs/System.Net.Security.Native/pal_gssapi.c +++ b/src/native/libs/System.Net.Security.Native/pal_gssapi.c @@ -276,7 +276,7 @@ uint32_t NetSecurityNative_ImportPrincipalName(uint32_t* minorStatus, uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus, GssCredId* claimantCredHandle, GssCtxId** contextHandle, - uint32_t isNtlm, + uint32_t packageType, GssName* targetName, uint32_t reqFlags, uint8_t* inputBytes, @@ -288,7 +288,7 @@ uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus, return NetSecurityNative_InitSecContextEx(minorStatus, claimantCredHandle, contextHandle, - isNtlm, + packageType, NULL, 0, targetName, @@ -303,7 +303,7 @@ uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus, uint32_t NetSecurityNative_InitSecContextEx(uint32_t* minorStatus, GssCredId* claimantCredHandle, GssCtxId** contextHandle, - uint32_t isNtlm, + uint32_t packageType, void* cbt, int32_t cbtSize, GssName* targetName, @@ -316,7 +316,7 @@ uint32_t NetSecurityNative_InitSecContextEx(uint32_t* minorStatus, { assert(minorStatus != NULL); assert(contextHandle != NULL); - assert(isNtlm == 0 || isNtlm == 1); + assert(packageType == PAL_GSS_NEGOTIATE || packageType == PAL_GSS_NTLM || packageType == PAL_GSS_KERBEROS); assert(targetName != NULL); assert(inputBytes != NULL || inputLength == 0); assert(outBuffer != NULL); @@ -330,27 +330,33 @@ uint32_t NetSecurityNative_InitSecContextEx(uint32_t* minorStatus, #if HAVE_GSS_SPNEGO_MECHANISM gss_OID krbMech = GSS_KRB5_MECHANISM; gss_OID desiredMech; - if (isNtlm) + if (packageType == PAL_GSS_NTLM) { desiredMech = GSS_NTLM_MECHANISM; } + else if (packageType == PAL_GSS_KERBEROS) + { + desiredMech = GSS_KRB5_MECHANISM; + } else { desiredMech = GSS_SPNEGO_MECHANISM; } #else gss_OID krbMech = (gss_OID)(unsigned long)gss_mech_krb5; - gss_OID_desc gss_mech_OID_desc; - if (isNtlm) + gss_OID desiredMech; + if (packageType == PAL_GSS_NTLM) + { + desiredMech = &gss_mech_ntlm_OID_desc; + } + else if (packageType == PAL_GSS_KERBEROS) { - gss_mech_OID_desc = gss_mech_ntlm_OID_desc; + desiredMech = gss_mech_krb5; } else { - gss_mech_OID_desc = gss_mech_spnego_OID_desc; + desiredMech = &gss_mech_spnego_OID_desc; } - - gss_OID desiredMech = &gss_mech_OID_desc; #endif GssBuffer inputToken = {.length = inputLength, .value = inputBytes}; @@ -379,7 +385,7 @@ uint32_t NetSecurityNative_InitSecContextEx(uint32_t* minorStatus, retFlags, NULL); - *isNtlmUsed = (isNtlm || majorStatus != GSS_S_COMPLETE || gss_oid_equal(outmech, krbMech) == 0) ? 1 : 0; + *isNtlmUsed = (packageType == PAL_GSS_NTLM || majorStatus != GSS_S_COMPLETE || gss_oid_equal(outmech, krbMech) == 0) ? 1 : 0; NetSecurityNative_MoveBuffer(&gssBuffer, outBuffer); return majorStatus; @@ -598,7 +604,7 @@ uint32_t NetSecurityNative_VerifyMic(uint32_t* minorStatus, } static uint32_t AcquireCredWithPassword(uint32_t* minorStatus, - int32_t isNtlm, + int32_t packageType, GssName* desiredName, char* password, uint32_t passwdLen, @@ -606,34 +612,39 @@ static uint32_t AcquireCredWithPassword(uint32_t* minorStatus, GssCredId** outputCredHandle) { assert(minorStatus != NULL); - assert(isNtlm == 1 || isNtlm == 0); + assert(packageType == PAL_GSS_NEGOTIATE || packageType == PAL_GSS_NTLM || packageType == PAL_GSS_KERBEROS); assert(desiredName != NULL); assert(password != NULL); assert(outputCredHandle != NULL); assert(*outputCredHandle == NULL); #if HAVE_GSS_SPNEGO_MECHANISM - (void)isNtlm; // unused + (void)packageType; // unused // Specifying GSS_SPNEGO_MECHANISM as a desiredMech on OSX fails. - gss_OID_set desiredMech = GSS_C_NO_OID_SET; + gss_OID_set desiredMechSet = GSS_C_NO_OID_SET; #else gss_OID_desc gss_mech_OID_desc; - if (isNtlm) + gss_OID desiredMech; + if (packageType == PAL_GSS_NTLM) + { + desiredMech = &gss_mech_ntlm_OID_desc; + } + else if (packageType == PAL_GSS_KERBEROS) { - gss_mech_OID_desc = gss_mech_ntlm_OID_desc; + desiredMech = gss_mech_krb5; } else { - gss_mech_OID_desc = gss_mech_spnego_OID_desc; + desiredMech = &gss_mech_spnego_OID_desc; } - gss_OID_set_desc gss_mech_OID_set_desc = {.count = 1, .elements = &gss_mech_OID_desc}; - gss_OID_set desiredMech = &gss_mech_OID_set_desc; + gss_OID_set_desc gss_mech_OID_set_desc = {.count = 1, .elements = desiredMech}; + gss_OID_set desiredMechSet = &gss_mech_OID_set_desc; #endif GssBuffer passwordBuffer = {.length = passwdLen, .value = password}; uint32_t majorStatus = gss_acquire_cred_with_password( - minorStatus, desiredName, &passwordBuffer, 0, desiredMech, credUsage, outputCredHandle, NULL, NULL); + minorStatus, desiredName, &passwordBuffer, 0, desiredMechSet, credUsage, outputCredHandle, NULL, NULL); return majorStatus; } @@ -652,14 +663,14 @@ uint32_t NetSecurityNative_AcquireAcceptorCred(uint32_t* minorStatus, } uint32_t NetSecurityNative_InitiateCredWithPassword(uint32_t* minorStatus, - int32_t isNtlm, + int32_t packageType, GssName* desiredName, char* password, uint32_t passwdLen, GssCredId** outputCredHandle) { return AcquireCredWithPassword( - minorStatus, isNtlm, desiredName, password, passwdLen, GSS_C_INITIATE, outputCredHandle); + minorStatus, packageType, desiredName, password, passwdLen, GSS_C_INITIATE, outputCredHandle); } uint32_t NetSecurityNative_IsNtlmInstalled() diff --git a/src/native/libs/System.Net.Security.Native/pal_gssapi.h b/src/native/libs/System.Net.Security.Native/pal_gssapi.h index 3bd8a59098378b..10be636c7789e5 100644 --- a/src/native/libs/System.Net.Security.Native/pal_gssapi.h +++ b/src/native/libs/System.Net.Security.Native/pal_gssapi.h @@ -40,6 +40,13 @@ typedef enum PAL_GSS_C_DELEG_POLICY_FLAG = 0x8000 } PAL_GssFlags; +typedef enum +{ + PAL_GSS_NEGOTIATE = 0, + PAL_GSS_NTLM = 1, + PAL_GSS_KERBEROS = 2, +} PAL_GssPackageType; + /* Issue: #7342 Disable padded warning which occurs in case of 32-bit builds @@ -111,7 +118,7 @@ Shims the gss_init_sec_context method with SPNEGO oids. PALEXPORT uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus, GssCredId* claimantCredHandle, GssCtxId** contextHandle, - uint32_t isNtlm, + uint32_t packageType, GssName* targetName, uint32_t reqFlags, uint8_t* inputBytes, @@ -123,7 +130,7 @@ PALEXPORT uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus, PALEXPORT uint32_t NetSecurityNative_InitSecContextEx(uint32_t* minorStatus, GssCredId* claimantCredHandle, GssCtxId** contextHandle, - uint32_t isNtlm, + uint32_t packageType, void* cbt, int32_t cbtSize, GssName* targetName, @@ -195,7 +202,7 @@ PALEXPORT uint32_t NetSecurityNative_VerifyMic(uint32_t* minorStatus, Shims the gss_acquire_cred_with_password method with GSS_C_INITIATE. */ PALEXPORT uint32_t NetSecurityNative_InitiateCredWithPassword(uint32_t* minorStatus, - int32_t isNtlm, + int32_t packageType, GssName* desiredName, char* password, uint32_t passwdLen, diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_ecc_import_export.c b/src/native/libs/System.Security.Cryptography.Native/pal_ecc_import_export.c index fedac751ab6019..99b2a58817d034 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_ecc_import_export.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_ecc_import_export.c @@ -327,10 +327,11 @@ int32_t CryptoNative_EcKeyCreateByKeyParameters(EC_KEY** key, const char* oid, u if (!nid) return -1; - *key = EC_KEY_new_by_curve_name(nid); - if (!(*key)) + EC_KEY* tmpKey = EC_KEY_new_by_curve_name(nid); + if (tmpKey == NULL) return -1; + int ret = 0; BIGNUM* dBn = NULL; BIGNUM* qxBn = NULL; BIGNUM* qyBn = NULL; @@ -344,7 +345,7 @@ int32_t CryptoNative_EcKeyCreateByKeyParameters(EC_KEY** key, const char* oid, u if (!qxBn || !qyBn) goto error; - if (!EC_KEY_set_public_key_affine_coordinates(*key, qxBn, qyBn)) + if (!EC_KEY_set_public_key_affine_coordinates(tmpKey, qxBn, qyBn)) goto error; // Set private key (optional) @@ -354,12 +355,12 @@ int32_t CryptoNative_EcKeyCreateByKeyParameters(EC_KEY** key, const char* oid, u if (!dBn) goto error; - if (!EC_KEY_set_private_key(*key, dBn)) + if (!EC_KEY_set_private_key(tmpKey, dBn)) goto error; } // Validate key - if (!EC_KEY_check_key(*key)) + if (!EC_KEY_check_key(tmpKey)) goto error; } @@ -373,10 +374,10 @@ int32_t CryptoNative_EcKeyCreateByKeyParameters(EC_KEY** key, const char* oid, u if (!dBn) goto error; - if (!EC_KEY_set_private_key(*key, dBn)) + if (!EC_KEY_set_private_key(tmpKey, dBn)) goto error; - const EC_GROUP* group = EC_KEY_get0_group(*key); + const EC_GROUP* group = EC_KEY_get0_group(tmpKey); if (!group) goto error; @@ -389,27 +390,26 @@ int32_t CryptoNative_EcKeyCreateByKeyParameters(EC_KEY** key, const char* oid, u if (!EC_POINT_mul(group, pubG, dBn, NULL, NULL, NULL)) goto error; - if (!EC_KEY_set_public_key(*key, pubG)) + if (!EC_KEY_set_public_key(tmpKey, pubG)) goto error; - if (!EC_KEY_check_key(*key)) + if (!EC_KEY_check_key(tmpKey)) goto error; } // Success - return 1; + *key = tmpKey; + tmpKey = NULL; + ret = 1; error: if (qxBn) BN_free(qxBn); if (qyBn) BN_free(qyBn); if (dBn) BN_clear_free(dBn); if (pubG) EC_POINT_free(pubG); - if (*key) - { - EC_KEY_free(*key); - *key = NULL; - } - return 0; + if (tmpKey) EC_KEY_free(tmpKey); + + return ret; } EC_KEY* CryptoNative_EcKeyCreateByExplicitParameters( @@ -436,6 +436,7 @@ EC_KEY* CryptoNative_EcKeyCreateByExplicitParameters( ERR_clear_error(); EC_KEY* key = NULL; + EC_KEY* ret = NULL; EC_POINT* G = NULL; EC_POINT* pubG = NULL; @@ -570,7 +571,8 @@ EC_KEY* CryptoNative_EcKeyCreateByExplicitParameters( } // Success - return key; + ret = key; + key = NULL; error: if (qxBn) BN_free(qxBn); @@ -587,5 +589,6 @@ EC_KEY* CryptoNative_EcKeyCreateByExplicitParameters( if (pubG) EC_POINT_free(pubG); if (group) EC_GROUP_free(group); if (key) EC_KEY_free(key); - return NULL; + + return ret; } diff --git a/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.il b/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.il new file mode 100644 index 00000000000000..33aa5426827e95 --- /dev/null +++ b/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.il @@ -0,0 +1,151 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +.assembly extern System.Runtime {} +.assembly extern System.Console {} +.assembly GenericCatchInterface {} + +// IL in this file is based on this C# program with a few IL modifications: + +// static class Program +// { +// private static int retCode = 0; +// static int Main() +// { +// try +// { +// try +// { +// throw new MyException(); +// } +// catch (MyException) // IL edit: Change to catch (IMyInterface) +// { +// Console.WriteLine("FAIL"); +// retCode++; +// } +// } +// catch +// { +// Console.WriteLine("PASS"); +// retCode += 50; +// } +// +// GenericCatch(); // IL edit: Change to GenericCatch() +// +// return retCode; +// } +// +// [MethodImpl(MethodImplOptions.NoInlining)] +// static void GenericCatch() where T : Exception // IL edit: Remove constraint +// { +// try +// { +// try +// { +// throw new MyException(); +// } +// catch (T) +// { +// Console.WriteLine("FAIL"); +// retCode++; +// } +// } +// catch +// { +// Console.WriteLine("PASS"); +// retCode += 50; +// } +// } +// } +// interface IMyInterface {} +// class MyException : Exception, IMyInterface {} + + +.class private abstract auto ansi sealed beforefieldinit GenericCatchInterfaceProgram + extends [System.Runtime]System.Object +{ + // + .field private static int32 retCode + + .method private hidebysig static int32 Main() cil managed + { + .entrypoint + .maxstack 2 + IL_0000: newobj instance void MyException::.ctor() + IL_0005: throw + + IL_0006: pop + IL_0007: ldstr "FAIL" + IL_000c: call void [System.Console]System.Console::WriteLine(string) + IL_0011: ldsfld int32 GenericCatchInterfaceProgram::retCode + IL_0016: ldc.i4.1 + IL_0017: add + IL_0018: stsfld int32 GenericCatchInterfaceProgram::retCode + IL_001d: leave.s IL_001f + + IL_001f: leave.s IL_003b + + IL_0021: pop + IL_0022: ldstr "PASS" + IL_0027: call void [System.Console]System.Console::WriteLine(string) + IL_002c: ldsfld int32 GenericCatchInterfaceProgram::retCode + IL_0031: ldc.i4.s 50 + IL_0033: add + IL_0034: stsfld int32 GenericCatchInterfaceProgram::retCode + IL_0039: leave.s IL_003b + + IL_003b: call void GenericCatchInterfaceProgram::GenericCatch() + IL_0040: ldsfld int32 GenericCatchInterfaceProgram::retCode + IL_0045: ret + IL_0046: + .try IL_0000 to IL_0006 catch IMyInterface handler IL_0006 to IL_001f + .try IL_0000 to IL_0021 catch [System.Runtime]System.Object handler IL_0021 to IL_003b + } + + .method private hidebysig static void GenericCatch<([System.Runtime]System.Object) T>() cil managed noinlining + { + .maxstack 2 + IL_0000: newobj instance void MyException::.ctor() + IL_0005: throw + + IL_0006: pop + IL_0007: ldstr "FAIL" + IL_000c: call void [System.Console]System.Console::WriteLine(string) + IL_0011: ldsfld int32 GenericCatchInterfaceProgram::retCode + IL_0016: ldc.i4.1 + IL_0017: add + IL_0018: stsfld int32 GenericCatchInterfaceProgram::retCode + IL_001d: leave.s IL_001f + + IL_001f: leave.s IL_003b + + IL_0021: pop + IL_0022: ldstr "PASS" + IL_0027: call void [System.Console]System.Console::WriteLine(string) + IL_002c: ldsfld int32 GenericCatchInterfaceProgram::retCode + IL_0031: ldc.i4.s 50 + IL_0033: add + IL_0034: stsfld int32 GenericCatchInterfaceProgram::retCode + IL_0039: leave.s IL_003b + + IL_003b: ret + IL_003c: + .try IL_0000 to IL_0006 catch !!T handler IL_0006 to IL_001f + .try IL_0000 to IL_0021 catch [System.Runtime]System.Object handler IL_0021 to IL_003b + } +} + +.class interface private abstract auto ansi IMyInterface {} + +.class private auto ansi beforefieldinit MyException + extends [System.Runtime]System.Exception + implements IMyInterface +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [System.Runtime]System.Exception::.ctor() + IL_0006: ret + } +} \ No newline at end of file diff --git a/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.ilproj b/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.ilproj new file mode 100644 index 00000000000000..1f01486f84882d --- /dev/null +++ b/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.ilproj @@ -0,0 +1,9 @@ + + + Exe + True + + + + + \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_62692/Runtime_62692.cs b/src/tests/JIT/Regression/JitBlue/Runtime_62692/Runtime_62692.cs new file mode 100644 index 00000000000000..aec577db661866 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_62692/Runtime_62692.cs @@ -0,0 +1,63 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; +using System; +using System.Runtime.Intrinsics.X86; + +public unsafe class Runtime_62692 +{ + [MethodImpl(MethodImplOptions.NoInlining)] + static uint Problem1(byte* pSrc, uint data) => Sse42.Crc32(*pSrc, data); + + [MethodImpl(MethodImplOptions.NoInlining)] + static uint Problem2(uint crc, ulong data) => Sse42.Crc32(crc, (uint)(data >> 16)); + + [MethodImpl(MethodImplOptions.NoInlining)] + static uint Problem3(uint crc, uint data) => Sse42.Crc32(crc, (uint)(byte)data); + + [MethodImpl(MethodImplOptions.NoInlining)] + static uint Problem4(uint crc, ulong data) => Sse42.Crc32(crc, (uint)(data >> 16)); + + [MethodImpl(MethodImplOptions.NoInlining)] + static uint Problem5(uint crc, double data) => Sse42.Crc32(crc, (uint)data); + + [MethodImpl(MethodImplOptions.NoInlining)] + static uint Problem6(uint crc, float data) => Sse42.Crc32(crc, (uint)data); + + static int Main() + { + if (Sse42.IsSupported) + { + long a = long.MaxValue; + AssertEqual(Problem1((byte*)&a, 111), 3150215170); + a = 333; + AssertEqual(Problem1((byte*)&a, 44), 2714165716); + AssertEqual(Problem2(uint.MaxValue, 42), 3080238136); + AssertEqual(Problem2(1111, 0xFFFF_FFFF_0000_0001), 3414328792); + AssertEqual(Problem3(1, 0xFFFF_0001), 0); + AssertEqual(Problem4(1111, 0xFFFF_FFFF_0000_0001), 3414328792); + AssertEqual(Problem5(1111, double.MaxValue), 3307008522); + AssertEqual(Problem6(1111, float.MaxValue), 3307008522); + AssertEqual(Problem5(1111, double.MinValue), 3307008522); + AssertEqual(Problem6(1111, float.MinValue), 3307008522); + AssertEqual(Problem5(1111, -0.0), 3307008522); + AssertEqual(Problem6(1111, -0.0f), 3307008522); + } + + Console.WriteLine(retCode); + return retCode; + } + + static int retCode = 100; + + [MethodImpl(MethodImplOptions.NoInlining)] + static void AssertEqual(uint a, uint b, [CallerLineNumber] int line = 0) + { + if (a != b) + { + Console.WriteLine($"{a} != {b}, Line:{line}"); + retCode++; + } + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_62692/Runtime_62692_r.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_62692/Runtime_62692_r.csproj new file mode 100644 index 00000000000000..cff31f0439e03e --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_62692/Runtime_62692_r.csproj @@ -0,0 +1,10 @@ + + + Exe + False + True + + + + + \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_62692/Runtime_62692_ro.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_62692/Runtime_62692_ro.csproj new file mode 100644 index 00000000000000..83ea5c091b8795 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_62692/Runtime_62692_ro.csproj @@ -0,0 +1,10 @@ + + + Exe + True + True + + + + + \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_72845/Runtime_72845.fs b/src/tests/JIT/Regression/JitBlue/Runtime_72845/Runtime_72845.fs new file mode 100644 index 00000000000000..15015e0dd5b5e3 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_72845/Runtime_72845.fs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// OSR method with modifiable this + +[] +let main _ = + let l1 = [0 .. 100000] + let l2 = [0 .. 100000] + let eq = l1 = l2 + printfn $"Lists equal: {eq}" + if eq then 100 else -1 diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_72845/Runtime_72845.fsproj b/src/tests/JIT/Regression/JitBlue/Runtime_72845/Runtime_72845.fsproj new file mode 100644 index 00000000000000..f8ba1e7f4a2575 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_72845/Runtime_72845.fsproj @@ -0,0 +1,14 @@ + + + Exe + + + True + True + True + $(NetCoreAppToolCurrent) + + + + + diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 0352b6bc49395c..1cda405752640b 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -1369,24 +1369,6 @@ - - - - - - - - - - - - - - - - - - @@ -1454,6 +1436,9 @@ + + https://github.com/dotnet/runtime/issues/72827 + https://github.com/dotnet/runtime/issues/71656 @@ -1820,7 +1805,7 @@ needs triage - needs triage + FSharp Test needs triage @@ -1963,6 +1948,9 @@ https://github.com/dotnet/runtime/issues/72016 + + FSharp Test + needs triage diff --git a/src/tests/nativeaot/SmokeTests/ComWrappers/ComWrappers.cs b/src/tests/nativeaot/SmokeTests/ComWrappers/ComWrappers.cs index b62eca4f86e499..1d56b5bf5542b8 100644 --- a/src/tests/nativeaot/SmokeTests/ComWrappers/ComWrappers.cs +++ b/src/tests/nativeaot/SmokeTests/ComWrappers/ComWrappers.cs @@ -83,7 +83,7 @@ public static void TestComInteropRegistrationRequired() CaptureComPointer(target); throw new Exception("Cannot work without ComWrappers.RegisterForMarshalling called"); } - catch (InvalidOperationException) + catch (NotSupportedException) { } } diff --git a/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs b/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs index 76440c785363bd..3bc01acb80df99 100644 --- a/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs +++ b/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs @@ -30,6 +30,8 @@ public static int Main() new BringUpTest().ToString(); } + TestGenericExceptions(); + int counter = 0; AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionEventHandler; @@ -50,8 +52,8 @@ public static int Main() Console.WriteLine("Exception caught!"); if (e.Message != "My exception") { - Console.WriteLine("Unexpected exception message!"); - return Fail; + Console.WriteLine("Unexpected exception message!"); + return Fail; } string stackTrace = e.StackTrace; @@ -65,7 +67,7 @@ public static int Main() try { - g.myObjectField = new Object(); + g.myObjectField = new Object(); } catch (NullReferenceException) { @@ -75,14 +77,14 @@ public static int Main() try { - try - { - g.myField++; - } - finally - { - counter++; - } + try + { + g.myField++; + } + finally + { + counter++; + } } catch (NullReferenceException) { @@ -99,8 +101,8 @@ public static int Main() Console.WriteLine("Exception caught via filter!"); if (e.Message != "Testing filter") { - Console.WriteLine("Unexpected exception message!"); - return Fail; + Console.WriteLine("Unexpected exception message!"); + return Fail; } counter++; } @@ -209,6 +211,36 @@ static void ThrowExcThroughMethodsWithFinalizers2(string caller) } } + static void TestGenericExceptions() + { + if (CatchGenericException(100, 0) != 42) + { + Environment.Exit(Fail); + } + + try + { + CatchGenericException(100, 0); + } + catch (DivideByZeroException) + { + return; + } + Environment.Exit(Fail); + } + + static int CatchGenericException(int a, int b) where T : Exception + { + try + { + return a / b; + } + catch (T) + { + return 42; + } + } + static bool FilterWithStackTrace(Exception e) { var stackTrace = new StackTrace(0, true);