diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 1a146e9cf20..c7b4b6da3e2 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -10307,22 +10307,73 @@ and TcAndBuildFixedExpr (cenv: cenv) env (overallPatTy, fixedExpr, overallExprTy let g = cenv.g + // Search for GetPinnableReference (like https://learn.microsoft.com/en-us/dotnet/api/system.span-1.getpinnablereference?view=net-7.0) + // on the target expression, and, if it exists, call it + let tryBuildGetPinnableReferenceCall () = + let getPinnableReferenceMInfo = + TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AllResults cenv env mBinding env.eAccessRights "GetPinnableReference" overallExprTy + |> List.tryFind (fun mInfo -> + // GetPinnableReference must be a parameterless method with a byref or inref return value + match mInfo.GetParamDatas(cenv.amap, mBinding, mInfo.FormalMethodInst), mInfo.GetFSharpReturnType(cenv.amap, mBinding, mInfo.FormalMethodInst) with + | [[]], retTy when isByrefTy g retTy && mInfo.IsInstance -> true + | _ -> false + ) + + match getPinnableReferenceMInfo with + | Some mInfo -> + checkLanguageFeatureAndRecover g.langVersion LanguageFeature.ExtendedFixedBindings mBinding + + let mInst = FreshenMethInfo mBinding mInfo + let pinnableReference, actualRetTy = BuildPossiblyConditionalMethodCall cenv env NeverMutates mBinding false mInfo NormalValUse mInst [ fixedExpr ] [] None + + let elemTy = destByrefTy g actualRetTy + UnifyTypes cenv env mBinding (mkNativePtrTy g elemTy) overallPatTy + + // For value types: + // let ptr: nativeptr = + // let pinned x = &(expr: 'a).GetPinnableReference() + // (nativeint) x + + // For reference types: + // let ptr: nativeptr = + // if isNull expr then + // (nativeint) expr + // else + // let pinned x = &(expr: 'a).GetPinnableReference() + // (nativeint) x + + let pinnedBinding = + mkCompGenLetIn mBinding "pinnedByref" actualRetTy pinnableReference (fun (v, ve) -> + v.SetIsFixed() + mkConvToNativeInt g ve mBinding) + + if isStructTy g overallExprTy then + Some pinnedBinding + else + Some (mkNullTest g mBinding fixedExpr pinnedBinding fixedExpr) + | None -> + None + warning(PossibleUnverifiableCode mBinding) match overallExprTy with | ty when isByrefTy g ty -> - let okByRef = - match stripDebugPoints (stripExpr fixedExpr) with - | Expr.Op (op, tyargs, args, _) -> + // Feature ExtendedFixedBindings allows *any* byref to be used with fixed bindings, whereas the old logic only allowed a specific + // subset. This preserves the old logic when the feature is turned off. + if not (g.langVersion.SupportsFeature LanguageFeature.ExtendedFixedBindings) then + let okByRef = + match stripDebugPoints (stripExpr fixedExpr) with + | Expr.Op (op, tyargs, args, _) -> match op, tyargs, args with | TOp.ValFieldGetAddr (rfref, _), _, [_] -> not rfref.Tycon.IsStructOrEnumTycon | TOp.ILAsm ([ I_ldflda fspec], _), _, _ -> fspec.DeclaringType.Boxity = ILBoxity.AsObject | TOp.ILAsm ([ I_ldelema _], _), _, _ -> true | TOp.RefAddrGet _, _, _ -> true | _ -> false - | _ -> false - if not okByRef then - error(Error(FSComp.SR.tcFixedNotAllowed(), mBinding)) + | _ -> false + + if not okByRef then + errorR (languageFeatureError g.langVersion LanguageFeature.ExtendedFixedBindings mBinding) let elemTy = destByrefTy g overallExprTy UnifyTypes cenv env mBinding (mkNativePtrTy g elemTy) overallPatTy @@ -10331,20 +10382,29 @@ and TcAndBuildFixedExpr (cenv: cenv) env (overallPatTy, fixedExpr, overallExprTy mkConvToNativeInt g ve mBinding) | ty when isStringTy g ty -> - let charPtrTy = mkNativePtrTy g g.char_ty - UnifyTypes cenv env mBinding charPtrTy overallPatTy - // - // let ptr: nativeptr = - // let pinned s = str - // (nativeptr)s + get_OffsettoStringData() - - mkCompGenLetIn mBinding "pinnedString" g.string_ty fixedExpr (fun (v, ve) -> - v.SetIsFixed() - let addrOffset = BuildOffsetToStringData cenv env mBinding - let stringAsNativeInt = mkConvToNativeInt g ve mBinding - let plusOffset = Expr.Op (TOp.ILAsm ([ AI_add ], [ g.nativeint_ty ]), [], [stringAsNativeInt; addrOffset], mBinding) - // check for non-null - mkNullTest g mBinding ve plusOffset ve) + let getPinnableRefCall = + if g.langVersion.SupportsFeature LanguageFeature.PreferStringGetPinnableReference then + tryBuildGetPinnableReferenceCall () + else + None + + match getPinnableRefCall with + | Some expr -> expr + | None -> + let charPtrTy = mkNativePtrTy g g.char_ty + UnifyTypes cenv env mBinding charPtrTy overallPatTy + // + // let ptr: nativeptr = + // let pinned s = str + // (nativeptr)s + get_OffsettoStringData() + + mkCompGenLetIn mBinding "pinnedString" g.string_ty fixedExpr (fun (v, ve) -> + v.SetIsFixed() + let addrOffset = BuildOffsetToStringData cenv env mBinding + let stringAsNativeInt = mkConvToNativeInt g ve mBinding + let plusOffset = Expr.Op (TOp.ILAsm ([ AI_add ], [ g.nativeint_ty ]), [], [stringAsNativeInt; addrOffset], mBinding) + // check for non-null + mkNullTest g mBinding ve plusOffset ve) | ty when isArray1DTy g ty -> let elemTy = destArrayTy g overallExprTy @@ -10377,7 +10437,10 @@ and TcAndBuildFixedExpr (cenv: cenv) env (overallPatTy, fixedExpr, overallExprTy zero) zero) - | _ -> error(Error(FSComp.SR.tcFixedNotAllowed(), mBinding)) + | _ -> + match tryBuildGetPinnableReferenceCall () with + | Some expr -> expr + | None -> error(Error(FSComp.SR.tcFixedNotAllowed(), mBinding)) /// Binding checking code, for all bindings including let bindings, let-rec bindings, member bindings and object-expression bindings and diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 9cb32180fca..a9276e1fb00 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1381,7 +1381,7 @@ tcTupleStructMismatch,"One tuple type is a struct tuple, the other is a referenc 3203,parsInvalidUseOfRec,"Invalid use of 'rec' keyword" 3204,tcStructUnionMultiCaseDistinctFields,"If a multicase union type is a struct, then all union cases must have unique names. For example: 'type A = B of b: int | C of c: int'." 3206,CallerMemberNameIsOverriden,"The CallerMemberNameAttribute applied to parameter '%s' will have no effect. It is overridden by the CallerFilePathAttribute." -3207,tcFixedNotAllowed,"Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string'" +3207,tcFixedNotAllowed,"Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference()" 3208,tcCouldNotFindOffsetToStringData,"Could not find method System.Runtime.CompilerServices.OffsetToStringData in references when building 'fixed' expression." 3209,chkNoByrefAddressOfLocal,"The address of the variable '%s' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope." 3210,tcNamedActivePattern,"%s is an active pattern and cannot be treated as a discriminated union case with named fields." @@ -1586,6 +1586,8 @@ featureStrictIndentation,"Raises errors on incorrect indentation, allows better featureConstraintIntersectionOnFlexibleTypes,"Constraint intersection on flexible types" featureChkNotTailRecursive,"Raises warnings if a member or function has the 'TailCall' attribute, but is not being used in a tail recursive way." featureWhileBang,"'while!' expression" +featureExtendedFixedBindings,"extended fixed bindings for byref and GetPinnableReference" +featurePreferStringGetPinnableReference,"prefer String.GetPinnableReference in fixed bindings" 3353,fsiInvalidDirective,"Invalid directive '#%s %s'" 3354,tcNotAFunctionButIndexerNamedIndexingNotYetEnabled,"This value supports indexing, e.g. '%s.[index]'. The syntax '%s[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation." 3354,tcNotAFunctionButIndexerIndexingNotYetEnabled,"This expression supports indexing, e.g. 'expr.[index]'. The syntax 'expr[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation." diff --git a/src/Compiler/Facilities/DiagnosticsLogger.fs b/src/Compiler/Facilities/DiagnosticsLogger.fs index ef90d556a2b..374a8ddb8bd 100644 --- a/src/Compiler/Facilities/DiagnosticsLogger.fs +++ b/src/Compiler/Facilities/DiagnosticsLogger.fs @@ -817,12 +817,15 @@ type internal SuppressLanguageFeatureCheck = | Yes | No +let internal languageFeatureError (langVersion: LanguageVersion) (langFeature: LanguageFeature) (m: range) = + let featureStr = LanguageVersion.GetFeatureString langFeature + let currentVersionStr = langVersion.SpecifiedVersionString + let suggestedVersionStr = LanguageVersion.GetFeatureVersionString langFeature + Error(FSComp.SR.chkFeatureNotLanguageSupported (featureStr, currentVersionStr, suggestedVersionStr), m) + let private tryLanguageFeatureErrorAux (langVersion: LanguageVersion) (langFeature: LanguageFeature) (m: range) = if not (langVersion.SupportsFeature langFeature) then - let featureStr = LanguageVersion.GetFeatureString langFeature - let currentVersionStr = langVersion.SpecifiedVersionString - let suggestedVersionStr = LanguageVersion.GetFeatureVersionString langFeature - Some(Error(FSComp.SR.chkFeatureNotLanguageSupported (featureStr, currentVersionStr, suggestedVersionStr), m)) + Some(languageFeatureError langVersion langFeature m) else None diff --git a/src/Compiler/Facilities/DiagnosticsLogger.fsi b/src/Compiler/Facilities/DiagnosticsLogger.fsi index 03b27b922a0..2fe91400fbd 100644 --- a/src/Compiler/Facilities/DiagnosticsLogger.fsi +++ b/src/Compiler/Facilities/DiagnosticsLogger.fsi @@ -432,6 +432,8 @@ type SuppressLanguageFeatureCheck = | Yes | No +val languageFeatureError: langVersion: LanguageVersion -> langFeature: LanguageFeature -> m: range -> exn + val checkLanguageFeatureError: langVersion: LanguageVersion -> langFeature: LanguageFeature -> m: range -> unit val checkLanguageFeatureAndRecover: langVersion: LanguageVersion -> langFeature: LanguageFeature -> m: range -> unit diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs index 342c4f55a39..9a60cc17136 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fs +++ b/src/Compiler/Facilities/LanguageFeatures.fs @@ -77,6 +77,8 @@ type LanguageFeature = | WarningWhenTailRecAttributeButNonTailRecUsage | UnmanagedConstraintCsharpInterop | WhileBang + | ExtendedFixedBindings + | PreferStringGetPinnableReference /// LanguageVersion management type LanguageVersion(versionText) = @@ -177,6 +179,8 @@ type LanguageVersion(versionText) = LanguageFeature.ConstraintIntersectionOnFlexibleTypes, previewVersion LanguageFeature.UnmanagedConstraintCsharpInterop, previewVersion LanguageFeature.WhileBang, previewVersion + LanguageFeature.ExtendedFixedBindings, previewVersion + LanguageFeature.PreferStringGetPinnableReference, previewVersion ] static let defaultLanguageVersion = LanguageVersion("default") @@ -309,6 +313,8 @@ type LanguageVersion(versionText) = | LanguageFeature.WarningWhenTailRecAttributeButNonTailRecUsage -> FSComp.SR.featureChkNotTailRecursive () | LanguageFeature.UnmanagedConstraintCsharpInterop -> FSComp.SR.featureUnmanagedConstraintCsharpInterop () | LanguageFeature.WhileBang -> FSComp.SR.featureWhileBang () + | LanguageFeature.ExtendedFixedBindings -> FSComp.SR.featureExtendedFixedBindings () + | LanguageFeature.PreferStringGetPinnableReference -> FSComp.SR.featurePreferStringGetPinnableReference () /// Get a version string associated with the given feature. static member GetFeatureVersionString feature = diff --git a/src/Compiler/Facilities/LanguageFeatures.fsi b/src/Compiler/Facilities/LanguageFeatures.fsi index 5b0b990c546..c1cb2378d4e 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fsi +++ b/src/Compiler/Facilities/LanguageFeatures.fsi @@ -67,6 +67,8 @@ type LanguageFeature = | WarningWhenTailRecAttributeButNonTailRecUsage | UnmanagedConstraintCsharpInterop | WhileBang + | ExtendedFixedBindings + | PreferStringGetPinnableReference /// LanguageVersion management type LanguageVersion = diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index fc3a30f3eb3..64fb8d7bff1 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -287,6 +287,11 @@ více typů podporuje měrné jednotky + + extended fixed bindings for byref and GetPinnableReference + extended fixed bindings for byref and GetPinnableReference + + Extended string interpolation similar to C# raw string literals. Extended string interpolation similar to C# raw string literals. @@ -392,6 +397,11 @@ správa balíčků + + prefer String.GetPinnableReference in fixed bindings + prefer String.GetPinnableReference in fixed bindings + + binary formatting for integers formátování typu binary pro integery @@ -7848,8 +7858,8 @@ - Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' - Neplatné použití fixed. fixed se dá použít jenom v deklaraci ve tvaru use x = fixed expr, kde výraz je pole, adresa pole nebo adresa prvku pole nebo řetězce. + Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference() + Neplatné použití fixed. fixed se dá použít jenom v deklaraci ve tvaru use x = fixed expr, kde výraz je pole, adresa pole nebo adresa prvku pole nebo řetězce. diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index 35bfa8d21ca..a0f465874b5 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -287,6 +287,11 @@ Maßeinheitenunterstützung durch weitere Typen + + extended fixed bindings for byref and GetPinnableReference + extended fixed bindings for byref and GetPinnableReference + + Extended string interpolation similar to C# raw string literals. Extended string interpolation similar to C# raw string literals. @@ -392,6 +397,11 @@ Paketverwaltung + + prefer String.GetPinnableReference in fixed bindings + prefer String.GetPinnableReference in fixed bindings + + binary formatting for integers binäre Formatierung für ganze Zahlen @@ -7848,8 +7858,8 @@ - Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' - Ungültige Verwendung von "fixed". "fixed" darf ausschließlich in einer Deklaration der Form "use x = fixed expr" verwendet werden. Dabei ist der Ausdruck ein Array, die Adresse eines Felds, die Adresse eines Arrayelements oder eine Zeichenfolge. + Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference() + Ungültige Verwendung von "fixed". "fixed" darf ausschließlich in einer Deklaration der Form "use x = fixed expr" verwendet werden. Dabei ist der Ausdruck ein Array, die Adresse eines Felds, die Adresse eines Arrayelements oder eine Zeichenfolge. diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index f5625cba24a..687fa4d6524 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -287,6 +287,11 @@ más tipos admiten las unidades de medida + + extended fixed bindings for byref and GetPinnableReference + extended fixed bindings for byref and GetPinnableReference + + Extended string interpolation similar to C# raw string literals. Extended string interpolation similar to C# raw string literals. @@ -392,6 +397,11 @@ administración de paquetes + + prefer String.GetPinnableReference in fixed bindings + prefer String.GetPinnableReference in fixed bindings + + binary formatting for integers formato binario para enteros @@ -7848,8 +7858,8 @@ - Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' - Uso no válido de 'fixed'. 'fixed' debe utilizarse solo en una declaración del formulario 'use x = fixed expr' donde la expresión es una matriz, la dirección de un campo, la dirección de un elemento de matriz o una cadena' + Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference() + Uso no válido de 'fixed'. 'fixed' debe utilizarse solo en una declaración del formulario 'use x = fixed expr' donde la expresión es una matriz, la dirección de un campo, la dirección de un elemento de matriz o una cadena' diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 8153986e712..014f244f72f 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -287,6 +287,11 @@ d'autres types prennent en charge les unités de mesure + + extended fixed bindings for byref and GetPinnableReference + extended fixed bindings for byref and GetPinnableReference + + Extended string interpolation similar to C# raw string literals. Extended string interpolation similar to C# raw string literals. @@ -392,6 +397,11 @@ Package Management + + prefer String.GetPinnableReference in fixed bindings + prefer String.GetPinnableReference in fixed bindings + + binary formatting for integers mise en forme binaire pour les entiers @@ -7848,8 +7858,8 @@ - Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' - Utilisation non valide de 'fixed'. Utilisez uniquement 'fixed' dans une déclaration de la forme 'use x = fixed expr' où l'expression est un tableau, l'adresse d'un champ, l'adresse d'un élément de tableau ou une chaîne + Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference() + Utilisation non valide de 'fixed'. Utilisez uniquement 'fixed' dans une déclaration de la forme 'use x = fixed expr' où l'expression est un tableau, l'adresse d'un champ, l'adresse d'un élément de tableau ou une chaîne diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 9a97fec4e59..ef5aee938b7 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -287,6 +287,11 @@ più tipi supportano le unità di misura + + extended fixed bindings for byref and GetPinnableReference + extended fixed bindings for byref and GetPinnableReference + + Extended string interpolation similar to C# raw string literals. Extended string interpolation similar to C# raw string literals. @@ -392,6 +397,11 @@ gestione pacchetti + + prefer String.GetPinnableReference in fixed bindings + prefer String.GetPinnableReference in fixed bindings + + binary formatting for integers formattazione binaria per interi @@ -7848,8 +7858,8 @@ - Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' - Uso non valido di 'fixed'. 'fixed' può essere usato solo in una dichiarazione in formato 'use x = fixed expr', in cui l'espressione è una matrice, l'indirizzo di un campo, l'indirizzo di un elemento di matrice oppure una stringa + Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference() + Uso non valido di 'fixed'. 'fixed' può essere usato solo in una dichiarazione in formato 'use x = fixed expr', in cui l'espressione è una matrice, l'indirizzo di un campo, l'indirizzo di un elemento di matrice oppure una stringa diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 19d71ce59f6..5e0d4816843 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -287,6 +287,11 @@ 単位をサポートするその他の型 + + extended fixed bindings for byref and GetPinnableReference + extended fixed bindings for byref and GetPinnableReference + + Extended string interpolation similar to C# raw string literals. Extended string interpolation similar to C# raw string literals. @@ -392,6 +397,11 @@ パッケージの管理 + + prefer String.GetPinnableReference in fixed bindings + prefer String.GetPinnableReference in fixed bindings + + binary formatting for integers 整数のバイナリ形式 @@ -7848,8 +7858,8 @@ - Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' - 'fixed' の使い方が正しくありません。'fixed' を使用できるのは書式 'use x = fixed expr' の宣言内だけで、この式は配列、フィールドのアドレス、配列要素のアドレス、または文字列です + Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference() + 'fixed' の使い方が正しくありません。'fixed' を使用できるのは書式 'use x = fixed expr' の宣言内だけで、この式は配列、フィールドのアドレス、配列要素のアドレス、または文字列です diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index c713e1b8a21..17f6a656387 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -287,6 +287,11 @@ 더 많은 형식이 측정 단위를 지원함 + + extended fixed bindings for byref and GetPinnableReference + extended fixed bindings for byref and GetPinnableReference + + Extended string interpolation similar to C# raw string literals. Extended string interpolation similar to C# raw string literals. @@ -392,6 +397,11 @@ 패키지 관리 + + prefer String.GetPinnableReference in fixed bindings + prefer String.GetPinnableReference in fixed bindings + + binary formatting for integers 정수에 대한 이진 서식 지정 @@ -7848,8 +7858,8 @@ - Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' - 'fixed'를 잘못 사용했습니다. 'fixed'는 식이 배열, 필드의 주소, 배열 요소 또는 문자열의 주소인 경우 'use x = fixed expr' 형식의 선언에만 사용할 수 있습니다. + Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference() + 'fixed'를 잘못 사용했습니다. 'fixed'는 식이 배열, 필드의 주소, 배열 요소 또는 문자열의 주소인 경우 'use x = fixed expr' 형식의 선언에만 사용할 수 있습니다. diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index 92677828fe2..33e6ceac663 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -287,6 +287,11 @@ więcej typów obsługuje jednostki miary + + extended fixed bindings for byref and GetPinnableReference + extended fixed bindings for byref and GetPinnableReference + + Extended string interpolation similar to C# raw string literals. Extended string interpolation similar to C# raw string literals. @@ -392,6 +397,11 @@ zarządzanie pakietami + + prefer String.GetPinnableReference in fixed bindings + prefer String.GetPinnableReference in fixed bindings + + binary formatting for integers formatowanie danych binarnych dla liczb całkowitych @@ -7848,8 +7858,8 @@ - Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' - Nieprawidłowe użycie wyrażenia „fixed”. Wyrażenia „fixed” można użyć tylko w deklaracji w postaci „use x = fixed expr”, gdzie wyrażenie jest tablicą, adresem pola, adresem elementu tablicy lub ciągiem + Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference() + Nieprawidłowe użycie wyrażenia „fixed”. Wyrażenia „fixed” można użyć tylko w deklaracji w postaci „use x = fixed expr”, gdzie wyrażenie jest tablicą, adresem pola, adresem elementu tablicy lub ciągiem diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 1d66f5bb290..5122f8a160a 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -287,6 +287,11 @@ mais tipos dão suporte para unidades de medida + + extended fixed bindings for byref and GetPinnableReference + extended fixed bindings for byref and GetPinnableReference + + Extended string interpolation similar to C# raw string literals. Extended string interpolation similar to C# raw string literals. @@ -392,6 +397,11 @@ gerenciamento de pacotes + + prefer String.GetPinnableReference in fixed bindings + prefer String.GetPinnableReference in fixed bindings + + binary formatting for integers formatação binária para números inteiros @@ -7848,8 +7858,8 @@ - Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' - Uso inválido da 'fixed'. 'fixed' somente pode ser usada em uma declaração no formato 'use x = fixed expr', em que a expressão é uma matriz, o endereço de um campo, o endereço de um elemento de matriz ou uma cadeia de caracteres + Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference() + Uso inválido da 'fixed'. 'fixed' somente pode ser usada em uma declaração no formato 'use x = fixed expr', em que a expressão é uma matriz, o endereço de um campo, o endereço de um elemento de matriz ou uma cadeia de caracteres diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 414c8aab909..8e1430bd842 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -287,6 +287,11 @@ другие типы поддерживают единицы измерения + + extended fixed bindings for byref and GetPinnableReference + extended fixed bindings for byref and GetPinnableReference + + Extended string interpolation similar to C# raw string literals. Extended string interpolation similar to C# raw string literals. @@ -392,6 +397,11 @@ управление пакетами + + prefer String.GetPinnableReference in fixed bindings + prefer String.GetPinnableReference in fixed bindings + + binary formatting for integers двоичное форматирование для целых чисел @@ -7848,8 +7858,8 @@ - Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' - Недопустимое использование выражения "fixed". Выражение "fixed" можно использовать только в объявлении формы "use x = fixed expr", где выражение является массивом, адресом поля, адресом элемента массива или строки. + Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference() + Недопустимое использование выражения "fixed". Выражение "fixed" можно использовать только в объявлении формы "use x = fixed expr", где выражение является массивом, адресом поля, адресом элемента массива или строки. diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index 8af91856df7..ab4079f393a 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -287,6 +287,11 @@ tür daha ölçü birimlerini destekler + + extended fixed bindings for byref and GetPinnableReference + extended fixed bindings for byref and GetPinnableReference + + Extended string interpolation similar to C# raw string literals. Extended string interpolation similar to C# raw string literals. @@ -392,6 +397,11 @@ paket yönetimi + + prefer String.GetPinnableReference in fixed bindings + prefer String.GetPinnableReference in fixed bindings + + binary formatting for integers tamsayılar için ikili biçim @@ -7848,8 +7858,8 @@ - Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' - Geçersiz 'fixed' kullanımı. 'fixed' yalnızca 'use x = fixed expr' biçimindeki bir bildirimde kullanılabilir. Burada ifade bir dizi, bir alanın adresi, bir dizi öğesinin adresi veya bir dizedir + Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference() + Geçersiz 'fixed' kullanımı. 'fixed' yalnızca 'use x = fixed expr' biçimindeki bir bildirimde kullanılabilir. Burada ifade bir dizi, bir alanın adresi, bir dizi öğesinin adresi veya bir dizedir diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 657aa764818..6c6d4861b46 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -287,6 +287,11 @@ 更多类型支持度量单位 + + extended fixed bindings for byref and GetPinnableReference + extended fixed bindings for byref and GetPinnableReference + + Extended string interpolation similar to C# raw string literals. Extended string interpolation similar to C# raw string literals. @@ -392,6 +397,11 @@ 包管理 + + prefer String.GetPinnableReference in fixed bindings + prefer String.GetPinnableReference in fixed bindings + + binary formatting for integers 整数的二进制格式设置 @@ -7848,8 +7858,8 @@ - Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' - 无效的 "fixed" 使用。"fixed" 只能用在 "use x = fixed expr" 形式的声明中,其中表达式为数组、字段的地址、数组元素或字符串的地址 + Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference() + 无效的 "fixed" 使用。"fixed" 只能用在 "use x = fixed expr" 形式的声明中,其中表达式为数组、字段的地址、数组元素或字符串的地址 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 1644d510773..281190c3b17 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -287,6 +287,11 @@ 更多支援測量單位的類型 + + extended fixed bindings for byref and GetPinnableReference + extended fixed bindings for byref and GetPinnableReference + + Extended string interpolation similar to C# raw string literals. Extended string interpolation similar to C# raw string literals. @@ -392,6 +397,11 @@ 套件管理 + + prefer String.GetPinnableReference in fixed bindings + prefer String.GetPinnableReference in fixed bindings + + binary formatting for integers 整數的二進位格式化 @@ -7848,8 +7858,8 @@ - Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' - 使用 'fixed' 無效。'fixed' 僅能用於格式為 'use x = fixed expr' 的宣告中,其中運算式為陣列、欄位的位址、陣列元素的位址或字串 + Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference() + 使用 'fixed' 無效。'fixed' 僅能用於格式為 'use x = fixed expr' 的宣告中,其中運算式為陣列、欄位的位址、陣列元素的位址或字串 diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/FixedBindings.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/FixedBindings.fs new file mode 100644 index 00000000000..6c1737b9518 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/FixedBindings.fs @@ -0,0 +1,733 @@ +namespace EmittedIL.FixedBindings + +open System.Reflection +open Microsoft.FSharp.NativeInterop +open Xunit +open FSharp.Compiler.Diagnostics +open FSharp.Test +open FSharp.Test.Utilities +open FSharp.Test.Compiler + +module Legacy = + [] + [] + let ``Pin naked string`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinNakedString.fs") + |> withLangVersion langVersion + |> withNoWarn 9 + |> compile + |> verifyIL [""" + .method public static char pinIt(string str) cil managed + { + + .maxstack 5 + .locals init (native int V_0, + string pinned V_1) + IL_0000: ldarg.0 + IL_0001: stloc.1 + IL_0002: ldarg.0 + IL_0003: brfalse.s IL_000f + + IL_0005: ldarg.0 + IL_0006: conv.i + IL_0007: call int32 [runtime]System.Runtime.CompilerServices.RuntimeHelpers::get_OffsetToStringData() + IL_000c: add + IL_000d: br.s IL_0010 + + IL_000f: ldarg.0 + IL_0010: stloc.0 + IL_0011: ldloc.0 + IL_0012: ldc.i4.0 + IL_0013: conv.i + IL_0014: sizeof [runtime]System.Char + IL_001a: mul + IL_001b: add + IL_001c: ldobj [runtime]System.Char + IL_0021: ret + } """ ] + + [] + [] + [] + let ``Pin naked array`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinNakedArray.fs") + |> withLangVersion langVersion + |> withNoWarn 9 + |> compile + |> verifyIL [""" + .method public static char pinIt(char[] arr) cil managed + { + + .maxstack 5 + .locals init (native int V_0, + char& pinned V_1) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001b + + IL_0003: ldarg.0 + IL_0004: call int32 [FSharp.Core]Microsoft.FSharp.Collections.ArrayModule::Length(!!0[]) + IL_0009: brfalse.s IL_0017 + + IL_000b: ldarg.0 + IL_000c: ldc.i4.0 + IL_000d: ldelema [runtime]System.Char + IL_0012: stloc.1 + IL_0013: ldloc.1 + IL_0014: conv.i + IL_0015: br.s IL_001d + + IL_0017: ldc.i4.0 + IL_0018: conv.i + IL_0019: br.s IL_001d + + IL_001b: ldc.i4.0 + IL_001c: conv.i + IL_001d: stloc.0 + IL_001e: ldloc.0 + IL_001f: ldc.i4.0 + IL_0020: conv.i + IL_0021: sizeof [runtime]System.Char + IL_0027: mul + IL_0028: add + IL_0029: ldobj [runtime]System.Char + IL_002e: ret + } """ ] + + [] + [] + [] + let ``Pin address of record field`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinAddressOfRecordField.fs") + |> withLangVersion langVersion + |> withNoWarn 9 + |> compileExeAndRun + |> verifyIL [""" + .method public static int32 pinIt(class FixedBindings/Point thing) cil managed + { + + .maxstack 5 + .locals init (native int V_0, + int32& pinned V_1) + IL_0000: ldarg.0 + IL_0001: ldflda int32 FixedBindings/Point::X@ + IL_0006: stloc.1 + IL_0007: ldloc.1 + IL_0008: conv.i + IL_0009: stloc.0 + IL_000a: ldloc.0 + IL_000b: ldc.i4.0 + IL_000c: conv.i + IL_000d: sizeof [runtime]System.Int32 + IL_0013: mul + IL_0014: add + IL_0015: ldobj [runtime]System.Int32 + IL_001a: ret + } """ ] + + [] + [] + [] + let ``Pin address of explicit field on this`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinAddressOfExplicitFieldOnThis.fs") + |> withLangVersion langVersion + |> withNoWarn 9 + |> compileExeAndRun + |> shouldSucceed + |> verifyIL [""" + .method public hidebysig instance int32 + PinIt() cil managed + { + + .maxstack 5 + .locals init (native int V_0, + int32& pinned V_1) + IL_0000: ldarg.0 + IL_0001: ldflda int32 FixedBindings/Point::X + IL_0006: stloc.1 + IL_0007: ldloc.1 + IL_0008: conv.i + IL_0009: stloc.0 + IL_000a: ldloc.0 + IL_000b: ldc.i4.0 + IL_000c: conv.i + IL_000d: sizeof [System.Runtime]System.Int32 + IL_0013: mul + IL_0014: add + IL_0015: ldobj [System.Runtime]System.Int32 + IL_001a: ret + } """ ] + + [] + [] + [] + let ``Pin address of array element`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinAddressOfArrayElement.fs") + |> withLangVersion langVersion + |> withNoWarn 9 + |> compileExeAndRun + |> shouldSucceed + |> verifyIL [""" + .method public static char pinIt(char[] arr) cil managed + { + + .maxstack 5 + .locals init (native int V_0, + char& pinned V_1) + IL_0000: ldarg.0 + IL_0001: ldc.i4.0 + IL_0002: ldelema [runtime]System.Char + IL_0007: stloc.1 + IL_0008: ldloc.1 + IL_0009: conv.i + IL_000a: stloc.0 + IL_000b: ldloc.0 + IL_000c: ldc.i4.0 + IL_000d: conv.i + IL_000e: sizeof [runtime]System.Char + IL_0014: mul + IL_0015: add + IL_0016: ldobj [runtime]System.Char + IL_001b: ret + } """ ] + +module ExtendedFixedBindings = + [] + [] + let ``Pin naked string`` langVersion = + let runtimeSupportsStringGetPinnableReference = + typeof.GetMethods() + |> Seq.exists (fun m -> m.Name = "GetPinnableReference") + +// Sanity check precondition: if .Net Framework were to ever get GetPinnableReference, we'll know here +#if NETCOREAPP3_0_OR_GREATER + Assert.True(runtimeSupportsStringGetPinnableReference) +#else + Assert.False(runtimeSupportsStringGetPinnableReference) +#endif + + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinNakedString.fs") + |> withLangVersion langVersion + |> withNoWarn 9 + |> compile + |> if runtimeSupportsStringGetPinnableReference then + (fun comp -> + comp + |> verifyIL [""" + .method public static char pinIt(string str) cil managed + { + + .maxstack 5 + .locals init (native int V_0, + char& pinned V_1) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_000e + + IL_0003: ldarg.0 + IL_0004: callvirt instance char& modreq([runtime]System.Runtime.InteropServices.InAttribute) [runtime]System.String::GetPinnableReference() + IL_0009: stloc.1 + IL_000a: ldloc.1 + IL_000b: conv.i + IL_000c: br.s IL_000f + + IL_000e: ldarg.0 + IL_000f: stloc.0 + IL_0010: ldloc.0 + IL_0011: ldc.i4.0 + IL_0012: conv.i + IL_0013: sizeof [runtime]System.Char + IL_0019: mul + IL_001a: add + IL_001b: ldobj [runtime]System.Char + IL_0020: ret + } """ ]) + else + (fun comp -> + comp + |> verifyIL [""" + .method public static char pinIt(string str) cil managed + { + + .maxstack 5 + .locals init (native int V_0, + string pinned V_1) + IL_0000: ldarg.0 + IL_0001: stloc.1 + IL_0002: ldarg.0 + IL_0003: brfalse.s IL_000f + + IL_0005: ldarg.0 + IL_0006: conv.i + IL_0007: call int32 [runtime]System.Runtime.CompilerServices.RuntimeHelpers::get_OffsetToStringData() + IL_000c: add + IL_000d: br.s IL_0010 + + IL_000f: ldarg.0 + IL_0010: stloc.0 + IL_0011: ldloc.0 + IL_0012: ldc.i4.0 + IL_0013: conv.i + IL_0014: sizeof [runtime]System.Char + IL_001a: mul + IL_001b: add + IL_001c: ldobj [runtime]System.Char + IL_0021: ret + } """ ]) + + [] + let ``Pin int byref of parameter`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinIntByrefOfParameter.fs") + |> withLangVersion langVersion + |> withNoWarn 9 + |> compileExeAndRun + |> shouldSucceed + |> verifyIL [""" + .method public static int32 pinIt(int32& thing) cil managed + { + + .maxstack 5 + .locals init (native int V_0, + int32& pinned V_1) + IL_0000: ldarg.0 + IL_0001: stloc.1 + IL_0002: ldarg.0 + IL_0003: conv.i + IL_0004: stloc.0 + IL_0005: ldloc.0 + IL_0006: ldc.i4.0 + IL_0007: conv.i + IL_0008: sizeof [runtime]System.Int32 + IL_000e: mul + IL_000f: add + IL_0010: ldobj [runtime]System.Int32 + IL_0015: ret + } """ ] + + [] + let ``Pin int byref of local variable`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinIntByrefOfLocalVariable.fs") + |> withLangVersion langVersion + |> withNoWarn 9 + |> compileExeAndRun + |> shouldSucceed + |> verifyIL [""" + .method public static void pinIt(int32 x) cil managed + { + + .maxstack 5 + .locals init (int32 V_0, + native int V_1, + int32& pinned V_2, + int32 V_3) + IL_0000: ldarg.0 + IL_0001: ldc.i4.1 + IL_0002: add + IL_0003: stloc.0 + IL_0004: ldloca.s V_0 + IL_0006: stloc.2 + IL_0007: ldloca.s V_0 + IL_0009: conv.i + IL_000a: stloc.1 + IL_000b: ldloc.1 + IL_000c: ldc.i4.0 + IL_000d: conv.i + IL_000e: sizeof [runtime]System.Int32 + IL_0014: mul + IL_0015: add + IL_0016: ldobj [runtime]System.Int32 + IL_001b: stloc.3 + IL_001c: ldloc.3 + IL_001d: ldloc.0 + IL_001e: beq.s IL_0027 + + IL_0020: call !!0 FixedBindings::fail() + IL_0025: pop + IL_0026: ret + + IL_0027: ret + } """ ] + +#if NETCOREAPP + [] + let ``Pin Span via manual GetPinnableReference call`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinSpanWithManualGetPinnableReferenceCall.fs") + |> withLangVersion langVersion + |> withNoWarn 9 + |> compileExeAndRun + |> shouldSucceed + |> verifyIL [""" + .method public static char pinIt(valuetype [runtime]System.Span`1 thing) cil managed + { + + .maxstack 5 + .locals init (native int V_0, + char& pinned V_1) + IL_0000: ldarga.s thing + IL_0002: call instance !0& valuetype [runtime]System.Span`1::GetPinnableReference() + IL_0007: stloc.1 + IL_0008: ldloc.1 + IL_0009: conv.i + IL_000a: stloc.0 + IL_000b: ldloc.0 + IL_000c: ldc.i4.0 + IL_000d: conv.i + IL_000e: sizeof [runtime]System.Char + IL_0014: mul + IL_0015: add + IL_0016: ldobj [runtime]System.Char + IL_001b: ret + } """ ] + + [] + let ``Pin Span`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinSpan.fs") + |> withLangVersion langVersion + |> withNoWarn 9 + |> compileExeAndRun + |> shouldSucceed + |> verifyIL [""" + .method public static char pinIt(valuetype [runtime]System.Span`1 thing) cil managed + { + + .maxstack 5 + .locals init (native int V_0, + char& pinned V_1) + IL_0000: ldarga.s thing + IL_0002: call instance !0& valuetype [runtime]System.Span`1::GetPinnableReference() + IL_0007: stloc.1 + IL_0008: ldloc.1 + IL_0009: conv.i + IL_000a: stloc.0 + IL_000b: ldloc.0 + IL_000c: ldc.i4.0 + IL_000d: conv.i + IL_000e: sizeof [runtime]System.Char + IL_0014: mul + IL_0015: add + IL_0016: ldobj [runtime]System.Char + IL_001b: ret + } """ ] + + [] + let ``Pin generic ReadOnlySpan`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinGenericReadOnlySpan.fs") + |> withLangVersion langVersion + |> withNoWarn 9 + |> compileExeAndRun + |> shouldSucceed + |> verifyIL [""" + .method public static !!a pinIt(valuetype [runtime]System.ReadOnlySpan`1 thing) cil managed + { + .param type a + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (native int V_0, + !!a& pinned V_1) + IL_0000: ldarga.s thing + IL_0002: call instance !0& modreq([runtime]System.Runtime.InteropServices.InAttribute) valuetype [runtime]System.ReadOnlySpan`1::GetPinnableReference() + IL_0007: stloc.1 + IL_0008: ldloc.1 + IL_0009: conv.i + IL_000a: stloc.0 + IL_000b: ldloc.0 + IL_000c: ldc.i4.0 + IL_000d: conv.i + IL_000e: sizeof !!a + IL_0014: mul + IL_0015: add + IL_0016: ldobj !!a + IL_001b: ret + } """ ] +#endif + + [] + let ``Pin type with method GetPinnableReference : unit -> byref`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithGetPinnableReferenceReturningByref.fs") + |> withLangVersion langVersion + |> withNoWarn 9 + |> compileExeAndRun + |> shouldSucceed + |> verifyIL [""" + .method public static int32 pinIt(class FixedExpressions/RefField`1 thing) cil managed + { + + .maxstack 5 + .locals init (native int V_0, + int32& pinned V_1) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_000e + + IL_0003: ldarg.0 + IL_0004: callvirt instance !0& class FixedExpressions/RefField`1::GetPinnableReference() + IL_0009: stloc.1 + IL_000a: ldloc.1 + IL_000b: conv.i + IL_000c: br.s IL_000f + + IL_000e: ldarg.0 + IL_000f: stloc.0 + IL_0010: ldloc.0 + IL_0011: ldc.i4.0 + IL_0012: conv.i + IL_0013: sizeof [runtime]System.Int32 + IL_0019: mul + IL_001a: add + IL_001b: ldobj [runtime]System.Int32 + IL_0020: ret + } """ ] + + [] + let ``Pin type with method GetPinnableReference : unit -> inref`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithGetPinnableReferenceReturningInref.fs") + |> withLangVersion langVersion + |> withNoWarn 9 + |> compileExeAndRun + |> shouldSucceed + |> verifyIL [""" + .method public static int32 pinIt(class FixedBindings/ReadonlyRefField`1 thing) cil managed + { + + .maxstack 5 + .locals init (native int V_0, + int32& pinned V_1) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_000e + + IL_0003: ldarg.0 + IL_0004: callvirt instance !0& modreq([runtime]System.Runtime.InteropServices.InAttribute) class FixedBindings/ReadonlyRefField`1::GetPinnableReference() + IL_0009: stloc.1 + IL_000a: ldloc.1 + IL_000b: conv.i + IL_000c: br.s IL_000f + + IL_000e: ldarg.0 + IL_000f: stloc.0 + IL_0010: ldloc.0 + IL_0011: ldc.i4.0 + IL_0012: conv.i + IL_0013: sizeof [runtime]System.Int32 + IL_0019: mul + IL_001a: add + IL_001b: ldobj [runtime]System.Int32 + IL_0020: ret + } """ ] + + [] + let ``Pin struct type with method GetPinnableReference : unit -> byref`` langVersion = + // Effectively tests the same thing as the test with Span, but this works on .NET Framework + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinStructTypeWithGetPinnableReferenceReturningByref.fs") + |> withLangVersion langVersion + |> withNoWarn 9 + |> compileExeAndRun + |> shouldSucceed + |> verifyIL [""" + .method public static !!a pinIt(valuetype FixedBindings/ArrayElementRef`1 thing) cil managed + { + .param type a + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (native int V_0, + !!a& pinned V_1) + IL_0000: ldarga.s thing + IL_0002: call instance !0& valuetype FixedBindings/ArrayElementRef`1::GetPinnableReference() + IL_0007: stloc.1 + IL_0008: ldloc.1 + IL_0009: conv.i + IL_000a: stloc.0 + IL_000b: ldloc.0 + IL_000c: ldc.i4.0 + IL_000d: conv.i + IL_000e: sizeof !!a + IL_0014: mul + IL_0015: add + IL_0016: ldobj !!a + IL_001b: ret + } """ ] + + [] + let ``Pin C# type with method GetPinnableReference : unit -> byref`` langVersion = + let csLib = + CSharpFromPath (__SOURCE_DIRECTORY__ ++ "PinCSharpTypeWithGetPinnableReferenceReturningByref.cs") |> withName "CsLib" + + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinCSharpTypeWithGetPinnableReferenceReturningByref.fs") + |> withLangVersion langVersion + |> withReferences [csLib] + |> withNoWarn 9 + |> compileExeAndRun + |> shouldSucceed + |> verifyIL [""" + .method public static int32 pinIt(class [CsLib]PinnableReference`1 thing) cil managed + { + + .maxstack 5 + .locals init (native int V_0, + int32& pinned V_1) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_000e + + IL_0003: ldarg.0 + IL_0004: callvirt instance !0& class [CsLib]PinnableReference`1::GetPinnableReference() + IL_0009: stloc.1 + IL_000a: ldloc.1 + IL_000b: conv.i + IL_000c: br.s IL_000f + + IL_000e: ldarg.0 + IL_000f: stloc.0 + IL_0010: ldloc.0 + IL_0011: ldc.i4.0 + IL_0012: conv.i + IL_0013: sizeof [runtime]System.Int32 + IL_0019: mul + IL_001a: add + IL_001b: ldobj [runtime]System.Int32 + IL_0020: ret + } """ ] + +#if NETCOREAPP + [] + let ``Pin C# byref struct type with method GetPinnableReference : unit -> byref`` langVersion = + // TODO: Could be a good idea to test a version of this type written in F# too once we get ref fields in byref-like structs: + // https://github.com/fsharp/fslang-suggestions/issues/1143 + let csLib = + CSharpFromPath (__SOURCE_DIRECTORY__ ++ "PinCSharpByrefStructTypeWithGetPinnableReferenceReturningByref.cs") + |> withName "CsLib" + |> withCSharpLanguageVersion CSharpLanguageVersion.CSharp11 + + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinCSharpByrefStructTypeWithGetPinnableReferenceReturningByref.fs") + |> withLangVersion langVersion + |> withReferences [csLib] + |> withNoWarn 9 + |> compileExeAndRun + |> shouldSucceed + |> verifyIL [""" + .method public static int32 pinIt(valuetype [CsLib]CsLib.RefField`1 refField) cil managed + { + + .maxstack 5 + .locals init (native int V_0, + int32& pinned V_1) + IL_0000: ldarga.s refField + IL_0002: call instance !0& valuetype [CsLib]CsLib.RefField`1::GetPinnableReference() + IL_0007: stloc.1 + IL_0008: ldloc.1 + IL_0009: conv.i + IL_000a: stloc.0 + IL_000b: ldloc.0 + IL_000c: ldc.i4.0 + IL_000d: conv.i + IL_000e: sizeof [runtime]System.Int32 + IL_0014: mul + IL_0015: add + IL_0016: ldobj [runtime]System.Int32 + IL_001b: ret + } """ ] +#endif + + [] + let ``Pin type with C# style extension method GetPinnableReference : unit -> byref`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithCSharpStyleExtensionGetPinnableReferenceReturningByref.fs") + |> withLangVersion langVersion + |> withNoWarn 9 + |> compileExeAndRun + |> shouldSucceed + |> verifyIL [""" + .method public static !!a pinIt(class FixedBindings/RefField`1 thing) cil managed + { + .param type a + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (native int V_0, + !!a& pinned V_1) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_000e + + IL_0003: ldarg.0 + IL_0004: call !!0& FixedBindings/RefFieldExtensions::GetPinnableReference(class FixedBindings/RefField`1) + IL_0009: stloc.1 + IL_000a: ldloc.1 + IL_000b: conv.i + IL_000c: br.s IL_000f + + IL_000e: ldarg.0 + IL_000f: stloc.0 + IL_0010: ldloc.0 + IL_0011: ldc.i4.0 + IL_0012: conv.i + IL_0013: sizeof !!a + IL_0019: mul + IL_001a: add + IL_001b: ldobj !!a + IL_0020: ret + } """ ] + + [] + let ``Pin type with F# style extension method GetPinnableReference : unit -> byref`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithFSharpStyleExtensionGetPinnableReferenceReturningByref.fs") + |> withLangVersion langVersion + |> withNoWarn 9 + |> compileExeAndRun + |> shouldSucceed + |> verifyIL [""" + .method public static !!T pinIt(class FixedBindings/RefField`1 thing) cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (native int V_0, + !!T& pinned V_1) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_000e + + IL_0003: ldarg.0 + IL_0004: callvirt instance !0& class FixedBindings/RefField`1::GetPinnableReference() + IL_0009: stloc.1 + IL_000a: ldloc.1 + IL_000b: conv.i + IL_000c: br.s IL_000f + + IL_000e: ldarg.0 + IL_000f: stloc.0 + IL_0010: ldloc.0 + IL_0011: ldc.i4.0 + IL_0012: conv.i + IL_0013: sizeof !!T + IL_0019: mul + IL_001a: add + IL_001b: ldobj !!T + IL_0020: ret + } """ ] + + [] + let ``Pin null value of type with GetPinnableReference`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinNullValueOfTypeWithGetPinnableReference.fs") + |> withLangVersion langVersion + |> withNoWarn 9 + |> compileExeAndRun + |> shouldSucceed + |> verifyIL [""" + .method public static bool pinIt(class FixedExpressions/RefField`1 thing) cil managed + { + + .maxstack 4 + .locals init (int32& pinned V_0) + IL_0000: ldc.i8 0x0 + IL_0009: conv.i + IL_000a: ldarg.0 + IL_000b: brfalse.s IL_0018 + + IL_000d: ldarg.0 + IL_000e: callvirt instance !0& class FixedExpressions/RefField`1::GetPinnableReference() + IL_0013: stloc.0 + IL_0014: ldloc.0 + IL_0015: conv.i + IL_0016: br.s IL_0019 + + IL_0018: ldarg.0 + IL_0019: ceq + IL_001b: ret + } +"""] diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinAddressOfArrayElement.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinAddressOfArrayElement.fs new file mode 100644 index 00000000000..b6eb61aea92 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinAddressOfArrayElement.fs @@ -0,0 +1,10 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +let pinIt (arr: char[]) = + use ptr = fixed &arr[0] + NativePtr.get ptr 0 + +let x = [|'a';'b';'c'|] +let y = pinIt x +if y <> 'a' then failwithf "y did not equal first element of x" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinAddressOfExplicitFieldOnThis.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinAddressOfExplicitFieldOnThis.fs new file mode 100644 index 00000000000..7320c742cad --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinAddressOfExplicitFieldOnThis.fs @@ -0,0 +1,16 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +type Point = + val mutable X: int + val mutable Y: int + + new(x: int, y: int) = { X = x; Y = y } + + member this.PinIt() = + use ptr = fixed &this.X + NativePtr.get ptr 0 + +let p = Point(10,20) +let xCopy = p.PinIt() +if xCopy <> p.X then failwith "xCopy was not equal to X" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinAddressOfRecordField.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinAddressOfRecordField.fs new file mode 100644 index 00000000000..1aad39790a7 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinAddressOfRecordField.fs @@ -0,0 +1,12 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +type Point = { mutable X: int; mutable Y: int } + +let pinIt (thing: Point) = + use ptr = fixed &thing.X + NativePtr.get ptr 0 + +let p = { X = 10; Y = 20 } +let xCopy = pinIt p +if xCopy <> p.X then failwith "xCopy was not equal to X" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinCSharpByrefStructTypeWithGetPinnableReferenceReturningByref.cs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinCSharpByrefStructTypeWithGetPinnableReferenceReturningByref.cs new file mode 100644 index 00000000000..b9c22320bb0 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinCSharpByrefStructTypeWithGetPinnableReferenceReturningByref.cs @@ -0,0 +1,20 @@ +namespace CsLib +{ + public ref struct RefField + { + private readonly ref T _value; + + public T Value + { + get => _value; + set => _value = value; + } + + public RefField(ref T value) + { + this._value = ref value; + } + + public ref T GetPinnableReference() => ref _value; + } +} \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinCSharpByrefStructTypeWithGetPinnableReferenceReturningByref.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinCSharpByrefStructTypeWithGetPinnableReferenceReturningByref.fs new file mode 100644 index 00000000000..a39cb2a8432 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinCSharpByrefStructTypeWithGetPinnableReferenceReturningByref.fs @@ -0,0 +1,15 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop +open CsLib + +let pinIt (refField: RefField) = + use ptr = fixed refField + NativePtr.get ptr 0 + +[] +let main _ = + let mutable x = 42 + let refToX = new RefField<_>(&x) + let y = pinIt refToX + if y <> x then failwith "y did not equal x" + 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinCSharpTypeWithGetPinnableReferenceReturningByref.cs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinCSharpTypeWithGetPinnableReferenceReturningByref.cs new file mode 100644 index 00000000000..bbab6d945d3 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinCSharpTypeWithGetPinnableReferenceReturningByref.cs @@ -0,0 +1,20 @@ +public class PinnableReference +{ + private T _value; + + public T Value + { + get => _value; + set => _value = value; + } + + public PinnableReference(T value) + { + this._value = value; + } + + public ref T GetPinnableReference() + { + return ref _value; + } +} \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinCSharpTypeWithGetPinnableReferenceReturningByref.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinCSharpTypeWithGetPinnableReferenceReturningByref.fs new file mode 100644 index 00000000000..d56c5cff860 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinCSharpTypeWithGetPinnableReferenceReturningByref.fs @@ -0,0 +1,14 @@ +module FixedExpressions +open Microsoft.FSharp.NativeInterop +open System + +let pinIt (thing: PinnableReference) = + use ptr = fixed thing + NativePtr.get ptr 0 + +[] +let main _ = + let x = PinnableReference(42) + let y = pinIt x + if y <> x.Value then failwith "y did not equal x value" + 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinGenericReadOnlySpan.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinGenericReadOnlySpan.fs new file mode 100644 index 00000000000..d63f946ba10 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinGenericReadOnlySpan.fs @@ -0,0 +1,14 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop +open System + +let pinIt (thing: ReadOnlySpan<'a>) = + use ptr = fixed thing + NativePtr.get ptr 0 + +[] +let main _ = + let span = ReadOnlySpan("The quick brown fox jumped over the lazy dog".ToCharArray()) + let x = pinIt span + if x <> 'T' then failwith "x did not equal the first char of the span" + 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinIntByrefOfLocalVariable.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinIntByrefOfLocalVariable.fs new file mode 100644 index 00000000000..ce08ac07fe6 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinIntByrefOfLocalVariable.fs @@ -0,0 +1,15 @@ +module FixedBindings +open System.Runtime.CompilerServices +open Microsoft.FSharp.NativeInterop + +[] +let fail () = + failwith "thingCopy was not the same as thing" + +let pinIt (x: int) = + let mutable thing = x + 1 + use ptr = fixed &thing + let thingCopy = NativePtr.get ptr 0 + if thingCopy <> thing then fail () + +pinIt 100 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinIntByrefOfParameter.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinIntByrefOfParameter.fs new file mode 100644 index 00000000000..419ab9dc950 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinIntByrefOfParameter.fs @@ -0,0 +1,10 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +let pinIt (thing: byref) = + use ptr = fixed &thing + NativePtr.get ptr 0 + +let mutable x = 42 +let xCopy = pinIt &x +if x <> xCopy then failwith "xCopy was not the same as x" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinNakedArray.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinNakedArray.fs new file mode 100644 index 00000000000..a8853cb24eb --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinNakedArray.fs @@ -0,0 +1,6 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +let pinIt (arr: char[]) = + use ptr = fixed arr + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinNakedString.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinNakedString.fs new file mode 100644 index 00000000000..95d259363d3 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinNakedString.fs @@ -0,0 +1,6 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +let pinIt (str: string) = + use ptr = fixed str + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinNullValueOfTypeWithGetPinnableReference.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinNullValueOfTypeWithGetPinnableReference.fs new file mode 100644 index 00000000000..d7c20ed43b0 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinNullValueOfTypeWithGetPinnableReference.fs @@ -0,0 +1,22 @@ +module FixedExpressions +open Microsoft.FSharp.NativeInterop +open System.Runtime.CompilerServices +open System + +type RefField<'T>(_value) = + let mutable _value = _value + member this.Value = _value + [] + member this.GetPinnableReference () : byref<'T> = &_value + +let pinIt (thing: RefField) = + use ptr = fixed thing + NativePtr.isNullPtr ptr + +[] +let main _ = + if (pinIt Unchecked.defaultof>) then + printfn "Success - null guard worked" + else + failwith "Test failed - null guard did not work" + 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinSpan.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinSpan.fs new file mode 100644 index 00000000000..9d0d5e95adc --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinSpan.fs @@ -0,0 +1,14 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop +open System + +let pinIt (thing: Span) = + use ptr = fixed thing + NativePtr.get ptr 0 + +[] +let main _ = + let span = Span("The quick brown fox jumped over the lazy dog".ToCharArray()) + let x = pinIt span + if x <> 'T' then failwith "x did not equal the first char of the span" + 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinSpanWithManualGetPinnableReferenceCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinSpanWithManualGetPinnableReferenceCall.fs new file mode 100644 index 00000000000..f3054550b64 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinSpanWithManualGetPinnableReferenceCall.fs @@ -0,0 +1,14 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop +open System + +let pinIt (thing: Span) = + use ptr = fixed &thing.GetPinnableReference() + NativePtr.get ptr 0 + +[] +let main _ = + let span = Span("The quick brown fox jumped over the lazy dog".ToCharArray()) + let x = pinIt span + if x <> 'T' then failwith "x did not equal the first char of the span" + 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinStructTypeWithGetPinnableReferenceReturningByref.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinStructTypeWithGetPinnableReferenceReturningByref.fs new file mode 100644 index 00000000000..87f636881c5 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinStructTypeWithGetPinnableReferenceReturningByref.fs @@ -0,0 +1,28 @@ +module FixedBindings +open System.Runtime.CompilerServices +open Microsoft.FSharp.NativeInterop +open System + +[] +type ArrayElementRef<'T> = + private { Values: 'T[]; Index: int } + + static member Create(values: 'T[], index) = + if index > values.Length then + raise (ArgumentOutOfRangeException(nameof(index), "")) + { Values = values; Index = index } + member this.Value = this.Values[this.Index] + [] + member this.GetPinnableReference () : byref<'T> = &this.Values[this.Index] + +let pinIt (thing: ArrayElementRef<'a>) = + use ptr = fixed thing + NativePtr.get ptr 0 + +[] +let main _ = + let arr = [|'a';'b';'c'|] + let x = ArrayElementRef.Create(arr, 1) + let y = pinIt x + if y <> x.Value then failwith "y did not equal x value" + 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinTypeWithCSharpStyleExtensionGetPinnableReferenceReturningByref.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinTypeWithCSharpStyleExtensionGetPinnableReferenceReturningByref.fs new file mode 100644 index 00000000000..e5256ecedd8 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinTypeWithCSharpStyleExtensionGetPinnableReferenceReturningByref.fs @@ -0,0 +1,22 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop +open System.Runtime.CompilerServices + +type RefField<'T> = { mutable _value: 'T } + +[] +type RefFieldExtensions = + [] + static member GetPinnableReference(refField: RefField<'T>) : byref<'T> = &refField._value + +let pinIt (thing: RefField<'T>) = + use ptr = fixed thing + NativePtr.get ptr 0 + +[] +let main _ = + let mutable x = 42 + let refToX = { _value = x } + let y = pinIt refToX + if y <> x then failwith "y did not equal x" + 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinTypeWithFSharpStyleExtensionGetPinnableReferenceReturningByref.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinTypeWithFSharpStyleExtensionGetPinnableReferenceReturningByref.fs new file mode 100644 index 00000000000..b54bebeeef8 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinTypeWithFSharpStyleExtensionGetPinnableReferenceReturningByref.fs @@ -0,0 +1,20 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop +open System.Runtime.CompilerServices + +type RefField<'T> = { mutable _value: 'T } +type RefField<'T> with + [] + member this.GetPinnableReference() : byref<'T> = &this._value + +let pinIt (thing: RefField<'T>) = + use ptr = fixed thing + NativePtr.get ptr 0 + +[] +let main _ = + let mutable x = 42 + let refToX = { _value = x } + let y = pinIt refToX + if y <> x then failwith "y did not equal x" + 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinTypeWithGetPinnableReferenceReturningByref.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinTypeWithGetPinnableReferenceReturningByref.fs new file mode 100644 index 00000000000..b276ae2672e --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinTypeWithGetPinnableReferenceReturningByref.fs @@ -0,0 +1,21 @@ +module FixedExpressions +open Microsoft.FSharp.NativeInterop +open System.Runtime.CompilerServices +open System + +type RefField<'T>(_value) = + let mutable _value = _value + member this.Value = _value + [] + member this.GetPinnableReference () : byref<'T> = &_value + +let pinIt (thing: RefField) = + use ptr = fixed thing + NativePtr.get ptr 0 + +[] +let main _ = + let x = RefField(42) + let y = pinIt x + if y <> x.Value then failwith "y did not equal x value" + 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinTypeWithGetPinnableReferenceReturningInref.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinTypeWithGetPinnableReferenceReturningInref.fs new file mode 100644 index 00000000000..43b580e574e --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/FixedBindings/PinTypeWithGetPinnableReferenceReturningInref.fs @@ -0,0 +1,21 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop +open System.Runtime.CompilerServices +open System + +type ReadonlyRefField<'T>(_value) = + let mutable _value = _value + member this.Value = _value + [] + member this.GetPinnableReference () : inref<'T> = &_value + +let pinIt (thing: ReadonlyRefField) = + use ptr = fixed thing + NativePtr.get ptr 0 + +[] +let main _ = + let x = ReadonlyRefField(42) + let y = pinIt x + if y <> x.Value then failwith "y did not equal x value" + 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index 20fd78fec08..d28b8274d83 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -159,6 +159,7 @@ + @@ -201,6 +202,7 @@ + diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/FixedBindings.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/FixedBindings.fs new file mode 100644 index 00000000000..86fb0c6c641 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/FixedBindings.fs @@ -0,0 +1,682 @@ +namespace Language.FixedBindings + +open Xunit +open FSharp.Test.Compiler + +module Legacy = + [] + [] + [] + let ``Pin naked string`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinNakedString.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + |> withDiagnostics [ + (Warning 9, Line 5, Col 9, Line 5, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Warning 9, Line 6, Col 5, Line 6, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + [] + let ``Pin naked array`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinNakedArray.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + |> withDiagnostics [ + (Warning 9, Line 5, Col 9, Line 5, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Warning 9, Line 6, Col 5, Line 6, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + [] + let ``Pin naked array with mismatching type`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinNakedArrayWithMismatchingType.fs") + |> withLangVersion langVersion + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 5, Col 9, Line 5, Col 31, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 1, Line 5, Col 9, Line 5, Col 31, """Type mismatch. Expecting a + 'nativeptr' +but given a + 'nativeptr' +The type 'int' does not match the type 'byte'""") + ] + + [] + [] + [] + let ``Pin naked string with mismatching type`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinNakedStringWithMismatchingType.fs") + |> withLangVersion langVersion + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 5, Col 9, Line 5, Col 31, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 1, Line 5, Col 9, Line 5, Col 31, """Type mismatch. Expecting a + 'nativeptr' +but given a + 'nativeptr' +The type 'char' does not match the type 'byte'""") + ] + + [] + [] + [] + let ``Pin naked Tuple -- illegal`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinNakedTuple.fs") + |> withLangVersion langVersion + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 5, Col 9, Line 5, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3207, Line 5, Col 9, Line 5, Col 12, """Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference()""") + ] + + [] + [] + [] + let ``Pin naked ValueTuple -- illegal`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinNakedValueTuple.fs") + |> withLangVersion langVersion + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 5, Col 9, Line 5, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3207, Line 5, Col 9, Line 5, Col 12, """Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference()""") + ] + + [] + [] + [] + let ``Pin naked discriminated union -- illegal`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinNakedDU.fs") + |> withLangVersion langVersion + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 7, Col 9, Line 7, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3207, Line 7, Col 9, Line 7, Col 12, """Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference()""") + ] + + [] + [] + [] + let ``Pin naked struct discriminated union -- illegal`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinNakedStructDU.fs") + |> withLangVersion langVersion + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 8, Col 9, Line 8, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3207, Line 8, Col 9, Line 8, Col 12, """Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference()""") + ] + + [] + [] + [] + let ``Pin address of array element`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinAddressOfArrayElement.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + |> withDiagnostics [ + (Warning 9, Line 5, Col 9, Line 5, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Warning 9, Line 6, Col 5, Line 6, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + [] + let ``Pin address of record field`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinAddressOfRecordField.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + |> withDiagnostics [ + (Warning 9, Line 7, Col 9, Line 7, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Warning 9, Line 8, Col 5, Line 8, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + [] + let ``Pin address of explicit field on this`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinAddressOfExplicitFieldOnThis.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + |> withDiagnostics [ + (Warning 9, Line 11, Col 13, Line 11, Col 16, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Warning 9, Line 12, Col 9, Line 12, Col 22, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + [] + let ``Pin naked object - illegal`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinNakedObject.fs") + |> withLangVersion langVersion + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 5, Col 9, Line 5, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3207, Line 5, Col 9, Line 5, Col 12, """Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference()""") + ] + + + [] + [] + [] + let ``Pin naked int - illegal`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinNakedInt.fs") + |> withLangVersion langVersion + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 5, Col 9, Line 5, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3207, Line 5, Col 9, Line 5, Col 12, """Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference()""") + ] + + [] + [] + [] + let ``Pin generic - illegal`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinGeneric.fs") + |> withLangVersion langVersion + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 5, Col 9, Line 5, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3207, Line 5, Col 9, Line 5, Col 12, """Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference()""") + ] + + [] + [] + [] + let ``Pin generic with unmanaged - illegal`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinGenericWithUnmanagedConstraint.fs") + |> withLangVersion langVersion + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 5, Col 9, Line 5, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3207, Line 5, Col 9, Line 5, Col 12, """Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference()""") + ] + + [] + [] + let ``Pin int byref parameter`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinIntByrefParameter.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 5, Col 9, Line 5, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3350, Line 5, Col 9, Line 5, Col 12, """Feature 'extended fixed bindings for byref and GetPinnableReference' is not available in F# 7.0. Please use language version 'PREVIEW' or greater.""") + (Warning 9, Line 6, Col 5, Line 6, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + let ``Pin int inref parmeter`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinIntInrefParameter.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 5, Col 9, Line 5, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3350, Line 5, Col 9, Line 5, Col 12, """Feature 'extended fixed bindings for byref and GetPinnableReference' is not available in F# 7.0. Please use language version 'PREVIEW' or greater.""") + (Warning 9, Line 6, Col 5, Line 6, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + let ``Pin int outref parmeter`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinIntOutrefParameter.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 5, Col 9, Line 5, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3350, Line 5, Col 9, Line 5, Col 12, """Feature 'extended fixed bindings for byref and GetPinnableReference' is not available in F# 7.0. Please use language version 'PREVIEW' or greater.""") + (Warning 9, Line 6, Col 5, Line 6, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + let ``Pin address of explicit field on this with default constructor class syntax`` langVersion = + // I think F# 7 and lower should have allowed this and that this was really just a bug, but we should preserve the existing behavior + // when turning the feature off + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinAddressOfExplicitFieldOnThisWithDefaultCtorClassSyntax.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 8, Col 13, Line 8, Col 16, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3350, Line 8, Col 13, Line 8, Col 16, """Feature 'extended fixed bindings for byref and GetPinnableReference' is not available in F# 7.0. Please use language version 'PREVIEW' or greater.""") + (Warning 9, Line 9, Col 9, Line 9, Col 22, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + let ``Pin int byref local variable`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinIntByrefLocalVariable.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 6, Col 9, Line 6, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3350, Line 6, Col 9, Line 6, Col 12, """Feature 'extended fixed bindings for byref and GetPinnableReference' is not available in F# 7.0. Please use language version 'PREVIEW' or greater.""") + (Warning 9, Line 7, Col 5, Line 7, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + +#if NETCOREAPP + [] + [] + let ``Pin Span`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinSpan.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 6, Col 9, Line 6, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3350, Line 6, Col 9, Line 6, Col 12, """Feature 'extended fixed bindings for byref and GetPinnableReference' is not available in F# 7.0. Please use language version 'PREVIEW' or greater.""") + (Warning 9, Line 7, Col 5, Line 7, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] +#endif + + [] + [] + let ``Pin custom struct byref type without GetPinnableReference method - illegal`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinCustomStructByrefTypeWithoutGetPinnableReference.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 10, Col 9, Line 10, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3207, Line 10, Col 9, Line 10, Col 12, """Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference()""") + ] + + [] + [] + let ``Pin type with method GetPinnableReference : unit -> byref`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithGetPinnableReferenceReturningByref.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 9, Col 9, Line 9, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3350, Line 9, Col 9, Line 9, Col 12, """Feature 'extended fixed bindings for byref and GetPinnableReference' is not available in F# 7.0. Please use language version 'PREVIEW' or greater.""") + (Warning 9, Line 10, Col 5, Line 10, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + let ``Pin type with method GetPinnableReference : unit -> inref`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithGetPinnableReferenceReturningInref.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 9, Col 9, Line 9, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3350, Line 9, Col 9, Line 9, Col 12, """Feature 'extended fixed bindings for byref and GetPinnableReference' is not available in F# 7.0. Please use language version 'PREVIEW' or greater.""") + (Warning 9, Line 10, Col 5, Line 10, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + let ``Pin type with extension method GetPinnableReference : unit -> byref`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithExtensionGetPinnableReferenceReturningByref.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 13, Col 9, Line 13, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3350, Line 13, Col 9, Line 13, Col 12, """Feature 'extended fixed bindings for byref and GetPinnableReference' is not available in F# 7.0. Please use language version 'PREVIEW' or greater.""") + (Warning 9, Line 14, Col 5, Line 14, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + let ``Pin type with method GetPinnableReference with parameters - illegal`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithGetPinnableReferenceWithParameters.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 9, Col 9, Line 9, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3207, Line 9, Col 9, Line 9, Col 12, """Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference()""") + ] + + [] + [] + let ``Pin type with method GetPinnableReference with non-byref return type - illegal`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithGetPinnableReferenceWithNonByrefReturnType.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 9, Col 9, Line 9, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3207, Line 9, Col 9, Line 9, Col 12, """Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference()""") + ] + + [] + [] + let ``Pin type with valid and invalid GetPinnableReference overloads`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithValidAndInvalidGetPinnableReferenceOverloads.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 11, Col 9, Line 11, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3350, Line 11, Col 9, Line 11, Col 12, """Feature 'extended fixed bindings for byref and GetPinnableReference' is not available in F# 7.0. Please use language version 'PREVIEW' or greater.""") + (Warning 9, Line 12, Col 5, Line 12, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + let ``Pin type with private method GetPinnableReference - illegal`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithPrivateGetPinnableReference.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 9, Col 9, Line 9, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3207, Line 9, Col 9, Line 9, Col 12, """Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference()""") + ] + + [] + [] + let ``Pin type with static method GetPinnableReference - illegal`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithStaticGetPinnableReference.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 9, Col 9, Line 9, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3207, Line 9, Col 9, Line 9, Col 12, """Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference()""") + ] + + [] + [] + let ``Pin type with mismatching GetPinnableReference return type`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithMismatchingGetPinnableReferenceReturnType.fs") + |> withLangVersion langVersion + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 9, Col 9, Line 9, Col 31, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3350, Line 9, Col 9, Line 9, Col 31, """Feature 'extended fixed bindings for byref and GetPinnableReference' is not available in F# 7.0. Please use language version 'PREVIEW' or greater.""") + (Error 1, Line 9, Col 9, Line 9, Col 31, "Type mismatch. Expecting a + 'nativeptr' +but given a + 'nativeptr' +The type 'int' does not match the type 'char'") + ] + + [] + [] + let ``Pin type with mismatching extension GetPinnableReference return type`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithMismatchingExtensionGetPinnableReferenceReturnType.fs") + |> withLangVersion langVersion + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 13, Col 9, Line 13, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3350, Line 13, Col 9, Line 13, Col 12, """Feature 'extended fixed bindings for byref and GetPinnableReference' is not available in F# 7.0. Please use language version 'PREVIEW' or greater.""") + (Warning 9, Line 14, Col 5, Line 14, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + +// FS-1081 - Extend fixed bindings +module ExtendedFixedBindings = + [] + [] + let ``Pin int byref parameter`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinIntByrefParameter.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + |> withDiagnostics [ + (Warning 9, Line 5, Col 9, Line 5, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Warning 9, Line 6, Col 5, Line 6, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + let ``Pin int inref parmeter`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinIntInrefParameter.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + |> withDiagnostics [ + (Warning 9, Line 5, Col 9, Line 5, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Warning 9, Line 6, Col 5, Line 6, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + let ``Pin int outref parmeter`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinIntOutrefParameter.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + |> withDiagnostics [ + (Warning 9, Line 5, Col 9, Line 5, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Warning 9, Line 6, Col 5, Line 6, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + let ``Pin address of explicit field on this with default constructor class syntax`` langVersion = + // I think F# 7 and lower should have allowed this and that this was really just a bug, but we should preserve the existing behavior + // when turning the feature off + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinAddressOfExplicitFieldOnThisWithDefaultCtorClassSyntax.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + |> withDiagnostics [ + (Warning 9, Line 8, Col 13, Line 8, Col 16, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Warning 9, Line 9, Col 9, Line 9, Col 22, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + let ``Pin int byref local variable`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinIntByrefLocalVariable.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + |> withDiagnostics [ + (Warning 9, Line 6, Col 9, Line 6, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Warning 9, Line 7, Col 5, Line 7, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + +#if NETCOREAPP + [] + [] + let ``Pin Span`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinSpan.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + |> withDiagnostics [ + (Warning 9, Line 6, Col 9, Line 6, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Warning 9, Line 7, Col 5, Line 7, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] +#endif + + [] + [] + let ``Pin custom struct byref type without GetPinnableReference method - illegal`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinCustomStructByrefTypeWithoutGetPinnableReference.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 10, Col 9, Line 10, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3207, Line 10, Col 9, Line 10, Col 12, """Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference()""") + ] + + [] + [] + let ``Pin type with method GetPinnableReference : unit -> byref`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithGetPinnableReferenceReturningByref.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + |> withDiagnostics [ + (Warning 9, Line 9, Col 9, Line 9, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Warning 9, Line 10, Col 5, Line 10, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + let ``Pin type with method GetPinnableReference : unit -> inref`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithGetPinnableReferenceReturningInref.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + |> withDiagnostics [ + (Warning 9, Line 9, Col 9, Line 9, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Warning 9, Line 10, Col 5, Line 10, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + let ``Pin type with extension method GetPinnableReference : unit -> byref`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithExtensionGetPinnableReferenceReturningByref.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + |> withDiagnostics [ + (Warning 9, Line 13, Col 9, Line 13, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Warning 9, Line 14, Col 5, Line 14, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + let ``Pin type with method GetPinnableReference with parameters - illegal`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithGetPinnableReferenceWithParameters.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 9, Col 9, Line 9, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3207, Line 9, Col 9, Line 9, Col 12, """Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference()""") + ] + + [] + [] + let ``Pin type with method GetPinnableReference with non-byref return type - illegal`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithGetPinnableReferenceWithNonByrefReturnType.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 9, Col 9, Line 9, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3207, Line 9, Col 9, Line 9, Col 12, """Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference()""") + ] + + [] + [] + let ``Pin type with a valid GetPinnableReference method and several invalid overloads`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithValidAndInvalidGetPinnableReferenceOverloads.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + |> withDiagnostics [ + (Warning 9, Line 11, Col 9, Line 11, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Warning 9, Line 12, Col 5, Line 12, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] + + [] + [] + let ``Pin type with private method GetPinnableReference - illegal`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithPrivateGetPinnableReference.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 9, Col 9, Line 9, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3207, Line 9, Col 9, Line 9, Col 12, """Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference()""") + ] + + [] + [] + let ``Pin type with static method GetPinnableReference - illegal`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithStaticGetPinnableReference.fs") + |> withLangVersion langVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 9, Col 9, Line 9, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 3207, Line 9, Col 9, Line 9, Col 12, """Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference()""") + ] + + [] + [] + let ``Pin type with mismatching GetPinnableReference return type`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithMismatchingGetPinnableReferenceReturnType.fs") + |> withLangVersion langVersion + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 9, Col 9, Line 9, Col 31, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Error 1, Line 9, Col 9, Line 9, Col 31, "Type mismatch. Expecting a + 'nativeptr' +but given a + 'nativeptr' +The type 'int' does not match the type 'char'") + ] + + [] + [] + let ``Pin type with mismatching extension GetPinnableReference return type`` langVersion = + FsFromPath (__SOURCE_DIRECTORY__ ++ "PinTypeWithMismatchingExtensionGetPinnableReferenceReturnType.fs") + |> withLangVersion langVersion + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 9, Line 13, Col 9, Line 13, Col 12, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + (Warning 9, Line 14, Col 5, Line 14, Col 18, """Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.""") + ] diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinAddressOfArrayElement.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinAddressOfArrayElement.fs new file mode 100644 index 00000000000..c44f4c389fb --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinAddressOfArrayElement.fs @@ -0,0 +1,6 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +let pinIt (arr: char[]) = + use ptr = fixed &arr[1] + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinAddressOfExplicitFieldOnThis.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinAddressOfExplicitFieldOnThis.fs new file mode 100644 index 00000000000..6215bccc864 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinAddressOfExplicitFieldOnThis.fs @@ -0,0 +1,12 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +type Point = + val mutable X: int + val mutable Y: int + + new(x: int, y: int) = { X = x; Y = y } + + member this.PinIt() = + use ptr = fixed &this.X + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinAddressOfExplicitFieldOnThisWithDefaultCtorClassSyntax.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinAddressOfExplicitFieldOnThisWithDefaultCtorClassSyntax.fs new file mode 100644 index 00000000000..88153fed1ce --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinAddressOfExplicitFieldOnThisWithDefaultCtorClassSyntax.fs @@ -0,0 +1,9 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +type Point() = + let mutable value = 42 + + member this.PinIt() = + let ptr = fixed &value + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinAddressOfRecordField.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinAddressOfRecordField.fs new file mode 100644 index 00000000000..707a0454dc1 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinAddressOfRecordField.fs @@ -0,0 +1,8 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +type Point = { mutable X: int; mutable Y: int } + +let pinIt (thing: Point) = + use ptr = fixed &thing.X + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinCustomStructByrefTypeWithoutGetPinnableReference.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinCustomStructByrefTypeWithoutGetPinnableReference.fs new file mode 100644 index 00000000000..936fd73f4a9 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinCustomStructByrefTypeWithoutGetPinnableReference.fs @@ -0,0 +1,11 @@ +module FixedBindings +open System +open System.Runtime.CompilerServices +open Microsoft.FSharp.NativeInterop + +[] +type BoringRefField<'T> = { Value: 'T } + +let pinIt (thing: BoringRefField) = + use ptr = fixed thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinGeneric.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinGeneric.fs new file mode 100644 index 00000000000..50bf16a6e0d --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinGeneric.fs @@ -0,0 +1,6 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +let pinIt (thing: 'a) = + use ptr = fixed thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinGenericWithUnmanagedConstraint.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinGenericWithUnmanagedConstraint.fs new file mode 100644 index 00000000000..81753f19205 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinGenericWithUnmanagedConstraint.fs @@ -0,0 +1,6 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +let pinIt<'a when 'a : unmanaged> (thing: 'a) = + use ptr = fixed thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinIntByrefLocalVariable.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinIntByrefLocalVariable.fs new file mode 100644 index 00000000000..22cbe69a89c --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinIntByrefLocalVariable.fs @@ -0,0 +1,7 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +let pinIt () = + let mutable thing = 42 + use ptr = fixed &thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinIntByrefParameter.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinIntByrefParameter.fs new file mode 100644 index 00000000000..08499789c6b --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinIntByrefParameter.fs @@ -0,0 +1,6 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +let pinIt (thing: byref) = + use ptr = fixed &thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinIntInrefParameter.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinIntInrefParameter.fs new file mode 100644 index 00000000000..2c147bfb57b --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinIntInrefParameter.fs @@ -0,0 +1,6 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +let pinIt (thing: inref) = + use ptr = fixed &thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinIntOutrefParameter.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinIntOutrefParameter.fs new file mode 100644 index 00000000000..511fc200a0b --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinIntOutrefParameter.fs @@ -0,0 +1,6 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +let pinIt (thing: outref) = + use ptr = fixed &thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedArray.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedArray.fs new file mode 100644 index 00000000000..a8853cb24eb --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedArray.fs @@ -0,0 +1,6 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +let pinIt (arr: char[]) = + use ptr = fixed arr + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedArrayWithMismatchingType.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedArrayWithMismatchingType.fs new file mode 100644 index 00000000000..af41d106065 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedArrayWithMismatchingType.fs @@ -0,0 +1,6 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +let pinIt (arr: int[]) = + use (ptr: nativeptr) = fixed arr + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedDU.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedDU.fs new file mode 100644 index 00000000000..3d6c8ed5e87 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedDU.fs @@ -0,0 +1,8 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +type Fruit = Apple | Banana + +let pinIt (x: Fruit) = + use ptr = fixed x + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedInt.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedInt.fs new file mode 100644 index 00000000000..0e9c150dcd5 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedInt.fs @@ -0,0 +1,6 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +let pinIt (thing: int) = + use ptr = fixed thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedObject.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedObject.fs new file mode 100644 index 00000000000..3e327811131 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedObject.fs @@ -0,0 +1,6 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +let pinIt (thing: obj) = + use ptr = fixed thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedString.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedString.fs new file mode 100644 index 00000000000..95d259363d3 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedString.fs @@ -0,0 +1,6 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +let pinIt (str: string) = + use ptr = fixed str + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedStringWithMismatchingType.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedStringWithMismatchingType.fs new file mode 100644 index 00000000000..8481f91cfc3 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedStringWithMismatchingType.fs @@ -0,0 +1,6 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +let pinIt (thing: string) = + use (ptr: nativeptr) = fixed thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedStructDU.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedStructDU.fs new file mode 100644 index 00000000000..81ea3e246e6 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedStructDU.fs @@ -0,0 +1,9 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +[] +type Fruit = Apple | Banana + +let pinIt (x: Fruit) = + use ptr = fixed x + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedTuple.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedTuple.fs new file mode 100644 index 00000000000..9cc1cd49885 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedTuple.fs @@ -0,0 +1,6 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +let pinIt (x: System.Tuple) = + use ptr = fixed x + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedValueTuple.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedValueTuple.fs new file mode 100644 index 00000000000..88de978bd0b --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinNakedValueTuple.fs @@ -0,0 +1,6 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +let pinIt (x: System.ValueTuple) = + use ptr = fixed x + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinSpan.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinSpan.fs new file mode 100644 index 00000000000..c8c53629802 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinSpan.fs @@ -0,0 +1,7 @@ +module FixedBindings +open System +open Microsoft.FSharp.NativeInterop + +let pinIt (thing: Span) = + use ptr = fixed thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithExtensionGetPinnableReferenceReturningByref.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithExtensionGetPinnableReferenceReturningByref.fs new file mode 100644 index 00000000000..c71f42eeb32 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithExtensionGetPinnableReferenceReturningByref.fs @@ -0,0 +1,14 @@ +module FixedBindings +open System.Runtime.CompilerServices +open Microsoft.FSharp.NativeInterop + +type RefField<'T> = { mutable _value: 'T } + +[] +type RefFieldExtensions = + [] + static member GetPinnableReference(refField: RefField<'T>) : byref<'T> = &refField._value + +let pinIt (thing: RefField<'T>) = + use ptr = fixed thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithGetPinnableReferenceReturningByref.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithGetPinnableReferenceReturningByref.fs new file mode 100644 index 00000000000..bf5981d0657 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithGetPinnableReferenceReturningByref.fs @@ -0,0 +1,10 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +type RefField<'T>(_value) = + let mutable _value = _value + member this.GetPinnableReference () : byref<'T> = &_value + +let pinIt (thing: RefField<'T>) = + use ptr = fixed thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithGetPinnableReferenceReturningInref.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithGetPinnableReferenceReturningInref.fs new file mode 100644 index 00000000000..79f298d5809 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithGetPinnableReferenceReturningInref.fs @@ -0,0 +1,10 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +type RefField<'T>(_value) = + let mutable _value = _value + member this.GetPinnableReference () : inref<'T> = &_value + +let pinIt (thing: RefField<'T>) = + use ptr = fixed thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithGetPinnableReferenceWithNonByrefReturnType.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithGetPinnableReferenceWithNonByrefReturnType.fs new file mode 100644 index 00000000000..1cb07ba948d --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithGetPinnableReferenceWithNonByrefReturnType.fs @@ -0,0 +1,10 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +type StrangeType<'T>(_value) = + let mutable _value = _value + member this.GetPinnableReference() : 'T = _value + +let pinIt (thing: StrangeType<'T>) = + use ptr = fixed thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithGetPinnableReferenceWithParameters.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithGetPinnableReferenceWithParameters.fs new file mode 100644 index 00000000000..2d5bf5693ae --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithGetPinnableReferenceWithParameters.fs @@ -0,0 +1,10 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +type StrangeType<'T>(_value) = + let mutable _value = _value + member this.GetPinnableReference(someValue: string) : byref<'T> = &_value + +let pinIt (thing: StrangeType<'T>) = + use ptr = fixed thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithMismatchingExtensionGetPinnableReferenceReturnType.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithMismatchingExtensionGetPinnableReferenceReturnType.fs new file mode 100644 index 00000000000..c71f42eeb32 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithMismatchingExtensionGetPinnableReferenceReturnType.fs @@ -0,0 +1,14 @@ +module FixedBindings +open System.Runtime.CompilerServices +open Microsoft.FSharp.NativeInterop + +type RefField<'T> = { mutable _value: 'T } + +[] +type RefFieldExtensions = + [] + static member GetPinnableReference(refField: RefField<'T>) : byref<'T> = &refField._value + +let pinIt (thing: RefField<'T>) = + use ptr = fixed thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithMismatchingGetPinnableReferenceReturnType.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithMismatchingGetPinnableReferenceReturnType.fs new file mode 100644 index 00000000000..3383d01055c --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithMismatchingGetPinnableReferenceReturnType.fs @@ -0,0 +1,10 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +type StrangeType() = + let mutable _value = 42 + member this.GetPinnableReference() = &_value + +let pinIt (thing: StrangeType) = + use (ptr: nativeptr) = fixed thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithPrivateGetPinnableReference.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithPrivateGetPinnableReference.fs new file mode 100644 index 00000000000..a1223d8e9c4 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithPrivateGetPinnableReference.fs @@ -0,0 +1,10 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +type StrangeType<'T>(_value) = + let mutable _value = _value + member private this.GetPinnableReference() : byref<'T> = _value + +let pinIt (thing: StrangeType<'T>) = + use ptr = fixed thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithStaticGetPinnableReference.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithStaticGetPinnableReference.fs new file mode 100644 index 00000000000..db7317e9122 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithStaticGetPinnableReference.fs @@ -0,0 +1,10 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +type StrangeType<'T>(_value) = + let mutable _value = _value + static member GetPinnableReference() : byref<'T> = Unchecked.defaultof> + +let pinIt (thing: StrangeType<'T>) = + use ptr = fixed thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithValidAndInvalidGetPinnableReferenceOverloads.fs b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithValidAndInvalidGetPinnableReferenceOverloads.fs new file mode 100644 index 00000000000..be1242b4525 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/FixedBindings/PinTypeWithValidAndInvalidGetPinnableReferenceOverloads.fs @@ -0,0 +1,12 @@ +module FixedBindings +open Microsoft.FSharp.NativeInterop + +type RefField<'T>(_value) = + let mutable _value = _value + member this.GetPinnableReference (x: int) : string = string x + member this.GetPinnableReference (x: int, y: string) = string x + y + member this.GetPinnableReference () : byref<'T> = &_value + +let pinIt (thing: RefField<'T>) = + use ptr = fixed thing + NativePtr.get ptr 0 \ No newline at end of file diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs index 0ce5b995ad2..ce5252136e0 100644 --- a/tests/FSharp.Test.Utilities/Compiler.fs +++ b/tests/FSharp.Test.Utilities/Compiler.fs @@ -355,7 +355,7 @@ module rec Compiler = let FsxFromPath (path: string) : CompilationUnit = fsFromString (SourceFromPath path) |> FS - + let Fs (source: string) : CompilationUnit = fsFromString (FsSource source) |> FS @@ -1113,7 +1113,7 @@ module rec Compiler = match s.OutputPath with | None -> failwith "Operation didn't produce any output!" | Some p -> func p il - | CompilationResult.Failure _ -> failwith "Result should be \"Success\" in order to get IL." + | CompilationResult.Failure f -> failwith $"Result should be \"Success\" in order to get IL. Failure: {Environment.NewLine}{f}" let verifyIL = doILCheck ILChecker.checkIL diff --git a/tests/FSharp.Test.Utilities/CompilerAssert.fs b/tests/FSharp.Test.Utilities/CompilerAssert.fs index d8a2ce0462a..429a1a035c5 100644 --- a/tests/FSharp.Test.Utilities/CompilerAssert.fs +++ b/tests/FSharp.Test.Utilities/CompilerAssert.fs @@ -133,6 +133,7 @@ type TestCompilation = type CSharpLanguageVersion = | CSharp8 = 0 | CSharp9 = 1 + | CSharp11 = 11 | Preview = 99 [] @@ -143,6 +144,7 @@ type CompilationUtil private () = match lv with | CSharpLanguageVersion.CSharp8 -> LanguageVersion.CSharp8 | CSharpLanguageVersion.CSharp9 -> LanguageVersion.CSharp9 + | CSharpLanguageVersion.CSharp11 -> LanguageVersion.CSharp11 | CSharpLanguageVersion.Preview -> LanguageVersion.Preview | _ -> LanguageVersion.Default diff --git a/tests/fsharp/typecheck/sigs/neg97.bsl b/tests/fsharp/typecheck/sigs/neg97.bsl index 1a4d97f87d9..4681334f765 100644 --- a/tests/fsharp/typecheck/sigs/neg97.bsl +++ b/tests/fsharp/typecheck/sigs/neg97.bsl @@ -3,24 +3,16 @@ neg97.fs(13,1,13,10): typecheck error FS0256: A value must be mutable in order t neg97.fs(16,9,16,10): typecheck error FS0009: Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'. -neg97.fs(16,9,16,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' +neg97.fs(16,9,16,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference() neg97.fs(20,9,20,10): typecheck error FS0009: Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'. -neg97.fs(20,9,20,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' +neg97.fs(20,9,20,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference() -neg97.fs(25,9,25,10): typecheck error FS0009: Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'. +neg97.fs(26,20,26,32): typecheck error FS0698: Invalid constraint: the type used for the constraint is sealed, which means the constraint could only be satisfied by at most one solution -neg97.fs(25,9,25,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' +neg97.fs(26,20,26,32): typecheck error FS0064: This construct causes code to be less generic than indicated by the type annotations. The type variable 'T has been constrained to be type 'string'. -neg97.fs(30,9,30,10): typecheck error FS0009: Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'. +neg97.fs(26,12,26,14): typecheck error FS0663: This type parameter has been used in a way that constrains it to always be 'string' -neg97.fs(30,9,30,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' - -neg97.fs(36,20,36,32): typecheck error FS0698: Invalid constraint: the type used for the constraint is sealed, which means the constraint could only be satisfied by at most one solution - -neg97.fs(36,20,36,32): typecheck error FS0064: This construct causes code to be less generic than indicated by the type annotations. The type variable 'T has been constrained to be type 'string'. - -neg97.fs(36,12,36,14): typecheck error FS0663: This type parameter has been used in a way that constrains it to always be 'string' - -neg97.fs(42,20,42,22): typecheck error FS0039: The type parameter 'T is not defined. +neg97.fs(32,20,32,22): typecheck error FS0039: The type parameter 'T is not defined. diff --git a/tests/fsharp/typecheck/sigs/neg97.fs b/tests/fsharp/typecheck/sigs/neg97.fs index 5cd8743df21..c035cdc958f 100644 --- a/tests/fsharp/typecheck/sigs/neg97.fs +++ b/tests/fsharp/typecheck/sigs/neg97.fs @@ -20,16 +20,6 @@ let pinAnyNotAllowed(x: 'T) = use p = fixed x () -let pinStackAddressNotAllowed(x: 'T) = - let mutable v = 0 - use p = fixed &v - () - -let pinStructAddressNotAllowed(x: 'T) = - let mutable v = { X = 1.0; Y = 1.0 } - use p = fixed &v.Y - () - module Example1 = type X<'T> = Y of 'T diff --git a/tests/fsharp/typecheck/sigs/neg97.vsbsl b/tests/fsharp/typecheck/sigs/neg97.vsbsl index 1a4d97f87d9..4681334f765 100644 --- a/tests/fsharp/typecheck/sigs/neg97.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg97.vsbsl @@ -3,24 +3,16 @@ neg97.fs(13,1,13,10): typecheck error FS0256: A value must be mutable in order t neg97.fs(16,9,16,10): typecheck error FS0009: Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'. -neg97.fs(16,9,16,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' +neg97.fs(16,9,16,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference() neg97.fs(20,9,20,10): typecheck error FS0009: Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'. -neg97.fs(20,9,20,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' +neg97.fs(20,9,20,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is one of the following: an array, the address of an array element, a string, a byref, an inref, or a type implementing GetPinnableReference() -neg97.fs(25,9,25,10): typecheck error FS0009: Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'. +neg97.fs(26,20,26,32): typecheck error FS0698: Invalid constraint: the type used for the constraint is sealed, which means the constraint could only be satisfied by at most one solution -neg97.fs(25,9,25,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' +neg97.fs(26,20,26,32): typecheck error FS0064: This construct causes code to be less generic than indicated by the type annotations. The type variable 'T has been constrained to be type 'string'. -neg97.fs(30,9,30,10): typecheck error FS0009: Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'. +neg97.fs(26,12,26,14): typecheck error FS0663: This type parameter has been used in a way that constrains it to always be 'string' -neg97.fs(30,9,30,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' - -neg97.fs(36,20,36,32): typecheck error FS0698: Invalid constraint: the type used for the constraint is sealed, which means the constraint could only be satisfied by at most one solution - -neg97.fs(36,20,36,32): typecheck error FS0064: This construct causes code to be less generic than indicated by the type annotations. The type variable 'T has been constrained to be type 'string'. - -neg97.fs(36,12,36,14): typecheck error FS0663: This type parameter has been used in a way that constrains it to always be 'string' - -neg97.fs(42,20,42,22): typecheck error FS0039: The type parameter 'T is not defined. +neg97.fs(32,20,32,22): typecheck error FS0039: The type parameter 'T is not defined.