slices: don't accept out of order indexes in Replace

Panic instead, as documented.

Fixes golang/go#56700

Change-Id: I47000f6f190278a54056cd229cb5a9bb5a6c1a90
Reviewed-on: https://go-review.googlesource.com/c/exp/+/449915
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
diff --git a/slices/slices.go b/slices/slices.go
index ff8b5d8..6b7928e 100644
--- a/slices/slices.go
+++ b/slices/slices.go
@@ -165,6 +165,7 @@
 // Replace replaces the elements s[i:j] by the given v, and returns the
 // modified slice. Replace panics if s[i:j] is not a valid slice of s.
 func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
+	_ = s[i:j] // verify that i:j is a valid subslice
 	tot := len(s[:i]) + len(v) + len(s[j:])
 	if tot <= cap(s) {
 		s2 := s[:tot]
diff --git a/slices/slices_test.go b/slices/slices_test.go
index 35ccad5..7473886 100644
--- a/slices/slices_test.go
+++ b/slices/slices_test.go
@@ -683,6 +683,23 @@
 	}
 }
 
+func TestReplacePanics(t *testing.T) {
+	for _, test := range []struct {
+		name string
+		s, v []int
+		i, j int
+	}{
+		{"indexes out of order", []int{1, 2}, []int{3}, 2, 1},
+		{"large index", []int{1, 2}, []int{3}, 1, 10},
+		{"negative index", []int{1, 2}, []int{3}, -1, 2},
+	} {
+		ss, vv := Clone(test.s), Clone(test.v)
+		if !panics(func() { Replace(ss, test.i, test.j, vv...) }) {
+			t.Errorf("Replace %s: should have panicked", test.name)
+		}
+	}
+}
+
 func BenchmarkReplace(b *testing.B) {
 	cases := []struct {
 		name string