diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index baa02b8997f92..ffff543b07fe5 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -1,5 +1,6 @@ use std::borrow::Cow; use std::collections::TryReserveError::*; +use std::fmt::Debug; use std::mem::size_of; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::vec::{Drain, IntoIter}; @@ -1573,3 +1574,56 @@ fn test_push_growth_strategy() { } } } + +macro_rules! generate_assert_eq_vec_and_prim { + ($name:ident<$B:ident>($type:ty)) => { + fn $name + Debug, $B: Debug>(a: Vec, b: $type) { + assert!(a == b); + assert_eq!(a, b); + } + }; +} + +generate_assert_eq_vec_and_prim! { assert_eq_vec_and_slice (&[B]) } +generate_assert_eq_vec_and_prim! { assert_eq_vec_and_array_3([B; 3]) } + +#[test] +fn partialeq_vec_and_prim() { + assert_eq_vec_and_slice(vec![1, 2, 3], &[1, 2, 3]); + assert_eq_vec_and_array_3(vec![1, 2, 3], [1, 2, 3]); +} + +macro_rules! assert_partial_eq_valid { + ($a2:ident, $a3:ident; $b2:ident, $b3: ident) => { + assert!($a2 == $b2); + assert!($a2 != $b3); + assert!($a3 != $b2); + assert!($a3 == $b3); + assert_eq!($a2, $b2); + assert_ne!($a2, $b3); + assert_ne!($a3, $b2); + assert_eq!($a3, $b3); + }; +} + +#[test] +fn partialeq_vec_full() { + let vec2: Vec<_> = vec![1, 2]; + let vec3: Vec<_> = vec![1, 2, 3]; + let slice2: &[_] = &[1, 2]; + let slice3: &[_] = &[1, 2, 3]; + let slicemut2: &[_] = &mut [1, 2]; + let slicemut3: &[_] = &mut [1, 2, 3]; + let array2: [_; 2] = [1, 2]; + let array3: [_; 3] = [1, 2, 3]; + let arrayref2: &[_; 2] = &[1, 2]; + let arrayref3: &[_; 3] = &[1, 2, 3]; + + assert_partial_eq_valid!(vec2,vec3; vec2,vec3); + assert_partial_eq_valid!(vec2,vec3; slice2,slice3); + assert_partial_eq_valid!(vec2,vec3; slicemut2,slicemut3); + assert_partial_eq_valid!(slice2,slice3; vec2,vec3); + assert_partial_eq_valid!(slicemut2,slicemut3; vec2,vec3); + assert_partial_eq_valid!(vec2,vec3; array2,array3); + assert_partial_eq_valid!(vec2,vec3; arrayref2,arrayref3); +} diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 0531084d0e4a3..fc8a992e1701b 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2342,12 +2342,12 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for Vec { } macro_rules! __impl_slice_eq1 { - ([$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => { - #[stable(feature = "rust1", since = "1.0.0")] + ([$($vars:tt)*] $lhs:ty, $rhs:ty $(where $ty:ty: $bound:ident)?, #[$stability:meta]) => { + #[$stability] impl PartialEq<$rhs> for $lhs where A: PartialEq, - $($constraints)* + $($ty: $bound)? { #[inline] fn eq(&self, other: &$rhs) -> bool { self[..] == other[..] } @@ -2357,18 +2357,23 @@ macro_rules! __impl_slice_eq1 { } } -__impl_slice_eq1! { [] Vec, Vec, } -__impl_slice_eq1! { [] Vec, &[B], } -__impl_slice_eq1! { [] Vec, &mut [B], } -__impl_slice_eq1! { [] Cow<'_, [A]>, Vec, A: Clone } -__impl_slice_eq1! { [] Cow<'_, [A]>, &[B], A: Clone } -__impl_slice_eq1! { [] Cow<'_, [A]>, &mut [B], A: Clone } -__impl_slice_eq1! { [const N: usize] Vec, [B; N], [B; N]: LengthAtMost32 } -__impl_slice_eq1! { [const N: usize] Vec, &[B; N], [B; N]: LengthAtMost32 } +__impl_slice_eq1! { [] Vec, Vec, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Vec, &[B], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Vec, &mut [B], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] &[A], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } +__impl_slice_eq1! { [] &mut [A], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } +__impl_slice_eq1! { [] Cow<'_, [A]>, Vec where A: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Cow<'_, [A]>, &[B] where A: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Cow<'_, [A]>, &mut [B] where A: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [const N: usize] Vec, [B; N] where [B; N]: LengthAtMost32, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [const N: usize] Vec, &[B; N] where [B; N]: LengthAtMost32, #[stable(feature = "rust1", since = "1.0.0")] } // NOTE: some less important impls are omitted to reduce code bloat // FIXME(Centril): Reconsider this? //__impl_slice_eq1! { [const N: usize] Vec, &mut [B; N], [B; N]: LengthAtMost32 } +//__impl_slice_eq1! { [const N: usize] [A; N], Vec, [A; N]: LengthAtMost32 } +//__impl_slice_eq1! { [const N: usize] &[A; N], Vec, [A; N]: LengthAtMost32 } +//__impl_slice_eq1! { [const N: usize] &mut [A; N], Vec, [A; N]: LengthAtMost32 } //__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, [B; N], [B; N]: LengthAtMost32 } //__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &[B; N], [B; N]: LengthAtMost32 } //__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &mut [B; N], [B; N]: LengthAtMost32 } diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs index e39d18d7733a2..acc09ddc014e6 100644 --- a/src/libcore/ptr/const_ptr.rs +++ b/src/libcore/ptr/const_ptr.rs @@ -330,6 +330,12 @@ impl *const T { /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2); /// ``` #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")] + #[rustc_deprecated( + since = "1.46.0", + reason = "Pointer distances across allocation \ + boundaries are not typically meaningful. \ + Use integer subtraction if you really need this." + )] #[inline] pub fn wrapping_offset_from(self, origin: *const T) -> isize where diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs index 40b5e4e22340e..2bbeb95965e7e 100644 --- a/src/libcore/ptr/mut_ptr.rs +++ b/src/libcore/ptr/mut_ptr.rs @@ -380,11 +380,18 @@ impl *mut T { /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2); /// ``` #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")] + #[rustc_deprecated( + since = "1.46.0", + reason = "Pointer distances across allocation \ + boundaries are not typically meaningful. \ + Use integer subtraction if you really need this." + )] #[inline] pub fn wrapping_offset_from(self, origin: *const T) -> isize where T: Sized, { + #[allow(deprecated_in_future, deprecated)] (self as *const T).wrapping_offset_from(origin) } diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 738b3bc7539a6..6a5e23adafa53 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -445,6 +445,7 @@ E0761: include_str!("./error_codes/E0761.md"), E0762: include_str!("./error_codes/E0762.md"), E0763: include_str!("./error_codes/E0763.md"), E0764: include_str!("./error_codes/E0764.md"), +E0765: include_str!("./error_codes/E0765.md"), ; // E0006, // merged with E0005 // E0008, // cannot bind by-move into a pattern guard diff --git a/src/librustc_error_codes/error_codes/E0765.md b/src/librustc_error_codes/error_codes/E0765.md new file mode 100644 index 0000000000000..456e3f3e9e408 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0765.md @@ -0,0 +1,13 @@ +A double quote string (`"`) was not terminated. + +Erroneous code example: + +```compile_fail,E0765 +let s = "; // error! +``` + +To fix this error, add the missing double quote at the end of the string: + +``` +let s = ""; // ok! +``` diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index cfe856abe36dd..60cf21552e9e9 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -52,7 +52,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } if self.tcx.has_attr(def_id, sym::rustc_args_required_const) { - bug!("reifying a fn ptr that requires const arguments"); + span_bug!( + self.cur_span(), + "reifying a fn ptr that requires const arguments" + ); } let instance = ty::Instance::resolve_for_fn_ptr( @@ -66,7 +69,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance)); self.write_scalar(fn_ptr, dest)?; } - _ => bug!("reify fn pointer on {:?}", src.layout.ty), + _ => span_bug!(self.cur_span(), "reify fn pointer on {:?}", src.layout.ty), } } @@ -77,7 +80,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // No change to value self.write_immediate(*src, dest)?; } - _ => bug!("fn to unsafe fn cast on {:?}", cast_ty), + _ => span_bug!(self.cur_span(), "fn to unsafe fn cast on {:?}", cast_ty), } } @@ -99,7 +102,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance)); self.write_scalar(fn_ptr, dest)?; } - _ => bug!("closure fn pointer on {:?}", src.layout.ty), + _ => span_bug!(self.cur_span(), "closure fn pointer on {:?}", src.layout.ty), } } } @@ -162,7 +165,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { assert!(src.layout.ty.is_unsafe_ptr()); return match *src { Immediate::ScalarPair(data, _) => Ok(data.into()), - Immediate::Scalar(..) => bug!( + Immediate::Scalar(..) => span_bug!( + self.cur_span(), "{:?} input to a fat-to-thin cast ({:?} -> {:?})", *src, src.layout.ty, @@ -216,7 +220,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } // Casts to bool are not permitted by rustc, no need to handle them here. - _ => bug!("invalid int to {:?} cast", cast_ty), + _ => span_bug!(self.cur_span(), "invalid int to {:?} cast", cast_ty), } } @@ -248,7 +252,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // float -> f64 Float(FloatTy::F64) => Scalar::from_f64(f.convert(&mut false).value), // That's it. - _ => bug!("invalid float to {:?} cast", dest_ty), + _ => span_bug!(self.cur_span(), "invalid float to {:?} cast", dest_ty), } } @@ -287,7 +291,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_immediate(val, dest) } - _ => bug!("invalid unsizing {:?} -> {:?}", src.layout.ty, cast_ty), + _ => { + span_bug!(self.cur_span(), "invalid unsizing {:?} -> {:?}", src.layout.ty, cast_ty) + } } } @@ -307,7 +313,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { assert_eq!(def_a, def_b); if def_a.is_box() || def_b.is_box() { if !def_a.is_box() || !def_b.is_box() { - bug!("invalid unsizing between {:?} -> {:?}", src.layout.ty, cast_ty.ty); + span_bug!( + self.cur_span(), + "invalid unsizing between {:?} -> {:?}", + src.layout.ty, + cast_ty.ty + ); } return self.unsize_into_ptr( src, @@ -335,7 +346,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } Ok(()) } - _ => bug!("unsize_into: invalid conversion: {:?} -> {:?}", src.layout, dest.layout), + _ => span_bug!( + self.cur_span(), + "unsize_into: invalid conversion: {:?} -> {:?}", + src.layout, + dest.layout + ), } } } diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 22f4691c22b3d..ceacbbe5139bf 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -536,7 +536,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if sized_size == Size::ZERO { return Ok(None); } else { - bug!("Fields cannot be extern types, unless they are at offset 0") + span_bug!( + self.cur_span(), + "Fields cannot be extern types, unless they are at offset 0" + ) } } }; @@ -584,7 +587,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::Foreign(_) => Ok(None), - _ => bug!("size_and_align_of::<{:?}> not supported", layout.ty), + _ => span_bug!(self.cur_span(), "size_and_align_of::<{:?}> not supported", layout.ty), } } #[inline] diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index ac28ccd181520..31bdc45a2eab9 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -135,7 +135,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let bits = self.force_bits(val, layout_of.size)?; let kind = match layout_of.abi { Abi::Scalar(ref scalar) => scalar.value, - _ => bug!("{} called on invalid type {:?}", intrinsic_name, ty), + _ => span_bug!( + self.cur_span(), + "{} called on invalid type {:?}", + intrinsic_name, + ty + ), }; let (nonzero, intrinsic_name) = match intrinsic_name { sym::cttz_nonzero => (true, sym::cttz), diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 35e433c4bd5cd..38948ee53846a 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -311,7 +311,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if let Ok(imm) = self.try_read_immediate(op)? { Ok(imm) } else { - bug!("primitive read failed for type: {:?}", op.layout.ty); + span_bug!(self.cur_span(), "primitive read failed for type: {:?}", op.layout.ty); } } @@ -360,9 +360,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let val = if offset.bytes() == 0 { a } else { b }; Immediate::from(val) } - Immediate::Scalar(val) => { - bug!("field access on non aggregate {:#?}, {:#?}", val, op.layout) - } + Immediate::Scalar(val) => span_bug!( + self.cur_span(), + "field access on non aggregate {:#?}, {:#?}", + val, + op.layout + ), }; Ok(OpTy { op: Operand::Immediate(immediate), layout: field_layout }) } @@ -545,7 +548,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::ConstKind::Infer(..) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(..) => { - bug!("eval_const_to_op: Unexpected ConstKind {:?}", val) + span_bug!(self.cur_span(), "eval_const_to_op: Unexpected ConstKind {:?}", val) } ty::ConstKind::Value(val_val) => val_val, }; @@ -656,7 +659,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .discriminants(def_id, *self.tcx) .find(|(_, var)| var.val == discr_bits) } - _ => bug!("tagged layout for non-adt non-generator"), + _ => span_bug!(self.cur_span(), "tagged layout for non-adt non-generator"), } .ok_or_else(|| err_ub!(InvalidTag(tag_val.erase_tag())))?; // Return the cast value, and the index. diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index d651267f82b79..607122935347e 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -61,7 +61,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Le => l <= r, Gt => l > r, Ge => l >= r, - _ => bug!("Invalid operation on char: {:?}", bin_op), + _ => span_bug!(self.cur_span(), "Invalid operation on char: {:?}", bin_op), }; (Scalar::from_bool(res), false, self.tcx.types.bool) } @@ -84,7 +84,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { BitAnd => l & r, BitOr => l | r, BitXor => l ^ r, - _ => bug!("Invalid operation on bool: {:?}", bin_op), + _ => span_bug!(self.cur_span(), "Invalid operation on bool: {:?}", bin_op), }; (Scalar::from_bool(res), false, self.tcx.types.bool) } @@ -110,7 +110,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Mul => ((l * r).value.into(), ty), Div => ((l / r).value.into(), ty), Rem => ((l % r).value.into(), ty), - _ => bug!("invalid float op: `{:?}`", bin_op), + _ => span_bug!(self.cur_span(), "invalid float op: `{:?}`", bin_op), }; (val, false, ty) } @@ -154,7 +154,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // For the remaining ops, the types must be the same on both sides if left_layout.ty != right_layout.ty { - bug!( + span_bug!( + self.cur_span(), "invalid asymmetric binary op {:?}: {:?} ({:?}), {:?} ({:?})", bin_op, l, @@ -251,7 +252,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { )); } - _ => bug!( + _ => span_bug!( + self.cur_span(), "invalid binary op {:?}: {:?}, {:?} (both {:?})", bin_op, l, @@ -333,7 +335,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { M::binary_ptr_op(self, bin_op, left, right) } - _ => bug!("Invalid MIR: bad LHS type for binop: {:?}", left.layout.ty), + _ => span_bug!( + self.cur_span(), + "Invalid MIR: bad LHS type for binop: {:?}", + left.layout.ty + ), } } @@ -367,7 +373,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let val = val.to_bool()?; let res = match un_op { Not => !val, - _ => bug!("Invalid bool op {:?}", un_op), + _ => span_bug!(self.cur_span(), "Invalid bool op {:?}", un_op), }; Ok((Scalar::from_bool(res), false, self.tcx.types.bool)) } @@ -375,7 +381,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let res = match (un_op, fty) { (Neg, FloatTy::F32) => Scalar::from_f32(-val.to_f32()?), (Neg, FloatTy::F64) => Scalar::from_f64(-val.to_f64()?), - _ => bug!("Invalid float op {:?}", un_op), + _ => span_bug!(self.cur_span(), "Invalid float op {:?}", un_op), }; Ok((res, false, layout.ty)) } diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 1d57fce39734e..0f3fbcf819574 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -232,7 +232,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::FnDef(..) => instance_ty.fn_sig(*self.tcx).abi(), ty::Closure(..) => Abi::RustCall, ty::Generator(..) => Abi::Rust, - _ => bug!("unexpected callee ty: {:?}", instance_ty), + _ => span_bug!(self.cur_span(), "unexpected callee ty: {:?}", instance_ty), } }; let normalize_abi = |abi| match abi { diff --git a/src/librustc_parse/lexer/mod.rs b/src/librustc_parse/lexer/mod.rs index 2e3cf4e746ae9..8e74c3847bc90 100644 --- a/src/librustc_parse/lexer/mod.rs +++ b/src/librustc_parse/lexer/mod.rs @@ -353,8 +353,15 @@ impl<'a> StringReader<'a> { } rustc_lexer::LiteralKind::Str { terminated } => { if !terminated { - self.fatal_span_(start, suffix_start, "unterminated double quote string") - .raise() + self.sess + .span_diagnostic + .struct_span_fatal_with_code( + self.mk_sp(start, suffix_start), + "unterminated double quote string", + error_code!(E0765), + ) + .emit(); + FatalError.raise(); } (token::Str, Mode::Str, 1, 1) // " " } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index bd2ce5a72e8d9..bb88b8191f1ad 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -49,6 +49,7 @@ crate struct ImportSuggestion { pub did: Option, pub descr: &'static str, pub path: Path, + pub accessible: bool, } /// Adjust the impl span so that just the `impl` keyword is taken by removing @@ -640,9 +641,11 @@ impl<'a> Resolver<'a> { let mut candidates = Vec::new(); let mut seen_modules = FxHashSet::default(); let not_local_module = crate_name.name != kw::Crate; - let mut worklist = vec![(start_module, Vec::::new(), not_local_module)]; + let mut worklist = + vec![(start_module, Vec::::new(), true, not_local_module)]; - while let Some((in_module, path_segments, in_module_is_extern)) = worklist.pop() { + while let Some((in_module, path_segments, accessible, in_module_is_extern)) = worklist.pop() + { // We have to visit module children in deterministic order to avoid // instabilities in reported imports (#43552). in_module.for_each_child(self, |this, ident, ns, name_binding| { @@ -650,11 +653,20 @@ impl<'a> Resolver<'a> { if name_binding.is_import() && !name_binding.is_extern_crate() { return; } + // avoid non-importable candidates as well if !name_binding.is_importable() { return; } + let child_accessible = + accessible && this.is_accessible_from(name_binding.vis, parent_scope.module); + + // do not venture inside inaccessible items of other crates + if in_module_is_extern && !child_accessible { + return; + } + // collect results based on the filter function // avoid suggesting anything from the same module in which we are resolving if ident.name == lookup_ident.name @@ -673,22 +685,29 @@ impl<'a> Resolver<'a> { segms.push(ast::PathSegment::from_ident(ident)); let path = Path { span: name_binding.span, segments: segms }; - // the entity is accessible in the following cases: - // 1. if it's defined in the same crate, it's always - // accessible (since private entities can be made public) - // 2. if it's defined in another crate, it's accessible - // only if both the module is public and the entity is - // declared as public (due to pruning, we don't explore - // outside crate private modules => no need to check this) - if !in_module_is_extern || name_binding.vis == ty::Visibility::Public { - let did = match res { - Res::Def(DefKind::Ctor(..), did) => this.parent(did), - _ => res.opt_def_id(), - }; - if candidates.iter().all(|v: &ImportSuggestion| v.did != did) { - candidates.push(ImportSuggestion { did, descr: res.descr(), path }); + let did = match res { + Res::Def(DefKind::Ctor(..), did) => this.parent(did), + _ => res.opt_def_id(), + }; + + if child_accessible { + // Remove invisible match if exists + if let Some(idx) = candidates + .iter() + .position(|v: &ImportSuggestion| v.did == did && !v.accessible) + { + candidates.remove(idx); } } + + if candidates.iter().all(|v: &ImportSuggestion| v.did != did) { + candidates.push(ImportSuggestion { + did, + descr: res.descr(), + path, + accessible: child_accessible, + }); + } } } @@ -701,20 +720,22 @@ impl<'a> Resolver<'a> { let is_extern_crate_that_also_appears_in_prelude = name_binding.is_extern_crate() && lookup_ident.span.rust_2018(); - let is_visible_to_user = - !in_module_is_extern || name_binding.vis == ty::Visibility::Public; - - if !is_extern_crate_that_also_appears_in_prelude && is_visible_to_user { - // add the module to the lookup + if !is_extern_crate_that_also_appears_in_prelude { let is_extern = in_module_is_extern || name_binding.is_extern_crate(); + // add the module to the lookup if seen_modules.insert(module.def_id().unwrap()) { - worklist.push((module, path_segments, is_extern)); + worklist.push((module, path_segments, child_accessible, is_extern)); } } } }) } + // If only some candidates are accessible, take just them + if !candidates.iter().all(|v: &ImportSuggestion| !v.accessible) { + candidates = candidates.into_iter().filter(|x| x.accessible).collect(); + } + candidates } diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 05ef0aa0bb689..478698ba20c70 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -887,7 +887,12 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { let path = Path { span: name_binding.span, segments: path_segments }; result = Some(( module, - ImportSuggestion { did: Some(def_id), descr: "module", path }, + ImportSuggestion { + did: Some(def_id), + descr: "module", + path, + accessible: true, + }, )); } else { // add the module to the lookup diff --git a/src/test/rustdoc-ui/test-compile-fail3.stderr b/src/test/rustdoc-ui/test-compile-fail3.stderr index 7a2f1815ed8e5..fab801b3beaea 100644 --- a/src/test/rustdoc-ui/test-compile-fail3.stderr +++ b/src/test/rustdoc-ui/test-compile-fail3.stderr @@ -1,4 +1,4 @@ -error: unterminated double quote string +error[E0765]: unterminated double quote string --> $DIR/test-compile-fail3.rs:3:1 | 3 | "fail @@ -6,3 +6,4 @@ error: unterminated double quote string error: aborting due to previous error +For more information about this error, try `rustc --explain E0765`. diff --git a/src/test/rustdoc-ui/unparseable-doc-test.stdout b/src/test/rustdoc-ui/unparseable-doc-test.stdout index 4ea6455d3aa4c..29cb22e2e4b09 100644 --- a/src/test/rustdoc-ui/unparseable-doc-test.stdout +++ b/src/test/rustdoc-ui/unparseable-doc-test.stdout @@ -5,7 +5,7 @@ test $DIR/unparseable-doc-test.rs - foo (line 6) ... FAILED failures: ---- $DIR/unparseable-doc-test.rs - foo (line 6) stdout ---- -error: unterminated double quote string +error[E0765]: unterminated double quote string --> $DIR/unparseable-doc-test.rs:8:1 | LL | "unterminated @@ -13,6 +13,7 @@ LL | "unterminated error: aborting due to previous error +For more information about this error, try `rustc --explain E0765`. Couldn't compile the test. failures: diff --git a/src/test/ui/codemap_tests/tab_2.stderr b/src/test/ui/codemap_tests/tab_2.stderr index 70414bbd953d6..0bfdc3ac2651d 100644 --- a/src/test/ui/codemap_tests/tab_2.stderr +++ b/src/test/ui/codemap_tests/tab_2.stderr @@ -1,4 +1,4 @@ -error: unterminated double quote string +error[E0765]: unterminated double quote string --> $DIR/tab_2.rs:4:7 | LL | """; @@ -8,3 +8,4 @@ LL | | } error: aborting due to previous error +For more information about this error, try `rustc --explain E0765`. diff --git a/src/test/ui/hygiene/globs.stderr b/src/test/ui/hygiene/globs.stderr index 8f6b7aca8fda8..6dcbf055a8bb7 100644 --- a/src/test/ui/hygiene/globs.stderr +++ b/src/test/ui/hygiene/globs.stderr @@ -23,14 +23,10 @@ LL | | } | |_____- in this macro invocation | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing one of these items +help: consider importing this function | LL | use bar::g; | -LL | use foo::test2::test::g; - | -LL | use foo::test::g; - | error[E0425]: cannot find function `f` in this scope --> $DIR/globs.rs:61:12 diff --git a/src/test/ui/issues/issue-26545.rs b/src/test/ui/issues/issue-26545.rs new file mode 100644 index 0000000000000..5652ee7470605 --- /dev/null +++ b/src/test/ui/issues/issue-26545.rs @@ -0,0 +1,12 @@ +mod foo { + pub struct B(pub ()); +} + +mod baz { + fn foo() { + B(()); + //~^ ERROR cannot find function, tuple struct or tuple variant `B` in this scope [E0425] + } +} + +fn main() {} diff --git a/src/test/ui/issues/issue-26545.stderr b/src/test/ui/issues/issue-26545.stderr new file mode 100644 index 0000000000000..d3c86692501d6 --- /dev/null +++ b/src/test/ui/issues/issue-26545.stderr @@ -0,0 +1,14 @@ +error[E0425]: cannot find function, tuple struct or tuple variant `B` in this scope + --> $DIR/issue-26545.rs:7:9 + | +LL | B(()); + | ^ not found in this scope + | +help: consider importing this tuple struct + | +LL | use foo::B; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/issues/issue-35675.rs b/src/test/ui/issues/issue-35675.rs index 7876811a9ac39..683761667d40a 100644 --- a/src/test/ui/issues/issue-35675.rs +++ b/src/test/ui/issues/issue-35675.rs @@ -33,7 +33,7 @@ fn qux() -> Some { fn main() {} mod x { - enum Enum { + pub enum Enum { Variant1, Variant2(), Variant3(usize), diff --git a/src/test/ui/issues/issue-42944.rs b/src/test/ui/issues/issue-42944.rs index cc365dc4c938e..a088f91554dfb 100644 --- a/src/test/ui/issues/issue-42944.rs +++ b/src/test/ui/issues/issue-42944.rs @@ -1,20 +1,20 @@ mod foo { - pub struct B(()); + pub struct Bx(()); } mod bar { - use foo::B; + use foo::Bx; fn foo() { - B(()); - //~^ ERROR expected function, tuple struct or tuple variant, found struct `B` [E0423] + Bx(()); + //~^ ERROR expected function, tuple struct or tuple variant, found struct `Bx` [E0423] } } mod baz { fn foo() { - B(()); - //~^ ERROR cannot find function, tuple struct or tuple variant `B` in this scope [E0425] + Bx(()); + //~^ ERROR cannot find function, tuple struct or tuple variant `Bx` in this scope [E0425] } } diff --git a/src/test/ui/issues/issue-42944.stderr b/src/test/ui/issues/issue-42944.stderr index e7e251e39c04f..9fad43757ba62 100644 --- a/src/test/ui/issues/issue-42944.stderr +++ b/src/test/ui/issues/issue-42944.stderr @@ -1,18 +1,18 @@ -error[E0423]: expected function, tuple struct or tuple variant, found struct `B` +error[E0423]: expected function, tuple struct or tuple variant, found struct `Bx` --> $DIR/issue-42944.rs:9:9 | -LL | B(()); - | ^ constructor is not visible here due to private fields +LL | Bx(()); + | ^^ constructor is not visible here due to private fields -error[E0425]: cannot find function, tuple struct or tuple variant `B` in this scope +error[E0425]: cannot find function, tuple struct or tuple variant `Bx` in this scope --> $DIR/issue-42944.rs:16:9 | -LL | B(()); - | ^ not found in this scope +LL | Bx(()); + | ^^ not found in this scope | help: consider importing this tuple struct | -LL | use foo::B; +LL | use foo::Bx; | error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-4366-2.stderr b/src/test/ui/issues/issue-4366-2.stderr index ecee595d4ab6a..a86ec7fabea4b 100644 --- a/src/test/ui/issues/issue-4366-2.stderr +++ b/src/test/ui/issues/issue-4366-2.stderr @@ -15,12 +15,10 @@ error[E0423]: expected function, found module `foo` LL | foo(); | ^^^ not a function | -help: consider importing one of these items instead +help: consider importing this function instead | LL | use foo::foo; | -LL | use m1::foo; - | error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-4366.stderr b/src/test/ui/issues/issue-4366.stderr index a094180572daa..469ea93e90468 100644 --- a/src/test/ui/issues/issue-4366.stderr +++ b/src/test/ui/issues/issue-4366.stderr @@ -4,12 +4,10 @@ error[E0425]: cannot find function `foo` in this scope LL | fn sub() -> isize { foo(); 1 } | ^^^ not found in this scope | -help: consider importing one of these items +help: consider importing this function | LL | use foo::foo; | -LL | use m1::foo; - | error: aborting due to previous error diff --git a/src/test/ui/issues/issue-44078.stderr b/src/test/ui/issues/issue-44078.stderr index 43b49e463128f..daf67219f4d0a 100644 --- a/src/test/ui/issues/issue-44078.stderr +++ b/src/test/ui/issues/issue-44078.stderr @@ -1,4 +1,4 @@ -error: unterminated double quote string +error[E0765]: unterminated double quote string --> $DIR/issue-44078.rs:2:8 | LL | "😊""; @@ -8,3 +8,4 @@ LL | | } error: aborting due to previous error +For more information about this error, try `rustc --explain E0765`. diff --git a/src/test/ui/parser/unbalanced-doublequote.stderr b/src/test/ui/parser/unbalanced-doublequote.stderr index 4d98515c224ad..94b300a7bd765 100644 --- a/src/test/ui/parser/unbalanced-doublequote.stderr +++ b/src/test/ui/parser/unbalanced-doublequote.stderr @@ -1,4 +1,4 @@ -error: unterminated double quote string +error[E0765]: unterminated double quote string --> $DIR/unbalanced-doublequote.rs:5:5 | LL | / " @@ -7,3 +7,4 @@ LL | | } error: aborting due to previous error +For more information about this error, try `rustc --explain E0765`. diff --git a/src/test/ui/privacy/privacy-ns1.stderr b/src/test/ui/privacy/privacy-ns1.stderr index 4d2af735fa6b9..eda9d4c128d81 100644 --- a/src/test/ui/privacy/privacy-ns1.stderr +++ b/src/test/ui/privacy/privacy-ns1.stderr @@ -11,14 +11,10 @@ help: a unit struct with a similar name exists | LL | Baz(); | ^^^ -help: consider importing one of these items instead - | -LL | use foo1::Bar; +help: consider importing this function instead | LL | use foo2::Bar; | -LL | use foo3::Bar; - | error[E0425]: cannot find function, tuple struct or tuple variant `Bar` in this scope --> $DIR/privacy-ns1.rs:51:5 @@ -33,14 +29,10 @@ help: a unit struct with a similar name exists | LL | Baz(); | ^^^ -help: consider importing one of these items - | -LL | use foo1::Bar; +help: consider importing this function | LL | use foo2::Bar; | -LL | use foo3::Bar; - | error[E0412]: cannot find type `Bar` in this scope --> $DIR/privacy-ns1.rs:52:17 @@ -55,14 +47,10 @@ help: a struct with a similar name exists | LL | let _x: Box; | ^^^ -help: consider importing one of these items +help: consider importing this trait | LL | use foo1::Bar; | -LL | use foo2::Bar; - | -LL | use foo3::Bar; - | error[E0107]: wrong number of const arguments: expected 0, found 1 --> $DIR/privacy-ns1.rs:35:17 diff --git a/src/test/ui/privacy/privacy-ns2.stderr b/src/test/ui/privacy/privacy-ns2.stderr index f1aa523742ae4..d7d9b83527509 100644 --- a/src/test/ui/privacy/privacy-ns2.stderr +++ b/src/test/ui/privacy/privacy-ns2.stderr @@ -4,14 +4,10 @@ error[E0423]: expected function, tuple struct or tuple variant, found trait `Bar LL | Bar(); | ^^^ not a function, tuple struct or tuple variant | -help: consider importing one of these items instead - | -LL | use foo1::Bar; +help: consider importing this function instead | LL | use foo2::Bar; | -LL | use foo3::Bar; - | error[E0423]: expected function, tuple struct or tuple variant, found trait `Bar` --> $DIR/privacy-ns2.rs:26:5 @@ -26,14 +22,10 @@ help: a unit struct with a similar name exists | LL | Baz(); | ^^^ -help: consider importing one of these items instead - | -LL | use foo1::Bar; +help: consider importing this function instead | LL | use foo2::Bar; | -LL | use foo3::Bar; - | error[E0573]: expected type, found function `Bar` --> $DIR/privacy-ns2.rs:43:14 @@ -45,14 +37,10 @@ help: use `=` if you meant to assign | LL | let _x = Bar(); | ^ -help: consider importing one of these items instead +help: consider importing this trait instead | LL | use foo1::Bar; | -LL | use foo2::Bar; - | -LL | use foo3::Bar; - | error[E0603]: trait `Bar` is private --> $DIR/privacy-ns2.rs:63:15 diff --git a/src/test/ui/resolve/issue-21221-1.stderr b/src/test/ui/resolve/issue-21221-1.stderr index d3e1953435359..538eeead9fc9d 100644 --- a/src/test/ui/resolve/issue-21221-1.stderr +++ b/src/test/ui/resolve/issue-21221-1.stderr @@ -25,11 +25,8 @@ LL | use mul1::Mul; | LL | use mul2::Mul; | -LL | use mul3::Mul; - | -LL | use mul4::Mul; +LL | use std::ops::Mul; | - and 2 other candidates error[E0405]: cannot find trait `ThisTraitReallyDoesntExistInAnyModuleReally` in this scope --> $DIR/issue-21221-1.rs:63:6 diff --git a/triagebot.toml b/triagebot.toml index fc2dbb8d4402d..5361a618d4e85 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -113,7 +113,7 @@ topic = "P-critical #{number} {title}" message_on_add = "@*WG-prioritization* issue #{number} has been assigned `P-critical`." [notify-zulip."P-high"] -required_labels = ["regression-from-stable-to-*"] +required_labels = ["regression-from-stable-to-[bn]*"] # only nightly and beta regressions zulip_stream = 227806 # #t-compiler/wg-prioritization topic = "P-high regression #{number} {title}" message_on_add = "@*WG-prioritization* issue #{number} has been assigned `P-high` and is a regression."