@@ -28,6 +28,7 @@ open FSharp.Compiler.TypedTreeBasics
2828open FSharp.Compiler .TypedTreeOps
2929open FSharp.Compiler .TypeHierarchy
3030open FSharp.Compiler .TypeRelations
31+ open Import
3132
3233//--------------------------------------------------------------------------
3334// NOTES: reraise safety checks
@@ -334,7 +335,20 @@ let RecordAnonRecdInfo cenv (anonInfo: AnonRecdTypeInfo) =
334335// approx walk of type
335336//--------------------------------------------------------------------------
336337
337- let rec CheckTypeDeep ( cenv : cenv ) ( visitTy , visitTyconRefOpt , visitAppTyOpt , visitTraitSolutionOpt , visitTyparOpt as f ) ( g : TcGlobals ) env isInner ty =
338+ /// Represents the container for nester type instantions, carrying information about the parent (generic type) and data about correspinding generic typar definition.
339+ /// For current use, IlGenericParameterDef was enough. For other future use cases, conversion into F# Typar might be needed.
340+ type TypeInstCtx =
341+ | NoInfo
342+ | IlGenericInst of parent : TyconRef * genericArg : ILGenericParameterDef
343+ | TyparInst of parent : TyconRef
344+ | TopLevelAllowingByRef
345+
346+ with member x.TyparAllowsRefStruct () =
347+ match x with
348+ | IlGenericInst(_, ilTypar) -> ilTypar.HasAllowsRefStruct
349+ | _ -> false
350+
351+ let rec CheckTypeDeep ( cenv : cenv ) ( visitTy , visitTyconRefOpt , visitAppTyOpt , visitTraitSolutionOpt , visitTyparOpt as f ) ( g : TcGlobals ) env ( typeInstParentOpt : TypeInstCtx ) ty =
338352 // We iterate the _solved_ constraints as well, to pick up any record of trait constraint solutions
339353 // This means we walk _all_ the constraints _everywhere_ in a type, including
340354 // those attached to _solved_ type variables. This is used by PostTypeCheckSemanticChecks to detect uses of
@@ -366,22 +380,30 @@ let rec CheckTypeDeep (cenv: cenv) (visitTy, visitTyconRefOpt, visitAppTyOpt, vi
366380 match ty with
367381 | TType_ forall ( tps, body) ->
368382 let env = BindTypars g env tps
369- CheckTypeDeep cenv f g env isInner body
383+ CheckTypeDeep cenv f g env typeInstParentOpt body
370384 tps |> List.iter ( fun tp -> tp.Constraints |> List.iter ( CheckTypeConstraintDeep cenv f g env))
371385
372386 | TType_ measure _ -> ()
373387
374388 | TType_ app ( tcref, tinst, _) ->
375389 match visitTyconRefOpt with
376- | Some visitTyconRef -> visitTyconRef isInner tcref
390+ | Some visitTyconRef -> visitTyconRef typeInstParentOpt tcref
377391 | None -> ()
378392
379393 // If it's a 'byref<'T>', don't check 'T as an inner. This allows byref<Span<'T>>.
380394 // 'byref<byref<'T>>' is invalid and gets checked in visitAppTy.
381- if isByrefTyconRef g tcref then
382- CheckTypesDeepNoInner cenv f g env tinst
395+ //if isByrefTyconRef g tcref then
396+ // CheckTypesDeepNoInner cenv f g env tinst
397+
398+ if tcref.CanDeref && tcref.IsILTycon && tinst.Length = tcref.ILTyconRawMetadata.GenericParams.Length then
399+ ( tinst, tcref.ILTyconRawMetadata.GenericParams)
400+ ||> List.iter2 ( fun ty ilGenericParam ->
401+ let typeInstParent = IlGenericInst( tcref, ilGenericParam)
402+ CheckTypeDeep cenv f g env typeInstParent ty)
383403 else
384- CheckTypesDeep cenv f g env tinst
404+ let parentRef = TyparInst( tcref)
405+ for ty in tinst do
406+ CheckTypeDeep cenv f g env parentRef ty
385407
386408 match visitAppTyOpt with
387409 | Some visitAppTy -> visitAppTy ( tcref, tinst)
@@ -398,8 +420,8 @@ let rec CheckTypeDeep (cenv: cenv) (visitTy, visitTyconRefOpt, visitAppTyOpt, vi
398420 CheckTypesDeep cenv f g env tys
399421
400422 | TType_ fun ( s, t, _) ->
401- CheckTypeDeep cenv f g env true s
402- CheckTypeDeep cenv f g env true t
423+ CheckTypeDeep cenv f g env NoInfo s
424+ CheckTypeDeep cenv f g env NoInfo t
403425
404426 | TType_ var ( tp, _) ->
405427 if not tp.IsSolved then
@@ -410,20 +432,16 @@ let rec CheckTypeDeep (cenv: cenv) (visitTy, visitTyconRefOpt, visitAppTyOpt, vi
410432
411433and CheckTypesDeep cenv f g env tys =
412434 for ty in tys do
413- CheckTypeDeep cenv f g env true ty
414-
415- and CheckTypesDeepNoInner cenv f g env tys =
416- for ty in tys do
417- CheckTypeDeep cenv f g env false ty
435+ CheckTypeDeep cenv f g env NoInfo ty
418436
419437and CheckTypeConstraintDeep cenv f g env x =
420438 match x with
421- | TyparConstraint.CoercesTo( ty, _) -> CheckTypeDeep cenv f g env true ty
439+ | TyparConstraint.CoercesTo( ty, _) -> CheckTypeDeep cenv f g env NoInfo ty
422440 | TyparConstraint.MayResolveMember( traitInfo, _) -> CheckTraitInfoDeep cenv f g env traitInfo
423- | TyparConstraint.DefaultsTo(_, ty, _) -> CheckTypeDeep cenv f g env true ty
441+ | TyparConstraint.DefaultsTo(_, ty, _) -> CheckTypeDeep cenv f g env NoInfo ty
424442 | TyparConstraint.SimpleChoice( tys, _) -> CheckTypesDeep cenv f g env tys
425- | TyparConstraint.IsEnum( underlyingTy, _) -> CheckTypeDeep cenv f g env true underlyingTy
426- | TyparConstraint.IsDelegate( argTys, retTy, _) -> CheckTypeDeep cenv f g env true argTys; CheckTypeDeep cenv f g env true retTy
443+ | TyparConstraint.IsEnum( underlyingTy, _) -> CheckTypeDeep cenv f g env NoInfo underlyingTy
444+ | TyparConstraint.IsDelegate( argTys, retTy, _) -> CheckTypeDeep cenv f g env NoInfo argTys; CheckTypeDeep cenv f g env NoInfo retTy
427445 | TyparConstraint.SupportsComparison _
428446 | TyparConstraint.SupportsEquality _
429447 | TyparConstraint.SupportsNull _
@@ -436,18 +454,18 @@ and CheckTypeConstraintDeep cenv f g env x =
436454and CheckTraitInfoDeep cenv ( _ , _ , _ , visitTraitSolutionOpt , _ as f ) g env traitInfo =
437455 CheckTypesDeep cenv f g env traitInfo.SupportTypes
438456 CheckTypesDeep cenv f g env traitInfo.CompiledObjectAndArgumentTypes
439- Option.iter ( CheckTypeDeep cenv f g env true ) traitInfo.CompiledReturnType
457+ Option.iter ( CheckTypeDeep cenv f g env NoInfo ) traitInfo.CompiledReturnType
440458 match visitTraitSolutionOpt, traitInfo.Solution with
441459 | Some visitTraitSolution, Some sln -> visitTraitSolution sln
442460 | _ -> ()
443461
444462/// Check for byref-like types
445463let CheckForByrefLikeType cenv env m ty check =
446- CheckTypeDeep cenv ( ignore, Some ( fun _deep tcref -> if isByrefLikeTyconRef cenv.g m tcref then check()), None, None, None) cenv.g env false ty
464+ CheckTypeDeep cenv ( ignore, Some ( fun ctx tcref -> if ( isByrefLikeTyconRef cenv.g m tcref && not ( ctx.TyparAllowsRefStruct ())) then check()), None, None, None) cenv.g env NoInfo ty
447465
448466/// Check for byref types
449467let CheckForByrefType cenv env ty check =
450- CheckTypeDeep cenv ( ignore, Some ( fun _deep tcref -> if isByrefTyconRef cenv.g tcref then check()), None, None, None) cenv.g env false ty
468+ CheckTypeDeep cenv ( ignore, Some ( fun _ctx tcref -> if isByrefTyconRef cenv.g tcref then check()), None, None, None) cenv.g env NoInfo ty
451469
452470/// check captures under lambdas
453471///
@@ -516,7 +534,7 @@ let CheckTypeForAccess (cenv: cenv) env objName valAcc m ty =
516534 if isLessAccessible tyconAcc valAcc then
517535 errorR( Error( FSComp.SR.chkTypeLessAccessibleThanType( tcref.DisplayName, ( objName())), m))
518536
519- CheckTypeDeep cenv ( visitType, None, None, None, None) cenv.g env false ty
537+ CheckTypeDeep cenv ( visitType, None, None, None, None) cenv.g env NoInfo ty
520538
521539let WarnOnWrongTypeForAccess ( cenv : cenv ) env objName valAcc m ty =
522540 if cenv.reportErrors then
@@ -534,7 +552,7 @@ let WarnOnWrongTypeForAccess (cenv: cenv) env objName valAcc m ty =
534552 let warningText = errorText + Environment.NewLine + FSComp.SR.tcTypeAbbreviationsCheckedAtCompileTime()
535553 warning( AttributeChecking.ObsoleteWarning( warningText, m))
536554
537- CheckTypeDeep cenv ( visitType, None, None, None, None) cenv.g env false ty
555+ CheckTypeDeep cenv ( visitType, None, None, None, None) cenv.g env NoInfo ty
538556
539557/// Indicates whether a byref or byref-like type is permitted at a particular location
540558[<RequireQualifiedAccess>]
@@ -629,16 +647,26 @@ let CheckTypeAux permitByRefLike (cenv: cenv) env m ty onInnerByrefError =
629647 else
630648 errorR ( Error( FSComp.SR.checkNotSufficientlyGenericBecauseOfScope( tp.DisplayName), m))
631649
632- let visitTyconRef isInner tcref =
650+ let visitTyconRef ( ctx : TypeInstCtx ) tcref =
651+ let checkInner () =
652+ match ctx with
653+ | TopLevelAllowingByRef -> false
654+ | TyparInst( parentTcRef)
655+ | IlGenericInst( parentTcRef,_) when isByrefTyconRef cenv.g parentTcRef -> false
656+ | _ -> true
657+
658+ let isInnerByRefLike () = checkInner() && isByrefLikeTyconRef cenv.g m tcref
659+
660+ let permitByRefLike =
661+ if ctx.TyparAllowsRefStruct() then PermitByRefType.All else permitByRefLike
633662
634- let isInnerByRefLike = isInner && isByrefLikeTyconRef cenv.g m tcref
635663
636664 match permitByRefLike with
637665 | PermitByRefType.None when isByrefLikeTyconRef cenv.g m tcref ->
638666 errorR( Error( FSComp.SR.chkErrorUseOfByref(), m))
639- | PermitByRefType.NoInnerByRefLike when isInnerByRefLike ->
667+ | PermitByRefType.NoInnerByRefLike when isInnerByRefLike() ->
640668 onInnerByrefError ()
641- | PermitByRefType.SpanLike when isByrefTyconRef cenv.g tcref || isInnerByRefLike ->
669+ | PermitByRefType.SpanLike when isByrefTyconRef cenv.g tcref || isInnerByRefLike() ->
642670 onInnerByrefError ()
643671 | _ -> ()
644672
@@ -665,7 +693,13 @@ let CheckTypeAux permitByRefLike (cenv: cenv) env m ty onInnerByrefError =
665693 cenv.potentialUnboundUsesOfVals <- cenv.potentialUnboundUsesOfVals.Add( vref.Stamp, m)
666694 | _ -> ()
667695
668- CheckTypeDeep cenv ( ignore, Some visitTyconRef, Some visitAppTy, Some visitTraitSolution, Some visitTyar) cenv.g env false ty
696+ let initialCtx =
697+ match permitByRefLike with
698+ | PermitByRefType.SpanLike
699+ | PermitByRefType.NoInnerByRefLike -> TopLevelAllowingByRef
700+ | _ -> NoInfo
701+
702+ CheckTypeDeep cenv ( ignore, Some visitTyconRef, Some visitAppTy, Some visitTraitSolution, Some visitTyar) cenv.g env initialCtx ty
669703
670704let CheckType permitByRefLike cenv env m ty =
671705 CheckTypeAux permitByRefLike cenv env m ty ( fun () -> errorR( Error( FSComp.SR.chkErrorUseOfByref(), m)))
@@ -1458,9 +1492,31 @@ and CheckExprOp cenv env (op, tyargs, args, m) ctxt expr =
14581492 CombineTwoLimits limit1 limit2
14591493
14601494 | TOp.ILCall (_, _, _, _, _, _, _, ilMethRef, enclTypeInst, methInst, retTypes), _, _ ->
1495+
14611496 CheckTypeInstNoByrefs cenv env m tyargs
1462- CheckTypeInstNoByrefs cenv env m enclTypeInst
1463- CheckTypeInstNoByrefs cenv env m methInst
1497+
1498+ match enclTypeInst, methInst with
1499+ | [],[] -> ()
1500+ | enclTypeInst, methInst ->
1501+ let tyconRef = ImportILTypeRef cenv.amap m ilMethRef.DeclaringTypeRef
1502+ match tyconRef.TypeReprInfo with
1503+ | TILObjectRepr( TILObjectReprData( scoref, _, tdef)) ->
1504+ ( enclTypeInst, tdef.GenericParams)
1505+ ||> List.iter2 ( fun typeInst typeGeneric ->
1506+ if not typeGeneric.HasAllowsRefStruct then
1507+ CheckTypeNoByrefs cenv env m typeInst)
1508+
1509+ match methInst with
1510+ | [] -> ()
1511+ | methInst ->
1512+ let methDef = resolveILMethodRefWithRescope ( rescopeILType scoref) tdef ilMethRef
1513+ ( methInst, methDef.GenericParams)
1514+ ||> List.iter2 ( fun methInst methGeneric ->
1515+ if not methGeneric.HasAllowsRefStruct then
1516+ CheckTypeNoByrefs cenv env m methInst)
1517+
1518+ | _ -> ()
1519+
14641520 CheckTypeInstNoInnerByrefs cenv env m retTypes // permit byref returns
14651521
14661522 let hasReceiver =
0 commit comments