Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 8 pull requests #69463

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
14999dd
Add methods to leak RefCell borrows to references
HeroicKatora Jan 29, 2020
178de46
Add primitive module to libcore/std
Mark-Simulacrum Dec 26, 2019
99b4357
Add tracking number, adjust documentation wording
HeroicKatora Feb 12, 2020
bec5d37
debug_assert a few more raw pointer methods
RalfJung Feb 16, 2020
7a6b451
increase slack for stack size test
RalfJung Feb 17, 2020
e355a33
Deduplicate identifier printing a bit
petrochenkov Feb 22, 2020
9c3ee1b
Bump core::primitive to 1.43
dtolnay Feb 24, 2020
329022d
Address method comments
HeroicKatora Feb 24, 2020
5ae4500
remove redundant clones in librustc_mir_build and librustc_data_struc…
matthiaskrgr Feb 24, 2020
d4a005b
librustc{, codegen_ssa,infer,mir_build}: don't clone types that are copy
matthiaskrgr Feb 24, 2020
1892ff7
librustc_macros: remove redundant single component path import
matthiaskrgr Feb 24, 2020
d134385
syntax: Remove `Nt(Impl,Trait,Foreign)Item`
petrochenkov Feb 24, 2020
245e15b
parse: extract `parse_stmt_item` & `parse_stmt_path_start`.
Centril Feb 23, 2020
32295ae
parse: simplify `parse_stmt_without_recovery`.
Centril Feb 23, 2020
1eb0844
parse: move condition into guard
Centril Feb 24, 2020
7876711
parse: address nitpick
Centril Feb 25, 2020
f56042f
Clean up E0370 explanation
GuillaumeGomez Feb 25, 2020
d6f83c5
Clean up E0371 explanation
GuillaumeGomez Feb 25, 2020
724e410
Rollup merge of #67637 - Mark-Simulacrum:primitive-mod, r=dtolnay
Dylan-DPC Feb 25, 2020
ef7c928
Rollup merge of #68712 - HeroicKatora:finalize-ref-cell, r=dtolnay
Dylan-DPC Feb 25, 2020
8677ad3
Rollup merge of #69208 - RalfJung:debug-assert, r=Mark-Simulacrum
Dylan-DPC Feb 25, 2020
9e487c8
Rollup merge of #69387 - petrochenkov:idprint, r=Mark-Simulacrum
Dylan-DPC Feb 25, 2020
55deb79
Rollup merge of #69423 - petrochenkov:nont, r=Centril
Dylan-DPC Feb 25, 2020
50241a7
Rollup merge of #69429 - matthiaskrgr:clippy_, r=estebank
Dylan-DPC Feb 25, 2020
2b7d4e8
Rollup merge of #69447 - Centril:minor-stmt-refactor, r=estebank
Dylan-DPC Feb 25, 2020
6e392e2
Rollup merge of #69457 - GuillaumeGomez:clean-up-e0370-e0371, r=Dylan…
Dylan-DPC Feb 25, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions src/libcore/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1245,6 +1245,38 @@ impl<'b, T: ?Sized> Ref<'b, T> {
let borrow = orig.borrow.clone();
(Ref { value: a, borrow }, Ref { value: b, borrow: orig.borrow })
}

/// Convert into a reference to the underlying data.
///
/// The underlying `RefCell` can never be mutably borrowed from again and will always appear
/// already immutably borrowed. It is not a good idea to leak more than a constant number of
/// references. The `RefCell` can be immutably borrowed again if only a smaller number of leaks
/// have occurred in total.
///
/// This is an associated function that needs to be used as
/// `Ref::leak(...)`. A method would interfere with methods of the
/// same name on the contents of a `RefCell` used through `Deref`.
///
/// # Examples
///
/// ```
/// #![feature(cell_leak)]
/// use std::cell::{RefCell, Ref};
/// let cell = RefCell::new(0);
///
/// let value = Ref::leak(cell.borrow());
/// assert_eq!(*value, 0);
///
/// assert!(cell.try_borrow().is_ok());
/// assert!(cell.try_borrow_mut().is_err());
/// ```
#[unstable(feature = "cell_leak", issue = "69099")]
pub fn leak(orig: Ref<'b, T>) -> &'b T {
// By forgetting this Ref we ensure that the borrow counter in the RefCell never goes back
// to UNUSED again. No further mutable references can be created from the original cell.
mem::forget(orig.borrow);
orig.value
}
}

#[unstable(feature = "coerce_unsized", issue = "27732")]
Expand Down Expand Up @@ -1330,6 +1362,37 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
let borrow = orig.borrow.clone();
(RefMut { value: a, borrow }, RefMut { value: b, borrow: orig.borrow })
}

/// Convert into a mutable reference to the underlying data.
///
/// The underlying `RefCell` can not be borrowed from again and will always appear already
/// mutably borrowed, making the returned reference the only to the interior.
///
/// This is an associated function that needs to be used as
/// `RefMut::leak(...)`. A method would interfere with methods of the
/// same name on the contents of a `RefCell` used through `Deref`.
///
/// # Examples
///
/// ```
/// #![feature(cell_leak)]
/// use std::cell::{RefCell, RefMut};
/// let cell = RefCell::new(0);
///
/// let value = RefMut::leak(cell.borrow_mut());
/// assert_eq!(*value, 0);
/// *value = 1;
///
/// assert!(cell.try_borrow_mut().is_err());
/// ```
#[unstable(feature = "cell_leak", issue = "69099")]
pub fn leak(orig: RefMut<'b, T>) -> &'b mut T {
// By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell never
// goes back to UNUSED again. No further references can be created from the original cell,
// making the current borrow the only reference for the remaining lifetime.
mem::forget(orig.borrow);
orig.value
}
}

struct BorrowRefMut<'b> {
Expand Down
9 changes: 5 additions & 4 deletions src/libcore/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1423,13 +1423,14 @@ pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
}

/// Checks whether the regions of memory starting at `src` and `dst` of size
/// `count * size_of::<T>()` overlap.
fn overlaps<T>(src: *const T, dst: *const T, count: usize) -> bool {
/// `count * size_of::<T>()` do *not* overlap.
pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool {
let src_usize = src as usize;
let dst_usize = dst as usize;
let size = mem::size_of::<T>().checked_mul(count).unwrap();
let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize };
size > diff
let overlaps = size > diff;
!overlaps
}

/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
Expand Down Expand Up @@ -1525,7 +1526,7 @@ pub unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {

debug_assert!(is_aligned_and_not_null(src), "attempt to copy from unaligned or null pointer");
debug_assert!(is_aligned_and_not_null(dst), "attempt to copy to unaligned or null pointer");
debug_assert!(!overlaps(src, dst, count), "attempt to copy to overlapping memory");
debug_assert!(is_nonoverlapping(src, dst, count), "attempt to copy to overlapping memory");
copy_nonoverlapping(src, dst, count)
}

Expand Down
3 changes: 3 additions & 0 deletions src/libcore/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,9 @@ mod bool;
mod tuple;
mod unit;

#[stable(feature = "core_primitive", since = "1.43.0")]
pub mod primitive;

// Pull in the `core_arch` crate directly into libcore. The contents of
// `core_arch` are in a different repository: rust-lang/stdarch.
//
Expand Down
67 changes: 67 additions & 0 deletions src/libcore/primitive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//! This module reexports the primitive types to allow usage that is not
//! possibly shadowed by other declared types.
//!
//! This is normally only useful in macro generated code.
//!
//! An example of this is when generating a new struct and an impl for it:
//!
//! ```rust,compile_fail
//! pub struct bool;
//!
//! impl QueryId for bool {
//! const SOME_PROPERTY: bool = true;
//! }
//!
//! # trait QueryId { const SOME_PROPERTY: core::primitive::bool; }
//! ```
//!
//! Note that the `SOME_PROPERTY` associated constant would not compile, as its
//! type `bool` refers to the struct, rather than to the primitive bool type.
//!
//! A correct implementation could look like:
//!
//! ```rust
//! # #[allow(non_camel_case_types)]
//! pub struct bool;
//!
//! impl QueryId for bool {
//! const SOME_PROPERTY: core::primitive::bool = true;
//! }
//!
//! # trait QueryId { const SOME_PROPERTY: core::primitive::bool; }
//! ```

#[stable(feature = "core_primitive", since = "1.43.0")]
pub use bool;
#[stable(feature = "core_primitive", since = "1.43.0")]
pub use char;
#[stable(feature = "core_primitive", since = "1.43.0")]
pub use f32;
#[stable(feature = "core_primitive", since = "1.43.0")]
pub use f64;
#[stable(feature = "core_primitive", since = "1.43.0")]
pub use i128;
#[stable(feature = "core_primitive", since = "1.43.0")]
pub use i16;
#[stable(feature = "core_primitive", since = "1.43.0")]
pub use i32;
#[stable(feature = "core_primitive", since = "1.43.0")]
pub use i64;
#[stable(feature = "core_primitive", since = "1.43.0")]
pub use i8;
#[stable(feature = "core_primitive", since = "1.43.0")]
pub use isize;
#[stable(feature = "core_primitive", since = "1.43.0")]
pub use str;
#[stable(feature = "core_primitive", since = "1.43.0")]
pub use u128;
#[stable(feature = "core_primitive", since = "1.43.0")]
pub use u16;
#[stable(feature = "core_primitive", since = "1.43.0")]
pub use u32;
#[stable(feature = "core_primitive", since = "1.43.0")]
pub use u64;
#[stable(feature = "core_primitive", since = "1.43.0")]
pub use u8;
#[stable(feature = "core_primitive", since = "1.43.0")]
pub use usize;
12 changes: 11 additions & 1 deletion src/libcore/ptr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
use crate::cmp::Ordering;
use crate::fmt;
use crate::hash;
use crate::intrinsics;
use crate::intrinsics::{self, is_aligned_and_not_null, is_nonoverlapping};
use crate::mem::{self, MaybeUninit};

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -392,6 +392,10 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
#[inline]
#[stable(feature = "swap_nonoverlapping", since = "1.27.0")]
pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
debug_assert!(is_aligned_and_not_null(x), "attempt to swap unaligned or null pointer");
debug_assert!(is_aligned_and_not_null(y), "attempt to swap unaligned or null pointer");
debug_assert!(is_nonoverlapping(x, y, count), "attempt to swap overlapping memory");

let x = x as *mut u8;
let y = y as *mut u8;
let len = mem::size_of::<T>() * count;
Expand Down Expand Up @@ -619,6 +623,7 @@ pub unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn read<T>(src: *const T) -> T {
// `copy_nonoverlapping` takes care of debug_assert.
let mut tmp = MaybeUninit::<T>::uninit();
copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
tmp.assume_init()
Expand Down Expand Up @@ -712,6 +717,7 @@ pub unsafe fn read<T>(src: *const T) -> T {
#[inline]
#[stable(feature = "ptr_unaligned", since = "1.17.0")]
pub unsafe fn read_unaligned<T>(src: *const T) -> T {
// `copy_nonoverlapping` takes care of debug_assert.
let mut tmp = MaybeUninit::<T>::uninit();
copy_nonoverlapping(src as *const u8, tmp.as_mut_ptr() as *mut u8, mem::size_of::<T>());
tmp.assume_init()
Expand Down Expand Up @@ -804,6 +810,7 @@ pub unsafe fn read_unaligned<T>(src: *const T) -> T {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn write<T>(dst: *mut T, src: T) {
debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer");
intrinsics::move_val_init(&mut *dst, src)
}

Expand Down Expand Up @@ -896,6 +903,7 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
#[inline]
#[stable(feature = "ptr_unaligned", since = "1.17.0")]
pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
// `copy_nonoverlapping` takes care of debug_assert.
copy_nonoverlapping(&src as *const T as *const u8, dst as *mut u8, mem::size_of::<T>());
mem::forget(src);
}
Expand Down Expand Up @@ -967,6 +975,7 @@ pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
#[inline]
#[stable(feature = "volatile", since = "1.9.0")]
pub unsafe fn read_volatile<T>(src: *const T) -> T {
debug_assert!(is_aligned_and_not_null(src), "attempt to read from unaligned or null pointer");
intrinsics::volatile_load(src)
}

Expand Down Expand Up @@ -1035,6 +1044,7 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
#[inline]
#[stable(feature = "volatile", since = "1.9.0")]
pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer");
intrinsics::volatile_store(dst, src);
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1526,7 +1526,7 @@ impl<'tcx> GlobalCtxt<'tcx> {
ty::tls::with_related_context(tcx, |icx| {
let new_icx = ty::tls::ImplicitCtxt {
tcx,
query: icx.query.clone(),
query: icx.query,
diagnostics: icx.diagnostics,
layout_depth: icx.layout_depth,
task_deps: icx.task_deps,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1447,7 +1447,7 @@ impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<TraitRef<'tcx>> {
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<&TraitRef<'tcx>> {
fn to_predicate(&self) -> Predicate<'tcx> {
ty::Predicate::Trait(
ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.value.clone() }),
ty::Binder::dummy(ty::TraitPredicate { trait_ref: *self.value }),
self.constness,
)
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/query/job.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ impl<'tcx> QueryLatch<'tcx> {
return CycleError { usage, cycle };
}

current_job = info.job.parent.clone();
current_job = info.job.parent;
}

panic!("did not find a cycle")
Expand Down
53 changes: 4 additions & 49 deletions src/librustc_ast_pretty/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::pp::{self, Breaks};

use rustc_span::edition::Edition;
use rustc_span::source_map::{SourceMap, Spanned};
use rustc_span::symbol::{kw, sym};
use rustc_span::symbol::{kw, sym, IdentPrinter};
use rustc_span::{BytePos, FileName, Span};
use syntax::ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
use syntax::ast::{Attribute, GenericArg, MacArgs};
Expand Down Expand Up @@ -196,40 +196,6 @@ pub fn literal_to_string(lit: token::Lit) -> String {
out
}

/// Print an ident from AST, `$crate` is converted into its respective crate name.
pub fn ast_ident_to_string(ident: ast::Ident, is_raw: bool) -> String {
ident_to_string(ident.name, is_raw, Some(ident.span))
}

// AST pretty-printer is used as a fallback for turning AST structures into token streams for
// proc macros. Additionally, proc macros may stringify their input and expect it survive the
// stringification (especially true for proc macro derives written between Rust 1.15 and 1.30).
// So we need to somehow pretty-print `$crate` in a way preserving at least some of its
// hygiene data, most importantly name of the crate it refers to.
// As a result we print `$crate` as `crate` if it refers to the local crate
// and as `::other_crate_name` if it refers to some other crate.
// Note, that this is only done if the ident token is printed from inside of AST pretty-pringing,
// but not otherwise. Pretty-printing is the only way for proc macros to discover token contents,
// so we should not perform this lossy conversion if the top level call to the pretty-printer was
// done for a token stream or a single token.
fn ident_to_string(name: ast::Name, is_raw: bool, convert_dollar_crate: Option<Span>) -> String {
if is_raw {
format!("r#{}", name)
} else {
if name == kw::DollarCrate {
if let Some(span) = convert_dollar_crate {
let converted = span.ctxt().dollar_crate_name();
return if converted.is_path_segment_keyword() {
converted.to_string()
} else {
format!("::{}", converted)
};
}
}
name.to_string()
}
}

/// Print the token kind precisely, without converting `$crate` into its respective crate name.
pub fn token_kind_to_string(tok: &TokenKind) -> String {
token_kind_to_string_ext(tok, None)
Expand Down Expand Up @@ -280,7 +246,7 @@ fn token_kind_to_string_ext(tok: &TokenKind, convert_dollar_crate: Option<Span>)
token::Literal(lit) => literal_to_string(lit),

/* Name components */
token::Ident(s, is_raw) => ident_to_string(s, is_raw, convert_dollar_crate),
token::Ident(s, is_raw) => IdentPrinter::new(s, is_raw, convert_dollar_crate).to_string(),
token::Lifetime(s) => s.to_string(),

/* Other */
Expand Down Expand Up @@ -315,14 +281,11 @@ pub fn nonterminal_to_string(nt: &Nonterminal) -> String {
token::NtBlock(ref e) => block_to_string(e),
token::NtStmt(ref e) => stmt_to_string(e),
token::NtPat(ref e) => pat_to_string(e),
token::NtIdent(e, is_raw) => ast_ident_to_string(e, is_raw),
token::NtIdent(e, is_raw) => IdentPrinter::for_ast_ident(e, is_raw).to_string(),
token::NtLifetime(e) => e.to_string(),
token::NtLiteral(ref e) => expr_to_string(e),
token::NtTT(ref tree) => tt_to_string(tree.clone()),
// FIXME(Centril): merge these variants.
token::NtImplItem(ref e) | token::NtTraitItem(ref e) => assoc_item_to_string(e),
token::NtVis(ref e) => vis_to_string(e),
token::NtForeignItem(ref e) => foreign_item_to_string(e),
}
}

Expand Down Expand Up @@ -358,10 +321,6 @@ pub fn item_to_string(i: &ast::Item) -> String {
to_string(|s| s.print_item(i))
}

fn assoc_item_to_string(i: &ast::AssocItem) -> String {
to_string(|s| s.print_assoc_item(i))
}

pub fn generic_params_to_string(generic_params: &[ast::GenericParam]) -> String {
to_string(|s| s.print_generic_params(generic_params))
}
Expand Down Expand Up @@ -404,10 +363,6 @@ pub fn param_to_string(arg: &ast::Param) -> String {
to_string(|s| s.print_param(arg, false))
}

fn foreign_item_to_string(arg: &ast::ForeignItem) -> String {
to_string(|s| s.print_foreign_item(arg))
}

fn visibility_qualified(vis: &ast::Visibility, s: &str) -> String {
format!("{}{}", to_string(|s| s.print_visibility(vis)), s)
}
Expand Down Expand Up @@ -819,7 +774,7 @@ impl<'a> PrintState<'a> for State<'a> {
}

fn print_ident(&mut self, ident: ast::Ident) {
self.s.word(ast_ident_to_string(ident, ident.is_raw_guess()));
self.s.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string());
self.ann.post(self, AnnNode::Ident(&ident))
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_codegen_ssa/mir/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
_ => {
let val = self.eval_mir_constant(constant)?;
let ty = self.monomorphize(&constant.literal.ty);
Ok(OperandRef::from_const(bx, val.clone(), ty))
Ok(OperandRef::from_const(bx, val, ty))
}
}
}
Expand Down
Loading