slog: rename AtomicLevel to LevelVar; doc tweaks

These changes were suggested in https://go-review.git.corp.google.com/c/proposal/+/444415/6.

Change-Id: If95b5c14c5e3fd611449cd259e2c5a1b488be229
Reviewed-on: https://go-review.googlesource.com/c/exp/+/446495
Run-TryBot: Jonathan Amsterdam <jba@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
diff --git a/slog/attr.go b/slog/attr.go
index 90541ee..29431cb 100644
--- a/slog/attr.go
+++ b/slog/attr.go
@@ -74,9 +74,9 @@
 	return Attr{key, AnyValue(value)}
 }
 
-// Equal reports whether two Attrs have equal keys and values.
-func (a1 Attr) Equal(a2 Attr) bool {
-	return a1.Key == a2.Key && a1.Value.Equal(a2.Value)
+// Equal reports whether a and b have equal keys and values.
+func (a Attr) Equal(b Attr) bool {
+	return a.Key == b.Key && a.Value.Equal(b.Value)
 }
 
 func (a Attr) String() string {
diff --git a/slog/handler.go b/slog/handler.go
index 5d476b2..893fad7 100644
--- a/slog/handler.go
+++ b/slog/handler.go
@@ -106,19 +106,21 @@
 // HandlerOptions are options for a TextHandler or JSONHandler.
 // A zero HandlerOptions consists entirely of default values.
 type HandlerOptions struct {
-	// Add a "source" attribute to the output whose value is of the form
-	// "file:line".
-	// This is false by default, because there is a cost to extracting this
-	// information.
+	// When AddSource is true, the handler adds a ("source", "file:line")
+	// attribute to the output indicating the source code position of the log
+	// statement. AddSource is false by default to skip the cost of computing
+	// this information.
 	AddSource bool
 
-	// Ignore records with levels below Level.Level().
-	// The default is InfoLevel.
+	// Level reports the minimum record level that will be logged.
+	// The handler discards records with lower levels.
+	// If Level is nil, the handler assumes InfoLevel.
+	// The handler calls Level.Level for each record processed;
+	// to adjust the minimum level dynamically, use a LevelVar.
 	Level Leveler
 
-	// If set, ReplaceAttr is called on each attribute of the message,
-	// and the returned value is used instead of the original. If the returned
-	// key is empty, the attribute is omitted from the output.
+	// ReplaceAttr is called to rewrite each attribute before it is logged.
+	// If ReplaceAttr returns an Attr with Key == "", the attribute is discarded.
 	//
 	// The built-in attributes with keys "time", "level", "source", and "msg"
 	// are passed to this function first, except that time and level are omitted
diff --git a/slog/handler_test.go b/slog/handler_test.go
index 3cfe9ff..0223cb8 100644
--- a/slog/handler_test.go
+++ b/slog/handler_test.go
@@ -319,8 +319,8 @@
 }
 
 func TestHandlerEnabled(t *testing.T) {
-	atomicLevel := func(l Level) *AtomicLevel {
-		var al AtomicLevel
+	levelVar := func(l Level) *LevelVar {
+		var al LevelVar
 		al.Set(l)
 		return &al
 	}
@@ -331,10 +331,10 @@
 	}{
 		{nil, true},
 		{WarnLevel, false},
-		{&AtomicLevel{}, true}, // defaults to Info
-		{atomicLevel(WarnLevel), false},
+		{&LevelVar{}, true}, // defaults to Info
+		{levelVar(WarnLevel), false},
 		{DebugLevel, true},
-		{atomicLevel(DebugLevel), true},
+		{levelVar(DebugLevel), true},
 	} {
 		h := &commonHandler{opts: HandlerOptions{Level: test.leveler}}
 		got := h.enabled(InfoLevel)
diff --git a/slog/level.go b/slog/level.go
index b799470..1d0ba18 100644
--- a/slog/level.go
+++ b/slog/level.go
@@ -83,25 +83,27 @@
 // It implements Leveler.
 func (l Level) Level() Level { return l }
 
-// An AtomicLevel is a Level that can be read and written safely by multiple
-// goroutines.
-// The default value of AtomicLevel is InfoLevel.
-type AtomicLevel struct {
+// A LevelVar is a Level variable, to allow a Handler level to change
+// dynamically.
+// It implements Leveler as well as a Set method,
+// and it is safe for use by multiple goroutines.
+// The zero LevelVar corresponds to InfoLevel.
+type LevelVar struct {
 	val atomic.Int64
 }
 
-// Level returns r's level.
-func (a *AtomicLevel) Level() Level {
-	return Level(int(a.val.Load()))
+// Level returns v's level.
+func (v *LevelVar) Level() Level {
+	return Level(int(v.val.Load()))
 }
 
-// Set sets the receiver's level to l.
-func (a *AtomicLevel) Set(l Level) {
-	a.val.Store(int64(l))
+// Set sets v's level to l.
+func (v *LevelVar) Set(l Level) {
+	v.val.Store(int64(l))
 }
 
-func (a *AtomicLevel) String() string {
-	return fmt.Sprintf("AtomicLevel(%s)", a.Level())
+func (v *LevelVar) String() string {
+	return fmt.Sprintf("LevelVar(%s)", v.Level())
 }
 
 // A Leveler provides a Level value.
@@ -109,7 +111,7 @@
 // As Level itself implements Leveler, clients typically supply
 // a Level value wherever a Leveler is needed, such as in HandlerOptions.
 // Clients who need to vary the level dynamically can provide a more complex
-// Leveler implementation such as *AtomicLevel.
+// Leveler implementation such as *LevelVar.
 type Leveler interface {
 	Level() Level
 }
diff --git a/slog/level_test.go b/slog/level_test.go
index b0a6013..d85de39 100644
--- a/slog/level_test.go
+++ b/slog/level_test.go
@@ -32,8 +32,8 @@
 	}
 }
 
-func TestAtomicLevel(t *testing.T) {
-	var al AtomicLevel
+func TestLevelVar(t *testing.T) {
+	var al LevelVar
 	if got, want := al.Level(), InfoLevel; got != want {
 		t.Errorf("got %v, want %v", got, want)
 	}
diff --git a/slog/logger.go b/slog/logger.go
index 942c5e8..8be8c34 100644
--- a/slog/logger.go
+++ b/slog/logger.go
@@ -78,7 +78,7 @@
 func (l Logger) Context() context.Context { return l.ctx }
 
 // With returns a new Logger that includes the given arguments, converted to
-// Attrs as in [Logger.Log]. The Attrs will be prepended to each output from the
+// Attrs as in [Logger.Log]. The Attrs will be added to each output from the
 // Logger.
 //
 // The new Logger's handler is the result of calling WithAttrs on the receiver's
diff --git a/slog/value.go b/slog/value.go
index de127b1..bcf10bd 100644
--- a/slog/value.go
+++ b/slog/value.go
@@ -168,7 +168,7 @@
 
 //////////////// Accessors
 
-// Any returns the Value's value as an any.
+// Any returns v's value as an any.
 func (v Value) Any() any {
 	switch v.Kind() {
 	case AnyKind, GroupKind, LogValuerKind:
@@ -195,8 +195,8 @@
 	}
 }
 
-// Int64 returns the Value's value as an int64. It panics
-// if the value is not a signed integer.
+// Int64 returns v's value as an int64. It panics
+// if v is not a signed integer.
 func (v Value) Int64() int64 {
 	if g, w := v.Kind(), Int64Kind; g != w {
 		panic(fmt.Sprintf("Value kind is %s, not %s", g, w))
@@ -204,8 +204,8 @@
 	return int64(v.num)
 }
 
-// Uint64 returns the Value's value as a uint64. It panics
-// if the value is not an unsigned integer.
+// Uint64 returns v's value as a uint64. It panics
+// if v is not an unsigned integer.
 func (v Value) Uint64() uint64 {
 	if g, w := v.Kind(), Uint64Kind; g != w {
 		panic(fmt.Sprintf("Value kind is %s, not %s", g, w))
@@ -213,8 +213,8 @@
 	return v.num
 }
 
-// Bool returns the Value's value as a bool. It panics
-// if the value is not a bool.
+// Bool returns v's value as a bool. It panics
+// if v is not a bool.
 func (v Value) Bool() bool {
 	if g, w := v.Kind(), BoolKind; g != w {
 		panic(fmt.Sprintf("Value kind is %s, not %s", g, w))
@@ -226,8 +226,8 @@
 	return a.num == 1
 }
 
-// Duration returns the Value's value as a time.Duration. It panics
-// if the value is not a time.Duration.
+// Duration returns v's value as a time.Duration. It panics
+// if v is not a time.Duration.
 func (a Value) Duration() time.Duration {
 	if g, w := a.Kind(), DurationKind; g != w {
 		panic(fmt.Sprintf("Value kind is %s, not %s", g, w))
@@ -240,8 +240,8 @@
 	return time.Duration(int64(a.num))
 }
 
-// Float64 returns the Value's value as a float64. It panics
-// if the value is not a float64.
+// Float64 returns v's value as a float64. It panics
+// if v is not a float64.
 func (v Value) Float64() float64 {
 	if g, w := v.Kind(), Float64Kind; g != w {
 		panic(fmt.Sprintf("Value kind is %s, not %s", g, w))
@@ -254,8 +254,8 @@
 	return math.Float64frombits(a.num)
 }
 
-// Time returns the Value's value as a time.Time. It panics
-// if the value is not a time.Time.
+// Time returns v's value as a time.Time. It panics
+// if v is not a time.Time.
 func (v Value) Time() time.Time {
 	if g, w := v.Kind(), TimeKind; g != w {
 		panic(fmt.Sprintf("Value kind is %s, not %s", g, w))
@@ -267,47 +267,47 @@
 	return time.Unix(0, int64(v.num)).In(v.any.(timeLocation))
 }
 
-// LogValuer returns the Value's value as a LogValuer. It panics
-// if the value is not a LogValuer.
+// LogValuer returns v's value as a LogValuer. It panics
+// if v is not a LogValuer.
 func (v Value) LogValuer() LogValuer {
 	return v.any.(LogValuer)
 }
 
-// Group returns the Value's value as a []Attr.
-// It panics if the Value's Kind is not GroupKind.
+// Group returns v's value as a []Attr.
+// It panics if v's Kind is not GroupKind.
 func (v Value) Group() []Attr {
 	return v.group()
 }
 
 //////////////// Other
 
-// Equal reports whether two Values have equal keys and values.
-func (v1 Value) Equal(v2 Value) bool {
-	k1 := v1.Kind()
-	k2 := v2.Kind()
+// Equal reports whether v and w have equal keys and values.
+func (v Value) Equal(w Value) bool {
+	k1 := v.Kind()
+	k2 := w.Kind()
 	if k1 != k2 {
 		return false
 	}
 	switch k1 {
 	case Int64Kind, Uint64Kind, BoolKind, DurationKind:
-		return v1.num == v2.num
+		return v.num == w.num
 	case StringKind:
-		return v1.str() == v2.str()
+		return v.str() == w.str()
 	case Float64Kind:
-		return v1.float() == v2.float()
+		return v.float() == w.float()
 	case TimeKind:
-		return v1.time().Equal(v2.time())
+		return v.time().Equal(w.time())
 	case AnyKind, LogValuerKind:
-		return v1.any == v2.any // may panic if non-comparable
+		return v.any == w.any // may panic if non-comparable
 	case GroupKind:
-		return slices.EqualFunc(v1.uncheckedGroup(), v2.uncheckedGroup(), Attr.Equal)
+		return slices.EqualFunc(v.uncheckedGroup(), w.uncheckedGroup(), Attr.Equal)
 	default:
 		panic(fmt.Sprintf("bad kind: %s", k1))
 	}
 }
 
-// append appends a text representation of the Value to dst.
-// The value is formatted as with fmt.Sprint.
+// append appends a text representation of v to dst.
+// v is formatted as with fmt.Sprint.
 func (v Value) append(dst []byte) []byte {
 	switch v.Kind() {
 	case StringKind:
@@ -331,8 +331,7 @@
 	}
 }
 
-// A LogValuer is a Value that transforms itself into a different Value (or,
-// using the Group feature, a group of Attrs) at the moment it is logged.
+// A LogValuer is any Go value that can convert itself into a Value for logging.
 //
 // This mechanism may be used to defer expensive operations until they are
 // needed, or to expand a single value into a sequence of components.
diff --git a/slog/value_safe.go b/slog/value_safe.go
index c5b66c9..38d5f97 100644
--- a/slog/value_safe.go
+++ b/slog/value_safe.go
@@ -26,7 +26,7 @@
 	any any
 }
 
-// Kind returns the Value's Kind.
+// Kind returns v's Kind.
 func (v Value) Kind() Kind {
 	switch k := v.any.(type) {
 	case Kind:
@@ -54,7 +54,7 @@
 }
 
 // String returns Value's value as a string, formatted like fmt.Sprint. Unlike
-// the methods Int64, Float64, and so on, which panic if the Value is of the
+// the methods Int64, Float64, and so on, which panic if v is of the
 // wrong kind, String never panics.
 func (v Value) String() string {
 	if v.Kind() == StringKind {
diff --git a/slog/value_unsafe.go b/slog/value_unsafe.go
index a5e86cb..f8e50cc 100644
--- a/slog/value_unsafe.go
+++ b/slog/value_unsafe.go
@@ -37,7 +37,7 @@
 	groupptr  unsafe.Pointer // used in Value.any when the Value is a []Attr
 )
 
-// Kind returns the Value's Kind.
+// Kind returns v's Kind.
 func (v Value) Kind() Kind {
 	switch x := v.any.(type) {
 	case Kind:
@@ -72,7 +72,7 @@
 }
 
 // String returns Value's value as a string, formatted like fmt.Sprint. Unlike
-// the methods Int64, Float64, and so on, which panic if the Value is of the
+// the methods Int64, Float64, and so on, which panic if v is of the
 // wrong kind, String never panics.
 func (v Value) String() string {
 	if sp, ok := v.any.(stringptr); ok {