From 6b2ef640624646fa9f02fe9cf137c7f07c3e15a2 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 1 May 2020 15:17:18 +0200 Subject: [PATCH 1/3] Fix #8856: Keep transparent flag --- compiler/src/dotty/tools/dotc/ast/untpd.scala | 2 +- compiler/src/dotty/tools/dotc/core/Flags.scala | 5 ++++- compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala | 2 -- .../dotc/tastyreflect/ReflectionCompilerInterface.scala | 1 + compiler/src/dotty/tools/dotc/typer/Namer.scala | 2 +- compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala | 6 +++--- compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 +- library/src/scala/tasty/Reflection.scala | 3 +++ library/src/scala/tasty/reflect/CompilerInterface.scala | 1 + library/src/scala/tasty/reflect/SourceCodePrinter.scala | 1 + tasty/src/dotty/tools/tasty/TastyFormat.scala | 2 +- 11 files changed, 17 insertions(+), 10 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index bb8da0d59d72..78b8cba20415 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -196,7 +196,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { case class Inline()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Inline) - case class Transparent()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.EmptyFlags) + case class Transparent()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Transparent) } /** Modifiers and annotations for definitions diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index 1bb664b63673..783041921615 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -347,8 +347,11 @@ object Flags { /** Labeled with `erased` modifier (erased value) */ val (_, Erased @ _, _) = newFlags(42, "erased") + /** Labelled with `transparent` modifier */ + val (Transparent @ _, _, _) = newFlags(43, "transparent") + /** An opaque type alias or a class containing one */ - val (Opaque @ _, _, _) = newFlags(43, "opaque") + val (Opaque @ _, _, _) = newFlags(44, "opaque") // ------------ Flags following this one are not pickled ---------------------------------- diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 98d231de643c..1141a1c2dd31 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -865,8 +865,6 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { if (rawFlags.is(Param)) flagMask = flagMask &~ Given val flags = rawFlags & flagMask var flagsText = toTextFlags(sym, flags) - if mods.hasMod(classOf[untpd.Mod.Transparent]) then - flagsText = "transparent " ~ flagsText val annotations = if (sym.exists) sym.annotations.filterNot(ann => dropAnnotForModText(ann.symbol)).map(_.tree) else mods.annotations.filterNot(tree => dropAnnotForModText(tree.symbol)) diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala index c2bb1173aced..e733dd2e04c5 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala @@ -1847,6 +1847,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def Flags_Lazy: Flags = core.Flags.Lazy def Flags_Override: Flags = core.Flags.Override def Flags_Inline: Flags = core.Flags.Inline + def Flags_Transparent: Flags = core.Flags.Transparent def Flags_Macro: Flags = core.Flags.Macro def Flags_Static: Flags = core.Flags.JavaStatic def Flags_JavaDefined: Flags = core.Flags.JavaDefined diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 9c6e83af0522..3a5e6a8529d3 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -866,7 +866,7 @@ class Namer { typer: Typer => case original: untpd.DefDef if sym.isInlineMethod => def rhsToInline(using Context): tpd.Tree = val mdef = typedAheadExpr(original).asInstanceOf[tpd.DefDef] - PrepareInlineable.wrapRHS(original, mdef.tpt, mdef.rhs) + PrepareInlineable.wrapRHS(sym, mdef.tpt, mdef.rhs) PrepareInlineable.registerInlineInfo(sym, rhsToInline)(using localContext(sym)) case _ => } diff --git a/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala b/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala index cf7286be340f..352e4134fe5f 100644 --- a/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala +++ b/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala @@ -204,9 +204,9 @@ object PrepareInlineable { def isLocal(sym: Symbol, inlineMethod: Symbol)(using Context): Boolean = isLocalOrParam(sym, inlineMethod) && !(sym.is(Param) && sym.owner == inlineMethod) - /** The type ascription `rhs: tpt`, unless `original` is `transparent`. */ - def wrapRHS(original: untpd.DefDef, tpt: Tree, rhs: Tree)(using Context): Tree = - if original.mods.hasMod(classOf[untpd.Mod.Transparent]) then rhs + /** The type ascription `rhs: tpt`, unless `sym` is `transparent`. */ + def wrapRHS(sym: Symbol, tpt: Tree, rhs: Tree)(using Context): Tree = + if sym.is(Transparent) then rhs else Typed(rhs, tpt) /** Register inline info for given inlineable method `sym`. diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 9c4ba0b47128..2c2f8fa0d63b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1865,7 +1865,7 @@ class Typer extends Namer if (sym.isInlineMethod) rhsCtx.addMode(Mode.InlineableBody) val rhs1 = typedExpr(ddef.rhs, tpt1.tpe.widenExpr)(using rhsCtx) - val rhsToInline = PrepareInlineable.wrapRHS(ddef, tpt1, rhs1) + val rhsToInline = PrepareInlineable.wrapRHS(sym, tpt1, rhs1) if (sym.isInlineMethod) PrepareInlineable.registerInlineInfo(sym, rhsToInline) diff --git a/library/src/scala/tasty/Reflection.scala b/library/src/scala/tasty/Reflection.scala index d3f6e63719b7..0cbc8f57cf64 100644 --- a/library/src/scala/tasty/Reflection.scala +++ b/library/src/scala/tasty/Reflection.scala @@ -2607,6 +2607,9 @@ class Reflection(private[scala] val internal: CompilerInterface) { self => /** Is this symbol `inline` */ def Inline: Flags = internal.Flags_Inline + /** Is this symbol a `transparent` */ + def Transparent: Flags = internal.Flags_Transparent + /** Is this symbol marked as a macro. An inline method containing toplevel splices */ def Macro: Flags = internal.Flags_Macro diff --git a/library/src/scala/tasty/reflect/CompilerInterface.scala b/library/src/scala/tasty/reflect/CompilerInterface.scala index 93bffe1b72cf..c602a8e8d919 100644 --- a/library/src/scala/tasty/reflect/CompilerInterface.scala +++ b/library/src/scala/tasty/reflect/CompilerInterface.scala @@ -1397,6 +1397,7 @@ trait CompilerInterface { def Flags_Lazy: Flags def Flags_Override: Flags def Flags_Inline: Flags + def Flags_Transparent: Flags def Flags_Macro: Flags def Flags_Static: Flags def Flags_JavaDefined: Flags diff --git a/library/src/scala/tasty/reflect/SourceCodePrinter.scala b/library/src/scala/tasty/reflect/SourceCodePrinter.scala index 75da3d55750b..504e6cc2e37a 100644 --- a/library/src/scala/tasty/reflect/SourceCodePrinter.scala +++ b/library/src/scala/tasty/reflect/SourceCodePrinter.scala @@ -34,6 +34,7 @@ class SourceCodePrinter[R <: Reflection & Singleton](val tasty: R)(syntaxHighlig if (flags.is(Flags.Lazy)) flagList += "lazy" if (flags.is(Flags.Override)) flagList += "override" if (flags.is(Flags.Inline)) flagList += "inline" + if (flags.is(Flags.Transparent)) flagList += "transparent" if (flags.is(Flags.Macro)) flagList += "macro" if (flags.is(Flags.JavaDefined)) flagList += "javaDefined" if (flags.is(Flags.Static)) flagList += "javaStatic" diff --git a/tasty/src/dotty/tools/tasty/TastyFormat.scala b/tasty/src/dotty/tools/tasty/TastyFormat.scala index f330254e4ff2..6b8a71b28328 100644 --- a/tasty/src/dotty/tools/tasty/TastyFormat.scala +++ b/tasty/src/dotty/tools/tasty/TastyFormat.scala @@ -248,7 +248,7 @@ Standard Section: "Comments" Comment* object TastyFormat { final val header: Array[Int] = Array(0x5C, 0xA1, 0xAB, 0x1F) - val MajorVersion: Int = 22 + val MajorVersion: Int = 23 val MinorVersion: Int = 0 /** Tags used to serialize names, should update [[nameTagToString]] if a new constant is added */ From f5c758ffda9decbd2951e7dfe6db592b0a4b86ac Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 1 May 2020 08:26:08 +0200 Subject: [PATCH 2/3] Make inline val transparent Inline vals aim to be a replacement of final vals with inferred literal types. They inline by having a literal type as a return type. In inline def terms, this is equivalent to transparent inline def returning the constant which is also stable. ``` inline val x = 3 transparent def y: Int = 3 ``` Therefore, such a definition of an inline val is always a transparent inline. ``` /*transparent*/ inline val x = 3 ``` If we define inline vals as always being transparent inline vals, then the constant type becomes an implementation detail rather than a restriction. This would imply that the following inline val are allowed. ``` inline val a: Byte = 1 inline val b: Short = 2 inline val c: Int = 3 ``` Note that with literal types it is impossible to directly implement `a` and `b` as those need a type annotation to infer their type, but the type would be widened. New `inline val` definition: * An `inline val` is `transparent` * An `inline val` is `final` or `abstract` * The RHS of an `inline val` must be a pure constant value Advantages * Aligns better with inline defs * Can define constant `Byte` and `Short` The proposed implementation would just reuse the same literal constant mechanism but modify slightly type inference for inline vals. When we type an inline val we use the return type to type/infer the type of the RHS, but then if the return type is not a constant, the return unwidened type is replaced by the type of the RHS. ``` inline val x: Int = 3 // typed as inline val x: 3 = 3 ``` --- .../src/dotty/tools/dotc/typer/Checking.scala | 24 ++++++++++++------- .../src/dotty/tools/dotc/typer/Typer.scala | 4 ++-- docs/docs/reference/metaprogramming/inline.md | 21 +++++++--------- tests/neg/i8841.check | 4 ---- tests/neg/i8841.scala | 2 +- tests/neg/inline-val.scala | 2 +- tests/pos/inline-vals.scala | 12 ++++++++++ 7 files changed, 40 insertions(+), 29 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 14584820ee3e..f3aefaa6be37 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -882,18 +882,24 @@ trait Checking { } } - /** Check that `tree` can be right hand-side or argument to `inline` value or parameter. */ - def checkInlineConformant(tpt: Tree, tree: Tree, sym: Symbol)(using Context): Unit = { + /** Check that `tree` can be right hand-side or argument to `inline` value. + * Returns the type (tpt) of the val, possibly adapted. + */ + def checkInlineConformant(tpt: Tree, tree: Tree, sym: Symbol)(using Context): Tree = { if sym.is(Inline, butNot = DeferredOrTermParamOrAccessor) && !ctx.erasedTypes && !ctx.inInlineMethod then - // final vals can be marked inline even if they're not pure, see Typer#patchFinalVals - val purityLevel = if (sym.is(Final)) Idempotent else Pure - tpt.tpe.widenTermRefExpr.dealias match + tree.tpe.widenTermRefExpr.dealias match case tp: ConstantType => + // final vals can be marked inline even if they're not pure, see Typer#patchFinalVals + val purityLevel = if (sym.is(Final)) Idempotent else Pure if !(exprPurity(tree) >= purityLevel) then - ctx.error(em"inline value must be pure", tree.sourcePos) + ctx.error("inline value must be pure", tree.sourcePos) + if tree.tpe =:= tpt.tpe then tpt + else TypeTree(tree.tpe).withSpan(tpt.span) case _ => - val pos = if tpt.span.isZeroExtent then tree.sourcePos else tpt.sourcePos - ctx.error(em"inline value must have a literal constant type", pos) + ctx.error("inline value must have a literal constant type", tree.sourcePos) + tpt + else + tpt } /** A hook to exclude selected symbols from double declaration check */ @@ -1222,7 +1228,7 @@ trait NoChecking extends ReChecking { override def checkImplicitConversionDefOK(sym: Symbol)(using Context): Unit = () override def checkImplicitConversionUseOK(sym: Symbol, posd: Positioned)(using Context): Unit = () override def checkFeasibleParent(tp: Type, pos: SourcePosition, where: => String = "")(using Context): Type = tp - override def checkInlineConformant(tpt: Tree, tree: Tree, sym: Symbol)(using Context): Unit = () + override def checkInlineConformant(tpt: Tree, tree: Tree, sym: Symbol)(using Context): Tree = tpt override def checkNoAlphaConflict(stats: List[Tree])(using Context): Unit = () override def checkParentCall(call: Tree, caller: ClassSymbol)(using Context): Unit = () override def checkSimpleKinded(tpt: Tree)(using Context): Tree = tpt diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 2c2f8fa0d63b..ffbf7cfce7d1 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1801,9 +1801,9 @@ class Typer extends Namer case rhs @ Ident(nme.WILDCARD) => rhs withType tpt1.tpe case rhs => typedExpr(rhs, tpt1.tpe.widenExpr) } - val vdef1 = assignType(cpy.ValDef(vdef)(name, tpt1, rhs1), sym) + val tpt2 = checkInlineConformant(tpt1, rhs1, sym) + val vdef1 = assignType(cpy.ValDef(vdef)(name, tpt2, rhs1), sym) checkSignatureRepeatedParam(sym) - checkInlineConformant(tpt1, rhs1, sym) patchFinalVals(vdef1) vdef1.setDefTree } diff --git a/docs/docs/reference/metaprogramming/inline.md b/docs/docs/reference/metaprogramming/inline.md index 5e79fabfd2bf..b26c3eac6c7c 100644 --- a/docs/docs/reference/metaprogramming/inline.md +++ b/docs/docs/reference/metaprogramming/inline.md @@ -235,18 +235,6 @@ inline val four = 4 inline val four: 4 = 4 ``` -It is also possible to have inline vals of types that do not have a syntax, such as `Short(4)`. - -```scala -trait InlineConstants { - inline val myShort: Short -} - -object Constants extends InlineConstants { - inline val myShort/*: Short(4)*/ = 4 -} -``` - ## Transparent Inline Methods Inline methods can additionally be declared `transparent`. @@ -287,6 +275,15 @@ transparent inline def zero(): Int = 0 val one: 1 = zero() + 1 ``` +All `inline val`s effectively are transparent. This allows any `inline val` to be costant folded. + +```scala +inline val one: Int = 1 + +val two: 2 = one + one +``` + + ## Inline Conditionals If the condition of an if-then-else expressions is a constant expression then it simplifies to diff --git a/tests/neg/i8841.check b/tests/neg/i8841.check index d5b79c6bc88b..316a3efd4517 100644 --- a/tests/neg/i8841.check +++ b/tests/neg/i8841.check @@ -1,7 +1,3 @@ --- Error: tests/neg/i8841.scala:2:20 ----------------------------------------------------------------------------------- -2 | inline val log1 : Boolean = false // error - | ^^^^^^^ - | inline value must have a literal constant type -- Error: tests/neg/i8841.scala:3:20 ----------------------------------------------------------------------------------- 3 | inline val log2 = true: Boolean // error | ^^^^^^^^^^^^^ diff --git a/tests/neg/i8841.scala b/tests/neg/i8841.scala index ebe39bb7991e..306697162b39 100644 --- a/tests/neg/i8841.scala +++ b/tests/neg/i8841.scala @@ -1,5 +1,5 @@ object Foo { - inline val log1 : Boolean = false // error + inline val log1 : Boolean = false inline val log2 = true: Boolean // error inline val log3: false = { println(); false } // error } diff --git a/tests/neg/inline-val.scala b/tests/neg/inline-val.scala index e6eeee9c6299..fb7bf7a6c485 100644 --- a/tests/neg/inline-val.scala +++ b/tests/neg/inline-val.scala @@ -1,4 +1,4 @@ inline val a = 1 : Int // error -inline val b: Int = 1 // error +inline val b: Int = 1 inline val c = b // error diff --git a/tests/pos/inline-vals.scala b/tests/pos/inline-vals.scala index b6d9cc44bdb0..5ca2dd8e1f73 100644 --- a/tests/pos/inline-vals.scala +++ b/tests/pos/inline-vals.scala @@ -21,3 +21,15 @@ object Constants extends InlineConstants { inline val myInlinedChar = 'a' inline val myInlinedString = "abc" } + +class Constants2 { + inline val myInlinedBoolean: Boolean = true + inline val myInlinedByte: Byte = 1 + inline val myInlinedShort: Short = 2 + inline val myInlinedInt: Int = 3 + inline val myInlinedLong: Long = 4 + inline val myInlinedFloat: Float = 5 + inline val myInlinedDouble: Double = 6 + inline val myInlinedChar: Char = 'a' + inline val myInlinedString: String = "abc" +} \ No newline at end of file From 1b8d71934cb9866878f23cd35a7c39ed4d0660a6 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 1 May 2020 16:40:59 +0200 Subject: [PATCH 3/3] Only refine type of inline vals marked as transparent --- .../src/dotty/tools/dotc/typer/Checking.scala | 23 +++++++++++-------- tests/neg/i8841.check | 4 ++++ tests/neg/i8841.scala | 2 +- tests/neg/inline-val.scala | 2 +- tests/pos/inline-vals.scala | 20 ++++++++-------- 5 files changed, 29 insertions(+), 22 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index f3aefaa6be37..35c63bdd14c6 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -887,17 +887,20 @@ trait Checking { */ def checkInlineConformant(tpt: Tree, tree: Tree, sym: Symbol)(using Context): Tree = { if sym.is(Inline, butNot = DeferredOrTermParamOrAccessor) && !ctx.erasedTypes && !ctx.inInlineMethod then - tree.tpe.widenTermRefExpr.dealias match - case tp: ConstantType => - // final vals can be marked inline even if they're not pure, see Typer#patchFinalVals - val purityLevel = if (sym.is(Final)) Idempotent else Pure - if !(exprPurity(tree) >= purityLevel) then - ctx.error("inline value must be pure", tree.sourcePos) - if tree.tpe =:= tpt.tpe then tpt - else TypeTree(tree.tpe).withSpan(tpt.span) + // final vals can be marked inline even if they're not pure, see Typer#patchFinalVals + val purityLevel = if (sym.is(Final)) Idempotent else Pure + if !(exprPurity(tree) >= purityLevel) then + ctx.error("inline value must be pure", tree.sourcePos) + tpt + else tpt.tpe.widenTermRefExpr.dealias match + case tp: ConstantType => tpt case _ => - ctx.error("inline value must have a literal constant type", tree.sourcePos) - tpt + if sym.is(Transparent) then + TypeTree(tree.tpe).withSpan(tpt.span) + else + val pos = if tpt.span.isZeroExtent then tree.sourcePos else tpt.sourcePos + ctx.error("inline value must have a literal constant type", pos) + tpt else tpt } diff --git a/tests/neg/i8841.check b/tests/neg/i8841.check index 316a3efd4517..d5b79c6bc88b 100644 --- a/tests/neg/i8841.check +++ b/tests/neg/i8841.check @@ -1,3 +1,7 @@ +-- Error: tests/neg/i8841.scala:2:20 ----------------------------------------------------------------------------------- +2 | inline val log1 : Boolean = false // error + | ^^^^^^^ + | inline value must have a literal constant type -- Error: tests/neg/i8841.scala:3:20 ----------------------------------------------------------------------------------- 3 | inline val log2 = true: Boolean // error | ^^^^^^^^^^^^^ diff --git a/tests/neg/i8841.scala b/tests/neg/i8841.scala index 306697162b39..ebe39bb7991e 100644 --- a/tests/neg/i8841.scala +++ b/tests/neg/i8841.scala @@ -1,5 +1,5 @@ object Foo { - inline val log1 : Boolean = false + inline val log1 : Boolean = false // error inline val log2 = true: Boolean // error inline val log3: false = { println(); false } // error } diff --git a/tests/neg/inline-val.scala b/tests/neg/inline-val.scala index fb7bf7a6c485..e6eeee9c6299 100644 --- a/tests/neg/inline-val.scala +++ b/tests/neg/inline-val.scala @@ -1,4 +1,4 @@ inline val a = 1 : Int // error -inline val b: Int = 1 +inline val b: Int = 1 // error inline val c = b // error diff --git a/tests/pos/inline-vals.scala b/tests/pos/inline-vals.scala index 5ca2dd8e1f73..50b08487028d 100644 --- a/tests/pos/inline-vals.scala +++ b/tests/pos/inline-vals.scala @@ -23,13 +23,13 @@ object Constants extends InlineConstants { } class Constants2 { - inline val myInlinedBoolean: Boolean = true - inline val myInlinedByte: Byte = 1 - inline val myInlinedShort: Short = 2 - inline val myInlinedInt: Int = 3 - inline val myInlinedLong: Long = 4 - inline val myInlinedFloat: Float = 5 - inline val myInlinedDouble: Double = 6 - inline val myInlinedChar: Char = 'a' - inline val myInlinedString: String = "abc" -} \ No newline at end of file + transparent inline val myInlinedBoolean: Boolean = true + transparent inline val myInlinedByte: Byte = 1 + transparent inline val myInlinedShort: Short = 2 + transparent inline val myInlinedInt: Int = 3 + transparent inline val myInlinedLong: Long = 4 + transparent inline val myInlinedFloat: Float = 5 + transparent inline val myInlinedDouble: Double = 6 + transparent inline val myInlinedChar: Char = 'a' + transparent inline val myInlinedString: String = "abc" +}