Skip to content

Commit 6253754

Browse files
committed
Auto merge of #67575 - Centril:rollup-feikoir, r=Centril
Rollup of 7 pull requests Successful merges: - #67337 (Ensure that evaluating or validating a constant never reads from a static) - #67543 (Add regression tests for fixed ICEs) - #67547 (Cleanup err codes) - #67551 (Add long error code explanation message for E0627) - #67561 (remove `description` from `Error` impls in docs) - #67569 (Clean up unsafety in char::encode_utf8) - #67572 (Use the chocolatey CDN directly to avoid the flaky API) Failed merges: r? @ghost
2 parents a4cd03d + a76d67f commit 6253754

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+491
-115
lines changed

src/ci/scripts/install-msys2.sh

+10-6
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,14 @@ IFS=$'\n\t'
1212
source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
1313

1414
if isWindows; then
15-
for RETRY_COUNT in 1 2 3 4 5 6 7 8 9 10; do
16-
choco install msys2 \
17-
--params="/InstallDir:$(ciCheckoutPath)/msys2 /NoPath" -y --no-progress \
18-
&& mkdir -p "$(ciCheckoutPath)/msys2/home/${USERNAME}" \
19-
&& ciCommandAddPath "$(ciCheckoutPath)/msys2/usr/bin" && break
20-
done
15+
# Pre-followed the api/v2 URL to the CDN since the API can be a bit flakey
16+
curl -sSL https://packages.chocolatey.org/msys2.20190524.0.0.20191030.nupkg > \
17+
msys2.nupkg
18+
curl -sSL https://packages.chocolatey.org/chocolatey-core.extension.1.3.5.1.nupkg > \
19+
chocolatey-core.extension.nupkg
20+
choco install -s . msys2 \
21+
--params="/InstallDir:$(ciCheckoutPath)/msys2 /NoPath" -y --no-progress
22+
rm msys2.nupkg chocolatey-core.extension.nupkg
23+
mkdir -p "$(ciCheckoutPath)/msys2/home/${USERNAME}"
24+
ciCommandAddPath "$(ciCheckoutPath)/msys2/usr/bin"
2125
fi

src/libcore/char/methods.rs

+29-30
Original file line numberDiff line numberDiff line change
@@ -434,36 +434,35 @@ impl char {
434434
#[inline]
435435
pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
436436
let code = self as u32;
437-
// SAFETY: each arm checks the size of the slice and only uses `get_unchecked` unsafe ops
438-
unsafe {
439-
let len = if code < MAX_ONE_B && !dst.is_empty() {
440-
*dst.get_unchecked_mut(0) = code as u8;
441-
1
442-
} else if code < MAX_TWO_B && dst.len() >= 2 {
443-
*dst.get_unchecked_mut(0) = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
444-
*dst.get_unchecked_mut(1) = (code & 0x3F) as u8 | TAG_CONT;
445-
2
446-
} else if code < MAX_THREE_B && dst.len() >= 3 {
447-
*dst.get_unchecked_mut(0) = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
448-
*dst.get_unchecked_mut(1) = (code >> 6 & 0x3F) as u8 | TAG_CONT;
449-
*dst.get_unchecked_mut(2) = (code & 0x3F) as u8 | TAG_CONT;
450-
3
451-
} else if dst.len() >= 4 {
452-
*dst.get_unchecked_mut(0) = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
453-
*dst.get_unchecked_mut(1) = (code >> 12 & 0x3F) as u8 | TAG_CONT;
454-
*dst.get_unchecked_mut(2) = (code >> 6 & 0x3F) as u8 | TAG_CONT;
455-
*dst.get_unchecked_mut(3) = (code & 0x3F) as u8 | TAG_CONT;
456-
4
457-
} else {
458-
panic!(
459-
"encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}",
460-
from_u32_unchecked(code).len_utf8(),
461-
code,
462-
dst.len(),
463-
)
464-
};
465-
from_utf8_unchecked_mut(dst.get_unchecked_mut(..len))
466-
}
437+
let len = self.len_utf8();
438+
match (len, &mut dst[..]) {
439+
(1, [a, ..]) => {
440+
*a = code as u8;
441+
}
442+
(2, [a, b, ..]) => {
443+
*a = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
444+
*b = (code & 0x3F) as u8 | TAG_CONT;
445+
}
446+
(3, [a, b, c, ..]) => {
447+
*a = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
448+
*b = (code >> 6 & 0x3F) as u8 | TAG_CONT;
449+
*c = (code & 0x3F) as u8 | TAG_CONT;
450+
}
451+
(4, [a, b, c, d, ..]) => {
452+
*a = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
453+
*b = (code >> 12 & 0x3F) as u8 | TAG_CONT;
454+
*c = (code >> 6 & 0x3F) as u8 | TAG_CONT;
455+
*d = (code & 0x3F) as u8 | TAG_CONT;
456+
}
457+
_ => panic!(
458+
"encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}",
459+
len,
460+
code,
461+
dst.len(),
462+
),
463+
};
464+
// SAFETY: We just wrote UTF-8 content in, so converting to str is fine.
465+
unsafe { from_utf8_unchecked_mut(&mut dst[..len]) }
467466
}
468467

469468
/// Encodes this character as UTF-16 into the provided `u16` buffer,

src/libcore/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@
129129
#![feature(associated_type_bounds)]
130130
#![feature(const_type_id)]
131131
#![feature(const_caller_location)]
132+
#![feature(slice_patterns)]
132133

133134
#[prelude_import]
134135
#[allow(unused)]

src/librustc/traits/error_reporting.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2373,7 +2373,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
23732373
let span = self.tcx.def_span(generator_did);
23742374

23752375
// Do not ICE on closure typeck (#66868).
2376-
if let None = self.tcx.hir().as_local_hir_id(generator_did) {
2376+
if self.tcx.hir().as_local_hir_id(generator_did).is_none() {
23772377
return false;
23782378
}
23792379

src/librustc_error_codes/error_codes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ E0622: include_str!("./error_codes/E0622.md"),
346346
E0623: include_str!("./error_codes/E0623.md"),
347347
E0624: include_str!("./error_codes/E0624.md"),
348348
E0626: include_str!("./error_codes/E0626.md"),
349+
E0627: include_str!("./error_codes/E0627.md"),
349350
E0631: include_str!("./error_codes/E0631.md"),
350351
E0633: include_str!("./error_codes/E0633.md"),
351352
E0635: include_str!("./error_codes/E0635.md"),
@@ -574,7 +575,6 @@ E0745: include_str!("./error_codes/E0745.md"),
574575
// E0612, // merged into E0609
575576
// E0613, // Removed (merged with E0609)
576577
E0625, // thread-local statics cannot be accessed at compile-time
577-
E0627, // yield statement outside of generator literal
578578
E0628, // generators cannot have explicit parameters
579579
E0629, // missing 'feature' (rustc_const_unstable)
580580
// rustc_const_unstable attribute must be paired with stable/unstable

src/librustc_error_codes/error_codes/E0124.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
You declared two fields of a struct with the same name. Erroneous code
2-
example:
1+
A struct was declared with two fields having the same name.
2+
3+
Erroneous code example:
34

45
```compile_fail,E0124
56
struct Foo {

src/librustc_error_codes/error_codes/E0128.md

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
Type parameter defaults can only use parameters that occur before them.
1+
A type parameter with default value is using forward declared identifier.
2+
23
Erroneous code example:
34

45
```compile_fail,E0128
@@ -7,11 +8,11 @@ struct Foo<T = U, U = ()> {
78
field2: U,
89
}
910
// error: type parameters with a default cannot use forward declared
10-
// identifiers
11+
// identifiers
1112
```
1213

13-
Since type parameters are evaluated in-order, you may be able to fix this issue
14-
by doing:
14+
Type parameter defaults can only use parameters that occur before them. Since
15+
type parameters are evaluated in-order, this issue could be fixed by doing:
1516

1617
```
1718
struct Foo<U = (), T = U> {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
A yield expression was used outside of the generator literal.
2+
3+
Erroneous code example:
4+
5+
```compile_fail,E0627
6+
#![feature(generators, generator_trait)]
7+
8+
fn fake_generator() -> &'static str {
9+
yield 1;
10+
return "foo"
11+
}
12+
13+
fn main() {
14+
let mut generator = fake_generator;
15+
}
16+
```
17+
18+
The error occurs because keyword `yield` can only be used inside the generator
19+
literal. This can be fixed by constructing the generator correctly.
20+
21+
```
22+
#![feature(generators, generator_trait)]
23+
24+
fn main() {
25+
let mut generator = || {
26+
yield 1;
27+
return "foo"
28+
};
29+
}
30+
```

src/librustc_mir/borrow_check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1424,7 +1424,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
14241424
}
14251425

14261426
/// Reports an error if this is a borrow of local data.
1427-
/// This is called for all Yield statements on movable generators
1427+
/// This is called for all Yield expressions on movable generators
14281428
fn check_for_local_borrow(&mut self, borrow: &BorrowData<'tcx>, yield_span: Span) {
14291429
debug!("check_for_local_borrow({:?})", borrow);
14301430

src/librustc_mir/borrow_check/path_utils.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ pub(super) fn is_active<'tcx>(
131131
}
132132

133133
/// Determines if a given borrow is borrowing local data
134-
/// This is called for all Yield statements on movable generators
134+
/// This is called for all Yield expressions on movable generators
135135
pub(super) fn borrow_of_local_data(place: &Place<'_>) -> bool {
136136
match place.base {
137137
PlaceBase::Static(_) => false,

src/librustc_mir/const_eval.rs

+41-12
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,15 @@ fn mk_eval_cx<'mir, 'tcx>(
4545
tcx: TyCtxt<'tcx>,
4646
span: Span,
4747
param_env: ty::ParamEnv<'tcx>,
48+
can_access_statics: bool,
4849
) -> CompileTimeEvalContext<'mir, 'tcx> {
4950
debug!("mk_eval_cx: {:?}", param_env);
50-
InterpCx::new(tcx.at(span), param_env, CompileTimeInterpreter::new(), Default::default())
51+
InterpCx::new(
52+
tcx.at(span),
53+
param_env,
54+
CompileTimeInterpreter::new(),
55+
MemoryExtra { can_access_statics },
56+
)
5157
}
5258

5359
fn op_to_const<'tcx>(
@@ -176,6 +182,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
176182
#[derive(Clone, Debug)]
177183
pub enum ConstEvalError {
178184
NeedsRfc(String),
185+
ConstAccessesStatic,
179186
}
180187

181188
impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalError {
@@ -195,6 +202,7 @@ impl fmt::Display for ConstEvalError {
195202
msg
196203
)
197204
}
205+
ConstAccessesStatic => write!(f, "constant accesses static"),
198206
}
199207
}
200208
}
@@ -204,6 +212,7 @@ impl Error for ConstEvalError {
204212
use self::ConstEvalError::*;
205213
match *self {
206214
NeedsRfc(_) => "this feature needs an rfc before being allowed inside constants",
215+
ConstAccessesStatic => "constant accesses static",
207216
}
208217
}
209218

@@ -224,6 +233,12 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> {
224233
pub(super) loop_detector: snapshot::InfiniteLoopDetector<'mir, 'tcx>,
225234
}
226235

236+
#[derive(Copy, Clone, Debug)]
237+
pub struct MemoryExtra {
238+
/// Whether this machine may read from statics
239+
can_access_statics: bool,
240+
}
241+
227242
impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
228243
fn new() -> Self {
229244
CompileTimeInterpreter {
@@ -311,7 +326,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
311326
type ExtraFnVal = !;
312327

313328
type FrameExtra = ();
314-
type MemoryExtra = ();
329+
type MemoryExtra = MemoryExtra;
315330
type AllocExtra = ();
316331

317332
type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>;
@@ -473,7 +488,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
473488

474489
#[inline(always)]
475490
fn init_allocation_extra<'b>(
476-
_memory_extra: &(),
491+
_memory_extra: &MemoryExtra,
477492
_id: AllocId,
478493
alloc: Cow<'b, Allocation>,
479494
_kind: Option<MemoryKind<!>>,
@@ -484,7 +499,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
484499

485500
#[inline(always)]
486501
fn tag_static_base_pointer(
487-
_memory_extra: &(),
502+
_memory_extra: &MemoryExtra,
488503
_id: AllocId,
489504
) -> Self::PointerTag {
490505
()
@@ -527,6 +542,17 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
527542
fn stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
528543
Ok(())
529544
}
545+
546+
fn before_access_static(
547+
memory_extra: &MemoryExtra,
548+
_allocation: &Allocation,
549+
) -> InterpResult<'tcx> {
550+
if memory_extra.can_access_statics {
551+
Ok(())
552+
} else {
553+
Err(ConstEvalError::ConstAccessesStatic.into())
554+
}
555+
}
530556
}
531557

532558
/// Extracts a field of a (variant of a) const.
@@ -540,7 +566,7 @@ pub fn const_field<'tcx>(
540566
value: &'tcx ty::Const<'tcx>,
541567
) -> &'tcx ty::Const<'tcx> {
542568
trace!("const_field: {:?}, {:?}", field, value);
543-
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
569+
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
544570
// get the operand again
545571
let op = ecx.eval_const_to_op(value, None).unwrap();
546572
// downcast
@@ -560,7 +586,7 @@ pub fn const_caller_location<'tcx>(
560586
(file, line, col): (Symbol, u32, u32),
561587
) -> &'tcx ty::Const<'tcx> {
562588
trace!("const_caller_location: {}:{}:{}", file, line, col);
563-
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all());
589+
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false);
564590

565591
let loc_ty = tcx.caller_location_ty();
566592
let loc_place = ecx.alloc_caller_location(file, line, col);
@@ -581,7 +607,7 @@ pub fn const_variant_index<'tcx>(
581607
val: &'tcx ty::Const<'tcx>,
582608
) -> VariantIdx {
583609
trace!("const_variant_index: {:?}", val);
584-
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
610+
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
585611
let op = ecx.eval_const_to_op(val, None).unwrap();
586612
ecx.read_discriminant(op).unwrap().1
587613
}
@@ -610,7 +636,9 @@ fn validate_and_turn_into_const<'tcx>(
610636
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
611637
) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
612638
let cid = key.value;
613-
let ecx = mk_eval_cx(tcx, tcx.def_span(key.value.instance.def_id()), key.param_env);
639+
let def_id = cid.instance.def.def_id();
640+
let is_static = tcx.is_static(def_id);
641+
let ecx = mk_eval_cx(tcx, tcx.def_span(key.value.instance.def_id()), key.param_env, is_static);
614642
let val = (|| {
615643
let mplace = ecx.raw_const_to_mplace(constant)?;
616644
let mut ref_tracking = RefTracking::new(mplace);
@@ -624,8 +652,7 @@ fn validate_and_turn_into_const<'tcx>(
624652
// Now that we validated, turn this into a proper constant.
625653
// Statics/promoteds are always `ByRef`, for the rest `op_to_const` decides
626654
// whether they become immediates.
627-
let def_id = cid.instance.def.def_id();
628-
if tcx.is_static(def_id) || cid.promoted.is_some() {
655+
if is_static || cid.promoted.is_some() {
629656
let ptr = mplace.ptr.to_ptr()?;
630657
Ok(tcx.mk_const(ty::Const {
631658
val: ty::ConstKind::Value(ConstValue::ByRef {
@@ -732,12 +759,14 @@ pub fn const_eval_raw_provider<'tcx>(
732759
return Err(ErrorHandled::Reported);
733760
}
734761

762+
let is_static = tcx.is_static(def_id);
763+
735764
let span = tcx.def_span(cid.instance.def_id());
736765
let mut ecx = InterpCx::new(
737766
tcx.at(span),
738767
key.param_env,
739768
CompileTimeInterpreter::new(),
740-
Default::default()
769+
MemoryExtra { can_access_statics: is_static },
741770
);
742771

743772
let res = ecx.load_mir(cid.instance.def, cid.promoted);
@@ -751,7 +780,7 @@ pub fn const_eval_raw_provider<'tcx>(
751780
}).map_err(|error| {
752781
let err = error_to_const_error(&ecx, error);
753782
// errors in statics are always emitted as fatal errors
754-
if tcx.is_static(def_id) {
783+
if is_static {
755784
// Ensure that if the above error was either `TooGeneric` or `Reported`
756785
// an error must be reported.
757786
let v = err.report_as_error(ecx.tcx, "could not evaluate static initializer");

0 commit comments

Comments
 (0)