diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index b86928534cb24..9235f8e7660a1 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -97,7 +97,10 @@ pub unsafe extern fn __rust_start_panic(_payload: usize) -> u32 { pub mod personalities { #[no_mangle] #[cfg(not(any( - target_arch = "wasm32", + all( + target_arch = "wasm32", + not(target_os = "emscripten"), + ), all( target_os = "windows", target_env = "gnu", diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e558d94551671..dd5d4b8f6afff 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -3705,7 +3705,7 @@ impl<'a> LoweringContext<'a> { let ohs = P(self.lower_expr(ohs)); hir::ExprKind::Unary(op, ohs) } - ExprKind::Lit(ref l) => hir::ExprKind::Lit(P((**l).clone())), + ExprKind::Lit(ref l) => hir::ExprKind::Lit(P((*l).clone())), ExprKind::Cast(ref expr, ref ty) => { let expr = P(self.lower_expr(expr)); hir::ExprKind::Cast(expr, self.lower_ty(ty, ImplTraitContext::disallowed())) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 1963d366e7a66..f833ebc7ca763 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -178,6 +178,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.msg_span_from_early_bound_and_free_regions(region) } ty::ReStatic => ("the static lifetime".to_owned(), None), + ty::ReEmpty => ("an empty lifetime".to_owned(), None), _ => bug!("{:?}", region), } } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index c2014a5fdd23a..a84226bf665d0 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -304,6 +304,20 @@ impl<'tcx> Mir<'tcx> { }) } + /// Returns an iterator over all user-declared mutable locals. + #[inline] + pub fn mut_vars_iter<'a>(&'a self) -> impl Iterator + 'a { + (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| { + let local = Local::new(index); + let decl = &self.local_decls[local]; + if decl.is_user_variable.is_some() && decl.mutability == Mutability::Mut { + Some(local) + } else { + None + } + }) + } + /// Returns an iterator over all user-declared mutable arguments and locals. #[inline] pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator + 'a { diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 5306f2c9689b1..78aabf86e300d 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -2082,7 +2082,7 @@ pub fn build_session_options_and_crate_config( error_format, &format!( "optimization level needs to be \ - between 0-3 (instead was `{}`)", + between 0-3, s or z (instead was `{}`)", arg ), ); diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 0ce1d8f822755..d7b5dd049e350 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -396,7 +396,10 @@ fn to_pretty_impl_header(tcx: TyCtxt<'_, '_, '_>, impl_def_id: DefId) -> Option< if !substs.is_noop() { types_without_default_bounds.extend(substs.types()); w.push('<'); - w.push_str(&substs.iter().map(|k| k.to_string()).collect::>().join(", ")); + w.push_str(&substs.iter() + .map(|k| k.to_string()) + .filter(|k| &k[..] != "'_") + .collect::>().join(", ")); w.push('>'); } diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 3dc31c517169f..54550b8a2055f 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -450,8 +450,7 @@ impl<'sess> OnDiskCache<'sess> { .map(|&(cnum, ..)| cnum) .max() .unwrap_or(0) + 1; - let mut map = IndexVec::new(); - map.resize(map_size as usize, None); + let mut map = IndexVec::from_elem_n(None, map_size as usize); for &(prev_cnum, ref crate_name, crate_disambiguator) in prev_cnums { let key = (crate_name.clone(), crate_disambiguator); diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index e50534a4e1dc9..bd7a1c2c3293e 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -225,9 +225,10 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> { // ...and then memcpy it to the intended destination. base::call_memcpy(bx, bx.pointercast(dst.llval, Type::i8p(cx)), + self.layout.align, bx.pointercast(llscratch, Type::i8p(cx)), + scratch_align, C_usize(cx, self.layout.size.bytes()), - self.layout.align.min(scratch_align), MemFlags::empty()); bx.lifetime_end(llscratch, scratch_size); diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index fb33fe85b0054..806025937cb11 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -53,7 +53,7 @@ use mir::place::PlaceRef; use attributes; use builder::{Builder, MemFlags}; use callee; -use common::{C_bool, C_bytes_in_context, C_i32, C_usize}; +use common::{C_bool, C_bytes_in_context, C_usize}; use rustc_mir::monomorphize::item::DefPathBasedNames; use common::{C_struct_in_context, C_array, val_ty}; use consts; @@ -77,7 +77,6 @@ use rustc_data_structures::sync::Lrc; use std::any::Any; use std::cmp; use std::ffi::CString; -use std::i32; use std::ops::{Deref, DerefMut}; use std::sync::mpsc; use std::time::{Instant, Duration}; @@ -319,8 +318,8 @@ pub fn coerce_unsized_into( } if src_f.layout.ty == dst_f.layout.ty { - memcpy_ty(bx, dst_f.llval, src_f.llval, src_f.layout, - src_f.align.min(dst_f.align), MemFlags::empty()); + memcpy_ty(bx, dst_f.llval, dst_f.align, src_f.llval, src_f.align, + src_f.layout, MemFlags::empty()); } else { coerce_unsized_into(bx, src_f, dst_f); } @@ -420,36 +419,34 @@ pub fn to_immediate_scalar( pub fn call_memcpy( bx: &Builder<'_, 'll, '_>, dst: &'ll Value, + dst_align: Align, src: &'ll Value, + src_align: Align, n_bytes: &'ll Value, - align: Align, flags: MemFlags, ) { if flags.contains(MemFlags::NONTEMPORAL) { // HACK(nox): This is inefficient but there is no nontemporal memcpy. - let val = bx.load(src, align); + let val = bx.load(src, src_align); let ptr = bx.pointercast(dst, val_ty(val).ptr_to()); - bx.store_with_flags(val, ptr, align, flags); + bx.store_with_flags(val, ptr, dst_align, flags); return; } let cx = bx.cx; - let ptr_width = &cx.sess().target.target.target_pointer_width; - let key = format!("llvm.memcpy.p0i8.p0i8.i{}", ptr_width); - let memcpy = cx.get_intrinsic(&key); let src_ptr = bx.pointercast(src, Type::i8p(cx)); let dst_ptr = bx.pointercast(dst, Type::i8p(cx)); let size = bx.intcast(n_bytes, cx.isize_ty, false); - let align = C_i32(cx, align.abi() as i32); - let volatile = C_bool(cx, flags.contains(MemFlags::VOLATILE)); - bx.call(memcpy, &[dst_ptr, src_ptr, size, align, volatile], None); + let volatile = flags.contains(MemFlags::VOLATILE); + bx.memcpy(dst_ptr, dst_align.abi(), src_ptr, src_align.abi(), size, volatile); } pub fn memcpy_ty( bx: &Builder<'_, 'll, 'tcx>, dst: &'ll Value, + dst_align: Align, src: &'ll Value, + src_align: Align, layout: TyLayout<'tcx>, - align: Align, flags: MemFlags, ) { let size = layout.size.bytes(); @@ -457,7 +454,7 @@ pub fn memcpy_ty( return; } - call_memcpy(bx, dst, src, C_usize(bx.cx, size), align, flags); + call_memcpy(bx, dst, dst_align, src, src_align, C_usize(bx.cx, size), flags); } pub fn call_memset( diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index f70a68c72489a..1b1a31def3759 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -781,6 +781,24 @@ impl Builder<'a, 'll, 'tcx> { } } + pub fn memcpy(&self, dst: &'ll Value, dst_align: u64, + src: &'ll Value, src_align: u64, + size: &'ll Value, is_volatile: bool) -> &'ll Value { + unsafe { + llvm::LLVMRustBuildMemCpy(self.llbuilder, dst, dst_align as c_uint, + src, src_align as c_uint, size, is_volatile) + } + } + + pub fn memmove(&self, dst: &'ll Value, dst_align: u64, + src: &'ll Value, src_align: u64, + size: &'ll Value, is_volatile: bool) -> &'ll Value { + unsafe { + llvm::LLVMRustBuildMemMove(self.llbuilder, dst, dst_align as c_uint, + src, src_align as c_uint, size, is_volatile) + } + } + pub fn minnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("minnum"); unsafe { diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 120449ae2af4c..555e4012c3add 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -530,12 +530,6 @@ fn declare_intrinsic(cx: &CodegenCx<'ll, '_>, key: &str) -> Option<&'ll Value> { let t_v4f64 = Type::vector(t_f64, 4); let t_v8f64 = Type::vector(t_f64, 8); - ifn!("llvm.memcpy.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void); - ifn!("llvm.memcpy.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void); - ifn!("llvm.memcpy.p0i8.p0i8.i64", fn(i8p, i8p, t_i64, t_i32, i1) -> void); - ifn!("llvm.memmove.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void); - ifn!("llvm.memmove.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void); - ifn!("llvm.memmove.p0i8.p0i8.i64", fn(i8p, i8p, t_i64, t_i32, i1) -> void); ifn!("llvm.memset.p0i8.i16", fn(i8p, t_i8, t_i16, t_i32, i1) -> void); ifn!("llvm.memset.p0i8.i32", fn(i8p, t_i8, t_i32, t_i32, i1) -> void); ifn!("llvm.memset.p0i8.i64", fn(i8p, t_i8, t_i64, t_i32, i1) -> void); diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index e44bd2d23672f..a4401cf96d9de 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -23,7 +23,7 @@ use glue; use type_::Type; use type_of::LayoutLlvmExt; use rustc::ty::{self, Ty}; -use rustc::ty::layout::{HasDataLayout, LayoutOf}; +use rustc::ty::layout::LayoutOf; use rustc::hir; use syntax::ast; use syntax::symbol::Symbol; @@ -690,28 +690,14 @@ fn copy_intrinsic( let cx = bx.cx; let (size, align) = cx.size_and_align_of(ty); let size = C_usize(cx, size.bytes()); - let align = C_i32(cx, align.abi() as i32); - - let operation = if allow_overlap { - "memmove" - } else { - "memcpy" - }; - - let name = format!("llvm.{}.p0i8.p0i8.i{}", operation, - cx.data_layout().pointer_size.bits()); - + let align = align.abi(); let dst_ptr = bx.pointercast(dst, Type::i8p(cx)); let src_ptr = bx.pointercast(src, Type::i8p(cx)); - let llfn = cx.get_intrinsic(&name); - - bx.call(llfn, - &[dst_ptr, - src_ptr, - bx.mul(size, count), - align, - C_bool(cx, volatile)], - None) + if allow_overlap { + bx.memmove(dst_ptr, align, src_ptr, align, bx.mul(size, count), volatile) + } else { + bx.memcpy(dst_ptr, align, src_ptr, align, bx.mul(size, count), volatile) + } } fn memset_intrinsic( diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 12d4670e4be4b..b994b1ffc4bce 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -998,6 +998,22 @@ extern "C" { Bundle: Option<&OperandBundleDef<'a>>, Name: *const c_char) -> &'a Value; + pub fn LLVMRustBuildMemCpy(B: &Builder<'a>, + Dst: &'a Value, + DstAlign: c_uint, + Src: &'a Value, + SrcAlign: c_uint, + Size: &'a Value, + IsVolatile: bool) + -> &'a Value; + pub fn LLVMRustBuildMemMove(B: &Builder<'a>, + Dst: &'a Value, + DstAlign: c_uint, + Src: &'a Value, + SrcAlign: c_uint, + Size: &'a Value, + IsVolatile: bool) + -> &'a Value; pub fn LLVMBuildSelect(B: &Builder<'a>, If: &'a Value, Then: &'a Value, diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs index a7f4c48c89bd6..3f9921a5cf930 100644 --- a/src/librustc_codegen_llvm/mir/block.rs +++ b/src/librustc_codegen_llvm/mir/block.rs @@ -784,7 +784,8 @@ impl FunctionCx<'a, 'll, 'tcx> { // have scary latent bugs around. let scratch = PlaceRef::alloca(bx, arg.layout, "arg"); - base::memcpy_ty(bx, scratch.llval, llval, op.layout, align, MemFlags::empty()); + base::memcpy_ty(bx, scratch.llval, scratch.align, llval, align, + op.layout, MemFlags::empty()); (scratch.llval, scratch.align, true) } else { (llval, align, true) diff --git a/src/librustc_codegen_llvm/mir/operand.rs b/src/librustc_codegen_llvm/mir/operand.rs index d1b6aa7fc4280..c76cbfcd97177 100644 --- a/src/librustc_codegen_llvm/mir/operand.rs +++ b/src/librustc_codegen_llvm/mir/operand.rs @@ -282,8 +282,8 @@ impl OperandValue<'ll> { } match self { OperandValue::Ref(r, None, source_align) => { - base::memcpy_ty(bx, dest.llval, r, dest.layout, - source_align.min(dest.align), flags) + base::memcpy_ty(bx, dest.llval, dest.align, r, source_align, + dest.layout, flags) } OperandValue::Ref(_, Some(_), _) => { bug!("cannot directly store unsized values"); @@ -324,7 +324,7 @@ impl OperandValue<'ll> { // Allocate an appropriate region on the stack, and copy the value into it let (llsize, _) = glue::size_and_align_of_dst(&bx, unsized_ty, Some(llextra)); let lldst = bx.array_alloca(Type::i8(bx.cx), llsize, "unsized_tmp", max_align); - base::call_memcpy(&bx, lldst, llptr, llsize, min_align, flags); + base::call_memcpy(&bx, lldst, max_align, llptr, min_align, llsize, flags); // Store the allocated region and the extra to the indirect place. let indirect_operand = OperandValue::Pair(lldst, llextra); diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 720e8def5ab1c..7e69e98071d4b 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -108,7 +108,13 @@ pub enum ColorConfig { impl ColorConfig { fn to_color_choice(&self) -> ColorChoice { match *self { - ColorConfig::Always => ColorChoice::Always, + ColorConfig::Always => { + if atty::is(atty::Stream::Stderr) { + ColorChoice::Always + } else { + ColorChoice::AlwaysAnsi + } + } ColorConfig::Never => ColorChoice::Never, ColorConfig::Auto if atty::is(atty::Stream::Stderr) => { ColorChoice::Auto diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index db56ce4627410..c432826dca865 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -21,7 +21,6 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::bit_set::BitSet; use std::fmt; -use std::hash::Hash; use std::ops::Index; crate struct BorrowSet<'tcx> { @@ -233,21 +232,13 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { self.insert_as_pending_if_two_phase(location, &assigned_place, region, kind, idx); - insert(&mut self.region_map, ®ion, idx); + self.region_map.entry(region).or_default().insert(idx); if let Some(local) = borrowed_place.root_local() { - insert(&mut self.local_map, &local, idx); + self.local_map.entry(local).or_default().insert(idx); } } - return self.super_assign(block, assigned_place, rvalue, location); - - fn insert<'a, K, V>(map: &'a mut FxHashMap>, k: &K, v: V) - where - K: Clone + Eq + Hash, - V: Eq + Hash, - { - map.entry(k.clone()).or_default().insert(v); - } + self.super_assign(block, assigned_place, rvalue, location) } fn visit_place( diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index d4f00ab3bb91a..4e03f6f7f5e7a 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -281,23 +281,21 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( // Note that this set is expected to be small - only upvars from closures // would have a chance of erroneously adding non-user-defined mutable vars // to the set. - let temporary_used_locals: FxHashSet = mbcx - .used_mut - .iter() + let temporary_used_locals: FxHashSet = mbcx.used_mut.iter() .filter(|&local| mbcx.mir.local_decls[*local].is_user_variable.is_none()) .cloned() .collect(); - mbcx.gather_used_muts(temporary_used_locals); + // For the remaining unused locals that are marked as mutable, we avoid linting any that + // were never initialized. These locals may have been removed as unreachable code; or will be + // linted as unused variables. + let unused_mut_locals = mbcx.mir.mut_vars_iter() + .filter(|local| !mbcx.used_mut.contains(local)) + .collect(); + mbcx.gather_used_muts(temporary_used_locals, unused_mut_locals); debug!("mbcx.used_mut: {:?}", mbcx.used_mut); - let used_mut = mbcx.used_mut; - - for local in mbcx - .mir - .mut_vars_and_args_iter() - .filter(|local| !used_mut.contains(local)) - { + for local in mbcx.mir.mut_vars_and_args_iter().filter(|local| !used_mut.contains(local)) { if let ClearCrossCrate::Set(ref vsi) = mbcx.mir.source_scope_local_data { let local_decl = &mbcx.mir.local_decls[local]; diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs index dad87ed65a7d4..7c75fb59917c0 100644 --- a/src/librustc_mir/borrow_check/used_muts.rs +++ b/src/librustc_mir/borrow_check/used_muts.rs @@ -9,43 +9,113 @@ // except according to those terms. use rustc::mir::visit::{PlaceContext, Visitor}; -use rustc::mir::{Local, Location, Place}; +use rustc::mir::{BasicBlock, Local, Location, Place, Statement, StatementKind, TerminatorKind}; use rustc_data_structures::fx::FxHashSet; use borrow_check::MirBorrowckCtxt; impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { - /// Walks the MIR looking for assignments to a set of locals, as part of the unused mutable - /// local variables lint, to update the context's `used_mut` in a single walk. - crate fn gather_used_muts(&mut self, locals: FxHashSet) { - let mut visitor = GatherUsedMutsVisitor { - needles: locals, - mbcx: self, - }; - visitor.visit_mir(visitor.mbcx.mir); + /// Walks the MIR adding to the set of `used_mut` locals that will be ignored for the purposes + /// of the `unused_mut` lint. + /// + /// `temporary_used_locals` should contain locals that were found to be temporary, mutable and + /// used from borrow checking. This function looks for assignments into these locals from + /// user-declared locals and adds those user-defined locals to the `used_mut` set. This can + /// occur due to a rare case involving upvars in closures. + /// + /// `never_initialized_mut_locals` should contain the set of user-declared mutable locals + /// (not arguments) that have not already been marked as being used. + /// This function then looks for assignments from statements or the terminator into the locals + /// from this set and removes them from the set. This leaves only those locals that have not + /// been assigned to - this set is used as a proxy for locals that were not initialized due to + /// unreachable code. These locals are then considered "used" to silence the lint for them. + /// See #55344 for context. + crate fn gather_used_muts( + &mut self, + temporary_used_locals: FxHashSet, + mut never_initialized_mut_locals: FxHashSet, + ) { + { + let mut visitor = GatherUsedMutsVisitor { + temporary_used_locals, + never_initialized_mut_locals: &mut never_initialized_mut_locals, + mbcx: self, + }; + visitor.visit_mir(visitor.mbcx.mir); + } + + // Take the union of the existed `used_mut` set with those variables we've found were + // never initialized. + debug!("gather_used_muts: never_initialized_mut_locals={:?}", never_initialized_mut_locals); + self.used_mut = self.used_mut.union(&never_initialized_mut_locals).cloned().collect(); } } -/// MIR visitor gathering the assignments to a set of locals, in a single walk. -/// 'visit = the duration of the MIR walk +/// MIR visitor for collecting used mutable variables. +/// The 'visit lifetime represents the duration of the MIR walk. struct GatherUsedMutsVisitor<'visit, 'cx: 'visit, 'gcx: 'tcx, 'tcx: 'cx> { - needles: FxHashSet, + temporary_used_locals: FxHashSet, + never_initialized_mut_locals: &'visit mut FxHashSet, mbcx: &'visit mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>, } impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'gcx, 'tcx> { + fn visit_terminator_kind( + &mut self, + _block: BasicBlock, + kind: &TerminatorKind<'tcx>, + _location: Location, + ) { + debug!("visit_terminator_kind: kind={:?}", kind); + match &kind { + TerminatorKind::Call { destination: Some((into, _)), .. } => { + if let Some(local) = into.base_local() { + debug!( + "visit_terminator_kind: kind={:?} local={:?} \ + never_initialized_mut_locals={:?}", + kind, local, self.never_initialized_mut_locals + ); + let _ = self.never_initialized_mut_locals.remove(&local); + } + }, + _ => {}, + } + } + + fn visit_statement( + &mut self, + _block: BasicBlock, + statement: &Statement<'tcx>, + _location: Location, + ) { + match &statement.kind { + StatementKind::Assign(into, _) => { + // Remove any locals that we found were initialized from the + // `never_initialized_mut_locals` set. At the end, the only remaining locals will + // be those that were never initialized - we will consider those as being used as + // they will either have been removed by unreachable code optimizations; or linted + // as unused variables. + if let Some(local) = into.base_local() { + debug!( + "visit_statement: statement={:?} local={:?} \ + never_initialized_mut_locals={:?}", + statement, local, self.never_initialized_mut_locals + ); + let _ = self.never_initialized_mut_locals.remove(&local); + } + }, + _ => {}, + } + } + fn visit_local( &mut self, local: &Local, place_context: PlaceContext<'tcx>, location: Location, ) { - if !self.needles.contains(local) { - return; - } - - if place_context.is_place_assignment() { + if place_context.is_place_assignment() && self.temporary_used_locals.contains(local) { // Propagate the Local assigned at this Location as a used mutable local variable for moi in &self.mbcx.move_data.loc_map[location] { let mpi = &self.mbcx.move_data.moves[*moi].path; diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 76a8501fb177a..54983b8f4e026 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -196,7 +196,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }; let return_block = BasicBlock::new(1); - let mut blocks = IndexVec::new(); + let mut blocks = IndexVec::with_capacity(2); let block = |blocks: &mut IndexVec<_, _>, kind| { blocks.push(BasicBlockData { statements: vec![], @@ -768,7 +768,8 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, })); } - let mut blocks = IndexVec::new(); + let n_blocks = if let Adjustment::RefMut = rcvr_adjustment { 5 } else { 2 }; + let mut blocks = IndexVec::with_capacity(n_blocks); let block = |blocks: &mut IndexVec<_, _>, statements, kind, is_cleanup| { blocks.push(BasicBlockData { statements, diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 199cf5650fda8..2db3bbda3233b 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -137,7 +137,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let callee_mir = match self.tcx.try_optimized_mir(callsite.location.span, callsite.callee) { - Ok(callee_mir) if self.should_inline(callsite, callee_mir) => { + Ok(callee_mir) if self.consider_optimizing(callsite, callee_mir) => { self.tcx.subst_and_normalize_erasing_regions( &callsite.substs, param_env, @@ -198,6 +198,18 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { } } + fn consider_optimizing(&self, + callsite: CallSite<'tcx>, + callee_mir: &Mir<'tcx>) + -> bool + { + debug!("consider_optimizing({:?})", callsite); + self.should_inline(callsite, callee_mir) + && self.tcx.consider_optimizing(|| format!("Inline {:?} into {:?}", + callee_mir.span, + callsite)) + } + fn should_inline(&self, callsite: CallSite<'tcx>, callee_mir: &Mir<'tcx>) diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index e79da88a2464b..c5add6260789a 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -310,16 +310,11 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { match statement.kind { StatementKind::Assign(_, box Rvalue::Ref(_, _, ref mut place)) => { // Find the underlying local for this (necessarily interior) borrow. - // HACK(eddyb) using a recursive function because of mutable borrows. - fn interior_base<'a, 'tcx>(place: &'a mut Place<'tcx>) - -> &'a mut Place<'tcx> { - if let Place::Projection(ref mut proj) = *place { - assert_ne!(proj.elem, ProjectionElem::Deref); - return interior_base(&mut proj.base); - } - place - } - let place = interior_base(place); + let mut place = place; + while let Place::Projection(ref mut proj) = *place { + assert_ne!(proj.elem, ProjectionElem::Deref); + place = &mut proj.base; + }; let ty = place.ty(local_decls, self.tcx).to_ty(self.tcx); let span = statement.source_info.span; diff --git a/src/librustc_target/spec/linux_musl_base.rs b/src/librustc_target/spec/linux_musl_base.rs index 7a3f3c2a518bc..c87f14977cb1d 100644 --- a/src/librustc_target/spec/linux_musl_base.rs +++ b/src/librustc_target/spec/linux_musl_base.rs @@ -24,31 +24,6 @@ pub fn opts() -> TargetOptions { // argument is *not* necessary for normal builds, but it can't hurt! base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,--eh-frame-hdr".to_string()); - // There's a whole bunch of circular dependencies when dealing with MUSL - // unfortunately. To put this in perspective libc is statically linked to - // liblibc and libunwind is statically linked to libstd: - // - // * libcore depends on `fmod` which is in libc (transitively in liblibc). - // liblibc, however, depends on libcore. - // * compiler-rt has personality symbols that depend on libunwind, but - // libunwind is in libstd which depends on compiler-rt. - // - // Recall that linkers discard libraries and object files as much as - // possible, and with all the static linking and archives flying around with - // MUSL the linker is super aggressively stripping out objects. For example - // the first case has fmod stripped from liblibc (it's in its own object - // file) so it's not there when libcore needs it. In the second example all - // the unused symbols from libunwind are stripped (each is in its own object - // file in libstd) before we end up linking compiler-rt which depends on - // those symbols. - // - // To deal with these circular dependencies we just force the compiler to - // link everything as a group, not stripping anything out until everything - // is processed. The linker will still perform a pass to strip out object - // files but it won't do so until all objects/archives have been processed. - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,-(".to_string()); - base.post_link_args.insert(LinkerFlavor::Gcc, vec!["-Wl,-)".to_string()]); - // When generating a statically linked executable there's generally some // small setup needed which is listed in these files. These are provided by // a musl toolchain and are linked by default by the `musl-gcc` script. Note diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 40f2072079a5a..4a300fe09215c 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -814,11 +814,6 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); report_unexpected_def(def); return self.tcx.types.err; } - // Replace constructor type with constructed type for tuple struct patterns. - let pat_ty = pat_ty.fn_sig(tcx).output(); - let pat_ty = pat_ty.no_bound_vars().expect("expected fn type"); - - self.demand_eqtype(pat.span, expected, pat_ty); let variant = match def { Def::Err => { @@ -836,6 +831,13 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); } _ => bug!("unexpected pattern definition: {:?}", def) }; + + // Replace constructor type with constructed type for tuple struct patterns. + let pat_ty = pat_ty.fn_sig(tcx).output(); + let pat_ty = pat_ty.no_bound_vars().expect("expected fn type"); + + self.demand_eqtype(pat.span, expected, pat_ty); + // Type check subpatterns. if subpats.len() == variant.fields.len() || subpats.len() < variant.fields.len() && ddpos.is_some() { diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 8f679b4d22b25..1ae3b0b88c6dd 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -70,7 +70,7 @@ /* General structure and fonts */ body { - font: 16px/1.4 "Source Serif Pro", Georgia, Times, "Times New Roman", serif; + font: 16px/1.4 "Source Serif Pro", serif; margin: 0; position: relative; padding: 10px 15px 20px 15px; @@ -114,7 +114,7 @@ h3.impl, h3.method, h3.type { h1, h2, h3, h4, .sidebar, a.source, .search-input, .content table :not(code)>a, .collapse-toggle, div.item-list .out-of-band { - font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-family: "Fira Sans", sans-serif; } ol, ul { @@ -133,7 +133,7 @@ summary { } code, pre { - font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", Inconsolata, monospace; + font-family: "Source Code Pro", monospace; white-space: pre-wrap; } .docblock code, .docblock-short code { @@ -415,7 +415,7 @@ h4 > code, h3 > code, .invisible > code { } #main > .since { top: inherit; - font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-family: "Fira Sans", sans-serif; } .content table:not(.table-display) { @@ -1338,7 +1338,7 @@ h3.important { kbd { display: inline-block; padding: 3px 5px; - font: 15px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; + font: 15px monospace; line-height: 10px; vertical-align: middle; border: solid 1px; diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 34bbbb53d5ff1..96c92ceb5bb41 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -399,6 +399,8 @@ macro_rules! await { /// For more information about select, see the `std::sync::mpsc::Select` structure. #[macro_export] #[unstable(feature = "mpsc_select", issue = "27800")] +#[rustc_deprecated(since = "1.32.0", + reason = "channel selection will be removed in a future release")] macro_rules! select { ( $($name:pat = $rx:ident.$meth:ident() => $code:expr),+ diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 81f98a55c1171..059ced4f56efd 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -124,6 +124,7 @@ //! ``` #![stable(feature = "rust1", since = "1.0.0")] +#![allow(deprecated)] // for mpsc_select // A description of how Rust's channel implementation works // diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs index a7a284cfb7994..2ec4b52dbf3cb 100644 --- a/src/libstd/sync/mpsc/select.rs +++ b/src/libstd/sync/mpsc/select.rs @@ -51,11 +51,10 @@ #![unstable(feature = "mpsc_select", reason = "This implementation, while likely sufficient, is unsafe and \ likely to be error prone. At some point in the future this \ - module will likely be replaced, and it is currently \ - unknown how much API breakage that will cause. The ability \ - to select over a number of channels will remain forever, \ - but no guarantees beyond this are being made", + module will be removed.", issue = "27800")] +#![rustc_deprecated(since = "1.32.0", + reason = "channel selection will be removed in a future release")] use fmt; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index cfedda18a7e22..2f17bc0548cad 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1086,7 +1086,7 @@ pub enum ExprKind { /// A unary operation (For example: `!x`, `*x`) Unary(UnOp, P), /// A literal (For example: `1`, `"foo"`) - Lit(P), + Lit(Lit), /// A cast (`foo as f64`) Cast(P, P), Type(P, P), diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 1701c8da2c5bd..88ee80e60888f 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -491,7 +491,7 @@ impl DummyResult { pub fn raw_expr(sp: Span) -> P { P(ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprKind::Lit(P(source_map::respan(sp, ast::LitKind::Bool(false)))), + node: ast::ExprKind::Lit(source_map::respan(sp, ast::LitKind::Bool(false))), span: sp, attrs: ThinVec::new(), }) diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 7928ec1606b1d..cacec867cf198 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -695,7 +695,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn expr_lit(&self, sp: Span, lit: ast::LitKind) -> P { - self.expr(sp, ast::ExprKind::Lit(P(respan(sp, lit)))) + self.expr(sp, ast::ExprKind::Lit(respan(sp, lit))) } fn expr_usize(&self, span: Span, i: usize) -> P { self.expr_lit(span, ast::LitKind::Int(i as u128, diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 37800a334c6da..c6e0adbb5a43e 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -274,7 +274,7 @@ pub mod rt { // FIXME: This is wrong P(ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprKind::Lit(P(self.clone())), + node: ast::ExprKind::Lit(self.clone()), span: DUMMY_SP, attrs: ThinVec::new(), }).to_tokens(cx) @@ -305,7 +305,7 @@ pub mod rt { let lit = ast::LitKind::Int(val as u128, ast::LitIntType::Signed($tag)); let lit = P(ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprKind::Lit(P(dummy_spanned(lit))), + node: ast::ExprKind::Lit(dummy_spanned(lit)), span: DUMMY_SP, attrs: ThinVec::new(), }); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c8a686da179fb..68e7e40c43efe 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1989,7 +1989,7 @@ impl<'a> Parser<'a> { let minus_lo = self.span; let minus_present = self.eat(&token::BinOp(token::Minus)); let lo = self.span; - let literal = P(self.parse_lit()?); + let literal = self.parse_lit()?; let hi = self.prev_span; let expr = self.mk_expr(lo.to(hi), ExprKind::Lit(literal), ThinVec::new()); diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 3dbde46f76241..f00b7f3a58f9c 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -1237,6 +1237,40 @@ extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, unwrap(Fn), makeArrayRef(unwrap(Args), NumArgs), Bundles, Name)); } +extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B, + LLVMValueRef Dst, unsigned DstAlign, + LLVMValueRef Src, unsigned SrcAlign, + LLVMValueRef Size, bool IsVolatile) { +#if LLVM_VERSION_GE(7, 0) + return wrap(unwrap(B)->CreateMemCpy( + unwrap(Dst), DstAlign, + unwrap(Src), SrcAlign, + unwrap(Size), IsVolatile)); +#else + unsigned Align = std::min(DstAlign, SrcAlign); + return wrap(unwrap(B)->CreateMemCpy( + unwrap(Dst), unwrap(Src), + unwrap(Size), Align, IsVolatile)); +#endif +} + +extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B, + LLVMValueRef Dst, unsigned DstAlign, + LLVMValueRef Src, unsigned SrcAlign, + LLVMValueRef Size, bool IsVolatile) { +#if LLVM_VERSION_GE(7, 0) + return wrap(unwrap(B)->CreateMemMove( + unwrap(Dst), DstAlign, + unwrap(Src), SrcAlign, + unwrap(Size), IsVolatile)); +#else + unsigned Align = std::min(DstAlign, SrcAlign); + return wrap(unwrap(B)->CreateMemMove( + unwrap(Dst), unwrap(Src), + unwrap(Size), Align, IsVolatile)); +#endif +} + extern "C" LLVMValueRef LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, LLVMBasicBlockRef Then, diff --git a/src/test/codegen/packed.rs b/src/test/codegen/packed.rs index 10dd12909b644..b50f5b6f16fed 100644 --- a/src/test/codegen/packed.rs +++ b/src/test/codegen/packed.rs @@ -65,7 +65,7 @@ pub struct BigPacked2 { pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 { // CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array // CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]]) -// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 %{{.*}}, i8* align 1 %{{.*}}, i{{[0-9]+}} 32, i1 false) +// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 %{{.*}}, i8* align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false) // check that calls whose destination is a field of a packed struct // go through an alloca rather than calling the function with an // unaligned destination. @@ -77,7 +77,7 @@ pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 { pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 { // CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array // CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]]) -// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 2 %{{.*}}, i8* align 2 %{{.*}}, i{{[0-9]+}} 32, i1 false) +// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 2 %{{.*}}, i8* align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false) // check that calls whose destination is a field of a packed struct // go through an alloca rather than calling the function with an // unaligned destination. diff --git a/src/test/codegen/stores.rs b/src/test/codegen/stores.rs index 0aaf00bfdbe8e..871bee13b1931 100644 --- a/src/test/codegen/stores.rs +++ b/src/test/codegen/stores.rs @@ -31,7 +31,7 @@ pub fn small_array_alignment(x: &mut [i8; 4], y: [i8; 4]) { // CHECK: store i32 %0, i32* [[TMP]] // CHECK: [[Y8:%[0-9]+]] = bitcast [4 x i8]* %y to i8* // CHECK: [[TMP8:%[0-9]+]] = bitcast i32* [[TMP]] to i8* -// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 [[Y8]], i8* align 1 [[TMP8]], i{{[0-9]+}} 4, i1 false) +// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 [[Y8]], i8* align 4 [[TMP8]], i{{[0-9]+}} 4, i1 false) *x = y; } @@ -45,6 +45,6 @@ pub fn small_struct_alignment(x: &mut Bytes, y: Bytes) { // CHECK: store i32 %0, i32* [[TMP]] // CHECK: [[Y8:%[0-9]+]] = bitcast %Bytes* %y to i8* // CHECK: [[TMP8:%[0-9]+]] = bitcast i32* [[TMP]] to i8* -// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 [[Y8]], i8* align 1 [[TMP8]], i{{[0-9]+}} 4, i1 false) +// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 [[Y8]], i8* align 4 [[TMP8]], i{{[0-9]+}} 4, i1 false) *x = y; } diff --git a/src/test/run-pass/issues/issue-13494.rs b/src/test/run-pass/issues/issue-13494.rs index 0750a4c895936..a31ad72b0881a 100644 --- a/src/test/run-pass/issues/issue-13494.rs +++ b/src/test/run-pass/issues/issue-13494.rs @@ -16,6 +16,7 @@ // expose is still present. #![feature(mpsc_select)] +#![allow(deprecated)] use std::sync::mpsc::{channel, Sender, Receiver}; use std::thread; diff --git a/src/test/ui/coherence/coherence-impls-copy.stderr b/src/test/ui/coherence/coherence-impls-copy.stderr index 613ee0a269e70..dc417957795f5 100644 --- a/src/test/ui/coherence/coherence-impls-copy.stderr +++ b/src/test/ui/coherence/coherence-impls-copy.stderr @@ -14,7 +14,7 @@ LL | impl Copy for &'static NotSync {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: conflicting implementation in crate `core`: - - impl<'_, T> std::marker::Copy for &T + - impl std::marker::Copy for &T where T: ?Sized; error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&[NotSync]`: @@ -24,7 +24,7 @@ LL | impl Copy for &'static [NotSync] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: conflicting implementation in crate `core`: - - impl<'_, T> std::marker::Copy for &T + - impl std::marker::Copy for &T where T: ?Sized; error[E0206]: the trait `Copy` may not be implemented for this type diff --git a/src/test/ui/e0119/issue-28981.stderr b/src/test/ui/e0119/issue-28981.stderr index 4886ad7717574..76ff88d6cc623 100644 --- a/src/test/ui/e0119/issue-28981.stderr +++ b/src/test/ui/e0119/issue-28981.stderr @@ -5,7 +5,7 @@ LL | impl Deref for Foo { } //~ ERROR must be used | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: conflicting implementation in crate `core`: - - impl<'_, T> std::ops::Deref for &T + - impl std::ops::Deref for &T where T: ?Sized; error[E0210]: type parameter `Foo` must be used as the type parameter for some local type (e.g. `MyStruct`) diff --git a/src/test/ui/extern/extern-const.fixed b/src/test/ui/extern/extern-const.fixed new file mode 100644 index 0000000000000..dca5698a70c20 --- /dev/null +++ b/src/test/ui/extern/extern-const.fixed @@ -0,0 +1,25 @@ +// Check extern items cannot be const + `rustfix` suggests using +// extern static. +// +// #54388: an unused reference to an undefined static may or may not +// compile. To sidestep this by using one that *is* defined. + +// run-rustfix +// ignore-wasm32 no external library to link to. +// compile-flags: -g -Z continue-parse-after-error +#![feature(libc)] +extern crate libc; + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + static rust_dbg_static_mut: libc::c_int; //~ ERROR extern items cannot be `const` +} + +fn main() { + // We suggest turning the (illegal) extern `const` into an extern `static`, + // but this also requires `unsafe` (a deny-by-default lint at comment time, + // future error; Issue #36247) + unsafe { + let _x = rust_dbg_static_mut; + } +} diff --git a/src/test/ui/extern/extern-const.rs b/src/test/ui/extern/extern-const.rs index d8a167311d55c..07dbe545a850a 100644 --- a/src/test/ui/extern/extern-const.rs +++ b/src/test/ui/extern/extern-const.rs @@ -1,18 +1,18 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. +// Check extern items cannot be const + `rustfix` suggests using +// extern static. // -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. +// #54388: an unused reference to an undefined static may or may not +// compile. To sidestep this by using one that *is* defined. -// FIXME(#54388): re-enable rustfix later, when this test has consistent output across targets -// compile-flags: -Z continue-parse-after-error +// run-rustfix +// ignore-wasm32 no external library to link to. +// compile-flags: -g -Z continue-parse-after-error +#![feature(libc)] +extern crate libc; +#[link(name = "rust_test_helpers", kind = "static")] extern "C" { - const C: u8; //~ ERROR extern items cannot be `const` + const rust_dbg_static_mut: libc::c_int; //~ ERROR extern items cannot be `const` } fn main() { @@ -20,6 +20,6 @@ fn main() { // but this also requires `unsafe` (a deny-by-default lint at comment time, // future error; Issue #36247) unsafe { - let _x = C; + let _x = rust_dbg_static_mut; } } diff --git a/src/test/ui/extern/extern-const.stderr b/src/test/ui/extern/extern-const.stderr index cbed5e56c76c4..7ebaec0368e3d 100644 --- a/src/test/ui/extern/extern-const.stderr +++ b/src/test/ui/extern/extern-const.stderr @@ -1,7 +1,7 @@ error: extern items cannot be `const` --> $DIR/extern-const.rs:15:5 | -LL | const C: u8; //~ ERROR extern items cannot be `const` +LL | const rust_dbg_static_mut: libc::c_int; //~ ERROR extern items cannot be `const` | ^^^^^ help: try using a static value: `static` error: aborting due to previous error diff --git a/src/test/ui/impl-trait/issue-55608-captures-empty-region.rs b/src/test/ui/impl-trait/issue-55608-captures-empty-region.rs new file mode 100644 index 0000000000000..7ebc348996f5e --- /dev/null +++ b/src/test/ui/impl-trait/issue-55608-captures-empty-region.rs @@ -0,0 +1,22 @@ +// This used to ICE because it creates an `impl Trait` that captures a +// hidden empty region. + +#![feature(conservative_impl_trait)] + +fn server() -> impl FilterBase2 { //~ ERROR [E0700] + segment2(|| { loop { } }).map2(|| "") +} + +trait FilterBase2 { + fn map2(self, _fn: F) -> Map2 where Self: Sized { loop { } } +} + +struct Map2 { _func: F } + +impl FilterBase2 for Map2 { } + +fn segment2(_fn: F) -> Map2 where F: Fn() -> Result<(), ()> { + loop { } +} + +fn main() { server(); } diff --git a/src/test/ui/impl-trait/issue-55608-captures-empty-region.stderr b/src/test/ui/impl-trait/issue-55608-captures-empty-region.stderr new file mode 100644 index 0000000000000..d1f147834d2ef --- /dev/null +++ b/src/test/ui/impl-trait/issue-55608-captures-empty-region.stderr @@ -0,0 +1,11 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/issue-55608-captures-empty-region.rs:6:16 + | +LL | fn server() -> impl FilterBase2 { //~ ERROR [E0700] + | ^^^^^^^^^^^^^^^^ + | + = note: hidden type `Map2<[closure@$DIR/issue-55608-captures-empty-region.rs:7:36: 7:41]>` captures an empty lifetime + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/match/match-fn-call.rs b/src/test/ui/match/match-fn-call.rs new file mode 100644 index 0000000000000..d9c50e75c4944 --- /dev/null +++ b/src/test/ui/match/match-fn-call.rs @@ -0,0 +1,12 @@ +use std::path::Path; + +fn main() { + let path = Path::new("foo"); + match path { + Path::new("foo") => println!("foo"), + //~^ ERROR expected tuple struct/variant + Path::new("bar") => println!("bar"), + //~^ ERROR expected tuple struct/variant + _ => (), + } +} diff --git a/src/test/ui/match/match-fn-call.stderr b/src/test/ui/match/match-fn-call.stderr new file mode 100644 index 0000000000000..4e24621706bdb --- /dev/null +++ b/src/test/ui/match/match-fn-call.stderr @@ -0,0 +1,15 @@ +error[E0164]: expected tuple struct/variant, found method `::new` + --> $DIR/match-fn-call.rs:6:9 + | +LL | Path::new("foo") => println!("foo"), + | ^^^^^^^^^^^^^^^^ not a tuple variant or struct + +error[E0164]: expected tuple struct/variant, found method `::new` + --> $DIR/match-fn-call.rs:8:9 + | +LL | Path::new("bar") => println!("bar"), + | ^^^^^^^^^^^^^^^^ not a tuple variant or struct + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0164`. diff --git a/src/test/ui/nll/issue-55344.rs b/src/test/ui/nll/issue-55344.rs new file mode 100644 index 0000000000000..131c979a24b7d --- /dev/null +++ b/src/test/ui/nll/issue-55344.rs @@ -0,0 +1,26 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass + +#![feature(nll)] +#![allow(unreachable_code)] +#![deny(unused_mut)] + +pub fn foo() { + return; + + let mut v = 0; + assert_eq!(v, 0); + v = 1; + assert_eq!(v, 1); +} + +fn main() {}