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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/Compiler/Checking/PostInferenceChecks.fs
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ let rec CheckTypeDeep (cenv: cenv) (visitTy, visitTyconRefOpt, visitAppTyOpt, vi

if tcref.CanDeref && tcref.IsILTycon && tinst.Length = tcref.ILTyconRawMetadata.GenericParams.Length then
(tinst,tcref.ILTyconRawMetadata.GenericParams)
||> List.iter2 (fun ty ilGenericParam ->
||> ListInline.iter2 (fun ty ilGenericParam ->
let typeInstParent = IlGenericInst(tcref, ilGenericParam)
CheckTypeDeep cenv f g env typeInstParent ty)
else
Expand Down Expand Up @@ -645,7 +645,7 @@ let CheckInterfaceTypeArgForUnimplementedStaticAbstractMembers (cenv: cenv) m (t
if cenv.reportErrors then
// Only check if the type parameter has interface constraints
let hasInterfaceConstraint =
typar.Constraints |> List.exists (function
typar.Constraints |> ListInline.exists (function
| TyparConstraint.CoercesTo(constraintTy, _) -> isInterfaceTy cenv.g constraintTy
| _ -> false)

Expand Down Expand Up @@ -710,7 +710,7 @@ let CheckTypeAux permitByRefLike (cenv: cenv) env m ty onInnerByrefError =
if tcref.CanDeref then
let typars = tcref.Typars
if typars.Length = tinst.Length then
(typars, tinst) ||> List.iter2 (CheckInterfaceTypeArgForUnimplementedStaticAbstractMembers cenv m)
(typars, tinst) ||> ListInline.iter2 (fun typar typeArg -> CheckInterfaceTypeArgForUnimplementedStaticAbstractMembers cenv m typar typeArg)

let visitTraitSolution info =
match info with
Expand Down
23 changes: 23 additions & 0 deletions src/Compiler/Utilities/illib.fs
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,29 @@ module Option =
module internal ValueTuple =
let inline map1Of2 ([<InlineIfLambda>] f) struct (a1, a2) = struct (f a1, a2)

/// List combinators that inline the closure argument into a cursor loop, so a caller on a
/// hot path allocates no closure even when the lambda captures per-call state.
module ListInline =

let inline iter2 ([<InlineIfLambda>] action: 'T1 -> 'T2 -> unit) (list1: 'T1 list) (list2: 'T2 list) =
let mutable l1 = list1
let mutable l2 = list2

while not l1.IsEmpty && not l2.IsEmpty do
action l1.Head l2.Head
l1 <- l1.Tail
l2 <- l2.Tail

let inline exists ([<InlineIfLambda>] predicate: 'T -> bool) (list: 'T list) =
let mutable remaining = list
let mutable found = false

while not found && not remaining.IsEmpty do
found <- predicate remaining.Head
remaining <- remaining.Tail

found

module List =

let sortWithOrder (c: IComparer<'T>) elements =
Expand Down
6 changes: 6 additions & 0 deletions src/Compiler/Utilities/illib.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,12 @@ module internal Option =

val attempt: f: (unit -> 'T) -> 'T option

module internal ListInline =

val inline iter2: action: ('T1 -> 'T2 -> unit) -> list1: 'T1 list -> list2: 'T2 list -> unit

val inline exists: predicate: ('T -> bool) -> list: 'T list -> bool

module internal List =

val sortWithOrder: c: IComparer<'T> -> elements: 'T list -> 'T list
Expand Down
Loading