diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index bb6041d7f3196..7cfc5385e2104 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -59,13 +59,13 @@ def v(*args): o("lld", "rust.lld", "build lld") o("lldb", "rust.lldb", "build lldb") o("missing-tools", "dist.missing-tools", "allow failures when building tools") -o("use-libcxx", "llvm.use_libcxx", "build LLVM with libc++") +o("use-libcxx", "llvm.use-libcxx", "build LLVM with libc++") o("cflags", "llvm.cflags", "build LLVM with these extra compiler flags") o("cxxflags", "llvm.cxxflags", "build LLVM with these extra compiler flags") o("ldflags", "llvm.ldflags", "build LLVM with these extra linker flags") -o("llvm-libunwind", "rust.llvm_libunwind", "use LLVM libunwind") +o("llvm-libunwind", "rust.llvm-libunwind", "use LLVM libunwind") # Optimization and debugging options. These may be overridden by the release # channel, etc. diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index c086bf2cf402a..f3b2a73d3c5dc 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -4,10 +4,10 @@ //! our CI. use std::env; -//use std::ffi::OsString; +use std::ffi::OsString; use std::fmt; use std::fs; -//use std::iter; +use std::iter; use std::path::{Path, PathBuf}; use std::process::Command; @@ -204,8 +204,8 @@ impl Step for Cargo { } /// Runs `cargo test` for `cargo` packaged with Rust. - fn run(self, _builder: &Builder<'_>) { - /*let compiler = builder.compiler(self.stage, self.host); + fn run(self, builder: &Builder<'_>) { + let compiler = builder.compiler(self.stage, self.host); builder.ensure(tool::Cargo { compiler, @@ -235,7 +235,7 @@ impl Step for Cargo { cargo.env("PATH", &path_for_cargo(builder, compiler)); - try_run(builder, &mut cargo.into());*/ + try_run(builder, &mut cargo.into()); } } @@ -590,14 +590,14 @@ impl Step for Clippy { } } -//fn path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString { -// // Configure PATH to find the right rustc. NB. we have to use PATH -// // and not RUSTC because the Cargo test suite has tests that will -// // fail if rustc is not spelled `rustc`. -// let path = builder.sysroot(compiler).join("bin"); -// let old_path = env::var_os("PATH").unwrap_or_default(); -// env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("") -//} +fn path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString { + // Configure PATH to find the right rustc. NB. we have to use PATH + // and not RUSTC because the Cargo test suite has tests that will + // fail if rustc is not spelled `rustc`. + let path = builder.sysroot(compiler).join("bin"); + let old_path = env::var_os("PATH").unwrap_or_default(); + env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("") +} #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct RustdocTheme { diff --git a/src/ci/run.sh b/src/ci/run.sh index 4afd61bf8a7ba..73c3a964f5396 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -37,8 +37,6 @@ if [ "$DIST_SRC" = "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-dist-src" fi -RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.parallel-compiler" - # If we're deploying artifacts then we set the release channel, otherwise if # we're not deploying then we want to be sure to enable all assertions because # we'll be running tests @@ -46,8 +44,13 @@ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.parallel-compiler" # FIXME: need a scheme for changing this `nightly` value to `beta` and `stable` # either automatically or manually. export RUST_RELEASE_CHANNEL=nightly + +# Always set the release channel for bootstrap; this is normally not important (i.e., only dist +# builds would seem to matter) but in practice bootstrap wants to know whether we're targeting +# master, beta, or stable with a build to determine whether to run some checks (notably toolstate). +RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL" + if [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then - RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.remap-debuginfo" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --debuginfo-level-std=1" @@ -55,6 +58,9 @@ if [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then if [ "$NO_LLVM_ASSERTIONS" = "1" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions" elif [ "$DEPLOY_ALT" != "" ]; then + if [ "$NO_PARALLEL_COMPILER" = "" ]; then + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.parallel-compiler" + fi RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-assertions" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.verify-llvm-ir" fi diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index e6e3454b36f81..dcdd26634de46 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -165,6 +165,62 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { self } + /// Marks the struct as non-exhaustive, indicating to the reader that there are some other + /// fields that are not shown in the debug representation. + /// + /// # Examples + /// + /// ``` + /// # #![feature(debug_non_exhaustive)] + /// use std::fmt; + /// + /// struct Bar { + /// bar: i32, + /// hidden: f32, + /// } + /// + /// impl fmt::Debug for Bar { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_struct("Bar") + /// .field("bar", &self.bar) + /// .finish_non_exhaustive() // Show that some other field(s) exist. + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Bar { bar: 10, hidden: 1.0 }), + /// "Bar { bar: 10, .. }", + /// ); + /// ``` + #[unstable(feature = "debug_non_exhaustive", issue = "67364")] + pub fn finish_non_exhaustive(&mut self) -> fmt::Result { + self.result = self.result.and_then(|_| { + // Draw non-exhaustive dots (`..`), and open brace if necessary (no fields). + if self.is_pretty() { + if !self.has_fields { + self.fmt.write_str(" {\n")?; + } + let mut slot = None; + let mut state = Default::default(); + let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut state); + writer.write_str("..\n")?; + } else { + if self.has_fields { + self.fmt.write_str(", ..")?; + } else { + self.fmt.write_str(" { ..")?; + } + } + if self.is_pretty() { + self.fmt.write_str("}")? + } else { + self.fmt.write_str(" }")?; + } + Ok(()) + }); + self.result + } + /// Finishes output and returns any error encountered. /// /// # Examples @@ -194,15 +250,16 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn finish(&mut self) -> fmt::Result { - if self.has_fields { - self.result = self.result.and_then(|_| { + self.result = self.result.and_then(|_| { + if self.has_fields { if self.is_pretty() { - self.fmt.write_str("}") + self.fmt.write_str("}")? } else { - self.fmt.write_str(" }") + self.fmt.write_str(" }")?; } - }); - } + } + Ok(()) + }); self.result } diff --git a/src/libcore/tests/fmt/builders.rs b/src/libcore/tests/fmt/builders.rs index 255724432816d..8f426abe43ffa 100644 --- a/src/libcore/tests/fmt/builders.rs +++ b/src/libcore/tests/fmt/builders.rs @@ -93,6 +93,89 @@ mod debug_struct { }", format!("{:#?}", Bar)); } + + #[test] + fn test_only_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_struct("Foo") + .finish_non_exhaustive() + } + } + + + assert_eq!("Foo { .. }", format!("{:?}", Foo)); + assert_eq!( +"Foo { + .. +}", + format!("{:#?}", Foo)); + } + + #[test] + fn test_multiple_and_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_struct("Foo") + .field("bar", &true) + .field("baz", &format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + assert_eq!("Foo { bar: true, baz: 10/20, .. }", format!("{:?}", Foo)); + assert_eq!( +"Foo { + bar: true, + baz: 10/20, + .. +}", + format!("{:#?}", Foo)); + } + + #[test] + fn test_nested_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_struct("Foo") + .field("bar", &true) + .field("baz", &format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + struct Bar; + + impl fmt::Debug for Bar { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_struct("Bar") + .field("foo", &Foo) + .field("hello", &"world") + .finish_non_exhaustive() + } + } + + assert_eq!("Bar { foo: Foo { bar: true, baz: 10/20, .. }, hello: \"world\", .. }", + format!("{:?}", Bar)); + assert_eq!( +"Bar { + foo: Foo { + bar: true, + baz: 10/20, + .. + }, + hello: \"world\", + .. +}", + format!("{:#?}", Bar)); + } + } mod debug_tuple { diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index b28ed2eaa0876..904c37fe54255 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -5,6 +5,7 @@ #![feature(core_private_bignum)] #![feature(core_private_diy_float)] #![feature(debug_map_key_value)] +#![feature(debug_non_exhaustive)] #![feature(dec2flt)] #![feature(exact_size_is_empty)] #![feature(fixed_size_array)] diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index aa7f4f2155dd1..d952bf7ab9e25 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -3,7 +3,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::vec::{Idx, IndexVec}; use smallvec::SmallVec; -use rustc_data_structures::sync::{Lrc, Lock, AtomicU32, AtomicUsize, Ordering}; +use rustc_data_structures::sync::{Lrc, Lock, AtomicU32, AtomicU64, Ordering}; use rustc_data_structures::sharded::{self, Sharded}; use std::sync::atomic::Ordering::SeqCst; use std::env; @@ -485,8 +485,8 @@ impl DepGraph { if cfg!(debug_assertions) { let current_dep_graph = &self.data.as_ref().unwrap().current; - Some((current_dep_graph.total_read_count.load(SeqCst) as u64, - current_dep_graph.total_duplicate_read_count.load(SeqCst) as u64)) + Some((current_dep_graph.total_read_count.load(SeqCst), + current_dep_graph.total_duplicate_read_count.load(SeqCst))) } else { None } @@ -970,8 +970,8 @@ pub(super) struct CurrentDepGraph { /// These are simple counters that are for profiling and /// debugging and only active with `debug_assertions`. - total_read_count: AtomicUsize, - total_duplicate_read_count: AtomicUsize, + total_read_count: AtomicU64, + total_duplicate_read_count: AtomicU64, } impl CurrentDepGraph { @@ -1012,8 +1012,8 @@ impl CurrentDepGraph { )), anon_id_seed: stable_hasher.finish(), forbidden_edge, - total_read_count: AtomicUsize::new(0), - total_duplicate_read_count: AtomicUsize::new(0), + total_read_count: AtomicU64::new(0), + total_duplicate_read_count: AtomicU64::new(0), } } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index ba8feb4ee739d..3b4adbaf78c74 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2060,6 +2060,11 @@ pub enum Rvalue<'tcx> { /// &x or &mut x Ref(Region<'tcx>, BorrowKind, Place<'tcx>), + /// Create a raw pointer to the given place + /// Can be generated by raw address of expressions (`&raw const x`), + /// or when casting a reference to a raw pointer. + AddressOf(Mutability, Place<'tcx>), + /// length of a [X] or [X;n] value Len(Place<'tcx>), @@ -2214,6 +2219,15 @@ impl<'tcx> Debug for Rvalue<'tcx> { write!(fmt, "&{}{}{:?}", region, kind_str, place) } + AddressOf(mutability, ref place) => { + let kind_str = match mutability { + Mutability::Mut => "mut", + Mutability::Not => "const", + }; + + write!(fmt, "&raw {} {:?}", kind_str, place) + } + Aggregate(ref kind, ref places) => { fn fmt_tuple(fmt: &mut Formatter<'_>, places: &[Operand<'_>]) -> fmt::Result { let mut tuple_fmt = fmt.debug_tuple(""); @@ -3085,6 +3099,9 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { Ref(region, bk, ref place) => { Ref(region.fold_with(folder), bk, place.fold_with(folder)) } + AddressOf(mutability, ref place) => { + AddressOf(mutability, place.fold_with(folder)) + } Len(ref place) => Len(place.fold_with(folder)), Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)), BinaryOp(op, ref rhs, ref lhs) => { @@ -3125,6 +3142,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { Use(ref op) => op.visit_with(visitor), Repeat(ref op, _) => op.visit_with(visitor), Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor), + AddressOf(_, ref place) => place.visit_with(visitor), Len(ref place) => place.visit_with(visitor), Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor), BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => { diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 445fa6ea8cab3..a24b1d863d644 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -172,6 +172,13 @@ impl<'tcx> Rvalue<'tcx> { } ) } + Rvalue::AddressOf(mutability, ref place) => { + let place_ty = place.ty(local_decls, tcx).ty; + tcx.mk_ptr(ty::TypeAndMut { + ty: place_ty, + mutbl: mutability.into(), + }) + } Rvalue::Len(..) => tcx.types.usize, Rvalue::Cast(.., ty) => ty, Rvalue::BinaryOp(op, ref lhs, ref rhs) => { diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 5d273fe85b6d2..fa96b51347d35 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -570,6 +570,18 @@ macro_rules! make_mir_visitor { self.visit_place(path, ctx, location); } + Rvalue::AddressOf(m, path) => { + let ctx = match m { + Mutability::Mut => PlaceContext::MutatingUse( + MutatingUseContext::AddressOf + ), + Mutability::Not => PlaceContext::NonMutatingUse( + NonMutatingUseContext::AddressOf + ), + }; + self.visit_place(path, ctx, location); + } + Rvalue::Len(path) => { self.visit_place( path, @@ -1031,6 +1043,8 @@ pub enum NonMutatingUseContext { ShallowBorrow, /// Unique borrow. UniqueBorrow, + /// AddressOf for *const pointer. + AddressOf, /// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place. /// For example, the projection `x.y` is not marked as a mutation in these cases: /// @@ -1054,6 +1068,8 @@ pub enum MutatingUseContext { Drop, /// Mutable borrow. Borrow, + /// AddressOf for *mut pointer. + AddressOf, /// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place. /// For example, the projection `x.y` is marked as a mutation in these cases: /// diff --git a/src/librustc/ty/cast.rs b/src/librustc/ty/cast.rs index bc12412312deb..fca53db1475a0 100644 --- a/src/librustc/ty/cast.rs +++ b/src/librustc/ty/cast.rs @@ -28,8 +28,6 @@ pub enum CastTy<'tcx> { FnPtr, /// Raw pointers Ptr(ty::TypeAndMut<'tcx>), - /// References - RPtr(ty::TypeAndMut<'tcx>), } /// Cast Kind. See RFC 401 (or librustc_typeck/check/cast.rs) @@ -63,7 +61,6 @@ impl<'tcx> CastTy<'tcx> { ty::Adt(d,_) if d.is_enum() && d.is_payloadfree() => Some(CastTy::Int(IntTy::CEnum)), ty::RawPtr(mt) => Some(CastTy::Ptr(mt)), - ty::Ref(_, ty, mutbl) => Some(CastTy::RPtr(ty::TypeAndMut { ty, mutbl })), ty::FnPtr(..) => Some(CastTy::FnPtr), _ => None, } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 78a31f4e54466..15bbfa7860fa7 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -212,6 +212,17 @@ pub enum AssocKind { Type } +impl AssocKind { + pub fn suggestion_descr(&self) -> &'static str { + match self { + ty::AssocKind::Method => "method call", + ty::AssocKind::Type | + ty::AssocKind::OpaqueTy => "associated type", + ty::AssocKind::Const => "associated constant", + } + } +} + impl AssocItem { pub fn def_kind(&self) -> DefKind { match self.kind { diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 6c627085b2ed8..7bcd981678640 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -340,10 +340,12 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> PlaceContext::MutatingUse(MutatingUseContext::Store) | PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) | PlaceContext::MutatingUse(MutatingUseContext::Borrow) | + PlaceContext::MutatingUse(MutatingUseContext::AddressOf) | PlaceContext::MutatingUse(MutatingUseContext::Projection) | PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) | PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) | PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => { self.not_ssa(local); } diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 5e13cabced000..5b21dfbdf1c69 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -448,7 +448,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let cx = self.cx; let tcx = self.cx.tcx(); - let result = match &place_ref { + let result = match place_ref { mir::PlaceRef { base: mir::PlaceBase::Local(index), projection: [], diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 488ae8dbf9036..3a8d782aa7308 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -7,7 +7,7 @@ use crate::MemFlags; use crate::common::{self, RealPredicate, IntPredicate}; use crate::traits::*; -use rustc::ty::{self, Ty, adjustment::{PointerCast}, Instance}; +use rustc::ty::{self, Ty, TyCtxt, adjustment::{PointerCast}, Instance}; use rustc::ty::cast::{CastTy, IntTy}; use rustc::ty::layout::{self, LayoutOf, HasTyCtxt}; use rustc::mir; @@ -342,8 +342,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } (CastTy::Ptr(_), CastTy::Ptr(_)) | - (CastTy::FnPtr, CastTy::Ptr(_)) | - (CastTy::RPtr(_), CastTy::Ptr(_)) => + (CastTy::FnPtr, CastTy::Ptr(_)) => bx.pointercast(llval, ll_t_out), (CastTy::Ptr(_), CastTy::Int(_)) | (CastTy::FnPtr, CastTy::Int(_)) => @@ -370,24 +369,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::Ref(_, bk, ref place) => { - let cg_place = self.codegen_place(&mut bx, &place.as_ref()); - - let ty = cg_place.layout.ty; + let mk_ref = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| tcx.mk_ref( + tcx.lifetimes.re_erased, + ty::TypeAndMut { ty, mutbl: bk.to_mutbl_lossy() } + ); + self.codegen_place_to_pointer(bx, place, mk_ref) + } - // Note: places are indirect, so storing the `llval` into the - // destination effectively creates a reference. - let val = if !bx.cx().type_has_metadata(ty) { - OperandValue::Immediate(cg_place.llval) - } else { - OperandValue::Pair(cg_place.llval, cg_place.llextra.unwrap()) - }; - (bx, OperandRef { - val, - layout: self.cx.layout_of(self.cx.tcx().mk_ref( - self.cx.tcx().lifetimes.re_erased, - ty::TypeAndMut { ty, mutbl: bk.to_mutbl_lossy() } - )), - }) + mir::Rvalue::AddressOf(mutability, ref place) => { + let mk_ptr = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| tcx.mk_ptr( + ty::TypeAndMut { ty, mutbl: mutability.into() } + ); + self.codegen_place_to_pointer(bx, place, mk_ptr) } mir::Rvalue::Len(ref place) => { @@ -543,6 +536,30 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cg_value.len(bx.cx()) } + /// Codegen an `Rvalue::AddressOf` or `Rvalue::Ref` + fn codegen_place_to_pointer( + &mut self, + mut bx: Bx, + place: &mir::Place<'tcx>, + mk_ptr_ty: impl FnOnce(TyCtxt<'tcx>, Ty<'tcx>) -> Ty<'tcx>, + ) -> (Bx, OperandRef<'tcx, Bx::Value>) { + let cg_place = self.codegen_place(&mut bx, &place.as_ref()); + + let ty = cg_place.layout.ty; + + // Note: places are indirect, so storing the `llval` into the + // destination effectively creates a reference. + let val = if !bx.cx().type_has_metadata(ty) { + OperandValue::Immediate(cg_place.llval) + } else { + OperandValue::Pair(cg_place.llval, cg_place.llextra.unwrap()) + }; + (bx, OperandRef { + val, + layout: self.cx.layout_of(mk_ptr_ty(self.cx.tcx(), ty)), + }) + } + pub fn codegen_scalar_binop( &mut self, bx: &mut Bx, @@ -699,6 +716,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>, span: Span) -> bool { match *rvalue { mir::Rvalue::Ref(..) | + mir::Rvalue::AddressOf(..) | mir::Rvalue::Len(..) | mir::Rvalue::Cast(..) | // (*) mir::Rvalue::BinaryOp(..) | diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 02611a36aaebc..fb541637e5f79 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -24,7 +24,6 @@ #![feature(integer_atomics)] #![feature(test)] #![feature(associated_type_bounds)] -#![feature(cfg_target_has_atomic)] #![cfg_attr(unix, feature(libc))] diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index c4aed0628ba42..6a19f52897e5d 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -317,9 +317,7 @@ cfg_if! { pub use parking_lot::MutexGuard as LockGuard; pub use parking_lot::MappedMutexGuard as MappedLockGuard; - pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32}; - #[cfg(target_has_atomic = "64")] - pub use std::sync::atomic::{AtomicU64}; + pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64}; pub use crossbeam_utils::atomic::AtomicCell; diff --git a/src/librustc_error_codes/error_codes/E0745.md b/src/librustc_error_codes/error_codes/E0745.md index 39bebdcd3750e..6595691ce786c 100644 --- a/src/librustc_error_codes/error_codes/E0745.md +++ b/src/librustc_error_codes/error_codes/E0745.md @@ -11,7 +11,7 @@ fn temp_address() { To avoid the error, first bind the temporary to a named local variable. -```ignore (not yet implemented) +``` # #![feature(raw_ref_op)] fn temp_address() { let val = 2; diff --git a/src/librustc_mir/borrow_check/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs index 58fac5512d9b6..d5b9aaf9511a1 100644 --- a/src/librustc_mir/borrow_check/invalidation.rs +++ b/src/librustc_mir/borrow_check/invalidation.rs @@ -3,7 +3,7 @@ use rustc::mir::visit::Visitor; use rustc::mir::{BasicBlock, Location, Body, Place, ReadOnlyBodyAndCache, Rvalue}; use rustc::mir::{Statement, StatementKind}; use rustc::mir::TerminatorKind; -use rustc::mir::{Operand, BorrowKind}; +use rustc::mir::{Operand, BorrowKind, Mutability}; use rustc_data_structures::graph::dominators::Dominators; use crate::dataflow::indexes::BorrowIndex; @@ -337,6 +337,22 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { ); } + Rvalue::AddressOf(mutability, ref place) => { + let access_kind = match mutability { + Mutability::Mut => (Deep, Write(WriteKind::MutableBorrow(BorrowKind::Mut { + allow_two_phase_borrow: false, + }))), + Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))), + }; + + self.access_place( + location, + place, + access_kind, + LocalMutationIsAllowed::No, + ); + } + Rvalue::Use(ref operand) | Rvalue::Repeat(ref operand, _) | Rvalue::UnaryOp(_ /*un_op*/, ref operand) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 11012ef2fc7ee..2554d5e729da9 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1233,6 +1233,31 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); } + + Rvalue::AddressOf(mutability, ref place) => { + let access_kind = match mutability { + Mutability::Mut => (Deep, Write(WriteKind::MutableBorrow(BorrowKind::Mut { + allow_two_phase_borrow: false, + }))), + Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))), + }; + + self.access_place( + location, + (place, span), + access_kind, + LocalMutationIsAllowed::No, + flow_state, + ); + + self.check_if_path_or_subpath_is_moved( + location, + InitializationRequiringAction::Borrow, + (place.as_ref(), span), + flow_state, + ); + } + Rvalue::Use(ref operand) | Rvalue::Repeat(ref operand, _) | Rvalue::UnaryOp(_ /*un_op*/, ref operand) diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 663536bc2b4b6..108279eeef492 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -2273,41 +2273,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_to = CastTy::from_ty(ty); match (cast_ty_from, cast_ty_to) { - (Some(CastTy::RPtr(ref_tm)), Some(CastTy::Ptr(ptr_tm))) => { - if let hir::Mutability::Mutable = ptr_tm.mutbl { - if let Err(terr) = self.eq_types( - ref_tm.ty, - ptr_tm.ty, - location.to_locations(), - ConstraintCategory::Cast, - ) { - span_mirbug!( - self, - rvalue, - "equating {:?} with {:?} yields {:?}", - ref_tm.ty, - ptr_tm.ty, - terr - ) - } - } else { - if let Err(terr) = self.sub_types( - ref_tm.ty, - ptr_tm.ty, - location.to_locations(), - ConstraintCategory::Cast, - ) { - span_mirbug!( - self, - rvalue, - "relating {:?} with {:?} yields {:?}", - ref_tm.ty, - ptr_tm.ty, - terr - ) - } - } - }, (None, _) | (_, None) | (_, Some(CastTy::FnPtr)) @@ -2320,7 +2285,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ty_from, ty, ), - _ => (), + (Some(CastTy::Int(_)), Some(CastTy::Int(_))) + | (Some(CastTy::Float), Some(CastTy::Int(_))) + | (Some(CastTy::Int(_)), Some(CastTy::Float)) + | (Some(CastTy::Float), Some(CastTy::Float)) + | (Some(CastTy::Ptr(_)), Some(CastTy::Int(_))) + | (Some(CastTy::FnPtr), Some(CastTy::Int(_))) + | (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) + | (Some(CastTy::Ptr(_)), Some(CastTy::Ptr(_))) + | (Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => (), } } } @@ -2371,7 +2344,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } - Rvalue::Use(..) + Rvalue::AddressOf(..) + | Rvalue::Use(..) | Rvalue::Len(..) | Rvalue::BinaryOp(..) | Rvalue::CheckedBinaryOp(..) @@ -2388,6 +2362,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Rvalue::Use(_) | Rvalue::Repeat(..) | Rvalue::Ref(..) + | Rvalue::AddressOf(..) | Rvalue::Len(..) | Rvalue::Cast(..) | Rvalue::BinaryOp(..) diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index ddacda72e1e65..15c7c92d7db51 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -276,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::Pointer { .. } | ExprKind::Repeat { .. } | ExprKind::Borrow { .. } + | ExprKind::AddressOf { .. } | ExprKind::Match { .. } | ExprKind::Loop { .. } | ExprKind::Block { .. } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 37eb0cc9d961e..24282a6617acf 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -276,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::NeverToAny { .. } | ExprKind::Use { .. } | ExprKind::Borrow { .. } + | ExprKind::AddressOf { .. } | ExprKind::Adt { .. } | ExprKind::Loop { .. } | ExprKind::LogicalOp { .. } diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir/build/expr/category.rs index 270a1a6447435..4d0039b2e8cec 100644 --- a/src/librustc_mir/build/expr/category.rs +++ b/src/librustc_mir/build/expr/category.rs @@ -49,6 +49,7 @@ impl Category { | ExprKind::Use { .. } | ExprKind::Adt { .. } | ExprKind::Borrow { .. } + | ExprKind::AddressOf { .. } | ExprKind::Call { .. } => Some(Category::Rvalue(RvalueFunc::Into)), ExprKind::Array { .. } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 07a44b190b20a..6b33e8433f673 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -3,6 +3,7 @@ use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::hair::*; +use rustc::hir; use rustc::mir::*; use rustc::ty::{self, CanonicalUserTypeAnnotation}; use rustc_data_structures::fx::FxHashMap; @@ -295,6 +296,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.cfg.push_assign(block, source_info, destination, borrow); block.unit() } + ExprKind::AddressOf { + 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)), + ), + }; + this.cfg.push_assign(block, source_info, destination, address_of); + block.unit() + } ExprKind::Adt { adt_def, variant_index, diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index fa0864e0de760..5522da6fbf085 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -335,6 +335,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { } } Rvalue::Ref(..) + | Rvalue::AddressOf(..) | Rvalue::Discriminant(..) | Rvalue::Len(..) | Rvalue::NullaryOp(NullOp::SizeOf, _) diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 8c852854be1f9..6cbc25aa7356e 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -137,8 +137,11 @@ fn apply_adjustment<'a, 'tcx>( arg: expr.to_ref(), } } - Adjust::Borrow(AutoBorrow::RawPtr(mutbl)) => { - raw_ref_shim(cx, expr.to_ref(), adjustment.target, mutbl, span, temp_lifetime) + Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => { + ExprKind::AddressOf { + mutability, + arg: expr.to_ref(), + } } }; @@ -262,17 +265,11 @@ fn make_mirror_unadjusted<'a, 'tcx>( } } - hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutbl, ref arg) => { - cx.tcx.sess - .struct_span_err( - expr.span, - "raw borrows are not yet implemented" - ) - .note("for more information, see https://github.com/rust-lang/rust/issues/64490") - .emit(); - - // Lower to an approximation to avoid further errors. - raw_ref_shim(cx, arg.to_ref(), expr_ty, mutbl, expr.span, temp_lifetime) + hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => { + ExprKind::AddressOf { + mutability, + arg: arg.to_ref(), + } } hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: &blk }, @@ -1082,67 +1079,6 @@ fn convert_var( } -/// Fake `&raw [mut|const] expr` using a borrow and a cast until `AddressOf` -/// exists in MIR. -fn raw_ref_shim<'tcx>( - cx: &mut Cx<'_, 'tcx>, - arg: ExprRef<'tcx>, - ty: Ty<'tcx>, - mutbl: hir::Mutability, - span: Span, - temp_lifetime: Option, -) -> ExprKind<'tcx> { - let arg_tm = if let ty::RawPtr(type_mutbl) = ty.kind { - type_mutbl - } else { - bug!("raw_ref_shim called with non-raw pointer type"); - }; - // Convert this to a suitable `&foo` and - // then an unsafe coercion. - let borrow_expr = Expr { - temp_lifetime, - ty: cx.tcx.mk_ref(cx.tcx.lifetimes.re_erased, arg_tm), - span, - kind: ExprKind::Borrow { - borrow_kind: mutbl.to_borrow_kind(), - arg, - }, - }; - let cast_expr = Expr { - temp_lifetime, - ty, - span, - kind: ExprKind::Cast { source: borrow_expr.to_ref() } - }; - - // To ensure that both implicit and explicit coercions are - // handled the same way, we insert an extra layer of indirection here. - // For explicit casts (e.g., 'foo as *const T'), the source of the 'Use' - // will be an ExprKind::Hair with the appropriate cast expression. Here, - // we make our Use source the generated Cast from the original coercion. - // - // In both cases, this outer 'Use' ensures that the inner 'Cast' is handled by - // as_operand, not by as_rvalue - causing the cast result to be stored in a temporary. - // Ordinary, this is identical to using the cast directly as an rvalue. However, if the - // source of the cast was previously borrowed as mutable, storing the cast in a - // temporary gives the source a chance to expire before the cast is used. For - // structs with a self-referential *mut ptr, this allows assignment to work as - // expected. - // - // For example, consider the type 'struct Foo { field: *mut Foo }', - // The method 'fn bar(&mut self) { self.field = self }' - // triggers a coercion from '&mut self' to '*mut self'. In order - // for the assignment to be valid, the implicit borrow - // of 'self' involved in the coercion needs to end before the local - // containing the '*mut T' is assigned to 'self.field' - otherwise, - // we end up trying to assign to 'self.field' while we have another mutable borrow - // active. - // - // We only need to worry about this kind of thing for coercions from refs to ptrs, - // since they get rid of a borrow implicitly. - ExprKind::Use { source: cast_expr.to_ref() } -} - fn bin_op(op: hir::BinOpKind) -> BinOp { match op { hir::BinOpKind::Add => BinOp::Add, diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 47644d9ba8372..46e0d2a17b32d 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -212,6 +212,11 @@ pub enum ExprKind<'tcx> { borrow_kind: BorrowKind, arg: ExprRef<'tcx>, }, + /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`. + AddressOf { + mutability: hir::Mutability, + arg: ExprRef<'tcx>, + }, Break { label: region::Scope, value: Option>, diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index 33ed69af6ba02..33cdf1b27f8db 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -248,7 +248,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { )?; } - Ref(_, _, ref place) => { + AddressOf(_, ref place) | Ref(_, _, ref place) => { let src = self.eval_place(place)?; let place = self.force_allocation(src)?; if place.layout.size.bytes() > 0 { diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index dc21c674eea2f..0e4fe3f7f4015 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -136,21 +136,9 @@ impl<'tcx> MirPass<'tcx> for AddRetag { // iterate backwards using indices. for i in (0..block_data.statements.len()).rev() { let (retag_kind, place) = match block_data.statements[i].kind { - // If we are casting *from* a reference, we may have to retag-as-raw. - StatementKind::Assign(box(ref place, Rvalue::Cast( - CastKind::Misc, - ref src, - dest_ty, - ))) => { - let src_ty = src.ty(&*local_decls, tcx); - if src_ty.is_region_ptr() { - // The only `Misc` casts on references are those creating raw pointers. - assert!(dest_ty.is_unsafe_ptr()); - (RetagKind::Raw, place.clone()) - } else { - // Some other cast, no retag - continue - } + // Retag-as-raw after escaping to a raw pointer. + StatementKind::Assign(box (ref place, Rvalue::AddressOf(..))) => { + (RetagKind::Raw, place.clone()) } // Assignments of reference or ptr type are the ones where we may have // to update tags. This includes `x = &[mut] ...` and hence diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index 3df60993d9ad5..e5f3003cd7110 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -224,6 +224,23 @@ impl NonConstOp for MutBorrow { } } +#[derive(Debug)] +pub struct MutAddressOf; +impl NonConstOp for MutAddressOf { + fn feature_gate(tcx: TyCtxt<'_>) -> Option { + Some(tcx.features().const_mut_refs) + } + + fn emit_error(&self, item: &Item<'_, '_>, span: Span) { + feature_err( + &item.tcx.sess.parse_sess, + sym::const_mut_refs, + span, + &format!("`&raw mut` is not allowed in {}s", item.const_kind()) + ).emit(); + } +} + #[derive(Debug)] pub struct MutDeref; impl NonConstOp for MutDeref { diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs index 223a5f8d605fc..28243bd71a228 100644 --- a/src/librustc_mir/transform/check_consts/qualifs.rs +++ b/src/librustc_mir/transform/check_consts/qualifs.rs @@ -151,17 +151,15 @@ pub trait Qualif { Self::in_operand(cx, per_local, lhs) || Self::in_operand(cx, per_local, rhs) } - Rvalue::Ref(_, _, ref place) => { + Rvalue::Ref(_, _, ref place) | Rvalue::AddressOf(_, ref place) => { // Special-case reborrows to be more like a copy of the reference. - if let &[ref proj_base @ .., elem] = place.projection.as_ref() { - if ProjectionElem::Deref == elem { - let base_ty = Place::ty_from(&place.base, proj_base, *cx.body, cx.tcx).ty; - if let ty::Ref(..) = base_ty.kind { - return Self::in_place(cx, per_local, PlaceRef { - base: &place.base, - projection: proj_base, - }); - } + if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() { + let base_ty = Place::ty_from(&place.base, proj_base, *cx.body, cx.tcx).ty; + if let ty::Ref(..) = base_ty.kind { + return Self::in_place(cx, per_local, PlaceRef { + base: &place.base, + projection: proj_base, + }); } } diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 6261315c711cd..0904264586c7c 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -276,6 +276,27 @@ impl Validator<'a, 'mir, 'tcx> { self.check_op_spanned(ops::StaticAccess, span) } } + + fn check_immutable_borrow_like( + &mut self, + location: Location, + place: &Place<'tcx>, + ) { + // FIXME: Change the `in_*` methods to take a `FnMut` so we don't have to manually + // seek the cursors beforehand. + self.qualifs.has_mut_interior.cursor.seek_before(location); + self.qualifs.indirectly_mutable.seek(location); + + let borrowed_place_has_mut_interior = HasMutInterior::in_place( + &self.item, + &|local| self.qualifs.has_mut_interior_eager_seek(local), + place.as_ref(), + ); + + if borrowed_place_has_mut_interior { + self.check_op(ops::CellBorrow); + } + } } impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { @@ -302,26 +323,44 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { trace!("visit_rvalue: rvalue={:?} location={:?}", rvalue, location); // Special-case reborrows to be more like a copy of a reference. - if let Rvalue::Ref(_, kind, ref place) = *rvalue { - if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, *self.body, place) { - let ctx = match kind { - BorrowKind::Shared => PlaceContext::NonMutatingUse( - NonMutatingUseContext::SharedBorrow, - ), - BorrowKind::Shallow => PlaceContext::NonMutatingUse( - NonMutatingUseContext::ShallowBorrow, - ), - BorrowKind::Unique => PlaceContext::NonMutatingUse( - NonMutatingUseContext::UniqueBorrow, - ), - BorrowKind::Mut { .. } => PlaceContext::MutatingUse( - MutatingUseContext::Borrow, - ), - }; - self.visit_place_base(&place.base, ctx, location); - self.visit_projection(&place.base, reborrowed_proj, ctx, location); - return; + match *rvalue { + Rvalue::Ref(_, kind, ref place) => { + if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, *self.body, place) { + let ctx = match kind { + BorrowKind::Shared => PlaceContext::NonMutatingUse( + NonMutatingUseContext::SharedBorrow, + ), + BorrowKind::Shallow => PlaceContext::NonMutatingUse( + NonMutatingUseContext::ShallowBorrow, + ), + BorrowKind::Unique => PlaceContext::NonMutatingUse( + NonMutatingUseContext::UniqueBorrow, + ), + BorrowKind::Mut { .. } => PlaceContext::MutatingUse( + MutatingUseContext::Borrow, + ), + }; + self.visit_place_base(&place.base, ctx, location); + self.visit_projection(&place.base, reborrowed_proj, ctx, location); + return; + } } + Rvalue::AddressOf(mutbl, ref place) => { + if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, *self.body, place) { + let ctx = match mutbl { + Mutability::Not => PlaceContext::NonMutatingUse( + NonMutatingUseContext::AddressOf, + ), + Mutability::Mut => PlaceContext::MutatingUse( + MutatingUseContext::AddressOf, + ), + }; + self.visit_place_base(&place.base, ctx, location); + self.visit_projection(&place.base, reborrowed_proj, ctx, location); + return; + } + } + _ => {} } self.super_rvalue(rvalue, location); @@ -367,34 +406,25 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { } } + Rvalue::AddressOf(Mutability::Mut, _) => { + self.check_op(ops::MutAddressOf) + } + // At the moment, `PlaceBase::Static` is only used for promoted MIR. | Rvalue::Ref(_, BorrowKind::Shared, ref place) | Rvalue::Ref(_, BorrowKind::Shallow, ref place) + | Rvalue::AddressOf(Mutability::Not, ref place) if matches!(place.base, PlaceBase::Static(_)) => bug!("Saw a promoted during const-checking, which must run before promotion"), - | Rvalue::Ref(_, kind @ BorrowKind::Shared, ref place) - | Rvalue::Ref(_, kind @ BorrowKind::Shallow, ref place) - => { - // FIXME: Change the `in_*` methods to take a `FnMut` so we don't have to manually - // seek the cursors beforehand. - self.qualifs.has_mut_interior.cursor.seek_before(location); - self.qualifs.indirectly_mutable.seek(location); - - let borrowed_place_has_mut_interior = HasMutInterior::in_place( - &self.item, - &|local| self.qualifs.has_mut_interior_eager_seek(local), - place.as_ref(), - ); - - if borrowed_place_has_mut_interior { - if let BorrowKind::Mut{ .. } = kind { - self.check_op(ops::MutBorrow); - } else { - self.check_op(ops::CellBorrow); - } - } - } + | Rvalue::Ref(_, BorrowKind::Shared, ref place) + | Rvalue::Ref(_, BorrowKind::Shallow, ref place) => { + self.check_immutable_borrow_like(location, place) + }, + + Rvalue::AddressOf(Mutability::Not, ref place) => { + self.check_immutable_borrow_like(location, place) + }, Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => { let operand_ty = operand.ty(*self.body, self.tcx); diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 4c723199102be..4e5d8ae08fe5b 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -196,7 +196,12 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> { } else if let TempState::Defined { ref mut uses, .. } = *temp { // We always allow borrows, even mutable ones, as we need // to promote mutable borrows of some ZSTs e.g., `&mut []`. - let allowed_use = context.is_borrow() || context.is_nonmutating_use(); + let allowed_use = match context { + PlaceContext::MutatingUse(MutatingUseContext::Borrow) + | PlaceContext::NonMutatingUse(_) => true, + PlaceContext::MutatingUse(_) + | PlaceContext::NonUse(_) => false, + }; debug!("visit_local: allowed_use={:?}", allowed_use); if allowed_use { *uses += 1; @@ -618,6 +623,21 @@ impl<'tcx> Validator<'_, 'tcx> { self.validate_operand(rhs) } + Rvalue::AddressOf(_, place) => { + // Raw reborrows can come from reference to pointer coercions, + // so are allowed. + if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() { + let base_ty = Place::ty_from(&place.base, proj_base, *self.body, self.tcx).ty; + if let ty::Ref(..) = base_ty.kind { + return self.validate_place(PlaceRef { + base: &place.base, + projection: proj_base, + }); + } + } + Err(Unpromotable) + } + Rvalue::Ref(_, kind, place) => { if let BorrowKind::Mut { .. } = kind { let ty = place.ty(*self.body, self.tcx).ty; @@ -950,7 +970,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { Candidate::Ref(loc) => { let ref mut statement = blocks[loc.block].statements[loc.statement_index]; match statement.kind { - StatementKind::Assign(box(_, Rvalue::Ref(_, _, ref mut place))) => { + StatementKind::Assign(box (_, Rvalue::Ref(_, _, ref mut place))) => { // Use the underlying local for this (necessarily interior) borrow. let ty = place.base.ty(local_decls).ty; let span = statement.source_info.span; diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index e2530795749a9..a61bff37fc873 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -135,7 +135,10 @@ fn check_rvalue( Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => { check_operand(tcx, operand, span, def_id, body) } - Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) => { + Rvalue::Len(place) + | Rvalue::Discriminant(place) + | Rvalue::Ref(_, _, place) + | Rvalue::AddressOf(_, place) => { check_place(tcx, place, span, def_id, body) } Rvalue::Cast(CastKind::Misc, operand, cast_ty) => { @@ -147,9 +150,6 @@ fn check_rvalue( span, "casting pointers to ints is unstable in const fn".into(), )), - (CastTy::RPtr(_), CastTy::Float) => bug!(), - (CastTy::RPtr(_), CastTy::Int(_)) => bug!(), - (CastTy::Ptr(_), CastTy::RPtr(_)) => bug!(), _ => check_operand(tcx, operand, span, def_id, body), } } diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 67e5bfafafd12..4f482431d3323 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -557,10 +557,10 @@ where /// if can_go then succ else drop-block /// drop-block: /// if ptr_based { - /// ptr = &mut *cur + /// ptr = cur /// cur = cur.offset(1) /// } else { - /// ptr = &mut P[cur] + /// ptr = &raw mut P[cur] /// cur = cur + 1 /// } /// drop(ptr) @@ -574,34 +574,28 @@ where unwind: Unwind, ptr_based: bool, ) -> BasicBlock { - let copy = |place: &Place<'tcx>| Operand::Copy(place.clone()); - let move_ = |place: &Place<'tcx>| Operand::Move(place.clone()); + let copy = |place: Place<'tcx>| Operand::Copy(place); + let move_ = |place: Place<'tcx>| Operand::Move(place); let tcx = self.tcx(); - let ref_ty = tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut { + let ptr_ty = tcx.mk_ptr(ty::TypeAndMut { ty: ety, mutbl: hir::Mutability::Mutable }); - let ptr = &Place::from(self.new_temp(ref_ty)); - let can_go = &Place::from(self.new_temp(tcx.types.bool)); + let ptr = &Place::from(self.new_temp(ptr_ty)); + let can_go = Place::from(self.new_temp(tcx.types.bool)); let one = self.constant_usize(1); let (ptr_next, cur_next) = if ptr_based { - (Rvalue::Ref( - tcx.lifetimes.re_erased, - BorrowKind::Mut { allow_two_phase_borrow: false }, - Place { - base: PlaceBase::Local(cur), - projection: tcx.intern_place_elems(&vec![ProjectionElem::Deref]), - } - ), - Rvalue::BinaryOp(BinOp::Offset, move_(&Place::from(cur)), one)) + ( + Rvalue::Use(copy(cur.into())), + Rvalue::BinaryOp(BinOp::Offset, move_(cur.into()), one), + ) } else { - (Rvalue::Ref( - tcx.lifetimes.re_erased, - BorrowKind::Mut { allow_two_phase_borrow: false }, - tcx.mk_place_index(self.place.clone(), cur)), - Rvalue::BinaryOp(BinOp::Add, move_(&Place::from(cur)), one)) + ( + Rvalue::AddressOf(Mutability::Mut, tcx.mk_place_index(self.place.clone(), cur)), + Rvalue::BinaryOp(BinOp::Add, move_(cur.into()), one), + ) }; let drop_block = BasicBlockData { @@ -620,9 +614,9 @@ where let loop_block = BasicBlockData { statements: vec![ - self.assign(can_go, Rvalue::BinaryOp(BinOp::Eq, - copy(&Place::from(cur)), - copy(length_or_end))) + self.assign(&can_go, Rvalue::BinaryOp(BinOp::Eq, + copy(Place::from(cur)), + copy(length_or_end.clone()))) ], is_cleanup: unwind.is_cleanup(), terminator: Some(Terminator { @@ -725,8 +719,6 @@ where let cur = self.new_temp(iter_ty); let length_or_end = if ptr_based { - // FIXME check if we want to make it return a `Place` directly - // if all use sites want a `Place::Base` anyway. Place::from(self.new_temp(iter_ty)) } else { length.clone() @@ -753,23 +745,16 @@ where let drop_block_stmts = if ptr_based { let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place)); let tmp = Place::from(self.new_temp(tmp_ty)); - // tmp = &mut P; + // tmp = &raw mut P; // cur = tmp as *mut T; // end = Offset(cur, len); vec![ - self.assign(&tmp, Rvalue::Ref( - tcx.lifetimes.re_erased, - BorrowKind::Mut { allow_two_phase_borrow: false }, - self.place.clone() - )), - self.assign( - &cur, - Rvalue::Cast(CastKind::Misc, Operand::Move(tmp), iter_ty), - ), + self.assign(&tmp, Rvalue::AddressOf(Mutability::Mut, self.place.clone())), + self.assign(&cur, Rvalue::Cast(CastKind::Misc, Operand::Move(tmp), iter_ty)), self.assign( &length_or_end, - Rvalue::BinaryOp(BinOp::Offset, Operand::Copy(cur), Operand::Move(length) - )), + Rvalue::BinaryOp(BinOp::Offset, Operand::Copy(cur), Operand::Move(length)), + ), ] } else { // cur = 0 (length already pushed) diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 68c2e16399a59..01eebeb8c55a5 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -167,6 +167,8 @@ pub fn categorize(context: PlaceContext) -> Option { PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) | PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) | + PlaceContext::MutatingUse(MutatingUseContext::AddressOf) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) | diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs index 359c8b3e73a90..7f3bab8f23299 100644 --- a/src/librustc_session/config.rs +++ b/src/librustc_session/config.rs @@ -1358,11 +1358,11 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "prints the LLVM optimization passes being run"), ast_json: bool = (false, parse_bool, [UNTRACKED], "print the AST as JSON and halt"), - // We default to min(4, vCPUs) here since we want to avoid spawning *too* - // many threads -- that causes scalability issues due to contention on - // the jobserver pipe (at least) -- but 4 is a reasonable amount on systems - // with lots of cores. - threads: usize = (std::cmp::min(::num_cpus::get(), 4), parse_threads, [UNTRACKED], + // We default to 1 here since we want to behave like + // a sequential compiler for now. This'll likely be adjusted + // in the future. Note that -Zthreads=0 is the way to get + // the num_cpus behavior. + threads: usize = (1, parse_threads, [UNTRACKED], "use a thread pool with N threads"), ast_json_noexpand: bool = (false, parse_bool, [UNTRACKED], "print the pre-expansion AST as JSON and halt"), diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index 4e72249aed129..150d207e5bfe9 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -14,7 +14,7 @@ use rustc_errors::ErrorReported; use rustc_data_structures::base_n; use rustc_data_structures::sync::{ - self, Lrc, Lock, OneThread, Once, AtomicUsize, Ordering, + self, Lrc, Lock, OneThread, Once, AtomicU64, AtomicUsize, Ordering, Ordering::SeqCst, }; use rustc_data_structures::impl_stable_hash_via_hash; @@ -119,7 +119,7 @@ pub struct Session { /// If `-zprint-fuel=crate`, `Some(crate)`. pub print_fuel_crate: Option, /// Always set to zero and incremented so that we can print fuel expended by a crate. - pub print_fuel: AtomicUsize, + pub print_fuel: AtomicU64, /// Loaded up early on in the initialization of this `Session` to avoid /// false positives about a job server in our environment. @@ -1116,7 +1116,7 @@ fn build_session_( out_of_fuel: false, }); let print_fuel_crate = sopts.debugging_opts.print_fuel.clone(); - let print_fuel = AtomicUsize::new(0); + let print_fuel = AtomicU64::new(0); let working_dir = env::current_dir().unwrap_or_else(|e| parse_sess.span_diagnostic diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 035ece238104f..21ba02746c79e 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -469,22 +469,48 @@ impl<'a, 'tcx> CastCheck<'tcx> { (Some(t_from), Some(t_cast)) => (t_from, t_cast), // Function item types may need to be reified before casts. (None, Some(t_cast)) => { - if let ty::FnDef(..) = self.expr_ty.kind { - // Attempt a coercion to a fn pointer type. - let f = self.expr_ty.fn_sig(fcx.tcx); - let res = fcx.try_coerce(self.expr, - self.expr_ty, - fcx.tcx.mk_fn_ptr(f), - AllowTwoPhase::No); - if let Err(TypeError::IntrinsicCast) = res { - return Err(CastError::IllegalCast); + match self.expr_ty.kind { + ty::FnDef(..) => { + // Attempt a coercion to a fn pointer type. + let f = self.expr_ty.fn_sig(fcx.tcx); + let res = fcx.try_coerce(self.expr, + self.expr_ty, + fcx.tcx.mk_fn_ptr(f), + AllowTwoPhase::No); + if let Err(TypeError::IntrinsicCast) = res { + return Err(CastError::IllegalCast); + } + if res.is_err() { + return Err(CastError::NonScalar); + } + (FnPtr, t_cast) } - if res.is_err() { - return Err(CastError::NonScalar); + // Special case some errors for references, and check for + // array-ptr-casts. `Ref` is not a CastTy because the cast + // is split into a coercion to a pointer type, followed by + // a cast. + ty::Ref(_, inner_ty, mutbl) => { + return match t_cast { + Int(_) | Float => match inner_ty.kind { + ty::Int(_) | + ty::Uint(_) | + ty::Float(_) | + ty::Infer(ty::InferTy::IntVar(_)) | + ty::Infer(ty::InferTy::FloatVar(_)) => { + Err(CastError::NeedDeref) + } + _ => Err(CastError::NeedViaPtr), + } + // array-ptr-cast + Ptr(mt) => self.check_ref_cast( + fcx, + TypeAndMut { mutbl, ty: inner_ty }, + mt, + ), + _ => Err(CastError::NonScalar), + }; } - (FnPtr, t_cast) - } else { - return Err(CastError::NonScalar); + _ => return Err(CastError::NonScalar), } } _ => return Err(CastError::NonScalar), @@ -492,7 +518,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { match (t_from, t_cast) { // These types have invariants! can't cast into them. - (_, RPtr(_)) | (_, Int(CEnum)) | (_, FnPtr) => Err(CastError::NonScalar), + (_, Int(CEnum)) | (_, FnPtr) => Err(CastError::NonScalar), // * -> Bool (_, Int(Bool)) => Err(CastError::CastToBool), @@ -517,28 +543,10 @@ impl<'a, 'tcx> CastCheck<'tcx> { (Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast (Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), // ptr-addr-cast (FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast), - (RPtr(p), Int(_)) | - (RPtr(p), Float) => { - match p.ty.kind { - ty::Int(_) | - ty::Uint(_) | - ty::Float(_) => { - Err(CastError::NeedDeref) - } - ty::Infer(t) => { - match t { - ty::InferTy::IntVar(_) | - ty::InferTy::FloatVar(_) => Err(CastError::NeedDeref), - _ => Err(CastError::NeedViaPtr), - } - } - _ => Err(CastError::NeedViaPtr), - } - } + // * -> ptr (Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast (FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt), - (RPtr(rmt), Ptr(mt)) => self.check_ref_cast(fcx, rmt, mt), // array-ptr-cast // prim -> prim (Int(CEnum), Int(_)) => Ok(CastKind::EnumCast), diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index fc7d19766373a..19441be87b959 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1425,8 +1425,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field: ast::Ident, ) -> Ty<'tcx> { let expr_t = self.check_expr_with_needs(base, needs); - let expr_t = self.structurally_resolved_type(base.span, - expr_t); + let expr_t = self.structurally_resolved_type(base.span, expr_t); let mut private_candidate = None; let mut autoderef = self.autoderef(expr.span, expr_t); while let Some((base_t, _)) = autoderef.next() { diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index f4b53b4d10604..9cd8c9abfd783 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -15,7 +15,7 @@ use rustc::traits::Obligation; use rustc::ty::{self, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable}; use rustc::ty::print::with_crate_prefix; use syntax_pos::{Span, FileName}; -use syntax::ast; +use syntax::{ast, source_map}; use syntax::util::lev_distance; use rustc_error_codes::*; @@ -79,37 +79,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; } - let print_disambiguation_help = | - err: &mut DiagnosticBuilder<'_>, - trait_name: String, - | { - err.help(&format!( - "to disambiguate the method call, write `{}::{}({}{})` instead", - trait_name, - item_name, - if rcvr_ty.is_region_ptr() && args.is_some() { - if rcvr_ty.is_mutable_ptr() { - "&mut " - } else { - "&" - } - } else { - "" - }, - args.map(|arg| arg - .iter() - .map(|arg| self.tcx.sess.source_map().span_to_snippet(arg.span) - .unwrap_or_else(|_| "...".to_owned())) - .collect::>() - .join(", ") - ).unwrap_or_else(|| "...".to_owned()) - )); - }; - let report_candidates = | span: Span, err: &mut DiagnosticBuilder<'_>, mut sources: Vec, + sugg_span: Span, | { sources.sort(); sources.dedup(); @@ -150,15 +124,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; - let note_str = if sources.len() > 1 { - format!("candidate #{} is defined in an impl{} for the type `{}`", - idx + 1, - insertion, - impl_ty) + let (note_str, idx) = if sources.len() > 1 { + (format!( + "candidate #{} is defined in an impl{} for the type `{}`", + idx + 1, + insertion, + impl_ty, + ), Some(idx + 1)) } else { - format!("the candidate is defined in an impl{} for the type `{}`", - insertion, - impl_ty) + (format!( + "the candidate is defined in an impl{} for the type `{}`", + insertion, + impl_ty, + ), None) }; if let Some(note_span) = note_span { // We have a span pointing to the method. Show note with snippet. @@ -168,7 +146,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.note(¬e_str); } if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) { - print_disambiguation_help(err, self.tcx.def_path_str(trait_ref.def_id)); + let path = self.tcx.def_path_str(trait_ref.def_id); + + let ty = match item.kind { + ty::AssocKind::Const | + ty::AssocKind::Type | + ty::AssocKind::OpaqueTy => rcvr_ty, + ty::AssocKind::Method => self.tcx.fn_sig(item.def_id) + .inputs() + .skip_binder() + .get(0) + .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr()) + .map(|ty| *ty) + .unwrap_or(rcvr_ty), + }; + print_disambiguation_help( + item_name, + args, + err, + path, + ty, + item.kind, + sugg_span, + idx, + self.tcx.sess.source_map(), + ); } } CandidateSource::TraitSource(trait_did) => { @@ -182,19 +184,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let item_span = self.tcx.sess.source_map() .def_span(self.tcx.def_span(item.def_id)); - if sources.len() > 1 { + let idx = if sources.len() > 1 { span_note!(err, item_span, "candidate #{} is defined in the trait `{}`", idx + 1, self.tcx.def_path_str(trait_did)); + Some(idx + 1) } else { span_note!(err, item_span, "the candidate is defined in the trait `{}`", self.tcx.def_path_str(trait_did)); - } - print_disambiguation_help(err, self.tcx.def_path_str(trait_did)); + None + }; + let path = self.tcx.def_path_str(trait_did); + print_disambiguation_help( + item_name, + args, + err, + path, + rcvr_ty, + item.kind, + sugg_span, + idx, + self.tcx.sess.source_map(), + ); } } } @@ -203,6 +218,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; + let sugg_span = if let SelfSource::MethodCall(expr) = source { + // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing. + self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span + } else { + span + }; + match error { MethodError::NoMatch(NoMatchData { static_candidates: static_sources, @@ -495,9 +517,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )); } - report_candidates(span, &mut err, static_sources); + report_candidates(span, &mut err, static_sources, sugg_span); } else if static_sources.len() > 1 { - report_candidates(span, &mut err, static_sources); + report_candidates(span, &mut err, static_sources, sugg_span); } if !unsatisfied_predicates.is_empty() { @@ -584,7 +606,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "multiple applicable items in scope"); err.span_label(span, format!("multiple `{}` found", item_name)); - report_candidates(span, &mut err, sources); + report_candidates(span, &mut err, sources, sugg_span); err.emit(); } @@ -1123,3 +1145,56 @@ impl hir::intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> { hir::intravisit::NestedVisitorMap::None } } + +fn print_disambiguation_help( + item_name: ast::Ident, + args: Option<&'tcx [hir::Expr]>, + err: &mut DiagnosticBuilder<'_>, + trait_name: String, + rcvr_ty: Ty<'_>, + kind: ty::AssocKind, + span: Span, + candidate: Option, + source_map: &source_map::SourceMap, +) { + let mut applicability = Applicability::MachineApplicable; + let sugg_args = if let (ty::AssocKind::Method, Some(args)) = (kind, args) { + format!( + "({}{})", + if rcvr_ty.is_region_ptr() { + if rcvr_ty.is_mutable_ptr() { + "&mut " + } else { + "&" + } + } else { + "" + }, + args.iter() + .map(|arg| source_map.span_to_snippet(arg.span) + .unwrap_or_else(|_| { + applicability = Applicability::HasPlaceholders; + "_".to_owned() + })) + .collect::>() + .join(", "), + ) + } else { + String::new() + }; + let sugg = format!("{}::{}{}", trait_name, item_name, sugg_args); + err.span_suggestion( + span, + &format!( + "disambiguate the {} for {}", + kind.suggestion_descr(), + if let Some(candidate) = candidate { + format!("candidate #{}", candidate) + } else { + "the candidate".to_string() + }, + ), + sugg, + applicability, + ); +} diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index d5f4ece726bea..a9d88370c612f 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -4,7 +4,7 @@ use crate::hash; use crate::io; use crate::iter; use crate::mem; -use crate::net::{hton, ntoh, IpAddr, Ipv4Addr, Ipv6Addr}; +use crate::net::{htons, ntohs, IpAddr, Ipv4Addr, Ipv6Addr}; use crate::option; use crate::slice; use crate::sys::net::netc as c; @@ -276,7 +276,7 @@ impl SocketAddrV4 { SocketAddrV4 { inner: c::sockaddr_in { sin_family: c::AF_INET as c::sa_family_t, - sin_port: hton(port), + sin_port: htons(port), sin_addr: *ip.as_inner(), ..unsafe { mem::zeroed() } }, @@ -326,7 +326,7 @@ impl SocketAddrV4 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn port(&self) -> u16 { - ntoh(self.inner.sin_port) + ntohs(self.inner.sin_port) } /// Changes the port number associated with this socket address. @@ -342,7 +342,7 @@ impl SocketAddrV4 { /// ``` #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_port(&mut self, new_port: u16) { - self.inner.sin_port = hton(new_port); + self.inner.sin_port = htons(new_port); } } @@ -368,7 +368,7 @@ impl SocketAddrV6 { SocketAddrV6 { inner: c::sockaddr_in6 { sin6_family: c::AF_INET6 as c::sa_family_t, - sin6_port: hton(port), + sin6_port: htons(port), sin6_addr: *ip.as_inner(), sin6_flowinfo: flowinfo, sin6_scope_id: scope_id, @@ -420,7 +420,7 @@ impl SocketAddrV6 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn port(&self) -> u16 { - ntoh(self.inner.sin6_port) + ntohs(self.inner.sin6_port) } /// Changes the port number associated with this socket address. @@ -436,7 +436,7 @@ impl SocketAddrV6 { /// ``` #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_port(&mut self, new_port: u16) { - self.inner.sin6_port = hton(new_port); + self.inner.sin6_port = htons(new_port); } /// Returns the flow information associated with this address. diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index b68146939fdcc..8652ed8b046bb 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -85,21 +85,10 @@ pub enum Shutdown { Both, } -#[doc(hidden)] -trait NetInt { - fn from_be(i: Self) -> Self; - fn to_be(&self) -> Self; -} -macro_rules! doit { - ($($t:ident)*) => ($(impl NetInt for $t { - fn from_be(i: Self) -> Self { <$t>::from_be(i) } - fn to_be(&self) -> Self { <$t>::to_be(*self) } - })*) -} -doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } - -fn hton(i: I) -> I { i.to_be() } -fn ntoh(i: I) -> I { I::from_be(i) } +#[inline] +const fn htons(i: u16) -> u16 { i.to_be() } +#[inline] +const fn ntohs(i: u16) -> u16 { u16::from_be(i) } fn each_addr(addr: A, mut f: F) -> io::Result where F: FnMut(io::Result<&SocketAddr>) -> io::Result diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 92ba071a03d68..274e19ec3e425 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -728,13 +728,13 @@ impl Mutability { #[derive(Clone, Copy, PartialEq, Eq, Debug)] #[derive(RustcEncodable, RustcDecodable, HashStable_Generic)] pub enum BorrowKind { - /// A raw borrow, `&raw const $expr` or `&raw mut $expr`. - /// The resulting type is either `*const T` or `*mut T` - /// where `T = typeof($expr)`. - Ref, /// A normal borrow, `&$expr` or `&mut $expr`. /// The resulting type is either `&'a T` or `&'a mut T` /// where `T = typeof($expr)` and `'a` is some lifetime. + Ref, + /// A raw borrow, `&raw const $expr` or `&raw mut $expr`. + /// The resulting type is either `*const T` or `*mut T` + /// where `T = typeof($expr)`. Raw, } diff --git a/src/test/mir-opt/address-of.rs b/src/test/mir-opt/address-of.rs new file mode 100644 index 0000000000000..bbd1ca68a8672 --- /dev/null +++ b/src/test/mir-opt/address-of.rs @@ -0,0 +1,112 @@ +fn address_of_reborrow() { + let y = &[0; 10]; + let mut z = &mut [0; 10]; + + y as *const _; + y as *const [i32; 10]; + y as *const dyn Send; + y as *const [i32]; + y as *const i32; // This is a cast, not a coercion + + let p: *const _ = y; + let p: *const [i32; 10] = y; + let p: *const dyn Send = y; + let p: *const [i32] = y; + + z as *const _; + z as *const [i32; 10]; + z as *const dyn Send; + z as *const [i32]; + + let p: *const _ = z; + let p: *const [i32; 10] = z; + let p: *const dyn Send = z; + let p: *const [i32] = z; + + z as *mut _; + z as *mut [i32; 10]; + z as *mut dyn Send; + z as *mut [i32]; + + let p: *mut _ = z; + let p: *mut [i32; 10] = z; + let p: *mut dyn Send = z; + let p: *mut [i32] = z; +} + +// The normal borrows here should be preserved +fn borrow_and_cast(mut x: i32) { + let p = &x as *const i32; + let q = &mut x as *const i32; + let r = &mut x as *mut i32; +} + +fn main() {} + +// START rustc.address_of_reborrow.SimplifyCfg-initial.after.mir +// bb0: { +// ... +// _5 = &raw const (*_1); // & to *const casts +// ... +// _7 = &raw const (*_1); +// ... +// _11 = &raw const (*_1); +// ... +// _14 = &raw const (*_1); +// ... +// _16 = &raw const (*_1); +// ... +// _17 = &raw const (*_1); // & to *const coercions +// ... +// _18 = &raw const (*_1); +// ... +// _20 = &raw const (*_1); +// ... +// _22 = &raw const (*_1); +// ... +// _24 = &raw const (*_2); // &mut to *const casts +// ... +// _26 = &raw const (*_2); +// ... +// _30 = &raw const (*_2); +// ... +// _33 = &raw const (*_2); +// ... +// _34 = &raw const (*_2); // &mut to *const coercions +// ... +// _35 = &raw const (*_2); +// ... +// _37 = &raw const (*_2); +// ... +// _39 = &raw const (*_2); +// ... +// _41 = &raw mut (*_2); // &mut to *mut casts +// ... +// _43 = &raw mut (*_2); +// ... +// _47 = &raw mut (*_2); +// ... +// _50 = &raw mut (*_2); +// ... +// _51 = &raw mut (*_2); // &mut to *mut coercions +// ... +// _52 = &raw mut (*_2); +// ... +// _54 = &raw mut (*_2); +// ... +// _56 = &raw mut (*_2); +// ... +// } +// END rustc.address_of_reborrow.SimplifyCfg-initial.after.mir + +// START rustc.borrow_and_cast.EraseRegions.after.mir +// bb0: { +// ... +// _4 = &_1; +// ... +// _7 = &mut _1; +// ... +// _10 = &mut _1; +// ... +// } +// END rustc.borrow_and_cast.EraseRegions.after.mir diff --git a/src/test/mir-opt/array-index-is-temporary.rs b/src/test/mir-opt/array-index-is-temporary.rs index 00a6b26d0cf22..096f98bade25a 100644 --- a/src/test/mir-opt/array-index-is-temporary.rs +++ b/src/test/mir-opt/array-index-is-temporary.rs @@ -18,24 +18,23 @@ fn main() { // START rustc.main.EraseRegions.after.mir // bb0: { // ... -// _5 = &mut _2; -// _4 = &mut (*_5); -// _3 = move _4 as *mut usize (Misc); +// _4 = &mut _2; +// _3 = &raw mut (*_4); // ... -// _7 = _3; -// _6 = const foo(move _7) -> bb1; +// _6 = _3; +// _5 = const foo(move _6) -> bb1; // } // // bb1: { // ... -// _8 = _2; -// _9 = Len(_1); -// _10 = Lt(_8, _9); -// assert(move _10, "index out of bounds: the len is move _9 but the index is _8") -> bb2; +// _7 = _2; +// _8 = Len(_1); +// _9 = Lt(_7, _8); +// assert(move _9, "index out of bounds: the len is move _8 but the index is _7") -> bb2; // } // // bb2: { -// _1[_8] = move _6; +// _1[_7] = move _5; // ... // return; // } diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs index 3f82b81a47de5..3c8c0ff449345 100644 --- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs +++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs @@ -11,25 +11,21 @@ fn main() { // START rustc.main.ConstProp.before.mir // bb0: { // ... -// _3 = _4; -// _2 = move _3 as *const i32 (Misc); -// ... +// _2 = &raw const (*_3); // _1 = move _2 as usize (Misc); // ... -// _6 = _1; -// _5 = const read(move _6) -> bb1; +// _5 = _1; +// _4 = const read(move _5) -> bb1; // } // END rustc.main.ConstProp.before.mir // START rustc.main.ConstProp.after.mir // bb0: { // ... -// _4 = const main::FOO; -// _3 = _4; -// _2 = move _3 as *const i32 (Misc); -// ... +// _3 = const main::FOO; +// _2 = &raw const (*_3); // _1 = move _2 as usize (Misc); // ... -// _6 = _1; -// _5 = const read(move _6) -> bb1; +// _5 = _1; +// _4 = const read(move _5) -> bb1; // } // END rustc.main.ConstProp.after.mir diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs index 32995448a21e9..ccecaeac96b83 100644 --- a/src/test/mir-opt/retag.rs +++ b/src/test/mir-opt/retag.rs @@ -82,18 +82,16 @@ fn main() { // _10 = move _8; // Retag(_10); // ... -// _13 = &mut (*_10); -// Retag(_13); -// _12 = move _13 as *mut i32 (Misc); +// _12 = &raw mut (*_10); // Retag([raw] _12); // ... -// _16 = move _17(move _18) -> bb5; +// _15 = move _16(move _17) -> bb5; // } // // bb5: { -// Retag(_16); +// Retag(_15); // ... -// _20 = const Test::foo_shr(move _21, move _23) -> [return: bb6, unwind: bb7]; +// _19 = const Test::foo_shr(move _20, move _22) -> [return: bb6, unwind: bb7]; // } // // ... diff --git a/src/test/mir-opt/slice-drop-shim.rs b/src/test/mir-opt/slice-drop-shim.rs index f270dec5fe232..5a37b67229c37 100644 --- a/src/test/mir-opt/slice-drop-shim.rs +++ b/src/test/mir-opt/slice-drop-shim.rs @@ -10,15 +10,15 @@ fn main() { // let mut _2: usize; // let mut _3: usize; // let mut _4: usize; -// let mut _5: &mut std::string::String; +// let mut _5: *mut std::string::String; // let mut _6: bool; -// let mut _7: &mut std::string::String; +// let mut _7: *mut std::string::String; // let mut _8: bool; // let mut _9: *mut std::string::String; // let mut _10: *mut std::string::String; -// let mut _11: &mut std::string::String; +// let mut _11: *mut std::string::String; // let mut _12: bool; -// let mut _13: &mut std::string::String; +// let mut _13: *mut std::string::String; // let mut _14: bool; // let mut _15: *mut [std::string::String]; // bb0: { @@ -31,7 +31,7 @@ fn main() { // resume; // } // bb3 (cleanup): { -// _5 = &mut (*_1)[_4]; +// _5 = &raw mut (*_1)[_4]; // _4 = Add(move _4, const 1usize); // drop((*_5)) -> bb4; // } @@ -40,7 +40,7 @@ fn main() { // switchInt(move _6) -> [false: bb3, otherwise: bb2]; // } // bb5: { -// _7 = &mut (*_1)[_4]; +// _7 = &raw mut (*_1)[_4]; // _4 = Add(move _4, const 1usize); // drop((*_7)) -> [return: bb6, unwind: bb4]; // } @@ -56,7 +56,7 @@ fn main() { // goto -> bb7; // } // bb9 (cleanup): { -// _11 = &mut (*_9); +// _11 = _9; // _9 = Offset(move _9, const 1usize); // drop((*_11)) -> bb10; // } @@ -65,7 +65,7 @@ fn main() { // switchInt(move _12) -> [false: bb9, otherwise: bb2]; // } // bb11: { -// _13 = &mut (*_9); +// _13 = _9; // _9 = Offset(move _9, const 1usize); // drop((*_13)) -> [return: bb12, unwind: bb10]; // } @@ -74,7 +74,7 @@ fn main() { // switchInt(move _14) -> [false: bb11, otherwise: bb1]; // } // bb13: { -// _15 = &mut (*_1); +// _15 = &raw mut (*_1); // _9 = move _15 as *mut std::string::String (Misc); // _10 = Offset(_9, move _3); // goto -> bb12; diff --git a/src/test/pretty/raw-address-of.rs b/src/test/pretty/raw-address-of.rs new file mode 100644 index 0000000000000..6ccc434a1e79c --- /dev/null +++ b/src/test/pretty/raw-address-of.rs @@ -0,0 +1,12 @@ +// pp-exact +#![feature(raw_ref_op)] + +const C_PTR: () = { let a = 1; &raw const a; }; +static S_PTR: () = { let b = false; &raw const b; }; + +fn main() { + let x = 123; + let mut y = 345; + let c_p = &raw const x; + let parens = unsafe { *(&raw mut (y)) }; +} diff --git a/src/test/ui/associated-const/associated-const-ambiguity-report.stderr b/src/test/ui/associated-const/associated-const-ambiguity-report.stderr index bb217bd182db6..92a8d19021a2c 100644 --- a/src/test/ui/associated-const/associated-const-ambiguity-report.stderr +++ b/src/test/ui/associated-const/associated-const-ambiguity-report.stderr @@ -9,13 +9,19 @@ note: candidate #1 is defined in an impl of the trait `Foo` for the type `i32` | LL | const ID: i32 = 1; | ^^^^^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `Foo::ID(...)` instead note: candidate #2 is defined in an impl of the trait `Bar` for the type `i32` --> $DIR/associated-const-ambiguity-report.rs:14:5 | LL | const ID: i32 = 3; | ^^^^^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `Bar::ID(...)` instead +help: disambiguate the associated constant for candidate #1 + | +LL | const X: i32 = Foo::ID; + | ^^^^^^^ +help: disambiguate the associated constant for candidate #2 + | +LL | const X: i32 = Bar::ID; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrow-raw-address-of-borrowed.rs b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.rs new file mode 100644 index 0000000000000..f25fd7f66b3cc --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.rs @@ -0,0 +1,22 @@ +#![feature(raw_ref_op)] + +fn address_of_shared() { + let mut x = 0; + let y = &x; + + let q = &raw mut x; //~ ERROR cannot borrow + + drop(y); +} + +fn address_of_mutably_borrowed() { + let mut x = 0; + let y = &mut x; + + let p = &raw const x; //~ ERROR cannot borrow + let q = &raw mut x; //~ ERROR cannot borrow + + drop(y); +} + +fn main() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-borrowed.stderr b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.stderr new file mode 100644 index 0000000000000..ff461b748be88 --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.stderr @@ -0,0 +1,40 @@ +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/borrow-raw-address-of-borrowed.rs:7:13 + | +LL | let y = &x; + | -- immutable borrow occurs here +LL | +LL | let q = &raw mut x; + | ^^^^^^^^^^ mutable borrow occurs here +LL | +LL | drop(y); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/borrow-raw-address-of-borrowed.rs:16:13 + | +LL | let y = &mut x; + | ------ mutable borrow occurs here +LL | +LL | let p = &raw const x; + | ^^^^^^^^^^^^ immutable borrow occurs here +... +LL | drop(y); + | - mutable borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrow-raw-address-of-borrowed.rs:17:13 + | +LL | let y = &mut x; + | ------ first mutable borrow occurs here +... +LL | let q = &raw mut x; + | ^^^^^^^^^^ second mutable borrow occurs here +LL | +LL | drop(y); + | - first borrow later used here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0499, E0502. +For more information about an error, try `rustc --explain E0499`. diff --git a/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs new file mode 100644 index 0000000000000..e381384fe65ec --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(raw_ref_op)] + +fn raw_reborrow() { + let x = &0; + let y = &mut 0; + + let p = &raw const *x; + let r = &raw const *y; + let s = &raw mut *y; +} + +unsafe fn raw_reborrow_of_raw() { + let x = &0 as *const i32; + let y = &mut 0 as *mut i32; + + let p = &raw const *x; + let r = &raw const *y; + let s = &raw mut *y; +} + +fn main() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.rs b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.rs new file mode 100644 index 0000000000000..712873528b5f1 --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.rs @@ -0,0 +1,17 @@ +// Check that `&raw mut` cannot be used to turn a `&T` into a `*mut T`. + +#![feature(raw_ref_op)] + +fn raw_reborrow() { + let x = &0; + + let q = &raw mut *x; //~ ERROR cannot borrow +} + +unsafe fn raw_reborrow_of_raw() { + let x = &0 as *const i32; + + let q = &raw mut *x; //~ ERROR cannot borrow +} + +fn main() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr new file mode 100644 index 0000000000000..31af38507c7d7 --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr @@ -0,0 +1,21 @@ +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrow-raw-address-of-deref-mutability.rs:8:13 + | +LL | let x = &0; + | -- help: consider changing this to be a mutable reference: `&mut 0` +LL | +LL | let q = &raw mut *x; + | ^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `*const` pointer + --> $DIR/borrow-raw-address-of-deref-mutability.rs:14:13 + | +LL | let x = &0 as *const i32; + | -- help: consider changing this to be a mutable pointer: `&mut 0` +LL | +LL | let q = &raw mut *x; + | ^^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability-ok.rs b/src/test/ui/borrowck/borrow-raw-address-of-mutability-ok.rs new file mode 100644 index 0000000000000..e1cf2dc53869b --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability-ok.rs @@ -0,0 +1,44 @@ +// check-pass + +#![feature(raw_ref_op)] + +fn mutable_address_of() { + let mut x = 0; + let y = &raw mut x; +} + +fn mutable_address_of_closure() { + let mut x = 0; + let mut f = || { + let y = &raw mut x; + }; + f(); +} + +fn const_address_of_closure() { + let x = 0; + let f = || { + let y = &raw const x; + }; + f(); +} + +fn make_fn(f: F) -> F { f } + +fn const_address_of_fn_closure() { + let x = 0; + let f = make_fn(|| { + let y = &raw const x; + }); + f(); +} + +fn const_address_of_fn_closure_move() { + let x = 0; + let f = make_fn(move || { + let y = &raw const x; + }); + f(); +} + +fn main() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability.rs b/src/test/ui/borrowck/borrow-raw-address-of-mutability.rs new file mode 100644 index 0000000000000..320c54b806a72 --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability.rs @@ -0,0 +1,42 @@ +#![feature(raw_ref_op)] + +fn mutable_address_of() { + let x = 0; + let y = &raw mut x; //~ ERROR cannot borrow +} + +fn mutable_address_of_closure() { + let x = 0; + let mut f = || { + let y = &raw mut x; //~ ERROR cannot borrow + }; + f(); +} + +fn mutable_address_of_imm_closure() { + let mut x = 0; + let f = || { + let y = &raw mut x; + }; + f(); //~ ERROR cannot borrow +} + +fn make_fn(f: F) -> F { f } + +fn mutable_address_of_fn_closure() { + let mut x = 0; + let f = make_fn(|| { + let y = &raw mut x; //~ ERROR cannot borrow + }); + f(); +} + +fn mutable_address_of_fn_closure_move() { + let mut x = 0; + let f = make_fn(move || { + let y = &raw mut x; //~ ERROR cannot borrow + }); + f(); +} + +fn main() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr new file mode 100644 index 0000000000000..cf01c362d50bc --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr @@ -0,0 +1,59 @@ +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrow-raw-address-of-mutability.rs:5:13 + | +LL | let x = 0; + | - help: consider changing this to be mutable: `mut x` +LL | let y = &raw mut x; + | ^^^^^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrow-raw-address-of-mutability.rs:11:17 + | +LL | let x = 0; + | - help: consider changing this to be mutable: `mut x` +LL | let mut f = || { +LL | let y = &raw mut x; + | ^^^^^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable + --> $DIR/borrow-raw-address-of-mutability.rs:21:5 + | +LL | let f = || { + | - help: consider changing this to be mutable: `mut f` +... +LL | f(); + | ^ cannot borrow as mutable + +error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/borrow-raw-address-of-mutability.rs:29:17 + | +LL | let y = &raw mut x; + | ^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to accept closures that implement `FnMut` + --> $DIR/borrow-raw-address-of-mutability.rs:28:21 + | +LL | let f = make_fn(|| { + | _____________________^ +LL | | let y = &raw mut x; +LL | | }); + | |_____^ + +error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/borrow-raw-address-of-mutability.rs:37:17 + | +LL | let y = &raw mut x; + | ^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to accept closures that implement `FnMut` + --> $DIR/borrow-raw-address-of-mutability.rs:36:21 + | +LL | let f = make_fn(move || { + | _____________________^ +LL | | let y = &raw mut x; +LL | | }); + | |_____^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/cast/cast-as-bool.rs b/src/test/ui/cast/cast-as-bool.rs index 8130f4dedc9aa..1aed218aeb473 100644 --- a/src/test/ui/cast/cast-as-bool.rs +++ b/src/test/ui/cast/cast-as-bool.rs @@ -5,5 +5,5 @@ fn main() { let t = (1 + 2) as bool; //~ ERROR cannot cast as `bool` //~| HELP compare with zero instead //~| SUGGESTION (1 + 2) != 0 - let v = "hello" as bool; //~ ERROR cannot cast as `bool` + let v = "hello" as bool; //~ ERROR casting `&'static str` as `bool` is invalid } diff --git a/src/test/ui/cast/cast-as-bool.stderr b/src/test/ui/cast/cast-as-bool.stderr index 30f8459c2e1e1..15d94ab69d88c 100644 --- a/src/test/ui/cast/cast-as-bool.stderr +++ b/src/test/ui/cast/cast-as-bool.stderr @@ -10,12 +10,13 @@ error[E0054]: cannot cast as `bool` LL | let t = (1 + 2) as bool; | ^^^^^^^^^^^^^^^ help: compare with zero instead: `(1 + 2) != 0` -error[E0054]: cannot cast as `bool` +error[E0606]: casting `&'static str` as `bool` is invalid --> $DIR/cast-as-bool.rs:8:13 | LL | let v = "hello" as bool; - | ^^^^^^^^^^^^^^^ unsupported cast + | ^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0054`. +Some errors have detailed explanations: E0054, E0606. +For more information about an error, try `rustc --explain E0054`. diff --git a/src/test/ui/consts/const-address-of-interior-mut.rs b/src/test/ui/consts/const-address-of-interior-mut.rs new file mode 100644 index 0000000000000..60c7c31daca78 --- /dev/null +++ b/src/test/ui/consts/const-address-of-interior-mut.rs @@ -0,0 +1,16 @@ +#![feature(raw_ref_op)] + +use std::cell::Cell; + +const A: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability + +static B: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability + +static mut C: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability + +const fn foo() { + let x = Cell::new(0); + let y = &raw const x; //~ ERROR interior mutability +} + +fn main() {} diff --git a/src/test/ui/consts/const-address-of-interior-mut.stderr b/src/test/ui/consts/const-address-of-interior-mut.stderr new file mode 100644 index 0000000000000..f15174c33b3a0 --- /dev/null +++ b/src/test/ui/consts/const-address-of-interior-mut.stderr @@ -0,0 +1,27 @@ +error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead + --> $DIR/const-address-of-interior-mut.rs:5:39 + | +LL | const A: () = { let x = Cell::new(2); &raw const x; }; + | ^^^^^^^^^^^^ + +error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead + --> $DIR/const-address-of-interior-mut.rs:7:40 + | +LL | static B: () = { let x = Cell::new(2); &raw const x; }; + | ^^^^^^^^^^^^ + +error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead + --> $DIR/const-address-of-interior-mut.rs:9:44 + | +LL | static mut C: () = { let x = Cell::new(2); &raw const x; }; + | ^^^^^^^^^^^^ + +error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead + --> $DIR/const-address-of-interior-mut.rs:13:13 + | +LL | let y = &raw const x; + | ^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0492`. diff --git a/src/test/ui/consts/const-address-of-mut.rs b/src/test/ui/consts/const-address-of-mut.rs new file mode 100644 index 0000000000000..fe9188cb4904c --- /dev/null +++ b/src/test/ui/consts/const-address-of-mut.rs @@ -0,0 +1,14 @@ +#![feature(raw_ref_op)] + +const A: () = { let mut x = 2; &raw mut x; }; //~ ERROR `&raw mut` is not allowed + +static B: () = { let mut x = 2; &raw mut x; }; //~ ERROR `&raw mut` is not allowed + +static mut C: () = { let mut x = 2; &raw mut x; }; //~ ERROR `&raw mut` is not allowed + +const fn foo() { + let mut x = 0; + let y = &raw mut x; //~ ERROR `&raw mut` is not allowed +} + +fn main() {} diff --git a/src/test/ui/consts/const-address-of-mut.stderr b/src/test/ui/consts/const-address-of-mut.stderr new file mode 100644 index 0000000000000..15f2296c42c25 --- /dev/null +++ b/src/test/ui/consts/const-address-of-mut.stderr @@ -0,0 +1,39 @@ +error[E0658]: `&raw mut` is not allowed in constants + --> $DIR/const-address-of-mut.rs:3:32 + | +LL | const A: () = { let mut x = 2; &raw mut x; }; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/57349 + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: `&raw mut` is not allowed in statics + --> $DIR/const-address-of-mut.rs:5:33 + | +LL | static B: () = { let mut x = 2; &raw mut x; }; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/57349 + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: `&raw mut` is not allowed in statics + --> $DIR/const-address-of-mut.rs:7:37 + | +LL | static mut C: () = { let mut x = 2; &raw mut x; }; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/57349 + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: `&raw mut` is not allowed in constant functions + --> $DIR/const-address-of-mut.rs:11:13 + | +LL | let y = &raw mut x; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/57349 + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/const-address-of.rs b/src/test/ui/consts/const-address-of.rs new file mode 100644 index 0000000000000..ba162f2a2badf --- /dev/null +++ b/src/test/ui/consts/const-address-of.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(raw_ref_op)] + +const A: *const i32 = &raw const *&2; +static B: () = { &raw const *&2; }; +static mut C: *const i32 = &raw const *&2; +const D: () = { let x = 2; &raw const x; }; +static E: () = { let x = 2; &raw const x; }; +static mut F: () = { let x = 2; &raw const x; }; + +const fn const_ptr() { + let x = 0; + let ptr = &raw const x; + let r = &x; + let ptr2 = &raw const *r; +} + +fn main() {} diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index 1f810c40572c0..90c90b5e9c98d 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -2,10 +2,7 @@ #![allow(unused)] #![allow(const_err)] // make sure we cannot allow away the errors tested here -// normalize-stderr-test "alignment \d+" -> "alignment N" -// normalize-stderr-test "offset \d+" -> "offset N" // normalize-stderr-test "allocation \d+" -> "allocation N" -// normalize-stderr-test "size \d+" -> "size N" #[repr(C)] union BoolTransmute { @@ -149,11 +146,23 @@ const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 } //~^ ERROR it is undefined behavior to use this value // # raw trait object -const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust}; +const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.raw_rust}; //~^ ERROR it is undefined behavior to use this value const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; //~^ ERROR it is undefined behavior to use this value const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl } as *const _; // ok because raw +// Const eval fails for these, so they need to be statics to error. +static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe { + DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust + //~^ ERROR could not evaluate static initializer +}; +static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe { + DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust + //~^ ERROR could not evaluate static initializer +}; + fn main() { + let _ = RAW_TRAIT_OBJ_VTABLE_NULL; + let _ = RAW_TRAIT_OBJ_VTABLE_INVALID; } diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index 85fb8ac2a4a36..195c4999e9e9a 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:87:1 + --> $DIR/ub-wide-ptr.rs:84:1 | LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) @@ -7,7 +7,7 @@ LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:90:1 + --> $DIR/ub-wide-ptr.rs:87:1 | LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer @@ -15,7 +15,7 @@ LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:93:1 + --> $DIR/ub-wide-ptr.rs:90:1 | LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer @@ -23,7 +23,7 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRe = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:97:1 + --> $DIR/ub-wide-ptr.rs:94:1 | LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . @@ -31,7 +31,7 @@ LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:100:1 + --> $DIR/ub-wide-ptr.rs:97:1 | LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 @@ -39,7 +39,7 @@ LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:107:1 + --> $DIR/ub-wide-ptr.rs:104:1 | LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer @@ -47,7 +47,7 @@ LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.sli = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:110:1 + --> $DIR/ub-wide-ptr.rs:107:1 | LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) @@ -55,7 +55,7 @@ LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { p = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:113:1 + --> $DIR/ub-wide-ptr.rs:110:1 | LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer @@ -63,7 +63,7 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:117:1 + --> $DIR/ub-wide-ptr.rs:114:1 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected something less or equal to 1 @@ -71,7 +71,7 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }. = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:123:1 + --> $DIR/ub-wide-ptr.rs:120:1 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected something less or equal to 1 @@ -79,7 +79,7 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:126:1 + --> $DIR/ub-wide-ptr.rs:123:1 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected something less or equal to 1 @@ -87,7 +87,7 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTrans = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:133:1 + --> $DIR/ub-wide-ptr.rs:130:1 | LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer @@ -95,7 +95,7 @@ LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:138:1 + --> $DIR/ub-wide-ptr.rs:135:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -103,7 +103,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:141:1 + --> $DIR/ub-wide-ptr.rs:138:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -111,7 +111,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:144:1 + --> $DIR/ub-wide-ptr.rs:141:1 | LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -119,7 +119,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDy = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:148:1 + --> $DIR/ub-wide-ptr.rs:145:1 | LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected something less or equal to 1 @@ -127,21 +127,33 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:152:1 + --> $DIR/ub-wide-ptr.rs:149:1 | -LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.raw_rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:154:1 + --> $DIR/ub-wide-ptr.rs:151:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. -error: aborting due to 18 previous errors +error[E0080]: could not evaluate static initializer + --> $DIR/ub-wide-ptr.rs:157:5 + | +LL | DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer + +error[E0080]: could not evaluate static initializer + --> $DIR/ub-wide-ptr.rs:161:5 + | +LL | DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 24, but is outside bounds of allocation N which has size 8 + +error: aborting due to 20 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs new file mode 100644 index 0000000000000..130ba9283b1d9 --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs @@ -0,0 +1,30 @@ +// check-pass + +#![feature(const_mut_refs)] +#![feature(const_fn)] +#![feature(raw_ref_op)] + +struct Foo { + x: usize +} + +const fn foo() -> Foo { + Foo { x: 0 } +} + +impl Foo { + const fn bar(&mut self) -> *mut usize { + &raw mut self.x + } +} + +const fn baz(foo: &mut Foo)-> *mut usize { + &raw mut foo.x +} + +const _: () = { + foo().bar(); + baz(&mut foo()); +}; + +fn main() {} diff --git a/src/test/ui/consts/const-prop-ice3.rs b/src/test/ui/consts/const-prop-ice3.rs new file mode 100644 index 0000000000000..8ab011661e3c5 --- /dev/null +++ b/src/test/ui/consts/const-prop-ice3.rs @@ -0,0 +1,7 @@ +// run-pass (ensure that const-prop is run) + +struct A(T); + +fn main() { + let _x = &(&A([2, 3]) as &A<[i32]>).0 as *const [i32] as *const i32; +} diff --git a/src/test/ui/consts/min_const_fn/address_of.rs b/src/test/ui/consts/min_const_fn/address_of.rs new file mode 100644 index 0000000000000..f8506d70b2498 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/address_of.rs @@ -0,0 +1,17 @@ +#![feature(raw_ref_op)] + +const fn mutable_address_of_in_const() { + let mut a = 0; + let b = &raw mut a; //~ ERROR `&raw mut` is not allowed +} + +struct X; + +impl X { + const fn inherent_mutable_address_of_in_const() { + let mut a = 0; + let b = &raw mut a; //~ ERROR `&raw mut` is not allowed + } +} + +fn main() {} diff --git a/src/test/ui/consts/min_const_fn/address_of.stderr b/src/test/ui/consts/min_const_fn/address_of.stderr new file mode 100644 index 0000000000000..3554b8112b168 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/address_of.stderr @@ -0,0 +1,21 @@ +error[E0658]: `&raw mut` is not allowed in constant functions + --> $DIR/address_of.rs:5:13 + | +LL | let b = &raw mut a; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/57349 + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: `&raw mut` is not allowed in constant functions + --> $DIR/address_of.rs:13:17 + | +LL | let b = &raw mut a; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/57349 + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/min_const_fn/address_of_const.rs b/src/test/ui/consts/min_const_fn/address_of_const.rs new file mode 100644 index 0000000000000..3db19e9cde8f0 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/address_of_const.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(raw_ref_op)] + +const fn const_address_of_in_const() { + let mut a = 0; + let b = &raw const a; +} + +struct X; + +impl X { + const fn inherent_const_address_of_in_const() { + let mut a = 0; + let b = &raw const a; + } +} + +fn main() {} diff --git a/src/test/ui/error-codes/E0034.stderr b/src/test/ui/error-codes/E0034.stderr index a58d16bfafb59..6db2ef5051d83 100644 --- a/src/test/ui/error-codes/E0034.stderr +++ b/src/test/ui/error-codes/E0034.stderr @@ -9,13 +9,19 @@ note: candidate #1 is defined in an impl of the trait `Trait1` for the type `Tes | LL | fn foo() {} | ^^^^^^^^ - = help: to disambiguate the method call, write `Trait1::foo(...)` instead note: candidate #2 is defined in an impl of the trait `Trait2` for the type `Test` --> $DIR/E0034.rs:16:5 | LL | fn foo() {} | ^^^^^^^^ - = help: to disambiguate the method call, write `Trait2::foo(...)` instead +help: disambiguate the method call for candidate #1 + | +LL | Trait1::foo() + | ^^^^^^^^^^^ +help: disambiguate the method call for candidate #2 + | +LL | Trait2::foo() + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/inference/inference_unstable_featured.stderr b/src/test/ui/inference/inference_unstable_featured.stderr index b06a6298a571c..fa908440e41ea 100644 --- a/src/test/ui/inference/inference_unstable_featured.stderr +++ b/src/test/ui/inference/inference_unstable_featured.stderr @@ -5,9 +5,15 @@ LL | assert_eq!('x'.ipu_flatten(), 0); | ^^^^^^^^^^^ multiple `ipu_flatten` found | = note: candidate #1 is defined in an impl of the trait `inference_unstable_iterator::IpuIterator` for the type `char` - = help: to disambiguate the method call, write `inference_unstable_iterator::IpuIterator::ipu_flatten('x')` instead = note: candidate #2 is defined in an impl of the trait `inference_unstable_itertools::IpuItertools` for the type `char` - = help: to disambiguate the method call, write `inference_unstable_itertools::IpuItertools::ipu_flatten('x')` instead +help: disambiguate the method call for candidate #1 + | +LL | assert_eq!(inference_unstable_iterator::IpuIterator::ipu_flatten(&'x'), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: disambiguate the method call for candidate #2 + | +LL | assert_eq!(inference_unstable_itertools::IpuItertools::ipu_flatten(&'x'), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-18446.stderr b/src/test/ui/issues/issue-18446.stderr index e6afc4c13a912..3422add9dd96b 100644 --- a/src/test/ui/issues/issue-18446.stderr +++ b/src/test/ui/issues/issue-18446.stderr @@ -2,7 +2,10 @@ error[E0034]: multiple applicable items in scope --> $DIR/issue-18446.rs:18:7 | LL | x.foo(); - | ^^^ multiple `foo` found + | --^^^-- + | | | + | | multiple `foo` found + | help: disambiguate the method call for candidate #2: `T::foo(&x)` | note: candidate #1 is defined in an impl for the type `dyn T` --> $DIR/issue-18446.rs:9:5 @@ -14,7 +17,6 @@ note: candidate #2 is defined in the trait `T` | LL | fn foo(&self); | ^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `T::foo(&x)` instead error: aborting due to previous error diff --git a/src/test/ui/issues/issue-3702-2.stderr b/src/test/ui/issues/issue-3702-2.stderr index 4d0ff750c254c..b18e407c3d464 100644 --- a/src/test/ui/issues/issue-3702-2.stderr +++ b/src/test/ui/issues/issue-3702-2.stderr @@ -9,13 +9,19 @@ note: candidate #1 is defined in an impl of the trait `ToPrimitive` for the type | LL | fn to_int(&self) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `ToPrimitive::to_int(&self)` instead note: candidate #2 is defined in an impl of the trait `Add` for the type `isize` --> $DIR/issue-3702-2.rs:14:5 | LL | fn to_int(&self) -> isize { *self } | ^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `Add::to_int(&self)` instead +help: disambiguate the method call for candidate #1 + | +LL | ToPrimitive::to_int(&self) + other.to_int() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: disambiguate the method call for candidate #2 + | +LL | Add::to_int(&self) + other.to_int() + | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-65634-raw-ident-suggestion.stderr b/src/test/ui/issues/issue-65634-raw-ident-suggestion.stderr index c7bb653dc1f14..feaf3dc753ffb 100644 --- a/src/test/ui/issues/issue-65634-raw-ident-suggestion.stderr +++ b/src/test/ui/issues/issue-65634-raw-ident-suggestion.stderr @@ -9,13 +9,19 @@ note: candidate #1 is defined in an impl of the trait `async` for the type `r#fn | LL | fn r#struct(&self) { | ^^^^^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `async::r#struct(r#fn {})` instead note: candidate #2 is defined in an impl of the trait `await` for the type `r#fn` --> $DIR/issue-65634-raw-ident-suggestion.rs:10:5 | LL | fn r#struct(&self) { | ^^^^^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `await::r#struct(r#fn {})` instead +help: disambiguate the method call for candidate #1 + | +LL | async::r#struct(&r#fn {}); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: disambiguate the method call for candidate #2 + | +LL | await::r#struct(&r#fn {}); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/lint/lint-unused-mut-variables.rs b/src/test/ui/lint/lint-unused-mut-variables.rs index 1af44ecf362bf..dd8dbda6d4303 100644 --- a/src/test/ui/lint/lint-unused-mut-variables.rs +++ b/src/test/ui/lint/lint-unused-mut-variables.rs @@ -3,7 +3,7 @@ // Exercise the unused_mut attribute in some positive and negative cases #![deny(unused_mut)] -#![feature(async_closure)] +#![feature(async_closure, raw_ref_op)] async fn baz_async( mut a: i32, @@ -177,6 +177,12 @@ fn main() { // leading underscore should avoid the warning, just like the // unused variable lint. let mut _allowed = 1; + + let mut raw_address_of_mut = 1; // OK + let mut_ptr = &raw mut raw_address_of_mut; + + let mut raw_address_of_const = 1; //~ ERROR: variable does not need to be mutable + let const_ptr = &raw const raw_address_of_const; } fn callback(f: F) where F: FnOnce() {} diff --git a/src/test/ui/lint/lint-unused-mut-variables.stderr b/src/test/ui/lint/lint-unused-mut-variables.stderr index 92c2b68652dc2..c1ab0ab33d4cc 100644 --- a/src/test/ui/lint/lint-unused-mut-variables.stderr +++ b/src/test/ui/lint/lint-unused-mut-variables.stderr @@ -180,6 +180,14 @@ LL | let mut v : &mut Vec<()> = &mut vec![]; | | | help: remove this `mut` +error: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:184:9 + | +LL | let mut raw_address_of_const = 1; + | ----^^^^^^^^^^^^^^^^^^^^ + | | + | help: remove this `mut` + error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:106:13 | @@ -197,7 +205,7 @@ LL | fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] { | help: remove this `mut` error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:196:9 + --> $DIR/lint-unused-mut-variables.rs:202:9 | LL | let mut b = vec![2]; | ----^ @@ -205,10 +213,10 @@ LL | let mut b = vec![2]; | help: remove this `mut` | note: lint level defined here - --> $DIR/lint-unused-mut-variables.rs:192:8 + --> $DIR/lint-unused-mut-variables.rs:198:8 | LL | #[deny(unused_mut)] | ^^^^^^^^^^ -error: aborting due to 25 previous errors +error: aborting due to 26 previous errors diff --git a/src/test/ui/methods/method-ambig-two-traits-cross-crate.stderr b/src/test/ui/methods/method-ambig-two-traits-cross-crate.stderr index 9f46a722a508e..fa3add81a28f5 100644 --- a/src/test/ui/methods/method-ambig-two-traits-cross-crate.stderr +++ b/src/test/ui/methods/method-ambig-two-traits-cross-crate.stderr @@ -9,9 +9,15 @@ note: candidate #1 is defined in an impl of the trait `Me2` for the type `usize` | LL | impl Me2 for usize { fn me(&self) -> usize { *self } } | ^^^^^^^^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `Me2::me(1_usize)` instead = note: candidate #2 is defined in an impl of the trait `ambig_impl_2_lib::Me` for the type `usize` - = help: to disambiguate the method call, write `ambig_impl_2_lib::Me::me(1_usize)` instead +help: disambiguate the method call for candidate #1 + | +LL | fn main() { Me2::me(&1_usize); } + | ^^^^^^^^^^^^^^^^^ +help: disambiguate the method call for candidate #2 + | +LL | fn main() { ambig_impl_2_lib::Me::me(&1_usize); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/methods/method-ambig-two-traits-from-bounds.stderr b/src/test/ui/methods/method-ambig-two-traits-from-bounds.stderr index 6c493c67e29d9..b6c81c2377ee4 100644 --- a/src/test/ui/methods/method-ambig-two-traits-from-bounds.stderr +++ b/src/test/ui/methods/method-ambig-two-traits-from-bounds.stderr @@ -9,13 +9,19 @@ note: candidate #1 is defined in the trait `A` | LL | trait A { fn foo(&self); } | ^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `A::foo(t)` instead note: candidate #2 is defined in the trait `B` --> $DIR/method-ambig-two-traits-from-bounds.rs:2:11 | LL | trait B { fn foo(&self); } | ^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `B::foo(t)` instead +help: disambiguate the method call for candidate #1 + | +LL | A::foo(t); + | ^^^^^^^^^ +help: disambiguate the method call for candidate #2 + | +LL | B::foo(t); + | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/methods/method-ambig-two-traits-from-impls.stderr b/src/test/ui/methods/method-ambig-two-traits-from-impls.stderr index 0b3724e030fa4..71c65f7ccc68d 100644 --- a/src/test/ui/methods/method-ambig-two-traits-from-impls.stderr +++ b/src/test/ui/methods/method-ambig-two-traits-from-impls.stderr @@ -9,13 +9,19 @@ note: candidate #1 is defined in an impl of the trait `A` for the type `AB` | LL | fn foo(self) {} | ^^^^^^^^^^^^ - = help: to disambiguate the method call, write `A::foo(AB {})` instead note: candidate #2 is defined in an impl of the trait `B` for the type `AB` --> $DIR/method-ambig-two-traits-from-impls.rs:11:5 | LL | fn foo(self) {} | ^^^^^^^^^^^^ - = help: to disambiguate the method call, write `B::foo(AB {})` instead +help: disambiguate the method call for candidate #1 + | +LL | A::foo(AB {}); + | ^^^^^^^^^^^^^ +help: disambiguate the method call for candidate #2 + | +LL | B::foo(AB {}); + | ^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr b/src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr index 81c99b33c813e..44f85071505d2 100644 --- a/src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr +++ b/src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr @@ -9,13 +9,19 @@ note: candidate #1 is defined in an impl of the trait `A` for the type `AB` | LL | fn foo() {} | ^^^^^^^^ - = help: to disambiguate the method call, write `A::foo(...)` instead note: candidate #2 is defined in an impl of the trait `B` for the type `AB` --> $DIR/method-ambig-two-traits-from-impls2.rs:11:5 | LL | fn foo() {} | ^^^^^^^^ - = help: to disambiguate the method call, write `B::foo(...)` instead +help: disambiguate the method call for candidate #1 + | +LL | A::foo(); + | ^^^^^^ +help: disambiguate the method call for candidate #2 + | +LL | B::foo(); + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/methods/method-ambig-two-traits-with-default-method.stderr b/src/test/ui/methods/method-ambig-two-traits-with-default-method.stderr index dc8aef2503739..3dbb17371004a 100644 --- a/src/test/ui/methods/method-ambig-two-traits-with-default-method.stderr +++ b/src/test/ui/methods/method-ambig-two-traits-with-default-method.stderr @@ -9,13 +9,19 @@ note: candidate #1 is defined in an impl of the trait `Foo` for the type `usize` | LL | trait Foo { fn method(&self) {} } | ^^^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `Foo::method(1_usize)` instead note: candidate #2 is defined in an impl of the trait `Bar` for the type `usize` --> $DIR/method-ambig-two-traits-with-default-method.rs:6:13 | LL | trait Bar { fn method(&self) {} } | ^^^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `Bar::method(1_usize)` instead +help: disambiguate the method call for candidate #1 + | +LL | Foo::method(&1_usize); + | ^^^^^^^^^^^^^^^^^^^^^ +help: disambiguate the method call for candidate #2 + | +LL | Bar::method(&1_usize); + | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr index c9d7da84e09f4..e7f295df8c482 100644 --- a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr +++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr @@ -25,19 +25,28 @@ note: candidate #1 is defined in an impl of the trait `internal::X` for the type | LL | fn foo(self: Smaht) -> u64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `internal::X::foo(x)` instead note: candidate #2 is defined in an impl of the trait `nuisance_foo::NuisanceFoo` for the type `_` --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:70:9 | LL | fn foo(self) {} | ^^^^^^^^^^^^ - = help: to disambiguate the method call, write `nuisance_foo::NuisanceFoo::foo(x)` instead note: candidate #3 is defined in the trait `FinalFoo` --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:57:5 | LL | fn foo(&self) -> u8; | ^^^^^^^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `FinalFoo::foo(x)` instead +help: disambiguate the method call for candidate #1 + | +LL | let z = internal::X::foo(x); + | ^^^^^^^^^^^^^^^^^^^ +help: disambiguate the method call for candidate #2 + | +LL | let z = nuisance_foo::NuisanceFoo::foo(x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: disambiguate the method call for candidate #3 + | +LL | let z = FinalFoo::foo(x); + | ^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:137:24 diff --git a/src/test/ui/packed/packed-struct-address-of-element.rs b/src/test/ui/packed/packed-struct-address-of-element.rs new file mode 100644 index 0000000000000..812d23fb58023 --- /dev/null +++ b/src/test/ui/packed/packed-struct-address-of-element.rs @@ -0,0 +1,37 @@ +// run-pass +#![allow(dead_code)] +#![deny(safe_packed_borrows)] +#![feature(raw_ref_op)] +// ignore-emscripten weird assertion? + +#[repr(packed)] +struct Foo1 { + bar: u8, + baz: usize +} + +#[repr(packed(2))] +struct Foo2 { + bar: u8, + baz: usize +} + +#[repr(C, packed(4))] +struct Foo4C { + bar: u8, + baz: usize +} + +pub fn main() { + let foo = Foo1 { bar: 1, baz: 2 }; + let brw = &raw const foo.baz; + unsafe { assert_eq!(brw.read_unaligned(), 2); } + + let foo = Foo2 { bar: 1, baz: 2 }; + let brw = &raw const foo.baz; + unsafe { assert_eq!(brw.read_unaligned(), 2); } + + let mut foo = Foo4C { bar: 1, baz: 2 }; + let brw = &raw mut foo.baz; + unsafe { assert_eq!(brw.read_unaligned(), 2); } +} diff --git a/src/test/ui/packed/packed-struct-borrow-element.rs b/src/test/ui/packed/packed-struct-borrow-element.rs index 6ac42ed0d471b..0072b6191ebb0 100644 --- a/src/test/ui/packed/packed-struct-borrow-element.rs +++ b/src/test/ui/packed/packed-struct-borrow-element.rs @@ -1,4 +1,4 @@ -// run-pass +// run-pass (note: this is spec-UB, but it works for now) #![allow(dead_code)] // ignore-emscripten weird assertion? diff --git a/src/test/ui/raw-ref-op/raw-ref-op.rs b/src/test/ui/raw-ref-op/raw-ref-op.rs index de847909eb371..0c6e23a00d525 100644 --- a/src/test/ui/raw-ref-op/raw-ref-op.rs +++ b/src/test/ui/raw-ref-op/raw-ref-op.rs @@ -1,11 +1,11 @@ -// FIXME(#64490): make this run-pass +// run-pass #![feature(raw_ref_op)] fn main() { let mut x = 123; - let c_p = &raw const x; //~ ERROR not yet implemented - let m_p = &raw mut x; //~ ERROR not yet implemented + let c_p = &raw const x; + let m_p = &raw mut x; let i_r = &x; assert!(c_p == i_r); assert!(c_p == m_p); diff --git a/src/test/ui/raw-ref-op/raw-ref-op.stderr b/src/test/ui/raw-ref-op/raw-ref-op.stderr deleted file mode 100644 index 04c59c95fca1e..0000000000000 --- a/src/test/ui/raw-ref-op/raw-ref-op.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: raw borrows are not yet implemented - --> $DIR/raw-ref-op.rs:7:15 - | -LL | let c_p = &raw const x; - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-op.rs:8:15 - | -LL | let m_p = &raw mut x; - | ^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs b/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs index d251586de5595..a814003aebf20 100644 --- a/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs +++ b/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs @@ -1,4 +1,4 @@ -// FIXME(#64490) This should be check-pass +// check-pass // Check that taking the address of a place that contains a dereference is // allowed. #![feature(raw_ref_op, type_ascription)] @@ -10,15 +10,15 @@ const SLICE_REF: &[i32] = &[5, 6]; fn main() { // These are all OK, we're not taking the address of the temporary - let deref_ref = &raw const *PAIR_REF; //~ ERROR not yet implemented - let field_deref_ref = &raw const PAIR_REF.0; //~ ERROR not yet implemented - let deref_ref = &raw const *ARRAY_REF; //~ ERROR not yet implemented - let index_deref_ref = &raw const ARRAY_REF[0]; //~ ERROR not yet implemented - let deref_ref = &raw const *SLICE_REF; //~ ERROR not yet implemented - let index_deref_ref = &raw const SLICE_REF[1]; //~ ERROR not yet implemented + let deref_ref = &raw const *PAIR_REF; + let field_deref_ref = &raw const PAIR_REF.0; + let deref_ref = &raw const *ARRAY_REF; + let index_deref_ref = &raw const ARRAY_REF[0]; + let deref_ref = &raw const *SLICE_REF; + let index_deref_ref = &raw const SLICE_REF[1]; let x = 0; - let ascribe_ref = &raw const (x: i32); //~ ERROR not yet implemented - let ascribe_deref = &raw const (*ARRAY_REF: [i32; 2]); //~ ERROR not yet implemented - let ascribe_index_deref = &raw const (ARRAY_REF[0]: i32); //~ ERROR not yet implemented + let ascribe_ref = &raw const (x: i32); + let ascribe_deref = &raw const (*ARRAY_REF: [i32; 2]); + let ascribe_index_deref = &raw const (ARRAY_REF[0]: i32); } diff --git a/src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr b/src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr deleted file mode 100644 index b0bfc74903b0c..0000000000000 --- a/src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr +++ /dev/null @@ -1,74 +0,0 @@ -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:13:21 - | -LL | let deref_ref = &raw const *PAIR_REF; - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:14:27 - | -LL | let field_deref_ref = &raw const PAIR_REF.0; - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:15:21 - | -LL | let deref_ref = &raw const *ARRAY_REF; - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:16:27 - | -LL | let index_deref_ref = &raw const ARRAY_REF[0]; - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:17:21 - | -LL | let deref_ref = &raw const *SLICE_REF; - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:18:27 - | -LL | let index_deref_ref = &raw const SLICE_REF[1]; - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:21:23 - | -LL | let ascribe_ref = &raw const (x: i32); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:22:25 - | -LL | let ascribe_deref = &raw const (*ARRAY_REF: [i32; 2]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:23:31 - | -LL | let ascribe_index_deref = &raw const (ARRAY_REF[0]: i32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: aborting due to 9 previous errors - diff --git a/src/test/ui/raw-ref-op/raw-ref-temp.rs b/src/test/ui/raw-ref-op/raw-ref-temp.rs index ac2445f049c66..32df56468da17 100644 --- a/src/test/ui/raw-ref-op/raw-ref-temp.rs +++ b/src/test/ui/raw-ref-op/raw-ref-temp.rs @@ -1,6 +1,8 @@ // Ensure that we don't allow taking the address of temporary values #![feature(raw_ref_op, type_ascription)] +const FOUR: u64 = 4; + const PAIR: (i32, i64) = (1, 2); const ARRAY: [i32; 2] = [1, 2]; @@ -8,8 +10,8 @@ const ARRAY: [i32; 2] = [1, 2]; fn main() { let ref_expr = &raw const 2; //~ ERROR cannot take address let mut_ref_expr = &raw mut 3; //~ ERROR cannot take address - let ref_const = &raw const 4; //~ ERROR cannot take address - let mut_ref_const = &raw mut 5; //~ ERROR cannot take address + let ref_const = &raw const FOUR; //~ ERROR cannot take address + let mut_ref_const = &raw mut FOUR; //~ ERROR cannot take address let field_ref_expr = &raw const (1, 2).0; //~ ERROR cannot take address let mut_field_ref_expr = &raw mut (1, 2).0; //~ ERROR cannot take address diff --git a/src/test/ui/raw-ref-op/raw-ref-temp.stderr b/src/test/ui/raw-ref-op/raw-ref-temp.stderr index de07073373506..80dea76d5953b 100644 --- a/src/test/ui/raw-ref-op/raw-ref-temp.stderr +++ b/src/test/ui/raw-ref-op/raw-ref-temp.stderr @@ -1,95 +1,95 @@ error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:9:31 + --> $DIR/raw-ref-temp.rs:11:31 | LL | let ref_expr = &raw const 2; | ^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:10:33 + --> $DIR/raw-ref-temp.rs:12:33 | LL | let mut_ref_expr = &raw mut 3; | ^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:11:32 + --> $DIR/raw-ref-temp.rs:13:32 | -LL | let ref_const = &raw const 4; - | ^ temporary value +LL | let ref_const = &raw const FOUR; + | ^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:12:34 + --> $DIR/raw-ref-temp.rs:14:34 | -LL | let mut_ref_const = &raw mut 5; - | ^ temporary value +LL | let mut_ref_const = &raw mut FOUR; + | ^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:14:37 + --> $DIR/raw-ref-temp.rs:16:37 | LL | let field_ref_expr = &raw const (1, 2).0; | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:15:39 + --> $DIR/raw-ref-temp.rs:17:39 | LL | let mut_field_ref_expr = &raw mut (1, 2).0; | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:16:32 + --> $DIR/raw-ref-temp.rs:18:32 | LL | let field_ref = &raw const PAIR.0; | ^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:17:34 + --> $DIR/raw-ref-temp.rs:19:34 | LL | let mut_field_ref = &raw mut PAIR.0; | ^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:19:37 + --> $DIR/raw-ref-temp.rs:21:37 | LL | let index_ref_expr = &raw const [1, 2][0]; | ^^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:20:39 + --> $DIR/raw-ref-temp.rs:22:39 | LL | let mut_index_ref_expr = &raw mut [1, 2][0]; | ^^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:21:32 + --> $DIR/raw-ref-temp.rs:23:32 | LL | let index_ref = &raw const ARRAY[0]; | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:22:34 + --> $DIR/raw-ref-temp.rs:24:34 | LL | let mut_index_ref = &raw mut ARRAY[1]; | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:24:34 + --> $DIR/raw-ref-temp.rs:26:34 | LL | let ref_ascribe = &raw const (2: i32); | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:25:36 + --> $DIR/raw-ref-temp.rs:27:36 | LL | let mut_ref_ascribe = &raw mut (3: i32); | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:27:40 + --> $DIR/raw-ref-temp.rs:29:40 | LL | let ascribe_field_ref = &raw const (PAIR.0: i32); | ^^^^^^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:28:38 + --> $DIR/raw-ref-temp.rs:30:38 | LL | let ascribe_index_ref = &raw mut (ARRAY[0]: i32); | ^^^^^^^^^^^^^^^ temporary value diff --git a/src/test/ui/raw-ref-op/unusual_locations.rs b/src/test/ui/raw-ref-op/unusual_locations.rs index f0a6bcce2ac8a..6bf37408a8bbd 100644 --- a/src/test/ui/raw-ref-op/unusual_locations.rs +++ b/src/test/ui/raw-ref-op/unusual_locations.rs @@ -1,25 +1,22 @@ -// FIXME(#64490): make this check-pass +// check-pass #![feature(raw_ref_op)] -const USES_PTR: () = { let u = (); &raw const u; }; //~ ERROR not yet implemented -static ALSO_USES_PTR: () = { let u = (); &raw const u; }; //~ ERROR not yet implemented +const USES_PTR: () = { let u = (); &raw const u; }; +static ALSO_USES_PTR: () = { let u = (); &raw const u; }; fn main() { - #[cfg(FALSE)] - { - let x: [i32; { let u = 2; let x = &raw const u; 4 }] - = [2; { let v = 3; let y = &raw const v; 4 }]; - let mut one = 1; - let two = 2; - if &raw const one == &raw mut one { - match &raw const two { - _ => {} - } + let x: [i32; { let u = 2; let x = &raw const u; 4 }] + = [2; { let v = 3; let y = &raw const v; 4 }]; + let mut one = 1; + let two = 2; + if &raw const one == &raw mut one { + match &raw const two { + _ => {} } - let three = 3; - let mut four = 4; - println!("{:p}", &raw const three); - unsafe { &raw mut four; } } + let three = 3; + let mut four = 4; + println!("{:p}", &raw const three); + unsafe { &raw mut four; } } diff --git a/src/test/ui/raw-ref-op/unusual_locations.stderr b/src/test/ui/raw-ref-op/unusual_locations.stderr deleted file mode 100644 index 3fae5db3d51a1..0000000000000 --- a/src/test/ui/raw-ref-op/unusual_locations.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: raw borrows are not yet implemented - --> $DIR/unusual_locations.rs:5:36 - | -LL | const USES_PTR: () = { let u = (); &raw const u; }; - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/unusual_locations.rs:6:42 - | -LL | static ALSO_USES_PTR: () = { let u = (); &raw const u; }; - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/span/issue-37767.stderr b/src/test/ui/span/issue-37767.stderr index 0bbff45436c23..9ed6c8b826f79 100644 --- a/src/test/ui/span/issue-37767.stderr +++ b/src/test/ui/span/issue-37767.stderr @@ -9,13 +9,19 @@ note: candidate #1 is defined in the trait `A` | LL | fn foo(&mut self) {} | ^^^^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `A::foo(&a)` instead note: candidate #2 is defined in the trait `B` --> $DIR/issue-37767.rs:6:5 | LL | fn foo(&mut self) {} | ^^^^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `B::foo(&a)` instead +help: disambiguate the method call for candidate #1 + | +LL | A::foo(&a) + | ^^^^^^^^^^ +help: disambiguate the method call for candidate #2 + | +LL | B::foo(&a) + | ^^^^^^^^^^ error[E0034]: multiple applicable items in scope --> $DIR/issue-37767.rs:22:7 @@ -28,13 +34,19 @@ note: candidate #1 is defined in the trait `C` | LL | fn foo(&self) {} | ^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `C::foo(&a)` instead note: candidate #2 is defined in the trait `D` --> $DIR/issue-37767.rs:18:5 | LL | fn foo(&self) {} | ^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `D::foo(&a)` instead +help: disambiguate the method call for candidate #1 + | +LL | C::foo(&a) + | ^^^^^^^^^^ +help: disambiguate the method call for candidate #2 + | +LL | D::foo(&a) + | ^^^^^^^^^^ error[E0034]: multiple applicable items in scope --> $DIR/issue-37767.rs:34:7 @@ -47,13 +59,19 @@ note: candidate #1 is defined in the trait `E` | LL | fn foo(self) {} | ^^^^^^^^^^^^ - = help: to disambiguate the method call, write `E::foo(a)` instead note: candidate #2 is defined in the trait `F` --> $DIR/issue-37767.rs:30:5 | LL | fn foo(self) {} | ^^^^^^^^^^^^ - = help: to disambiguate the method call, write `F::foo(a)` instead +help: disambiguate the method call for candidate #1 + | +LL | E::foo(a) + | ^^^^^^^^^ +help: disambiguate the method call for candidate #2 + | +LL | F::foo(a) + | ^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr index 36db5bea86294..53a6238422b57 100644 --- a/src/test/ui/span/issue-7575.stderr +++ b/src/test/ui/span/issue-7575.stderr @@ -10,24 +10,33 @@ note: candidate #1 is defined in the trait `CtxtFn` | LL | fn f9(_: usize) -> usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `CtxtFn::f9(u, 342)` instead note: candidate #2 is defined in the trait `OtherTrait` --> $DIR/issue-7575.rs:8:5 | LL | fn f9(_: usize) -> usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `OtherTrait::f9(u, 342)` instead note: candidate #3 is defined in the trait `UnusedTrait` --> $DIR/issue-7575.rs:17:5 | LL | fn f9(_: usize) -> usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `UnusedTrait::f9(u, 342)` instead = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `f9`, perhaps you need to implement one of them: candidate #1: `CtxtFn` candidate #2: `OtherTrait` candidate #3: `UnusedTrait` +help: disambiguate the method call for candidate #1 + | +LL | u.f8(42) + CtxtFn::f9(u, 342) + m.fff(42) + | ^^^^^^^^^^^^^^^^^^ +help: disambiguate the method call for candidate #2 + | +LL | u.f8(42) + OtherTrait::f9(u, 342) + m.fff(42) + | ^^^^^^^^^^^^^^^^^^^^^^ +help: disambiguate the method call for candidate #3 + | +LL | u.f8(42) + UnusedTrait::f9(u, 342) + m.fff(42) + | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0599]: no method named `fff` found for type `Myisize` in the current scope --> $DIR/issue-7575.rs:62:30 @@ -60,8 +69,11 @@ note: the candidate is defined in the trait `ManyImplTrait` | LL | fn is_str() -> bool { | ^^^^^^^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `ManyImplTrait::is_str(t)` instead = help: items from traits can only be used if the type parameter is bounded by the trait +help: disambiguate the method call for the candidate + | +LL | ManyImplTrait::is_str(t) + | help: the following trait defines an item `is_str`, perhaps you need to restrict type parameter `T` with it: | LL | fn param_bound(t: T) -> bool { diff --git a/src/test/ui/traits/cycle-cache-err-60010.rs b/src/test/ui/traits/cycle-cache-err-60010.rs index ebed4a02d0f33..cbddef082be67 100644 --- a/src/test/ui/traits/cycle-cache-err-60010.rs +++ b/src/test/ui/traits/cycle-cache-err-60010.rs @@ -28,7 +28,7 @@ struct SalsaStorage { } impl Database for RootDatabase { - type Storage = SalsaStorage; + type Storage = SalsaStorage; //~ ERROR overflow } impl HasQueryGroup for RootDatabase {} impl Query for ParseQuery diff --git a/src/test/ui/traits/cycle-cache-err-60010.stderr b/src/test/ui/traits/cycle-cache-err-60010.stderr index 2fc26bb11e3e3..295845b1146ef 100644 --- a/src/test/ui/traits/cycle-cache-err-60010.stderr +++ b/src/test/ui/traits/cycle-cache-err-60010.stderr @@ -6,6 +6,22 @@ LL | _parse: >::Data, | = note: required because of the requirements on the impl of `Query` for `ParseQuery` -error: aborting due to previous error +error[E0275]: overflow evaluating the requirement `Runtime: std::panic::RefUnwindSafe` + --> $DIR/cycle-cache-err-60010.rs:31:5 + | +LL | type Storage; + | ------- associated type defined here +... +LL | impl Database for RootDatabase { + | ------------------------------ in this `impl` item +LL | type Storage = SalsaStorage; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: required because it appears within the type `RootDatabase` + = note: required because of the requirements on the impl of `SourceDatabase` for `RootDatabase` + = note: required because of the requirements on the impl of `Query` for `ParseQuery` + = note: required because it appears within the type `SalsaStorage` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/traits/trait-alias-ambiguous.stderr b/src/test/ui/traits/trait-alias-ambiguous.stderr index cde7dd0824924..48a029104aeca 100644 --- a/src/test/ui/traits/trait-alias-ambiguous.stderr +++ b/src/test/ui/traits/trait-alias-ambiguous.stderr @@ -9,13 +9,19 @@ note: candidate #1 is defined in an impl of the trait `inner::A` for the type `u | LL | fn foo(&self) {} | ^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `inner::A::foo(t)` instead note: candidate #2 is defined in an impl of the trait `inner::B` for the type `u8` --> $DIR/trait-alias-ambiguous.rs:11:9 | LL | fn foo(&self) {} | ^^^^^^^^^^^^^ - = help: to disambiguate the method call, write `inner::B::foo(t)` instead +help: disambiguate the method call for candidate #1 + | +LL | inner::A::foo(&t); + | ^^^^^^^^^^^^^^^^^ +help: disambiguate the method call for candidate #2 + | +LL | inner::B::foo(&t); + | ^^^^^^^^^^^^^^^^^ error: aborting due to previous error