diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index a0a63620c08a9..9c579209fe51c 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -915,14 +915,22 @@ impl<'hir> LoweringContext<'_, 'hir> { ); } if !self.sess.features_untracked().destructuring_assignment { - feature_err( + let mut err = feature_err( &self.sess.parse_sess, sym::destructuring_assignment, eq_sign_span, "destructuring assignments are unstable", - ) - .span_label(lhs.span, "cannot assign to this expression") - .emit(); + ); + err.span_label(lhs.span, "cannot assign to this expression"); + if self.is_in_loop_condition { + err.span_suggestion_verbose( + lhs.span.shrink_to_lo(), + "you might have meant to use pattern destructuring", + "let ".to_string(), + rustc_errors::Applicability::MachineApplicable, + ); + } + err.emit(); } let mut assignments = vec![]; diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 46e2a99a0d094..a0f8aabbe0e72 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -447,16 +447,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // check if the RHS is from desugaring let opt_assignment_rhs_span = self.body.find_assignments(local).first().map(|&location| { - let stmt = &self.body[location.block].statements - [location.statement_index]; - match stmt.kind { - mir::StatementKind::Assign(box ( - _, - mir::Rvalue::Use(mir::Operand::Copy(place)), - )) => { - self.body.local_decls[place.local].source_info.span - } - _ => self.body.source_info(location).span, + if let Some(mir::Statement { + source_info: _, + kind: + mir::StatementKind::Assign(box ( + _, + mir::Rvalue::Use(mir::Operand::Copy(place)), + )), + }) = self.body[location.block] + .statements + .get(location.statement_index) + { + self.body.local_decls[place.local].source_info.span + } else { + self.body.source_info(location).span } }); match opt_assignment_rhs_span.and_then(|s| s.desugaring_kind()) { diff --git a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs index 2144e7ed67acb..45d4906259312 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs @@ -71,7 +71,7 @@ fn cast_target_to_abi_params(cast: CastTarget) -> SmallVec<[AbiParam; 2]> { .prefix .iter() .flatten() - .map(|&kind| reg_to_abi_param(Reg { kind, size: cast.prefix_chunk_size })) + .map(|®| reg_to_abi_param(reg)) .chain((0..rest_count).map(|_| reg_to_abi_param(cast.rest.unit))) .collect::>(); diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs index ce428c589a478..a8b1e70e2bb80 100644 --- a/compiler/rustc_codegen_gcc/src/abi.rs +++ b/compiler/rustc_codegen_gcc/src/abi.rs @@ -14,7 +14,7 @@ impl<'a, 'gcc, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // TODO(antoyo) } - fn get_param(&self, index: usize) -> Self::Value { + fn get_param(&mut self, index: usize) -> Self::Value { self.cx.current_func.borrow().expect("current func") .get_param(index as i32) .to_rvalue() @@ -48,8 +48,8 @@ impl GccType for CastTarget { let mut args: Vec<_> = self .prefix .iter() - .flat_map(|option_kind| { - option_kind.map(|kind| Reg { kind, size: self.prefix_chunk_size }.gcc_type(cx)) + .flat_map(|option_reg| { + option_reg.map(|reg| reg.gcc_type(cx)) }) .chain((0..rest_count).map(|_| rest_gcc_unit)) .collect(); diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index bedd3523d899e..d38ff588317a2 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -181,9 +181,7 @@ impl LlvmType for CastTarget { let mut args: Vec<_> = self .prefix .iter() - .flat_map(|option_kind| { - option_kind.map(|kind| Reg { kind, size: self.prefix_chunk_size }.llvm_type(cx)) - }) + .flat_map(|option_reg| option_reg.map(|reg| reg.llvm_type(cx))) .chain((0..rest_count).map(|_| rest_ll_unit)) .collect(); @@ -466,6 +464,9 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { ); } } + PassMode::Cast(cast) => { + cast.attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn); + } _ => {} } for arg in &self.args { @@ -497,8 +498,8 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { apply(a); apply(b); } - PassMode::Cast(_) => { - apply(&ArgAttributes::new()); + PassMode::Cast(cast) => { + apply(&cast.attrs); } } } @@ -533,6 +534,13 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { ); } } + PassMode::Cast(cast) => { + cast.attrs.apply_attrs_to_callsite( + llvm::AttributePlace::ReturnValue, + &bx.cx, + callsite, + ); + } _ => {} } if let abi::Abi::Scalar(scalar) = self.ret.layout.abi { @@ -577,8 +585,8 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { apply(bx.cx, a); apply(bx.cx, b); } - PassMode::Cast(_) => { - apply(bx.cx, &ArgAttributes::new()); + PassMode::Cast(cast) => { + apply(bx.cx, &cast.attrs); } } } @@ -607,7 +615,7 @@ impl AbiBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { fn_abi.apply_attrs_callsite(self, callsite) } - fn get_param(&self, index: usize) -> Self::Value { + fn get_param(&mut self, index: usize) -> Self::Value { llvm::get_param(self.llfn(), index as c_uint) } } diff --git a/compiler/rustc_codegen_ssa/src/traits/abi.rs b/compiler/rustc_codegen_ssa/src/traits/abi.rs index dd8495850bd54..a00d78daf4dcb 100644 --- a/compiler/rustc_codegen_ssa/src/traits/abi.rs +++ b/compiler/rustc_codegen_ssa/src/traits/abi.rs @@ -4,5 +4,5 @@ use rustc_target::abi::call::FnAbi; pub trait AbiBuilderMethods<'tcx>: BackendTypes { fn apply_attrs_callsite(&mut self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, callsite: Self::Value); - fn get_param(&self, index: usize) -> Self::Value; + fn get_param(&mut self, index: usize) -> Self::Value; } diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index c4a2ecee096eb..b48ca3bd0c0d3 100644 --- a/compiler/rustc_infer/src/traits/structural_impls.rs +++ b/compiler/rustc_infer/src/traits/structural_impls.rs @@ -70,6 +70,7 @@ impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.predicate.visit_with(visitor) + self.predicate.visit_with(visitor)?; + self.param_env.visit_with(visitor) } } diff --git a/compiler/rustc_target/src/abi/call/mips64.rs b/compiler/rustc_target/src/abi/call/mips64.rs index 2e00ffc7e1473..1ac454be5e9ad 100644 --- a/compiler/rustc_target/src/abi/call/mips64.rs +++ b/compiler/rustc_target/src/abi/call/mips64.rs @@ -1,4 +1,6 @@ -use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; +use crate::abi::call::{ + ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, PassMode, Reg, Uniform, +}; use crate::abi::{self, HasDataLayout, Size, TyAbiInterface}; fn extend_integer_width_mips(arg: &mut ArgAbi<'_, Ty>, bits: u64) { @@ -115,7 +117,7 @@ where for _ in 0..((offset - last_offset).bits() / 64) .min((prefix.len() - prefix_index) as u64) { - prefix[prefix_index] = Some(RegKind::Integer); + prefix[prefix_index] = Some(Reg::i64()); prefix_index += 1; } @@ -123,7 +125,7 @@ where break; } - prefix[prefix_index] = Some(RegKind::Float); + prefix[prefix_index] = Some(Reg::f64()); prefix_index += 1; last_offset = offset + Reg::f64().size; } @@ -137,8 +139,13 @@ where let rest_size = size - Size::from_bytes(8) * prefix_index as u64; arg.cast_to(CastTarget { prefix, - prefix_chunk_size: Size::from_bytes(8), rest: Uniform { unit: Reg::i64(), total: rest_size }, + attrs: ArgAttributes { + regular: ArgAttribute::default(), + arg_ext: ArgExtension::None, + pointee_size: Size::ZERO, + pointee_align: None, + }, }); } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 4768c9e2db5e1..735b7e76e3862 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -214,9 +214,9 @@ impl Uniform { #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct CastTarget { - pub prefix: [Option; 8], - pub prefix_chunk_size: Size, + pub prefix: [Option; 8], pub rest: Uniform, + pub attrs: ArgAttributes, } impl From for CastTarget { @@ -227,29 +227,48 @@ impl From for CastTarget { impl From for CastTarget { fn from(uniform: Uniform) -> CastTarget { - CastTarget { prefix: [None; 8], prefix_chunk_size: Size::ZERO, rest: uniform } + CastTarget { + prefix: [None; 8], + rest: uniform, + attrs: ArgAttributes { + regular: ArgAttribute::default(), + arg_ext: ArgExtension::None, + pointee_size: Size::ZERO, + pointee_align: None, + }, + } } } impl CastTarget { pub fn pair(a: Reg, b: Reg) -> CastTarget { CastTarget { - prefix: [Some(a.kind), None, None, None, None, None, None, None], - prefix_chunk_size: a.size, + prefix: [Some(a), None, None, None, None, None, None, None], rest: Uniform::from(b), + attrs: ArgAttributes { + regular: ArgAttribute::default(), + arg_ext: ArgExtension::None, + pointee_size: Size::ZERO, + pointee_align: None, + }, } } - pub fn size(&self, cx: &C) -> Size { - (self.prefix_chunk_size * self.prefix.iter().filter(|x| x.is_some()).count() as u64) - .align_to(self.rest.align(cx)) - + self.rest.total + pub fn size(&self, _cx: &C) -> Size { + let mut size = self.rest.total; + for i in 0..self.prefix.iter().count() { + match self.prefix[i] { + Some(v) => size += Size { raw: v.size.bytes() }, + None => {} + } + } + return size; } pub fn align(&self, cx: &C) -> Align { self.prefix .iter() - .filter_map(|x| x.map(|kind| Reg { kind, size: self.prefix_chunk_size }.align(cx))) + .filter_map(|x| x.map(|reg| reg.align(cx))) .fold(cx.data_layout().aggregate_align.abi.max(self.rest.align(cx)), |acc, align| { acc.max(align) }) diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs index 5d74c94e2c6f6..39d80c4c7e76d 100644 --- a/compiler/rustc_target/src/abi/call/sparc64.rs +++ b/compiler/rustc_target/src/abi/call/sparc64.rs @@ -1,7 +1,9 @@ // FIXME: This needs an audit for correctness and completeness. -use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform}; -use crate::abi::{HasDataLayout, TyAbiInterface}; +use crate::abi::call::{ + ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, Reg, RegKind, Uniform, +}; +use crate::abi::{self, HasDataLayout, Size, TyAbiInterface}; fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option where @@ -16,7 +18,7 @@ where let valid_unit = match unit.kind { RegKind::Integer => false, - RegKind::Float => true, + RegKind::Float => false, RegKind::Vector => arg.layout.size.bits() == 128, }; @@ -24,33 +26,7 @@ where }) } -fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>) -where - Ty: TyAbiInterface<'a, C> + Copy, - C: HasDataLayout, -{ - if !ret.layout.is_aggregate() { - ret.extend_integer_width_to(64); - return; - } - - if let Some(uniform) = is_homogeneous_aggregate(cx, ret) { - ret.cast_to(uniform); - return; - } - let size = ret.layout.size; - let bits = size.bits(); - if bits <= 256 { - let unit = Reg::i64(); - ret.cast_to(Uniform { unit, total: size }); - return; - } - - // don't return aggregates in registers - ret.make_indirect(); -} - -fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) +fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, in_registers_max: Size) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, @@ -60,13 +36,97 @@ where return; } + // This doesn't intentionally handle structures with floats which needs + // special care below. if let Some(uniform) = is_homogeneous_aggregate(cx, arg) { arg.cast_to(uniform); return; } + if let abi::FieldsShape::Arbitrary { .. } = arg.layout.fields { + let dl = cx.data_layout(); + let size = arg.layout.size; + let mut prefix = [None; 8]; + let mut prefix_index = 0; + let mut last_offset = Size::ZERO; + let mut has_float = false; + let mut arg_attribute = ArgAttribute::default(); + + for i in 0..arg.layout.fields.count() { + let field = arg.layout.field(cx, i); + let offset = arg.layout.fields.offset(i); + + if let abi::Abi::Scalar(scalar) = &field.abi { + if scalar.value == abi::F32 || scalar.value == abi::F64 { + has_float = true; + + if !last_offset.is_aligned(dl.f64_align.abi) && last_offset < offset { + if prefix_index == prefix.len() { + break; + } + prefix[prefix_index] = Some(Reg::i32()); + prefix_index += 1; + last_offset = last_offset + Reg::i32().size; + } + + for _ in 0..((offset - last_offset).bits() / 64) + .min((prefix.len() - prefix_index) as u64) + { + prefix[prefix_index] = Some(Reg::i64()); + prefix_index += 1; + last_offset = last_offset + Reg::i64().size; + } + + if last_offset < offset { + if prefix_index == prefix.len() { + break; + } + prefix[prefix_index] = Some(Reg::i32()); + prefix_index += 1; + last_offset = last_offset + Reg::i32().size; + } + + if prefix_index == prefix.len() { + break; + } + + if scalar.value == abi::F32 { + arg_attribute = ArgAttribute::InReg; + prefix[prefix_index] = Some(Reg::f32()); + last_offset = offset + Reg::f32().size; + } else { + prefix[prefix_index] = Some(Reg::f64()); + last_offset = offset + Reg::f64().size; + } + prefix_index += 1; + } + } + } + + if has_float && arg.layout.size <= in_registers_max { + let mut rest_size = size - last_offset; + + if (rest_size.raw % 8) != 0 && prefix_index < prefix.len() { + prefix[prefix_index] = Some(Reg::i32()); + rest_size = rest_size - Reg::i32().size; + } + + arg.cast_to(CastTarget { + prefix, + rest: Uniform { unit: Reg::i64(), total: rest_size }, + attrs: ArgAttributes { + regular: arg_attribute, + arg_ext: ArgExtension::None, + pointee_size: Size::ZERO, + pointee_align: None, + }, + }); + return; + } + } + let total = arg.layout.size; - if total.bits() > 128 { + if total > in_registers_max { arg.make_indirect(); return; } @@ -80,13 +140,13 @@ where C: HasDataLayout, { if !fn_abi.ret.is_ignore() { - classify_ret(cx, &mut fn_abi.ret); + classify_arg(cx, &mut fn_abi.ret, Size { raw: 32 }); } for arg in &mut fn_abi.args { if arg.is_ignore() { continue; } - classify_arg(cx, arg); + classify_arg(cx, arg, Size { raw: 16 }); } } diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 28712e0658269..77f7cccc04ba4 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -1458,7 +1458,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { cause, expected, found, - coercion_error, + coercion_error.clone(), fcx, parent_id, expression.map(|expr| (expr, blk_id)), @@ -1472,7 +1472,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { cause, expected, found, - coercion_error, + coercion_error.clone(), fcx, id, None, @@ -1483,7 +1483,12 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { } } _ => { - err = fcx.report_mismatched_types(cause, expected, found, coercion_error); + err = fcx.report_mismatched_types( + cause, + expected, + found, + coercion_error.clone(), + ); } } @@ -1492,7 +1497,14 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { } if let Some(expr) = expression { - fcx.emit_coerce_suggestions(&mut err, expr, found, expected, None); + fcx.emit_coerce_suggestions( + &mut err, + expr, + found, + expected, + None, + coercion_error, + ); } err.emit_unless(unsized_return); diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index ece2d7b4f3793..12cd7ad184892 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -10,6 +10,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{is_range_literal, Node}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::adjustment::AllowTwoPhase; +use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut}; use rustc_span::symbol::sym; @@ -27,8 +28,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_ty: Ty<'tcx>, expected: Ty<'tcx>, expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, + error: TypeError<'tcx>, ) { - self.annotate_expected_due_to_let_ty(err, expr); + self.annotate_expected_due_to_let_ty(err, expr, error); self.suggest_box_deref(err, expr, expected, expr_ty); self.suggest_compatible_variants(err, expr, expected, expr_ty); self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr); @@ -145,9 +147,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expr = expr.peel_drop_temps(); let cause = self.misc(expr.span); let expr_ty = self.resolve_vars_with_obligations(checked_ty); - let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e); + let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e.clone()); - self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr); + self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, e); (expected, Some(err)) } @@ -156,15 +158,104 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, err: &mut DiagnosticBuilder<'_>, expr: &hir::Expr<'_>, + error: TypeError<'_>, ) { let parent = self.tcx.hir().get_parent_node(expr.hir_id); - if let Some(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. })) = - self.tcx.hir().find(parent) - { - if init.hir_id == expr.hir_id { + match (self.tcx.hir().find(parent), error) { + (Some(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. })), _) + if init.hir_id == expr.hir_id => + { // Point at `let` assignment type. err.span_label(ty.span, "expected due to this"); } + ( + Some(hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Assign(lhs, rhs, _), .. + })), + TypeError::Sorts(ExpectedFound { expected, .. }), + ) if rhs.hir_id == expr.hir_id && !expected.is_closure() => { + // We ignore closures explicitly because we already point at them elsewhere. + // Point at the assigned-to binding. + let mut primary_span = lhs.span; + let mut secondary_span = lhs.span; + let mut post_message = ""; + match lhs.kind { + hir::ExprKind::Path(hir::QPath::Resolved( + None, + hir::Path { + res: + hir::def::Res::Def( + hir::def::DefKind::Static | hir::def::DefKind::Const, + def_id, + ), + .. + }, + )) => { + if let Some(hir::Node::Item(hir::Item { + ident, + kind: hir::ItemKind::Static(ty, ..) | hir::ItemKind::Const(ty, ..), + .. + })) = self.tcx.hir().get_if_local(*def_id) + { + primary_span = ty.span; + secondary_span = ident.span; + post_message = " type"; + } + } + hir::ExprKind::Path(hir::QPath::Resolved( + None, + hir::Path { res: hir::def::Res::Local(hir_id), .. }, + )) => { + if let Some(hir::Node::Binding(pat)) = self.tcx.hir().find(*hir_id) { + let parent = self.tcx.hir().get_parent_node(pat.hir_id); + primary_span = pat.span; + secondary_span = pat.span; + match self.tcx.hir().find(parent) { + Some(hir::Node::Local(hir::Local { ty: Some(ty), .. })) => { + primary_span = ty.span; + post_message = " type"; + } + Some(hir::Node::Local(hir::Local { init: Some(init), .. })) => { + primary_span = init.span; + post_message = " value"; + } + Some(hir::Node::Param(hir::Param { ty_span, .. })) => { + primary_span = *ty_span; + post_message = " parameter type"; + } + _ => {} + } + } + } + _ => {} + } + + if primary_span != secondary_span + && self + .tcx + .sess + .source_map() + .is_multiline(secondary_span.shrink_to_hi().until(primary_span)) + { + // We are pointing at the binding's type or initializer value, but it's pattern + // is in a different line, so we point at both. + err.span_label(secondary_span, "expected due to the type of this binding"); + err.span_label(primary_span, &format!("expected due to this{}", post_message)); + } else if post_message == "" { + // We are pointing at either the assignment lhs or the binding def pattern. + err.span_label(primary_span, "expected due to the type of this binding"); + } else { + // We are pointing at the binding's type or initializer value. + err.span_label(primary_span, &format!("expected due to this{}", post_message)); + } + + if !lhs.is_syntactic_place_expr() { + // We already emitted E0070 "invalid left-hand side of assignment", so we + // silence this. + err.delay_as_bug(); + } + } + _ => {} } } diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index c9fa0fd72fc50..eb997b014c77b 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -833,7 +833,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, lhs: &'tcx hir::Expr<'tcx>, err_code: &'static str, - expr_span: &Span, + op_span: Span, ) { if lhs.is_syntactic_place_expr() { return; @@ -841,11 +841,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME: Make this use SessionDiagnostic once error codes can be dynamically set. let mut err = self.tcx.sess.struct_span_err_with_code( - *expr_span, + op_span, "invalid left-hand side of assignment", DiagnosticId::Error(err_code.into()), ); err.span_label(lhs.span, "cannot assign to this expression"); + + let mut parent = self.tcx.hir().get_parent_node(lhs.hir_id); + while let Some(node) = self.tcx.hir().find(parent) { + match node { + hir::Node::Expr(hir::Expr { + kind: + hir::ExprKind::Loop( + hir::Block { + expr: + Some(hir::Expr { + kind: + hir::ExprKind::Match(expr, ..) | hir::ExprKind::If(expr, ..), + .. + }), + .. + }, + _, + hir::LoopSource::While, + _, + ), + .. + }) => { + // We have a situation like `while Some(0) = value.get(0) {`, where `while let` + // was more likely intended. + err.span_suggestion_verbose( + expr.span.shrink_to_lo(), + "you might have meant to use pattern destructuring", + "let ".to_string(), + Applicability::MachineApplicable, + ); + if !self.sess().features_untracked().destructuring_assignment { + // We already emit an E0658 with a suggestion for `while let`, this is + // redundant output. + err.delay_as_bug(); + } + break; + } + hir::Node::Item(_) + | hir::Node::ImplItem(_) + | hir::Node::TraitItem(_) + | hir::Node::Crate(_) => break, + _ => { + parent = self.tcx.hir().get_parent_node(parent); + } + } + } + err.emit(); } @@ -953,7 +1000,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { (Applicability::MaybeIncorrect, false) }; - if !lhs.is_syntactic_place_expr() { + if !lhs.is_syntactic_place_expr() && !matches!(lhs.kind, hir::ExprKind::Lit(_)) { // Do not suggest `if let x = y` as `==` is way more likely to be the intention. let hir = self.tcx.hir(); if let hir::Node::Expr(hir::Expr { kind: ExprKind::If { .. }, .. }) = @@ -965,7 +1012,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "let ".to_string(), applicability, ); - } + }; } if eq { err.span_suggestion_verbose( @@ -986,7 +1033,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return self.tcx.ty_error(); } - self.check_lhs_assignable(lhs, "E0070", span); + self.check_lhs_assignable(lhs, "E0070", *span); let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace); let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty, Some(lhs)); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index a119a6838b8d2..74d7f0a80b6ca 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -737,6 +737,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &mut |err| { if let Some(expected_ty) = expected.only_has_type(self) { self.consider_hint_about_removing_semicolon(blk, expected_ty, err); + if expected_ty == self.tcx.types.bool { + // If this is caused by a missing `let` in a `while let`, + // silence this redundant error, as we already emit E0070. + let parent = self.tcx.hir().get_parent_node(blk.hir_id); + let parent = self.tcx.hir().get_parent_node(parent); + let parent = self.tcx.hir().get_parent_node(parent); + let parent = self.tcx.hir().get_parent_node(parent); + let parent = self.tcx.hir().get_parent_node(parent); + match self.tcx.hir().find(parent) { + Some(hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Loop(_, _, hir::LoopSource::While, _), + .. + })) => { + err.delay_as_bug(); + } + _ => {} + } + } } if let Some(fn_span) = fn_span { err.span_label( diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 9c53a1d4eb68d..f83209f57a897 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -42,7 +42,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return_ty }; - self.check_lhs_assignable(lhs, "E0067", &op.span); + self.check_lhs_assignable(lhs, "E0067", op.span); ty } diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index ba4e1ca31148c..f71282a1b52d4 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -72,7 +72,7 @@ ENV PATH="/node-v14.4.0-linux-x64/bin:${PATH}" # https://github.com/puppeteer/puppeteer/issues/375 # # We also specify the version in case we need to update it to go around cache limitations. -RUN npm install -g browser-ui-test@0.4.5 --unsafe-perm=true +RUN npm install -g browser-ui-test@0.5.0 --unsafe-perm=true ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 0f3eb2ca07d23..bfad510695131 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -305,6 +305,10 @@ nav.sub { overflow-y: scroll; } +.rustdoc.source .sidebar { + overflow-y: auto; +} + /* Improve the scrollbar display on firefox */ * { scrollbar-width: initial; diff --git a/src/test/assembly/sparc-struct-abi.rs b/src/test/assembly/sparc-struct-abi.rs new file mode 100644 index 0000000000000..6bee887369215 --- /dev/null +++ b/src/test/assembly/sparc-struct-abi.rs @@ -0,0 +1,64 @@ +// Test SPARC64 ABI +// - float structure members are passes in floating point registers +// (#86163) + +// assembly-output: emit-asm +// needs-llvm-components: sparc +// compile-flags: --target=sparcv9-sun-solaris +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +pub trait Sized {} +#[lang = "copy"] +pub trait Copy {} + +#[repr(C)] +pub struct Franta { + a: f32, + b: f32, + c: f32, + d: f32, +} + +// NB: due to delay slots the `ld` following the call is actually executed before the call. +#[no_mangle] +pub unsafe extern "C" fn callee(arg: Franta) { + // CHECK-LABEL: callee: + // CHECK: st %f3, [[PLACE_D:.*]] + // CHECK: st %f2, [[PLACE_C:.*]] + // CHECK: st %f1, [[PLACE_B:.*]] + // CHECK: st %f0, [[PLACE_A:.*]] + // CHECK: call tst_use + // CHECK-NEXT: ld [[PLACE_A]], %f1 + // CHECK: call tst_use + // CHECK-NEXT: ld [[PLACE_B]], %f1 + // CHECK: call tst_use + // CHECK-NEXT: ld [[PLACE_C]], %f1 + // CHECK: call tst_use + // CHECK-NEXT: ld [[PLACE_D]], %f1 + clobber(); + tst_use(arg.a); + tst_use(arg.b); + tst_use(arg.c); + tst_use(arg.d); +} + +extern "C" { + fn opaque_callee(arg: Franta, intarg: i32); + fn tst_use(arg: f32); + fn clobber(); +} + +#[no_mangle] +pub unsafe extern "C" fn caller() { + // CHECK-LABEL: caller: + // CHECK: ld [{{.*}}], %f0 + // CHECK: ld [{{.*}}], %f1 + // CHECK: ld [{{.*}}], %f2 + // CHECK: ld [{{.*}}], %f3 + // CHECK: call opaque_callee + // CHECK: mov 3, %o2 + opaque_callee(Franta { a: 1.0, b: 2.0, c: 3.0, d: 4.0 }, 3); +} diff --git a/src/test/codegen/sparc-struct-abi.rs b/src/test/codegen/sparc-struct-abi.rs index f228d7c550084..642515f775b7b 100644 --- a/src/test/codegen/sparc-struct-abi.rs +++ b/src/test/codegen/sparc-struct-abi.rs @@ -1,5 +1,5 @@ // Checks that we correctly codegen extern "C" functions returning structs. -// See issue #52638. +// See issues #52638 and #86163. // compile-flags: -O --target=sparc64-unknown-linux-gnu --crate-type=rlib // needs-llvm-components: sparc @@ -25,3 +25,64 @@ pub struct Bool { pub extern "C" fn structbool() -> Bool { Bool { b: true } } + + +#[repr(C)] +pub struct BoolFloat { + b: bool, + f: f32, +} + +// CHECK: define inreg { i32, float } @structboolfloat() +// CHECK-NEXT: start: +// CHECK-NEXT: ret { i32, float } { i32 16777216, float 0x40091EB860000000 } +#[no_mangle] +pub extern "C" fn structboolfloat() -> BoolFloat { + BoolFloat { b: true, f: 3.14 } +} + +// CHECK: define void @structboolfloat_input({ i32, float } inreg %0) +// CHECK-NEXT: start: +#[no_mangle] +pub extern "C" fn structboolfloat_input(a: BoolFloat) { } + + +#[repr(C)] +pub struct ShortDouble { + s: i16, + d: f64, +} + +// CHECK: define { i64, double } @structshortdouble() +// CHECK-NEXT: start: +// CHECK-NEXT: ret { i64, double } { i64 34621422135410688, double 3.140000e+00 } +#[no_mangle] +pub extern "C" fn structshortdouble() -> ShortDouble { + ShortDouble { s: 123, d: 3.14 } +} + +// CHECK: define void @structshortdouble_input({ i64, double } %0) +// CHECK-NEXT: start: +#[no_mangle] +pub extern "C" fn structshortdouble_input(a: ShortDouble) { } + + +#[repr(C)] +pub struct FloatLongFloat { + f: f32, + i: i64, + g: f32, +} + +// CHECK: define inreg { float, i32, i64, float, i32 } @structfloatlongfloat() +// CHECK-NEXT: start: +// CHECK-NEXT: ret { float, i32, i64, float, i32 } { float 0x3FB99999A0000000, i32 undef, i64 123, float 0x40091EB860000000, i32 undef } +#[no_mangle] +pub extern "C" fn structfloatlongfloat() -> FloatLongFloat { + FloatLongFloat { f: 0.1, i: 123, g: 3.14 } +} + +// CHECK: define void @structfloatlongfloat_input(%FloatLongFloat* noalias nocapture dereferenceable(24) %a) +// CHECK-NEXT: start: +#[no_mangle] +pub extern "C" fn structfloatlongfloat_input(a: FloatLongFloat) { } diff --git a/src/test/rustdoc-gui/anchors.goml b/src/test/rustdoc-gui/anchors.goml index 4ce0ed1a4b8fd..5f809f9aa4ed4 100644 --- a/src/test/rustdoc-gui/anchors.goml +++ b/src/test/rustdoc-gui/anchors.goml @@ -1,5 +1,6 @@ // This test is to ensure that the anchors (`ยง`) have the expected color. goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html +show-text: true // This is needed to ensure that the text color is computed. show-text: true diff --git a/src/test/rustdoc-gui/search-filter.goml b/src/test/rustdoc-gui/search-filter.goml index a098dbd9f129b..7a8f8ca5311ad 100644 --- a/src/test/rustdoc-gui/search-filter.goml +++ b/src/test/rustdoc-gui/search-filter.goml @@ -1,9 +1,11 @@ goto: file://|DOC_PATH|/test_docs/index.html +show-text: true write: (".search-input", "test") // Waiting for the search results to appear... wait-for: "#titles" assert-text: ("#results .externcrate", "test_docs") -text: (".search-input", "") + +goto: file://|DOC_PATH|/test_docs/index.html // We now want to change the crate filter. click: "#crate-search" // We select "lib2" option then press enter to change the filter. diff --git a/src/test/ui/borrowck/issue-91206.rs b/src/test/ui/borrowck/issue-91206.rs new file mode 100644 index 0000000000000..3b1fbf4b69902 --- /dev/null +++ b/src/test/ui/borrowck/issue-91206.rs @@ -0,0 +1,15 @@ +struct TestClient; + +impl TestClient { + fn get_inner_ref(&self) -> &Vec { + todo!() + } +} + +fn main() { + let client = TestClient; + let inner = client.get_inner_ref(); + //~^ HELP consider changing this to be a mutable reference + inner.clear(); + //~^ ERROR cannot borrow `*inner` as mutable, as it is behind a `&` reference [E0596] +} diff --git a/src/test/ui/borrowck/issue-91206.stderr b/src/test/ui/borrowck/issue-91206.stderr new file mode 100644 index 0000000000000..535d247452a59 --- /dev/null +++ b/src/test/ui/borrowck/issue-91206.stderr @@ -0,0 +1,12 @@ +error[E0596]: cannot borrow `*inner` as mutable, as it is behind a `&` reference + --> $DIR/issue-91206.rs:13:5 + | +LL | let inner = client.get_inner_ref(); + | ----- help: consider changing this to be a mutable reference: `&mut Vec` +LL | +LL | inner.clear(); + | ^^^^^^^^^^^^^ `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr index 02dce4f7a97e8..3a7095789336c 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/issue-72787.rs:11:17 + --> $DIR/issue-72787.rs:12:17 | LL | Condition<{ LHS <= RHS }>: True | ^^^ cannot perform const operation using `LHS` @@ -8,7 +8,7 @@ LL | Condition<{ LHS <= RHS }>: True = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/issue-72787.rs:11:24 + --> $DIR/issue-72787.rs:12:24 | LL | Condition<{ LHS <= RHS }>: True | ^^^ cannot perform const operation using `RHS` @@ -17,7 +17,7 @@ LL | Condition<{ LHS <= RHS }>: True = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/issue-72787.rs:25:25 + --> $DIR/issue-72787.rs:26:25 | LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^ cannot perform const operation using `I` @@ -26,7 +26,7 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/issue-72787.rs:25:36 + --> $DIR/issue-72787.rs:26:36 | LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^ cannot perform const operation using `J` @@ -35,7 +35,15 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions error[E0283]: type annotations needed - --> $DIR/issue-72787.rs:21:26 + --> $DIR/issue-72787.rs:10:38 + | +LL | impl True for IsLessOrEqual where + | ^^^^ cannot infer type for struct `IsLessOrEqual` + | + = note: cannot satisfy `IsLessOrEqual: True` + +error[E0283]: type annotations needed + --> $DIR/issue-72787.rs:22:26 | LL | IsLessOrEqual: True, | ^^^^ cannot infer type for struct `IsLessOrEqual` @@ -43,13 +51,13 @@ LL | IsLessOrEqual: True, = note: cannot satisfy `IsLessOrEqual: True` error[E0283]: type annotations needed - --> $DIR/issue-72787.rs:21:26 + --> $DIR/issue-72787.rs:22:26 | LL | IsLessOrEqual: True, | ^^^^ cannot infer type for struct `IsLessOrEqual` | = note: cannot satisfy `IsLessOrEqual: True` -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-72787.rs b/src/test/ui/const-generics/generic_const_exprs/issue-72787.rs index 77ad57f0640fa..2ea5d634f6ef3 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-72787.rs +++ b/src/test/ui/const-generics/generic_const_exprs/issue-72787.rs @@ -8,6 +8,7 @@ pub struct Condition; pub trait True {} impl True for IsLessOrEqual where +//[min]~^ ERROR type annotations needed Condition<{ LHS <= RHS }>: True //[min]~^ Error generic parameters may not be used in const operations //[min]~| Error generic parameters may not be used in const operations diff --git a/src/test/ui/dst/dst-bad-assign-3.stderr b/src/test/ui/dst/dst-bad-assign-3.stderr index 04e46233532b2..b326dbbbc1405 100644 --- a/src/test/ui/dst/dst-bad-assign-3.stderr +++ b/src/test/ui/dst/dst-bad-assign-3.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/dst-bad-assign-3.rs:33:12 | LL | f5.2 = Bar1 {f: 36}; - | ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1` + | ---- ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1` + | | + | expected due to the type of this binding | = note: expected trait object `dyn ToBar` found struct `Bar1` diff --git a/src/test/ui/dst/dst-bad-assign.stderr b/src/test/ui/dst/dst-bad-assign.stderr index f87a34c6d3783..614f213875129 100644 --- a/src/test/ui/dst/dst-bad-assign.stderr +++ b/src/test/ui/dst/dst-bad-assign.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/dst-bad-assign.rs:35:14 | LL | f5.ptr = Bar1 {f: 36}; - | ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1` + | ------ ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1` + | | + | expected due to the type of this binding | = note: expected trait object `dyn ToBar` found struct `Bar1` diff --git a/src/test/ui/error-codes/E0070.rs b/src/test/ui/error-codes/E0070.rs index ab956d8109838..3aae0c9ff6e72 100644 --- a/src/test/ui/error-codes/E0070.rs +++ b/src/test/ui/error-codes/E0070.rs @@ -6,7 +6,6 @@ fn some_function() { SOME_CONST = 14; //~ ERROR E0070 1 = 3; //~ ERROR E0070 some_other_func() = 4; //~ ERROR E0070 - //~^ ERROR E0308 } fn main() { diff --git a/src/test/ui/error-codes/E0070.stderr b/src/test/ui/error-codes/E0070.stderr index e24d498e3520c..8868bc257a703 100644 --- a/src/test/ui/error-codes/E0070.stderr +++ b/src/test/ui/error-codes/E0070.stderr @@ -22,13 +22,6 @@ LL | some_other_func() = 4; | | | cannot assign to this expression -error[E0308]: mismatched types - --> $DIR/E0070.rs:8:25 - | -LL | some_other_func() = 4; - | ^ expected `()`, found integer - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0070, E0308. -For more information about an error, try `rustc --explain E0070`. +For more information about this error, try `rustc --explain E0070`. diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs index 1c6b9805b51b6..229c174daa864 100644 --- a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs +++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs @@ -1,10 +1,10 @@ // Test that we use fully-qualified type names in error messages. fn main() { - let x: Option; + let x: //~ NOTE expected due to the type of this binding + Option; //~ NOTE expected due to this type x = 5; //~^ ERROR mismatched types - //~| expected enum `Option` - //~| found type `{integer}` - //~| expected enum `Option`, found integer + //~| NOTE expected enum `Option` + //~| NOTE expected enum `Option`, found integer } diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr index 03fb299b39cd2..4750c5ccdf702 100644 --- a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr +++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr @@ -1,6 +1,10 @@ error[E0308]: mismatched types - --> $DIR/fully-qualified-type-name1.rs:5:9 + --> $DIR/fully-qualified-type-name1.rs:6:9 | +LL | let x: + | - expected due to the type of this binding +LL | Option; + | ------------- expected due to this type LL | x = 5; | ^ expected enum `Option`, found integer | diff --git a/src/test/ui/impl-trait/impl-trait-in-macro.stderr b/src/test/ui/impl-trait/impl-trait-in-macro.stderr index b5f9986ce4089..7cfbe3447b813 100644 --- a/src/test/ui/impl-trait/impl-trait-in-macro.stderr +++ b/src/test/ui/impl-trait/impl-trait-in-macro.stderr @@ -7,6 +7,8 @@ LL | ($($tr:tt)*) => { impl $($tr)* }; | expected type parameter | found type parameter ... +LL | let mut a = x; + | - expected due to this value LL | a = y; | ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug` | diff --git a/src/test/ui/impl-trait/universal-two-impl-traits.stderr b/src/test/ui/impl-trait/universal-two-impl-traits.stderr index 7c120235fd176..ab8a53d0db399 100644 --- a/src/test/ui/impl-trait/universal-two-impl-traits.stderr +++ b/src/test/ui/impl-trait/universal-two-impl-traits.stderr @@ -6,6 +6,7 @@ LL | fn foo(x: impl Debug, y: impl Debug) -> String { | | | expected type parameter LL | let mut a = x; + | - expected due to this value LL | a = y; | ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug` | diff --git a/src/test/ui/integral-variable-unification-error.rs b/src/test/ui/integral-variable-unification-error.rs index 5200b4a829db2..8d1621321e8e6 100644 --- a/src/test/ui/integral-variable-unification-error.rs +++ b/src/test/ui/integral-variable-unification-error.rs @@ -1,6 +1,8 @@ fn main() { - let mut x = 2; + let mut x //~ NOTE expected due to the type of this binding + = + 2; //~ NOTE expected due to this value x = 5.0; //~^ ERROR mismatched types - //~| expected integer, found floating-point number + //~| NOTE expected integer, found floating-point number } diff --git a/src/test/ui/integral-variable-unification-error.stderr b/src/test/ui/integral-variable-unification-error.stderr index b49bff1b0d84d..f77c265a2ada7 100644 --- a/src/test/ui/integral-variable-unification-error.stderr +++ b/src/test/ui/integral-variable-unification-error.stderr @@ -1,6 +1,11 @@ error[E0308]: mismatched types - --> $DIR/integral-variable-unification-error.rs:3:9 + --> $DIR/integral-variable-unification-error.rs:5:9 | +LL | let mut x + | ----- expected due to the type of this binding +LL | = +LL | 2; + | - expected due to this value LL | x = 5.0; | ^^^ expected integer, found floating-point number diff --git a/src/test/ui/issues/issue-13407.rs b/src/test/ui/issues/issue-13407.rs index fa53d55f5b3d7..7ea81ffb59e7e 100644 --- a/src/test/ui/issues/issue-13407.rs +++ b/src/test/ui/issues/issue-13407.rs @@ -5,6 +5,5 @@ mod A { fn main() { A::C = 1; //~^ ERROR: invalid left-hand side of assignment - //~| ERROR: mismatched types //~| ERROR: struct `C` is private } diff --git a/src/test/ui/issues/issue-13407.stderr b/src/test/ui/issues/issue-13407.stderr index 4df1813a710ff..54b6c640d9d79 100644 --- a/src/test/ui/issues/issue-13407.stderr +++ b/src/test/ui/issues/issue-13407.stderr @@ -18,13 +18,7 @@ LL | A::C = 1; | | | cannot assign to this expression -error[E0308]: mismatched types - --> $DIR/issue-13407.rs:6:12 - | -LL | A::C = 1; - | ^ expected struct `C`, found integer - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0070, E0308, E0603. +Some errors have detailed explanations: E0070, E0603. For more information about an error, try `rustc --explain E0070`. diff --git a/src/test/ui/issues/issue-2951.stderr b/src/test/ui/issues/issue-2951.stderr index b966b33938917..538bbe2f50296 100644 --- a/src/test/ui/issues/issue-2951.stderr +++ b/src/test/ui/issues/issue-2951.stderr @@ -6,6 +6,7 @@ LL | fn foo(x: T, y: U) { | | | expected type parameter LL | let mut xx = x; + | - expected due to this value LL | xx = y; | ^ expected type parameter `T`, found type parameter `U` | diff --git a/src/test/ui/issues/issue-53348.rs b/src/test/ui/issues/issue-53348.rs index 65f4656b02266..d2f8c77c0ce11 100644 --- a/src/test/ui/issues/issue-53348.rs +++ b/src/test/ui/issues/issue-53348.rs @@ -5,7 +5,7 @@ fn main() { v.into_iter().map(|s|s.to_owned()).collect::>(); - let mut a = String::new(); + let mut a = String::new(); //~ NOTE expected due to this value for i in v { a = *i.to_string(); //~^ ERROR mismatched types diff --git a/src/test/ui/issues/issue-53348.stderr b/src/test/ui/issues/issue-53348.stderr index 8f500261243f1..71d9f5b3dbbff 100644 --- a/src/test/ui/issues/issue-53348.stderr +++ b/src/test/ui/issues/issue-53348.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/issue-53348.rs:10:13 | +LL | let mut a = String::new(); + | ------------- expected due to this value +LL | for i in v { LL | a = *i.to_string(); | ^^^^^^^^^^^^^^ expected struct `String`, found `str` diff --git a/src/test/ui/issues/issue-77218.rs b/src/test/ui/issues/issue-77218.rs deleted file mode 100644 index a6a2401795ff4..0000000000000 --- a/src/test/ui/issues/issue-77218.rs +++ /dev/null @@ -1,11 +0,0 @@ -fn main() { - let value = [7u8]; - while Some(0) = value.get(0) { //~ ERROR destructuring assignments are unstable - //~| ERROR invalid left-hand side of assignment - //~| ERROR mismatched types - //~| ERROR mismatched types - - // FIXME The following diagnostic should also be emitted - // HELP you might have meant to use pattern matching - } -} diff --git a/src/test/ui/issues/issue-77218.stderr b/src/test/ui/issues/issue-77218.stderr deleted file mode 100644 index ce70c0111bee2..0000000000000 --- a/src/test/ui/issues/issue-77218.stderr +++ /dev/null @@ -1,40 +0,0 @@ -error[E0658]: destructuring assignments are unstable - --> $DIR/issue-77218.rs:3:19 - | -LL | while Some(0) = value.get(0) { - | ------- ^ - | | - | cannot assign to this expression - | - = note: see issue #71126 for more information - = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable - -error[E0070]: invalid left-hand side of assignment - --> $DIR/issue-77218.rs:3:19 - | -LL | while Some(0) = value.get(0) { - | - ^ - | | - | cannot assign to this expression - -error[E0308]: mismatched types - --> $DIR/issue-77218.rs:3:16 - | -LL | while Some(0) = value.get(0) { - | ^ expected integer, found `&u8` - | -help: consider dereferencing the borrow - | -LL | while Some(*0) = value.get(0) { - | + - -error[E0308]: mismatched types - --> $DIR/issue-77218.rs:3:11 - | -LL | while Some(0) = value.get(0) { - | ^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0070, E0308, E0658. -For more information about an error, try `rustc --explain E0070`. diff --git a/src/test/ui/issues/issue-77218/issue-77218-2.fixed b/src/test/ui/issues/issue-77218/issue-77218-2.fixed new file mode 100644 index 0000000000000..06487fe0886f9 --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218-2.fixed @@ -0,0 +1,7 @@ +// run-rustfix +#![feature(destructuring_assignment)] +fn main() { + let value = [7u8]; + while let Some(0) = value.get(0) { //~ ERROR invalid left-hand side of assignment + } +} diff --git a/src/test/ui/issues/issue-77218/issue-77218-2.rs b/src/test/ui/issues/issue-77218/issue-77218-2.rs new file mode 100644 index 0000000000000..e19cec08e4318 --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218-2.rs @@ -0,0 +1,7 @@ +// run-rustfix +#![feature(destructuring_assignment)] +fn main() { + let value = [7u8]; + while Some(0) = value.get(0) { //~ ERROR invalid left-hand side of assignment + } +} diff --git a/src/test/ui/issues/issue-77218/issue-77218-2.stderr b/src/test/ui/issues/issue-77218/issue-77218-2.stderr new file mode 100644 index 0000000000000..8d9eb2219d54c --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218-2.stderr @@ -0,0 +1,16 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/issue-77218-2.rs:5:19 + | +LL | while Some(0) = value.get(0) { + | - ^ + | | + | cannot assign to this expression + | +help: you might have meant to use pattern destructuring + | +LL | while let Some(0) = value.get(0) { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0070`. diff --git a/src/test/ui/issues/issue-77218/issue-77218.fixed b/src/test/ui/issues/issue-77218/issue-77218.fixed new file mode 100644 index 0000000000000..4ea5110902225 --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218.fixed @@ -0,0 +1,6 @@ +// run-rustfix +fn main() { + let value = [7u8]; + while let Some(0) = value.get(0) { //~ ERROR destructuring assignments are unstable + } +} diff --git a/src/test/ui/issues/issue-77218/issue-77218.rs b/src/test/ui/issues/issue-77218/issue-77218.rs new file mode 100644 index 0000000000000..0f3c12f56351d --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218.rs @@ -0,0 +1,6 @@ +// run-rustfix +fn main() { + let value = [7u8]; + while Some(0) = value.get(0) { //~ ERROR destructuring assignments are unstable + } +} diff --git a/src/test/ui/issues/issue-77218/issue-77218.stderr b/src/test/ui/issues/issue-77218/issue-77218.stderr new file mode 100644 index 0000000000000..54f49609a4427 --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218.stderr @@ -0,0 +1,18 @@ +error[E0658]: destructuring assignments are unstable + --> $DIR/issue-77218.rs:4:19 + | +LL | while Some(0) = value.get(0) { + | ------- ^ + | | + | cannot assign to this expression + | + = note: see issue #71126 for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable +help: you might have meant to use pattern destructuring + | +LL | while let Some(0) = value.get(0) { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-77919.rs b/src/test/ui/issues/issue-77919.rs index 966d76d148af3..6e597b7669abc 100644 --- a/src/test/ui/issues/issue-77919.rs +++ b/src/test/ui/issues/issue-77919.rs @@ -10,4 +10,4 @@ struct Multiply { } impl TypeVal for Multiply where N: TypeVal {} //~^ ERROR cannot find type `VAL` in this scope -//~| ERROR not all trait items implemented, missing: `VAL` +//~| ERROR type annotations needed diff --git a/src/test/ui/issues/issue-77919.stderr b/src/test/ui/issues/issue-77919.stderr index 97bd5ab36b65d..f98556bc72f47 100644 --- a/src/test/ui/issues/issue-77919.stderr +++ b/src/test/ui/issues/issue-77919.stderr @@ -17,16 +17,15 @@ LL | impl TypeVal for Multiply where N: TypeVal {} | | | help: you might be missing a type parameter: `, VAL` -error[E0046]: not all trait items implemented, missing: `VAL` - --> $DIR/issue-77919.rs:11:1 +error[E0283]: type annotations needed + --> $DIR/issue-77919.rs:11:12 | -LL | const VAL: T; - | ------------- `VAL` from trait -... LL | impl TypeVal for Multiply where N: TypeVal {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation + | ^^^^^^^^^^^^^^ cannot infer type for struct `Multiply` + | + = note: cannot satisfy `Multiply: TypeVal` error: aborting due to 3 previous errors -Some errors have detailed explanations: E0046, E0412. -For more information about an error, try `rustc --explain E0046`. +Some errors have detailed explanations: E0283, E0412. +For more information about an error, try `rustc --explain E0283`. diff --git a/src/test/ui/mismatched_types/issue-84976.stderr b/src/test/ui/mismatched_types/issue-84976.stderr index 0c27e17294131..f8f2b1f0f5720 100644 --- a/src/test/ui/mismatched_types/issue-84976.stderr +++ b/src/test/ui/mismatched_types/issue-84976.stderr @@ -7,6 +7,9 @@ LL | length = { foo(&length) }; error[E0308]: mismatched types --> $DIR/issue-84976.rs:17:14 | +LL | let mut length = 0; + | - expected due to this value +... LL | length = foo(&length); | ^^^^^^^^^^^^ expected `u32`, found `i32` @@ -19,6 +22,9 @@ LL | float_length = { bar(&float_length) }; error[E0308]: mismatched types --> $DIR/issue-84976.rs:23:20 | +LL | let mut float_length = 0.0; + | --- expected due to this value +... LL | float_length = bar(&float_length); | ^^^^^^^^^^^^^^^^^^ expected `f32`, found `f64` diff --git a/src/test/ui/output-type-mismatch.stderr b/src/test/ui/output-type-mismatch.stderr index 533bd87c9cccb..4507a4df621e1 100644 --- a/src/test/ui/output-type-mismatch.stderr +++ b/src/test/ui/output-type-mismatch.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/output-type-mismatch.rs:5:31 | LL | fn main() { let i: isize; i = f(); } - | ^^^ expected `isize`, found `()` + | ----- ^^^ expected `isize`, found `()` + | | + | expected due to this type error: aborting due to previous error diff --git a/src/test/ui/static/static-mut-bad-types.stderr b/src/test/ui/static/static-mut-bad-types.stderr index ddd98ff40798a..983e1026f91e9 100644 --- a/src/test/ui/static/static-mut-bad-types.stderr +++ b/src/test/ui/static/static-mut-bad-types.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/static-mut-bad-types.rs:5:13 | +LL | static mut a: isize = 3; + | ----- expected due to this type +... LL | a = true; | ^^^^ expected `isize`, found `bool` diff --git a/src/test/ui/suggestions/if-let-typo.stderr b/src/test/ui/suggestions/if-let-typo.stderr index 7f71cb485815f..058f42f220064 100644 --- a/src/test/ui/suggestions/if-let-typo.stderr +++ b/src/test/ui/suggestions/if-let-typo.stderr @@ -70,11 +70,6 @@ error[E0308]: mismatched types | LL | if 3 = foo {} | ^^^^^^^ expected `bool`, found `()` - | -help: you might have meant to use pattern matching - | -LL | if let 3 = foo {} - | +++ error[E0070]: invalid left-hand side of assignment --> $DIR/if-let-typo.rs:10:16 diff --git a/src/test/ui/suggestions/mut-ref-reassignment.stderr b/src/test/ui/suggestions/mut-ref-reassignment.stderr index fd5677898e656..3bd98c7630780 100644 --- a/src/test/ui/suggestions/mut-ref-reassignment.stderr +++ b/src/test/ui/suggestions/mut-ref-reassignment.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/mut-ref-reassignment.rs:2:11 | +LL | fn suggestion(opt: &mut Option) { + | ------------------- expected due to this parameter type LL | opt = None; | ^^^^ expected mutable reference, found enum `Option` | @@ -14,6 +16,8 @@ LL | *opt = None; error[E0308]: mismatched types --> $DIR/mut-ref-reassignment.rs:6:11 | +LL | fn no_suggestion(opt: &mut Result) { + | ----------------------- expected due to this parameter type LL | opt = None | ^^^^ expected mutable reference, found enum `Option` | @@ -23,6 +27,8 @@ LL | opt = None error[E0308]: mismatched types --> $DIR/mut-ref-reassignment.rs:10:11 | +LL | fn suggestion2(opt: &mut Option) { + | ------------------- expected due to this parameter type LL | opt = Some(String::new()) | ^^^^^^^^^^^^^^^^^^^ expected mutable reference, found enum `Option` | @@ -36,6 +42,8 @@ LL | *opt = Some(String::new()) error[E0308]: mismatched types --> $DIR/mut-ref-reassignment.rs:14:11 | +LL | fn no_suggestion2(opt: &mut Option) { + | ------------------- expected due to this parameter type LL | opt = Some(42) | ^^^^^^^^ expected mutable reference, found enum `Option` | diff --git a/src/test/ui/type-alias-impl-trait/argument-types.stderr b/src/test/ui/type-alias-impl-trait/argument-types.stderr index 1cbf9c95d3148..a87e44a048b25 100644 --- a/src/test/ui/type-alias-impl-trait/argument-types.stderr +++ b/src/test/ui/type-alias-impl-trait/argument-types.stderr @@ -4,6 +4,8 @@ error[E0308]: mismatched types LL | type Foo = impl Debug; | ---------- the expected opaque type ... +LL | fn foo1(mut x: Foo) { + | --- expected due to this parameter type LL | x = 22_u32; | ^^^^^^ expected opaque type, found `u32` | diff --git a/src/test/ui/type/type-check/assignment-expected-bool.stderr b/src/test/ui/type/type-check/assignment-expected-bool.stderr index 862ac65bc24e4..e2b821f7b05e9 100644 --- a/src/test/ui/type/type-check/assignment-expected-bool.stderr +++ b/src/test/ui/type/type-check/assignment-expected-bool.stderr @@ -48,10 +48,6 @@ error[E0308]: mismatched types LL | if 0 = 0 {} | ^^^^^ expected `bool`, found `()` | -help: you might have meant to use pattern matching - | -LL | if let 0 = 0 {} - | +++ help: you might have meant to compare for equality | LL | if 0 == 0 {} diff --git a/src/test/ui/type/type-check/assignment-in-if.stderr b/src/test/ui/type/type-check/assignment-in-if.stderr index 710be9d6a0420..f4ef44e2444ee 100644 --- a/src/test/ui/type/type-check/assignment-in-if.stderr +++ b/src/test/ui/type/type-check/assignment-in-if.stderr @@ -37,10 +37,6 @@ error[E0308]: mismatched types LL | if 3 = x { | ^^^^^ expected `bool`, found `()` | -help: you might have meant to use pattern matching - | -LL | if let 3 = x { - | +++ help: you might have meant to compare for equality | LL | if 3 == x { diff --git a/src/test/ui/typeck/issue-81293.stderr b/src/test/ui/typeck/issue-81293.stderr index 1e6ff3b5f9ee7..c545a563b0d0a 100644 --- a/src/test/ui/typeck/issue-81293.stderr +++ b/src/test/ui/typeck/issue-81293.stderr @@ -7,6 +7,9 @@ LL | a = c + b * 5; error[E0308]: mismatched types --> $DIR/issue-81293.rs:6:9 | +LL | let a: u16; + | --- expected due to this type +... LL | a = c + b * 5; | ^^^^^^^^^ expected `u16`, found `usize` diff --git a/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr b/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr index fe10fa733d238..56817ee2ca9f8 100644 --- a/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr +++ b/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-87771-ice-assign-assign-to-bool.rs:3:9 | +LL | let mut a; + | ----- expected due to the type of this binding LL | a = a = true; | ^^^^^^^^ expected `bool`, found `()` diff --git a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr index 439884b7d274a..0d7713aa9a278 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr @@ -24,6 +24,9 @@ LL | | } error[E0308]: mismatched types --> $DIR/ice-6250.rs:12:14 | +LL | for reference in vec![1, 2, 3] { + | --------- expected due to the type of this binding +... LL | Some(reference) = cache.data.get(key) { | ^^^^^^^^^ expected integer, found `&i32` |