summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-02-15 10:20:05 +0000
committerbors <bors@rust-lang.org>2020-02-15 10:20:05 +0000
commitdbef35309d10bed2f09cd55b3e9ea980a58c62aa (patch)
tree72b0aff59d492542867e747604c2abee64856211
parentAuto merge of #67681 - matthewjasper:infer-regions-in-borrowck, r=nikomatsakis (diff)
parentRollup merge of #69180 - Aaron1011:feature/comma-struct-init, r=petrochenkov (diff)
downloadrust-dbef35309d10bed2f09cd55b3e9ea980a58c62aa.tar.gz
rust-dbef35309d10bed2f09cd55b3e9ea980a58c62aa.tar.bz2
rust-dbef35309d10bed2f09cd55b3e9ea980a58c62aa.tar.xz
Auto merge of #69182 - Dylan-DPC:rollup-ifsa9fx, r=Dylan-DPC
Rollup of 6 pull requests Successful merges: - #64069 (Added From<Vec<NonZeroU8>> for CString) - #66721 (implement LowerExp and UpperExp for integers) - #69106 (Fix std::fs::copy on WASI target) - #69154 (Avoid calling `fn_sig` on closures) - #69166 (Check `has_typeck_tables` before calling `typeck_tables_of`) - #69180 (Suggest a comma if a struct initializer field fails to parse) Failed merges: r? @ghost
-rw-r--r--src/libcore/fmt/num.rs163
-rw-r--r--src/libcore/tests/fmt/num.rs80
-rw-r--r--src/librustc_mir/const_eval/eval_queries.rs5
-rw-r--r--src/librustc_parse/parser/expr.rs8
-rw-r--r--src/librustc_typeck/collect.rs4
-rw-r--r--src/libstd/ffi/c_str.rs27
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libstd/sys/wasi/fs.rs10
-rw-r--r--src/test/ui/consts/issue-68684.rs15
-rw-r--r--src/test/ui/macros/issue-68060.rs16
-rw-r--r--src/test/ui/macros/issue-68060.stderr24
-rw-r--r--src/test/ui/parser/removed-syntax-with-1.stderr5
-rw-r--r--src/test/ui/suggestions/struct-initializer-comma.rs13
-rw-r--r--src/test/ui/suggestions/struct-initializer-comma.stderr23
14 files changed, 387 insertions, 7 deletions
diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs
index d562639..c187471 100644
--- a/src/libcore/fmt/num.rs
+++ b/src/libcore/fmt/num.rs
@@ -4,6 +4,7 @@
4 4
5use crate::fmt; 5use crate::fmt;
6use crate::mem::MaybeUninit; 6use crate::mem::MaybeUninit;
7use crate::num::flt2dec;
7use crate::ops::{Div, Rem, Sub}; 8use crate::ops::{Div, Rem, Sub};
8use crate::ptr; 9use crate::ptr;
9use crate::slice; 10use crate::slice;
@@ -256,6 +257,161 @@ macro_rules! impl_Display {
256 }; 257 };
257} 258}
258 259
260macro_rules! impl_Exp {
261 ($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => {
262 fn $name(
263 mut n: $u,
264 is_nonnegative: bool,
265 upper: bool,
266 f: &mut fmt::Formatter<'_>
267 ) -> fmt::Result {
268 let (mut n, mut exponent, trailing_zeros, added_precision) = {
269 let mut exponent = 0;
270 // count and remove trailing decimal zeroes
271 while n % 10 == 0 && n >= 10 {
272 n /= 10;
273 exponent += 1;
274 }
275 let trailing_zeros = exponent;
276
277 let (added_precision, subtracted_precision) = match f.precision() {
278 Some(fmt_prec) => {
279 // number of decimal digits minus 1
280 let mut tmp = n;
281 let mut prec = 0;
282 while tmp >= 10 {
283 tmp /= 10;
284 prec += 1;
285 }
286 (fmt_prec.saturating_sub(prec), prec.saturating_sub(fmt_prec))
287 }
288 None => (0,0)
289 };
290 for _ in 1..subtracted_precision {
291 n/=10;
292 exponent += 1;
293 }
294 if subtracted_precision != 0 {
295 let rem = n % 10;
296 n /= 10;
297 exponent += 1;
298 // round up last digit
299 if rem >= 5 {
300 n += 1;
301 }
302 }
303 (n, exponent, trailing_zeros, added_precision)
304 };
305
306 // 39 digits (worst case u128) + . = 40
307 let mut buf = [MaybeUninit::<u8>::uninit(); 40];
308 let mut curr = buf.len() as isize; //index for buf
309 let buf_ptr = MaybeUninit::first_ptr_mut(&mut buf);
310 let lut_ptr = DEC_DIGITS_LUT.as_ptr();
311
312 // decode 2 chars at a time
313 while n >= 100 {
314 let d1 = ((n % 100) as isize) << 1;
315 curr -= 2;
316 unsafe {
317 ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
318 }
319 n /= 100;
320 exponent += 2;
321 }
322 // n is <= 99, so at most 2 chars long
323 let mut n = n as isize; // possibly reduce 64bit math
324 // decode second-to-last character
325 if n >= 10 {
326 curr -= 1;
327 unsafe {
328 *buf_ptr.offset(curr) = (n as u8 % 10_u8) + b'0';
329 }
330 n /= 10;
331 exponent += 1;
332 }
333 // add decimal point iff >1 mantissa digit will be printed
334 if exponent != trailing_zeros || added_precision != 0 {
335 curr -= 1;
336 unsafe {
337 *buf_ptr.offset(curr) = b'.';
338 }
339 }
340
341 let buf_slice = unsafe {
342 // decode last character
343 curr -= 1;
344 *buf_ptr.offset(curr) = (n as u8) + b'0';
345
346 let len = buf.len() - curr as usize;
347 slice::from_raw_parts(buf_ptr.offset(curr), len)
348 };
349
350 // stores 'e' (or 'E') and the up to 2-digit exponent
351 let mut exp_buf = [MaybeUninit::<u8>::uninit(); 3];
352 let exp_ptr = MaybeUninit::first_ptr_mut(&mut exp_buf);
353 let exp_slice = unsafe {
354 *exp_ptr.offset(0) = if upper {b'E'} else {b'e'};
355 let len = if exponent < 10 {
356 *exp_ptr.offset(1) = (exponent as u8) + b'0';
357 2
358 } else {
359 let off = exponent << 1;
360 ptr::copy_nonoverlapping(lut_ptr.offset(off), exp_ptr.offset(1), 2);
361 3
362 };
363 slice::from_raw_parts(exp_ptr, len)
364 };
365
366 let parts = &[
367 flt2dec::Part::Copy(buf_slice),
368 flt2dec::Part::Zero(added_precision),
369 flt2dec::Part::Copy(exp_slice)
370 ];
371 let sign = if !is_nonnegative {
372 &b"-"[..]
373 } else if f.sign_plus() {
374 &b"+"[..]
375 } else {
376 &b""[..]
377 };
378 let formatted = flt2dec::Formatted{sign, parts};
379 f.pad_formatted_parts(&formatted)
380 }
381
382 $(
383 #[stable(feature = "integer_exp_format", since = "1.42.0")]
384 impl fmt::LowerExp for $t {
385 #[allow(unused_comparisons)]
386 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
387 let is_nonnegative = *self >= 0;
388 let n = if is_nonnegative {
389 self.$conv_fn()
390 } else {
391 // convert the negative num to positive by summing 1 to it's 2 complement
392 (!self.$conv_fn()).wrapping_add(1)
393 };
394 $name(n, is_nonnegative, false, f)
395 }
396 })*
397 $(
398 #[stable(feature = "integer_exp_format", since = "1.42.0")]
399 impl fmt::UpperExp for $t {
400 #[allow(unused_comparisons)]
401 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
402 let is_nonnegative = *self >= 0;
403 let n = if is_nonnegative {
404 self.$conv_fn()
405 } else {
406 // convert the negative num to positive by summing 1 to it's 2 complement
407 (!self.$conv_fn()).wrapping_add(1)
408 };
409 $name(n, is_nonnegative, true, f)
410 }
411 })*
412 };
413}
414
259// Include wasm32 in here since it doesn't reflect the native pointer size, and 415// Include wasm32 in here since it doesn't reflect the native pointer size, and
260// often cares strongly about getting a smaller code size. 416// often cares strongly about getting a smaller code size.
261#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))] 417#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))]
@@ -265,6 +421,10 @@ mod imp {
265 i8, u8, i16, u16, i32, u32, i64, u64, usize, isize 421 i8, u8, i16, u16, i32, u32, i64, u64, usize, isize
266 as u64 via to_u64 named fmt_u64 422 as u64 via to_u64 named fmt_u64
267 ); 423 );
424 impl_Exp!(
425 i8, u8, i16, u16, i32, u32, i64, u64, usize, isize
426 as u64 via to_u64 named exp_u64
427 );
268} 428}
269 429
270#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))] 430#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))]
@@ -272,6 +432,9 @@ mod imp {
272 use super::*; 432 use super::*;
273 impl_Display!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named fmt_u32); 433 impl_Display!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named fmt_u32);
274 impl_Display!(i64, u64 as u64 via to_u64 named fmt_u64); 434 impl_Display!(i64, u64 as u64 via to_u64 named fmt_u64);
435 impl_Exp!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named exp_u32);
436 impl_Exp!(i64, u64 as u64 via to_u64 named exp_u64);
275} 437}
276 438
277impl_Display!(i128, u128 as u128 via to_u128 named fmt_u128); 439impl_Display!(i128, u128 as u128 via to_u128 named fmt_u128);
440impl_Exp!(i128, u128 as u128 via to_u128 named exp_u128);
diff --git a/src/libcore/tests/fmt/num.rs b/src/libcore/tests/fmt/num.rs
index 10fcf8b..a50c2b4 100644
--- a/src/libcore/tests/fmt/num.rs
+++ b/src/libcore/tests/fmt/num.rs
@@ -38,6 +38,16 @@ fn test_format_int() {
38 assert_eq!(format!("{:o}", 1i16), "1"); 38 assert_eq!(format!("{:o}", 1i16), "1");
39 assert_eq!(format!("{:o}", 1i32), "1"); 39 assert_eq!(format!("{:o}", 1i32), "1");
40 assert_eq!(format!("{:o}", 1i64), "1"); 40 assert_eq!(format!("{:o}", 1i64), "1");
41 assert_eq!(format!("{:e}", 1isize), "1e0");
42 assert_eq!(format!("{:e}", 1i8), "1e0");
43 assert_eq!(format!("{:e}", 1i16), "1e0");
44 assert_eq!(format!("{:e}", 1i32), "1e0");
45 assert_eq!(format!("{:e}", 1i64), "1e0");
46 assert_eq!(format!("{:E}", 1isize), "1E0");
47 assert_eq!(format!("{:E}", 1i8), "1E0");
48 assert_eq!(format!("{:E}", 1i16), "1E0");
49 assert_eq!(format!("{:E}", 1i32), "1E0");
50 assert_eq!(format!("{:E}", 1i64), "1E0");
41 51
42 assert_eq!(format!("{}", 1usize), "1"); 52 assert_eq!(format!("{}", 1usize), "1");
43 assert_eq!(format!("{}", 1u8), "1"); 53 assert_eq!(format!("{}", 1u8), "1");
@@ -69,6 +79,14 @@ fn test_format_int() {
69 assert_eq!(format!("{:o}", 1u16), "1"); 79 assert_eq!(format!("{:o}", 1u16), "1");
70 assert_eq!(format!("{:o}", 1u32), "1"); 80 assert_eq!(format!("{:o}", 1u32), "1");
71 assert_eq!(format!("{:o}", 1u64), "1"); 81 assert_eq!(format!("{:o}", 1u64), "1");
82 assert_eq!(format!("{:e}", 1u8), "1e0");
83 assert_eq!(format!("{:e}", 1u16), "1e0");
84 assert_eq!(format!("{:e}", 1u32), "1e0");
85 assert_eq!(format!("{:e}", 1u64), "1e0");
86 assert_eq!(format!("{:E}", 1u8), "1E0");
87 assert_eq!(format!("{:E}", 1u16), "1E0");
88 assert_eq!(format!("{:E}", 1u32), "1E0");
89 assert_eq!(format!("{:E}", 1u64), "1E0");
72 90
73 // Test a larger number 91 // Test a larger number
74 assert_eq!(format!("{:b}", 55), "110111"); 92 assert_eq!(format!("{:b}", 55), "110111");
@@ -76,6 +94,64 @@ fn test_format_int() {
76 assert_eq!(format!("{}", 55), "55"); 94 assert_eq!(format!("{}", 55), "55");
77 assert_eq!(format!("{:x}", 55), "37"); 95 assert_eq!(format!("{:x}", 55), "37");
78 assert_eq!(format!("{:X}", 55), "37"); 96 assert_eq!(format!("{:X}", 55), "37");
97 assert_eq!(format!("{:e}", 55), "5.5e1");
98 assert_eq!(format!("{:E}", 55), "5.5E1");
99 assert_eq!(format!("{:e}", 10000000000u64), "1e10");
100 assert_eq!(format!("{:E}", 10000000000u64), "1E10");
101 assert_eq!(format!("{:e}", 10000000001u64), "1.0000000001e10");
102 assert_eq!(format!("{:E}", 10000000001u64), "1.0000000001E10");
103}
104
105#[test]
106fn test_format_int_exp_limits() {
107 use core::{i128, i16, i32, i64, i8, u128, u16, u32, u64, u8};
108 assert_eq!(format!("{:e}", i8::MIN), "-1.28e2");
109 assert_eq!(format!("{:e}", i8::MAX), "1.27e2");
110 assert_eq!(format!("{:e}", i16::MIN), "-3.2768e4");
111 assert_eq!(format!("{:e}", i16::MAX), "3.2767e4");
112 assert_eq!(format!("{:e}", i32::MIN), "-2.147483648e9");
113 assert_eq!(format!("{:e}", i32::MAX), "2.147483647e9");
114 assert_eq!(format!("{:e}", i64::MIN), "-9.223372036854775808e18");
115 assert_eq!(format!("{:e}", i64::MAX), "9.223372036854775807e18");
116 assert_eq!(format!("{:e}", i128::MIN), "-1.70141183460469231731687303715884105728e38");
117 assert_eq!(format!("{:e}", i128::MAX), "1.70141183460469231731687303715884105727e38");
118
119 assert_eq!(format!("{:e}", u8::MAX), "2.55e2");
120 assert_eq!(format!("{:e}", u16::MAX), "6.5535e4");
121 assert_eq!(format!("{:e}", u32::MAX), "4.294967295e9");
122 assert_eq!(format!("{:e}", u64::MAX), "1.8446744073709551615e19");
123 assert_eq!(format!("{:e}", u128::MAX), "3.40282366920938463463374607431768211455e38");
124}
125
126#[test]
127fn test_format_int_exp_precision() {
128 use core::{i128, i16, i32, i64, i8};
129
130 //test that float and integer match
131 let big_int: u32 = 314_159_265;
132 assert_eq!(format!("{:.1e}", big_int), format!("{:.1e}", f64::from(big_int)));
133
134 //test adding precision
135 assert_eq!(format!("{:.10e}", i8::MIN), "-1.2800000000e2");
136 assert_eq!(format!("{:.10e}", i16::MIN), "-3.2768000000e4");
137 assert_eq!(format!("{:.10e}", i32::MIN), "-2.1474836480e9");
138 assert_eq!(format!("{:.20e}", i64::MIN), "-9.22337203685477580800e18");
139 assert_eq!(format!("{:.40e}", i128::MIN), "-1.7014118346046923173168730371588410572800e38");
140
141 //test rounding
142 assert_eq!(format!("{:.1e}", i8::MIN), "-1.3e2");
143 assert_eq!(format!("{:.1e}", i16::MIN), "-3.3e4");
144 assert_eq!(format!("{:.1e}", i32::MIN), "-2.1e9");
145 assert_eq!(format!("{:.1e}", i64::MIN), "-9.2e18");
146 assert_eq!(format!("{:.1e}", i128::MIN), "-1.7e38");
147
148 //test huge precision
149 assert_eq!(format!("{:.1000e}", 1), format!("1.{}e0", "0".repeat(1000)));
150 //test zero precision
151 assert_eq!(format!("{:.0e}", 1), format!("1e0",));
152
153 //test padding with precision (and sign)
154 assert_eq!(format!("{:+10.3e}", 1), " +1.000e0");
79} 155}
80 156
81#[test] 157#[test]
@@ -86,6 +162,8 @@ fn test_format_int_zero() {
86 assert_eq!(format!("{:o}", 0), "0"); 162 assert_eq!(format!("{:o}", 0), "0");
87 assert_eq!(format!("{:x}", 0), "0"); 163 assert_eq!(format!("{:x}", 0), "0");
88 assert_eq!(format!("{:X}", 0), "0"); 164 assert_eq!(format!("{:X}", 0), "0");
165 assert_eq!(format!("{:e}", 0), "0e0");
166 assert_eq!(format!("{:E}", 0), "0E0");
89 167
90 assert_eq!(format!("{}", 0u32), "0"); 168 assert_eq!(format!("{}", 0u32), "0");
91 assert_eq!(format!("{:?}", 0u32), "0"); 169 assert_eq!(format!("{:?}", 0u32), "0");
@@ -93,6 +171,8 @@ fn test_format_int_zero() {
93 assert_eq!(format!("{:o}", 0u32), "0"); 171 assert_eq!(format!("{:o}", 0u32), "0");
94 assert_eq!(format!("{:x}", 0u32), "0"); 172 assert_eq!(format!("{:x}", 0u32), "0");
95 assert_eq!(format!("{:X}", 0u32), "0"); 173 assert_eq!(format!("{:X}", 0u32), "0");
174 assert_eq!(format!("{:e}", 0u32), "0e0");
175 assert_eq!(format!("{:E}", 0u32), "0E0");
96} 176}
97 177
98#[test] 178#[test]
diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs
index 2e8e4da..4fdabed 100644
--- a/src/librustc_mir/const_eval/eval_queries.rs
+++ b/src/librustc_mir/const_eval/eval_queries.rs
@@ -288,7 +288,10 @@ pub fn const_eval_raw_provider<'tcx>(
288 let cid = key.value; 288 let cid = key.value;
289 let def_id = cid.instance.def.def_id(); 289 let def_id = cid.instance.def.def_id();
290 290
291 if def_id.is_local() && tcx.typeck_tables_of(def_id).tainted_by_errors { 291 if def_id.is_local()
292 && tcx.has_typeck_tables(def_id)
293 && tcx.typeck_tables_of(def_id).tainted_by_errors
294 {
292 return Err(ErrorHandled::Reported); 295 return Err(ErrorHandled::Reported);
293 } 296 }
294 297
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs
index 5a4225e..20b9df0 100644
--- a/src/librustc_parse/parser/expr.rs
+++ b/src/librustc_parse/parser/expr.rs
@@ -1832,10 +1832,16 @@ impl<'a> Parser<'a> {
1832 } 1832 }
1833 } 1833 }
1834 Err(mut e) => { 1834 Err(mut e) => {
1835 e.span_label(struct_sp, "while parsing this struct");
1835 if let Some(f) = recovery_field { 1836 if let Some(f) = recovery_field {
1836 fields.push(f); 1837 fields.push(f);
1838 e.span_suggestion(
1839 self.prev_span.shrink_to_hi(),
1840 "try adding a comma",
1841 ",".into(),
1842 Applicability::MachineApplicable,
1843 );
1837 } 1844 }
1838 e.span_label(struct_sp, "while parsing this struct");
1839 e.emit(); 1845 e.emit();
1840 self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore); 1846 self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
1841 self.eat(&token::Comma); 1847 self.eat(&token::Comma);
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 1a505a3..80d914d 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -2280,7 +2280,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
2280 } else if attr.check_name(sym::thread_local) { 2280 } else if attr.check_name(sym::thread_local) {
2281 codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL; 2281 codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
2282 } else if attr.check_name(sym::track_caller) { 2282 } else if attr.check_name(sym::track_caller) {
2283 if tcx.fn_sig(id).abi() != abi::Abi::Rust { 2283 if tcx.is_closure(id) || tcx.fn_sig(id).abi() != abi::Abi::Rust {
2284 struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI") 2284 struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
2285 .emit(); 2285 .emit();
2286 } 2286 }
@@ -2301,7 +2301,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
2301 codegen_fn_attrs.export_name = Some(s); 2301 codegen_fn_attrs.export_name = Some(s);
2302 } 2302 }
2303 } else if attr.check_name(sym::target_feature) { 2303 } else if attr.check_name(sym::target_feature) {
2304 if tcx.fn_sig(id).unsafety() == Unsafety::Normal { 2304 if tcx.is_closure(id) || tcx.fn_sig(id).unsafety() == Unsafety::Normal {
2305 let msg = "`#[target_feature(..)]` can only be applied to `unsafe` functions"; 2305 let msg = "`#[target_feature(..)]` can only be applied to `unsafe` functions";
2306 tcx.sess 2306 tcx.sess
2307 .struct_span_err(attr.span, msg) 2307 .struct_span_err(attr.span, msg)
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index 700e015..04eaba5 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -6,6 +6,7 @@ use crate::fmt::{self, Write};
6use crate::io; 6use crate::io;
7use crate::mem; 7use crate::mem;
8use crate::memchr; 8use crate::memchr;
9use crate::num::NonZeroU8;
9use crate::ops; 10use crate::ops;
10use crate::os::raw::c_char; 11use crate::os::raw::c_char;
11use crate::ptr; 12use crate::ptr;
@@ -741,6 +742,32 @@ impl From<Box<CStr>> for CString {
741 } 742 }
742} 743}
743 744
745#[stable(feature = "cstring_from_vec_of_nonzerou8", since = "1.43.0")]
746impl From<Vec<NonZeroU8>> for CString {
747 /// Converts a [`Vec`]`<`[`NonZeroU8`]`>` into a [`CString`] without
748 /// copying nor checking for inner null bytes.
749 ///
750 /// [`CString`]: ../ffi/struct.CString.html
751 /// [`NonZeroU8`]: ../num/struct.NonZeroU8.html
752 /// [`Vec`]: ../vec/struct.Vec.html
753 #[inline]
754 fn from(v: Vec<NonZeroU8>) -> CString {
755 unsafe {
756 // Transmute `Vec<NonZeroU8>` to `Vec<u8>`.
757 let v: Vec<u8> = {
758 // Safety:
759 // - transmuting between `NonZeroU8` and `u8` is sound;
760 // - `alloc::Layout<NonZeroU8> == alloc::Layout<u8>`.
761 let (ptr, len, cap): (*mut NonZeroU8, _, _) = Vec::into_raw_parts(v);
762 Vec::from_raw_parts(ptr.cast::<u8>(), len, cap)
763 };
764 // Safety: `v` cannot contain null bytes, given the type-level
765 // invariant of `NonZeroU8`.
766 CString::from_vec_unchecked(v)
767 }
768 }
769}
770
744#[stable(feature = "more_box_slice_clone", since = "1.29.0")] 771#[stable(feature = "more_box_slice_clone", since = "1.29.0")]
745impl Clone for Box<CStr> { 772impl Clone for Box<CStr> {
746 #[inline] 773 #[inline]
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index f9c9f22..799585f 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -309,6 +309,7 @@
309#![feature(unboxed_closures)] 309#![feature(unboxed_closures)]
310#![feature(untagged_unions)] 310#![feature(untagged_unions)]
311#![feature(unwind_attributes)] 311#![feature(unwind_attributes)]
312#![feature(vec_into_raw_parts)]
312// NB: the above list is sorted to minimize merge conflicts. 313// NB: the above list is sorted to minimize merge conflicts.
313#![default_lib_allocator] 314#![default_lib_allocator]
314 315
diff --git a/src/libstd/sys/wasi/fs.rs b/src/libstd/sys/wasi/fs.rs
index 04bfdf6..a11f61f 100644
--- a/src/libstd/sys/wasi/fs.rs
+++ b/src/libstd/sys/wasi/fs.rs
@@ -12,7 +12,6 @@ use crate::sys::time::SystemTime;
12use crate::sys::unsupported; 12use crate::sys::unsupported;
13use crate::sys_common::FromInner; 13use crate::sys_common::FromInner;
14 14
15pub use crate::sys_common::fs::copy;
16pub use crate::sys_common::fs::remove_dir_all; 15pub use crate::sys_common::fs::remove_dir_all;
17 16
18pub struct File { 17pub struct File {
@@ -647,3 +646,12 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
647pub fn osstr2str(f: &OsStr) -> io::Result<&str> { 646pub fn osstr2str(f: &OsStr) -> io::Result<&str> {
648 f.to_str().ok_or_else(|| io::Error::new(io::ErrorKind::Other, "input must be utf-8")) 647 f.to_str().ok_or_else(|| io::Error::new(io::ErrorKind::Other, "input must be utf-8"))
649} 648}
649
650pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
651 use crate::fs::File;
652
653 let mut reader = File::open(from)?;
654 let mut writer = File::create(to)?;
655
656 io::copy(&mut reader, &mut writer)
657}
diff --git a/src/test/ui/consts/issue-68684.rs b/src/test/ui/consts/issue-68684.rs
new file mode 100644
index 0000000..c98f199
--- /dev/null
+++ b/src/test/ui/consts/issue-68684.rs
@@ -0,0 +1,15 @@
1// check-pass
2
3enum _Enum {
4 A(),
5}
6
7type _E = _Enum;
8
9const fn _a() -> _Enum {
10 _E::A()
11}
12
13const _A: _Enum = _a();
14
15fn main() {}
diff --git a/src/test/ui/macros/issue-68060.rs b/src/test/ui/macros/issue-68060.rs
new file mode 100644
index 0000000..85ebd66
--- /dev/null
+++ b/src/test/ui/macros/issue-68060.rs
@@ -0,0 +1,16 @@
1// build-fail
2
3#![feature(track_caller)]
4
5fn main() {
6 (0..)
7 .map(
8 #[target_feature(enable = "")]
9 //~^ ERROR: the feature named `` is not valid for this target
10 //~| ERROR: `#[target_feature(..)]` can only be applied to `unsafe` functions
11 #[track_caller]
12 //~^ ERROR: `#[track_caller]` requires Rust ABI
13 |_| (),
14 )
15 .next();
16}
diff --git a/src/test/ui/macros/issue-68060.stderr b/src/test/ui/macros/issue-68060.stderr
new file mode 100644
index 0000000..2308674
--- /dev/null
+++ b/src/test/ui/macros/issue-68060.stderr
@@ -0,0 +1,24 @@
1error: `#[target_feature(..)]` can only be applied to `unsafe` functions
2 --> $DIR/issue-68060.rs:8:13
3 |
4LL | #[target_feature(enable = "")]
5 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can only be applied to `unsafe` functions
6...
7LL | |_| (),
8 | ------ not an `unsafe` function
9
10error: the feature named `` is not valid for this target
11 --> $DIR/issue-68060.rs:8:30
12 |
13LL | #[target_feature(enable = "")]
14 | ^^^^^^^^^^^ `` is not valid for this target
15
16error[E0737]: `#[track_caller]` requires Rust ABI
17 --> $DIR/issue-68060.rs:11:13
18 |
19LL | #[track_caller]
20 | ^^^^^^^^^^^^^^^
21
22error: aborting due to 3 previous errors
23
24For more information about this error, try `rustc --explain E0737`.
diff --git a/src/test/ui/parser/removed-syntax-with-1.stderr b/src/test/ui/parser/removed-syntax-with-1.stderr
index 193138d..c3f747b 100644
--- a/src/test/ui/parser/removed-syntax-with-1.stderr
+++ b/src/test/ui/parser/removed-syntax-with-1.stderr
@@ -2,8 +2,9 @@ error: expected one of `,`, `.`, `?`, `}`, or an operator, found `with`
2 --> $DIR/removed-syntax-with-1.rs:8:25 2 --> $DIR/removed-syntax-with-1.rs:8:25
3 | 3 |
4LL | let b = S { foo: () with a, bar: () }; 4LL | let b = S { foo: () with a, bar: () };
5 | - ^^^^ expected one of `,`, `.`, `?`, `}`, or an operator 5 | - -^^^^ expected one of `,`, `.`, `?`, `}`, or an operator
6 | | 6 | | |
7 | | help: try adding a comma: `,`
7 | while parsing this struct 8 | while parsing this struct
8 9
9error: aborting due to previous error 10error: aborting due to previous error
diff --git a/src/test/ui/suggestions/struct-initializer-comma.rs b/src/test/ui/suggestions/struct-initializer-comma.rs
new file mode 100644
index 0000000..613b976
--- /dev/null
+++ b/src/test/ui/suggestions/struct-initializer-comma.rs
@@ -0,0 +1,13 @@
1struct Foo {
2 first: bool,
3 second: u8,
4}
5
6fn main() {
7 let a = Foo {
8 //~^ ERROR missing field
9 first: true
10 second: 25
11 //~^ ERROR expected one of
12 };
13}
diff --git a/src/test/ui/suggestions/struct-initializer-comma.stderr b/src/test/ui/suggestions/struct-initializer-comma.stderr
new file mode 100644
index 0000000..731e8e1
--- /dev/null
+++ b/src/test/ui/suggestions/struct-initializer-comma.stderr
@@ -0,0 +1,23 @@
1error: expected one of `,`, `.`, `?`, `}`, or an operator, found `second`
2 --> $DIR/struct-initializer-comma.rs:10:9
3 |
4LL | let a = Foo {
5 | --- while parsing this struct
6LL |
7LL | first: true
8 | -
9 | |
10 | expected one of `,`, `.`, `?`, `}`, or an operator
11 | help: try adding a comma: `,`
12LL | second: 25
13 | ^^^^^^ unexpected token
14
15error[E0063]: missing field `second` in initializer of `Foo`
16 --> $DIR/struct-initializer-comma.rs:7:13
17 |
18LL | let a = Foo {
19 | ^^^ missing `second`
20
21error: aborting due to 2 previous errors
22
23For more information about this error, try `rustc --explain E0063`.