diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index a3a73ff6c6cf6..924563fc44f6e 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -259,7 +259,8 @@ pub(crate) struct FatPtr { /// ``` #[inline] #[unstable(feature = "slice_from_raw_parts", reason = "recently added", issue = "36925")] -pub fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { +#[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")] +pub const fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { unsafe { Repr { raw: FatPtr { data, len } }.rust } } @@ -275,7 +276,8 @@ pub fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { /// [`from_raw_parts_mut`]: ../../std/slice/fn.from_raw_parts_mut.html #[inline] #[unstable(feature = "slice_from_raw_parts", reason = "recently added", issue = "36925")] -pub fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { +#[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")] +pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { unsafe { Repr { raw: FatPtr { data, len } }.rust_mut } } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 3da992dca30ee..e2cc99813aca5 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2325,7 +2325,7 @@ impl str { i.get_mut(self) } - /// Returns a unchecked subslice of `str`. + /// Returns an unchecked subslice of `str`. /// /// This is the unchecked alternative to indexing the `str`. /// diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index b28ed2eaa0876..1f20ebc01e993 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -36,6 +36,9 @@ #![feature(iter_is_partitioned)] #![feature(iter_order_by)] #![feature(cmp_min_max_by)] +#![feature(slice_from_raw_parts)] +#![feature(const_slice_from_raw_parts)] +#![feature(const_raw_ptr_deref)] extern crate test; diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs index eea736bc88f01..473bc881d2932 100644 --- a/src/libcore/tests/ptr.rs +++ b/src/libcore/tests/ptr.rs @@ -1,6 +1,17 @@ use core::cell::RefCell; use core::ptr::*; +#[test] +fn test_const_from_raw_parts() { + const SLICE: &[u8] = &[1, 2, 3, 4]; + const FROM_RAW: &[u8] = unsafe { &*slice_from_raw_parts(SLICE.as_ptr(), SLICE.len()) }; + assert_eq!(SLICE, FROM_RAW); + + let slice = &[1, 2, 3, 4, 5]; + let from_raw = unsafe { &*slice_from_raw_parts(slice.as_ptr(), 2) } ; + assert_eq!(&slice[..2], from_raw); +} + #[test] fn test() { unsafe { diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 6b83788298e4d..2fd708f1ea344 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2253,7 +2253,7 @@ impl<'a> LoweringContext<'a> { let is_mutable_pat = match arg.pat.kind { PatKind::Ident(BindingMode::ByValue(mt), _, _) | PatKind::Ident(BindingMode::ByRef(mt), _, _) => - mt == Mutability::Mutable, + mt == Mutability::Mut, _ => false, }; @@ -2264,7 +2264,7 @@ impl<'a> LoweringContext<'a> { // the case where we have a mutable pattern to a reference as that would // no longer be an `ImplicitSelf`. TyKind::Rptr(_, ref mt) if mt.ty.kind.is_implicit_self() && - mt.mutbl == ast::Mutability::Mutable => + mt.mutbl == ast::Mutability::Mut => hir::ImplicitSelfKind::MutRef, TyKind::Rptr(_, ref mt) if mt.ty.kind.is_implicit_self() => hir::ImplicitSelfKind::ImmRef, @@ -3068,10 +3068,10 @@ impl<'a> LoweringContext<'a> { fn lower_binding_mode(&mut self, b: &BindingMode) -> hir::BindingAnnotation { match *b { - BindingMode::ByValue(Mutability::Immutable) => hir::BindingAnnotation::Unannotated, - BindingMode::ByRef(Mutability::Immutable) => hir::BindingAnnotation::Ref, - BindingMode::ByValue(Mutability::Mutable) => hir::BindingAnnotation::Mutable, - BindingMode::ByRef(Mutability::Mutable) => hir::BindingAnnotation::RefMut, + BindingMode::ByValue(Mutability::Not) => hir::BindingAnnotation::Unannotated, + BindingMode::ByRef(Mutability::Not) => hir::BindingAnnotation::Ref, + BindingMode::ByValue(Mutability::Mut) => hir::BindingAnnotation::Mutable, + BindingMode::ByRef(Mutability::Mut) => hir::BindingAnnotation::RefMut, } } diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs index 04031710dc5ea..a1a37719812b6 100644 --- a/src/librustc/hir/lowering/expr.rs +++ b/src/librustc/hir/lowering/expr.rs @@ -1340,7 +1340,7 @@ impl LoweringContext<'_> { fn expr_mut_addr_of(&mut self, span: Span, e: P) -> hir::Expr { self.expr( span, - hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mutable, e), + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e), ThinVec::new(), ) } diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index 97228c8f24038..b59c7438005b2 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -169,11 +169,10 @@ impl hir::Pat { self.each_binding(|annotation, _, _, _| { match annotation { hir::BindingAnnotation::Ref => match result { - None | Some(hir::Mutability::Immutable) => - result = Some(hir::Mutability::Immutable), + None | Some(hir::Mutability::Not) => result = Some(hir::Mutability::Not), _ => {} } - hir::BindingAnnotation::RefMut => result = Some(hir::Mutability::Mutable), + hir::BindingAnnotation::RefMut => result = Some(hir::Mutability::Mut), _ => {} } }); diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index a069331582ea6..92ad1c38fa043 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -386,7 +386,7 @@ impl<'a> State<'a> { } hir::ForeignItemKind::Static(ref t, m) => { self.head(visibility_qualified(&item.vis, "static")); - if m == hir::Mutability::Mutable { + if m == hir::Mutability::Mut { self.word_space("mut"); } self.print_ident(item.ident); @@ -502,7 +502,7 @@ impl<'a> State<'a> { } hir::ItemKind::Static(ref ty, m, expr) => { self.head(visibility_qualified(&item.vis, "static")); - if m == hir::Mutability::Mutable { + if m == hir::Mutability::Mut { self.word_space("mut"); } self.print_ident(item.ident); @@ -1632,11 +1632,11 @@ impl<'a> State<'a> { match binding_mode { hir::BindingAnnotation::Ref => { self.word_nbsp("ref"); - self.print_mutability(hir::Mutability::Immutable, false); + self.print_mutability(hir::Mutability::Not, false); } hir::BindingAnnotation::RefMut => { self.word_nbsp("ref"); - self.print_mutability(hir::Mutability::Mutable, false); + self.print_mutability(hir::Mutability::Mut, false); } hir::BindingAnnotation::Unannotated => {} hir::BindingAnnotation::Mutable => { @@ -2065,8 +2065,8 @@ impl<'a> State<'a> { pub fn print_mutability(&mut self, mutbl: hir::Mutability, print_const: bool) { match mutbl { - hir::Mutability::Mutable => self.word_nbsp("mut"), - hir::Mutability::Immutable => if print_const { self.word_nbsp("const") }, + hir::Mutability::Mut => self.word_nbsp("mut"), + hir::Mutability::Not => if print_const { self.word_nbsp("const") }, } } diff --git a/src/librustc/lint/internal.rs b/src/librustc/lint/internal.rs index 10c0c63995ca2..f80a72365e361 100644 --- a/src/librustc/lint/internal.rs +++ b/src/librustc/lint/internal.rs @@ -132,7 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind { } } } - TyKind::Rptr(_, MutTy { ty: inner_ty, mutbl: Mutability::Immutable }) => { + TyKind::Rptr(_, MutTy { ty: inner_ty, mutbl: Mutability::Not }) => { if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner_def_id()) { if cx.tcx.impl_trait_ref(impl_did).is_some() { return; diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index f849361e08be9..a1bb80f6179e2 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -106,7 +106,7 @@ impl Allocation { undef_mask: UndefMask::new(size, true), size, align, - mutability: Mutability::Immutable, + mutability: Mutability::Not, extra: (), } } @@ -123,7 +123,7 @@ impl Allocation { undef_mask: UndefMask::new(size, false), size, align, - mutability: Mutability::Mutable, + mutability: Mutability::Mut, extra: (), } } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 3b4adbaf78c74..0757e02da970d 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -34,6 +34,7 @@ use std::ops::Index; use std::slice; use std::{iter, mem, option, u32}; use syntax::ast::Name; +pub use syntax::ast::Mutability; use syntax::symbol::Symbol; use syntax_pos::{Span, DUMMY_SP}; @@ -396,22 +397,7 @@ pub struct SourceInfo { } /////////////////////////////////////////////////////////////////////////// -// Mutability and borrow kinds - -#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)] -pub enum Mutability { - Mut, - Not, -} - -impl From for hir::Mutability { - fn from(m: Mutability) -> Self { - match m { - Mutability::Mut => hir::Mutability::Mutable, - Mutability::Not => hir::Mutability::Immutable, - } - } -} +// Borrow kinds #[derive( Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, HashStable, @@ -2886,7 +2872,6 @@ pub enum ClosureOutlivesSubject<'tcx> { CloneTypeFoldableAndLiftImpls! { BlockTailInfo, MirPhase, - Mutability, SourceInfo, FakeReadCause, RetagKind, diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index a24b1d863d644..841c0b458d157 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -279,17 +279,17 @@ impl<'tcx> BinOp { impl BorrowKind { pub fn to_mutbl_lossy(self) -> hir::Mutability { match self { - BorrowKind::Mut { .. } => hir::Mutability::Mutable, - BorrowKind::Shared => hir::Mutability::Immutable, + BorrowKind::Mut { .. } => hir::Mutability::Mut, + BorrowKind::Shared => hir::Mutability::Not, // We have no type corresponding to a unique imm borrow, so // use `&mut`. It gives all the capabilities of an `&uniq` // and hence is a safe "over approximation". - BorrowKind::Unique => hir::Mutability::Mutable, + BorrowKind::Unique => hir::Mutability::Mut, // We have no type corresponding to a shallow borrow, so use // `&` as an approximation. - BorrowKind::Shallow => hir::Mutability::Immutable, + BorrowKind::Shallow => hir::Mutability::Not, } } } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 4839974d6255c..735627578a627 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1548,8 +1548,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind { let trait_type = match mutability { - hir::Mutability::Mutable => self.tcx.mk_imm_ref(region, t_type), - hir::Mutability::Immutable => self.tcx.mk_mut_ref(region, t_type), + hir::Mutability::Mut => self.tcx.mk_imm_ref(region, t_type), + hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type), }; let new_obligation = self.mk_obligation_for_def_id( @@ -1565,7 +1565,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let sp = self.tcx.sess.source_map() .span_take_while(span, |c| c.is_whitespace() || *c == '&'); if points_at_arg && - mutability == hir::Mutability::Immutable && + mutability == hir::Mutability::Not && refs_number > 0 { err.span_suggestion( diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 94a77c553e53a..f1cd002d19b64 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2622,7 +2622,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Char | ty::RawPtr(..) | ty::Never - | ty::Ref(_, _, hir::Mutability::Immutable) => { + | ty::Ref(_, _, hir::Mutability::Not) => { // Implementations provided in libcore None } @@ -2633,7 +2633,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Generator(..) | ty::GeneratorWitness(..) | ty::Foreign(..) - | ty::Ref(_, _, hir::Mutability::Mutable) => None, + | ty::Ref(_, _, hir::Mutability::Mut) => None, ty::Array(element_ty, _) => { // (*) binder moved here diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs index 342644752b6c2..0c04ba96365ed 100644 --- a/src/librustc/ty/adjustment.rs +++ b/src/librustc/ty/adjustment.rs @@ -109,8 +109,8 @@ pub struct OverloadedDeref<'tcx> { impl<'tcx> OverloadedDeref<'tcx> { pub fn method_call(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> (DefId, SubstsRef<'tcx>) { let trait_def_id = match self.mutbl { - hir::Mutability::Immutable => tcx.lang_items().deref_trait(), - hir::Mutability::Mutable => tcx.lang_items().deref_mut_trait() + hir::Mutability::Not => tcx.lang_items().deref_trait(), + hir::Mutability::Mut => tcx.lang_items().deref_mut_trait() }; let method_def_id = tcx.associated_items(trait_def_id.unwrap()) .find(|m| m.kind == ty::AssocKind::Method).unwrap().def_id; @@ -138,15 +138,15 @@ pub enum AllowTwoPhase { #[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable)] pub enum AutoBorrowMutability { - Mutable { allow_two_phase_borrow: AllowTwoPhase }, - Immutable, + Mut { allow_two_phase_borrow: AllowTwoPhase }, + Not, } impl From for hir::Mutability { fn from(m: AutoBorrowMutability) -> Self { match m { - AutoBorrowMutability::Mutable { .. } => hir::Mutability::Mutable, - AutoBorrowMutability::Immutable => hir::Mutability::Immutable, + AutoBorrowMutability::Mut { .. } => hir::Mutability::Mut, + AutoBorrowMutability::Not => hir::Mutability::Not, } } } diff --git a/src/librustc/ty/binding.rs b/src/librustc/ty/binding.rs index 491e09dff0950..00cff1f1be17f 100644 --- a/src/librustc/ty/binding.rs +++ b/src/librustc/ty/binding.rs @@ -13,10 +13,10 @@ CloneTypeFoldableAndLiftImpls! { BindingMode, } impl BindingMode { pub fn convert(ba: BindingAnnotation) -> BindingMode { match ba { - Unannotated => BindingMode::BindByValue(Mutability::Immutable), - Mutable => BindingMode::BindByValue(Mutability::Mutable), - Ref => BindingMode::BindByReference(Mutability::Immutable), - RefMut => BindingMode::BindByReference(Mutability::Mutable), + Unannotated => BindingMode::BindByValue(Mutability::Not), + Mutable => BindingMode::BindByValue(Mutability::Mut), + Ref => BindingMode::BindByReference(Mutability::Not), + RefMut => BindingMode::BindByReference(Mutability::Mut), } } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 595ea40b2ffd5..0806e2d77650e 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2406,22 +2406,22 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_mut_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::Mutability::Mutable}) + self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::Mutability::Mut }) } #[inline] pub fn mk_imm_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::Mutability::Immutable}) + self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::Mutability::Not }) } #[inline] pub fn mk_mut_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::Mutability::Mutable}) + self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::Mutability::Mut }) } #[inline] pub fn mk_imm_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::Mutability::Immutable}) + self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::Mutability::Not }) } #[inline] diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index be6d21564a0f1..0218cb1d6fda7 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -248,7 +248,7 @@ impl<'tcx> ty::TyS<'tcx> { format!("`&{}`", tymut_string).into() } else { // Unknown type name, it's long or has type arguments match mutbl { - hir::Mutability::Mutable => "mutable reference", + hir::Mutability::Mut => "mutable reference", _ => "reference", }.into() } @@ -293,7 +293,7 @@ impl<'tcx> ty::TyS<'tcx> { ty::Slice(_) => "slice".into(), ty::RawPtr(_) => "raw pointer".into(), ty::Ref(.., mutbl) => match mutbl { - hir::Mutability::Mutable => "mutable reference", + hir::Mutability::Mut => "mutable reference", _ => "reference" }.into(), ty::FnDef(..) => "fn item".into(), diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index c7278dc4fac70..a8c44aa507cd8 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -2221,12 +2221,12 @@ where let tcx = cx.tcx(); let is_freeze = ty.is_freeze(tcx, cx.param_env(), DUMMY_SP); let kind = match mt { - hir::Mutability::Immutable => if is_freeze { + hir::Mutability::Not => if is_freeze { PointerKind::Frozen } else { PointerKind::Shared }, - hir::Mutability::Mutable => { + hir::Mutability::Mut => { // Previously we would only emit noalias annotations for LLVM >= 6 or in // panic=abort mode. That was deemed right, as prior versions had many bugs // in conjunction with unwinding, but later versions didn’t seem to have diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 15bbfa7860fa7..62fea7c31a9d9 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2657,8 +2657,8 @@ impl<'tcx> TyS<'tcx> { impl BorrowKind { pub fn from_mutbl(m: hir::Mutability) -> BorrowKind { match m { - hir::Mutability::Mutable => MutBorrow, - hir::Mutability::Immutable => ImmBorrow, + hir::Mutability::Mut => MutBorrow, + hir::Mutability::Not => ImmBorrow, } } @@ -2668,13 +2668,13 @@ impl BorrowKind { /// question. pub fn to_mutbl_lossy(self) -> hir::Mutability { match self { - MutBorrow => hir::Mutability::Mutable, - ImmBorrow => hir::Mutability::Immutable, + MutBorrow => hir::Mutability::Mut, + ImmBorrow => hir::Mutability::Not, // We have no type corresponding to a unique imm borrow, so // use `&mut`. It gives all the capabilities of an `&uniq` // and hence is a safe "over approximation". - UniqueImmBorrow => hir::Mutability::Mutable, + UniqueImmBorrow => hir::Mutability::Mut, } } diff --git a/src/librustc/ty/print/obsolete.rs b/src/librustc/ty/print/obsolete.rs index 7eb774849b178..5e146119b51ac 100644 --- a/src/librustc/ty/print/obsolete.rs +++ b/src/librustc/ty/print/obsolete.rs @@ -59,8 +59,8 @@ impl DefPathBasedNames<'tcx> { ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => { output.push('*'); match mutbl { - hir::Mutability::Immutable => output.push_str("const "), - hir::Mutability::Mutable => output.push_str("mut "), + hir::Mutability::Not => output.push_str("const "), + hir::Mutability::Mut => output.push_str("mut "), } self.push_type_name(inner_type, output, debug); diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 745f7d0276d80..b4f1f9d779a69 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -490,8 +490,8 @@ pub trait PrettyPrinter<'tcx>: ty::Float(t) => p!(write("{}", t.name_str())), ty::RawPtr(ref tm) => { p!(write("*{} ", match tm.mutbl { - hir::Mutability::Mutable => "mut", - hir::Mutability::Immutable => "const", + hir::Mutability::Mut => "mut", + hir::Mutability::Not => "const", })); p!(print(tm.ty)) } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index efdf40fd6b8a4..15b14c51c7843 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -121,8 +121,8 @@ impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> { } else { let mutbl = a.mutbl; let variance = match mutbl { - ast::Mutability::Immutable => ty::Covariant, - ast::Mutability::Mutable => ty::Invariant, + ast::Mutability::Not => ty::Covariant, + ast::Mutability::Mut => ty::Invariant, }; let ty = relation.relate_with_variance(variance, &a.ty, &b.ty)?; Ok(ty::TypeAndMut { ty, mutbl }) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 6cb0d1e9946b5..ea4369c0180fe 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1853,8 +1853,8 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_mutable_ptr(&self) -> bool { match self.kind { - RawPtr(TypeAndMut { mutbl: hir::Mutability::Mutable, .. }) | - Ref(_, _, hir::Mutability::Mutable) => true, + RawPtr(TypeAndMut { mutbl: hir::Mutability::Mut, .. }) | + Ref(_, _, hir::Mutability::Mut) => true, _ => false } } @@ -2044,7 +2044,7 @@ impl<'tcx> TyS<'tcx> { Adt(def, _) if def.is_box() => { Some(TypeAndMut { ty: self.boxed_ty(), - mutbl: hir::Mutability::Immutable, + mutbl: hir::Mutability::Not, }) }, Ref(_, ty, mutbl) => Some(TypeAndMut { ty, mutbl }), diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 0b11a9efd81d7..f054a630e4b8e 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -183,7 +183,7 @@ impl<'tcx> ty::ParamEnv<'tcx> { // Now libcore provides that impl. ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) | ty::Char | ty::RawPtr(..) | ty::Never | - ty::Ref(_, _, hir::Mutability::Immutable) => return Ok(()), + ty::Ref(_, _, hir::Mutability::Not) => return Ok(()), ty::Adt(adt, substs) => (adt, substs), @@ -679,7 +679,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns `true` if the node pointed to by `def_id` is a mutable `static` item. pub fn is_mutable_static(&self, def_id: DefId) -> bool { - self.static_mutability(def_id) == Some(hir::Mutability::Mutable) + self.static_mutability(def_id) == Some(hir::Mutability::Mut) } /// Get the type of the pointer to the static that we use in MIR. diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index ff03c1f76d87a..cda8fbc3517a9 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -277,7 +277,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { let base_addr = match alloc_kind { Some(GlobalAlloc::Memory(alloc)) => { let init = const_alloc_to_llvm(self, alloc); - if alloc.mutability == Mutability::Mutable { + if alloc.mutability == Mutability::Mut { self.static_addr_of_mut(init, alloc.align, None) } else { self.static_addr_of(init, alloc.align, None) diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 900f2d2defc0f..e178050b36918 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -1582,7 +1582,7 @@ fn generic_simd_intrinsic( // The second argument must be a simd vector with an element type that's a pointer // to the element type of the first argument let (pointer_count, underlying_ty) = match arg_tys[1].simd_type(tcx).kind { - ty::RawPtr(p) if p.ty == in_elem && p.mutbl == hir::Mutability::Mutable + ty::RawPtr(p) if p.ty == in_elem && p.mutbl == hir::Mutability::Mut => (ptr_count(arg_tys[1].simd_type(tcx)), non_ptr(arg_tys[1].simd_type(tcx))), _ => { diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 40739387b00c4..3145b0df63b8a 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -3,6 +3,7 @@ use crate::llvm; use syntax_pos::symbol::Symbol; use rustc::session::Session; use rustc::session::config::PrintRequest; +use rustc_data_structures::fx::FxHashSet; use rustc_target::spec::{MergeFunctions, PanicStrategy}; use libc::c_int; use std::ffi::CString; @@ -51,20 +52,37 @@ unsafe fn configure_llvm(sess: &Session) { llvm::LLVMRustInstallFatalErrorHandler(); + fn llvm_arg_to_arg_name(full_arg: &str) -> &str { + full_arg.trim().split(|c: char| { + c == '=' || c.is_whitespace() + }).next().unwrap_or("") + } + + let user_specified_args: FxHashSet<_> = sess + .opts + .cg + .llvm_args + .iter() + .map(|s| llvm_arg_to_arg_name(s)) + .filter(|s| s.len() > 0) + .collect(); + { - let mut add = |arg: &str| { - let s = CString::new(arg).unwrap(); - llvm_args.push(s.as_ptr()); - llvm_c_strs.push(s); + // This adds the given argument to LLVM. Unless `force` is true + // user specified arguments are *not* overridden. + let mut add = |arg: &str, force: bool| { + if force || !user_specified_args.contains(llvm_arg_to_arg_name(arg)) { + let s = CString::new(arg).unwrap(); + llvm_args.push(s.as_ptr()); + llvm_c_strs.push(s); + } }; - add("rustc"); // fake program name - if sess.time_llvm_passes() { add("-time-passes"); } - if sess.print_llvm_passes() { add("-debug-pass=Structure"); } - if sess.opts.debugging_opts.disable_instrumentation_preinliner { - add("-disable-preinline"); - } + add("rustc", true); // fake program name + if sess.time_llvm_passes() { add("-time-passes", false); } + if sess.print_llvm_passes() { add("-debug-pass=Structure", false); } + if sess.opts.debugging_opts.generate_arange_section { - add("-generate-arange-section"); + add("-generate-arange-section", false); } if get_major_version() >= 8 { match sess.opts.debugging_opts.merge_functions @@ -72,22 +90,22 @@ unsafe fn configure_llvm(sess: &Session) { MergeFunctions::Disabled | MergeFunctions::Trampolines => {} MergeFunctions::Aliases => { - add("-mergefunc-use-aliases"); + add("-mergefunc-use-aliases", false); } } } if sess.target.target.target_os == "emscripten" && sess.panic_strategy() == PanicStrategy::Unwind { - add("-enable-emscripten-cxx-exceptions"); + add("-enable-emscripten-cxx-exceptions", false); } // HACK(eddyb) LLVM inserts `llvm.assume` calls to preserve align attributes // during inlining. Unfortunately these may block other optimizations. - add("-preserve-alignment-assumptions-during-inlining=false"); + add("-preserve-alignment-assumptions-during-inlining=false", false); for arg in &sess.opts.cg.llvm_args { - add(&(*arg)); + add(&(*arg), true); } } diff --git a/src/librustc_codegen_ssa/debuginfo/type_names.rs b/src/librustc_codegen_ssa/debuginfo/type_names.rs index 8ff08e832dc17..c5340892daf0c 100644 --- a/src/librustc_codegen_ssa/debuginfo/type_names.rs +++ b/src/librustc_codegen_ssa/debuginfo/type_names.rs @@ -62,8 +62,8 @@ pub fn push_debuginfo_type_name<'tcx>( output.push('*'); } match mutbl { - hir::Mutability::Immutable => output.push_str("const "), - hir::Mutability::Mutable => output.push_str("mut "), + hir::Mutability::Not => output.push_str("const "), + hir::Mutability::Mut => output.push_str("mut "), } push_debuginfo_type_name(tcx, inner_type, true, output, visited); diff --git a/src/librustc_codegen_utils/symbol_names/v0.rs b/src/librustc_codegen_utils/symbol_names/v0.rs index 1dfcc21f3903d..858ad9f1cfda7 100644 --- a/src/librustc_codegen_utils/symbol_names/v0.rs +++ b/src/librustc_codegen_utils/symbol_names/v0.rs @@ -373,8 +373,8 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { ty::Ref(r, ty, mutbl) => { self.push(match mutbl { - hir::Mutability::Immutable => "R", - hir::Mutability::Mutable => "Q", + hir::Mutability::Not => "R", + hir::Mutability::Mut => "Q", }); if *r != ty::ReErased { self = r.print(self)?; @@ -384,8 +384,8 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { ty::RawPtr(mt) => { self.push(match mt.mutbl { - hir::Mutability::Immutable => "P", - hir::Mutability::Mutable => "O", + hir::Mutability::Not => "P", + hir::Mutability::Mut => "O", }); self = mt.ty.print(self)?; } diff --git a/src/librustc_error_codes/error_codes/E0120.md b/src/librustc_error_codes/error_codes/E0120.md index 99c2a493a46b9..dc7258d87317f 100644 --- a/src/librustc_error_codes/error_codes/E0120.md +++ b/src/librustc_error_codes/error_codes/E0120.md @@ -1,5 +1,7 @@ -An attempt was made to implement Drop on a trait, which is not allowed: only -structs and enums can implement Drop. An example causing this error: +Drop was implemented on a trait, which is not allowed: only structs and +enums can implement Drop. + +Erroneous code example: ```compile_fail,E0120 trait MyTrait {} @@ -10,7 +12,7 @@ impl Drop for MyTrait { ``` A workaround for this problem is to wrap the trait up in a struct, and implement -Drop on that. An example is shown below: +Drop on that: ``` trait MyTrait {} @@ -22,7 +24,7 @@ impl Drop for MyWrapper { ``` -Alternatively, wrapping trait objects requires something like the following: +Alternatively, wrapping trait objects requires something: ``` trait MyTrait {} diff --git a/src/librustc_error_codes/error_codes/E0121.md b/src/librustc_error_codes/error_codes/E0121.md index 069d0fc48fb0f..06fe396d50d3b 100644 --- a/src/librustc_error_codes/error_codes/E0121.md +++ b/src/librustc_error_codes/error_codes/E0121.md @@ -1,10 +1,24 @@ -In order to be consistent with Rust's lack of global type inference, -type and const placeholders are disallowed by design in item signatures. +The type placeholder `_` was used within a type on an item's signature. -Examples of this error include: +Erroneous code example: ```compile_fail,E0121 -fn foo() -> _ { 5 } // error, explicitly write out the return type instead +fn foo() -> _ { 5 } // error -static BAR: _ = "test"; // error, explicitly write out the type instead +static BAR: _ = "test"; // error +``` + +In those cases, you need to provide the type explicitly: + +``` +fn foo() -> i32 { 5 } // ok! + +static BAR: &str = "test"; // ok! +``` + +The type placeholder `_` can be used outside item's signature as follows: + +``` +let x = "a4a".split('4') + .collect::>(); // No need to precise the Vec's generic type. ``` diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 1fc89961889f1..4cf694631d0d3 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -887,8 +887,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { consider instead using an UnsafeCell"; match get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (&ty1.kind, &ty2.kind)) { Some((&ty::Ref(_, _, from_mt), &ty::Ref(_, _, to_mt))) => { - if to_mt == hir::Mutability::Mutable && - from_mt == hir::Mutability::Immutable { + if to_mt == hir::Mutability::Mut && + from_mt == hir::Mutability::Not { cx.span_lint(MUTABLE_TRANSMUTES, expr.span, msg); } } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index e6f39cca6dc3a..06ec3f3800915 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -392,7 +392,7 @@ impl UnusedParens { avoid_or: bool, avoid_mut: bool, ) { - use ast::{PatKind, BindingMode::ByValue, Mutability::Mutable}; + use ast::{PatKind, BindingMode, Mutability}; if let PatKind::Paren(inner) = &value.kind { match inner.kind { @@ -404,7 +404,7 @@ impl UnusedParens { // Avoid `p0 | .. | pn` if we should. PatKind::Or(..) if avoid_or => return, // Avoid `mut x` and `mut x @ p` if we should: - PatKind::Ident(ByValue(Mutable), ..) if avoid_mut => return, + PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ..) if avoid_mut => return, // Otherwise proceed with linting. _ => {} } @@ -560,7 +560,7 @@ impl EarlyLintPass for UnusedParens { Ident(.., Some(p)) | Box(p) => self.check_unused_parens_pat(cx, p, true, false), // Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342. // Also avoid linting on `& mut? (p0 | .. | pn)`, #64106. - Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Immutable), + Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not), } } @@ -668,9 +668,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAllocation { for adj in cx.tables.expr_adjustments(e) { if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(_, m)) = adj.kind { let msg = match m { - adjustment::AutoBorrowMutability::Immutable => + adjustment::AutoBorrowMutability::Not => "unnecessary allocation, use `&` instead", - adjustment::AutoBorrowMutability::Mutable { .. }=> + adjustment::AutoBorrowMutability::Mut { .. }=> "unnecessary allocation, use `&mut` instead" }; cx.span_lint(UNUSED_ALLOCATION, e.span, msg); diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index a1f95e35cbef2..eb2fb39fb2f25 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -1401,9 +1401,9 @@ impl<'a, 'tcx> CrateMetadata { fn static_mutability(&self, id: DefIndex) -> Option { match self.kind(id) { EntryKind::ImmStatic | - EntryKind::ForeignImmStatic => Some(hir::Mutability::Immutable), + EntryKind::ForeignImmStatic => Some(hir::Mutability::Not), EntryKind::MutStatic | - EntryKind::ForeignMutStatic => Some(hir::Mutability::Mutable), + EntryKind::ForeignMutStatic => Some(hir::Mutability::Mut), _ => None, } } diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index c1562a7734271..d963323342c33 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -1054,8 +1054,8 @@ impl EncodeContext<'tcx> { debug!("EncodeContext::encode_info_for_item({:?})", def_id); record!(self.per_def.kind[def_id] <- match item.kind { - hir::ItemKind::Static(_, hir::Mutability::Mutable, _) => EntryKind::MutStatic, - hir::ItemKind::Static(_, hir::Mutability::Immutable, _) => EntryKind::ImmStatic, + hir::ItemKind::Static(_, hir::Mutability::Mut, _) => EntryKind::MutStatic, + hir::ItemKind::Static(_, hir::Mutability::Not, _) => EntryKind::ImmStatic, hir::ItemKind::Const(_, body_id) => { let qualifs = self.tcx.at(item.span).mir_const_qualif(def_id); EntryKind::Const( @@ -1544,10 +1544,8 @@ impl EncodeContext<'tcx> { }; EntryKind::ForeignFn(self.lazy(data)) } - hir::ForeignItemKind::Static(_, hir::Mutability::Mutable) => - EntryKind::ForeignMutStatic, - hir::ForeignItemKind::Static(_, hir::Mutability::Immutable) => - EntryKind::ForeignImmStatic, + hir::ForeignItemKind::Static(_, hir::Mutability::Mut) => EntryKind::ForeignMutStatic, + hir::ForeignItemKind::Static(_, hir::Mutability::Not) => EntryKind::ForeignImmStatic, hir::ForeignItemKind::Type => EntryKind::ForeignType, }); record!(self.per_def.visibility[def_id] <- diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs index 016a3195c982d..38101c35dcc14 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs @@ -261,7 +261,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // we have an explicit self. Do the same thing in this case and check // for a `self: &mut Self` to suggest removing the `&mut`. if let ty::Ref( - _, _, hir::Mutability::Mutable + _, _, hir::Mutability::Mut ) = local_decl.ty.kind { true } else { @@ -578,7 +578,7 @@ fn suggest_ampmut<'tcx>( } let ty_mut = local_decl.ty.builtin_deref(true).unwrap(); - assert_eq!(ty_mut.mutbl, hir::Mutability::Immutable); + assert_eq!(ty_mut.mutbl, hir::Mutability::Not); (highlight_span, if local_decl.ty.is_region_ptr() { format!("&mut {}", ty_mut.ty) @@ -614,7 +614,7 @@ fn annotate_struct_field( // we can expect a field that is an immutable reference to a type. if let hir::Node::Field(field) = node { if let hir::TyKind::Rptr(lifetime, hir::MutTy { - mutbl: hir::Mutability::Immutable, + mutbl: hir::Mutability::Not, ref ty }) = field.ty.kind { // Get the snippets in two parts - the named lifetime (if there is one) and diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 2554d5e729da9..cd1e72e9d1701 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -160,7 +160,7 @@ fn do_mir_borrowck<'a, 'tcx>( }; let bm = *tables.pat_binding_modes().get(var_hir_id) .expect("missing binding mode"); - if bm == ty::BindByValue(hir::Mutability::Mutable) { + if bm == ty::BindByValue(hir::Mutability::Mut) { upvar.mutability = Mutability::Mut; } upvar @@ -2225,10 +2225,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ty::Ref(_, _, mutbl) => { match mutbl { // Shared borrowed data is never mutable - hir::Mutability::Immutable => Err(place), + hir::Mutability::Not => Err(place), // Mutably borrowed data is mutable, but only if we have a // unique path to the `&mut` - hir::Mutability::Mutable => { + hir::Mutability::Mut => { let mode = match self.is_upvar_field_projection(place) { Some(field) if self.upvars[field.index()].by_ref => @@ -2248,10 +2248,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ty::RawPtr(tnm) => { match tnm.mutbl { // `*const` raw pointers are not mutable - hir::Mutability::Immutable => Err(place), + hir::Mutability::Not => Err(place), // `*mut` raw pointers are always mutable, regardless of // context. The users have to check by themselves. - hir::Mutability::Mutable => { + hir::Mutability::Mut => { Ok(RootPlace { place_base: place.base, place_projection: place.projection, diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs index c62de2af55f44..e11db4ad5bb60 100644 --- a/src/librustc_mir/borrow_check/place_ext.rs +++ b/src/librustc_mir/borrow_check/place_ext.rs @@ -58,7 +58,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { if *elem == ProjectionElem::Deref { let ty = Place::ty_from(&self.base, proj_base, body, tcx).ty; match ty.kind { - ty::Ref(_, _, hir::Mutability::Immutable) if i == 0 => { + ty::Ref(_, _, hir::Mutability::Not) if i == 0 => { // For references to thread-local statics, we do need // to track the borrow. if body.local_decls[local].is_ref_to_thread_local() { @@ -66,7 +66,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { } return true; } - ty::RawPtr(..) | ty::Ref(_, _, hir::Mutability::Immutable) => { + ty::RawPtr(..) | ty::Ref(_, _, hir::Mutability::Not) => { // For both derefs of raw pointers and `&T` // references, the original path is `Copy` and // therefore not significant. In particular, diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index 9245064f87594..0cc7af330caad 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -246,13 +246,11 @@ fn place_components_conflict<'tcx>( debug!("borrow_conflicts_with_place: shallow access behind ptr"); return false; } - (ProjectionElem::Deref, ty::Ref(_, _, hir::Mutability::Immutable), _) => { + (ProjectionElem::Deref, ty::Ref(_, _, hir::Mutability::Not), _) => { // Shouldn't be tracked bug!("Tracking borrow behind shared reference."); } - (ProjectionElem::Deref, - ty::Ref(_, _, hir::Mutability::Mutable), - AccessDepth::Drop) => { + (ProjectionElem::Deref, ty::Ref(_, _, hir::Mutability::Mut), AccessDepth::Drop) => { // Values behind a mutable reference are not access either by dropping a // value, or by StorageDead debug!("borrow_conflicts_with_place: drop access behind ptr"); diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index 248faa56777de..5b9ce7cb5fd8d 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -149,7 +149,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> { ty::Ref( _, /*rgn*/ _, /*ty*/ - hir::Mutability::Immutable + hir::Mutability::Not ) => { // don't continue traversing over derefs of raw pointers or shared // borrows. @@ -160,7 +160,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> { ty::Ref( _, /*rgn*/ _, /*ty*/ - hir::Mutability::Mutable, + hir::Mutability::Mut, ) => { self.next = Some(PlaceRef { base: cursor.base, diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 108279eeef492..5613fd045ea50 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -2162,7 +2162,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let ty_from = match op.ty(*body, tcx).kind { ty::RawPtr(ty::TypeAndMut { ty: ty_from, - mutbl: hir::Mutability::Mutable, + mutbl: hir::Mutability::Mut, }) => ty_from, _ => { span_mirbug!( @@ -2177,7 +2177,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let ty_to = match ty.kind { ty::RawPtr(ty::TypeAndMut { ty: ty_to, - mutbl: hir::Mutability::Immutable, + mutbl: hir::Mutability::Not, }) => ty_to, _ => { span_mirbug!( @@ -2211,7 +2211,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let opt_ty_elem = match ty_from.kind { ty::RawPtr( - ty::TypeAndMut { mutbl: hir::Mutability::Immutable, ty: array_ty } + ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: array_ty } ) => { match array_ty.kind { ty::Array(ty_elem, _) => Some(ty_elem), @@ -2236,7 +2236,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let ty_to = match ty.kind { ty::RawPtr( - ty::TypeAndMut { mutbl: hir::Mutability::Immutable, ty: ty_to } + ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: ty_to } ) => { ty_to } @@ -2504,13 +2504,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { }); match mutbl { - hir::Mutability::Immutable => { + hir::Mutability::Not => { // Immutable reference. We don't need the base // to be valid for the entire lifetime of // the borrow. break; } - hir::Mutability::Mutable => { + hir::Mutability::Mut => { // Mutable reference. We *do* need the base // to be valid, because after the base becomes // invalid, someone else can use our mutable deref. diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 6b33e8433f673..608415408e35c 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -300,16 +300,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { mutability, arg, } => { - let address_of = match mutability { - hir::Mutability::Immutable => Rvalue::AddressOf( - Mutability::Not, - unpack!(block = this.as_read_only_place(block, arg)), - ), - hir::Mutability::Mutable => Rvalue::AddressOf( - Mutability::Mut, - unpack!(block = this.as_place(block, arg)), - ), + let place = match mutability { + hir::Mutability::Not => this.as_read_only_place(block, arg), + hir::Mutability::Mut => this.as_place(block, arg), }; + let address_of = Rvalue::AddressOf(mutability, unpack!(block = place)); this.cfg.push_assign(block, source_info, destination, address_of); block.unit() } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 0009eb45cc035..3479ad6749a90 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -821,7 +821,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { name = ident.name; if let Some(&bm) = hir_tables.pat_binding_modes().get(pat.hir_id) { - if bm == ty::BindByValue(hir::Mutability::Mutable) { + if bm == ty::BindByValue(hir::Mutability::Mut) { mutability = Mutability::Mut; } else { mutability = Mutability::Not; diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 6cbc25aa7356e..c05641fe8bf0a 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -812,13 +812,12 @@ impl ToBorrowKind for AutoBorrowMutability { fn to_borrow_kind(&self) -> BorrowKind { use rustc::ty::adjustment::AllowTwoPhase; match *self { - AutoBorrowMutability::Mutable { allow_two_phase_borrow } => + AutoBorrowMutability::Mut { allow_two_phase_borrow } => BorrowKind::Mut { allow_two_phase_borrow: match allow_two_phase_borrow { AllowTwoPhase::Yes => true, AllowTwoPhase::No => false }}, - AutoBorrowMutability::Immutable => - BorrowKind::Shared, + AutoBorrowMutability::Not => BorrowKind::Shared, } } } @@ -826,8 +825,8 @@ impl ToBorrowKind for AutoBorrowMutability { impl ToBorrowKind for hir::Mutability { fn to_borrow_kind(&self) -> BorrowKind { match *self { - hir::Mutability::Mutable => BorrowKind::Mut { allow_two_phase_borrow: false }, - hir::Mutability::Immutable => BorrowKind::Shared, + hir::Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false }, + hir::Mutability::Not => BorrowKind::Shared, } } } @@ -994,7 +993,7 @@ fn convert_var( let ref_closure_ty = cx.tcx.mk_ref(region, ty::TypeAndMut { ty: closure_ty, - mutbl: hir::Mutability::Immutable, + mutbl: hir::Mutability::Not, }); Expr { ty: closure_ty, @@ -1015,7 +1014,7 @@ fn convert_var( let ref_closure_ty = cx.tcx.mk_ref(region, ty::TypeAndMut { ty: closure_ty, - mutbl: hir::Mutability::Mutable, + mutbl: hir::Mutability::Mut, }); Expr { ty: closure_ty, diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 8156cfe7ab51d..28f0edadc89ca 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -269,7 +269,7 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_>, pat: &Pa pat.walk(|p| { if let hir::PatKind::Binding(_, _, ident, None) = p.kind { if let Some(&bm) = cx.tables.pat_binding_modes().get(p.hir_id) { - if bm != ty::BindByValue(hir::Mutability::Immutable) { + if bm != ty::BindByValue(hir::Mutability::Not) { // Nothing to check. return true; } diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 0086c3b0e103f..7f15b3de5efc0 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -598,14 +598,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let bm = *self.tables.pat_binding_modes().get(pat.hir_id) .expect("missing binding mode"); let (mutability, mode) = match bm { - ty::BindByValue(hir::Mutability::Mutable) => - (Mutability::Mut, BindingMode::ByValue), - ty::BindByValue(hir::Mutability::Immutable) => - (Mutability::Not, BindingMode::ByValue), - ty::BindByReference(hir::Mutability::Mutable) => + ty::BindByValue(mutbl) => (mutbl, BindingMode::ByValue), + ty::BindByReference(hir::Mutability::Mut) => (Mutability::Not, BindingMode::ByRef( BorrowKind::Mut { allow_two_phase_borrow: false })), - ty::BindByReference(hir::Mutability::Immutable) => + ty::BindByReference(hir::Mutability::Not) => (Mutability::Not, BindingMode::ByRef( BorrowKind::Shared)), }; diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index f9cb40ffe9446..e4698303afe99 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -115,11 +115,11 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>( // For statics, allocation mutability is the combination of the place mutability and // the type mutability. // The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere. - if mutability == Mutability::Immutable && frozen { - alloc.mutability = Mutability::Immutable; + if mutability == Mutability::Not && frozen { + alloc.mutability = Mutability::Not; } else { // Just making sure we are not "upgrading" an immutable allocation to mutable. - assert_eq!(alloc.mutability, Mutability::Mutable); + assert_eq!(alloc.mutability, Mutability::Mut); } } else { // We *could* be non-frozen at `ConstBase`, for constants like `Cell::new(0)`. @@ -127,10 +127,10 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>( // initial value was computed. // Constants are never mutable. assert_eq!( - mutability, Mutability::Immutable, + mutability, Mutability::Not, "Something went very wrong: mutability requested for a constant" ); - alloc.mutability = Mutability::Immutable; + alloc.mutability = Mutability::Not; }; // link the alloc id to the actual allocation let alloc = tcx.intern_const_alloc(alloc); @@ -179,7 +179,7 @@ for // We are crossing over an `UnsafeCell`, we can mutate again. This means that // References we encounter inside here are interned as pointing to mutable // allocations. - let old = std::mem::replace(&mut self.mutability, Mutability::Mutable); + let old = std::mem::replace(&mut self.mutability, Mutability::Mut); assert_ne!( self.mode, InternMode::Const, "UnsafeCells are not allowed behind references in constants. This should have \ @@ -210,7 +210,7 @@ for if let Ok(vtable) = mplace.meta.unwrap().to_ptr() { // explitly choose `Immutable` here, since vtables are immutable, even // if the reference of the fat pointer is mutable - self.intern_shallow(vtable.alloc_id, Mutability::Immutable, None)?; + self.intern_shallow(vtable.alloc_id, Mutability::Not, None)?; } } // Check if we have encountered this pointer+layout combination before. @@ -223,16 +223,16 @@ for // const qualification enforces it. We can lift it in the future. match (self.mode, mutability) { // immutable references are fine everywhere - (_, hir::Mutability::Immutable) => {}, + (_, hir::Mutability::Not) => {}, // all is "good and well" in the unsoundness of `static mut` // mutable references are ok in `static`. Either they are treated as immutable // because they are behind an immutable one, or they are behind an `UnsafeCell` // and thus ok. - (InternMode::Static, hir::Mutability::Mutable) => {}, + (InternMode::Static, hir::Mutability::Mut) => {}, // we statically prevent `&mut T` via `const_qualif` and double check this here - (InternMode::ConstBase, hir::Mutability::Mutable) | - (InternMode::Const, hir::Mutability::Mutable) => { + (InternMode::ConstBase, hir::Mutability::Mut) | + (InternMode::Const, hir::Mutability::Mut) => { match referenced_ty.kind { ty::Array(_, n) if n.eval_usize(self.ecx.tcx.tcx, self.ecx.param_env) == 0 => {} @@ -243,16 +243,14 @@ for }, } // Compute the mutability with which we'll start visiting the allocation. This is - // what gets changed when we encounter an `UnsafeCell` - let mutability = match (self.mutability, mutability) { - // The only way a mutable reference actually works as a mutable reference is - // by being in a `static mut` directly or behind another mutable reference. - // If there's an immutable reference or we are inside a static, then our - // mutable reference is equivalent to an immutable one. As an example: - // `&&mut Foo` is semantically equivalent to `&&Foo` - (Mutability::Mutable, hir::Mutability::Mutable) => Mutability::Mutable, - _ => Mutability::Immutable, - }; + // what gets changed when we encounter an `UnsafeCell`. + // + // The only way a mutable reference actually works as a mutable reference is + // by being in a `static mut` directly or behind another mutable reference. + // If there's an immutable reference or we are inside a static, then our + // mutable reference is equivalent to an immutable one. As an example: + // `&&mut Foo` is semantically equivalent to `&&Foo` + let mutability = self.mutability.and(mutability); // Recursing behind references changes the intern mode for constants in order to // cause assertions to trigger if we encounter any `UnsafeCell`s. let mode = match self.mode { @@ -282,11 +280,10 @@ pub fn intern_const_alloc_recursive>( ) -> InterpResult<'tcx> { let tcx = ecx.tcx; let (base_mutability, base_intern_mode) = match place_mut { - Some(hir::Mutability::Immutable) => (Mutability::Immutable, InternMode::Static), // `static mut` doesn't care about interior mutability, it's mutable anyway - Some(hir::Mutability::Mutable) => (Mutability::Mutable, InternMode::Static), + Some(mutbl) => (mutbl, InternMode::Static), // consts, promoteds. FIXME: what about array lengths, array initializers? - None => (Mutability::Immutable, InternMode::ConstBase), + None => (Mutability::Not, InternMode::ConstBase), }; // Type based interning. @@ -346,7 +343,7 @@ pub fn intern_const_alloc_recursive>( // We cannot have mutable memory inside a constant. // FIXME: ideally we would assert that they already are immutable, to double- // check our static checks. - alloc.mutability = Mutability::Immutable; + alloc.mutability = Mutability::Not; } let alloc = tcx.intern_const_alloc(alloc); tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc); diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 8f177ad122580..ba571043d3813 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -539,7 +539,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // Need to make a copy, even if `get_static_alloc` is able // to give us a cheap reference. let alloc = Self::get_static_alloc(memory_extra, tcx, id)?; - if alloc.mutability == Mutability::Immutable { + if alloc.mutability == Mutability::Not { throw_unsup!(ModifiedConstantMemory) } match M::STATIC_KIND { @@ -553,7 +553,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { Err(e) => Err(e), Ok(a) => { let a = &mut a.1; - if a.mutability == Mutability::Immutable { + if a.mutability == Mutability::Not { throw_unsup!(ModifiedConstantMemory) } Ok(a) @@ -643,7 +643,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> { - self.get_raw_mut(id)?.mutability = Mutability::Immutable; + self.get_raw_mut(id)?.mutability = Mutability::Not; Ok(()) } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 48e7193ec39d4..93ab7b9aab7fb 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -444,13 +444,27 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Field(field, _) => self.operand_field(base, field.index() as u64)?, Downcast(_, variant) => self.operand_downcast(base, variant)?, Deref => self.deref_operand(base)?.into(), - Subslice { .. } | ConstantIndex { .. } | Index(_) => if base.layout.is_zst() { + ConstantIndex { .. } | Index(_) if base.layout.is_zst() => { OpTy { op: Operand::Immediate(Scalar::zst().into()), // the actual index doesn't matter, so we just pick a convenient one like 0 layout: base.layout.field(self, 0)?, } - } else { + } + Subslice { from, to, from_end } if base.layout.is_zst() => { + let elem_ty = if let ty::Array(elem_ty, _) = base.layout.ty.kind { + elem_ty + } else { + bug!("slices shouldn't be zero-sized"); + }; + assert!(!from_end, "arrays shouldn't be subsliced from the end"); + + OpTy { + op: Operand::Immediate(Scalar::zst().into()), + layout: self.layout_of(self.tcx.mk_array(elem_ty, (to - from) as u64))?, + } + } + Subslice { .. } | ConstantIndex { .. } | Index(_) => { // The rest should only occur as mplace, we do not use Immediates for types // allowing such operations. This matches place_projection forcing an allocation. let mplace = base.assert_mem_place(); diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 42fbfeca3f05d..8923b167fdee8 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -455,7 +455,10 @@ where ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { let len = base.len(self)?; // also asserts that we have a type where this makes sense let actual_to = if from_end { - assert!(from <= len - to); + if from + to > len { + // This can only be reached in ConstProp and non-rustc-MIR. + throw_ub!(BoundsCheckFailed { len: len as u64, index: from as u64 + to as u64 }); + } len - to } else { to @@ -523,7 +526,11 @@ where from_end, } => { let n = base.len(self)?; - assert!(n >= min_length as u64); + if n < min_length as u64 { + // This can only be reached in ConstProp and non-rustc-MIR. + throw_ub!(BoundsCheckFailed { len: min_length as u64, index: n as u64 }); + } + assert!(offset < min_length); let index = if from_end { n - u64::from(offset) diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 47b08048f8389..a29748962181e 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -471,7 +471,7 @@ impl CloneShimBuilder<'tcx> { Mutability::Not, tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut { ty, - mutbl: hir::Mutability::Immutable, + mutbl: hir::Mutability::Not, }) ); @@ -757,7 +757,7 @@ fn build_call_shim<'tcx>( Mutability::Not, tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut { ty: sig.inputs()[0], - mutbl: hir::Mutability::Mutable + mutbl: hir::Mutability::Mut }), span )); diff --git a/src/librustc_mir/transform/check_consts/mod.rs b/src/librustc_mir/transform/check_consts/mod.rs index 89672e81c7cd4..e8365a9ee1c13 100644 --- a/src/librustc_mir/transform/check_consts/mod.rs +++ b/src/librustc_mir/transform/check_consts/mod.rs @@ -87,8 +87,8 @@ impl ConstKind { HirKind::Const => ConstKind::Const, - HirKind::Static(hir::Mutability::Immutable) => ConstKind::Static, - HirKind::Static(hir::Mutability::Mutable) => ConstKind::StaticMut, + HirKind::Static(hir::Mutability::Not) => ConstKind::Static, + HirKind::Static(hir::Mutability::Mut) => ConstKind::StaticMut, }; Some(mode) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 62aec1975c216..1a24a8b371d76 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -238,7 +238,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { ) -> InterpResult<'tcx> { // if the static allocation is mutable or if it has relocations (it may be legal to mutate // the memory behind that in the future), then we can't const prop it - if allocation.mutability == Mutability::Mutable || allocation.relocations().len() > 0 { + if allocation.mutability == Mutability::Mut || allocation.relocations().len() > 0 { throw_unsup!(ConstPropUnsupported("can't eval mutable statics in ConstProp")); } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 3d15d04717211..b314ff83abe6a 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -391,7 +391,7 @@ fn make_generator_state_argument_indirect<'tcx>( let ref_gen_ty = tcx.mk_ref(region, ty::TypeAndMut { ty: gen_ty, - mutbl: hir::Mutability::Mutable + mutbl: hir::Mutability::Mut }); // Replace the by value generator argument @@ -969,7 +969,7 @@ fn create_generator_drop_shim<'tcx>( mutability: Mutability::Mut, ty: tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, - mutbl: hir::Mutability::Mutable, + mutbl: hir::Mutability::Mut, }), user_ty: UserTypeProjections::none(), source_info, diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index a61bff37fc873..0d2e0bb8281e0 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -79,7 +79,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) - fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> McfResult { for ty in ty.walk() { match ty.kind { - ty::Ref(_, _, hir::Mutability::Mutable) => { + ty::Ref(_, _, hir::Mutability::Mut) => { if !feature_allowed(tcx, fn_def_id, sym::const_mut_refs) { return Err(( span, diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 4f482431d3323..6ff84996bd34a 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -521,7 +521,7 @@ where let ref_ty = tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut { ty, - mutbl: hir::Mutability::Mutable + mutbl: hir::Mutability::Mut }); let ref_place = self.new_temp(ref_ty); let unit_temp = Place::from(self.new_temp(tcx.mk_unit())); @@ -580,7 +580,7 @@ where let ptr_ty = tcx.mk_ptr(ty::TypeAndMut { ty: ety, - mutbl: hir::Mutability::Mutable + mutbl: hir::Mutability::Mut }); let ptr = &Place::from(self.new_temp(ptr_ty)); let can_go = Place::from(self.new_temp(tcx.types.bool)); diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 16daefd1450ab..353f6607c1db7 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -22,7 +22,7 @@ const TURBOFISH: &'static str = "use `::<...>` instead of `<...>` to specify typ pub(super) fn dummy_arg(ident: Ident) -> Param { let pat = P(Pat { id: ast::DUMMY_NODE_ID, - kind: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None), + kind: PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None), span: ident.span, }); let ty = Ty { diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 229ca07f13b51..271e5092018d9 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1239,8 +1239,8 @@ impl<'a> Parser<'a> { // Construct the error and stash it away with the hope // that typeck will later enrich the error with a type. let kind = match m { - Some(Mutability::Mutable) => "static mut", - Some(Mutability::Immutable) => "static", + Some(Mutability::Mut) => "static mut", + Some(Mutability::Not) => "static", None => "const", }; let mut err = self.struct_span_err(id.span, &format!("missing type for `{}` item", kind)); @@ -1960,7 +1960,7 @@ impl<'a> Parser<'a> { match ty { Ok(ty) => { let ident = Ident::new(kw::Invalid, self.prev_span); - let bm = BindingMode::ByValue(Mutability::Immutable); + let bm = BindingMode::ByValue(Mutability::Not); let pat = self.mk_pat_ident(ty.span, bm, ident); (pat, ty) } @@ -2032,7 +2032,7 @@ impl<'a> Parser<'a> { .span_label(span, msg) .emit(); - Ok((SelfKind::Value(Mutability::Immutable), expect_self_ident(this), this.prev_span)) + Ok((SelfKind::Value(Mutability::Not), expect_self_ident(this), this.prev_span)) }; // Parse optional `self` parameter of a method. @@ -2044,23 +2044,23 @@ impl<'a> Parser<'a> { let eself = if is_isolated_self(self, 1) { // `&self` self.bump(); - SelfKind::Region(None, Mutability::Immutable) + SelfKind::Region(None, Mutability::Not) } else if is_isolated_mut_self(self, 1) { // `&mut self` self.bump(); self.bump(); - SelfKind::Region(None, Mutability::Mutable) + SelfKind::Region(None, Mutability::Mut) } else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_self(self, 2) { // `&'lt self` self.bump(); let lt = self.expect_lifetime(); - SelfKind::Region(Some(lt), Mutability::Immutable) + SelfKind::Region(Some(lt), Mutability::Not) } else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_mut_self(self, 2) { // `&'lt mut self` self.bump(); let lt = self.expect_lifetime(); self.bump(); - SelfKind::Region(Some(lt), Mutability::Mutable) + SelfKind::Region(Some(lt), Mutability::Mut) } else { // `¬_self` return Ok(None); @@ -2083,12 +2083,12 @@ impl<'a> Parser<'a> { } // `self` and `self: TYPE` token::Ident(..) if is_isolated_self(self, 0) => { - parse_self_possibly_typed(self, Mutability::Immutable)? + parse_self_possibly_typed(self, Mutability::Not)? } // `mut self` and `mut self: TYPE` token::Ident(..) if is_isolated_mut_self(self, 0) => { self.bump(); - parse_self_possibly_typed(self, Mutability::Mutable)? + parse_self_possibly_typed(self, Mutability::Mut)? } _ => return Ok(None), }; diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 255e789b58ea9..16bc2e1a8d60e 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -974,18 +974,18 @@ impl<'a> Parser<'a> { /// Parses mutability (`mut` or nothing). fn parse_mutability(&mut self) -> Mutability { if self.eat_keyword(kw::Mut) { - Mutability::Mutable + Mutability::Mut } else { - Mutability::Immutable + Mutability::Not } } /// Possibly parses mutability (`const` or `mut`). fn parse_const_or_mut(&mut self) -> Option { if self.eat_keyword(kw::Mut) { - Some(Mutability::Mutable) + Some(Mutability::Mut) } else if self.eat_keyword(kw::Const) { - Some(Mutability::Immutable) + Some(Mutability::Not) } else { None } diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs index 593fb30bb752a..33cac1aaceeb0 100644 --- a/src/librustc_parse/parser/pat.rs +++ b/src/librustc_parse/parser/pat.rs @@ -325,7 +325,7 @@ impl<'a> Parser<'a> { // Parse `ident @ pat` // This can give false positives and parse nullary enums, // they are dealt with later in resolve. - self.parse_pat_ident(BindingMode::ByValue(Mutability::Immutable))? + self.parse_pat_ident(BindingMode::ByValue(Mutability::Not))? } else if self.is_start_of_pat_with_path() { // Parse pattern starting with a path let (qself, path) = if self.eat_lt() { @@ -539,7 +539,7 @@ impl<'a> Parser<'a> { ) .emit(); - self.parse_pat_ident(BindingMode::ByRef(Mutability::Mutable)) + self.parse_pat_ident(BindingMode::ByRef(Mutability::Mut)) } /// Turn all by-value immutable bindings in a pattern into mutable bindings. @@ -552,10 +552,10 @@ impl<'a> Parser<'a> { } fn visit_pat(&mut self, pat: &mut P) { - if let PatKind::Ident(BindingMode::ByValue(ref mut m @ Mutability::Immutable), ..) + if let PatKind::Ident(BindingMode::ByValue(ref mut m @ Mutability::Not), ..) = pat.kind { - *m = Mutability::Mutable; + *m = Mutability::Mut; self.0 = true; } noop_visit_pat(pat, self); @@ -986,10 +986,10 @@ impl<'a> Parser<'a> { hi = self.prev_span; let bind_type = match (is_ref, is_mut) { - (true, true) => BindingMode::ByRef(Mutability::Mutable), - (true, false) => BindingMode::ByRef(Mutability::Immutable), - (false, true) => BindingMode::ByValue(Mutability::Mutable), - (false, false) => BindingMode::ByValue(Mutability::Immutable), + (true, true) => BindingMode::ByRef(Mutability::Mut), + (true, false) => BindingMode::ByRef(Mutability::Not), + (false, true) => BindingMode::ByValue(Mutability::Mut), + (false, false) => BindingMode::ByValue(Mutability::Not), }; let fieldpat = self.mk_pat_ident(boxed_span.to(hi), bind_type, fieldname); diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 6f7ab0542d5fa..86692610324d4 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -261,7 +261,7 @@ impl<'a> Parser<'a> { .span_label(span, msg) .help("use `*mut T` or `*const T` as appropriate") .emit(); - Mutability::Immutable + Mutability::Not }); let t = self.parse_ty_no_plus()?; Ok(MutTy { ty: t, mutbl }) diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index e90231f984b1f..ee6a67802ade3 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -161,9 +161,9 @@ impl<'a> AstValidator<'a> { fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, bool)) { for Param { pat, .. } in &decl.inputs { match pat.kind { - PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), _, None) | + PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, None) | PatKind::Wild => {} - PatKind::Ident(BindingMode::ByValue(Mutability::Mutable), _, None) => + PatKind::Ident(BindingMode::ByValue(Mutability::Mut), _, None) => report_err(pat.span, true), _ => report_err(pat.span, false), } diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs index 725a742382e02..f7bdefcb0690b 100644 --- a/src/librustc_passes/check_const.rs +++ b/src/librustc_passes/check_const.rs @@ -81,8 +81,8 @@ impl ConstKind { let owner = hir_map.body_owner(body.id()); let const_kind = match hir_map.body_owner_kind(owner) { hir::BodyOwnerKind::Const => Self::Const, - hir::BodyOwnerKind::Static(Mutability::Mutable) => Self::StaticMut, - hir::BodyOwnerKind::Static(Mutability::Immutable) => Self::Static, + hir::BodyOwnerKind::Static(Mutability::Mut) => Self::StaticMut, + hir::BodyOwnerKind::Static(Mutability::Not) => Self::Static, hir::BodyOwnerKind::Fn if is_const_fn(owner) => Self::ConstFn, hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure => return None, diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 4321f62e03bc8..43ac85993344e 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -1472,7 +1472,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { // An immutable (no `mut`) by-value (no `ref`) binding pattern without // a sub pattern (no `@ $pat`) is syntactically ambiguous as it could // also be interpreted as a path to e.g. a constant, variant, etc. - let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Immutable); + let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Not); match res { Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 424d57c8fe7fa..0509748020a84 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -985,7 +985,7 @@ impl<'l> Visitor<'l> for PathCollector<'l> { // Even if the ref is mut, you can't change the ref, only // the data pointed at, so showing the initialising expression // is still worthwhile. - ast::BindingMode::ByRef(_) => ast::Mutability::Immutable, + ast::BindingMode::ByRef(_) => ast::Mutability::Not, ast::BindingMode::ByValue(mt) => mt, }; self.collected_idents diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 255938a193c97..d1ac0ac210e40 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -175,8 +175,8 @@ impl Sig for ast::Ty { } ast::TyKind::Ptr(ref mt) => { let prefix = match mt.mutbl { - ast::Mutability::Mutable => "*mut ", - ast::Mutability::Immutable => "*const ", + ast::Mutability::Mut => "*mut ", + ast::Mutability::Not => "*const ", }; let nested = mt.ty.make(offset + prefix.len(), id, scx)?; let text = format!("{}{}", prefix, nested.text); @@ -188,7 +188,7 @@ impl Sig for ast::Ty { prefix.push_str(&l.ident.to_string()); prefix.push(' '); } - if let ast::Mutability::Mutable = mt.mutbl { + if let ast::Mutability::Mut = mt.mutbl { prefix.push_str("mut "); }; @@ -330,7 +330,7 @@ impl Sig for ast::Item { match self.kind { ast::ItemKind::Static(ref ty, m, ref expr) => { let mut text = "static ".to_owned(); - if m == ast::Mutability::Mutable { + if m == ast::Mutability::Mut { text.push_str("mut "); } let name = self.ident.to_string(); @@ -787,7 +787,7 @@ impl Sig for ast::ForeignItem { } ast::ForeignItemKind::Static(ref ty, m) => { let mut text = "static ".to_owned(); - if m == ast::Mutability::Mutable { + if m == ast::Mutability::Mut { text.push_str("mut "); } let name = self.ident.to_string(); diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index 9ddc9c0d602af..2f2d03fc596e4 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -866,8 +866,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "extra arguments to prepend to the linker invocation (space separated)"), profile: bool = (false, parse_bool, [TRACKED], "insert profiling code"), - disable_instrumentation_preinliner: bool = (false, parse_bool, [TRACKED], - "Disable the instrumentation pre-inliner, useful for profiling / PGO."), relro_level: Option = (None, parse_relro_level, [TRACKED], "choose which RELRO level to use"), nll_facts: bool = (false, parse_bool, [UNTRACKED], diff --git a/src/librustc_traits/chalk_context/program_clauses/builtin.rs b/src/librustc_traits/chalk_context/program_clauses/builtin.rs index 3ad68d4a9dfa6..f281ac1762064 100644 --- a/src/librustc_traits/chalk_context/program_clauses/builtin.rs +++ b/src/librustc_traits/chalk_context/program_clauses/builtin.rs @@ -243,7 +243,7 @@ crate fn assemble_builtin_copy_clone_impls<'tcx>( ty::Float(..) | ty::RawPtr(..) | ty::Never | - ty::Ref(_, _, hir::Mutability::Immutable) => (), + ty::Ref(_, _, hir::Mutability::Not) => (), // Non parametric primitive types. ty::Infer(ty::IntVar(_)) | @@ -319,7 +319,7 @@ crate fn assemble_builtin_copy_clone_impls<'tcx>( ty::Generator(..) | ty::Str | ty::Slice(..) | - ty::Ref(_, _, hir::Mutability::Mutable) => (), + ty::Ref(_, _, hir::Mutability::Mut) => (), ty::Bound(..) | ty::GeneratorWitness(..) | diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 6b34159066a30..182c64e9069cd 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -430,8 +430,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let contains_ref_bindings = arms.iter() .filter_map(|a| a.pat.contains_explicit_ref_binding()) .max_by_key(|m| match *m { - hir::Mutability::Mutable => 1, - hir::Mutability::Immutable => 0, + hir::Mutability::Mut => 1, + hir::Mutability::Not => 0, }); if let Some(m) = contains_ref_bindings { diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 1b3af48ea83bf..db969486b8d16 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -217,8 +217,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if borrow { if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind { let mutbl = match mutbl { - hir::Mutability::Immutable => AutoBorrowMutability::Immutable, - hir::Mutability::Mutable => AutoBorrowMutability::Mutable { + hir::Mutability::Not => AutoBorrowMutability::Not, + hir::Mutability::Mut => AutoBorrowMutability::Mut { // For initial two-phase borrow // deployment, conservatively omit // overloaded function call ops. diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 21ba02746c79e..052364396953f 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -637,8 +637,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { ) -> Result { // array-ptr-cast. - if m_expr.mutbl == hir::Mutability::Immutable && - m_cast.mutbl == hir::Mutability::Immutable { + if m_expr.mutbl == hir::Mutability::Not && + m_cast.mutbl == hir::Mutability::Not { if let ty::Array(ety, _) = m_expr.ty.kind { // Due to the limitations of LLVM global constants, // region pointers end up pointing at copies of diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 726b3ba985778..e44b00d74bf0a 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -101,10 +101,10 @@ fn coerce_mutbls<'tcx>(from_mutbl: hir::Mutability, to_mutbl: hir::Mutability) -> RelateResult<'tcx, ()> { match (from_mutbl, to_mutbl) { - (hir::Mutability::Mutable, hir::Mutability::Mutable) | - (hir::Mutability::Immutable, hir::Mutability::Immutable) | - (hir::Mutability::Mutable, hir::Mutability::Immutable) => Ok(()), - (hir::Mutability::Immutable, hir::Mutability::Mutable) => Err(TypeError::Mutability), + (hir::Mutability::Mut, hir::Mutability::Mut) | + (hir::Mutability::Not, hir::Mutability::Not) | + (hir::Mutability::Mut, hir::Mutability::Not) => Ok(()), + (hir::Mutability::Not, hir::Mutability::Mut) => Err(TypeError::Mutability), } } @@ -412,7 +412,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } }; - if ty == a && mt_a.mutbl == hir::Mutability::Immutable && autoderef.step_count() == 1 { + if ty == a && mt_a.mutbl == hir::Mutability::Not && autoderef.step_count() == 1 { // As a special case, if we would produce `&'a *x`, that's // a total no-op. We end up with the type `&'a T` just as // we started with. In that case, just skip it @@ -424,7 +424,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // `self.x` both have `&mut `type would be a move of // `self.x`, but we auto-coerce it to `foo(&mut *self.x)`, // which is a borrow. - assert_eq!(mt_b.mutbl, hir::Mutability::Immutable); // can only coerce &T -> &U + assert_eq!(mt_b.mutbl, hir::Mutability::Not); // can only coerce &T -> &U return success(vec![], ty, obligations); } @@ -441,8 +441,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { _ => span_bug!(span, "expected a ref type, got {:?}", ty), }; let mutbl = match mt_b.mutbl { - hir::Mutability::Immutable => AutoBorrowMutability::Immutable, - hir::Mutability::Mutable => AutoBorrowMutability::Mutable { + hir::Mutability::Not => AutoBorrowMutability::Not, + hir::Mutability::Mut => AutoBorrowMutability::Mut { allow_two_phase_borrow: self.allow_two_phase, } }; @@ -487,8 +487,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let coercion = Coercion(self.cause.span); let r_borrow = self.next_region_var(coercion); let mutbl = match mutbl_b { - hir::Mutability::Immutable => AutoBorrowMutability::Immutable, - hir::Mutability::Mutable => AutoBorrowMutability::Mutable { + hir::Mutability::Not => AutoBorrowMutability::Not, + hir::Mutability::Mut => AutoBorrowMutability::Mut { // We don't allow two-phase borrows here, at least for initial // implementation. If it happens that this coercion is a function argument, // the reborrow in coerce_borrowed_ptr will pick it up. diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 4241422852291..ab8a4e5a9d053 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -534,8 +534,8 @@ fn compare_self_type<'tcx>( let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty).is_ok(); match ExplicitSelf::determine(self_arg_ty, can_eq_self) { ExplicitSelf::ByValue => "self".to_owned(), - ExplicitSelf::ByReference(_, hir::Mutability::Immutable) => "&self".to_owned(), - ExplicitSelf::ByReference(_, hir::Mutability::Mutable) => "&mut self".to_owned(), + ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(), + ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(), _ => format!("self: {}", self_arg_ty) } }) diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 16a55d2a4d318..6a78a4d733a94 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -436,10 +436,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // bar(&x); // error, expected &mut // ``` let ref_ty = match mutability { - hir::Mutability::Mutable => { + hir::Mutability::Mut => { self.tcx.mk_mut_ref(self.tcx.mk_region(ty::ReStatic), checked_ty) } - hir::Mutability::Immutable => { + hir::Mutability::Not => { self.tcx.mk_imm_ref(self.tcx.mk_region(ty::ReStatic), checked_ty) } }; @@ -489,7 +489,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { })) = self.tcx.hir().find( self.tcx.hir().get_parent_node(expr.hir_id), ) { - if mutability == hir::Mutability::Mutable { + if mutability == hir::Mutability::Mut { // Found the following case: // fn foo(opt: &mut Option){ opt = None } // --- ^^^^ @@ -508,12 +508,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } return Some(match mutability { - hir::Mutability::Mutable => ( + hir::Mutability::Mut => ( sp, "consider mutably borrowing here", format!("{}&mut {}", field_name, sugg_expr), ), - hir::Mutability::Immutable => ( + hir::Mutability::Not => ( sp, "consider borrowing here", format!("{}&{}", field_name, sugg_expr), diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index fba933ab0ce25..025bb05f63a4a 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -2,13 +2,15 @@ use crate::check::regionck::RegionCtxt; use crate::hir; use crate::hir::def_id::DefId; +use crate::util::common::ErrorReported; use rustc::infer::outlives::env::OutlivesEnvironment; use rustc::infer::{InferOk, SuppressRegionErrors}; use rustc::middle::region; use rustc::traits::{ObligationCause, TraitEngine, TraitEngineExt}; +use rustc::ty::error::TypeError; +use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc::ty::subst::{Subst, SubstsRef}; -use rustc::ty::{self, Ty, TyCtxt}; -use crate::util::common::ErrorReported; +use rustc::ty::{self, Predicate, Ty, TyCtxt}; use syntax_pos::Span; @@ -56,8 +58,10 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro // already checked by coherence, but compilation may // not have been terminated. let span = tcx.def_span(drop_impl_did); - tcx.sess.delay_span_bug(span, - &format!("should have been rejected by coherence check: {}", dtor_self_type)); + tcx.sess.delay_span_bug( + span, + &format!("should have been rejected by coherence check: {}", dtor_self_type), + ); Err(ErrorReported) } } @@ -85,10 +89,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( let fresh_impl_self_ty = drop_impl_ty.subst(tcx, fresh_impl_substs); let cause = &ObligationCause::misc(drop_impl_span, drop_impl_hir_id); - match infcx - .at(cause, impl_param_env) - .eq(named_type, fresh_impl_self_ty) - { + match infcx.at(cause, impl_param_env).eq(named_type, fresh_impl_self_ty) { Ok(InferOk { obligations, .. }) => { fulfillment_cx.register_predicate_obligations(infcx, obligations); } @@ -99,12 +100,13 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( drop_impl_span, E0366, "Implementations of Drop cannot be specialized" - ).span_note( + ) + .span_note( item_span, "Use same sequence of generic type and region \ parameters that is on the struct/enum definition", ) - .emit(); + .emit(); return Err(ErrorReported); } } @@ -194,6 +196,8 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( let assumptions_in_impl_context = generic_assumptions.instantiate(tcx, &self_to_impl_substs); let assumptions_in_impl_context = assumptions_in_impl_context.predicates; + let self_param_env = tcx.param_env(self_type_did); + // An earlier version of this code attempted to do this checking // via the traits::fulfill machinery. However, it ran into trouble // since the fulfill machinery merely turns outlives-predicates @@ -207,14 +211,35 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( // to take on a structure that is roughly an alpha-renaming of // the generic parameters of the item definition.) - // This path now just checks *all* predicates via the direct - // lookup, rather than using fulfill machinery. + // This path now just checks *all* predicates via an instantiation of + // the `SimpleEqRelation`, which simply forwards to the `relate` machinery + // after taking care of anonymizing late bound regions. // // However, it may be more efficient in the future to batch - // the analysis together via the fulfill , rather than the - // repeated `contains` calls. + // the analysis together via the fulfill (see comment above regarding + // the usage of the fulfill machinery), rather than the + // repeated `.iter().any(..)` calls. - if !assumptions_in_impl_context.contains(&predicate) { + // This closure is a more robust way to check `Predicate` equality + // than simple `==` checks (which were the previous implementation). + // It relies on `ty::relate` for `TraitPredicate` and `ProjectionPredicate` + // (which implement the Relate trait), while delegating on simple equality + // for the other `Predicate`. + // This implementation solves (Issue #59497) and (Issue #58311). + // It is unclear to me at the moment whether the approach based on `relate` + // could be extended easily also to the other `Predicate`. + let predicate_matches_closure = |p: &'_ Predicate<'tcx>| { + let mut relator: SimpleEqRelation<'tcx> = SimpleEqRelation::new(tcx, self_param_env); + match (predicate, p) { + (Predicate::Trait(a), Predicate::Trait(b)) => relator.relate(a, b).is_ok(), + (Predicate::Projection(a), Predicate::Projection(b)) => { + relator.relate(a, b).is_ok() + } + _ => predicate == p, + } + }; + + if !assumptions_in_impl_context.iter().any(predicate_matches_closure) { let item_span = tcx.hir().span(self_type_hir_id); struct_span_err!( tcx.sess, @@ -222,12 +247,13 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( E0367, "The requirement `{}` is added only by the Drop impl.", predicate - ).span_note( + ) + .span_note( item_span, "The same requirement must be part of \ the struct/enum definition", ) - .emit(); + .emit(); result = Err(ErrorReported); } } @@ -253,3 +279,99 @@ crate fn check_drop_obligations<'a, 'tcx>( Ok(()) } + +// This is an implementation of the TypeRelation trait with the +// aim of simply comparing for equality (without side-effects). +// It is not intended to be used anywhere else other than here. +crate struct SimpleEqRelation<'tcx> { + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, +} + +impl<'tcx> SimpleEqRelation<'tcx> { + fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> SimpleEqRelation<'tcx> { + SimpleEqRelation { tcx, param_env } + } +} + +impl TypeRelation<'tcx> for SimpleEqRelation<'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn param_env(&self) -> ty::ParamEnv<'tcx> { + self.param_env + } + + fn tag(&self) -> &'static str { + "dropck::SimpleEqRelation" + } + + fn a_is_expected(&self) -> bool { + true + } + + fn relate_with_variance>( + &mut self, + _: ty::Variance, + a: &T, + b: &T, + ) -> RelateResult<'tcx, T> { + // Here we ignore variance because we require drop impl's types + // to be *exactly* the same as to the ones in the struct definition. + self.relate(a, b) + } + + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + debug!("SimpleEqRelation::tys(a={:?}, b={:?})", a, b); + ty::relate::super_relate_tys(self, a, b) + } + + fn regions( + &mut self, + a: ty::Region<'tcx>, + b: ty::Region<'tcx>, + ) -> RelateResult<'tcx, ty::Region<'tcx>> { + debug!("SimpleEqRelation::regions(a={:?}, b={:?})", a, b); + + // We can just equate the regions because LBRs have been + // already anonymized. + if a == b { + Ok(a) + } else { + // I'm not sure is this `TypeError` is the right one, but + // it should not matter as it won't be checked (the dropck + // will emit its own, more informative and higher-level errors + // in case anything goes wrong). + Err(TypeError::RegionsPlaceholderMismatch) + } + } + + fn consts( + &mut self, + a: &'tcx ty::Const<'tcx>, + b: &'tcx ty::Const<'tcx>, + ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { + debug!("SimpleEqRelation::consts(a={:?}, b={:?})", a, b); + ty::relate::super_relate_consts(self, a, b) + } + + fn binders( + &mut self, + a: &ty::Binder, + b: &ty::Binder, + ) -> RelateResult<'tcx, ty::Binder> + where + T: Relate<'tcx>, + { + debug!("SimpleEqRelation::binders({:?}: {:?}", a, b); + + // Anonymizing the LBRs is necessary to solve (Issue #59497). + // After we do so, it should be totally fine to skip the binders. + let anon_a = self.tcx.anonymize_late_bound_regions(a); + let anon_b = self.tcx.anonymize_late_bound_regions(b); + self.relate(anon_a.skip_binder(), anon_b.skip_binder())?; + + Ok(a.clone()) + } +} diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 19441be87b959..17b168cfab05a 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -365,8 +365,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let method = self.register_infer_ok_obligations(ok); if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind { let mutbl = match mutbl { - hir::Mutability::Immutable => AutoBorrowMutability::Immutable, - hir::Mutability::Mutable => AutoBorrowMutability::Mutable { + hir::Mutability::Not => AutoBorrowMutability::Not, + hir::Mutability::Mut => AutoBorrowMutability::Mut { // (It shouldn't actually matter for unary ops whether // we enable two-phase borrows or not, since a unary // op has no additional operands.) diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index cec831147c44f..c5eb94e2165b8 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -165,7 +165,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) { "prefetch_read_instruction" | "prefetch_write_instruction" => { (1, vec![tcx.mk_ptr(ty::TypeAndMut { ty: param(0), - mutbl: hir::Mutability::Immutable + mutbl: hir::Mutability::Not }), tcx.types.i32], tcx.mk_unit()) } @@ -181,13 +181,13 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) { vec![ tcx.mk_ptr(ty::TypeAndMut { ty: param(0), - mutbl: hir::Mutability::Immutable + mutbl: hir::Mutability::Not }), tcx.types.isize ], tcx.mk_ptr(ty::TypeAndMut { ty: param(0), - mutbl: hir::Mutability::Immutable + mutbl: hir::Mutability::Not })) } "copy" | "copy_nonoverlapping" => { @@ -195,11 +195,11 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) { vec![ tcx.mk_ptr(ty::TypeAndMut { ty: param(0), - mutbl: hir::Mutability::Immutable + mutbl: hir::Mutability::Not }), tcx.mk_ptr(ty::TypeAndMut { ty: param(0), - mutbl: hir::Mutability::Mutable + mutbl: hir::Mutability::Mut }), tcx.types.usize, ], @@ -210,11 +210,11 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) { vec![ tcx.mk_ptr(ty::TypeAndMut { ty: param(0), - mutbl: hir::Mutability::Mutable + mutbl: hir::Mutability::Mut }), tcx.mk_ptr(ty::TypeAndMut { ty: param(0), - mutbl: hir::Mutability::Immutable + mutbl: hir::Mutability::Not }), tcx.types.usize, ], @@ -225,7 +225,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) { vec![ tcx.mk_ptr(ty::TypeAndMut { ty: param(0), - mutbl: hir::Mutability::Mutable + mutbl: hir::Mutability::Mut }), tcx.types.u8, tcx.types.usize, @@ -351,14 +351,14 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) { } "va_start" | "va_end" => { - match mk_va_list_ty(hir::Mutability::Mutable) { + match mk_va_list_ty(hir::Mutability::Mut) { Some((va_list_ref_ty, _)) => (0, vec![va_list_ref_ty], tcx.mk_unit()), None => bug!("`va_list` language item needed for C-variadic intrinsics") } } "va_copy" => { - match mk_va_list_ty(hir::Mutability::Immutable) { + match mk_va_list_ty(hir::Mutability::Not) { Some((va_list_ref_ty, va_list_ty)) => { let va_list_ptr_ty = tcx.mk_mut_ptr(va_list_ty); (0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.mk_unit()) @@ -368,7 +368,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) { } "va_arg" => { - match mk_va_list_ty(hir::Mutability::Mutable) { + match mk_va_list_ty(hir::Mutability::Mut) { Some((va_list_ref_ty, _)) => (1, vec![va_list_ref_ty], param(0)), None => bug!("`va_list` language item needed for C-variadic intrinsics") } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 4bdab84faf123..d04baf7dd077b 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -131,7 +131,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { sig: method_sig, }; - if let Some(hir::Mutability::Mutable) = pick.autoref { + if let Some(hir::Mutability::Mut) = pick.autoref { self.convert_place_derefs_to_mutable(); } @@ -172,8 +172,8 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { ty: target }); let mutbl = match mutbl { - hir::Mutability::Immutable => AutoBorrowMutability::Immutable, - hir::Mutability::Mutable => AutoBorrowMutability::Mutable { + hir::Mutability::Not => AutoBorrowMutability::Not, + hir::Mutability::Mut => AutoBorrowMutability::Mut { // Method call receivers are the primary use case // for two-phase borrows. allow_two_phase_borrow: AllowTwoPhase::Yes, @@ -554,8 +554,8 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { if let Adjust::Borrow(AutoBorrow::Ref(..)) = adjustment.kind { debug!("convert_place_op_to_mutable: converting autoref {:?}", adjustment); let mutbl = match mutbl { - hir::Mutability::Immutable => AutoBorrowMutability::Immutable, - hir::Mutability::Mutable => AutoBorrowMutability::Mutable { + hir::Mutability::Not => AutoBorrowMutability::Not, + hir::Mutability::Mut => AutoBorrowMutability::Mut { // For initial two-phase borrow // deployment, conservatively omit // overloaded operators. diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 880ead0e3018a..f797eec911bfd 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -608,11 +608,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let lang_def_id = lang_items.slice_u8_alloc_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Immutable }) => { + ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => { let lang_def_id = lang_items.const_ptr_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mutable }) => { + ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => { let lang_def_id = lang_items.mut_ptr_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } @@ -1047,8 +1047,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { span_bug!(self.span, "{:?} was applicable but now isn't?", step.self_ty) }); self.pick_by_value_method(step, self_ty).or_else(|| { - self.pick_autorefd_method(step, self_ty, hir::Mutability::Immutable).or_else(|| { - self.pick_autorefd_method(step, self_ty, hir::Mutability::Mutable) + self.pick_autorefd_method(step, self_ty, hir::Mutability::Not).or_else(|| { + self.pick_autorefd_method(step, self_ty, hir::Mutability::Mut) })})}) .next() } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7f1c6c99cf8d1..afd027e34380d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -397,8 +397,8 @@ pub enum Needs { impl Needs { fn maybe_mut_place(m: hir::Mutability) -> Self { match m { - hir::Mutability::Mutable => Needs::MutPlace, - hir::Mutability::Immutable => Needs::None, + hir::Mutability::Mut => Needs::MutPlace, + hir::Mutability::Not => Needs::None, } } } @@ -1436,7 +1436,7 @@ fn check_fn<'a, 'tcx>( ty::Ref(region, ty, mutbl) => match ty.kind { ty::Adt(ref adt, _) => { adt.did == panic_info_did && - mutbl == hir::Mutability::Immutable && + mutbl == hir::Mutability::Not && *region != RegionKind::ReStatic }, _ => false, @@ -3419,8 +3419,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut adjustments = autoderef.adjust_steps(self, needs); if let ty::Ref(region, _, r_mutbl) = method.sig.inputs()[0].kind { let mutbl = match r_mutbl { - hir::Mutability::Immutable => AutoBorrowMutability::Immutable, - hir::Mutability::Mutable => AutoBorrowMutability::Mutable { + hir::Mutability::Not => AutoBorrowMutability::Not, + hir::Mutability::Mut => AutoBorrowMutability::Mut { // Indexing can be desugared to a method call, // so maybe we could use two-phase here. // See the documentation of AllowTwoPhase for why that's diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 4f20a91e4b013..041a6c6f44c51 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -206,8 +206,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if is_assign == IsAssign::Yes || by_ref_binop { if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind { let mutbl = match mutbl { - hir::Mutability::Immutable => AutoBorrowMutability::Immutable, - hir::Mutability::Mutable => AutoBorrowMutability::Mutable { + hir::Mutability::Not => AutoBorrowMutability::Not, + hir::Mutability::Mut => AutoBorrowMutability::Mut { // Allow two-phase borrows for binops in initial deployment // since they desugar to methods allow_two_phase_borrow: AllowTwoPhase::Yes, @@ -223,8 +223,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if by_ref_binop { if let ty::Ref(region, _, mutbl) = method.sig.inputs()[1].kind { let mutbl = match mutbl { - hir::Mutability::Immutable => AutoBorrowMutability::Immutable, - hir::Mutability::Mutable => AutoBorrowMutability::Mutable { + hir::Mutability::Not => AutoBorrowMutability::Not, + hir::Mutability::Mut => AutoBorrowMutability::Mut { // Allow two-phase borrows for binops in initial deployment // since they desugar to methods allow_two_phase_borrow: AllowTwoPhase::Yes, diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 4fb57a6562574..11f744e97614c 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -32,7 +32,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn check_pat_top(&self, pat: &'tcx Pat, expected: Ty<'tcx>, discrim_span: Option) { - let def_bm = BindingMode::BindByValue(hir::Mutability::Immutable); + let def_bm = BindingMode::BindByValue(hir::Mutability::Not); self.check_pat(pat, expected, def_bm, discrim_span); } @@ -196,7 +196,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // See issue #46688. let def_bm = match pat.kind { - PatKind::Ref(..) => ty::BindByValue(hir::Mutability::Immutable), + PatKind::Ref(..) => ty::BindByValue(hir::Mutability::Not), _ => def_bm, }; (expected, def_bm) @@ -277,10 +277,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // (depending on whether we observe `&` or `&mut`). ty::BindByValue(_) | // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`). - ty::BindByReference(hir::Mutability::Mutable) => inner_mutability, + ty::BindByReference(hir::Mutability::Mut) => inner_mutability, // Once a `ref`, always a `ref`. // This is because a `& &mut` cannot mutate the underlying value. - ty::BindByReference(m @ hir::Mutability::Immutable) => m, + ty::BindByReference(m @ hir::Mutability::Not) => m, }); } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 8ceb21748520e..179c462f5e374 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -1255,7 +1255,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { // know whether this scenario has occurred; but I wanted to show // how all the types get adjusted.) match ref_mutability { - hir::Mutability::Immutable => { + hir::Mutability::Not => { // The reference being reborrowed is a shareable ref of // type `&'a T`. In this case, it doesn't matter where we // *found* the `&T` pointer, the memory it references will @@ -1263,7 +1263,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { true } - hir::Mutability::Mutable => { + hir::Mutability::Mut => { // The reference being reborrowed is either an `&mut T`. This is // the case where recursion is needed. false diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index c5a6c07297918..68cb0080b7d41 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -353,7 +353,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { // borrowed pointer implies that the // pointer itself must be unique, but not // necessarily *mutable* - ty::Ref(.., hir::Mutability::Mutable) => borrow_kind = ty::UniqueImmBorrow, + ty::Ref(.., hir::Mutability::Mut) => borrow_kind = ty::UniqueImmBorrow, _ => (), } } diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index d126a96014bc3..3797fcb1a6b4c 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -360,7 +360,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>, mt_b: ty::TypeAndMut<'tcx>, mk_ptr: &dyn Fn(Ty<'tcx>) -> Ty<'tcx>| { - if (mt_a.mutbl, mt_b.mutbl) == (hir::Mutability::Immutable, hir::Mutability::Mutable) { + if (mt_a.mutbl, mt_b.mutbl) == (hir::Mutability::Not, hir::Mutability::Mut) { infcx.report_mismatched_types(&cause, mk_ptr(mt_b.ty), target, diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index 1c228396b8cb7..2e2e56e6dcfed 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -109,7 +109,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { "[T]", item.span); } - ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Immutable }) => { + ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => { self.check_primitive_impl(def_id, lang_items.const_ptr_impl(), None, @@ -117,7 +117,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { "*const T", item.span); } - ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mutable }) => { + ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => { self.check_primitive_impl(def_id, lang_items.mut_ptr_impl(), None, diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 1e1be72221fcb..30558a0f5f679 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -454,12 +454,12 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { mt: &ty::TypeAndMut<'tcx>, variance: VarianceTermPtr<'a>) { match mt.mutbl { - hir::Mutability::Mutable => { + hir::Mutability::Mut => { let invar = self.invariant(variance); self.add_constraints_from_ty(current, mt.ty, invar); } - hir::Mutability::Immutable => { + hir::Mutability::Not => { self.add_constraints_from_ty(current, mt.ty, variance); } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e5f684cbca87b..cebfd99452ad4 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2101,8 +2101,8 @@ impl Clean for doctree::Constant<'_> { impl Clean for hir::Mutability { fn clean(&self, _: &DocContext<'_>) -> Mutability { match self { - &hir::Mutability::Mutable => Mutable, - &hir::Mutability::Immutable => Immutable, + &hir::Mutability::Mut => Mutable, + &hir::Mutability::Not => Immutable, } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index c1458236788cb..aa38a8135cecb 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -509,7 +509,7 @@ impl Pat { // In a type expression `_` is an inference variable. PatKind::Wild => TyKind::Infer, // An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`. - PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None) => { + PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None) => { TyKind::Path(None, Path::from_ident(*ident)) } PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()), @@ -695,30 +695,30 @@ pub enum PatKind { #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)] pub enum Mutability { - Mutable, - Immutable, + Mut, + Not, } impl Mutability { /// Returns `MutMutable` only if both `self` and `other` are mutable. pub fn and(self, other: Self) -> Self { match self { - Mutability::Mutable => other, - Mutability::Immutable => Mutability::Immutable, + Mutability::Mut => other, + Mutability::Not => Mutability::Not, } } pub fn invert(self) -> Self { match self { - Mutability::Mutable => Mutability::Immutable, - Mutability::Immutable => Mutability::Mutable, + Mutability::Mut => Mutability::Not, + Mutability::Not => Mutability::Mut, } } pub fn prefix_str(&self) -> &'static str { match self { - Mutability::Mutable => "mut ", - Mutability::Immutable => "", + Mutability::Mut => "mut ", + Mutability::Not => "", } } } @@ -2037,7 +2037,7 @@ impl Param { SelfKind::Explicit(ty, mutbl) => param(mutbl, ty), SelfKind::Value(mutbl) => param(mutbl, infer_ty), SelfKind::Region(lt, mutbl) => param( - Mutability::Immutable, + Mutability::Not, P(Ty { id: DUMMY_NODE_ID, kind: TyKind::Rptr( diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 87f6ae85b6970..e63d11ce83227 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1071,7 +1071,7 @@ impl<'a> State<'a> { } ast::ForeignItemKind::Static(ref t, m) => { self.head(visibility_qualified(&item.vis, "static")); - if m == ast::Mutability::Mutable { + if m == ast::Mutability::Mut { self.word_space("mut"); } self.print_ident(item.ident); @@ -1162,7 +1162,7 @@ impl<'a> State<'a> { } ast::ItemKind::Static(ref ty, m, ref expr) => { self.head(visibility_qualified(&item.vis, "static")); - if m == ast::Mutability::Mutable { + if m == ast::Mutability::Mut { self.word_space("mut"); } self.print_ident(item.ident); @@ -2302,8 +2302,8 @@ impl<'a> State<'a> { self.word_nbsp("ref"); self.print_mutability(mutbl, false); } - ast::BindingMode::ByValue(ast::Mutability::Immutable) => {} - ast::BindingMode::ByValue(ast::Mutability::Mutable) => { + ast::BindingMode::ByValue(ast::Mutability::Not) => {} + ast::BindingMode::ByValue(ast::Mutability::Mut) => { self.word_nbsp("mut"); } } @@ -2366,7 +2366,7 @@ impl<'a> State<'a> { } PatKind::Ref(ref inner, mutbl) => { self.s.word("&"); - if mutbl == ast::Mutability::Mutable { + if mutbl == ast::Mutability::Mut { self.s.word("mut "); } self.print_pat(inner); @@ -2667,8 +2667,8 @@ impl<'a> State<'a> { pub fn print_mutability(&mut self, mutbl: ast::Mutability, print_const: bool) { match mutbl { - ast::Mutability::Mutable => self.word_nbsp("mut"), - ast::Mutability::Immutable => if print_const { self.word_nbsp("const"); }, + ast::Mutability::Mut => self.word_nbsp("mut"), + ast::Mutability::Not => if print_const { self.word_nbsp("const"); }, } } diff --git a/src/libsyntax_expand/build.rs b/src/libsyntax_expand/build.rs index 4c539cad111a0..7c69be56beb81 100644 --- a/src/libsyntax_expand/build.rs +++ b/src/libsyntax_expand/build.rs @@ -178,7 +178,7 @@ impl<'a> ExtCtxt<'a> { pub fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident, ex: P) -> ast::Stmt { let pat = if mutbl { - let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Mutable); + let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Mut); self.pat_ident_binding_mode(sp, ident, binding_mode) } else { self.pat_ident(sp, ident) @@ -269,7 +269,7 @@ impl<'a> ExtCtxt<'a> { } pub fn expr_addr_of(&self, sp: Span, e: P) -> P { - self.expr(sp, ast::ExprKind::AddrOf(ast::BorrowKind::Ref, ast::Mutability::Immutable, e)) + self.expr(sp, ast::ExprKind::AddrOf(ast::BorrowKind::Ref, ast::Mutability::Not, e)) } pub fn expr_call( @@ -421,7 +421,7 @@ impl<'a> ExtCtxt<'a> { self.pat(span, PatKind::Lit(expr)) } pub fn pat_ident(&self, span: Span, ident: ast::Ident) -> P { - let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Immutable); + let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Not); self.pat_ident_binding_mode(span, ident, binding_mode) } diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index 132ce76e1bb6d..1b1a231f2d870 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -16,7 +16,7 @@ pub fn expand_deriving_debug(cx: &mut ExtCtxt<'_>, push: &mut dyn FnMut(Annotatable)) { // &mut ::std::fmt::Formatter let fmtr = Ptr(Box::new(Literal(path_std!(cx, fmt::Formatter))), - Borrowed(None, ast::Mutability::Mutable)); + Borrowed(None, ast::Mutability::Mut)); let trait_def = TraitDef { span, diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs index 3a0379a0eb02b..5cc5aebaba020 100644 --- a/src/libsyntax_ext/deriving/decodable.rs +++ b/src/libsyntax_ext/deriving/decodable.rs @@ -39,7 +39,7 @@ pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt<'_>, }, explicit_self: None, args: vec![(Ptr(Box::new(Literal(Path::new_local(typaram))), - Borrowed(None, Mutability::Mutable)), "d")], + Borrowed(None, Mutability::Mut)), "d")], ret_ty: Literal(Path::new_(pathvec_std!(cx, result::Result), None, diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index 2105946b666b2..99ee0f47d6d66 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -123,7 +123,7 @@ pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt<'_>, }, explicit_self: borrowed_explicit_self(), args: vec![(Ptr(Box::new(Literal(Path::new_local(typaram))), - Borrowed(None, Mutability::Mutable)), "s")], + Borrowed(None, Mutability::Mut)), "s")], ret_ty: Literal(Path::new_( pathvec_std!(cx, result::Result), None, diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 5158a5b3da217..5fecd13db9895 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -1017,7 +1017,7 @@ impl<'a> MethodDef<'a> { struct_path, struct_def, &format!("__self_{}", i), - ast::Mutability::Immutable, + ast::Mutability::Not, use_temporaries); patterns.push(pat); raw_fields.push(ident_expr); @@ -1227,8 +1227,8 @@ impl<'a> MethodDef<'a> { type_ident, variant, self_arg_name, - ast::Mutability::Immutable); - (cx.pat(sp, PatKind::Ref(p, ast::Mutability::Immutable)), idents) + ast::Mutability::Not); + (cx.pat(sp, PatKind::Ref(p, ast::Mutability::Not)), idents) }; // A single arm has form (&VariantK, &VariantK, ...) => BodyK @@ -1558,7 +1558,7 @@ impl<'a> TraitDef<'a> { field_paths.iter() .map(|path| { let binding_mode = if use_temporaries { - ast::BindingMode::ByValue(ast::Mutability::Immutable) + ast::BindingMode::ByValue(ast::Mutability::Not) } else { ast::BindingMode::ByRef(mutbl) }; diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs index 607746597a592..b7aa8874aad3d 100644 --- a/src/libsyntax_ext/deriving/generic/ty.rs +++ b/src/libsyntax_ext/deriving/generic/ty.rs @@ -108,7 +108,7 @@ pub enum Ty<'a> { } pub fn borrowed_ptrty() -> PtrTy { - Borrowed(None, ast::Mutability::Immutable) + Borrowed(None, ast::Mutability::Not) } pub fn borrowed(ty: Box>) -> Ty<'_> { Ptr(ty, borrowed_ptrty()) @@ -268,7 +268,7 @@ pub fn get_explicit_self(cx: &ExtCtxt<'_>, // this constructs a fresh `self` path let self_path = cx.expr_self(span); match *self_ptr { - None => (self_path, respan(span, SelfKind::Value(ast::Mutability::Immutable))), + None => (self_path, respan(span, SelfKind::Value(ast::Mutability::Not))), Some(ref ptr) => { let self_ty = respan(span, diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs index fe9ef78bb1b00..3ea8dcf46ec1b 100644 --- a/src/libsyntax_ext/deriving/hash.rs +++ b/src/libsyntax_ext/deriving/hash.rs @@ -35,7 +35,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt<'_>, }, explicit_self: borrowed_explicit_self(), args: vec![(Ptr(Box::new(Literal(arg)), - Borrowed(None, Mutability::Mutable)), "state")], + Borrowed(None, Mutability::Mut)), "state")], ret_ty: nil_ty(), attributes: vec![], is_unsafe: false, diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs index 6fb48bf81735b..1ea202f630b62 100644 --- a/src/libsyntax_ext/env.rs +++ b/src/libsyntax_ext/env.rs @@ -31,7 +31,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt<'_>, cx.ty_ident(sp, Ident::new(sym::str, sp)), Some(lt), - ast::Mutability::Immutable))], + ast::Mutability::Not))], )) } Ok(s) => { diff --git a/src/libsyntax_ext/global_allocator.rs b/src/libsyntax_ext/global_allocator.rs index dc29e057455d1..025d3e91c8166 100644 --- a/src/libsyntax_ext/global_allocator.rs +++ b/src/libsyntax_ext/global_allocator.rs @@ -180,6 +180,6 @@ impl AllocFnFactory<'_, '_> { fn ptr_u8(&self) -> P { let u8 = self.cx.path_ident(self.span, Ident::new(sym::u8, self.span)); let ty_u8 = self.cx.ty_path(u8); - self.cx.ty_ptr(self.span, ty_u8, Mutability::Mutable) + self.cx.ty_ptr(self.span, ty_u8, Mutability::Mut) } } diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs index 604400c3cc2ff..bcc38c8644a09 100644 --- a/src/libsyntax_ext/proc_macro_harness.rs +++ b/src/libsyntax_ext/proc_macro_harness.rs @@ -415,8 +415,8 @@ fn mk_decls( cx.ty(span, ast::TyKind::Slice( cx.ty_path(cx.path(span, vec![proc_macro, bridge, client, proc_macro_ty])))), - None, ast::Mutability::Immutable), - ast::Mutability::Immutable, + None, ast::Mutability::Not), + ast::Mutability::Not, cx.expr_vec_slice(span, decls), ).map(|mut i| { let attr = cx.meta_word(span, sym::rustc_proc_macro_decls); diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs index f19d13ff5c5c3..0c050e314133e 100644 --- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs @@ -141,7 +141,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P)) { 15 => { iter_exprs( depth - 1, - &mut |e| g(ExprKind::AddrOf(BorrowKind::Ref, Mutability::Immutable, e)), + &mut |e| g(ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, e)), ); }, 16 => { diff --git a/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs b/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs new file mode 100644 index 0000000000000..0e767d9613a99 --- /dev/null +++ b/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs @@ -0,0 +1,97 @@ +// Test that slice subslice patterns are correctly handled in const evaluation. + +// run-pass + +#![feature(slice_patterns, const_fn, const_if_match)] +#[derive(PartialEq, Debug, Clone)] +struct N(u8); + +#[derive(PartialEq, Debug, Clone)] +struct Z; + +macro_rules! n { + ($($e:expr),* $(,)?) => { + [$(N($e)),*] + } +} + +// This macro has an unused variable so that it can be repeated base on the +// number of times a repeated variable (`$e` in `z`) occurs. +macro_rules! zed { + ($e:expr) => { Z } +} + +macro_rules! z { + ($($e:expr),* $(,)?) => { + [$(zed!($e)),*] + } +} + +// Compare constant evaluation and runtime evaluation of a given expression. +macro_rules! compare_evaluation_inner { + ($e:expr, $t:ty $(,)?) => {{ + const CONST_EVAL: $t = $e; + const fn const_eval() -> $t { $e } + static CONST_EVAL2: $t = const_eval(); + let runtime_eval = $e; + assert_eq!(CONST_EVAL, runtime_eval); + assert_eq!(CONST_EVAL2, runtime_eval); + }} +} + +// Compare the result of matching `$e` against `$p` using both `if let` and +// `match`. +macro_rules! compare_evaluation { + ($p:pat, $e:expr, $matches:expr, $t:ty $(,)?) => {{ + compare_evaluation_inner!(if let $p = $e as &[_] { $matches } else { None }, $t); + compare_evaluation_inner!(match $e as &[_] { $p => $matches, _ => None }, $t); + }} +} + +// Repeat `$test`, substituting the given macro variables with the given +// identifiers. +// +// For example: +// +// repeat! { +// ($name); X; Y: +// struct $name; +// } +// +// Expands to: +// +// struct X; struct Y; +// +// This is used to repeat the tests using both the `N` and `Z` +// types. +macro_rules! repeat { + (($($dollar:tt $placeholder:ident)*); $($($values:ident),+);*: $($test:tt)*) => { + macro_rules! single { + ($($dollar $placeholder:ident),*) => { $($test)* } + } + $(single!($($values),+);)* + } +} + +fn main() { + repeat! { + ($arr $Ty); n, N; z, Z: + compare_evaluation!([_, x @ .., _], &$arr!(1, 2, 3, 4), Some(x), Option<&'static [$Ty]>); + compare_evaluation!([x, .., _], &$arr!(1, 2, 3, 4), Some(x), Option<&'static $Ty>); + compare_evaluation!([_, .., x], &$arr!(1, 2, 3, 4), Some(x), Option<&'static $Ty>); + + compare_evaluation!([_, x @ .., _], &$arr!(1, 2), Some(x), Option<&'static [$Ty]>); + compare_evaluation!([x, .., _], &$arr!(1, 2), Some(x), Option<&'static $Ty>); + compare_evaluation!([_, .., x], &$arr!(1, 2), Some(x), Option<&'static $Ty>); + + compare_evaluation!([_, x @ .., _], &$arr!(1), Some(x), Option<&'static [$Ty]>); + compare_evaluation!([x, .., _], &$arr!(1), Some(x), Option<&'static $Ty>); + compare_evaluation!([_, .., x], &$arr!(1), Some(x), Option<&'static $Ty>); + } + + compare_evaluation!([N(x), .., _], &n!(1, 2, 3, 4), Some(x), Option<&'static u8>); + compare_evaluation!([_, .., N(x)], &n!(1, 2, 3, 4), Some(x), Option<&'static u8>); + + compare_evaluation!([N(x), .., _], &n!(1, 2), Some(x), Option<&'static u8>); + compare_evaluation!([_, .., N(x)], &n!(1, 2), Some(x), Option<&'static u8>); +} diff --git a/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs b/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs new file mode 100644 index 0000000000000..5444f8a9051bd --- /dev/null +++ b/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs @@ -0,0 +1,97 @@ +// Test that array subslice patterns are correctly handled in const evaluation. + +// run-pass + +#![feature(slice_patterns)] + +#[derive(PartialEq, Debug, Clone)] +struct N(u8); + +#[derive(PartialEq, Debug, Clone)] +struct Z; + +macro_rules! n { + ($($e:expr),* $(,)?) => { + [$(N($e)),*] + } +} + +// This macro has an unused variable so that it can be repeated base on the +// number of times a repeated variable (`$e` in `z`) occurs. +macro_rules! zed { + ($e:expr) => { Z } +} + +macro_rules! z { + ($($e:expr),* $(,)?) => { + [$(zed!($e)),*] + } +} + +// Compare constant evaluation and runtime evaluation of a given expression. +macro_rules! compare_evaluation { + ($e:expr, $t:ty $(,)?) => {{ + const CONST_EVAL: $t = $e; + const fn const_eval() -> $t { $e } + static CONST_EVAL2: $t = const_eval(); + let runtime_eval = $e; + assert_eq!(CONST_EVAL, runtime_eval); + assert_eq!(CONST_EVAL2, runtime_eval); + }} +} + +// Repeat `$test`, substituting the given macro variables with the given +// identifiers. +// +// For example: +// +// repeat! { +// ($name); X; Y: +// struct $name; +// } +// +// Expands to: +// +// struct X; struct Y; +// +// This is used to repeat the tests using both the `N` and `Z` +// types. +macro_rules! repeat { + (($($dollar:tt $placeholder:ident)*); $($($values:ident),+);*: $($test:tt)*) => { + macro_rules! single { + ($($dollar $placeholder:ident),*) => { $($test)* } + } + $(single!($($values),+);)* + } +} + +fn main() { + repeat! { + ($arr $Ty); n, N; z, Z: + compare_evaluation!({ let [_, x @ .., _] = $arr!(1, 2, 3, 4); x }, [$Ty; 2]); + compare_evaluation!({ let [_, ref x @ .., _] = $arr!(1, 2, 3, 4); x }, &'static [$Ty; 2]); + compare_evaluation!({ let [_, x @ .., _] = &$arr!(1, 2, 3, 4); x }, &'static [$Ty; 2]); + + compare_evaluation!({ let [_, _, x @ .., _, _] = $arr!(1, 2, 3, 4); x }, [$Ty; 0]); + compare_evaluation!( + { let [_, _, ref x @ .., _, _] = $arr!(1, 2, 3, 4); x }, + &'static [$Ty; 0], + ); + compare_evaluation!( + { let [_, _, x @ .., _, _] = &$arr!(1, 2, 3, 4); x }, + &'static [$Ty; 0], + ); + + compare_evaluation!({ let [_, .., x] = $arr!(1, 2, 3, 4); x }, $Ty); + compare_evaluation!({ let [_, .., ref x] = $arr!(1, 2, 3, 4); x }, &'static $Ty); + compare_evaluation!({ let [_, _y @ .., x] = &$arr!(1, 2, 3, 4); x }, &'static $Ty); + } + + compare_evaluation!({ let [_, .., N(x)] = n!(1, 2, 3, 4); x }, u8); + compare_evaluation!({ let [_, .., N(ref x)] = n!(1, 2, 3, 4); x }, &'static u8); + compare_evaluation!({ let [_, .., N(x)] = &n!(1, 2, 3, 4); x }, &'static u8); + + compare_evaluation!({ let [N(x), .., _] = n!(1, 2, 3, 4); x }, u8); + compare_evaluation!({ let [N(ref x), .., _] = n!(1, 2, 3, 4); x }, &'static u8); + compare_evaluation!({ let [N(x), .., _] = &n!(1, 2, 3, 4); x }, &'static u8); +} diff --git a/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs b/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs new file mode 100644 index 0000000000000..a70ccb7aa4b73 --- /dev/null +++ b/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs @@ -0,0 +1,118 @@ +// Check that closure captures for slice patterns are inferred correctly + +#![feature(slice_patterns)] +#![allow(unused_variables)] + +// run-pass + +fn arr_by_ref(x: [String; 3]) { + let r = &x; + let f = || { + let [ref y, ref z @ ..] = x; + }; + f(); + f(); + // Ensure `x` was borrowed + drop(r); + // Ensure that `x` wasn't moved from. + drop(x); +} + +fn arr_by_mut(mut x: [String; 3]) { + let mut f = || { + let [ref mut y, ref mut z @ ..] = x; + }; + f(); + f(); + drop(x); +} + +fn arr_by_move(x: [String; 3]) { + let f = || { + let [y, z @ ..] = x; + }; + f(); +} + +fn arr_ref_by_ref(x: &[String; 3]) { + let r = &x; + let f = || { + let [ref y, ref z @ ..] = *x; + }; + let g = || { + let [y, z @ ..] = x; + }; + f(); + g(); + f(); + g(); + drop(r); + drop(x); +} + +fn arr_ref_by_mut(x: &mut [String; 3]) { + let mut f = || { + let [ref mut y, ref mut z @ ..] = *x; + }; + f(); + f(); + let mut g = || { + let [y, z @ ..] = x; + // Ensure binding mode was chosen correctly: + std::mem::swap(y, &mut z[0]); + }; + g(); + g(); + drop(x); +} + +fn arr_box_by_move(x: Box<[String; 3]>) { + let f = || { + let [y, z @ ..] = *x; + }; + f(); +} + +fn slice_by_ref(x: &[String]) { + let r = &x; + let f = || { + if let [ref y, ref z @ ..] = *x {} + }; + let g = || { + if let [y, z @ ..] = x {} + }; + f(); + g(); + f(); + g(); + drop(r); + drop(x); +} + +fn slice_by_mut(x: &mut [String]) { + let mut f = || { + if let [ref mut y, ref mut z @ ..] = *x {} + }; + f(); + f(); + let mut g = || { + if let [y, z @ ..] = x { + // Ensure binding mode was chosen correctly: + std::mem::swap(y, &mut z[0]); + } + }; + g(); + g(); + drop(x); +} + +fn main() { + arr_by_ref(Default::default()); + arr_by_mut(Default::default()); + arr_by_move(Default::default()); + arr_ref_by_ref(&Default::default()); + arr_ref_by_mut(&mut Default::default()); + arr_box_by_move(Default::default()); + slice_by_ref(&<[_; 3]>::default()); + slice_by_mut(&mut <[_; 3]>::default()); +} diff --git a/src/test/ui/borrowck/borrowck-closures-slice-patterns.rs b/src/test/ui/borrowck/borrowck-closures-slice-patterns.rs new file mode 100644 index 0000000000000..984eb8804b7a2 --- /dev/null +++ b/src/test/ui/borrowck/borrowck-closures-slice-patterns.rs @@ -0,0 +1,84 @@ +// Check that closure captures for slice patterns are inferred correctly + +#![feature(slice_patterns)] + +fn arr_by_ref(mut x: [String; 3]) { + let f = || { + let [ref y, ref z @ ..] = x; + }; + let r = &mut x; + //~^ ERROR cannot borrow + f(); +} + +fn arr_by_mut(mut x: [String; 3]) { + let mut f = || { + let [ref mut y, ref mut z @ ..] = x; + }; + let r = &x; + //~^ ERROR cannot borrow + f(); +} + +fn arr_by_move(x: [String; 3]) { + let f = || { + let [y, z @ ..] = x; + }; + &x; + //~^ ERROR borrow of moved value +} + +fn arr_ref_by_ref(x: &mut [String; 3]) { + let f = || { + let [ref y, ref z @ ..] = *x; + }; + let r = &mut *x; + //~^ ERROR cannot borrow + f(); +} + +fn arr_ref_by_uniq(x: &mut [String; 3]) { + let mut f = || { + let [ref mut y, ref mut z @ ..] = *x; + }; + let r = &x; + //~^ ERROR cannot borrow + f(); +} + +fn arr_box_by_move(x: Box<[String; 3]>) { + let f = || { + let [y, z @ ..] = *x; + }; + &x; + //~^ ERROR borrow of moved value +} + +fn slice_by_ref(x: &mut [String]) { + let f = || { + if let [ref y, ref z @ ..] = *x {} + }; + let r = &mut *x; + //~^ ERROR cannot borrow + f(); +} + +fn slice_by_uniq(x: &mut [String]) { + let mut f = || { + if let [ref mut y, ref mut z @ ..] = *x {} + }; + let r = &x; + //~^ ERROR cannot borrow + f(); +} + +fn main() { + arr_by_ref(Default::default()); + arr_by_mut(Default::default()); + arr_by_move(Default::default()); + arr_ref_by_ref(&mut Default::default()); + arr_ref_by_uniq(&mut Default::default()); + arr_box_by_move(Default::default()); + slice_by_ref(&mut <[_; 3]>::default()); + slice_by_uniq(&mut <[_; 3]>::default()); +} diff --git a/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr b/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr new file mode 100644 index 0000000000000..c5b27f5f8b403 --- /dev/null +++ b/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr @@ -0,0 +1,114 @@ +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-closures-slice-patterns.rs:9:13 + | +LL | let f = || { + | -- immutable borrow occurs here +LL | let [ref y, ref z @ ..] = x; + | - first borrow occurs due to use of `x` in closure +LL | }; +LL | let r = &mut x; + | ^^^^^^ mutable borrow occurs here +LL | +LL | f(); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-closures-slice-patterns.rs:18:13 + | +LL | let mut f = || { + | -- mutable borrow occurs here +LL | let [ref mut y, ref mut z @ ..] = x; + | - first borrow occurs due to use of `x` in closure +LL | }; +LL | let r = &x; + | ^^ immutable borrow occurs here +LL | +LL | f(); + | - mutable borrow later used here + +error[E0382]: borrow of moved value: `x` + --> $DIR/borrowck-closures-slice-patterns.rs:27:5 + | +LL | fn arr_by_move(x: [String; 3]) { + | - move occurs because `x` has type `[std::string::String; 3]`, which does not implement the `Copy` trait +LL | let f = || { + | -- value moved into closure here +LL | let [y, z @ ..] = x; + | - variable moved due to use in closure +LL | }; +LL | &x; + | ^^ value borrowed here after move + +error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-closures-slice-patterns.rs:35:13 + | +LL | let f = || { + | -- immutable borrow occurs here +LL | let [ref y, ref z @ ..] = *x; + | - first borrow occurs due to use of `x` in closure +LL | }; +LL | let r = &mut *x; + | ^^^^^^^ mutable borrow occurs here +LL | +LL | f(); + | - immutable borrow later used here + +error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access + --> $DIR/borrowck-closures-slice-patterns.rs:44:13 + | +LL | let mut f = || { + | -- closure construction occurs here +LL | let [ref mut y, ref mut z @ ..] = *x; + | - first borrow occurs due to use of `x` in closure +LL | }; +LL | let r = &x; + | ^^ second borrow occurs here +LL | +LL | f(); + | - first borrow later used here + +error[E0382]: borrow of moved value: `x` + --> $DIR/borrowck-closures-slice-patterns.rs:53:5 + | +LL | fn arr_box_by_move(x: Box<[String; 3]>) { + | - move occurs because `x` has type `std::boxed::Box<[std::string::String; 3]>`, which does not implement the `Copy` trait +LL | let f = || { + | -- value moved into closure here +LL | let [y, z @ ..] = *x; + | - variable moved due to use in closure +LL | }; +LL | &x; + | ^^ value borrowed here after move + +error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-closures-slice-patterns.rs:61:13 + | +LL | let f = || { + | -- immutable borrow occurs here +LL | if let [ref y, ref z @ ..] = *x {} + | - first borrow occurs due to use of `x` in closure +LL | }; +LL | let r = &mut *x; + | ^^^^^^^ mutable borrow occurs here +LL | +LL | f(); + | - immutable borrow later used here + +error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access + --> $DIR/borrowck-closures-slice-patterns.rs:70:13 + | +LL | let mut f = || { + | -- closure construction occurs here +LL | if let [ref mut y, ref mut z @ ..] = *x {} + | - first borrow occurs due to use of `x` in closure +LL | }; +LL | let r = &x; + | ^^ second borrow occurs here +LL | +LL | f(); + | - first borrow later used here + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0382, E0501, E0502. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/dropck/dropck_fn_type.rs b/src/test/ui/dropck/dropck_fn_type.rs new file mode 100644 index 0000000000000..2934217df346e --- /dev/null +++ b/src/test/ui/dropck/dropck_fn_type.rs @@ -0,0 +1,20 @@ +// run-pass +//! Regression test for #58311, regarding the usage of Fn types in drop impls + +// All of this Drop impls should compile. + +#[allow(dead_code)] +struct S [u8; 1]>(F); + +impl [u8; 1]> Drop for S { + fn drop(&mut self) {} +} + +#[allow(dead_code)] +struct P [A; 10]>(F); + +impl [A; 10]> Drop for P { + fn drop(&mut self) {} +} + +fn main() {} diff --git a/src/test/ui/dropck/dropck_traits.rs b/src/test/ui/dropck/dropck_traits.rs new file mode 100644 index 0000000000000..98e8e88a25995 --- /dev/null +++ b/src/test/ui/dropck/dropck_traits.rs @@ -0,0 +1,68 @@ +// run-pass +//! Regression test for #34426, regarding HRTB in drop impls + +// All of this Drop impls should compile. + +pub trait Lifetime<'a> {} +impl<'a> Lifetime<'a> for i32 {} + +#[allow(dead_code)] +struct Foo +where + for<'a> L: Lifetime<'a>, +{ + l: L, +} + +impl Drop for Foo +where + for<'a> L: Lifetime<'a>, +{ + fn drop(&mut self) {} +} + +#[allow(dead_code)] +struct Foo2 +where + for<'a> L: Lifetime<'a>, +{ + l: L, +} + +impl Lifetime<'a>> Drop for Foo2 +where + for<'x> T: Lifetime<'x>, +{ + fn drop(&mut self) {} +} + +pub trait Lifetime2<'a, 'b> {} +impl<'a, 'b> Lifetime2<'a, 'b> for i32 {} + +#[allow(dead_code)] +struct Bar +where + for<'a, 'b> L: Lifetime2<'a, 'b>, +{ + l: L, +} + +impl Drop for Bar +where + for<'a, 'b> L: Lifetime2<'a, 'b>, +{ + fn drop(&mut self) {} +} + +#[allow(dead_code)] +struct FnHolder Fn(&'a T, dyn for<'b> Lifetime2<'a, 'b>) -> u8>(T); + +impl Fn(&'a T, dyn for<'b> Lifetime2<'a, 'b>) -> u8> Drop for FnHolder { + fn drop(&mut self) {} +} + +fn main() { + let _foo = Foo { l: 0 }; + + let _bar = Bar { l: 0 }; +} diff --git a/src/test/ui/moves/move-out-of-array-ref.rs b/src/test/ui/moves/move-out-of-array-ref.rs new file mode 100644 index 0000000000000..4ca60ddfec27c --- /dev/null +++ b/src/test/ui/moves/move-out-of-array-ref.rs @@ -0,0 +1,36 @@ +// Ensure that we cannot move out of a reference to a fixed-size array + +#![feature(slice_patterns)] + +struct D { _x: u8 } + +impl Drop for D { fn drop(&mut self) { } } + +fn move_elem(a: &[D; 4]) -> D { + let [_, e, _, _] = *a; //~ ERROR cannot move + e +} + +fn move_subarr(a: &[D; 4]) -> [D; 2] { + let [_, s @ .. , _] = *a; //~ ERROR cannot move + s +} + +fn move_elem_mut(a: &mut [D; 4]) -> D { + let [_, e, _, _] = *a; //~ ERROR cannot move + e +} + +fn move_subarr_mut(a: &mut [D; 4]) -> [D; 2] { + let [_, s @ .. , _] = *a; //~ ERROR cannot move + s +} + +fn main() { + fn d() -> D { D { _x: 0 } } + + move_elem(&[d(), d(), d(), d()]); + move_subarr(&[d(), d(), d(), d()]); + move_elem_mut(&mut [d(), d(), d(), d()]); + move_subarr_mut(&mut [d(), d(), d(), d()]); +} diff --git a/src/test/ui/moves/move-out-of-array-ref.stderr b/src/test/ui/moves/move-out-of-array-ref.stderr new file mode 100644 index 0000000000000..ae3d2f5f2826a --- /dev/null +++ b/src/test/ui/moves/move-out-of-array-ref.stderr @@ -0,0 +1,47 @@ +error[E0508]: cannot move out of type `[D; 4]`, a non-copy array + --> $DIR/move-out-of-array-ref.rs:10:24 + | +LL | let [_, e, _, _] = *a; + | - ^^ + | | | + | | cannot move out of here + | | help: consider borrowing here: `&*a` + | data moved here + | move occurs because `e` has type `D`, which does not implement the `Copy` trait + +error[E0508]: cannot move out of type `[D; 4]`, a non-copy array + --> $DIR/move-out-of-array-ref.rs:15:27 + | +LL | let [_, s @ .. , _] = *a; + | ------ ^^ + | | | + | | cannot move out of here + | | help: consider borrowing here: `&*a` + | data moved here + | move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait + +error[E0508]: cannot move out of type `[D; 4]`, a non-copy array + --> $DIR/move-out-of-array-ref.rs:20:24 + | +LL | let [_, e, _, _] = *a; + | - ^^ + | | | + | | cannot move out of here + | | help: consider borrowing here: `&*a` + | data moved here + | move occurs because `e` has type `D`, which does not implement the `Copy` trait + +error[E0508]: cannot move out of type `[D; 4]`, a non-copy array + --> $DIR/move-out-of-array-ref.rs:25:27 + | +LL | let [_, s @ .. , _] = *a; + | ------ ^^ + | | | + | | cannot move out of here + | | help: consider borrowing here: `&*a` + | data moved here + | move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0508`. diff --git a/src/test/ui/moves/move-out-of-slice-2.rs b/src/test/ui/moves/move-out-of-slice-2.rs new file mode 100644 index 0000000000000..e460246193e5b --- /dev/null +++ b/src/test/ui/moves/move-out-of-slice-2.rs @@ -0,0 +1,34 @@ +#![feature(slice_patterns, unsized_locals)] + +struct A; +#[derive(Clone, Copy)] +struct C; + +fn main() { + let a: Box<[A]> = Box::new([A]); + match *a { + //~^ ERROR cannot move out of type `[A]`, a non-copy slice + [a @ ..] => {}, + _ => {} + } + let b: Box<[A]> = Box::new([A, A, A]); + match *b { + //~^ ERROR cannot move out of type `[A]`, a non-copy slice + [_, _, b @ .., _] => {}, + _ => {} + } + + // `[C]` isn't `Copy`, even if `C` is. + let c: Box<[C]> = Box::new([C]); + match *c { + //~^ ERROR cannot move out of type `[C]`, a non-copy slice + [c @ ..] => {}, + _ => {} + } + let d: Box<[C]> = Box::new([C, C, C]); + match *d { + //~^ ERROR cannot move out of type `[C]`, a non-copy slice + [_, _, d @ .., _] => {}, + _ => {} + } +} diff --git a/src/test/ui/moves/move-out-of-slice-2.stderr b/src/test/ui/moves/move-out-of-slice-2.stderr new file mode 100644 index 0000000000000..058f34b24a3b6 --- /dev/null +++ b/src/test/ui/moves/move-out-of-slice-2.stderr @@ -0,0 +1,51 @@ +error[E0508]: cannot move out of type `[A]`, a non-copy slice + --> $DIR/move-out-of-slice-2.rs:9:11 + | +LL | match *a { + | ^^ cannot move out of here +LL | +LL | [a @ ..] => {}, + | ------ + | | + | data moved here + | move occurs because `a` has type `[A]`, which does not implement the `Copy` trait + +error[E0508]: cannot move out of type `[A]`, a non-copy slice + --> $DIR/move-out-of-slice-2.rs:15:11 + | +LL | match *b { + | ^^ cannot move out of here +LL | +LL | [_, _, b @ .., _] => {}, + | ------ + | | + | data moved here + | move occurs because `b` has type `[A]`, which does not implement the `Copy` trait + +error[E0508]: cannot move out of type `[C]`, a non-copy slice + --> $DIR/move-out-of-slice-2.rs:23:11 + | +LL | match *c { + | ^^ cannot move out of here +LL | +LL | [c @ ..] => {}, + | ------ + | | + | data moved here + | move occurs because `c` has type `[C]`, which does not implement the `Copy` trait + +error[E0508]: cannot move out of type `[C]`, a non-copy slice + --> $DIR/move-out-of-slice-2.rs:29:11 + | +LL | match *d { + | ^^ cannot move out of here +LL | +LL | [_, _, d @ .., _] => {}, + | ------ + | | + | data moved here + | move occurs because `d` has type `[C]`, which does not implement the `Copy` trait + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0508`.