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
This commit is contained in:
bors 2019-12-24 03:40:33 +00:00
commit 625375400c
43 changed files with 491 additions and 115 deletions

View File

@ -12,10 +12,14 @@ IFS=$'\n\t'
source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
if isWindows; then if isWindows; then
for RETRY_COUNT in 1 2 3 4 5 6 7 8 9 10; do # Pre-followed the api/v2 URL to the CDN since the API can be a bit flakey
choco install msys2 \ curl -sSL https://packages.chocolatey.org/msys2.20190524.0.0.20191030.nupkg > \
--params="/InstallDir:$(ciCheckoutPath)/msys2 /NoPath" -y --no-progress \ msys2.nupkg
&& mkdir -p "$(ciCheckoutPath)/msys2/home/${USERNAME}" \ curl -sSL https://packages.chocolatey.org/chocolatey-core.extension.1.3.5.1.nupkg > \
&& ciCommandAddPath "$(ciCheckoutPath)/msys2/usr/bin" && break chocolatey-core.extension.nupkg
done 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 fi

View File

@ -434,36 +434,35 @@ impl char {
#[inline] #[inline]
pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str { pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
let code = self as u32; let code = self as u32;
// SAFETY: each arm checks the size of the slice and only uses `get_unchecked` unsafe ops let len = self.len_utf8();
unsafe { match (len, &mut dst[..]) {
let len = if code < MAX_ONE_B && !dst.is_empty() { (1, [a, ..]) => {
*dst.get_unchecked_mut(0) = code as u8; *a = code as u8;
1 }
} else if code < MAX_TWO_B && dst.len() >= 2 { (2, [a, b, ..]) => {
*dst.get_unchecked_mut(0) = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; *a = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
*dst.get_unchecked_mut(1) = (code & 0x3F) as u8 | TAG_CONT; *b = (code & 0x3F) as u8 | TAG_CONT;
2 }
} else if code < MAX_THREE_B && dst.len() >= 3 { (3, [a, b, c, ..]) => {
*dst.get_unchecked_mut(0) = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; *a = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
*dst.get_unchecked_mut(1) = (code >> 6 & 0x3F) as u8 | TAG_CONT; *b = (code >> 6 & 0x3F) as u8 | TAG_CONT;
*dst.get_unchecked_mut(2) = (code & 0x3F) as u8 | TAG_CONT; *c = (code & 0x3F) as u8 | TAG_CONT;
3 }
} else if dst.len() >= 4 { (4, [a, b, c, d, ..]) => {
*dst.get_unchecked_mut(0) = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; *a = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
*dst.get_unchecked_mut(1) = (code >> 12 & 0x3F) as u8 | TAG_CONT; *b = (code >> 12 & 0x3F) as u8 | TAG_CONT;
*dst.get_unchecked_mut(2) = (code >> 6 & 0x3F) as u8 | TAG_CONT; *c = (code >> 6 & 0x3F) as u8 | TAG_CONT;
*dst.get_unchecked_mut(3) = (code & 0x3F) as u8 | TAG_CONT; *d = (code & 0x3F) as u8 | TAG_CONT;
4 }
} else { _ => panic!(
panic!( "encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}",
"encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}", len,
from_u32_unchecked(code).len_utf8(), code,
code, dst.len(),
dst.len(), ),
) };
}; // SAFETY: We just wrote UTF-8 content in, so converting to str is fine.
from_utf8_unchecked_mut(dst.get_unchecked_mut(..len)) unsafe { from_utf8_unchecked_mut(&mut dst[..len]) }
}
} }
/// Encodes this character as UTF-16 into the provided `u16` buffer, /// Encodes this character as UTF-16 into the provided `u16` buffer,

View File

@ -129,6 +129,7 @@
#![feature(associated_type_bounds)] #![feature(associated_type_bounds)]
#![feature(const_type_id)] #![feature(const_type_id)]
#![feature(const_caller_location)] #![feature(const_caller_location)]
#![feature(slice_patterns)]
#[prelude_import] #[prelude_import]
#[allow(unused)] #[allow(unused)]

View File

@ -2373,7 +2373,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let span = self.tcx.def_span(generator_did); let span = self.tcx.def_span(generator_did);
// Do not ICE on closure typeck (#66868). // 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; return false;
} }

View File

@ -346,6 +346,7 @@ E0622: include_str!("./error_codes/E0622.md"),
E0623: include_str!("./error_codes/E0623.md"), E0623: include_str!("./error_codes/E0623.md"),
E0624: include_str!("./error_codes/E0624.md"), E0624: include_str!("./error_codes/E0624.md"),
E0626: include_str!("./error_codes/E0626.md"), E0626: include_str!("./error_codes/E0626.md"),
E0627: include_str!("./error_codes/E0627.md"),
E0631: include_str!("./error_codes/E0631.md"), E0631: include_str!("./error_codes/E0631.md"),
E0633: include_str!("./error_codes/E0633.md"), E0633: include_str!("./error_codes/E0633.md"),
E0635: include_str!("./error_codes/E0635.md"), E0635: include_str!("./error_codes/E0635.md"),
@ -574,7 +575,6 @@ E0745: include_str!("./error_codes/E0745.md"),
// E0612, // merged into E0609 // E0612, // merged into E0609
// E0613, // Removed (merged with E0609) // E0613, // Removed (merged with E0609)
E0625, // thread-local statics cannot be accessed at compile-time E0625, // thread-local statics cannot be accessed at compile-time
E0627, // yield statement outside of generator literal
E0628, // generators cannot have explicit parameters E0628, // generators cannot have explicit parameters
E0629, // missing 'feature' (rustc_const_unstable) E0629, // missing 'feature' (rustc_const_unstable)
// rustc_const_unstable attribute must be paired with stable/unstable // rustc_const_unstable attribute must be paired with stable/unstable

View File

@ -1,5 +1,6 @@
You declared two fields of a struct with the same name. Erroneous code A struct was declared with two fields having the same name.
example:
Erroneous code example:
```compile_fail,E0124 ```compile_fail,E0124
struct Foo { struct Foo {

View File

@ -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: Erroneous code example:
```compile_fail,E0128 ```compile_fail,E0128
@ -7,11 +8,11 @@ struct Foo<T = U, U = ()> {
field2: U, field2: U,
} }
// error: type parameters with a default cannot use forward declared // 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 Type parameter defaults can only use parameters that occur before them. Since
by doing: type parameters are evaluated in-order, this issue could be fixed by doing:
``` ```
struct Foo<U = (), T = U> { struct Foo<U = (), T = U> {

View File

@ -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"
};
}
```

View File

@ -1424,7 +1424,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} }
/// Reports an error if this is a borrow of local data. /// 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) { fn check_for_local_borrow(&mut self, borrow: &BorrowData<'tcx>, yield_span: Span) {
debug!("check_for_local_borrow({:?})", borrow); debug!("check_for_local_borrow({:?})", borrow);

View File

@ -131,7 +131,7 @@ pub(super) fn is_active<'tcx>(
} }
/// Determines if a given borrow is borrowing local data /// 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 { pub(super) fn borrow_of_local_data(place: &Place<'_>) -> bool {
match place.base { match place.base {
PlaceBase::Static(_) => false, PlaceBase::Static(_) => false,

View File

@ -45,9 +45,15 @@ fn mk_eval_cx<'mir, 'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
span: Span, span: Span,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
can_access_statics: bool,
) -> CompileTimeEvalContext<'mir, 'tcx> { ) -> CompileTimeEvalContext<'mir, 'tcx> {
debug!("mk_eval_cx: {:?}", param_env); 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>( fn op_to_const<'tcx>(
@ -176,6 +182,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum ConstEvalError { pub enum ConstEvalError {
NeedsRfc(String), NeedsRfc(String),
ConstAccessesStatic,
} }
impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalError { impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalError {
@ -195,6 +202,7 @@ impl fmt::Display for ConstEvalError {
msg msg
) )
} }
ConstAccessesStatic => write!(f, "constant accesses static"),
} }
} }
} }
@ -204,6 +212,7 @@ impl Error for ConstEvalError {
use self::ConstEvalError::*; use self::ConstEvalError::*;
match *self { match *self {
NeedsRfc(_) => "this feature needs an rfc before being allowed inside constants", NeedsRfc(_) => "this feature needs an rfc before being allowed inside constants",
ConstAccessesStatic => "constant accesses static",
} }
} }
@ -224,6 +233,12 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> {
pub(super) loop_detector: snapshot::InfiniteLoopDetector<'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> { impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
fn new() -> Self { fn new() -> Self {
CompileTimeInterpreter { CompileTimeInterpreter {
@ -311,7 +326,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
type ExtraFnVal = !; type ExtraFnVal = !;
type FrameExtra = (); type FrameExtra = ();
type MemoryExtra = (); type MemoryExtra = MemoryExtra;
type AllocExtra = (); type AllocExtra = ();
type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>; type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>;
@ -473,7 +488,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
#[inline(always)] #[inline(always)]
fn init_allocation_extra<'b>( fn init_allocation_extra<'b>(
_memory_extra: &(), _memory_extra: &MemoryExtra,
_id: AllocId, _id: AllocId,
alloc: Cow<'b, Allocation>, alloc: Cow<'b, Allocation>,
_kind: Option<MemoryKind<!>>, _kind: Option<MemoryKind<!>>,
@ -484,7 +499,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
#[inline(always)] #[inline(always)]
fn tag_static_base_pointer( fn tag_static_base_pointer(
_memory_extra: &(), _memory_extra: &MemoryExtra,
_id: AllocId, _id: AllocId,
) -> Self::PointerTag { ) -> Self::PointerTag {
() ()
@ -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> { fn stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
Ok(()) 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. /// Extracts a field of a (variant of a) const.
@ -540,7 +566,7 @@ pub fn const_field<'tcx>(
value: &'tcx ty::Const<'tcx>, value: &'tcx ty::Const<'tcx>,
) -> &'tcx ty::Const<'tcx> { ) -> &'tcx ty::Const<'tcx> {
trace!("const_field: {:?}, {:?}", field, value); 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 // get the operand again
let op = ecx.eval_const_to_op(value, None).unwrap(); let op = ecx.eval_const_to_op(value, None).unwrap();
// downcast // downcast
@ -560,7 +586,7 @@ pub fn const_caller_location<'tcx>(
(file, line, col): (Symbol, u32, u32), (file, line, col): (Symbol, u32, u32),
) -> &'tcx ty::Const<'tcx> { ) -> &'tcx ty::Const<'tcx> {
trace!("const_caller_location: {}:{}:{}", file, line, col); 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_ty = tcx.caller_location_ty();
let loc_place = ecx.alloc_caller_location(file, line, col); let loc_place = ecx.alloc_caller_location(file, line, col);
@ -581,7 +607,7 @@ pub fn const_variant_index<'tcx>(
val: &'tcx ty::Const<'tcx>, val: &'tcx ty::Const<'tcx>,
) -> VariantIdx { ) -> VariantIdx {
trace!("const_variant_index: {:?}", val); 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(); let op = ecx.eval_const_to_op(val, None).unwrap();
ecx.read_discriminant(op).unwrap().1 ecx.read_discriminant(op).unwrap().1
} }
@ -610,7 +636,9 @@ fn validate_and_turn_into_const<'tcx>(
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> { ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
let cid = key.value; 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 val = (|| {
let mplace = ecx.raw_const_to_mplace(constant)?; let mplace = ecx.raw_const_to_mplace(constant)?;
let mut ref_tracking = RefTracking::new(mplace); let mut ref_tracking = RefTracking::new(mplace);
@ -624,8 +652,7 @@ fn validate_and_turn_into_const<'tcx>(
// Now that we validated, turn this into a proper constant. // Now that we validated, turn this into a proper constant.
// Statics/promoteds are always `ByRef`, for the rest `op_to_const` decides // Statics/promoteds are always `ByRef`, for the rest `op_to_const` decides
// whether they become immediates. // whether they become immediates.
let def_id = cid.instance.def.def_id(); if is_static || cid.promoted.is_some() {
if tcx.is_static(def_id) || cid.promoted.is_some() {
let ptr = mplace.ptr.to_ptr()?; let ptr = mplace.ptr.to_ptr()?;
Ok(tcx.mk_const(ty::Const { Ok(tcx.mk_const(ty::Const {
val: ty::ConstKind::Value(ConstValue::ByRef { val: ty::ConstKind::Value(ConstValue::ByRef {
@ -732,12 +759,14 @@ pub fn const_eval_raw_provider<'tcx>(
return Err(ErrorHandled::Reported); return Err(ErrorHandled::Reported);
} }
let is_static = tcx.is_static(def_id);
let span = tcx.def_span(cid.instance.def_id()); let span = tcx.def_span(cid.instance.def_id());
let mut ecx = InterpCx::new( let mut ecx = InterpCx::new(
tcx.at(span), tcx.at(span),
key.param_env, key.param_env,
CompileTimeInterpreter::new(), CompileTimeInterpreter::new(),
Default::default() MemoryExtra { can_access_statics: is_static },
); );
let res = ecx.load_mir(cid.instance.def, cid.promoted); let res = ecx.load_mir(cid.instance.def, cid.promoted);
@ -751,7 +780,7 @@ pub fn const_eval_raw_provider<'tcx>(
}).map_err(|error| { }).map_err(|error| {
let err = error_to_const_error(&ecx, error); let err = error_to_const_error(&ecx, error);
// errors in statics are always emitted as fatal errors // 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` // Ensure that if the above error was either `TooGeneric` or `Reported`
// an error must be reported. // an error must be reported.
let v = err.report_as_error(ecx.tcx, "could not evaluate static initializer"); let v = err.report_as_error(ecx.tcx, "could not evaluate static initializer");

View File

@ -20,7 +20,6 @@ pub trait CompileTimeMachine<'mir, 'tcx> = Machine<
PointerTag = (), PointerTag = (),
ExtraFnVal = !, ExtraFnVal = !,
FrameExtra = (), FrameExtra = (),
MemoryExtra = (),
AllocExtra = (), AllocExtra = (),
MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>, MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>,
>; >;
@ -320,12 +319,20 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
// We can't call the `intern_shallow` method here, as its logic is tailored to safe // We can't call the `intern_shallow` method here, as its logic is tailored to safe
// references and a `leftover_allocations` set (where we only have a todo-list here). // references and a `leftover_allocations` set (where we only have a todo-list here).
// So we hand-roll the interning logic here again. // So we hand-roll the interning logic here again.
if base_intern_mode != InternMode::Static { match base_intern_mode {
// If it's not a static, it *must* be immutable. InternMode::Static => {}
// We cannot have mutable memory inside a constant. InternMode::Const | InternMode::ConstBase => {
// FIXME: ideally we would assert that they already are immutable, to double- // If it's not a static, it *must* be immutable.
// check our static checks. // We cannot have mutable memory inside a constant.
alloc.mutability = Mutability::Not; // We use `delay_span_bug` here, because this can be reached in the presence
// of fancy transmutes.
if alloc.mutability == Mutability::Mut {
// For better errors later, mark the allocation as immutable
// (on top of the delayed ICE).
alloc.mutability = Mutability::Not;
ecx.tcx.sess.delay_span_bug(ecx.tcx.span, "mutable allocation in constant");
}
}
} }
let alloc = tcx.intern_const_alloc(alloc); let alloc = tcx.intern_const_alloc(alloc);
tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc); tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc);
@ -337,6 +344,8 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
} else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) { } else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) {
// dangling pointer // dangling pointer
throw_unsup!(ValidationFailure("encountered dangling pointer in final constant".into())) throw_unsup!(ValidationFailure("encountered dangling pointer in final constant".into()))
} else if ecx.tcx.alloc_map.lock().get(alloc_id).is_none() {
span_bug!(ecx.tcx.span, "encountered unknown alloc id {:?}", alloc_id);
} }
} }
Ok(()) Ok(())

View File

@ -212,7 +212,10 @@ pub trait Machine<'mir, 'tcx>: Sized {
} }
/// Called before a `StaticKind::Static` value is accessed. /// Called before a `StaticKind::Static` value is accessed.
fn before_access_static(_allocation: &Allocation) -> InterpResult<'tcx> { fn before_access_static(
_memory_extra: &Self::MemoryExtra,
_allocation: &Allocation,
) -> InterpResult<'tcx> {
Ok(()) Ok(())
} }

View File

@ -116,7 +116,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M>
// carefully copy only the reachable parts. // carefully copy only the reachable parts.
impl<'mir, 'tcx, M> Clone for Memory<'mir, 'tcx, M> impl<'mir, 'tcx, M> Clone for Memory<'mir, 'tcx, M>
where where
M: Machine<'mir, 'tcx, PointerTag = (), AllocExtra = (), MemoryExtra = ()>, M: Machine<'mir, 'tcx, PointerTag = (), AllocExtra = ()>,
M::MemoryExtra: Copy,
M::MemoryMap: AllocMap<AllocId, (MemoryKind<M::MemoryKinds>, Allocation)>, M::MemoryMap: AllocMap<AllocId, (MemoryKind<M::MemoryKinds>, Allocation)>,
{ {
fn clone(&self) -> Self { fn clone(&self) -> Self {
@ -124,7 +125,7 @@ where
alloc_map: self.alloc_map.clone(), alloc_map: self.alloc_map.clone(),
extra_fn_ptr_map: self.extra_fn_ptr_map.clone(), extra_fn_ptr_map: self.extra_fn_ptr_map.clone(),
dead_alloc_map: self.dead_alloc_map.clone(), dead_alloc_map: self.dead_alloc_map.clone(),
extra: (), extra: self.extra,
tcx: self.tcx, tcx: self.tcx,
} }
} }
@ -455,7 +456,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
let id = raw_const.alloc_id; let id = raw_const.alloc_id;
let allocation = tcx.alloc_map.lock().unwrap_memory(id); let allocation = tcx.alloc_map.lock().unwrap_memory(id);
M::before_access_static(allocation)?; M::before_access_static(memory_extra, allocation)?;
Cow::Borrowed(allocation) Cow::Borrowed(allocation)
} }
} }

View File

@ -224,6 +224,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
} }
fn before_access_static( fn before_access_static(
_memory_extra: &(),
allocation: &Allocation<Self::PointerTag, Self::AllocExtra>, allocation: &Allocation<Self::PointerTag, Self::AllocExtra>,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
// if the static allocation is mutable or if it has relocations (it may be legal to mutate // if the static allocation is mutable or if it has relocations (it may be legal to mutate

View File

@ -1810,7 +1810,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.sess, self.tcx.sess,
expr.span, expr.span,
E0627, E0627,
"yield statement outside of generator literal" "yield expression outside of generator literal"
) )
.emit(); .emit();
} }

View File

@ -91,10 +91,6 @@ pub trait Error: Debug + Display {
/// } /// }
/// ///
/// impl Error for SuperError { /// impl Error for SuperError {
/// fn description(&self) -> &str {
/// "I'm the superhero of errors"
/// }
///
/// fn cause(&self) -> Option<&dyn Error> { /// fn cause(&self) -> Option<&dyn Error> {
/// Some(&self.side) /// Some(&self.side)
/// } /// }
@ -109,11 +105,7 @@ pub trait Error: Debug + Display {
/// } /// }
/// } /// }
/// ///
/// impl Error for SuperErrorSideKick { /// impl Error for SuperErrorSideKick {}
/// fn description(&self) -> &str {
/// "I'm SuperError side kick"
/// }
/// }
/// ///
/// fn get_super_error() -> Result<(), SuperError> { /// fn get_super_error() -> Result<(), SuperError> {
/// Err(SuperError { side: SuperErrorSideKick }) /// Err(SuperError { side: SuperErrorSideKick })
@ -159,10 +151,6 @@ pub trait Error: Debug + Display {
/// } /// }
/// ///
/// impl Error for SuperError { /// impl Error for SuperError {
/// fn description(&self) -> &str {
/// "I'm the superhero of errors"
/// }
///
/// fn source(&self) -> Option<&(dyn Error + 'static)> { /// fn source(&self) -> Option<&(dyn Error + 'static)> {
/// Some(&self.side) /// Some(&self.side)
/// } /// }
@ -177,11 +165,7 @@ pub trait Error: Debug + Display {
/// } /// }
/// } /// }
/// ///
/// impl Error for SuperErrorSideKick { /// impl Error for SuperErrorSideKick {}
/// fn description(&self) -> &str {
/// "I'm SuperError side kick"
/// }
/// }
/// ///
/// fn get_super_error() -> Result<(), SuperError> { /// fn get_super_error() -> Result<(), SuperError> {
/// Err(SuperError { side: SuperErrorSideKick }) /// Err(SuperError { side: SuperErrorSideKick })
@ -261,11 +245,7 @@ impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
/// } /// }
/// } /// }
/// ///
/// impl Error for AnError { /// impl Error for AnError {}
/// fn description(&self) -> &str {
/// "Description of an error"
/// }
/// }
/// ///
/// let an_error = AnError; /// let an_error = AnError;
/// assert!(0 == mem::size_of_val(&an_error)); /// assert!(0 == mem::size_of_val(&an_error));
@ -300,11 +280,7 @@ impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync +
/// } /// }
/// } /// }
/// ///
/// impl Error for AnError { /// impl Error for AnError {}
/// fn description(&self) -> &str {
/// "Description of an error"
/// }
/// }
/// ///
/// unsafe impl Send for AnError {} /// unsafe impl Send for AnError {}
/// ///

View File

@ -402,9 +402,7 @@ impl Error {
/// } /// }
/// } /// }
/// ///
/// impl error::Error for MyError { /// impl error::Error for MyError {}
/// fn description(&self) -> &str { &self.v }
/// }
/// ///
/// impl Display for MyError { /// impl Display for MyError {
/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

View File

@ -0,0 +1,16 @@
// check-pass
#![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
struct Const<const N: usize>;
impl<const C: usize> Const<{C}> {
fn successor() -> Const<{C + 1}> {
Const
}
}
fn main() {
let _x: Const::<2> = Const::<1>::successor();
}

View File

@ -0,0 +1,8 @@
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
--> $DIR/issue-61747.rs:3:12
|
LL | #![feature(const_generics)]
| ^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default

View File

@ -0,0 +1,10 @@
// check-pass
#![allow(incomplete_features, dead_code, unconditional_recursion)]
#![feature(const_generics)]
fn fact<const N: usize>() {
fact::<{ N - 1 }>();
}
fn main() {}

View File

@ -0,0 +1,12 @@
// compile-flags: -Zunleash-the-miri-inside-of-you
#![allow(dead_code)]
const TEST: &u8 = &MY_STATIC;
//~^ skipping const checks
//~| it is undefined behavior to use this value
static MY_STATIC: u8 = 4;
fn main() {
}

View File

@ -0,0 +1,17 @@
warning: skipping const checks
--> $DIR/const-points-to-static.rs:5:20
|
LL | const TEST: &u8 = &MY_STATIC;
| ^^^^^^^^^
error[E0080]: it is undefined behavior to use this value
--> $DIR/const-points-to-static.rs:5:1
|
LL | const TEST: &u8 = &MY_STATIC;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error: aborting due to previous error
For more information about this error, try `rustc --explain E0080`.

View File

@ -1,9 +1,8 @@
// compile-flags: -Zunleash-the-miri-inside-of-you // compile-flags: -Zunleash-the-miri-inside-of-you
// run-pass
#![allow(dead_code)] #![allow(dead_code)]
const TEST: u8 = MY_STATIC; const TEST: u8 = MY_STATIC; //~ ERROR any use of this value will cause an error
//~^ skipping const checks //~^ skipping const checks
static MY_STATIC: u8 = 4; static MY_STATIC: u8 = 4;

View File

@ -1,6 +1,18 @@
warning: skipping const checks warning: skipping const checks
--> $DIR/const-prop-read-static-in-const.rs:6:18 --> $DIR/const-prop-read-static-in-const.rs:5:18
| |
LL | const TEST: u8 = MY_STATIC; LL | const TEST: u8 = MY_STATIC;
| ^^^^^^^^^ | ^^^^^^^^^
error: any use of this value will cause an error
--> $DIR/const-prop-read-static-in-const.rs:5:18
|
LL | const TEST: u8 = MY_STATIC;
| -----------------^^^^^^^^^-
| |
| constant accesses static
|
= note: `#[deny(const_err)]` on by default
error: aborting due to previous error

View File

@ -0,0 +1,38 @@
// compile-flags: -Zunleash-the-miri-inside-of-you
#![warn(const_err)]
#![feature(const_raw_ptr_deref)]
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
const BOO: &usize = { //~ ERROR undefined behavior to use this value
static FOO: AtomicUsize = AtomicUsize::new(0);
unsafe { &*(&FOO as *const _ as *const usize) }
//~^ WARN skipping const checks
};
const FOO: usize = {
static FOO: AtomicUsize = AtomicUsize::new(0);
FOO.fetch_add(1, Ordering::Relaxed) //~ WARN any use of this value will cause an error
//~^ WARN skipping const checks
//~| WARN skipping const checks
};
const BAR: usize = {
static FOO: AtomicUsize = AtomicUsize::new(0);
unsafe { *(&FOO as *const _ as *const usize) } //~ WARN any use of this value will cause an err
//~^ WARN skipping const checks
};
static mut MUTABLE: u32 = 0;
const BAD: u32 = unsafe { MUTABLE }; //~ WARN any use of this value will cause an error
//~^ WARN skipping const checks
// ok some day perhaps
const BOO_OK: &usize = { //~ ERROR it is undefined behavior to use this value
static FOO: usize = 0;
&FOO
//~^ WARN skipping const checks
};
fn main() {}

View File

@ -0,0 +1,100 @@
warning: skipping const checks
--> $DIR/const_refers_to_static.rs:11:18
|
LL | unsafe { &*(&FOO as *const _ as *const usize) }
| ^^^
warning: skipping const checks
--> $DIR/const_refers_to_static.rs:17:5
|
LL | FOO.fetch_add(1, Ordering::Relaxed)
| ^^^
warning: skipping const checks
--> $DIR/const_refers_to_static.rs:17:5
|
LL | FOO.fetch_add(1, Ordering::Relaxed)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: skipping const checks
--> $DIR/const_refers_to_static.rs:24:17
|
LL | unsafe { *(&FOO as *const _ as *const usize) }
| ^^^
warning: skipping const checks
--> $DIR/const_refers_to_static.rs:29:27
|
LL | const BAD: u32 = unsafe { MUTABLE };
| ^^^^^^^
warning: skipping const checks
--> $DIR/const_refers_to_static.rs:35:6
|
LL | &FOO
| ^^^
error[E0080]: it is undefined behavior to use this value
--> $DIR/const_refers_to_static.rs:9:1
|
LL | / const BOO: &usize = {
LL | | static FOO: AtomicUsize = AtomicUsize::new(0);
LL | | unsafe { &*(&FOO as *const _ as *const usize) }
LL | |
LL | | };
| |__^ constant accesses static
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
warning: any use of this value will cause an error
--> $DIR/const_refers_to_static.rs:17:5
|
LL | / const FOO: usize = {
LL | | static FOO: AtomicUsize = AtomicUsize::new(0);
LL | | FOO.fetch_add(1, Ordering::Relaxed)
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `std::sync::atomic::AtomicUsize::fetch_add`
LL | |
LL | |
LL | | };
| |__-
|
note: lint level defined here
--> $DIR/const_refers_to_static.rs:2:9
|
LL | #![warn(const_err)]
| ^^^^^^^^^
warning: any use of this value will cause an error
--> $DIR/const_refers_to_static.rs:24:14
|
LL | / const BAR: usize = {
LL | | static FOO: AtomicUsize = AtomicUsize::new(0);
LL | | unsafe { *(&FOO as *const _ as *const usize) }
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
LL | |
LL | | };
| |__-
warning: any use of this value will cause an error
--> $DIR/const_refers_to_static.rs:29:27
|
LL | const BAD: u32 = unsafe { MUTABLE };
| --------------------------^^^^^^^---
| |
| constant accesses static
error[E0080]: it is undefined behavior to use this value
--> $DIR/const_refers_to_static.rs:33:1
|
LL | / const BOO_OK: &usize = {
LL | | static FOO: usize = 0;
LL | | &FOO
LL | |
LL | | };
| |__^ constant accesses static
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.

View File

@ -0,0 +1,19 @@
// compile-flags: -Zunleash-the-miri-inside-of-you
// failure-status: 101
// rustc-env:RUST_BACKTRACE=0
// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET"
// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS"
// normalize-stderr-test "interpret/intern.rs:[0-9]*:[0-9]*" -> "interpret/intern.rs:LL:CC"
#![feature(const_raw_ptr_deref)]
#![feature(const_mut_refs)]
#![deny(const_err)]
use std::cell::UnsafeCell;
// make sure we do not just intern this as mutable
const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
//~^ WARN: skipping const checks
//~| ERROR: mutable allocation in constant
fn main() {}

View File

@ -0,0 +1,25 @@
warning: skipping const checks
--> $DIR/mutable_const2.rs:15:38
|
LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
| ^^^^^^^^^^^^^^^^^^^^
error: internal compiler error: mutable allocation in constant
--> $DIR/mutable_const2.rs:15:1
|
LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:349:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
error: internal compiler error: unexpected panic
note: the compiler unexpectedly panicked. this is a bug.
note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports
note: rustc VERSION running on TARGET
note: compiler flags: FLAGS

View File

@ -1,6 +1,6 @@
fn main() { fn main() {
yield true; //~ ERROR yield syntax is experimental yield true; //~ ERROR yield syntax is experimental
//~^ ERROR yield statement outside of generator literal //~^ ERROR yield expression outside of generator literal
} }
#[cfg(FALSE)] #[cfg(FALSE)]

View File

@ -25,7 +25,7 @@ LL | yield 0;
= note: for more information, see https://github.com/rust-lang/rust/issues/43122 = note: for more information, see https://github.com/rust-lang/rust/issues/43122
= help: add `#![feature(generators)]` to the crate attributes to enable = help: add `#![feature(generators)]` to the crate attributes to enable
error[E0627]: yield statement outside of generator literal error[E0627]: yield expression outside of generator literal
--> $DIR/feature-gate-generators.rs:2:5 --> $DIR/feature-gate-generators.rs:2:5
| |
LL | yield true; LL | yield true;
@ -33,4 +33,5 @@ LL | yield true;
error: aborting due to 4 previous errors error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0658`. Some errors have detailed explanations: E0627, E0658.
For more information about an error, try `rustc --explain E0627`.

View File

@ -1,6 +1,6 @@
#![feature(generators)] #![feature(generators)]
const A: u8 = { yield 3u8; 3u8}; const A: u8 = { yield 3u8; 3u8};
//~^ ERROR yield statement outside //~^ ERROR yield expression outside
fn main() {} fn main() {}

View File

@ -1,4 +1,4 @@
error[E0627]: yield statement outside of generator literal error[E0627]: yield expression outside of generator literal
--> $DIR/yield-in-const.rs:3:17 --> $DIR/yield-in-const.rs:3:17
| |
LL | const A: u8 = { yield 3u8; 3u8}; LL | const A: u8 = { yield 3u8; 3u8};
@ -6,3 +6,4 @@ LL | const A: u8 = { yield 3u8; 3u8};
error: aborting due to previous error error: aborting due to previous error
For more information about this error, try `rustc --explain E0627`.

View File

@ -1,4 +1,4 @@
#![feature(generators)] #![feature(generators)]
fn main() { yield; } fn main() { yield; }
//~^ ERROR yield statement outside //~^ ERROR yield expression outside

View File

@ -1,4 +1,4 @@
error[E0627]: yield statement outside of generator literal error[E0627]: yield expression outside of generator literal
--> $DIR/yield-in-function.rs:3:13 --> $DIR/yield-in-function.rs:3:13
| |
LL | fn main() { yield; } LL | fn main() { yield; }
@ -6,3 +6,4 @@ LL | fn main() { yield; }
error: aborting due to previous error error: aborting due to previous error
For more information about this error, try `rustc --explain E0627`.

View File

@ -1,6 +1,6 @@
#![feature(generators)] #![feature(generators)]
static B: u8 = { yield 3u8; 3u8}; static B: u8 = { yield 3u8; 3u8};
//~^ ERROR yield statement outside //~^ ERROR yield expression outside
fn main() {} fn main() {}

View File

@ -1,4 +1,4 @@
error[E0627]: yield statement outside of generator literal error[E0627]: yield expression outside of generator literal
--> $DIR/yield-in-static.rs:3:18 --> $DIR/yield-in-static.rs:3:18
| |
LL | static B: u8 = { yield 3u8; 3u8}; LL | static B: u8 = { yield 3u8; 3u8};
@ -6,3 +6,4 @@ LL | static B: u8 = { yield 3u8; 3u8};
error: aborting due to previous error error: aborting due to previous error
For more information about this error, try `rustc --explain E0627`.

View File

@ -0,0 +1,13 @@
// Fixed by #67160
trait Trait1 {
type A;
}
trait Trait2 {
type Type1<B>: Trait1<A=B>;
//~^ ERROR: generic associated types are unstable
//~| ERROR: type-generic associated types are not yet implemented
}
fn main() {}

View File

@ -0,0 +1,20 @@
error[E0658]: generic associated types are unstable
--> $DIR/issue-67424.rs:8:5
|
LL | type Type1<B>: Trait1<A=B>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/44265
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
error: type-generic associated types are not yet implemented
--> $DIR/issue-67424.rs:8:5
|
LL | type Type1<B>: Trait1<A=B>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/44265
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -3,5 +3,6 @@
static A: &'static [u32] = &[1]; static A: &'static [u32] = &[1];
static B: [u32; 1] = [0; A.len()]; static B: [u32; 1] = [0; A.len()];
//~^ ERROR [E0013] //~^ ERROR [E0013]
//~| ERROR evaluation of constant value failed
fn main() {} fn main() {}

View File

@ -4,6 +4,13 @@ error[E0013]: constants cannot refer to statics, use a constant instead
LL | static B: [u32; 1] = [0; A.len()]; LL | static B: [u32; 1] = [0; A.len()];
| ^ | ^
error: aborting due to previous error error[E0080]: evaluation of constant value failed
--> $DIR/issue-52060.rs:4:26
|
LL | static B: [u32; 1] = [0; A.len()];
| ^ constant accesses static
For more information about this error, try `rustc --explain E0013`. error: aborting due to 2 previous errors
Some errors have detailed explanations: E0013, E0080.
For more information about an error, try `rustc --explain E0013`.

View File

@ -0,0 +1,14 @@
// Regression test for #66270, fixed by #66246
struct Bug {
incorrect_field: 0,
//~^ ERROR expected type
}
struct Empty {}
fn main() {
let Bug {
any_field: Empty {},
} = Bug {};
}

View File

@ -0,0 +1,8 @@
error: expected type, found `0`
--> $DIR/issue-66270-pat-struct-parser-recovery.rs:4:22
|
LL | incorrect_field: 0,
| ^ expected type
error: aborting due to previous error