Skip to content
Permalink
Browse files

Auto merge of #63498 - Mark-Simulacrum:stable-next, r=Mark-Simulacrum

1.37.0 stable

This promotes beta to stable and backports a few PRs:

 - Avoid ICE when referencing desugared local binding in borrow error (#63051)
 - Don't access a static just for its size and alignment (#62982) via 331e09b
  • Loading branch information...
bors committed Aug 13, 2019
2 parents 3f55461 + c9be294 commit eae3437dfe991621e8afdc82734f4a172d7ddf9b
@@ -30,6 +30,10 @@ steps:
- bash: printenv | sort - bash: printenv | sort
displayName: Show environment variables displayName: Show environment variables


# Log the date, even on failure. Attempting to debug SSL certificate errors.
- bash: date
displayName: Print out date (before build)

- bash: | - bash: |
set -e set -e
df -h df -h
@@ -198,3 +202,8 @@ steps:
condition: variables['AWS_SECRET_ACCESS_KEY'] condition: variables['AWS_SECRET_ACCESS_KEY']
continueOnError: true continueOnError: true
displayName: Upload CPU usage statistics displayName: Upload CPU usage statistics

# Log the date, even on failure. Attempting to debug SSL certificate errors.
- bash: date
continueOnError: true
displayName: Print out date (after build)
@@ -45,7 +45,7 @@ fi
# #
# FIXME: need a scheme for changing this `nightly` value to `beta` and `stable` # FIXME: need a scheme for changing this `nightly` value to `beta` and `stable`
# either automatically or manually. # either automatically or manually.
export RUST_RELEASE_CHANNEL=beta export RUST_RELEASE_CHANNEL=stable
if [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then if [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL"
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp"
@@ -1116,19 +1116,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
bug!("try_report_cannot_return_reference_to_local: not a local") bug!("try_report_cannot_return_reference_to_local: not a local")
}; };
match self.body.local_kind(local) { match self.body.local_kind(local) {
LocalKind::ReturnPointer | LocalKind::Temp => { LocalKind::ReturnPointer | LocalKind::Temp => (
( "temporary value".to_string(),
"temporary value".to_string(), "temporary value created here".to_string(),
"temporary value created here".to_string(), ),
) LocalKind::Arg => (
} "function parameter".to_string(),
LocalKind::Arg => { "function parameter borrowed here".to_string(),
( ),
"function parameter".to_string(), LocalKind::Var => (
"function parameter borrowed here".to_string(), "local binding".to_string(),
) "local binding introduced here".to_string(),
}, ),
LocalKind::Var => bug!("local variable without a name"),
} }
}; };


@@ -54,6 +54,11 @@ pub trait AllocMap<K: Hash + Eq, V> {
k: K, k: K,
vacant: impl FnOnce() -> Result<V, E> vacant: impl FnOnce() -> Result<V, E>
) -> Result<&mut V, E>; ) -> Result<&mut V, E>;

/// Read-only lookup.
fn get(&self, k: K) -> Option<&V> {
self.get_or(k, || Err(())).ok()
}
} }


/// Methods of this trait signifies a point where CTFE evaluation would fail /// Methods of this trait signifies a point where CTFE evaluation would fail
@@ -492,13 +492,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
id: AllocId, id: AllocId,
liveness: AllocCheck, liveness: AllocCheck,
) -> InterpResult<'static, (Size, Align)> { ) -> InterpResult<'static, (Size, Align)> {
if let Ok(alloc) = self.get(id) { // # Regular allocations
// Don't use `self.get` here as that will
// a) cause cycles in case `id` refers to a static
// b) duplicate a static's allocation in miri
if let Some((_, alloc)) = self.alloc_map.get(id) {
return Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)); return Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align));
} }
// can't do this in the match argument, we may get cycle errors since the lock would get
// dropped after the match. // # Statics and function pointers
// Can't do this in the match argument, we may get cycle errors since the lock would
// be held throughout the match.
let alloc = self.tcx.alloc_map.lock().get(id); let alloc = self.tcx.alloc_map.lock().get(id);
// Could also be a fn ptr or extern static
match alloc { match alloc {
Some(GlobalAlloc::Function(..)) => { Some(GlobalAlloc::Function(..)) => {
if let AllocCheck::Dereferencable = liveness { if let AllocCheck::Dereferencable = liveness {
@@ -507,28 +512,26 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
} else { } else {
Ok((Size::ZERO, Align::from_bytes(1).unwrap())) Ok((Size::ZERO, Align::from_bytes(1).unwrap()))
} }
} },
// `self.get` would also work, but can cause cycles if a static refers to itself
Some(GlobalAlloc::Static(did)) => { Some(GlobalAlloc::Static(did)) => {
// The only way `get` couldn't have worked here is if this is an extern static // Use size and align of the type.
assert!(self.tcx.is_foreign_item(did));
// Use size and align of the type
let ty = self.tcx.type_of(did); let ty = self.tcx.type_of(did);
let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap(); let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
Ok((layout.size, layout.align.abi)) Ok((layout.size, layout.align.abi))
} },
_ => { Some(GlobalAlloc::Memory(alloc)) =>
if let Ok(alloc) = self.get(id) { // Need to duplicate the logic here, because the global allocations have
Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)) // different associated types than the interpreter-local ones.
} Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)),
else if let AllocCheck::MaybeDead = liveness { // The rest must be dead.
// Deallocated pointers are allowed, we should be able to find None => if let AllocCheck::MaybeDead = liveness {
// them in the map. // Deallocated pointers are allowed, we should be able to find
Ok(*self.dead_alloc_map.get(&id) // them in the map.
.expect("deallocated pointers should all be recorded in `dead_alloc_map`")) Ok(*self.dead_alloc_map.get(&id)
} else { .expect("deallocated pointers should all be recorded in \
err!(DanglingPointerDeref) `dead_alloc_map`"))
} } else {
err!(DanglingPointerDeref)
}, },
} }
} }
@@ -0,0 +1,33 @@
// To avoid leaking the names of local bindings from expressions like for loops, #60984
// explicitly ignored them, but an assertion that `LocalKind::Var` *must* have a name would
// trigger an ICE. Before this change, this file's output would be:
// ```
// error[E0515]: cannot return value referencing local variable `__next`
// --> return-local-binding-from-desugaring.rs:LL:CC
// |
// LL | for ref x in xs {
// | ----- `__next` is borrowed here
// ...
// LL | result
// | ^^^^^^ returns a value referencing data owned by the current function
// ```
// FIXME: ideally `LocalKind` would carry more information to more accurately explain the problem.

use std::collections::HashMap;
use std::hash::Hash;

fn group_by<I, F, T>(xs: &mut I, f: F) -> HashMap<T, Vec<&I::Item>>
where
I: Iterator,
F: Fn(&I::Item) -> T,
T: Eq + Hash,
{
let mut result = HashMap::new();
for ref x in xs {
let key = f(x);
result.entry(key).or_insert(Vec::new()).push(x);
}
result //~ ERROR cannot return value referencing local binding
}

fn main() {}
@@ -0,0 +1,12 @@
error[E0515]: cannot return value referencing local binding
--> $DIR/return-local-binding-from-desugaring.rs:30:5
|
LL | for ref x in xs {
| -- local binding introduced here
...
LL | result
| ^^^^^^ returns a value referencing data owned by the current function

error: aborting due to previous error

For more information about this error, try `rustc --explain E0515`.
@@ -0,0 +1,11 @@
// compile-pass

struct Foo {
foo: Option<&'static Foo>
}

static FOO: Foo = Foo {
foo: Some(&FOO),
};

fn main() {}

0 comments on commit eae3437

Please sign in to comment.
You can’t perform that action at this time.