diff --git a/compiler/rustc_builtin_macros/src/compile_error.rs b/compiler/rustc_builtin_macros/src/compile_error.rs index 990b88295690c..72397aa2500f9 100644 --- a/compiler/rustc_builtin_macros/src/compile_error.rs +++ b/compiler/rustc_builtin_macros/src/compile_error.rs @@ -13,7 +13,7 @@ pub fn expand_compile_error<'cx>( return DummyResult::any(sp); }; - cx.span_err(sp, &var); + cx.span_err(sp, var.as_str()); DummyResult::any(sp) } diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs index 66ee93ce3c90e..b8828fa671a5d 100644 --- a/compiler/rustc_builtin_macros/src/env.rs +++ b/compiler/rustc_builtin_macros/src/env.rs @@ -21,8 +21,8 @@ pub fn expand_option_env<'cx>( }; let sp = cx.with_def_site_ctxt(sp); - let value = env::var(&var.as_str()).ok().as_deref().map(Symbol::intern); - cx.sess.parse_sess.env_depinfo.borrow_mut().insert((Symbol::intern(&var), value)); + let value = env::var(var.as_str()).ok().as_deref().map(Symbol::intern); + cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value)); let e = match value { None => { let lt = cx.lifetime(sp, Ident::new(kw::StaticLifetime, sp)); diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index ece250f61d54f..2817fce463b91 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -104,7 +104,7 @@ pub fn expand_include<'cx>( return DummyResult::any(sp); }; // The file will be added to the code map by the parser - let file = match resolve_path(cx, file, sp) { + let file = match resolve_path(cx, file.as_str(), sp) { Ok(f) => f, Err(mut err) => { err.emit(); @@ -176,7 +176,7 @@ pub fn expand_include_str( let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_str!") else { return DummyResult::any(sp); }; - let file = match resolve_path(cx, file, sp) { + let file = match resolve_path(cx, file.as_str(), sp) { Ok(f) => f, Err(mut err) => { err.emit(); @@ -210,7 +210,7 @@ pub fn expand_include_bytes( let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_bytes!") else { return DummyResult::any(sp); }; - let file = match resolve_path(cx, file, sp) { + let file = match resolve_path(cx, file.as_str(), sp) { Ok(f) => f, Err(mut err) => { err.emit(); diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index 6c22296db716d..7f15bc75fda23 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -288,8 +288,8 @@ fn load_imported_symbols_for_jit( match data[cnum.as_usize() - 1] { Linkage::NotLinked | Linkage::IncludedFromDylib => {} Linkage::Static => { - let name = &crate_info.crate_name[&cnum]; - let mut err = sess.struct_err(&format!("Can't load static lib {}", name.as_str())); + let name = crate_info.crate_name[&cnum]; + let mut err = sess.struct_err(&format!("Can't load static lib {}", name)); err.note("rustc_codegen_cranelift can only load dylibs in JIT mode."); err.emit(); } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index a727da0570449..cf32d558d4a51 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -216,7 +216,7 @@ pub fn each_linked_rlib( Some(_) => {} None => return Err("could not find formats for rlibs".to_string()), } - let name = &info.crate_name[&cnum]; + let name = info.crate_name[&cnum]; let used_crate_source = &info.used_crate_source[&cnum]; if let Some((path, _)) = &used_crate_source.rlib { f(cnum, &path); @@ -467,7 +467,7 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>( let mut all_native_libs = vec![]; let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| { - let name = &codegen_results.crate_info.crate_name[&cnum]; + let name = codegen_results.crate_info.crate_name[&cnum]; let native_libs = &codegen_results.crate_info.native_libraries[&cnum]; // Here when we include the rlib into our staticlib we need to make a diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 010560248054e..7933afb50e8ce 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -861,7 +861,7 @@ impl CrateInfo { for &cnum in crates.iter() { info.native_libraries .insert(cnum, tcx.native_libraries(cnum).iter().map(Into::into).collect()); - info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string()); + info.crate_name.insert(cnum, tcx.crate_name(cnum)); info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum).clone()); if tcx.is_compiler_builtins(cnum) { info.compiler_builtins = Some(cnum); diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index a2d60472ed9ed..5273b6cc83725 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -146,7 +146,7 @@ pub struct CrateInfo { pub profiler_runtime: Option, pub is_no_builtins: FxHashSet, pub native_libraries: FxHashMap>, - pub crate_name: FxHashMap, + pub crate_name: FxHashMap, pub used_libraries: Vec, pub used_crate_source: FxHashMap>, pub used_crates: Vec, diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index b856d1708abc9..498b2f1b081b3 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -167,17 +167,18 @@ pub(super) fn op_to_const<'tcx>( }, Immediate::ScalarPair(a, b) => { // We know `offset` is relative to the allocation, so we can use `into_parts`. - let (data, start) = match ecx.scalar_to_ptr(a.check_init().unwrap()).into_parts() { - (Some(alloc_id), offset) => { - (ecx.tcx.global_alloc(alloc_id).unwrap_memory(), offset.bytes()) - } - (None, _offset) => ( - ecx.tcx.intern_const_alloc(Allocation::from_bytes_byte_aligned_immutable( - b"" as &[u8], - )), - 0, - ), - }; + let (data, start) = + match ecx.scalar_to_ptr(a.check_init().unwrap()).unwrap().into_parts() { + (Some(alloc_id), offset) => { + (ecx.tcx.global_alloc(alloc_id).unwrap_memory(), offset.bytes()) + } + (None, _offset) => ( + ecx.tcx.intern_const_alloc( + Allocation::from_bytes_byte_aligned_immutable(b"" as &[u8]), + ), + 0, + ), + }; let len = b.to_machine_usize(ecx).unwrap(); let start = start.try_into().unwrap(); let len: usize = len.try_into().unwrap(); diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index c44e27fc4a098..d57504deeab90 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -197,8 +197,8 @@ impl interpret::MayLeak for ! { } impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { - fn guaranteed_eq(&mut self, a: Scalar, b: Scalar) -> bool { - match (a, b) { + fn guaranteed_eq(&mut self, a: Scalar, b: Scalar) -> InterpResult<'tcx, bool> { + Ok(match (a, b) { // Comparisons between integers are always known. (Scalar::Int { .. }, Scalar::Int { .. }) => a == b, // Equality with integers can never be known for sure. @@ -207,11 +207,11 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { // some things (like functions and vtables) do not have stable addresses // so we need to be careful around them (see e.g. #73722). (Scalar::Ptr(..), Scalar::Ptr(..)) => false, - } + }) } - fn guaranteed_ne(&mut self, a: Scalar, b: Scalar) -> bool { - match (a, b) { + fn guaranteed_ne(&mut self, a: Scalar, b: Scalar) -> InterpResult<'tcx, bool> { + Ok(match (a, b) { // Comparisons between integers are always known. (Scalar::Int(_), Scalar::Int(_)) => a != b, // Comparisons of abstract pointers with null pointers are known if the pointer @@ -219,13 +219,13 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { // Inequality with integers other than null can never be known for sure. (Scalar::Int(int), ptr @ Scalar::Ptr(..)) | (ptr @ Scalar::Ptr(..), Scalar::Int(int)) => { - int.is_null() && !self.scalar_may_be_null(ptr) + int.is_null() && !self.scalar_may_be_null(ptr)? } // FIXME: return `true` for at least some comparisons where we can reliably // determine the result of runtime inequality tests at compile-time. // Examples include comparison of addresses in different static items. (Scalar::Ptr(..), Scalar::Ptr(..)) => false, - } + }) } } @@ -329,9 +329,9 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, let a = ecx.read_immediate(&args[0])?.to_scalar()?; let b = ecx.read_immediate(&args[1])?.to_scalar()?; let cmp = if intrinsic_name == sym::ptr_guaranteed_eq { - ecx.guaranteed_eq(a, b) + ecx.guaranteed_eq(a, b)? } else { - ecx.guaranteed_ne(a, b) + ecx.guaranteed_ne(a, b)? }; ecx.write_scalar(Scalar::from_bool(cmp), dest)?; } diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index a244b79ed0754..3ea3729dbcd17 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -283,7 +283,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if let Some(entry_idx) = vptr_entry_idx { let entry_idx = u64::try_from(entry_idx).unwrap(); let (old_data, old_vptr) = val.to_scalar_pair()?; - let old_vptr = self.scalar_to_ptr(old_vptr); + let old_vptr = self.scalar_to_ptr(old_vptr)?; let new_vptr = self .read_new_vtable_after_trait_upcasting_from_vtable(old_vptr, entry_idx)?; self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest) diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index a2ea0f516bfa4..f0fff602fe4cf 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -640,7 +640,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(Some((size, align))) } ty::Dynamic(..) => { - let vtable = self.scalar_to_ptr(metadata.unwrap_meta()); + let vtable = self.scalar_to_ptr(metadata.unwrap_meta())?; // Read size and align from vtable (already checks size). Ok(Some(self.read_size_and_align_from_vtable(vtable)?)) } diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index f1acb9e41c4ce..1fda60c021eed 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -202,7 +202,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory if let ty::Dynamic(..) = tcx.struct_tail_erasing_lifetimes(referenced_ty, self.ecx.param_env).kind() { - let ptr = self.ecx.scalar_to_ptr(mplace.meta.unwrap_meta()); + let ptr = self.ecx.scalar_to_ptr(mplace.meta.unwrap_meta())?; if let Some(alloc_id) = ptr.provenance { // Explicitly choose const mode here, since vtables are immutable, even // if the reference of the fat pointer is mutable. diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index a02115a110b7b..556a44a523819 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -1102,30 +1102,38 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Machine pointer introspection. impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { - pub fn scalar_to_ptr(&self, scalar: Scalar) -> Pointer> { + pub fn scalar_to_ptr( + &self, + scalar: Scalar, + ) -> InterpResult<'tcx, Pointer>> { // We use `to_bits_or_ptr_internal` since we are just implementing the method people need to // call to force getting out a pointer. - match scalar.to_bits_or_ptr_internal(self.pointer_size()) { - Err(ptr) => ptr.into(), - Ok(bits) => { - let addr = u64::try_from(bits).unwrap(); - let ptr = M::ptr_from_addr(&self, addr); - if addr == 0 { - assert!(ptr.provenance.is_none(), "null pointer can never have an AllocId"); + Ok( + match scalar + .to_bits_or_ptr_internal(self.pointer_size()) + .map_err(|s| err_ub!(ScalarSizeMismatch(s)))? + { + Err(ptr) => ptr.into(), + Ok(bits) => { + let addr = u64::try_from(bits).unwrap(); + let ptr = M::ptr_from_addr(&self, addr); + if addr == 0 { + assert!(ptr.provenance.is_none(), "null pointer can never have an AllocId"); + } + ptr } - ptr - } - } + }, + ) } /// Test if this value might be null. /// If the machine does not support ptr-to-int casts, this is conservative. - pub fn scalar_may_be_null(&self, scalar: Scalar) -> bool { - match scalar.try_to_int() { + pub fn scalar_may_be_null(&self, scalar: Scalar) -> InterpResult<'tcx, bool> { + Ok(match scalar.try_to_int() { Ok(int) => int.is_null(), Err(_) => { // Can only happen during CTFE. - let ptr = self.scalar_to_ptr(scalar); + let ptr = self.scalar_to_ptr(scalar)?; match self.ptr_try_get_alloc_id(ptr) { Ok((alloc_id, offset, _)) => { let (size, _align) = self @@ -1138,7 +1146,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Err(_offset) => bug!("a non-int scalar is always a pointer"), } } - } + }) } /// Turning a "maybe pointer" into a proper pointer (and some information diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index ee1ba60829316..dfc0028e87fcc 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -342,7 +342,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &self, op: &OpTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, Pointer>> { - Ok(self.scalar_to_ptr(self.read_scalar(op)?.check_init()?)) + self.scalar_to_ptr(self.read_scalar(op)?.check_init()?) } // Turn the wide MPlace into a string (must already be dereferenced!) @@ -738,7 +738,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // okay. Everything else, we conservatively reject. let ptr_valid = niche_start == 0 && variants_start == variants_end - && !self.scalar_may_be_null(tag_val); + && !self.scalar_may_be_null(tag_val)?; if !ptr_valid { throw_ub!(InvalidTag(dbg_val)) } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 5f7f52ef9e9f4..51d47af2f8e24 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -281,7 +281,7 @@ where }; let mplace = MemPlace { - ptr: self.scalar_to_ptr(ptr.check_init()?), + ptr: self.scalar_to_ptr(ptr.check_init()?)?, // We could use the run-time alignment here. For now, we do not, because // the point of tracking the alignment here is to make sure that the *static* // alignment information emitted with the loads is correct. The run-time @@ -1104,7 +1104,7 @@ where &self, mplace: &MPlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, (ty::Instance<'tcx>, MPlaceTy<'tcx, M::PointerTag>)> { - let vtable = self.scalar_to_ptr(mplace.vtable()); // also sanity checks the type + let vtable = self.scalar_to_ptr(mplace.vtable())?; // also sanity checks the type let (instance, ty) = self.read_drop_type_from_vtable(vtable)?; let layout = self.layout_of(ty)?; diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index c2a38c6978bfb..c2664565f15cb 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -519,7 +519,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .kind(), ty::Dynamic(..) )); - let vtable = self.scalar_to_ptr(receiver_place.meta.unwrap_meta()); + let vtable = self.scalar_to_ptr(receiver_place.meta.unwrap_meta())?; let fn_val = self.get_vtable_slot(vtable, u64::try_from(idx).unwrap())?; // `*mut receiver_place.layout.ty` is almost the layout that we diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs index 5cf3807faaa6d..235938422a893 100644 --- a/compiler/rustc_const_eval/src/interpret/traits.rs +++ b/compiler/rustc_const_eval/src/interpret/traits.rs @@ -50,7 +50,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let vtable_slot = self .get_ptr_alloc(vtable_slot, ptr_size, self.tcx.data_layout.pointer_align.abi)? .expect("cannot be a ZST"); - let fn_ptr = self.scalar_to_ptr(vtable_slot.read_ptr_sized(Size::ZERO)?.check_init()?); + let fn_ptr = self.scalar_to_ptr(vtable_slot.read_ptr_sized(Size::ZERO)?.check_init()?)?; self.get_ptr_fn(fn_ptr) } @@ -75,7 +75,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .check_init()?; // We *need* an instance here, no other kind of function value, to be able // to determine the type. - let drop_instance = self.get_ptr_fn(self.scalar_to_ptr(drop_fn))?.as_instance()?; + let drop_instance = self.get_ptr_fn(self.scalar_to_ptr(drop_fn)?)?.as_instance()?; trace!("Found drop fn: {:?}", drop_instance); let fn_sig = drop_instance.ty(*self.tcx, self.param_env).fn_sig(*self.tcx); let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig); @@ -132,7 +132,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .get_ptr_alloc(vtable_slot, pointer_size, self.tcx.data_layout.pointer_align.abi)? .expect("cannot be a ZST"); - let new_vtable = self.scalar_to_ptr(new_vtable.read_ptr_sized(Size::ZERO)?.check_init()?); + let new_vtable = + self.scalar_to_ptr(new_vtable.read_ptr_sized(Size::ZERO)?.check_init()?)?; Ok(new_vtable) } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 349806d997945..4a0aa41de739b 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -312,7 +312,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env); match tail.kind() { ty::Dynamic(..) => { - let vtable = self.ecx.scalar_to_ptr(meta.unwrap_meta()); + let vtable = self.ecx.scalar_to_ptr(meta.unwrap_meta())?; // Direct call to `check_ptr_access_align` checks alignment even on CTFE machines. try_validation!( self.ecx.check_ptr_access_align( @@ -577,7 +577,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // If we check references recursively, also check that this points to a function. if let Some(_) = self.ref_tracking { - let ptr = self.ecx.scalar_to_ptr(value); + let ptr = self.ecx.scalar_to_ptr(value)?; let _fn = try_validation!( self.ecx.get_ptr_fn(ptr), self.path, @@ -590,7 +590,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // FIXME: Check if the signature matches } else { // Otherwise (for standalone Miri), we have to still check it to be non-null. - if self.ecx.scalar_may_be_null(value) { + if self.ecx.scalar_may_be_null(value)? { throw_validation_failure!(self.path, { "a null function pointer" }); } } @@ -667,7 +667,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // We support 2 kinds of ranges here: full range, and excluding zero. if start == 1 && end == max_value { // Only null is the niche. So make sure the ptr is NOT null. - if self.ecx.scalar_may_be_null(value) { + if self.ecx.scalar_may_be_null(value)? { throw_validation_failure!(self.path, { "a potentially null pointer" } expected { diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 12b117d6fc9b4..3799623563f83 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1221,7 +1221,7 @@ pub fn get_single_str_from_tts( sp: Span, tts: TokenStream, name: &str, -) -> Option { +) -> Option { let mut p = cx.new_parser_from_tts(tts); if p.token == token::Eof { cx.span_err(sp, &format!("{} takes 1 argument", name)); @@ -1233,7 +1233,7 @@ pub fn get_single_str_from_tts( if p.token != token::Eof { cx.span_err(sp, &format!("{} takes 1 argument", name)); } - expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s.to_string()) + expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s) } /// Extracts comma-separated expressions from `tts`. diff --git a/compiler/rustc_incremental/src/assert_module_sources.rs b/compiler/rustc_incremental/src/assert_module_sources.rs index 4b235213f7f5c..7569abfbb10e5 100644 --- a/compiler/rustc_incremental/src/assert_module_sources.rs +++ b/compiler/rustc_incremental/src/assert_module_sources.rs @@ -22,12 +22,12 @@ //! was re-used. use rustc_ast as ast; +use rustc_data_structures::stable_set::FxHashSet; use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::mir::mono::CodegenUnitNameBuilder; use rustc_middle::ty::TyCtxt; use rustc_session::cgu_reuse_tracker::*; use rustc_span::symbol::{sym, Symbol}; -use std::collections::BTreeSet; #[allow(missing_docs)] pub fn assert_module_sources(tcx: TyCtxt<'_>) { @@ -36,12 +36,8 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>) { return; } - let available_cgus = tcx - .collect_and_partition_mono_items(()) - .1 - .iter() - .map(|cgu| cgu.name().to_string()) - .collect::>(); + let available_cgus = + tcx.collect_and_partition_mono_items(()).1.iter().map(|cgu| cgu.name()).collect(); let ams = AssertModuleSource { tcx, available_cgus }; @@ -53,7 +49,7 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>) { struct AssertModuleSource<'tcx> { tcx: TyCtxt<'tcx>, - available_cgus: BTreeSet, + available_cgus: FxHashSet, } impl<'tcx> AssertModuleSource<'tcx> { @@ -124,18 +120,17 @@ impl<'tcx> AssertModuleSource<'tcx> { debug!("mapping '{}' to cgu name '{}'", self.field(attr, sym::module), cgu_name); - if !self.available_cgus.contains(cgu_name.as_str()) { + if !self.available_cgus.contains(&cgu_name) { + let mut cgu_names: Vec<&str> = + self.available_cgus.iter().map(|cgu| cgu.as_str()).collect(); + cgu_names.sort(); self.tcx.sess.span_err( attr.span, &format!( "no module named `{}` (mangled: {}). Available modules: {}", user_path, cgu_name, - self.available_cgus - .iter() - .map(|cgu| cgu.to_string()) - .collect::>() - .join(", ") + cgu_names.join(", ") ), ); } diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_lifetime.rs index 98375cbad9f9b..bc50730ab8b83 100644 --- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs +++ b/compiler/rustc_middle/src/middle/resolve_lifetime.rs @@ -6,6 +6,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::ItemLocalId; use rustc_macros::HashStable; +use rustc_span::symbol::Symbol; #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)] pub enum Region { @@ -23,7 +24,7 @@ pub enum Region { pub enum LifetimeScopeForPath { // Contains all lifetime names that are in scope and could possibly be used in generics // arguments of path. - NonElided(Vec), + NonElided(Vec), // Information that allows us to suggest args of the form `<'_>` in case // no generic arguments were provided for a path. diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 63f2bc51aeeaa..438f356f072c6 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -15,8 +15,8 @@ use rustc_target::abi::{Align, HasDataLayout, Size}; use super::{ read_target_uint, write_target_uint, AllocId, InterpError, InterpResult, Pointer, Provenance, - ResourceExhaustionInfo, Scalar, ScalarMaybeUninit, UndefinedBehaviorInfo, UninitBytesAccess, - UnsupportedOpInfo, + ResourceExhaustionInfo, Scalar, ScalarMaybeUninit, ScalarSizeMismatch, UndefinedBehaviorInfo, + UninitBytesAccess, UnsupportedOpInfo, }; use crate::ty; @@ -81,6 +81,8 @@ impl<'tcx, Tag, Extra> ConstAllocation<'tcx, Tag, Extra> { /// is added when converting to `InterpError`. #[derive(Debug)] pub enum AllocError { + /// A scalar had the wrong size. + ScalarSizeMismatch(ScalarSizeMismatch), /// Encountered a pointer where we needed raw bytes. ReadPointerAsBytes, /// Partially overwriting a pointer. @@ -90,10 +92,19 @@ pub enum AllocError { } pub type AllocResult = Result; +impl From for AllocError { + fn from(s: ScalarSizeMismatch) -> Self { + AllocError::ScalarSizeMismatch(s) + } +} + impl AllocError { pub fn to_interp_error<'tcx>(self, alloc_id: AllocId) -> InterpError<'tcx> { use AllocError::*; match self { + ScalarSizeMismatch(s) => { + InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ScalarSizeMismatch(s)) + } ReadPointerAsBytes => InterpError::Unsupported(UnsupportedOpInfo::ReadPointerAsBytes), PartialPointerOverwrite(offset) => InterpError::Unsupported( UnsupportedOpInfo::PartialPointerOverwrite(Pointer::new(alloc_id, offset)), @@ -425,7 +436,7 @@ impl Allocation { // `to_bits_or_ptr_internal` is the right method because we just want to store this data // as-is into memory. - let (bytes, provenance) = match val.to_bits_or_ptr_internal(range.size) { + let (bytes, provenance) = match val.to_bits_or_ptr_internal(range.size)? { Err(val) => { let (provenance, offset) = val.into_parts(); (u128::from(offset.bytes()), Some(provenance)) diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 492091a4f2540..9afe9523fcab0 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -221,6 +221,13 @@ pub struct UninitBytesAccess { pub uninit_size: Size, } +/// Information about a size mismatch. +#[derive(Debug)] +pub struct ScalarSizeMismatch { + pub target_size: u64, + pub data_size: u64, +} + /// Error information for when the program caused Undefined Behavior. pub enum UndefinedBehaviorInfo<'tcx> { /// Free-form case. Only for errors that are never caught! @@ -298,10 +305,7 @@ pub enum UndefinedBehaviorInfo<'tcx> { /// Working with a local that is not currently live. DeadLocal, /// Data size is not equal to target size. - ScalarSizeMismatch { - target_size: u64, - data_size: u64, - }, + ScalarSizeMismatch(ScalarSizeMismatch), /// A discriminant of an uninhabited enum variant is written. UninhabitedEnumVariantWritten, } @@ -408,7 +412,7 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { "using uninitialized data, but this operation requires initialized memory" ), DeadLocal => write!(f, "accessing a dead local variable"), - ScalarSizeMismatch { target_size, data_size } => write!( + ScalarSizeMismatch(self::ScalarSizeMismatch { target_size, data_size }) => write!( f, "scalar size mismatch: expected {} bytes but got {} bytes instead", target_size, data_size diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index bce962491b7b1..d8cba39c6d97b 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -120,7 +120,8 @@ use crate::ty::{self, Instance, Ty, TyCtxt}; pub use self::error::{ struct_error, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult, InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, MachineStopType, - ResourceExhaustionInfo, UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo, + ResourceExhaustionInfo, ScalarSizeMismatch, UndefinedBehaviorInfo, UninitBytesAccess, + UnsupportedOpInfo, }; pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar, ScalarMaybeUninit}; diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 8e32603a35702..9cffdf2993ed5 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -12,6 +12,7 @@ use crate::ty::{Lift, ParamEnv, ScalarInt, Ty, TyCtxt}; use super::{ AllocId, AllocRange, ConstAllocation, InterpResult, Pointer, PointerArithmetic, Provenance, + ScalarSizeMismatch, }; /// Represents the result of const evaluation via the `eval_to_allocation` query. @@ -300,16 +301,29 @@ impl Scalar { /// /// This method only exists for the benefit of low-level operations that truly need to treat the /// scalar in whatever form it is. + /// + /// This throws UB (instead of ICEing) on a size mismatch since size mismatches can arise in + /// Miri when someone declares a function that we shim (such as `malloc`) with a wrong type. #[inline] - pub fn to_bits_or_ptr_internal(self, target_size: Size) -> Result> { + pub fn to_bits_or_ptr_internal( + self, + target_size: Size, + ) -> Result>, ScalarSizeMismatch> { assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST"); - match self { - Scalar::Int(int) => Ok(int.assert_bits(target_size)), + Ok(match self { + Scalar::Int(int) => Ok(int.to_bits(target_size).map_err(|size| { + ScalarSizeMismatch { target_size: target_size.bytes(), data_size: size.bytes() } + })?), Scalar::Ptr(ptr, sz) => { - assert_eq!(target_size.bytes(), u64::from(sz)); + if target_size.bytes() != sz.into() { + return Err(ScalarSizeMismatch { + target_size: target_size.bytes(), + data_size: sz.into(), + }); + } Err(ptr) } - } + }) } } @@ -348,10 +362,10 @@ impl<'tcx, Tag: Provenance> Scalar { assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST"); self.try_to_int().map_err(|_| err_unsup!(ReadPointerAsBytes))?.to_bits(target_size).map_err( |size| { - err_ub!(ScalarSizeMismatch { + err_ub!(ScalarSizeMismatch(ScalarSizeMismatch { target_size: target_size.bytes(), data_size: size.bytes(), - }) + })) .into() }, ) diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index b2dd67fb16dce..69dac03883940 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -561,8 +561,7 @@ fn write_scope_tree( } indented_decl.push(';'); - let local_name = - if local == RETURN_PLACE { " return place".to_string() } else { String::new() }; + let local_name = if local == RETURN_PLACE { " return place" } else { "" }; writeln!( w, diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index 1fadd0c26fc49..bb3ba3e596d14 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -146,7 +146,7 @@ impl IntRange { // straight to the result, after doing a bit of checking. (We // could remove this branch and just fall through, which // is more general but much slower.) - if let Ok(bits) = scalar.to_bits_or_ptr_internal(target_size) { + if let Ok(bits) = scalar.to_bits_or_ptr_internal(target_size).unwrap() { return Some(bits); } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 1f12f99efb3d5..c45326e1e6e6c 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -20,7 +20,7 @@ use rustc_session::lint::builtin::{ CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, UNUSED_ATTRIBUTES, }; use rustc_session::parse::feature_err; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use std::collections::hash_map::Entry; @@ -536,7 +536,7 @@ impl CheckAttrVisitor<'_> { fn check_doc_alias_value( &self, meta: &NestedMetaItem, - doc_alias: &str, + doc_alias: Symbol, hir_id: HirId, target: Target, is_list: bool, @@ -554,14 +554,17 @@ impl CheckAttrVisitor<'_> { ); false }; - if doc_alias.is_empty() { + if doc_alias == kw::Empty { return err_fn( meta.name_value_literal_span().unwrap_or_else(|| meta.span()), "attribute cannot have empty value", ); } - if let Some(c) = - doc_alias.chars().find(|&c| c == '"' || c == '\'' || (c.is_whitespace() && c != ' ')) + + let doc_alias_str = doc_alias.as_str(); + if let Some(c) = doc_alias_str + .chars() + .find(|&c| c == '"' || c == '\'' || (c.is_whitespace() && c != ' ')) { self.tcx.sess.span_err( meta.name_value_literal_span().unwrap_or_else(|| meta.span()), @@ -573,7 +576,7 @@ impl CheckAttrVisitor<'_> { ); return false; } - if doc_alias.starts_with(' ') || doc_alias.ends_with(' ') { + if doc_alias_str.starts_with(' ') || doc_alias_str.ends_with(' ') { return err_fn( meta.name_value_literal_span().unwrap_or_else(|| meta.span()), "cannot start or end with ' '", @@ -608,11 +611,11 @@ impl CheckAttrVisitor<'_> { return err_fn(meta.span(), &format!("isn't allowed on {}", err)); } let item_name = self.tcx.hir().name(hir_id); - if item_name.as_str() == doc_alias { + if item_name == doc_alias { return err_fn(meta.span(), "is the same as the item's name"); } let span = meta.span(); - if let Err(entry) = aliases.try_insert(doc_alias.to_owned(), span) { + if let Err(entry) = aliases.try_insert(doc_alias_str.to_owned(), span) { self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, span, |lint| { lint.build("doc alias is duplicated") .span_label(*entry.entry.get(), "first defined here") @@ -635,14 +638,7 @@ impl CheckAttrVisitor<'_> { match v.literal() { Some(l) => match l.kind { LitKind::Str(s, _) => { - if !self.check_doc_alias_value( - v, - s.as_str(), - hir_id, - target, - true, - aliases, - ) { + if !self.check_doc_alias_value(v, s, hir_id, target, true, aliases) { errors += 1; } } @@ -670,8 +666,8 @@ impl CheckAttrVisitor<'_> { } } errors == 0 - } else if let Some(doc_alias) = meta.value_str().map(|s| s.to_string()) { - self.check_doc_alias_value(meta, &doc_alias, hir_id, target, false, aliases) + } else if let Some(doc_alias) = meta.value_str() { + self.check_doc_alias_value(meta, doc_alias, hir_id, target, false, aliases) } else { self.tcx .sess @@ -686,8 +682,8 @@ impl CheckAttrVisitor<'_> { } fn check_doc_keyword(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool { - let doc_keyword = meta.value_str().map(|s| s.to_string()).unwrap_or_else(String::new); - if doc_keyword.is_empty() { + let doc_keyword = meta.value_str().unwrap_or(kw::Empty); + if doc_keyword == kw::Empty { self.doc_attr_str_error(meta, "keyword"); return false; } @@ -718,7 +714,7 @@ impl CheckAttrVisitor<'_> { return false; } } - if !rustc_lexer::is_ident(&doc_keyword) { + if !rustc_lexer::is_ident(doc_keyword.as_str()) { self.tcx .sess .struct_span_err( @@ -911,20 +907,20 @@ impl CheckAttrVisitor<'_> { ) -> bool { let mut is_valid = true; - if let Some(list) = attr.meta().and_then(|mi| mi.meta_item_list().map(|l| l.to_vec())) { - for meta in &list { + if let Some(mi) = attr.meta() && let Some(list) = mi.meta_item_list() { + for meta in list { if let Some(i_meta) = meta.meta_item() { match i_meta.name_or_empty() { sym::alias - if !self.check_attr_not_crate_level(&meta, hir_id, "alias") - || !self.check_doc_alias(&meta, hir_id, target, aliases) => + if !self.check_attr_not_crate_level(meta, hir_id, "alias") + || !self.check_doc_alias(meta, hir_id, target, aliases) => { is_valid = false } sym::keyword - if !self.check_attr_not_crate_level(&meta, hir_id, "keyword") - || !self.check_doc_keyword(&meta, hir_id) => + if !self.check_attr_not_crate_level(meta, hir_id, "keyword") + || !self.check_doc_keyword(meta, hir_id) => { is_valid = false } @@ -936,15 +932,15 @@ impl CheckAttrVisitor<'_> { | sym::html_root_url | sym::html_no_source | sym::test - if !self.check_attr_crate_level(&attr, &meta, hir_id) => + if !self.check_attr_crate_level(attr, meta, hir_id) => { is_valid = false; } sym::inline | sym::no_inline if !self.check_doc_inline( - &attr, - &meta, + attr, + meta, hir_id, target, specified_inline, @@ -976,7 +972,7 @@ impl CheckAttrVisitor<'_> { | sym::plugins => {} sym::test => { - if !self.check_test_attr(&meta, hir_id) { + if !self.check_test_attr(meta, hir_id) { is_valid = false; } } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 84b4a803403f9..ff033cbb57299 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -696,7 +696,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { hir::ItemKind::ExternCrate(_) => { // compiler-generated `extern crate` items have a dummy span. // `std` is still checked for the `restricted-std` feature. - if item.span.is_dummy() && item.ident.as_str() != "std" { + if item.span.is_dummy() && item.ident.name != sym::std { return; } diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index afb19d7df9fce..1460b5efbb058 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -587,7 +587,7 @@ fn get_lifetime_scopes_for_path(mut scope: &Scope<'_>) -> LifetimeScopeForPath { match scope { Scope::Binder { lifetimes, s, .. } => { available_lifetimes.extend(lifetimes.keys().filter_map(|p| match p { - hir::ParamName::Plain(ident) => Some(ident.name.to_string()), + hir::ParamName::Plain(ident) => Some(ident.name), _ => None, })); scope = s; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 9998c5bb087e1..ac98dd5801e40 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -36,6 +36,7 @@ use rustc_span::symbol::{kw, sym}; use rustc_span::{ExpnKind, Span, DUMMY_SP}; use std::fmt; use std::iter; +use std::ops::ControlFlow; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::query::normalize::AtExt as _; @@ -2226,9 +2227,10 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { post.dedup(); if self.is_tainted_by_errors() - && crate_names.len() == 1 - && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str()) - && spans.len() == 0 + && (crate_names.len() == 1 + && spans.len() == 0 + && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str()) + || predicate.visit_with(&mut HasNumericInferVisitor).is_break()) { // Avoid complaining about other inference issues for expressions like // `42 >> 1`, where the types are still `{integer}`, but we want to @@ -2666,3 +2668,17 @@ impl ArgKind { } } } + +struct HasNumericInferVisitor; + +impl<'tcx> ty::TypeVisitor<'tcx> for HasNumericInferVisitor { + type BreakTy = (); + + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + if matches!(ty.kind(), ty::Infer(ty::FloatVar(_) | ty::IntVar(_))) { + ControlFlow::Break(()) + } else { + ControlFlow::CONTINUE + } + } +} diff --git a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs index 24b6639d7f275..1b1a2037d9eaa 100644 --- a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs @@ -497,7 +497,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { param_names .iter() .take(num_params_to_take) - .map(|p| (*p).clone()) + .map(|p| p.as_str()) .collect::>() .join(", ") } else { diff --git a/library/core/src/macros/panic.md b/library/core/src/macros/panic.md index d8206e7893114..98fb7e9e41d7a 100644 --- a/library/core/src/macros/panic.md +++ b/library/core/src/macros/panic.md @@ -24,20 +24,30 @@ See also the macro [`compile_error!`], for raising errors during compilation. # When to use `panic!` vs `Result` -The Rust model of error handling groups errors into two major categories: -recoverable and unrecoverable errors. For a recoverable error, such as a file -not found error, it’s reasonable to report the problem to the user and retry -the operation. Unrecoverable errors are always symptoms of bugs, like trying to -access a location beyond the end of an array. +The Rust language provides two complementary systems for constructing / +representing, reporting, propagating, reacting to, and discarding errors. These +responsibilities are collectively known as "error handling." `panic!` and +`Result` are similar in that they are each the primary interface of their +respective error handling systems; however, the meaning these interfaces attach +to their errors and the responsibilities they fulfill within their respective +error handling systems differ. -The Rust language and standard library provides `Result` and `panic!` as parts -of two complementary systems for representing, reporting, propagating, reacting -to, and discarding errors for in these two categories. +The `panic!` macro is used to construct errors that represent a bug that has +been detected in your program. With `panic!` you provide a message that +describes the bug and the language then constructs an error with that message, +reports it, and propagates it for you. -The `panic!` macro is provided to represent unrecoverable errors, whereas the -`Result` enum is provided to represent recoverable errors. For more detailed -information about error handling check out the [book] or the [`std::result`] -module docs. +`Result` on the other hand is used to wrap other types that represent either +the successful result of some computation, `Ok(T)`, or error types that +represent an anticipated runtime failure mode of that computation, `Err(E)`. +`Result` is used alongside user defined types which represent the various +anticipated runtime failure modes that the associated computation could +encounter. `Result` must be propagated manually, often with the the help of the +`?` operator and `Try` trait, and they must be reported manually, often with +the help of the `Error` trait. + +For more detailed information about error handling check out the [book] or the +[`std::result`] module docs. [ounwrap]: Option::unwrap [runwrap]: Result::unwrap diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 8c19cf973fc86..d06e4fa1cc2f5 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -425,13 +425,26 @@ crate fn build_impl( None => ( tcx.associated_items(did) .in_definition_order() - .filter_map(|item| { - if associated_trait.is_some() || item.vis.is_public() { - Some(item.clean(cx)) + .filter(|item| { + // If this is a trait impl, filter out associated items whose corresponding item + // in the associated trait is marked `doc(hidden)`. + // If this is an inherent impl, filter out private associated items. + if let Some(associated_trait) = associated_trait { + let trait_item = tcx + .associated_items(associated_trait.def_id) + .find_by_name_and_kind( + tcx, + item.ident(tcx), + item.kind, + associated_trait.def_id, + ) + .unwrap(); // corresponding associated item has to exist + !tcx.is_doc_hidden(trait_item.def_id) } else { - None + item.vis.is_public() } }) + .map(|item| item.clean(cx)) .collect::>(), clean::enter_impl_trait(cx, |cx| { clean_ty_generics(cx, tcx.generics_of(did), predicates) diff --git a/src/test/rustdoc/auxiliary/cross-crate-hidden-assoc-trait-items.rs b/src/test/rustdoc/auxiliary/cross-crate-hidden-assoc-trait-items.rs new file mode 100644 index 0000000000000..3baf8a6c07ee8 --- /dev/null +++ b/src/test/rustdoc/auxiliary/cross-crate-hidden-assoc-trait-items.rs @@ -0,0 +1,19 @@ +pub trait Tr { + type VisibleAssoc; + #[doc(hidden)] + type HiddenAssoc; + + const VISIBLE_ASSOC: (); + #[doc(hidden)] + const HIDDEN_ASSOC: (); +} + +pub struct Ty; + +impl Tr for Ty { + type VisibleAssoc = (); + type HiddenAssoc = (); + + const VISIBLE_ASSOC: () = (); + const HIDDEN_ASSOC: () = (); +} diff --git a/src/test/rustdoc/cross-crate-hidden-assoc-trait-items.rs b/src/test/rustdoc/cross-crate-hidden-assoc-trait-items.rs new file mode 100644 index 0000000000000..d02bc4fe71250 --- /dev/null +++ b/src/test/rustdoc/cross-crate-hidden-assoc-trait-items.rs @@ -0,0 +1,23 @@ +// Regression test for issue #95717 +// Hide cross-crate `#[doc(hidden)]` associated items in trait impls. + +#![crate_name = "dependent"] +// edition:2021 +// aux-crate:dependency=cross-crate-hidden-assoc-trait-items.rs + +// The trait `Tr` contains 2 hidden and 2 visisible associated items. +// Instead of checking for the absence of the hidden items, check for the presence of the +// visible items instead and assert that there are *exactly two* associated items +// (by counting the number of `section`s). This is more robust and future-proof. + +// @has dependent/struct.Ty.html +// @has - '//*[@id="associatedtype.VisibleAssoc"]' 'type VisibleAssoc = ()' +// @has - '//*[@id="associatedconstant.VISIBLE_ASSOC"]' 'const VISIBLE_ASSOC: ()' +// @count - '//*[@class="impl-items"]/section' 2 + +// @has dependent/trait.Tr.html +// @has - '//*[@id="associatedtype.VisibleAssoc-1"]' 'type VisibleAssoc = ()' +// @has - '//*[@id="associatedconstant.VISIBLE_ASSOC-1"]' 'const VISIBLE_ASSOC: ()' +// @count - '//*[@class="impl-items"]/section' 2 + +pub use dependency::{Tr, Ty}; diff --git a/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.rs b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.rs index cff6f29a15386..b4fef11f1e29a 100644 --- a/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.rs +++ b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.rs @@ -5,5 +5,40 @@ macro_rules! count { }; } +macro_rules! dollar_dollar { + () => { + macro_rules! bar { + ( $$( $$any:tt )* ) => { $$( $$any )* }; + //~^ ERROR meta-variable expressions are unstable + //~| ERROR meta-variable expressions are unstable + //~| ERROR meta-variable expressions are unstable + //~| ERROR meta-variable expressions are unstable + } + }; +} + +macro_rules! index { + ( $( $e:stmt ),* ) => { + $( ${ignore(e)} ${index()} )* + //~^ ERROR meta-variable expressions are unstable + //~| ERROR meta-variable expressions are unstable + }; +} + +macro_rules! ignore { + ( $( $i:stmt ),* ) => {{ + 0 $( + 1 ${ignore(i)} )* + //~^ ERROR meta-variable expressions are unstable + }}; +} + +macro_rules! length { + ( $( $e:stmt ),* ) => { + $( ${ignore(e)} ${length()} )* + //~^ ERROR meta-variable expressions are unstable + //~| ERROR meta-variable expressions are unstable + }; +} + fn main() { } diff --git a/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.stderr b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.stderr index f573194479314..ecf598b104d05 100644 --- a/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.stderr +++ b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.stderr @@ -7,6 +7,87 @@ LL | ${ count(e) } = note: see issue #83527 for more information = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable -error: aborting due to previous error +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:11:16 + | +LL | ( $$( $$any:tt )* ) => { $$( $$any )* }; + | ^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:11:20 + | +LL | ( $$( $$any:tt )* ) => { $$( $$any )* }; + | ^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:11:39 + | +LL | ( $$( $$any:tt )* ) => { $$( $$any )* }; + | ^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:11:43 + | +LL | ( $$( $$any:tt )* ) => { $$( $$any )* }; + | ^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:22:13 + | +LL | $( ${ignore(e)} ${index()} )* + | ^^^^^^^^^^^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:22:26 + | +LL | $( ${ignore(e)} ${index()} )* + | ^^^^^^^^^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:30:19 + | +LL | 0 $( + 1 ${ignore(i)} )* + | ^^^^^^^^^^^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:37:13 + | +LL | $( ${ignore(e)} ${length()} )* + | ^^^^^^^^^^^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:37:26 + | +LL | $( ${ignore(e)} ${length()} )* + | ^^^^^^^^^^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/traits/no-fallback-multiple-impls.rs b/src/test/ui/traits/no-fallback-multiple-impls.rs new file mode 100644 index 0000000000000..7ed3796f08b76 --- /dev/null +++ b/src/test/ui/traits/no-fallback-multiple-impls.rs @@ -0,0 +1,16 @@ +trait Fallback { + fn foo(&self) {} +} + +impl Fallback for i32 {} + +impl Fallback for u64 {} + +impl Fallback for usize {} + +fn main() { + missing(); + //~^ ERROR cannot find function `missing` in this scope + 0.foo(); + // But then we shouldn't report an inference ambiguity here... +} diff --git a/src/test/ui/traits/no-fallback-multiple-impls.stderr b/src/test/ui/traits/no-fallback-multiple-impls.stderr new file mode 100644 index 0000000000000..61c9e5aaabdb4 --- /dev/null +++ b/src/test/ui/traits/no-fallback-multiple-impls.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `missing` in this scope + --> $DIR/no-fallback-multiple-impls.rs:12:5 + | +LL | missing(); + | ^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/traits/test-2.rs b/src/test/ui/traits/test-2.rs index d062de25ac8c1..342928e882a55 100644 --- a/src/test/ui/traits/test-2.rs +++ b/src/test/ui/traits/test-2.rs @@ -6,9 +6,9 @@ impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah(&self) {} } impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah(&self) {} } fn main() { - 10.dup::(); //~ ERROR type annotations needed + 10.dup::(); //~^ ERROR this associated function takes 0 generic arguments but 1 - 10.blah::(); //~ ERROR type annotations needed + 10.blah::(); //~^ ERROR this associated function takes 1 generic argument but 2 (Box::new(10) as Box).dup(); //~^ ERROR E0038 diff --git a/src/test/ui/traits/test-2.stderr b/src/test/ui/traits/test-2.stderr index 5eec012458450..77ea4e4e974eb 100644 --- a/src/test/ui/traits/test-2.stderr +++ b/src/test/ui/traits/test-2.stderr @@ -79,35 +79,7 @@ LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } = note: required because of the requirements on the impl of `CoerceUnsized>` for `Box<{integer}>` = note: required by cast to type `Box` -error[E0283]: type annotations needed - --> $DIR/test-2.rs:9:8 - | -LL | 10.dup::(); - | ^^^ cannot infer type for type `{integer}` - | -note: multiple `impl`s satisfying `{integer}: bar` found - --> $DIR/test-2.rs:5:1 - | -LL | impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah(&self) {} } - | ^^^^^^^^^^^^^^^^ -LL | impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah(&self) {} } - | ^^^^^^^^^^^^^^^^ - -error[E0283]: type annotations needed - --> $DIR/test-2.rs:11:8 - | -LL | 10.blah::(); - | ^^^^ cannot infer type for type `{integer}` - | -note: multiple `impl`s satisfying `{integer}: bar` found - --> $DIR/test-2.rs:5:1 - | -LL | impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah(&self) {} } - | ^^^^^^^^^^^^^^^^ -LL | impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah(&self) {} } - | ^^^^^^^^^^^^^^^^ - -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0038, E0107, E0283. +Some errors have detailed explanations: E0038, E0107. For more information about an error, try `rustc --explain E0038`.