Skip to content

Commit

Permalink
Auto merge of #67575 - Centril:rollup-feikoir, r=Centril
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Dec 24, 2019
2 parents a4cd03d + a76d67f commit 6253754
Show file tree
Hide file tree
Showing 43 changed files with 491 additions and 115 deletions.
16 changes: 10 additions & 6 deletions src/ci/scripts/install-msys2.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ IFS=$'\n\t'
source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"

if isWindows; then
for RETRY_COUNT in 1 2 3 4 5 6 7 8 9 10; do
choco install msys2 \
--params="/InstallDir:$(ciCheckoutPath)/msys2 /NoPath" -y --no-progress \
&& mkdir -p "$(ciCheckoutPath)/msys2/home/${USERNAME}" \
&& ciCommandAddPath "$(ciCheckoutPath)/msys2/usr/bin" && break
done
# Pre-followed the api/v2 URL to the CDN since the API can be a bit flakey
curl -sSL https://packages.chocolatey.org/msys2.20190524.0.0.20191030.nupkg > \
msys2.nupkg
curl -sSL https://packages.chocolatey.org/chocolatey-core.extension.1.3.5.1.nupkg > \
chocolatey-core.extension.nupkg
choco install -s . msys2 \
--params="/InstallDir:$(ciCheckoutPath)/msys2 /NoPath" -y --no-progress
rm msys2.nupkg chocolatey-core.extension.nupkg
mkdir -p "$(ciCheckoutPath)/msys2/home/${USERNAME}"
ciCommandAddPath "$(ciCheckoutPath)/msys2/usr/bin"
fi
59 changes: 29 additions & 30 deletions src/libcore/char/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,36 +434,35 @@ impl char {
#[inline]
pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
let code = self as u32;
// SAFETY: each arm checks the size of the slice and only uses `get_unchecked` unsafe ops
unsafe {
let len = if code < MAX_ONE_B && !dst.is_empty() {
*dst.get_unchecked_mut(0) = code as u8;
1
} else if code < MAX_TWO_B && dst.len() >= 2 {
*dst.get_unchecked_mut(0) = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
*dst.get_unchecked_mut(1) = (code & 0x3F) as u8 | TAG_CONT;
2
} else if code < MAX_THREE_B && dst.len() >= 3 {
*dst.get_unchecked_mut(0) = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
*dst.get_unchecked_mut(1) = (code >> 6 & 0x3F) as u8 | TAG_CONT;
*dst.get_unchecked_mut(2) = (code & 0x3F) as u8 | TAG_CONT;
3
} else if dst.len() >= 4 {
*dst.get_unchecked_mut(0) = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
*dst.get_unchecked_mut(1) = (code >> 12 & 0x3F) as u8 | TAG_CONT;
*dst.get_unchecked_mut(2) = (code >> 6 & 0x3F) as u8 | TAG_CONT;
*dst.get_unchecked_mut(3) = (code & 0x3F) as u8 | TAG_CONT;
4
} else {
panic!(
"encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}",
from_u32_unchecked(code).len_utf8(),
code,
dst.len(),
)
};
from_utf8_unchecked_mut(dst.get_unchecked_mut(..len))
}
let len = self.len_utf8();
match (len, &mut dst[..]) {
(1, [a, ..]) => {
*a = code as u8;
}
(2, [a, b, ..]) => {
*a = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
*b = (code & 0x3F) as u8 | TAG_CONT;
}
(3, [a, b, c, ..]) => {
*a = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
*b = (code >> 6 & 0x3F) as u8 | TAG_CONT;
*c = (code & 0x3F) as u8 | TAG_CONT;
}
(4, [a, b, c, d, ..]) => {
*a = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
*b = (code >> 12 & 0x3F) as u8 | TAG_CONT;
*c = (code >> 6 & 0x3F) as u8 | TAG_CONT;
*d = (code & 0x3F) as u8 | TAG_CONT;
}
_ => panic!(
"encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}",
len,
code,
dst.len(),
),
};
// SAFETY: We just wrote UTF-8 content in, so converting to str is fine.
unsafe { from_utf8_unchecked_mut(&mut dst[..len]) }
}

/// Encodes this character as UTF-16 into the provided `u16` buffer,
Expand Down
1 change: 1 addition & 0 deletions src/libcore/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@
#![feature(associated_type_bounds)]
#![feature(const_type_id)]
#![feature(const_caller_location)]
#![feature(slice_patterns)]

#[prelude_import]
#[allow(unused)]
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2373,7 +2373,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let span = self.tcx.def_span(generator_did);

// Do not ICE on closure typeck (#66868).
if let None = self.tcx.hir().as_local_hir_id(generator_did) {
if self.tcx.hir().as_local_hir_id(generator_did).is_none() {
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_error_codes/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ E0622: include_str!("./error_codes/E0622.md"),
E0623: include_str!("./error_codes/E0623.md"),
E0624: include_str!("./error_codes/E0624.md"),
E0626: include_str!("./error_codes/E0626.md"),
E0627: include_str!("./error_codes/E0627.md"),
E0631: include_str!("./error_codes/E0631.md"),
E0633: include_str!("./error_codes/E0633.md"),
E0635: include_str!("./error_codes/E0635.md"),
Expand Down Expand Up @@ -574,7 +575,6 @@ E0745: include_str!("./error_codes/E0745.md"),
// E0612, // merged into E0609
// E0613, // Removed (merged with E0609)
E0625, // thread-local statics cannot be accessed at compile-time
E0627, // yield statement outside of generator literal
E0628, // generators cannot have explicit parameters
E0629, // missing 'feature' (rustc_const_unstable)
// rustc_const_unstable attribute must be paired with stable/unstable
Expand Down
5 changes: 3 additions & 2 deletions src/librustc_error_codes/error_codes/E0124.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
You declared two fields of a struct with the same name. Erroneous code
example:
A struct was declared with two fields having the same name.

Erroneous code example:

```compile_fail,E0124
struct Foo {
Expand Down
9 changes: 5 additions & 4 deletions src/librustc_error_codes/error_codes/E0128.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Type parameter defaults can only use parameters that occur before them.
A type parameter with default value is using forward declared identifier.

Erroneous code example:

```compile_fail,E0128
Expand All @@ -7,11 +8,11 @@ struct Foo<T = U, U = ()> {
field2: U,
}
// error: type parameters with a default cannot use forward declared
// identifiers
// identifiers
```

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

```
struct Foo<U = (), T = U> {
Expand Down
30 changes: 30 additions & 0 deletions src/librustc_error_codes/error_codes/E0627.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
A yield expression was used outside of the generator literal.

Erroneous code example:

```compile_fail,E0627
#![feature(generators, generator_trait)]
fn fake_generator() -> &'static str {
yield 1;
return "foo"
}
fn main() {
let mut generator = fake_generator;
}
```

The error occurs because keyword `yield` can only be used inside the generator
literal. This can be fixed by constructing the generator correctly.

```
#![feature(generators, generator_trait)]
fn main() {
let mut generator = || {
yield 1;
return "foo"
};
}
```
2 changes: 1 addition & 1 deletion src/librustc_mir/borrow_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1424,7 +1424,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}

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

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/borrow_check/path_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ pub(super) fn is_active<'tcx>(
}

/// Determines if a given borrow is borrowing local data
/// This is called for all Yield statements on movable generators
/// This is called for all Yield expressions on movable generators
pub(super) fn borrow_of_local_data(place: &Place<'_>) -> bool {
match place.base {
PlaceBase::Static(_) => false,
Expand Down
53 changes: 41 additions & 12 deletions src/librustc_mir/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,15 @@ fn mk_eval_cx<'mir, 'tcx>(
tcx: TyCtxt<'tcx>,
span: Span,
param_env: ty::ParamEnv<'tcx>,
can_access_statics: bool,
) -> CompileTimeEvalContext<'mir, 'tcx> {
debug!("mk_eval_cx: {:?}", param_env);
InterpCx::new(tcx.at(span), param_env, CompileTimeInterpreter::new(), Default::default())
InterpCx::new(
tcx.at(span),
param_env,
CompileTimeInterpreter::new(),
MemoryExtra { can_access_statics },
)
}

fn op_to_const<'tcx>(
Expand Down Expand Up @@ -176,6 +182,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
#[derive(Clone, Debug)]
pub enum ConstEvalError {
NeedsRfc(String),
ConstAccessesStatic,
}

impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalError {
Expand All @@ -195,6 +202,7 @@ impl fmt::Display for ConstEvalError {
msg
)
}
ConstAccessesStatic => write!(f, "constant accesses static"),
}
}
}
Expand All @@ -204,6 +212,7 @@ impl Error for ConstEvalError {
use self::ConstEvalError::*;
match *self {
NeedsRfc(_) => "this feature needs an rfc before being allowed inside constants",
ConstAccessesStatic => "constant accesses static",
}
}

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

#[derive(Copy, Clone, Debug)]
pub struct MemoryExtra {
/// Whether this machine may read from statics
can_access_statics: bool,
}

impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
fn new() -> Self {
CompileTimeInterpreter {
Expand Down Expand Up @@ -311,7 +326,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
type ExtraFnVal = !;

type FrameExtra = ();
type MemoryExtra = ();
type MemoryExtra = MemoryExtra;
type AllocExtra = ();

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

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

#[inline(always)]
fn tag_static_base_pointer(
_memory_extra: &(),
_memory_extra: &MemoryExtra,
_id: AllocId,
) -> Self::PointerTag {
()
Expand Down Expand Up @@ -527,6 +542,17 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
fn stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
Ok(())
}

fn before_access_static(
memory_extra: &MemoryExtra,
_allocation: &Allocation,
) -> InterpResult<'tcx> {
if memory_extra.can_access_statics {
Ok(())
} else {
Err(ConstEvalError::ConstAccessesStatic.into())
}
}
}

/// Extracts a field of a (variant of a) const.
Expand All @@ -540,7 +566,7 @@ pub fn const_field<'tcx>(
value: &'tcx ty::Const<'tcx>,
) -> &'tcx ty::Const<'tcx> {
trace!("const_field: {:?}, {:?}", field, value);
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
// get the operand again
let op = ecx.eval_const_to_op(value, None).unwrap();
// downcast
Expand All @@ -560,7 +586,7 @@ pub fn const_caller_location<'tcx>(
(file, line, col): (Symbol, u32, u32),
) -> &'tcx ty::Const<'tcx> {
trace!("const_caller_location: {}:{}:{}", file, line, col);
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all());
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false);

let loc_ty = tcx.caller_location_ty();
let loc_place = ecx.alloc_caller_location(file, line, col);
Expand All @@ -581,7 +607,7 @@ pub fn const_variant_index<'tcx>(
val: &'tcx ty::Const<'tcx>,
) -> VariantIdx {
trace!("const_variant_index: {:?}", val);
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
let op = ecx.eval_const_to_op(val, None).unwrap();
ecx.read_discriminant(op).unwrap().1
}
Expand Down Expand Up @@ -610,7 +636,9 @@ fn validate_and_turn_into_const<'tcx>(
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
let cid = key.value;
let ecx = mk_eval_cx(tcx, tcx.def_span(key.value.instance.def_id()), key.param_env);
let def_id = cid.instance.def.def_id();
let is_static = tcx.is_static(def_id);
let ecx = mk_eval_cx(tcx, tcx.def_span(key.value.instance.def_id()), key.param_env, is_static);
let val = (|| {
let mplace = ecx.raw_const_to_mplace(constant)?;
let mut ref_tracking = RefTracking::new(mplace);
Expand All @@ -624,8 +652,7 @@ fn validate_and_turn_into_const<'tcx>(
// Now that we validated, turn this into a proper constant.
// Statics/promoteds are always `ByRef`, for the rest `op_to_const` decides
// whether they become immediates.
let def_id = cid.instance.def.def_id();
if tcx.is_static(def_id) || cid.promoted.is_some() {
if is_static || cid.promoted.is_some() {
let ptr = mplace.ptr.to_ptr()?;
Ok(tcx.mk_const(ty::Const {
val: ty::ConstKind::Value(ConstValue::ByRef {
Expand Down Expand Up @@ -732,12 +759,14 @@ pub fn const_eval_raw_provider<'tcx>(
return Err(ErrorHandled::Reported);
}

let is_static = tcx.is_static(def_id);

let span = tcx.def_span(cid.instance.def_id());
let mut ecx = InterpCx::new(
tcx.at(span),
key.param_env,
CompileTimeInterpreter::new(),
Default::default()
MemoryExtra { can_access_statics: is_static },
);

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

0 comments on commit 6253754

Please sign in to comment.