Auto merge of #110967 - matthiaskrgr:rollup-vfbl7gm, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - #110877 (Provide better type hints when a type doesn't support a binary operator)
 - #110917 (only error combining +whole-archive and +bundle for rlibs)
 - #110921 (Use `NonNull::new_unchecked` and `NonNull::len` in `rustc_arena`.)
 - #110927 (Encoder/decoder cleanups)
 - #110944 (share BinOp::Offset between CTFE and Miri)
 - #110948 (run-make test: using single quotes to not trigger the shell)
 - #110957 (Fix an ICE in conflict error diagnostics)
 - #110960 (fix false negative for `unused_mut`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-04-28 23:13:42 +00:00
commit 7a96158b53
48 changed files with 449 additions and 342 deletions

View File

@ -74,7 +74,7 @@ impl<T> ArenaChunk<T> {
#[inline]
unsafe fn new(capacity: usize) -> ArenaChunk<T> {
ArenaChunk {
storage: NonNull::new(Box::into_raw(Box::new_uninit_slice(capacity))).unwrap(),
storage: NonNull::new_unchecked(Box::into_raw(Box::new_uninit_slice(capacity))),
entries: 0,
}
}
@ -85,7 +85,7 @@ impl<T> ArenaChunk<T> {
// The branch on needs_drop() is an -O1 performance optimization.
// Without the branch, dropping TypedArena<u8> takes linear time.
if mem::needs_drop::<T>() {
let slice = &mut *(self.storage.as_mut());
let slice = self.storage.as_mut();
ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(&mut slice[..len]));
}
}
@ -104,7 +104,7 @@ impl<T> ArenaChunk<T> {
// A pointer as large as possible for zero-sized elements.
ptr::invalid_mut(!0)
} else {
self.start().add((*self.storage.as_ptr()).len())
self.start().add(self.storage.len())
}
}
}
@ -288,7 +288,7 @@ impl<T> TypedArena<T> {
// If the previous chunk's len is less than HUGE_PAGE
// bytes, then this chunk will be least double the previous
// chunk's size.
new_cap = (*last_chunk.storage.as_ptr()).len().min(HUGE_PAGE / elem_size / 2);
new_cap = last_chunk.storage.len().min(HUGE_PAGE / elem_size / 2);
new_cap *= 2;
} else {
new_cap = PAGE / elem_size;
@ -396,7 +396,7 @@ impl DroplessArena {
// If the previous chunk's len is less than HUGE_PAGE
// bytes, then this chunk will be least double the previous
// chunk's size.
new_cap = (*last_chunk.storage.as_ptr()).len().min(HUGE_PAGE / 2);
new_cap = last_chunk.storage.len().min(HUGE_PAGE / 2);
new_cap *= 2;
} else {
new_cap = PAGE;

View File

@ -360,7 +360,7 @@ impl Printer {
fn check_stack(&mut self, mut depth: usize) {
while let Some(&index) = self.scan_stack.back() {
let mut entry = &mut self.buf[index];
let entry = &mut self.buf[index];
match entry.token {
Token::Begin(_) => {
if depth == 0 {

View File

@ -1359,7 +1359,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
// Get closure's arguments
let ty::Closure(_, substs) = typeck_results.expr_ty(closure_expr).kind() else { unreachable!() };
let ty::Closure(_, substs) = typeck_results.expr_ty(closure_expr).kind() else { /* hir::Closure can be a generator too */ return };
let sig = substs.as_closure().sig();
let tupled_params =
tcx.erase_late_bound_regions(sig.inputs().iter().next().unwrap().map_bound(|&b| b));

View File

@ -935,6 +935,7 @@ enum InitializationRequiringAction {
PartialAssignment,
}
#[derive(Debug)]
struct RootPlace<'tcx> {
place_local: Local,
place_projection: &'tcx [PlaceElem<'tcx>],
@ -1848,11 +1849,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// is allowed, remove this match arm.
ty::Adt(..) | ty::Tuple(..) => {
check_parent_of_field(self, location, place_base, span, flow_state);
// rust-lang/rust#21232, #54499, #54986: during period where we reject
// partial initialization, do not complain about unnecessary `mut` on
// an attempt to do a partial initialization.
self.used_mut.insert(place.local);
}
_ => {}
@ -1940,6 +1936,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
(prefix, base, span),
mpi,
);
// rust-lang/rust#21232, #54499, #54986: during period where we reject
// partial initialization, do not complain about unnecessary `mut` on
// an attempt to do a partial initialization.
this.used_mut.insert(base.local);
}
}
}

View File

@ -221,7 +221,7 @@ fn append_list(
) {
let mut p = target_list;
loop {
let mut r = &mut constraints[p];
let r = &mut constraints[p];
match r.next_constraint {
Some(q) => p = q,
None => {

View File

@ -349,7 +349,10 @@ fn link_rlib<'a>(
let NativeLibKind::Static { bundle: None | Some(true), whole_archive } = lib.kind else {
continue;
};
if whole_archive == Some(true) && !codegen_results.crate_info.feature_packed_bundled_libs {
if whole_archive == Some(true)
&& flavor == RlibFlavor::Normal
&& !codegen_results.crate_info.feature_packed_bundled_libs
{
sess.emit_err(errors::IncompatibleLinkingModifiers);
}
if flavor == RlibFlavor::Normal && let Some(filename) = lib.filename {

View File

@ -559,20 +559,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
}
fn binary_ptr_op(
ecx: &InterpCx<'mir, 'tcx, Self>,
bin_op: mir::BinOp,
left: &ImmTy<'tcx>,
right: &ImmTy<'tcx>,
_ecx: &InterpCx<'mir, 'tcx, Self>,
_bin_op: mir::BinOp,
_left: &ImmTy<'tcx>,
_right: &ImmTy<'tcx>,
) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> {
if bin_op == mir::BinOp::Offset {
let ptr = left.to_scalar().to_pointer(ecx)?;
let offset_count = right.to_scalar().to_target_isize(ecx)?;
let pointee_ty = left.layout.ty.builtin_deref(true).unwrap().ty;
let offset_ptr = ecx.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?;
return Ok((Scalar::from_maybe_pointer(offset_ptr, ecx), false, left.layout.ty));
}
throw_unsup_format!("pointer arithmetic or comparison is not supported at compile-time");
}

View File

@ -299,6 +299,30 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Ok((val, false, ty))
}
fn binary_ptr_op(
&self,
bin_op: mir::BinOp,
left: &ImmTy<'tcx, M::Provenance>,
right: &ImmTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx, (Scalar<M::Provenance>, bool, Ty<'tcx>)> {
use rustc_middle::mir::BinOp::*;
match bin_op {
// Pointer ops that are always supported.
Offset => {
let ptr = left.to_scalar().to_pointer(self)?;
let offset_count = right.to_scalar().to_target_isize(self)?;
let pointee_ty = left.layout.ty.builtin_deref(true).unwrap().ty;
let offset_ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?;
Ok((Scalar::from_maybe_pointer(offset_ptr, self), false, left.layout.ty))
}
// Fall back to machine hook so Miri can support more pointer ops.
_ => M::binary_ptr_op(self, bin_op, left, right),
}
}
/// Returns the result of the specified operation, whether it overflowed, and
/// the result type.
pub fn overflowing_binary_op(
@ -368,7 +392,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
right.layout.ty
);
M::binary_ptr_op(self, bin_op, left, right)
self.binary_ptr_op(bin_op, left, right)
}
_ => span_bug!(
self.cur_span(),

View File

@ -26,7 +26,7 @@ use rustc_target::spec::abi::Abi;
use smallvec::SmallVec;
use std::fmt;
#[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)]
#[derive(Debug, Copy, Clone, HashStable_Generic)]
pub struct Lifetime {
pub hir_id: HirId,
@ -41,8 +41,7 @@ pub struct Lifetime {
pub res: LifetimeName,
}
#[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)]
#[derive(HashStable_Generic)]
#[derive(Debug, Copy, Clone, HashStable_Generic)]
pub enum ParamName {
/// Some user-given name like `T` or `'x`.
Plain(Ident),
@ -85,8 +84,7 @@ impl ParamName {
}
}
#[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)]
#[derive(HashStable_Generic)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)]
pub enum LifetimeName {
/// User-given names or fresh (synthetic) names.
Param(LocalDefId),
@ -243,13 +241,13 @@ impl<'hir> PathSegment<'hir> {
}
}
#[derive(Encodable, Clone, Copy, Debug, HashStable_Generic)]
#[derive(Clone, Copy, Debug, HashStable_Generic)]
pub struct ConstArg {
pub value: AnonConst,
pub span: Span,
}
#[derive(Encodable, Clone, Copy, Debug, HashStable_Generic)]
#[derive(Clone, Copy, Debug, HashStable_Generic)]
pub struct InferArg {
pub hir_id: HirId,
pub span: Span,
@ -422,8 +420,7 @@ impl<'hir> GenericArgs<'hir> {
}
}
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)]
#[derive(HashStable_Generic)]
#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable_Generic)]
pub enum GenericArgsParentheses {
No,
/// Bounds for `feature(return_type_notation)`, like `T: Trait<method(..): Send>`,
@ -435,8 +432,7 @@ pub enum GenericArgsParentheses {
/// A modifier on a bound, currently this is only used for `?Sized`, where the
/// modifier is `Maybe`. Negative bounds should also be handled here.
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)]
#[derive(HashStable_Generic)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub enum TraitBoundModifier {
None,
Maybe,
@ -474,7 +470,7 @@ impl GenericBound<'_> {
pub type GenericBounds<'hir> = &'hir [GenericBound<'hir>];
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub enum LifetimeParamKind {
// Indicates that the lifetime definition was explicitly declared (e.g., in
// `fn foo<'a>(x: &'a u8) -> &'a u8 { x }`).
@ -539,7 +535,7 @@ impl<'hir> GenericParam<'hir> {
/// early-bound (but can be a late-bound lifetime in functions, for example),
/// or from a `for<...>` binder, in which case it's late-bound (and notably,
/// does not show up in the parent item's generics).
#[derive(Debug, HashStable_Generic, PartialEq, Eq, Copy, Clone)]
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub enum GenericParamSource {
// Early or late-bound parameters defined on an item
Generics,
@ -1097,7 +1093,7 @@ pub struct PatField<'hir> {
pub span: Span,
}
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
pub enum RangeEnd {
Included,
Excluded,
@ -1197,7 +1193,7 @@ pub enum PatKind<'hir> {
Slice(&'hir [Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [Pat<'hir>]),
}
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
pub enum BinOpKind {
/// The `+` operator (addition).
Add,
@ -1325,7 +1321,7 @@ impl Into<ast::BinOpKind> for BinOpKind {
pub type BinOp = Spanned<BinOpKind>;
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
pub enum UnOp {
/// The `*` operator (dereferencing).
Deref,
@ -1450,19 +1446,19 @@ pub struct ExprField<'hir> {
pub is_shorthand: bool,
}
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
pub enum BlockCheckMode {
DefaultBlock,
UnsafeBlock(UnsafeSource),
}
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
pub enum UnsafeSource {
CompilerGenerated,
UserProvided,
}
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct BodyId {
pub hir_id: HirId,
}
@ -1506,7 +1502,7 @@ impl<'hir> Body<'hir> {
}
/// The type of source expression that caused this generator to be created.
#[derive(Clone, PartialEq, PartialOrd, Eq, Hash, Debug, Copy)]
#[derive(Clone, PartialEq, Eq, Debug, Copy, Hash)]
#[derive(HashStable_Generic, Encodable, Decodable)]
pub enum GeneratorKind {
/// An explicit `async` block or the body of an async function.
@ -1539,7 +1535,7 @@ impl GeneratorKind {
///
/// This helps error messages but is also used to drive coercions in
/// type-checking (see #60424).
#[derive(Clone, PartialEq, PartialOrd, Eq, Hash, Debug, Copy)]
#[derive(Clone, PartialEq, Eq, Hash, Debug, Copy)]
#[derive(HashStable_Generic, Encodable, Decodable)]
pub enum AsyncGeneratorKind {
/// An explicit `async` block written by the user.
@ -1649,7 +1645,7 @@ impl fmt::Display for ConstContext {
/// A literal.
pub type Lit = Spanned<LitKind>;
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub enum ArrayLen {
Infer(HirId, Span),
Body(AnonConst),
@ -1671,7 +1667,7 @@ impl ArrayLen {
///
/// You can check if this anon const is a default in a const param
/// `const N: usize = { ... }` with `tcx.hir().opt_const_param_default_param_def_id(..)`
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub struct AnonConst {
pub hir_id: HirId,
pub def_id: LocalDefId,
@ -2105,7 +2101,7 @@ impl<'hir> QPath<'hir> {
}
/// Hints at the original code for a let statement.
#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub enum LocalSource {
/// A `match _ { .. }`.
Normal,
@ -2158,7 +2154,7 @@ impl MatchSource {
}
/// The loop type that yielded an `ExprKind::Loop`.
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
pub enum LoopSource {
/// A `loop { .. }` loop.
Loop,
@ -2178,7 +2174,7 @@ impl LoopSource {
}
}
#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub enum LoopIdError {
OutsideLoopScope,
UnlabeledCfInWhileCondition,
@ -2197,7 +2193,7 @@ impl fmt::Display for LoopIdError {
}
}
#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub struct Destination {
/// This is `Some(_)` iff there is an explicit user-specified 'label
pub label: Option<Label>,
@ -2208,7 +2204,7 @@ pub struct Destination {
}
/// The yield kind that caused an `ExprKind::Yield`.
#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable, Decodable, HashStable_Generic)]
#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub enum YieldSource {
/// An `<expr>.await`.
Await { expr: Option<HirId> },
@ -2327,7 +2323,7 @@ impl<'hir> TraitItem<'hir> {
}
/// Represents a trait method's body (or just argument names).
#[derive(Encodable, Debug, Clone, Copy, HashStable_Generic)]
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub enum TraitFn<'hir> {
/// No default body in the trait, just a signature.
Required(&'hir [Ident]),
@ -2658,7 +2654,7 @@ pub struct OpaqueTy<'hir> {
}
/// From whence the opaque type came.
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable_Generic)]
pub enum OpaqueTyOrigin {
/// `-> impl Trait`
FnReturn(LocalDefId),
@ -2818,7 +2814,7 @@ impl ImplicitSelfKind {
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
#[derive(HashStable_Generic)]
pub enum IsAsync {
Async,
@ -2831,7 +2827,7 @@ impl IsAsync {
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)]
#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable, Decodable, HashStable_Generic)]
pub enum Defaultness {
Default { has_value: bool },
Final,
@ -2887,13 +2883,13 @@ pub enum ClosureBinder {
For { span: Span },
}
#[derive(Encodable, Debug, Clone, Copy, HashStable_Generic)]
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct Mod<'hir> {
pub spans: ModSpans,
pub item_ids: &'hir [ItemId],
}
#[derive(Copy, Clone, Debug, HashStable_Generic, Encodable)]
#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub struct ModSpans {
/// A span from the first token past `{` to the last token until `}`.
/// For `mod foo;`, the inner span ranges from the first token
@ -2922,7 +2918,7 @@ pub struct Variant<'hir> {
pub span: Span,
}
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
pub enum UseKind {
/// One import, e.g., `use foo::bar` or `use foo::bar as baz`.
/// Also produced for each element of a list `use`, e.g.
@ -3233,7 +3229,7 @@ impl fmt::Display for Unsafety {
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[derive(Encodable, Decodable, HashStable_Generic)]
pub enum Constness {
Const,
@ -3249,7 +3245,7 @@ impl fmt::Display for Constness {
}
}
#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub struct FnHeader {
pub unsafety: Unsafety,
pub constness: Constness,
@ -3381,7 +3377,7 @@ impl ItemKind<'_> {
/// type or method, and whether it is public). This allows other
/// passes to find the impl they want without loading the ID (which
/// means fewer edges in the incremental compilation graph).
#[derive(Encodable, Debug, Clone, Copy, HashStable_Generic)]
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct TraitItemRef {
pub id: TraitItemId,
pub ident: Ident,
@ -3405,7 +3401,7 @@ pub struct ImplItemRef {
pub trait_item_def_id: Option<DefId>,
}
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
pub enum AssocItemKind {
Const,
Fn { has_self: bool },
@ -3474,7 +3470,7 @@ pub enum ForeignItemKind<'hir> {
}
/// A variable captured by a closure.
#[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)]
#[derive(Debug, Copy, Clone, HashStable_Generic)]
pub struct Upvar {
/// First span where it is accessed (there can be multiple).
pub span: Span,
@ -3483,7 +3479,7 @@ pub struct Upvar {
// The TraitCandidate's import_ids is empty if the trait is defined in the same module, and
// has length > 0 if the trait is found through an chain of imports, starting with the
// import/use statement in the scope where the trait is used.
#[derive(Encodable, Decodable, Debug, Clone, HashStable_Generic)]
#[derive(Debug, Clone, HashStable_Generic)]
pub struct TraitCandidate {
pub def_id: DefId,
pub import_ids: SmallVec<[LocalDefId; 1]>,

View File

@ -421,7 +421,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
let target_scopes = visitor.fixup_scopes.drain(start_point..);
for scope in target_scopes {
let mut yield_data =
let yield_data =
visitor.scope_tree.yield_in_scope.get_mut(&scope).unwrap().last_mut().unwrap();
let count = yield_data.expr_and_pat_count;
let span = yield_data.span;

View File

@ -455,15 +455,9 @@ fn fatally_break_rust(sess: &Session) {
));
}
fn has_expected_num_generic_args(
tcx: TyCtxt<'_>,
trait_did: Option<DefId>,
expected: usize,
) -> bool {
trait_did.map_or(true, |trait_did| {
let generics = tcx.generics_of(trait_did);
generics.count() == expected + if generics.has_self { 1 } else { 0 }
})
fn has_expected_num_generic_args(tcx: TyCtxt<'_>, trait_did: DefId, expected: usize) -> bool {
let generics = tcx.generics_of(trait_did);
generics.count() == expected + if generics.has_self { 1 } else { 0 }
}
pub fn provide(providers: &mut Providers) {

View File

@ -27,8 +27,8 @@ use rustc_middle::traits::util::supertraits;
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
use rustc_middle::ty::IsSuggestable;
use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Symbol;
use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span};
@ -2068,7 +2068,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut derives = Vec::<(String, Span, Symbol)>::new();
let mut traits = Vec::new();
for (pred, _, _) in unsatisfied_predicates {
let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() else { continue };
let Some(ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred))) =
pred.kind().no_bound_vars()
else {
continue
};
let adt = match trait_pred.self_ty().ty_adt_def() {
Some(adt) if adt.did().is_local() => adt,
_ => continue,
@ -2085,22 +2089,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| sym::Hash
| sym::Debug => true,
_ => false,
} && match trait_pred.trait_ref.substs.as_slice() {
// Only suggest deriving if lhs == rhs...
[lhs, rhs] => {
if let Some(lhs) = lhs.as_type()
&& let Some(rhs) = rhs.as_type()
{
self.can_eq(self.param_env, lhs, rhs)
} else {
false
}
},
// Unary ops can always be derived
[_] => true,
_ => false,
};
if can_derive {
let self_name = trait_pred.self_ty().to_string();
let self_span = self.tcx.def_span(adt.did());
if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
for super_trait in
supertraits(self.tcx, ty::Binder::dummy(trait_pred.trait_ref))
{
if let Some(parent_diagnostic_name) =
self.tcx.get_diagnostic_name(super_trait.def_id())
{
if let Some(parent_diagnostic_name) =
self.tcx.get_diagnostic_name(super_trait.def_id())
{
derives.push((
self_name.clone(),
self_span,
parent_diagnostic_name,
));
}
derives.push((self_name.clone(), self_span, parent_diagnostic_name));
}
}
derives.push((self_name, self_span, diagnostic_name));

View File

@ -408,7 +408,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
};
let is_compatible = |lhs_ty, rhs_ty| {
let is_compatible_after_call = |lhs_ty, rhs_ty| {
self.lookup_op_method(
lhs_ty,
Some((rhs_expr, rhs_ty)),
@ -416,6 +416,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected,
)
.is_ok()
// Suggest calling even if, after calling, the types don't
// implement the operator, since it'll lead to better
// diagnostics later.
|| self.can_eq(self.param_env, lhs_ty, rhs_ty)
};
// We should suggest `a + b` => `*a + b` if `a` is copy, and suggest
@ -436,16 +440,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
suggest_deref_binop(*lhs_deref_ty);
}
} else if self.suggest_fn_call(&mut err, lhs_expr, lhs_ty, |lhs_ty| {
is_compatible(lhs_ty, rhs_ty)
is_compatible_after_call(lhs_ty, rhs_ty)
}) || self.suggest_fn_call(&mut err, rhs_expr, rhs_ty, |rhs_ty| {
is_compatible(lhs_ty, rhs_ty)
is_compatible_after_call(lhs_ty, rhs_ty)
}) || self.suggest_two_fn_call(
&mut err,
rhs_expr,
rhs_ty,
lhs_expr,
lhs_ty,
|lhs_ty, rhs_ty| is_compatible(lhs_ty, rhs_ty),
|lhs_ty, rhs_ty| is_compatible_after_call(lhs_ty, rhs_ty),
) {
// Cool
}
@ -719,7 +723,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Op::Binary(op, _) => op.span,
Op::Unary(_, span) => span,
};
let (opname, trait_did) = lang_item_for_op(self.tcx, op, span);
let (opname, Some(trait_did)) = lang_item_for_op(self.tcx, op, span) else {
// Bail if the operator trait is not defined.
return Err(vec![]);
};
debug!(
"lookup_op_method(lhs_ty={:?}, op={:?}, opname={:?}, trait_did={:?})",
@ -759,18 +766,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
},
);
let method = trait_did.and_then(|trait_did| {
self.lookup_method_in_trait(cause.clone(), opname, trait_did, lhs_ty, Some(input_types))
});
match (method, trait_did) {
(Some(ok), _) => {
let method = self.lookup_method_in_trait(
cause.clone(),
opname,
trait_did,
lhs_ty,
Some(input_types),
);
match method {
Some(ok) => {
let method = self.register_infer_ok_obligations(ok);
self.select_obligations_where_possible(|_| {});
Ok(method)
}
(None, None) => Err(vec![]),
(None, Some(trait_did)) => {
None => {
// This path may do some inference, so make sure we've really
// doomed compilation so as to not accidentally stabilize new
// inference or something here...
self.tcx.sess.delay_span_bug(span, "this path really should be doomed...");
// Guide inference for the RHS expression if it's provided --
// this will allow us to better error reporting, at the expense
// of making some error messages a bit more specific.
if let Some((rhs_expr, rhs_ty)) = opt_rhs
&& rhs_ty.is_ty_var()
{
self.check_expr_coercible_to_type(rhs_expr, rhs_ty, None);
}
let (obligation, _) =
self.obligation_for_method(cause, trait_did, lhs_ty, Some(input_types));
// FIXME: This should potentially just add the obligation to the `FnCtxt`

View File

@ -200,9 +200,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
debug!("try_overloaded_place_op({:?},{:?},{:?})", span, base_ty, op);
let (imm_tr, imm_op) = match op {
let (Some(imm_tr), imm_op) = (match op {
PlaceOp::Deref => (self.tcx.lang_items().deref_trait(), sym::deref),
PlaceOp::Index => (self.tcx.lang_items().index_trait(), sym::index),
}) else {
// Bail if `Deref` or `Index` isn't defined.
return None;
};
// If the lang item was declared incorrectly, stop here so that we don't
@ -219,15 +222,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return None;
}
imm_tr.and_then(|trait_did| {
self.lookup_method_in_trait(
self.misc(span),
Ident::with_dummy_span(imm_op),
trait_did,
base_ty,
Some(arg_tys),
)
})
self.lookup_method_in_trait(
self.misc(span),
Ident::with_dummy_span(imm_op),
imm_tr,
base_ty,
Some(arg_tys),
)
}
fn try_mutable_overloaded_place_op(
@ -239,9 +240,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
debug!("try_mutable_overloaded_place_op({:?},{:?},{:?})", span, base_ty, op);
let (mut_tr, mut_op) = match op {
let (Some(mut_tr), mut_op) = (match op {
PlaceOp::Deref => (self.tcx.lang_items().deref_mut_trait(), sym::deref_mut),
PlaceOp::Index => (self.tcx.lang_items().index_mut_trait(), sym::index_mut),
}) else {
// Bail if `DerefMut` or `IndexMut` isn't defined.
return None;
};
// If the lang item was declared incorrectly, stop here so that we don't
@ -258,15 +262,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return None;
}
mut_tr.and_then(|trait_did| {
self.lookup_method_in_trait(
self.misc(span),
Ident::with_dummy_span(mut_op),
trait_did,
base_ty,
Some(arg_tys),
)
})
self.lookup_method_in_trait(
self.misc(span),
Ident::with_dummy_span(mut_op),
mut_tr,
base_ty,
Some(arg_tys),
)
}
/// Convert auto-derefs, indices, etc of an expression from `Deref` and `Index`

View File

@ -203,7 +203,7 @@ impl Scope {
pub type ScopeDepth = u32;
/// The region scope tree encodes information about region relationships.
#[derive(TyEncodable, TyDecodable, Default, Debug)]
#[derive(Default, Debug)]
pub struct ScopeTree {
/// If not empty, this body is the root of this region hierarchy.
pub root_body: Option<hir::HirId>,
@ -317,13 +317,13 @@ pub struct ScopeTree {
/// candidates in general). In constants, the `lifetime` field is None
/// to indicate that certain expressions escape into 'static and
/// should have no local cleanup scope.
#[derive(Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
#[derive(Debug, Copy, Clone, HashStable)]
pub enum RvalueCandidateType {
Borrow { target: hir::ItemLocalId, lifetime: Option<Scope> },
Pattern { target: hir::ItemLocalId, lifetime: Option<Scope> },
}
#[derive(Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
#[derive(Debug, Copy, Clone, HashStable)]
pub struct YieldData {
/// The `Span` of the yield.
pub span: Span,

View File

@ -199,7 +199,7 @@ impl<'tcx> ObligationCause<'tcx> {
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
#[derive(Clone, Debug, PartialEq, Eq, Lift, HashStable, TyEncodable, TyDecodable)]
#[derive(TypeVisitable, TypeFoldable)]
pub struct UnifyReceiverContext<'tcx> {
pub assoc_item: ty::AssocItem,
@ -207,7 +207,7 @@ pub struct UnifyReceiverContext<'tcx> {
pub substs: SubstsRef<'tcx>,
}
#[derive(Clone, PartialEq, Eq, Hash, Lift, Default, HashStable)]
#[derive(Clone, PartialEq, Eq, Lift, Default, HashStable)]
#[derive(TypeVisitable, TypeFoldable, TyEncodable, TyDecodable)]
pub struct InternedObligationCauseCode<'tcx> {
/// `None` for `ObligationCauseCode::MiscObligation` (a common case, occurs ~60% of
@ -243,7 +243,7 @@ impl<'tcx> std::ops::Deref for InternedObligationCauseCode<'tcx> {
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
#[derive(Clone, Debug, PartialEq, Eq, Lift, HashStable, TyEncodable, TyDecodable)]
#[derive(TypeVisitable, TypeFoldable)]
pub enum ObligationCauseCode<'tcx> {
/// Not well classified or should be obvious from the span.
@ -468,7 +468,7 @@ pub enum WellFormedLoc {
},
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
#[derive(Clone, Debug, PartialEq, Eq, Lift, HashStable, TyEncodable, TyDecodable)]
#[derive(TypeVisitable, TypeFoldable)]
pub struct ImplDerivedObligationCause<'tcx> {
pub derived: DerivedObligationCause<'tcx>,
@ -529,7 +529,7 @@ impl<'tcx> ty::Lift<'tcx> for StatementAsExpression {
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
#[derive(Clone, Debug, PartialEq, Eq, Lift, HashStable, TyEncodable, TyDecodable)]
#[derive(TypeVisitable, TypeFoldable)]
pub struct MatchExpressionArmCause<'tcx> {
pub arm_block_id: Option<hir::HirId>,
@ -545,7 +545,7 @@ pub struct MatchExpressionArmCause<'tcx> {
pub opt_suggest_box_span: Option<Span>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(Lift, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
pub struct IfExpressionCause<'tcx> {
pub then_id: hir::HirId,
@ -556,7 +556,7 @@ pub struct IfExpressionCause<'tcx> {
pub opt_suggest_box_span: Option<Span>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
#[derive(Clone, Debug, PartialEq, Eq, Lift, HashStable, TyEncodable, TyDecodable)]
#[derive(TypeVisitable, TypeFoldable)]
pub struct DerivedObligationCause<'tcx> {
/// The trait predicate of the parent obligation that led to the

View File

@ -188,7 +188,7 @@ impl<'tcx> AdtDef<'tcx> {
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, HashStable, TyEncodable, TyDecodable)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable, TyEncodable, TyDecodable)]
pub enum AdtKind {
Struct,
Union,

View File

@ -51,13 +51,6 @@ macro_rules! write_leb128 {
}};
}
/// A byte that [cannot occur in UTF8 sequences][utf8]. Used to mark the end of a string.
/// This way we can skip validation and still be relatively sure that deserialization
/// did not desynchronize.
///
/// [utf8]: https://en.wikipedia.org/w/index.php?title=UTF-8&oldid=1058865525#Codepage_layout
const STR_SENTINEL: u8 = 0xC1;
impl Encoder for MemEncoder {
#[inline]
fn emit_usize(&mut self, v: usize) {
@ -114,28 +107,6 @@ impl Encoder for MemEncoder {
self.data.extend_from_slice(&v.to_le_bytes());
}
#[inline]
fn emit_i8(&mut self, v: i8) {
self.emit_u8(v as u8);
}
#[inline]
fn emit_bool(&mut self, v: bool) {
self.emit_u8(if v { 1 } else { 0 });
}
#[inline]
fn emit_char(&mut self, v: char) {
self.emit_u32(v as u32);
}
#[inline]
fn emit_str(&mut self, v: &str) {
self.emit_usize(v.len());
self.emit_raw_bytes(v.as_bytes());
self.emit_u8(STR_SENTINEL);
}
#[inline]
fn emit_raw_bytes(&mut self, s: &[u8]) {
self.data.extend_from_slice(s);
@ -480,28 +451,6 @@ impl Encoder for FileEncoder {
self.write_all(&v.to_le_bytes());
}
#[inline]
fn emit_i8(&mut self, v: i8) {
self.emit_u8(v as u8);
}
#[inline]
fn emit_bool(&mut self, v: bool) {
self.emit_u8(if v { 1 } else { 0 });
}
#[inline]
fn emit_char(&mut self, v: char) {
self.emit_u32(v as u32);
}
#[inline]
fn emit_str(&mut self, v: &str) {
self.emit_usize(v.len());
self.emit_raw_bytes(v.as_bytes());
self.emit_u8(STR_SENTINEL);
}
#[inline]
fn emit_raw_bytes(&mut self, s: &[u8]) {
self.write_all(s);
@ -555,40 +504,11 @@ impl<'a> MemDecoder<'a> {
panic!("MemDecoder exhausted")
}
#[inline]
fn read_byte(&mut self) -> u8 {
if self.current == self.end {
Self::decoder_exhausted();
}
// SAFETY: This type guarantees current <= end, and we just checked current == end.
unsafe {
let byte = *self.current;
self.current = self.current.add(1);
byte
}
}
#[inline]
fn read_array<const N: usize>(&mut self) -> [u8; N] {
self.read_raw_bytes(N).try_into().unwrap()
}
// The trait method doesn't have a lifetime parameter, and we need a version of this
// that definitely returns a slice based on the underlying storage as opposed to
// the Decoder itself in order to implement read_str efficiently.
#[inline]
fn read_raw_bytes_inherent(&mut self, bytes: usize) -> &'a [u8] {
if bytes > self.remaining() {
Self::decoder_exhausted();
}
// SAFETY: We just checked if this range is in-bounds above.
unsafe {
let slice = std::slice::from_raw_parts(self.current, bytes);
self.current = self.current.add(bytes);
slice
}
}
/// While we could manually expose manipulation of the decoder position,
/// all current users of that method would need to reset the position later,
/// incurring the bounds check of set_position twice.
@ -653,7 +573,15 @@ impl<'a> Decoder for MemDecoder<'a> {
#[inline]
fn read_u8(&mut self) -> u8 {
self.read_byte()
if self.current == self.end {
Self::decoder_exhausted();
}
// SAFETY: This type guarantees current <= end, and we just checked current == end.
unsafe {
let byte = *self.current;
self.current = self.current.add(1);
byte
}
}
#[inline]
@ -681,39 +609,22 @@ impl<'a> Decoder for MemDecoder<'a> {
i16::from_le_bytes(self.read_array())
}
#[inline]
fn read_i8(&mut self) -> i8 {
self.read_byte() as i8
}
#[inline]
fn read_isize(&mut self) -> isize {
read_leb128!(self, read_isize_leb128)
}
#[inline]
fn read_bool(&mut self) -> bool {
let value = self.read_u8();
value != 0
}
#[inline]
fn read_char(&mut self) -> char {
let bits = self.read_u32();
std::char::from_u32(bits).unwrap()
}
#[inline]
fn read_str(&mut self) -> &str {
let len = self.read_usize();
let bytes = self.read_raw_bytes_inherent(len + 1);
assert!(bytes[len] == STR_SENTINEL);
unsafe { std::str::from_utf8_unchecked(&bytes[..len]) }
}
#[inline]
fn read_raw_bytes(&mut self, bytes: usize) -> &[u8] {
self.read_raw_bytes_inherent(bytes)
fn read_raw_bytes(&mut self, bytes: usize) -> &'a [u8] {
if bytes > self.remaining() {
Self::decoder_exhausted();
}
// SAFETY: We just checked if this range is in-bounds above.
unsafe {
let slice = std::slice::from_raw_parts(self.current, bytes);
self.current = self.current.add(bytes);
slice
}
}
#[inline]
@ -787,12 +698,7 @@ impl Encodable<FileEncoder> for IntEncodedWithFixedSize {
impl<'a> Decodable<MemDecoder<'a>> for IntEncodedWithFixedSize {
#[inline]
fn decode(decoder: &mut MemDecoder<'a>) -> IntEncodedWithFixedSize {
let _start_pos = decoder.position();
let bytes = decoder.read_raw_bytes(IntEncodedWithFixedSize::ENCODED_SIZE);
let value = u64::from_le_bytes(bytes.try_into().unwrap());
let _end_pos = decoder.position();
debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
IntEncodedWithFixedSize(value)
let bytes = decoder.read_array::<{ IntEncodedWithFixedSize::ENCODED_SIZE }>();
IntEncodedWithFixedSize(u64::from_le_bytes(bytes))
}
}

View File

@ -12,6 +12,13 @@ use std::path;
use std::rc::Rc;
use std::sync::Arc;
/// A byte that [cannot occur in UTF8 sequences][utf8]. Used to mark the end of a string.
/// This way we can skip validation and still be relatively sure that deserialization
/// did not desynchronize.
///
/// [utf8]: https://en.wikipedia.org/w/index.php?title=UTF-8&oldid=1058865525#Codepage_layout
const STR_SENTINEL: u8 = 0xC1;
/// A note about error handling.
///
/// Encoders may be fallible, but in practice failure is rare and there are so
@ -40,10 +47,29 @@ pub trait Encoder {
fn emit_i64(&mut self, v: i64);
fn emit_i32(&mut self, v: i32);
fn emit_i16(&mut self, v: i16);
fn emit_i8(&mut self, v: i8);
fn emit_bool(&mut self, v: bool);
fn emit_char(&mut self, v: char);
fn emit_str(&mut self, v: &str);
#[inline]
fn emit_i8(&mut self, v: i8) {
self.emit_u8(v as u8);
}
#[inline]
fn emit_bool(&mut self, v: bool) {
self.emit_u8(if v { 1 } else { 0 });
}
#[inline]
fn emit_char(&mut self, v: char) {
self.emit_u32(v as u32);
}
#[inline]
fn emit_str(&mut self, v: &str) {
self.emit_usize(v.len());
self.emit_raw_bytes(v.as_bytes());
self.emit_u8(STR_SENTINEL);
}
fn emit_raw_bytes(&mut self, s: &[u8]);
fn emit_enum_variant<F>(&mut self, v_id: usize, f: F)
@ -79,11 +105,38 @@ pub trait Decoder {
fn read_i64(&mut self) -> i64;
fn read_i32(&mut self) -> i32;
fn read_i16(&mut self) -> i16;
fn read_i8(&mut self) -> i8;
fn read_bool(&mut self) -> bool;
fn read_char(&mut self) -> char;
fn read_str(&mut self) -> &str;
#[inline]
fn read_i8(&mut self) -> i8 {
self.read_u8() as i8
}
#[inline]
fn read_bool(&mut self) -> bool {
let value = self.read_u8();
value != 0
}
#[inline]
fn read_char(&mut self) -> char {
let bits = self.read_u32();
std::char::from_u32(bits).unwrap()
}
#[inline]
fn read_str(&mut self) -> &str {
let len = self.read_usize();
let bytes = self.read_raw_bytes(len + 1);
assert!(bytes[len] == STR_SENTINEL);
unsafe { std::str::from_utf8_unchecked(&bytes[..len]) }
}
fn read_raw_bytes(&mut self, len: usize) -> &[u8];
// Although there is an `emit_enum_variant` method in `Encoder`, the code
// patterns in decoding are different enough to encoding that there is no
// need for a corresponding `read_enum_variant` method here.
fn peek_byte(&self) -> u8;
fn position(&self) -> usize;
}

View File

@ -917,7 +917,7 @@ mod parse {
}
}
let mut options = slot.get_or_insert_default();
let options = slot.get_or_insert_default();
let mut seen_always = false;
let mut seen_never = false;
let mut seen_ignore_loops = false;

View File

@ -53,17 +53,6 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriInterpCx<'mir, 'tcx> {
(Scalar::from_bool(res), false, self.tcx.types.bool)
}
Offset => {
assert!(left.layout.ty.is_unsafe_ptr());
let ptr = left.to_scalar().to_pointer(self)?;
let offset = right.to_scalar().to_target_isize(self)?;
let pointee_ty =
left.layout.ty.builtin_deref(true).expect("Offset called on non-ptr type").ty;
let ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset)?;
(Scalar::from_maybe_pointer(ptr, self), false, left.layout.ty)
}
// Some more operations are possible with atomics.
// The return value always has the provenance of the *left* operand.
Add | Sub | BitOr | BitAnd | BitXor => {

View File

@ -25,7 +25,7 @@ all:
# Run rustc with `-Ztemps-dir` set to a directory
# *inside* the inaccessible one, so that it can't create it
$(RUSTC) program.rs -Ztemps-dir=$(TMPDIR)/inaccessible/tmp 2>&1 \
| $(CGREP) "failed to find or create the directory specified by `--temps-dir`"
| $(CGREP) 'failed to find or create the directory specified by `--temps-dir`'
# Make the inaccessible directory accessible,
# so that compiletest can delete the temp dir

7
tests/ui/binop/eq-arr.rs Normal file
View File

@ -0,0 +1,7 @@
fn main() {
struct X;
//~^ HELP consider annotating `X` with `#[derive(PartialEq)]`
let xs = [X, X, X];
let eq = xs == [X, X, X];
//~^ ERROR binary operation `==` cannot be applied to type `[X; 3]`
}

View File

@ -0,0 +1,22 @@
error[E0369]: binary operation `==` cannot be applied to type `[X; 3]`
--> $DIR/eq-arr.rs:5:17
|
LL | let eq = xs == [X, X, X];
| -- ^^ --------- [X; 3]
| |
| [X; 3]
|
note: an implementation of `PartialEq` might be missing for `X`
--> $DIR/eq-arr.rs:2:5
|
LL | struct X;
| ^^^^^^^^ must implement `PartialEq`
help: consider annotating `X` with `#[derive(PartialEq)]`
|
LL + #[derive(PartialEq)]
LL | struct X;
|
error: aborting due to previous error
For more information about this error, try `rustc --explain E0369`.

13
tests/ui/binop/eq-vec.rs Normal file
View File

@ -0,0 +1,13 @@
fn main() {
#[derive(Debug)]
enum Foo {
//~^ HELP consider annotating `Foo` with `#[derive(PartialEq)]`
Bar,
Qux,
}
let vec1 = vec![Foo::Bar, Foo::Qux];
let vec2 = vec![Foo::Bar, Foo::Qux];
assert_eq!(vec1, vec2);
//~^ ERROR binary operation `==` cannot be applied to type `Vec<Foo>`
}

View File

@ -0,0 +1,24 @@
error[E0369]: binary operation `==` cannot be applied to type `Vec<Foo>`
--> $DIR/eq-vec.rs:11:5
|
LL | assert_eq!(vec1, vec2);
| ^^^^^^^^^^^^^^^^^^^^^^
| |
| Vec<Foo>
| Vec<Foo>
|
note: an implementation of `PartialEq` might be missing for `Foo`
--> $DIR/eq-vec.rs:3:5
|
LL | enum Foo {
| ^^^^^^^^ must implement `PartialEq`
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Foo` with `#[derive(PartialEq)]`
|
LL + #[derive(PartialEq)]
LL | enum Foo {
|
error: aborting due to previous error
For more information about this error, try `rustc --explain E0369`.

View File

@ -6,11 +6,11 @@ LL | a + a;
| |
| A
|
note: an implementation of `Add<_>` might be missing for `A`
note: an implementation of `Add` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^ must implement `Add<_>`
| ^^^^^^^^ must implement `Add`
note: the trait `Add` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
@ -22,11 +22,11 @@ LL | a - a;
| |
| A
|
note: an implementation of `Sub<_>` might be missing for `A`
note: an implementation of `Sub` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^ must implement `Sub<_>`
| ^^^^^^^^ must implement `Sub`
note: the trait `Sub` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
@ -38,11 +38,11 @@ LL | a * a;
| |
| A
|
note: an implementation of `Mul<_>` might be missing for `A`
note: an implementation of `Mul` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^ must implement `Mul<_>`
| ^^^^^^^^ must implement `Mul`
note: the trait `Mul` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
@ -54,11 +54,11 @@ LL | a / a;
| |
| A
|
note: an implementation of `Div<_>` might be missing for `A`
note: an implementation of `Div` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^ must implement `Div<_>`
| ^^^^^^^^ must implement `Div`
note: the trait `Div` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
@ -70,11 +70,11 @@ LL | a % a;
| |
| A
|
note: an implementation of `Rem<_>` might be missing for `A`
note: an implementation of `Rem` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^ must implement `Rem<_>`
| ^^^^^^^^ must implement `Rem`
note: the trait `Rem` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
@ -86,11 +86,11 @@ LL | a & a;
| |
| A
|
note: an implementation of `BitAnd<_>` might be missing for `A`
note: an implementation of `BitAnd` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^ must implement `BitAnd<_>`
| ^^^^^^^^ must implement `BitAnd`
note: the trait `BitAnd` must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
@ -102,11 +102,11 @@ LL | a | a;
| |
| A
|
note: an implementation of `BitOr<_>` might be missing for `A`
note: an implementation of `BitOr` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^ must implement `BitOr<_>`
| ^^^^^^^^ must implement `BitOr`
note: the trait `BitOr` must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
@ -118,11 +118,11 @@ LL | a << a;
| |
| A
|
note: an implementation of `Shl<_>` might be missing for `A`
note: an implementation of `Shl` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^ must implement `Shl<_>`
| ^^^^^^^^ must implement `Shl`
note: the trait `Shl` must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
@ -134,11 +134,11 @@ LL | a >> a;
| |
| A
|
note: an implementation of `Shr<_>` might be missing for `A`
note: an implementation of `Shr` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^ must implement `Shr<_>`
| ^^^^^^^^ must implement `Shr`
note: the trait `Shr` must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
@ -150,11 +150,11 @@ LL | a == a;
| |
| A
|
note: an implementation of `PartialEq<_>` might be missing for `A`
note: an implementation of `PartialEq` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^ must implement `PartialEq<_>`
| ^^^^^^^^ must implement `PartialEq`
help: consider annotating `A` with `#[derive(PartialEq)]`
|
LL + #[derive(PartialEq)]
@ -169,11 +169,11 @@ LL | a != a;
| |
| A
|
note: an implementation of `PartialEq<_>` might be missing for `A`
note: an implementation of `PartialEq` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^ must implement `PartialEq<_>`
| ^^^^^^^^ must implement `PartialEq`
help: consider annotating `A` with `#[derive(PartialEq)]`
|
LL + #[derive(PartialEq)]
@ -188,11 +188,11 @@ LL | a < a;
| |
| A
|
note: an implementation of `PartialOrd<_>` might be missing for `A`
note: an implementation of `PartialOrd` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^ must implement `PartialOrd<_>`
| ^^^^^^^^ must implement `PartialOrd`
help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]`
|
LL + #[derive(PartialEq, PartialOrd)]
@ -207,11 +207,11 @@ LL | a <= a;
| |
| A
|
note: an implementation of `PartialOrd<_>` might be missing for `A`
note: an implementation of `PartialOrd` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^ must implement `PartialOrd<_>`
| ^^^^^^^^ must implement `PartialOrd`
help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]`
|
LL + #[derive(PartialEq, PartialOrd)]
@ -226,11 +226,11 @@ LL | a > a;
| |
| A
|
note: an implementation of `PartialOrd<_>` might be missing for `A`
note: an implementation of `PartialOrd` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^ must implement `PartialOrd<_>`
| ^^^^^^^^ must implement `PartialOrd`
help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]`
|
LL + #[derive(PartialEq, PartialOrd)]
@ -245,11 +245,11 @@ LL | a >= a;
| |
| A
|
note: an implementation of `PartialOrd<_>` might be missing for `A`
note: an implementation of `PartialOrd` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^ must implement `PartialOrd<_>`
| ^^^^^^^^ must implement `PartialOrd`
help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]`
|
LL + #[derive(PartialEq, PartialOrd)]

View File

@ -6,11 +6,11 @@ LL | let w = u * 3;
| |
| Thing
|
note: an implementation of `Mul<_>` might be missing for `Thing`
note: an implementation of `Mul<{integer}>` might be missing for `Thing`
--> $DIR/issue-3820.rs:1:1
|
LL | struct Thing {
| ^^^^^^^^^^^^ must implement `Mul<_>`
| ^^^^^^^^^^^^ must implement `Mul<{integer}>`
note: the trait `Mul` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL

View File

@ -7,11 +7,11 @@ LL | #[derive(PartialEq)]
LL | x: Error
| ^^^^^^^^
|
note: an implementation of `PartialEq<_>` might be missing for `Error`
note: an implementation of `PartialEq` might be missing for `Error`
--> $DIR/derives-span-PartialEq-enum-struct-variant.rs:4:1
|
LL | struct Error;
| ^^^^^^^^^^^^ must implement `PartialEq<_>`
| ^^^^^^^^^^^^ must implement `PartialEq`
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(PartialEq)]`
|

View File

@ -7,11 +7,11 @@ LL | #[derive(PartialEq)]
LL | Error
| ^^^^^
|
note: an implementation of `PartialEq<_>` might be missing for `Error`
note: an implementation of `PartialEq` might be missing for `Error`
--> $DIR/derives-span-PartialEq-enum.rs:4:1
|
LL | struct Error;
| ^^^^^^^^^^^^ must implement `PartialEq<_>`
| ^^^^^^^^^^^^ must implement `PartialEq`
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(PartialEq)]`
|

View File

@ -7,11 +7,11 @@ LL | struct Struct {
LL | x: Error
| ^^^^^^^^
|
note: an implementation of `PartialEq<_>` might be missing for `Error`
note: an implementation of `PartialEq` might be missing for `Error`
--> $DIR/derives-span-PartialEq-struct.rs:4:1
|
LL | struct Error;
| ^^^^^^^^^^^^ must implement `PartialEq<_>`
| ^^^^^^^^^^^^ must implement `PartialEq`
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(PartialEq)]`
|

View File

@ -7,11 +7,11 @@ LL | struct Struct(
LL | Error
| ^^^^^
|
note: an implementation of `PartialEq<_>` might be missing for `Error`
note: an implementation of `PartialEq` might be missing for `Error`
--> $DIR/derives-span-PartialEq-tuple-struct.rs:4:1
|
LL | struct Error;
| ^^^^^^^^^^^^ must implement `PartialEq<_>`
| ^^^^^^^^^^^^ must implement `PartialEq`
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(PartialEq)]`
|

View File

@ -7,11 +7,11 @@ LL | struct E {
LL | x: NoCloneOrEq
| ^^^^^^^^^^^^^^
|
note: an implementation of `PartialEq<_>` might be missing for `NoCloneOrEq`
note: an implementation of `PartialEq` might be missing for `NoCloneOrEq`
--> $DIR/deriving-no-inner-impl-error-message.rs:1:1
|
LL | struct NoCloneOrEq;
| ^^^^^^^^^^^^^^^^^^ must implement `PartialEq<_>`
| ^^^^^^^^^^^^^^^^^^ must implement `PartialEq`
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `NoCloneOrEq` with `#[derive(PartialEq)]`
|

View File

@ -44,11 +44,11 @@ LL | S { x: a, y: b } += s;
| |
| cannot use `+=` on type `S`
|
note: an implementation of `AddAssign<_>` might be missing for `S`
note: an implementation of `AddAssign` might be missing for `S`
--> $DIR/note-unsupported.rs:1:1
|
LL | struct S { x: u8, y: u8 }
| ^^^^^^^^ must implement `AddAssign<_>`
| ^^^^^^^^ must implement `AddAssign`
note: the trait `AddAssign` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL

View File

@ -0,0 +1,12 @@
// edition:2021
// compile-flags: -Zdrop-tracking-mir=yes
#![feature(generators)]
fn main() {
let x = &mut ();
|| {
let _c = || yield *&mut *x;
|| _ = &mut *x;
//~^ cannot borrow `*x` as mutable more than once at a time
};
}

View File

@ -0,0 +1,18 @@
error[E0499]: cannot borrow `*x` as mutable more than once at a time
--> $DIR/issue-110929-generator-conflict-error-ice.rs:9:9
|
LL | let _c = || yield *&mut *x;
| -- -- first borrow occurs due to use of `*x` in generator
| |
| first mutable borrow occurs here
LL | || _ = &mut *x;
| ^^ -- second borrow occurs due to use of `*x` in closure
| |
| second mutable borrow occurs here
LL |
LL | };
| - first borrow might be used here, when `_c` is dropped and runs the destructor for generator
error: aborting due to previous error
For more information about this error, try `rustc --explain E0499`.

View File

@ -6,16 +6,17 @@ LL | a == A::Value;
| |
| A
|
note: an implementation of `PartialEq<_>` might be missing for `A`
note: an implementation of `PartialEq<fn(()) -> A {A::Value}>` might be missing for `A`
--> $DIR/issue-62375.rs:1:1
|
LL | enum A {
| ^^^^^^ must implement `PartialEq<_>`
help: consider annotating `A` with `#[derive(PartialEq)]`
|
LL + #[derive(PartialEq)]
LL | enum A {
| ^^^^^^ must implement `PartialEq<fn(()) -> A {A::Value}>`
note: the trait `PartialEq` must be implemented
--> $SRC_DIR/core/src/cmp.rs:LL:COL
help: use parentheses to construct this tuple variant
|
LL | a == A::Value(/* () */);
| ++++++++++
error: aborting due to previous error

View File

@ -205,3 +205,11 @@ fn bar() {
let mut b = vec![2]; //~ ERROR: variable does not need to be mutable
}
struct Arg(i32);
// Regression test for https://github.com/rust-lang/rust/issues/110849
fn write_through_reference(mut arg: &mut Arg) {
//~^ WARN: variable does not need to be mutable
arg.0 = 1
}

View File

@ -218,5 +218,13 @@ note: the lint level is defined here
LL | #[deny(unused_mut)]
| ^^^^^^^^^^
error: aborting due to previous error; 25 warnings emitted
warning: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:212:28
|
LL | fn write_through_reference(mut arg: &mut Arg) {
| ----^^^
| |
| help: remove this `mut`
error: aborting due to previous error; 26 warnings emitted

View File

@ -6,11 +6,11 @@ LL | a += *b;
| |
| cannot use `+=` on type `Foo`
|
note: an implementation of `AddAssign<_>` might be missing for `Foo`
note: an implementation of `AddAssign` might be missing for `Foo`
--> $DIR/assignment-operator-unimplemented.rs:1:1
|
LL | struct Foo;
| ^^^^^^^^^^ must implement `AddAssign<_>`
| ^^^^^^^^^^ must implement `AddAssign`
note: the trait `AddAssign` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL

View File

@ -30,11 +30,11 @@ LL | let _ = |A | B: E| ();
| |
| E
|
note: an implementation of `BitOr<_>` might be missing for `E`
note: an implementation of `BitOr<()>` might be missing for `E`
--> $DIR/or-patterns-syntactic-fail.rs:6:1
|
LL | enum E { A, B }
| ^^^^^^ must implement `BitOr<_>`
| ^^^^^^ must implement `BitOr<()>`
note: the trait `BitOr` must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL

View File

@ -21,11 +21,11 @@ LL | let y = World::Hello + World::Goodbye;
| |
| World
|
note: an implementation of `Add<_>` might be missing for `World`
note: an implementation of `Add` might be missing for `World`
--> $DIR/issue-39018.rs:15:1
|
LL | enum World {
| ^^^^^^^^^^ must implement `Add<_>`
| ^^^^^^^^^^ must implement `Add`
note: the trait `Add` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL

View File

@ -6,11 +6,11 @@ LL | let _ = s == t;
| |
| S<T>
|
note: an implementation of `PartialEq<_>` might be missing for `S<T>`
note: an implementation of `PartialEq` might be missing for `S<T>`
--> $DIR/invalid-bin-op.rs:5:1
|
LL | struct S<T>(T);
| ^^^^^^^^^^^ must implement `PartialEq<_>`
| ^^^^^^^^^^^ must implement `PartialEq`
help: consider annotating `S<T>` with `#[derive(PartialEq)]`
|
LL + #[derive(PartialEq)]

View File

@ -6,11 +6,11 @@ LL | a + b
| |
| Wrapper<T>
|
note: an implementation of `Add<_>` might be missing for `Wrapper<T>`
note: an implementation of `Add<T>` might be missing for `Wrapper<T>`
--> $DIR/restrict-type-not-param.rs:3:1
|
LL | struct Wrapper<T>(T);
| ^^^^^^^^^^^^^^^^^ must implement `Add<_>`
| ^^^^^^^^^^^^^^^^^ must implement `Add<T>`
note: the trait `Add` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement

View File

@ -11,7 +11,7 @@ fn main() {
let mut map = HashMap::new();
map.insert("a", Test { v: 0 });
for (_k, mut v) in map.iter_mut() {
for (_k, v) in map.iter_mut() {
//~^ HELP use mutable method
//~| NOTE this iterator yields `&` references
v.v += 1;

View File

@ -11,7 +11,7 @@ fn main() {
let mut map = HashMap::new();
map.insert("a", Test { v: 0 });
for (_k, mut v) in map.iter() {
for (_k, v) in map.iter() {
//~^ HELP use mutable method
//~| NOTE this iterator yields `&` references
v.v += 1;

View File

@ -1,11 +1,11 @@
error[E0594]: cannot assign to `v.v`, which is behind a `&` reference
--> $DIR/suggest-mut-method-for-loop-hashmap.rs:17:9
|
LL | for (_k, mut v) in map.iter() {
| ----------
| | |
| | help: use mutable method: `iter_mut()`
| this iterator yields `&` references
LL | for (_k, v) in map.iter() {
| ----------
| | |
| | help: use mutable method: `iter_mut()`
| this iterator yields `&` references
...
LL | v.v += 1;
| ^^^^^^^^ `v` is a `&` reference, so the data it refers to cannot be written

View File

@ -1,8 +1,8 @@
error[E0369]: cannot subtract `(dyn Vector2<ScalarType = i32> + 'static)` from `dyn Vector2<ScalarType = i32>`
error[E0369]: cannot subtract `dyn Vector2<ScalarType = i32>` from `dyn Vector2<ScalarType = i32>`
--> $DIR/type-unsatisfiable.rs:57:20
|
LL | let bar = *hey - *word;
| ---- ^ ----- (dyn Vector2<ScalarType = i32> + 'static)
| ---- ^ ----- dyn Vector2<ScalarType = i32>
| |
| dyn Vector2<ScalarType = i32>