Skip to content

Commit

Permalink
Auto merge of rust-lang#72778 - RalfJung:rollup-f01z68m, r=RalfJung
Browse files Browse the repository at this point in the history
Rollup of 9 pull requests

Successful merges:

 - rust-lang#72299 (more `LocalDefId`s)
 - rust-lang#72368 (Resolve overflow behavior for RangeFrom)
 - rust-lang#72441 (Fix ICE with explicit late-bound lifetimes)
 - rust-lang#72499 (Override Box::<[T]>::clone_from)
 - rust-lang#72521 (Properly handle InlineAsmOperand::SymFn when collecting monomorphized items)
 - rust-lang#72540 (mir: adjust conditional in recursion limit check)
 - rust-lang#72563 (multiple Return terminators are possible)
 - rust-lang#72585 (Only capture tokens for items with outer attributes)
 - rust-lang#72607 (Eagerly lower asm sub-expressions to HIR even if there is an error)

Failed merges:

r? @ghost
  • Loading branch information
bors committed May 30, 2020
2 parents 91fb72a + 69310de commit 74e8046
Show file tree
Hide file tree
Showing 51 changed files with 580 additions and 256 deletions.
8 changes: 8 additions & 0 deletions src/liballoc/boxed.rs
Expand Up @@ -1109,6 +1109,14 @@ impl<T: Clone> Clone for Box<[T]> {
fn clone(&self) -> Self {
self.to_vec().into_boxed_slice()
}

fn clone_from(&mut self, other: &Self) {
if self.len() == other.len() {
self.clone_from_slice(&other);
} else {
*self = other.clone();
}
}
}

#[stable(feature = "box_borrow", since = "1.1.0")]
Expand Down
33 changes: 33 additions & 0 deletions src/liballoc/tests/boxed.rs
Expand Up @@ -16,3 +16,36 @@ fn unitialized_zero_size_box() {
NonNull::<MaybeUninit<String>>::dangling().as_ptr(),
);
}

#[derive(Clone, PartialEq, Eq, Debug)]
struct Dummy {
_data: u8,
}

#[test]
fn box_clone_and_clone_from_equivalence() {
for size in (0..8).map(|i| 2usize.pow(i)) {
let control = vec![Dummy { _data: 42 }; size].into_boxed_slice();
let clone = control.clone();
let mut copy = vec![Dummy { _data: 84 }; size].into_boxed_slice();
copy.clone_from(&control);
assert_eq!(control, clone);
assert_eq!(control, copy);
}
}

/// This test might give a false positive in case the box realocates, but the alocator keeps the
/// original pointer.
///
/// On the other hand it won't give a false negative, if it fails than the memory was definitly not
/// reused
#[test]
fn box_clone_from_ptr_stability() {
for size in (0..8).map(|i| 2usize.pow(i)) {
let control = vec![Dummy { _data: 42 }; size].into_boxed_slice();
let mut copy = vec![Dummy { _data: 84 }; size].into_boxed_slice();
let copy_raw = copy.as_ptr() as usize;
copy.clone_from(&control);
assert_eq!(copy.as_ptr() as usize, copy_raw);
}
}
10 changes: 1 addition & 9 deletions src/libcore/iter/range.rs
Expand Up @@ -619,15 +619,7 @@ impl<A: Step> Iterator for ops::RangeFrom<A> {

#[inline]
fn nth(&mut self, n: usize) -> Option<A> {
// If we would jump over the maximum value, panic immediately.
// This is consistent with behavior before the Step redesign,
// even though it's inconsistent with n `next` calls.
// To get consistent behavior, change it to use `forward` instead.
// This change should go through FCP separately to the redesign, so is for now left as a
// FIXME: make this consistent
let plus_n =
Step::forward_checked(self.start.clone(), n).expect("overflow in RangeFrom::nth");
// The final step should always be debug-checked.
let plus_n = Step::forward(self.start.clone(), n);
self.start = Step::forward(plus_n.clone(), 1);
Some(plus_n)
}
Expand Down
14 changes: 10 additions & 4 deletions src/libcore/ops/range.rs
Expand Up @@ -151,10 +151,16 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
///
/// The `RangeFrom` `start..` contains all values with `x >= start`.
///
/// *Note*: Currently, no overflow checking is done for the [`Iterator`]
/// implementation; if you use an integer range and the integer overflows, it
/// might panic in debug mode or create an endless loop in release mode. **This
/// overflow behavior might change in the future.**
/// *Note*: Overflow in the [`Iterator`] implementation (when the contained
/// data type reaches its numerical limit) is allowed to panic, wrap, or
/// saturate. This behavior is defined by the implementation of the [`Step`]
/// trait. For primitive integers, this follows the normal rules, and respects
/// the overflow checks profile (panic in debug, wrap in release). Note also
/// that overflow happens earlier than you might assume: the overflow happens
/// in the call to `next` that yields the maximum value, as the range must be
/// set to a state to yield the next value.
///
/// [`Step`]: crate::iter::Step
///
/// # Examples
///
Expand Down
70 changes: 36 additions & 34 deletions src/librustc_ast_lowering/expr.rs
Expand Up @@ -974,20 +974,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
}

fn lower_expr_asm(&mut self, sp: Span, asm: &InlineAsm) -> hir::ExprKind<'hir> {
let asm_arch = if let Some(asm_arch) = self.sess.asm_arch {
asm_arch
} else {
if self.sess.asm_arch.is_none() {
struct_span_err!(self.sess, sp, E0472, "asm! is unsupported on this target").emit();
return hir::ExprKind::Err;
};
if asm.options.contains(InlineAsmOptions::ATT_SYNTAX) {
match asm_arch {
asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64 => {}
_ => self
.sess
.struct_span_err(sp, "the `att_syntax` option is only supported on x86")
.emit(),
}
}
if asm.options.contains(InlineAsmOptions::ATT_SYNTAX)
&& !matches!(
self.sess.asm_arch,
Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64)
)
{
self.sess
.struct_span_err(sp, "the `att_syntax` option is only supported on x86")
.emit();
}

// Lower operands to HIR, filter_map skips any operands with invalid
Expand All @@ -1001,10 +999,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
Some(match reg {
InlineAsmRegOrRegClass::Reg(s) => asm::InlineAsmRegOrRegClass::Reg(
asm::InlineAsmReg::parse(
asm_arch,
|feature| {
self.sess.target_features.contains(&Symbol::intern(feature))
},
sess.asm_arch?,
|feature| sess.target_features.contains(&Symbol::intern(feature)),
s,
)
.map_err(|e| {
Expand All @@ -1015,7 +1011,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
),
InlineAsmRegOrRegClass::RegClass(s) => {
asm::InlineAsmRegOrRegClass::RegClass(
asm::InlineAsmRegClass::parse(asm_arch, s)
asm::InlineAsmRegClass::parse(sess.asm_arch?, s)
.map_err(|e| {
let msg = format!(
"invalid register class `{}`: {}",
Expand All @@ -1029,33 +1025,38 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
})
};
let op = match op {
InlineAsmOperand::In { reg, expr } => hir::InlineAsmOperand::In {
reg: lower_reg(*reg)?,

// lower_reg is executed last because we need to lower all
// sub-expressions even if we throw them away later.
let op = match *op {
InlineAsmOperand::In { reg, ref expr } => hir::InlineAsmOperand::In {
expr: self.lower_expr_mut(expr),
reg: lower_reg(reg)?,
},
InlineAsmOperand::Out { reg, late, expr } => hir::InlineAsmOperand::Out {
reg: lower_reg(*reg)?,
late: *late,
InlineAsmOperand::Out { reg, late, ref expr } => hir::InlineAsmOperand::Out {
late,
expr: expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
reg: lower_reg(reg)?,
},
InlineAsmOperand::InOut { reg, late, expr } => hir::InlineAsmOperand::InOut {
reg: lower_reg(*reg)?,
late: *late,
expr: self.lower_expr_mut(expr),
},
InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => {
InlineAsmOperand::InOut { reg, late, ref expr } => {
hir::InlineAsmOperand::InOut {
late,
expr: self.lower_expr_mut(expr),
reg: lower_reg(reg)?,
}
}
InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => {
hir::InlineAsmOperand::SplitInOut {
reg: lower_reg(*reg)?,
late: *late,
late,
in_expr: self.lower_expr_mut(in_expr),
out_expr: out_expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
reg: lower_reg(reg)?,
}
}
InlineAsmOperand::Const { expr } => {
InlineAsmOperand::Const { ref expr } => {
hir::InlineAsmOperand::Const { expr: self.lower_expr_mut(expr) }
}
InlineAsmOperand::Sym { expr } => {
InlineAsmOperand::Sym { ref expr } => {
hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) }
}
};
Expand All @@ -1069,6 +1070,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}

// Validate template modifiers against the register classes for the operands
let asm_arch = sess.asm_arch.unwrap();
for p in &asm.template {
if let InlineAsmTemplatePiece::Placeholder {
operand_idx,
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_codegen_ssa/mir/block.rs
Expand Up @@ -908,13 +908,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
mir::InlineAsmOperand::SymFn { ref value } => {
let literal = self.monomorphize(&value.literal);
if let ty::FnDef(def_id, substs) = literal.ty.kind {
let instance = ty::Instance::resolve(
let instance = ty::Instance::resolve_for_fn_ptr(
bx.tcx(),
ty::ParamEnv::reveal_all(),
def_id,
substs,
)
.unwrap()
.unwrap();
InlineAsmOperandRef::SymFn { instance }
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_error_codes/error_codes/E0055.md
Expand Up @@ -6,7 +6,7 @@ recursion limit (which can be set via the `recursion_limit` attribute).
For a somewhat artificial example:

```compile_fail,E0055
#![recursion_limit="5"]
#![recursion_limit="4"]
struct Foo;
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_expand/base.rs
Expand Up @@ -12,7 +12,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::{self, Lrc};
use rustc_errors::{DiagnosticBuilder, ErrorReported};
use rustc_parse::{self, parser, MACRO_ARGUMENTS};
use rustc_session::parse::ParseSess;
use rustc_session::{parse::ParseSess, Limit};
use rustc_span::def_id::DefId;
use rustc_span::edition::Edition;
use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
Expand Down Expand Up @@ -941,7 +941,7 @@ pub struct ExpansionData {
pub struct ExtCtxt<'a> {
pub parse_sess: &'a ParseSess,
pub ecfg: expand::ExpansionConfig<'a>,
pub reduced_recursion_limit: Option<usize>,
pub reduced_recursion_limit: Option<Limit>,
pub root_path: PathBuf,
pub resolver: &'a mut dyn Resolver,
pub current_expansion: ExpansionData,
Expand Down
7 changes: 4 additions & 3 deletions src/librustc_expand/expand.rs
Expand Up @@ -24,6 +24,7 @@ use rustc_parse::validate_attr;
use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS;
use rustc_session::lint::BuiltinLintDiagnostics;
use rustc_session::parse::{feature_err, ParseSess};
use rustc_session::Limit;
use rustc_span::source_map::respan;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{FileName, Span, DUMMY_SP};
Expand Down Expand Up @@ -664,7 +665,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
) -> ExpandResult<AstFragment, Invocation> {
let recursion_limit =
self.cx.reduced_recursion_limit.unwrap_or(self.cx.ecfg.recursion_limit);
if self.cx.current_expansion.depth > recursion_limit {
if !recursion_limit.value_within_limit(self.cx.current_expansion.depth) {
if self.cx.reduced_recursion_limit.is_none() {
self.error_recursion_limit_reached();
}
Expand Down Expand Up @@ -1784,7 +1785,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
pub struct ExpansionConfig<'feat> {
pub crate_name: String,
pub features: Option<&'feat Features>,
pub recursion_limit: usize,
pub recursion_limit: Limit,
pub trace_mac: bool,
pub should_test: bool, // If false, strip `#[test]` nodes
pub keep_macs: bool,
Expand All @@ -1795,7 +1796,7 @@ impl<'feat> ExpansionConfig<'feat> {
ExpansionConfig {
crate_name,
features: None,
recursion_limit: 1024,
recursion_limit: Limit::new(1024),
trace_mac: false,
should_test: false,
keep_macs: false,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_interface/passes.rs
Expand Up @@ -838,7 +838,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {

sess.time("MIR_effect_checking", || {
for def_id in tcx.body_owners() {
mir::transform::check_unsafety::check_unsafety(tcx, def_id.to_def_id())
mir::transform::check_unsafety::check_unsafety(tcx, def_id)
}
});

Expand Down
8 changes: 4 additions & 4 deletions src/librustc_middle/middle/limits.rs
Expand Up @@ -8,7 +8,7 @@
use crate::bug;
use rustc_ast::ast;
use rustc_data_structures::sync::OnceCell;
use rustc_session::Session;
use rustc_session::{Limit, Session};
use rustc_span::symbol::{sym, Symbol};

use std::num::IntErrorKind;
Expand All @@ -22,7 +22,7 @@ pub fn update_limits(sess: &Session, krate: &ast::Crate) {
fn update_limit(
sess: &Session,
krate: &ast::Crate,
limit: &OnceCell<usize>,
limit: &OnceCell<Limit>,
name: Symbol,
default: usize,
) {
Expand All @@ -34,7 +34,7 @@ fn update_limit(
if let Some(s) = attr.value_str() {
match s.as_str().parse() {
Ok(n) => {
limit.set(n).unwrap();
limit.set(Limit::new(n)).unwrap();
return;
}
Err(e) => {
Expand Down Expand Up @@ -62,5 +62,5 @@ fn update_limit(
}
}
}
limit.set(default).unwrap();
limit.set(Limit::new(default)).unwrap();
}
3 changes: 2 additions & 1 deletion src/librustc_middle/mir/mod.rs
Expand Up @@ -1072,7 +1072,8 @@ pub enum TerminatorKind<'tcx> {
Abort,

/// Indicates a normal return. The return place should have
/// been filled in by now. This should occur at most once.
/// been filled in before this executes. This can occur multiple times
/// in different basic blocks.
Return,

/// Indicates a terminator that can never be reached.
Expand Down
10 changes: 8 additions & 2 deletions src/librustc_middle/query/mod.rs
Expand Up @@ -386,8 +386,14 @@ rustc_queries! {
storage(ArenaCacheSelector<'tcx>)
}

/// HACK: when evaluated, this reports a "unsafe derive on repr(packed)" error
query unsafe_derive_on_repr_packed(_: DefId) -> () {}
/// HACK: when evaluated, this reports a "unsafe derive on repr(packed)" error.
///
/// Unsafety checking is executed for each method separately, but we only want
/// to emit this error once per derive. As there are some impls with multiple
/// methods, we use a query for deduplication.
query unsafe_derive_on_repr_packed(key: LocalDefId) -> () {
desc { |tcx| "processing `{}`", tcx.def_path_str(key.to_def_id()) }
}

/// The signature of functions and closures.
query fn_sig(_: DefId) -> ty::PolyFnSig<'tcx> {}
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_middle/ty/layout.rs
Expand Up @@ -187,10 +187,9 @@ fn layout_raw<'tcx>(
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
) -> Result<&'tcx Layout, LayoutError<'tcx>> {
ty::tls::with_related_context(tcx, move |icx| {
let rec_limit = tcx.sess.recursion_limit.get().copied().unwrap();
let (param_env, ty) = query.into_parts();

if icx.layout_depth > rec_limit {
if !tcx.sess.recursion_limit().value_within_limit(icx.layout_depth) {
tcx.sess.fatal(&format!("overflow representing the type `{}`", ty));
}

Expand Down
5 changes: 3 additions & 2 deletions src/librustc_mir/const_eval/machine.rs
Expand Up @@ -10,6 +10,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_ast::ast::Mutability;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::AssertMessage;
use rustc_session::Limit;
use rustc_span::symbol::Symbol;

use crate::interpret::{
Expand Down Expand Up @@ -109,8 +110,8 @@ pub struct MemoryExtra {
}

impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
pub(super) fn new(const_eval_limit: usize) -> Self {
CompileTimeInterpreter { steps_remaining: const_eval_limit, stack: Vec::new() }
pub(super) fn new(const_eval_limit: Limit) -> Self {
CompileTimeInterpreter { steps_remaining: const_eval_limit.0, stack: Vec::new() }
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/interpret/eval_context.rs
Expand Up @@ -651,7 +651,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
M::after_stack_push(self)?;
info!("ENTERING({}) {}", self.frame_idx(), self.frame().instance);

if self.stack().len() > self.tcx.sess.recursion_limit() {
if !self.tcx.sess.recursion_limit().value_within_limit(self.stack().len()) {
throw_exhaust!(StackFrameLimitReached)
} else {
Ok(())
Expand Down

0 comments on commit 74e8046

Please sign in to comment.