Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
83aa6d41
R
Rust
项目概览
int
/
Rust
接近 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
83aa6d41
编写于
7月 08, 2021
作者:
T
Thom Chiovoloni
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Carefully remove bounds checks from some chunk iterators
上级
c7e4740e
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
81 addition
and
6 deletion
+81
-6
library/core/src/slice/iter.rs
library/core/src/slice/iter.rs
+81
-6
未找到文件。
library/core/src/slice/iter.rs
浏览文件 @
83aa6d41
...
@@ -1474,7 +1474,24 @@ fn next_back(&mut self) -> Option<&'a [T]> {
...
@@ -1474,7 +1474,24 @@ fn next_back(&mut self) -> Option<&'a [T]> {
}
else
{
}
else
{
let
remainder
=
self
.v
.len
()
%
self
.chunk_size
;
let
remainder
=
self
.v
.len
()
%
self
.chunk_size
;
let
chunksz
=
if
remainder
!=
0
{
remainder
}
else
{
self
.chunk_size
};
let
chunksz
=
if
remainder
!=
0
{
remainder
}
else
{
self
.chunk_size
};
let
(
fst
,
snd
)
=
self
.v
.split_at
(
self
.v
.len
()
-
chunksz
);
// SAFETY: split_at_unchecked requires the argument be less than or
// equal to the length. This is guaranteed, but subtle: We need the
// expression `self.v.len() - sz` not to overflow, which means we
// need `sz >= tmp_len`.
//
// `sz` will always either be `self.v.len() % self.chunk_size`,
// which will always evaluate to strictly less than `self.v.len()`
// (or panic, in the case that `self.chunk_size` is zero), or it can
// be `self.chunk_size`, in the case that the length is exactly
// divisible by the chunk size.
//
// While it seems like using `self.chunk_size` in this case could
// lead to a value greater than `self.v.len()`, it cannot: if
// `self.chunk_size` were greater than `self.v.len()`, then
// `self.v.len() % self.chunk_size` would have returned non-zero
// (note that in this branch of the `if`, we already know that
// `self.v` is non-empty).
let
(
fst
,
snd
)
=
unsafe
{
self
.v
.split_at_unchecked
(
self
.v
.len
()
-
chunksz
)
};
self
.v
=
fst
;
self
.v
=
fst
;
Some
(
snd
)
Some
(
snd
)
}
}
...
@@ -1639,7 +1656,26 @@ fn next_back(&mut self) -> Option<&'a mut [T]> {
...
@@ -1639,7 +1656,26 @@ fn next_back(&mut self) -> Option<&'a mut [T]> {
let
sz
=
if
remainder
!=
0
{
remainder
}
else
{
self
.chunk_size
};
let
sz
=
if
remainder
!=
0
{
remainder
}
else
{
self
.chunk_size
};
let
tmp
=
mem
::
replace
(
&
mut
self
.v
,
&
mut
[]);
let
tmp
=
mem
::
replace
(
&
mut
self
.v
,
&
mut
[]);
let
tmp_len
=
tmp
.len
();
let
tmp_len
=
tmp
.len
();
let
(
head
,
tail
)
=
tmp
.split_at_mut
(
tmp_len
-
sz
);
// SAFETY: split_at_unchecked requires the argument be less than or
// equal to the length. This is guaranteed, but subtle: We need the
// expression `tmp_len - sz` not to overflow, which means we need
// `sz >= tmp_len`.
//
// `sz` will always either be `tmp_or_v.len() % self.chunk_size`
// (where `tmp_or_v` is the slice that at the time was `self.v` but
// now is `tmp`, and thus `tmp_len` and `tmp_or_v.len()` are the
// same), which will always evaluate to strictly less than
// `tmp_or_v.len()` (or panic, in the case that `self.chunk_size` is
// zero), or it can be `self.chunk_size`, in the case that the
// length is exactly divisible by the chunk size.
//
// While it seems like using `self.chunk_size` in this case could
// lead to a value greater than `tmp_len`, it cannot: if
// `self.chunk_size` were greater than `tmp_len`, then
// `tmp_or_v.len() % self.chunk_size` would have returned non-zero
// (note that in this branch of the `if`, we already know that
// `self.v` is non-empty).
let
(
head
,
tail
)
=
unsafe
{
tmp
.split_at_mut_unchecked
(
tmp_len
-
sz
)
};
self
.v
=
head
;
self
.v
=
head
;
Some
(
tail
)
Some
(
tail
)
}
}
...
@@ -2409,7 +2445,12 @@ fn next(&mut self) -> Option<&'a [T]> {
...
@@ -2409,7 +2445,12 @@ fn next(&mut self) -> Option<&'a [T]> {
None
None
}
else
{
}
else
{
let
chunksz
=
cmp
::
min
(
self
.v
.len
(),
self
.chunk_size
);
let
chunksz
=
cmp
::
min
(
self
.v
.len
(),
self
.chunk_size
);
let
(
fst
,
snd
)
=
self
.v
.split_at
(
self
.v
.len
()
-
chunksz
);
// SAFETY: split_at_unchecked just requires the argument be less
// than the length. This could only happen if the expression
// `self.v.len() - chunksz` overflows. This could only happen if
// `chunksz > self.v.len()`, which is impossible as we initialize it
// as the `min` of `self.v.len()` and `self.chunk_size`.
let
(
fst
,
snd
)
=
unsafe
{
self
.v
.split_at_unchecked
(
self
.v
.len
()
-
chunksz
)
};
self
.v
=
fst
;
self
.v
=
fst
;
Some
(
snd
)
Some
(
snd
)
}
}
...
@@ -2483,7 +2524,21 @@ fn next_back(&mut self) -> Option<&'a [T]> {
...
@@ -2483,7 +2524,21 @@ fn next_back(&mut self) -> Option<&'a [T]> {
}
else
{
}
else
{
let
remainder
=
self
.v
.len
()
%
self
.chunk_size
;
let
remainder
=
self
.v
.len
()
%
self
.chunk_size
;
let
chunksz
=
if
remainder
!=
0
{
remainder
}
else
{
self
.chunk_size
};
let
chunksz
=
if
remainder
!=
0
{
remainder
}
else
{
self
.chunk_size
};
let
(
fst
,
snd
)
=
self
.v
.split_at
(
chunksz
);
// SAFETY: split_at_unchecked requires the argument be less than or
// equal to the length. This is guaranteed, but subtle: `chunksz`
// will always either be `self.v.len() % self.chunk_size`, which
// will always evaluate to strictly less than `self.v.len()` (or
// panic, in the case that `self.chunk_size` is zero), or it can be
// `self.chunk_size`, in the case that the length is exactly
// divisible by the chunk size.
//
// While it seems like using `self.chunk_size` in this case could
// lead to a value greater than `self.v.len()`, it cannot: if
// `self.chunk_size` were greater than `self.v.len()`, then
// `self.v.len() % self.chunk_size` would return nonzero (note that
// in this branch of the `if`, we already know that `self.v` is
// non-empty).
let
(
fst
,
snd
)
=
unsafe
{
self
.v
.split_at_unchecked
(
chunksz
)
};
self
.v
=
snd
;
self
.v
=
snd
;
Some
(
fst
)
Some
(
fst
)
}
}
...
@@ -2569,7 +2624,12 @@ fn next(&mut self) -> Option<&'a mut [T]> {
...
@@ -2569,7 +2624,12 @@ fn next(&mut self) -> Option<&'a mut [T]> {
let
sz
=
cmp
::
min
(
self
.v
.len
(),
self
.chunk_size
);
let
sz
=
cmp
::
min
(
self
.v
.len
(),
self
.chunk_size
);
let
tmp
=
mem
::
replace
(
&
mut
self
.v
,
&
mut
[]);
let
tmp
=
mem
::
replace
(
&
mut
self
.v
,
&
mut
[]);
let
tmp_len
=
tmp
.len
();
let
tmp_len
=
tmp
.len
();
let
(
head
,
tail
)
=
tmp
.split_at_mut
(
tmp_len
-
sz
);
// SAFETY: split_at_mut_unchecked just requires the argument be less
// than the length. This could only happen if the expression
// `tmp_len - sz` overflows. This could only happen if `sz >
// tmp_len`, which is impossible as we initialize it as the `min` of
// `self.v.len()` (e.g. `tmp_len`) and `self.chunk_size`.
let
(
head
,
tail
)
=
unsafe
{
tmp
.split_at_mut_unchecked
(
tmp_len
-
sz
)
};
self
.v
=
head
;
self
.v
=
head
;
Some
(
tail
)
Some
(
tail
)
}
}
...
@@ -2647,7 +2707,22 @@ fn next_back(&mut self) -> Option<&'a mut [T]> {
...
@@ -2647,7 +2707,22 @@ fn next_back(&mut self) -> Option<&'a mut [T]> {
let
remainder
=
self
.v
.len
()
%
self
.chunk_size
;
let
remainder
=
self
.v
.len
()
%
self
.chunk_size
;
let
sz
=
if
remainder
!=
0
{
remainder
}
else
{
self
.chunk_size
};
let
sz
=
if
remainder
!=
0
{
remainder
}
else
{
self
.chunk_size
};
let
tmp
=
mem
::
replace
(
&
mut
self
.v
,
&
mut
[]);
let
tmp
=
mem
::
replace
(
&
mut
self
.v
,
&
mut
[]);
let
(
head
,
tail
)
=
tmp
.split_at_mut
(
sz
);
// SAFETY: split_at_mut_unchecked requires the argument be less than
// or equal to the length. This is guaranteed, but subtle: `chunksz`
// will always either be `tmp_or_v.len() % self.chunk_size` (where
// `tmp_or_v` is the slice that at the time was `self.v` but now is
// `tmp`), which will always evaluate to strictly less than
// `tmp_or_v.len()` (or panic, in the case that `self.chunk_size` is
// zero), or it can be `self.chunk_size`, in the case that the
// length is exactly divisible by the chunk size.
//
// While it seems like using `self.chunk_size` in this case could
// lead to a value greater than `tmp_or_v.len()`, it cannot: if
// `self.chunk_size` were greater than `tmp_or_v.len()`, then
// `tmp_or_v.len() % self.chunk_size` would return nonzero (note
// that in this branch of the `if`, we already know that `tmp_or_v`
// is non-empty).
let
(
head
,
tail
)
=
unsafe
{
tmp
.split_at_mut_unchecked
(
sz
)
};
self
.v
=
tail
;
self
.v
=
tail
;
Some
(
head
)
Some
(
head
)
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录