diff --git a/compiler/ast/types.nim b/compiler/ast/types.nim index 9bb6c072301..ed0068390f1 100644 --- a/compiler/ast/types.nim +++ b/compiler/ast/types.nim @@ -60,6 +60,9 @@ type bvcSingle ## single-location view bvcSequence ## view of contiguous locations + ViewTypeKind* = enum + noView, immutableView, mutableView + proc base*(t: PType): PType = result = t[0] @@ -1558,6 +1561,74 @@ proc classifyBackendView*(t: PType): BackendViewKind = tyAnd, tyOr, tyNot, tyAnything, tyFromExpr: unreachable() +proc combine(dest: var ViewTypeKind, b: ViewTypeKind) {.inline.} = + case dest + of noView, mutableView: + dest = b + of immutableView: + if b == mutableView: dest = b + +proc classifyViewTypeAux(marker: var IntSet, t: PType): ViewTypeKind + +proc classifyViewTypeNode(marker: var IntSet, n: PNode): ViewTypeKind = + case n.kind + of nkSym: + result = classifyViewTypeAux(marker, n.typ) + of nkOfBranch: + result = classifyViewTypeNode(marker, n.lastSon) + else: + result = noView + for child in n: + result.combine classifyViewTypeNode(marker, child) + if result == mutableView: break + +proc classifyViewTypeAux(marker: var IntSet, t: PType): ViewTypeKind = + if containsOrIncl(marker, t.id): return noView + case t.kind + of tyVar: + result = mutableView + of tyLent, tyOpenArray, tyVarargs: + result = immutableView + of tyGenericInst, tyDistinct, tyAlias, tyInferred, tySink, + tyUncheckedArray, tySequence, tyArray, tyRef, tyStatic: + result = classifyViewTypeAux(marker, lastSon(t)) + of tyFromExpr: + if t.len > 0: + result = classifyViewTypeAux(marker, lastSon(t)) + else: + result = noView + of tyTuple: + result = noView + for i in 0.. use pass by pointer if - # not already a pointer-like type - if s.position == 0 and retType != nil and retType.kind == tyLent: + # first parameter and return type is immutable view? --> use pass by pointer + # if not already a pointer-like type + if s.position == 0 and retType != nil and + classifyViewType(retType) == immutableView: result = pt.kind notin {tyVar, tyOpenArray, tyVarargs, tyRef, tyPtr, tyPointer} diff --git a/compiler/mir/mirgen.nim b/compiler/mir/mirgen.nim index 8bdff9a0fc2..a071314d883 100644 --- a/compiler/mir/mirgen.nim +++ b/compiler/mir/mirgen.nim @@ -766,7 +766,7 @@ proc genArgs(c: var TCtx, n: PNode) = c.add empty(c, n[i]) elif i == 1 and not fntyp[0].isEmptyType() and not isHandleLike(t) and - classifyBackendView(fntyp[0]) != bvcNone: + classifyViewType(fntyp[0]) == immutableView: # the procedure returns a view, but the first parameter is not something # that resembles a handle. We need to make sure that the first argument # (which the view could be created from), is passed by reference diff --git a/compiler/sem/typeallowed.nim b/compiler/sem/typeallowed.nim index 2493c710ee6..92354dd6cf0 100644 --- a/compiler/sem/typeallowed.nim +++ b/compiler/sem/typeallowed.nim @@ -217,78 +217,6 @@ proc typeAllowedOrError*(t: PType, kind: TSymKind, c: PContext, kind: kind, allowedFlags: flags))) -type - ViewTypeKind* = enum - noView, immutableView, mutableView - -proc combine(dest: var ViewTypeKind, b: ViewTypeKind) {.inline.} = - case dest - of noView, mutableView: - dest = b - of immutableView: - if b == mutableView: dest = b - -proc classifyViewTypeAux(marker: var IntSet, t: PType): ViewTypeKind - -proc classifyViewTypeNode(marker: var IntSet, n: PNode): ViewTypeKind = - case n.kind - of nkSym: - result = classifyViewTypeAux(marker, n.typ) - of nkOfBranch: - result = classifyViewTypeNode(marker, n.lastSon) - else: - result = noView - for child in n: - result.combine classifyViewTypeNode(marker, child) - if result == mutableView: break - -proc classifyViewTypeAux(marker: var IntSet, t: PType): ViewTypeKind = - if containsOrIncl(marker, t.id): return noView - case t.kind - of tyVar: - result = mutableView - of tyLent, tyOpenArray, tyVarargs: - result = immutableView - of tyGenericInst, tyDistinct, tyAlias, tyInferred, tySink, - tyUncheckedArray, tySequence, tyArray, tyRef, tyStatic: - result = classifyViewTypeAux(marker, lastSon(t)) - of tyFromExpr: - if t.len > 0: - result = classifyViewTypeAux(marker, lastSon(t)) - else: - result = noView - of tyTuple: - result = noView - for i in 0..