Skip to content

Commit 6f1aca5

Browse files
committed
feat: opaque_repr attr to suppress "trivial structure" opt (pt 2)
1 parent 062f629 commit 6f1aca5

8 files changed

Lines changed: 57 additions & 0 deletions

File tree

src/Init/Core.lean

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ attribute [simp] namedPattern
3838
Thunks are "lazy" values that are evaluated when first accessed using `Thunk.get/map/bind`.
3939
The value is then stored and not recomputed for all further accesses. -/
4040
-- NOTE: the runtime has special support for the `Thunk` type to implement this behavior
41+
@[opaque_repr]
4142
structure Thunk (α : Type u) : Type u where
4243
/-- Constructs a new thunk from a function `Unit → α`
4344
that will be called when the thunk is forced. -/
@@ -359,6 +360,7 @@ possibly being computed on another thread. This is similar to `Future` in Scala,
359360
360361
The tasks have an overridden representation in the runtime.
361362
-/
363+
@[opaque_repr]
362364
structure Task (α : Type u) : Type u where
363365
/-- `Task.pure (a : α)` constructs a task that is already resolved with value `a`. -/
364366
pure ::

src/Init/Data/ByteArray/Basic.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Init.Data.UInt.Basic
1010
import Init.Data.Option.Basic
1111
universe u
1212

13+
@[opaque_repr]
1314
structure ByteArray where
1415
data : Array UInt8
1516

src/Init/Data/Float.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ opaque floatSpec : FloatSpec := {
2626
decLe := fun _ _ => inferInstanceAs (Decidable True)
2727
}
2828

29+
@[opaque_repr]
2930
structure Float where
3031
val : floatSpec.float
3132

src/Init/Data/FloatArray/Basic.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Init.Data.Float
99
import Init.Data.Option.Basic
1010
universe u
1111

12+
@[opaque_repr]
1213
structure FloatArray where
1314
data : Array Float
1415

src/Init/Data/Int/Basic.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ and larger numbers use an arbitrary precision "bignum" library
3737
(usually [GMP](https://gmplib.org/)). A "small number" is an integer
3838
that can be encoded with 63 bits (31 bits on 32-bits architectures).
3939
-/
40+
@[opaque_repr]
4041
inductive Int : Type where
4142
/-- A natural number is an integer (`0` to `∞`). -/
4243
| ofNat : Nat → Int

src/Init/Prelude.lean

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,7 @@ This type is special-cased by both the kernel and the compiler:
10351035
to 2^63 directly and larger numbers use an arbitrary precision "bignum"
10361036
library (usually [GMP](https://gmplib.org/)).
10371037
-/
1038+
@[opaque_repr]
10381039
inductive Nat where
10391040
/-- `Nat.zero`, normally written `0 : Nat`, is the smallest natural number.
10401041
This is one of the two constructors of `Nat`. -/
@@ -1780,6 +1781,7 @@ def UInt8.size : Nat := 256
17801781
The type of unsigned 8-bit integers. This type has special support in the
17811782
compiler to make it actually 8 bits rather than wrapping a `Nat`.
17821783
-/
1784+
@[opaque_repr]
17831785
structure UInt8 where
17841786
/-- Unpack a `UInt8` as a `Nat` less than `2^8`.
17851787
This function is overridden with a native implementation. -/
@@ -1819,6 +1821,7 @@ def UInt16.size : Nat := 65536
18191821
The type of unsigned 16-bit integers. This type has special support in the
18201822
compiler to make it actually 16 bits rather than wrapping a `Nat`.
18211823
-/
1824+
@[opaque_repr]
18221825
structure UInt16 where
18231826
/-- Unpack a `UInt16` as a `Nat` less than `2^16`.
18241827
This function is overridden with a native implementation. -/
@@ -1858,6 +1861,7 @@ def UInt32.size : Nat := 4294967296
18581861
The type of unsigned 32-bit integers. This type has special support in the
18591862
compiler to make it actually 32 bits rather than wrapping a `Nat`.
18601863
-/
1864+
@[opaque_repr]
18611865
structure UInt32 where
18621866
/-- Unpack a `UInt32` as a `Nat` less than `2^32`.
18631867
This function is overridden with a native implementation. -/
@@ -1934,6 +1938,7 @@ def UInt64.size : Nat := 18446744073709551616
19341938
The type of unsigned 64-bit integers. This type has special support in the
19351939
compiler to make it actually 64 bits rather than wrapping a `Nat`.
19361940
-/
1941+
@[opaque_repr]
19371942
structure UInt64 where
19381943
/-- Unpack a `UInt64` as a `Nat` less than `2^64`.
19391944
This function is overridden with a native implementation. -/
@@ -1985,6 +1990,7 @@ for the platform's architecture.
19851990
For example, if running on a 32-bit machine, USize is equivalent to UInt32.
19861991
Or on a 64-bit machine, UInt64.
19871992
-/
1993+
@[opaque_repr]
19881994
structure USize where
19891995
/-- Unpack a `USize` as a `Nat` less than `USize.size`.
19901996
This function is overridden with a native implementation. -/
@@ -2268,6 +2274,7 @@ def List.get {α : Type u} : (as : List α) → Fin as.length → α
22682274
The compiler overrides the data representation of this type to a byte sequence,
22692275
and both `String.utf8ByteSize` and `String.length` are cached and O(1).
22702276
-/
2277+
@[opaque_repr]
22712278
structure String where
22722279
/-- Pack a `List Char` into a `String`. This function is overridden by the
22732280
compiler and is O(n) in the length of the list. -/
@@ -2492,6 +2499,7 @@ as they are used "linearly" all updates will be performed destructively on the
24922499
array, so it has comparable performance to mutable arrays in imperative
24932500
programming languages.
24942501
-/
2502+
@[opaque_repr]
24952503
structure Array (α : Type u) where
24962504
/-- Convert a `List α` into an `Array α`. This function is overridden
24972505
to `List.toArray` and is O(n) in the length of the list. -/

tests/lean/opaqueReprAttr.lean

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
namespace MkAndValAreOptimizedAway
2+
3+
structure MyZero where
4+
val : Nat
5+
6+
def MyZero.valImpl (_self : MyZero) : Nat := 0
7+
attribute [implemented_by MyZero.valImpl] MyZero.val
8+
9+
unsafe def MyZero.mkImpl (_val : Nat) : MyZero := unsafeCast 0
10+
attribute [implemented_by MyZero.mkImpl] MyZero.mk
11+
12+
#eval (MyZero.mk 1).val -- 1
13+
14+
end MkAndValAreOptimizedAway
15+
16+
namespace UsingAttr
17+
18+
@[opaque_repr]
19+
structure MyZero where
20+
val : Nat
21+
22+
def MyZero.valImpl (_self : MyZero) : Nat := 0
23+
attribute [implemented_by MyZero.valImpl] MyZero.val
24+
25+
unsafe def MyZero.mkImpl (_val : Nat) : MyZero := unsafeCast 0
26+
attribute [implemented_by MyZero.mkImpl] MyZero.mk
27+
28+
#eval (MyZero.mk 1).val -- 0
29+
30+
-- FIXME: it would be nice if we didn't have to override casesOn too
31+
@[inline] def MyZero.casesOnImpl {motive : MyZero → Sort u} (t : MyZero)
32+
(mk : ∀ val, motive { val }) : motive t := mk _
33+
attribute [implemented_by MyZero.casesOnImpl] MyZero.casesOn
34+
35+
-- we need a blackBox here because the compiler will optimize
36+
-- `(MyZero.mk n).casesOn f` to `f n` otherwise (and this is desirable, even for opaque_repr types)
37+
@[noinline] def blackBox := @id
38+
#eval ((blackBox (MyZero.mk 1)).casesOn fun n => n : Nat) -- 0
39+
40+
end UsingAttr
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
1
2+
0
3+
0

0 commit comments

Comments
 (0)