Skip to content

Commit b17fe79

Browse files
author
bors-servo
authored
Auto merge of #259 - servo:maybe-uninit, r=SimonSapin,nox
Unconditionally use MaybeUninit This raises the minimum Rust version to 1.36.0, so this is a breaking change.
2 parents 6c69040 + 4721b69 commit b17fe79

File tree

4 files changed

+29
-43
lines changed

4 files changed

+29
-43
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ rust:
33
- nightly
44
- beta
55
- stable
6-
- 1.31.0
6+
- 1.36.0
77

88
script:
99
- cargo build --verbose

Cargo.toml

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "cssparser"
3-
version = "0.25.9"
3+
version = "0.26.0"
44
authors = [ "Simon Sapin <[email protected]>" ]
55

66
description = "Rust implementation of CSS Syntax Level 3"
@@ -30,7 +30,6 @@ serde = {version = "1.0", optional = true}
3030
smallvec = "0.6"
3131

3232
[build-dependencies]
33-
autocfg = "0.1.4"
3433
syn = { version = "1", features = ["extra-traits", "fold", "full"] }
3534
quote = "1"
3635
proc-macro2 = "1"

build.rs

-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

5-
extern crate autocfg;
65
#[macro_use]
76
extern crate quote;
87
#[macro_use]
@@ -50,7 +49,5 @@ fn main() {
5049
println!("cargo:rustc-cfg=rustc_has_pr45225")
5150
}
5251

53-
autocfg::new().emit_has_path("std::mem::MaybeUninit");
54-
5552
codegen::main();
5653
}

src/macros.rs

+27-37
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

5+
use std::mem::MaybeUninit;
6+
57
// See docs of the `procedural-masquerade` crate.
68
define_invoke_proc_macro!(cssparser_internal__invoke_proc_macro);
79

@@ -110,42 +112,16 @@ macro_rules! ascii_case_insensitive_phf_map {
110112
#[doc(hidden)]
111113
macro_rules! cssparser_internal__to_lowercase {
112114
($input: expr, $BUFFER_SIZE: expr => $output: ident) => {
113-
let mut buffer;
114-
// Safety: `buffer` is only used in `_internal__to_lowercase`,
115-
// which initializes with `copy_from_slice` the part of the buffer it uses,
116-
// before it uses it.
117115
#[allow(unsafe_code)]
118-
let buffer = unsafe { cssparser_internal__uninit!(buffer, $BUFFER_SIZE) };
116+
let mut buffer = unsafe {
117+
::std::mem::MaybeUninit::<[::std::mem::MaybeUninit<u8>; $BUFFER_SIZE]>::uninit()
118+
.assume_init()
119+
};
119120
let input: &str = $input;
120-
let $output = $crate::_internal__to_lowercase(buffer, input);
121+
let $output = $crate::_internal__to_lowercase(&mut buffer, input);
121122
};
122123
}
123124

124-
#[cfg(has_std__mem__MaybeUninit)]
125-
#[macro_export]
126-
#[doc(hidden)]
127-
macro_rules! cssparser_internal__uninit {
128-
($buffer: ident, $BUFFER_SIZE: expr) => {
129-
{
130-
$buffer = ::std::mem::MaybeUninit::<[u8; $BUFFER_SIZE]>::uninit();
131-
&mut *($buffer.as_mut_ptr())
132-
}
133-
}
134-
}
135-
136-
// FIXME: remove this when we require Rust 1.36
137-
#[cfg(not(has_std__mem__MaybeUninit))]
138-
#[macro_export]
139-
#[doc(hidden)]
140-
macro_rules! cssparser_internal__uninit {
141-
($buffer: ident, $BUFFER_SIZE: expr) => {
142-
{
143-
$buffer = ::std::mem::uninitialized::<[u8; $BUFFER_SIZE]>();
144-
&mut $buffer
145-
}
146-
}
147-
}
148-
149125
/// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros.
150126
///
151127
/// **This function is not part of the public API. It can change or be removed between any verisons.**
@@ -154,14 +130,28 @@ macro_rules! cssparser_internal__uninit {
154130
/// Otherwise, return `input` ASCII-lowercased, using `buffer` as temporary space if necessary.
155131
#[doc(hidden)]
156132
#[allow(non_snake_case)]
157-
pub fn _internal__to_lowercase<'a>(buffer: &'a mut [u8], input: &'a str) -> Option<&'a str> {
133+
pub fn _internal__to_lowercase<'a>(
134+
buffer: &'a mut [MaybeUninit<u8>],
135+
input: &'a str,
136+
) -> Option<&'a str> {
158137
if let Some(buffer) = buffer.get_mut(..input.len()) {
159138
if let Some(first_uppercase) = input.bytes().position(|byte| matches!(byte, b'A'..=b'Z')) {
160-
buffer.copy_from_slice(input.as_bytes());
161-
buffer[first_uppercase..].make_ascii_lowercase();
162-
// `buffer` was initialized to a copy of `input` (which is &str so well-formed UTF-8)
163-
// then lowercased (which preserves UTF-8 well-formedness)
164-
unsafe { Some(::std::str::from_utf8_unchecked(buffer)) }
139+
unsafe {
140+
// This cast doesn’t change the pointer’s validity
141+
// since `u8` has the same layout as `MaybeUninit<u8>`:
142+
let input_bytes = &*(input.as_bytes() as *const [u8] as *const [MaybeUninit<u8>]);
143+
144+
buffer.copy_from_slice(&*input_bytes);
145+
146+
// Same as above re layout, plus these bytes have been initialized:
147+
let buffer = &mut *(buffer as *mut [MaybeUninit<u8>] as *mut [u8]);
148+
149+
buffer[first_uppercase..].make_ascii_lowercase();
150+
// `buffer` was initialized to a copy of `input`
151+
// (which is `&str` so well-formed UTF-8)
152+
// then ASCII-lowercased (which preserves UTF-8 well-formedness):
153+
Some(::std::str::from_utf8_unchecked(buffer))
154+
}
165155
} else {
166156
// Input is already lower-case
167157
Some(input)

0 commit comments

Comments
 (0)