diff --git a/Cargo.lock b/Cargo.lock index 5f01a9430cd03..c0905982467df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3595,6 +3595,7 @@ dependencies = [ "rustc_index", "rustc_infer", "rustc_lexer", + "rustc_macros", "rustc_middle", "rustc_mir_dataflow", "rustc_serialize", diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml index 87a287e694a20..fbf628e865e2c 100644 --- a/compiler/rustc_borrowck/Cargo.toml +++ b/compiler/rustc_borrowck/Cargo.toml @@ -19,6 +19,7 @@ rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_lexer = { path = "../rustc_lexer" } +rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_const_eval = { path = "../rustc_const_eval" } rustc_mir_dataflow = { path = "../rustc_mir_dataflow" } diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 07f182102f346..1ef2b0ae98843 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -19,6 +19,9 @@ use std::fmt; use std::rc::Rc; use crate::region_infer::values::RegionElement; +use crate::session_diagnostics::HigherRankedErrorCause; +use crate::session_diagnostics::HigherRankedLifetimeError; +use crate::session_diagnostics::HigherRankedSubtypeError; use crate::MirBorrowckCtxt; #[derive(Clone)] @@ -69,7 +72,7 @@ impl<'tcx> UniverseInfo<'tcx> { // up in the existing UI tests. Consider investigating this // some more. mbcx.buffer_error( - mbcx.infcx.tcx.sess.struct_span_err(cause.span, "higher-ranked subtype error"), + mbcx.infcx.tcx.sess.create_err(HigherRankedSubtypeError { span: cause.span }), ); } } @@ -216,9 +219,12 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> { tcx: TyCtxt<'tcx>, span: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error"); - err.note(&format!("could not prove {}", self.canonical_query.value.value.predicate)); - err + tcx.sess.create_err(HigherRankedLifetimeError { + cause: Some(HigherRankedErrorCause::CouldNotProve { + predicate: self.canonical_query.value.value.predicate.to_string(), + }), + span, + }) } fn base_universe(&self) -> ty::UniverseIndex { @@ -263,9 +269,12 @@ where tcx: TyCtxt<'tcx>, span: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error"); - err.note(&format!("could not normalize `{}`", self.canonical_query.value.value.value)); - err + tcx.sess.create_err(HigherRankedLifetimeError { + cause: Some(HigherRankedErrorCause::CouldNotNormalize { + value: self.canonical_query.value.value.value.to_string(), + }), + span, + }) } fn base_universe(&self) -> ty::UniverseIndex { @@ -326,7 +335,7 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { // FIXME: This error message isn't great, but it doesn't show up in the existing UI tests, // and is only the fallback when the nice error fails. Consider improving this some more. - tcx.sess.struct_span_err(span, "higher-ranked lifetime error") + tcx.sess.create_err(HigherRankedLifetimeError { cause: None, span }) } fn base_universe(&self) -> ty::UniverseIndex { @@ -366,7 +375,7 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { // FIXME: This error message isn't great, but it doesn't show up in the existing UI tests, // and is only the fallback when the nice error fails. Consider improving this some more. - tcx.sess.struct_span_err(span, "higher-ranked lifetime error for opaque type!") + tcx.sess.create_err(HigherRankedLifetimeError { cause: None, span }) } fn base_universe(&self) -> ty::UniverseIndex { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index e0f8da1c872d3..5d3997289bb33 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -24,6 +24,7 @@ use rustc_span::symbol::Ident; use rustc_span::Span; use crate::borrowck_errors; +use crate::session_diagnostics::GenericDoesNotLiveLongEnough; use super::{OutlivesSuggestionBuilder, RegionName}; use crate::region_infer::BlameConstraint; @@ -196,9 +197,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // to report it; we could probably handle it by // iterating over the universal regions and reporting // an error that multiple bounds are required. - self.buffer_error(self.infcx.tcx.sess.struct_span_err( - type_test_span, - &format!("`{}` does not live long enough", type_test.generic_kind), + self.buffer_error(self.infcx.tcx.sess.create_err( + GenericDoesNotLiveLongEnough { + kind: type_test.generic_kind.to_string(), + span: type_test_span, + }, )); } } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index a2df072aa3119..7d6f37340c2bb 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -76,6 +76,7 @@ mod places_conflict; mod prefixes; mod region_infer; mod renumber; +mod session_diagnostics; mod type_check; mod universal_regions; mod used_muts; diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs new file mode 100644 index 0000000000000..895723d44ff1b --- /dev/null +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -0,0 +1,44 @@ +use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic}; +use rustc_middle::ty::Ty; +use rustc_span::Span; + +#[derive(SessionDiagnostic)] +#[error(borrowck::move_unsized, code = "E0161")] +pub(crate) struct MoveUnsized<'tcx> { + pub ty: Ty<'tcx>, + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(borrowck::higher_ranked_lifetime_error)] +pub(crate) struct HigherRankedLifetimeError { + #[subdiagnostic] + pub cause: Option, + #[primary_span] + pub span: Span, +} + +#[derive(SessionSubdiagnostic)] +pub(crate) enum HigherRankedErrorCause { + #[note(borrowck::could_not_prove)] + CouldNotProve { predicate: String }, + #[note(borrowck::could_not_normalize)] + CouldNotNormalize { value: String }, +} + +#[derive(SessionDiagnostic)] +#[error(borrowck::higher_ranked_subtype_error)] +pub(crate) struct HigherRankedSubtypeError { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(borrowck::generic_does_not_live_long_enough)] +pub(crate) struct GenericDoesNotLiveLongEnough { + pub kind: String, + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 542fc6b0f485d..5ee1f5a8e8e37 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -9,7 +9,6 @@ use hir::OpaqueTyOrigin; use rustc_data_structures::frozen::Frozen; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::vec_map::VecMap; -use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; @@ -48,6 +47,7 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::MoveData; use rustc_mir_dataflow::ResultsCursor; +use crate::session_diagnostics::MoveUnsized; use crate::{ borrow_set::BorrowSet, constraints::{OutlivesConstraint, OutlivesConstraintSet}, @@ -1780,19 +1780,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // slot or local, so to find all unsized rvalues it is enough // to check all temps, return slots and locals. if self.reported_errors.replace((ty, span)).is_none() { - let mut diag = struct_span_err!( - self.tcx().sess, - span, - E0161, - "cannot move a value of type {0}: the size of {0} \ - cannot be statically determined", - ty - ); - // While this is located in `nll::typeck` this error is not // an NLL error, it's a required check to prevent creation // of unsized rvalues in a call expression. - diag.emit(); + self.tcx().sess.emit_err(MoveUnsized { ty, span }); } } } diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index fb484fba9fd06..076415b2d1b2f 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -366,22 +366,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { assert_eq!(def_a, def_b); - if def_a.is_box() || def_b.is_box() { - if !def_a.is_box() || !def_b.is_box() { - span_bug!( - self.cur_span(), - "invalid unsizing between {:?} -> {:?}", - src.layout.ty, - cast_ty.ty - ); - } - return self.unsize_into_ptr( - src, - dest, - src.layout.ty.boxed_ty(), - cast_ty.ty.boxed_ty(), - ); - } // unsizing of generic struct with pointer fields // Example: `Arc` -> `Arc` diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 630281bb09254..905ab6cb578fc 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -594,7 +594,13 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' Ok(true) } ty::Adt(def, ..) if def.is_box() => { - self.check_safe_pointer(value, "box")?; + let unique = self.ecx.operand_field(value, 0)?; + let nonnull = self.ecx.operand_field(&unique, 0)?; + let ptr = self.ecx.operand_field(&nonnull, 0)?; + self.check_safe_pointer(&ptr, "box")?; + + // Check other fields of Box + self.walk_value(value)?; Ok(true) } ty::FnPtr(_sig) => { diff --git a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl new file mode 100644 index 0000000000000..645673ef47aeb --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl @@ -0,0 +1,18 @@ +borrowck-move-unsized = + cannot move a value of type `{$ty}` + .label = the size of `{$ty}` cannot be statically determined + +borrowck-higher-ranked-lifetime-error = + higher-ranked lifetime error + +borrowck-could-not-prove = + could not prove `{$predicate}` + +borrowck-could-not-normalize = + could not normalize `{$value}` + +borrowck-higher-ranked-subtype-error = + higher-ranked subtype error + +generic-does-not-live-long-enough = + `{$kind}` does not live long enough \ No newline at end of file diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 90eb5ef54462d..d52b94b78dfac 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -35,6 +35,7 @@ fluent_messages! { privacy => "../locales/en-US/privacy.ftl", typeck => "../locales/en-US/typeck.ftl", builtin_macros => "../locales/en-US/builtin_macros.ftl", + borrowck => "../locales/en-US/borrowck.ftl", } pub use fluent_generated::{self as fluent, DEFAULT_LOCALE_RESOURCES}; diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 8b2a995f1c58e..6d74e9a9f2b9e 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -281,9 +281,19 @@ pub trait Emitter { let message = bundle.get_message(&identifier).expect("missing diagnostic in fluent bundle"); let value = match attr { Some(attr) => { - message.get_attribute(attr).expect("missing attribute in fluent message").value() + if let Some(attr) = message.get_attribute(attr) { + attr.value() + } else { + panic!("missing attribute `{attr}` in fluent message `{identifier}`") + } + } + None => { + if let Some(value) = message.value() { + value + } else { + panic!("missing value in fluent message `{identifier}`") + } } - None => message.value().expect("missing value in fluent message"), }; let mut err = vec![]; diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index b94d205488d01..e319f17b0e60d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -342,8 +342,8 @@ pub fn same_type_modulo_infer<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { ) | (&ty::Infer(ty::InferTy::TyVar(_)), _) | (_, &ty::Infer(ty::InferTy::TyVar(_))) => true, - (&ty::Ref(reg_a, ty_a, mut_a), &ty::Ref(reg_b, ty_b, mut_b)) => { - reg_a == reg_b && mut_a == mut_b && same_type_modulo_infer(*ty_a, *ty_b) + (&ty::Ref(_, ty_a, mut_a), &ty::Ref(_, ty_b, mut_b)) => { + mut_a == mut_b && same_type_modulo_infer(*ty_a, *ty_b) } _ => a == b, } diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 0495439385bee..0f87e638d2618 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -33,8 +33,9 @@ fn is_stable(place: PlaceRef<'_>) -> bool { }) } -/// Determine whether this type may be a reference (or box), and thus needs retagging. -fn may_be_reference(ty: Ty<'_>) -> bool { +/// Determine whether this type may contain a reference (or box), and thus needs retagging. +/// We will only recurse `depth` times into Tuples/ADTs to bound the cost of this. +fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> bool { match ty.kind() { // Primitive types that are not references ty::Bool @@ -50,8 +51,20 @@ fn may_be_reference(ty: Ty<'_>) -> bool { // References ty::Ref(..) => true, ty::Adt(..) if ty.is_box() => true, - // Compound types are not references - ty::Array(..) | ty::Slice(..) | ty::Tuple(..) | ty::Adt(..) => false, + // Compound types: recurse + ty::Array(ty, _) | ty::Slice(ty) => { + // This does not branch so we keep the depth the same. + may_contain_reference(*ty, depth, tcx) + } + ty::Tuple(tys) => { + depth == 0 || tys.iter().any(|ty| may_contain_reference(ty, depth - 1, tcx)) + } + ty::Adt(adt, subst) => { + depth == 0 + || adt.variants().iter().any(|v| { + v.fields.iter().any(|f| may_contain_reference(f.ty(tcx, subst), depth - 1, tcx)) + }) + } // Conservative fallback _ => true, } @@ -83,7 +96,7 @@ impl<'tcx> MirPass<'tcx> for AddRetag { // FIXME: Instead of giving up for unstable places, we should introduce // a temporary and retag on that. is_stable(place.as_ref()) - && may_be_reference(place.ty(&*local_decls, tcx).ty) + && may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx) && is_not_temp(&local_decls[place.local]) }; let place_base_raw = |place: &Place<'tcx>| { diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 5d08ea99ac64a..424eff2f6212a 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -236,7 +236,7 @@ impl<'tcx> AbstractConst<'tcx> { ) -> Result>, ErrorGuaranteed> { let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?; debug!("AbstractConst::new({:?}) = {:?}", uv, inner); - Ok(inner.map(|inner| AbstractConst { inner, substs: uv.substs })) + Ok(inner.map(|inner| AbstractConst { inner, substs: tcx.erase_regions(uv.substs) })) } pub fn from_const( @@ -416,6 +416,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { // `AbstractConst`s should not contain any promoteds as they require references which // are not allowed. assert_eq!(ct.promoted, None); + assert_eq!(ct, self.tcx.erase_regions(ct)); } } } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 08df01c0c1a1a..dc49ff90f34b0 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -24,7 +24,6 @@ use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt}; use rustc_infer::infer::InferOk; use rustc_infer::infer::TypeTrace; use rustc_middle::ty::adjustment::AllowTwoPhase; -use rustc_middle::ty::error::TypeError; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt}; use rustc_session::Session; @@ -35,12 +34,6 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode, StatementAsExpres use std::iter; use std::slice; -enum TupleMatchFound { - None, - Single, - /// Beginning and end Span - Multiple(Span, Span), -} impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(in super::super) fn check_casts(&self) { let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut(); @@ -216,14 +209,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let minimum_input_count = expected_input_tys.len(); let provided_arg_count = provided_args.len(); - // We'll also want to keep track of the fully coerced argument types, for an awkward hack near the end - // FIXME(compiler-errors): Get rid of this, actually. - let mut final_arg_types: Vec, Ty<'_>)>> = vec![None; provided_arg_count]; - // We introduce a helper function to demand that a given argument satisfy a given input // This is more complicated than just checking type equality, as arguments could be coerced // This version writes those types back so further type checking uses the narrowed types - let demand_compatible = |idx, final_arg_types: &mut Vec, Ty<'tcx>)>>| { + let demand_compatible = |idx| { let formal_input_ty: Ty<'tcx> = formal_input_tys[idx]; let expected_input_ty: Ty<'tcx> = expected_input_tys[idx]; let provided_arg = &provided_args[idx]; @@ -242,9 +231,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise. let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty); - // Keep track of these for below - final_arg_types[idx] = Some((checked_ty, coerced_ty)); - // Cause selection errors caused by resolving a single argument to point at the // argument and not the call. This lets us customize the span pointed to in the // fulfillment error to be more accurate. @@ -253,16 +239,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr); self.point_at_arg_instead_of_call_if_possible( errors, - &final_arg_types, call_expr, call_span, provided_args, + &expected_input_tys, ); }); - // Make sure we store the resolved type - final_arg_types[idx] = Some((checked_ty, coerced_ty)); - let coerce_error = self .try_coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None) .err(); @@ -320,10 +303,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr); self.point_at_arg_instead_of_call_if_possible( errors, - &final_arg_types, call_expr, call_span, &provided_args, + &expected_input_tys, ); }) } @@ -352,7 +335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { continue; } - let compatible = demand_compatible(idx, &mut final_arg_types); + let compatible = demand_compatible(idx); let is_compatible = matches!(compatible, Compatibility::Compatible); compatibility_diagonal[idx] = compatible; @@ -445,72 +428,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None => "function", }; - let try_tuple_wrap_args = || { - // The case where we expect a single tuple and wrapping all the args - // in parentheses (or adding a comma to already existing parentheses) - // will result in a tuple that satisfies the call. - // This isn't super ideal code, because we copy code from elsewhere - // and somewhat duplicate this. We also delegate to the general type - // mismatch suggestions for the single arg case. - match self.suggested_tuple_wrap(&expected_input_tys, provided_args) { - TupleMatchFound::Single => { - let expected_ty = expected_input_tys[0]; - let provided_ty = final_arg_types[0].map(|ty| ty.0).unwrap(); - let expected_ty = self.resolve_vars_if_possible(expected_ty); - let provided_ty = self.resolve_vars_if_possible(provided_ty); - let cause = &self.misc(provided_args[0].span); - let compatibility = demand_compatible(0, &mut final_arg_types); - let type_error = match compatibility { - Compatibility::Incompatible(Some(error)) => error, - _ => TypeError::Mismatch, - }; - let trace = TypeTrace::types(cause, true, expected_ty, provided_ty); - let mut err = self.report_and_explain_type_error(trace, &type_error); - self.emit_coerce_suggestions( - &mut err, - &provided_args[0], - final_arg_types[0].map(|ty| ty.0).unwrap(), - final_arg_types[0].map(|ty| ty.1).unwrap(), - None, - None, - ); - err.span_label( - full_call_span, - format!("arguments to this {} are incorrect", call_name), - ); - // Call out where the function is defined - label_fn_like(tcx, &mut err, fn_def_id); - err.emit(); - return true; - } - TupleMatchFound::Multiple(start, end) => { - let mut err = tcx.sess.struct_span_err_with_code( - full_call_span, - &format!( - "this {} takes {}{} but {} {} supplied", - call_name, - if c_variadic { "at least " } else { "" }, - potentially_plural_count(minimum_input_count, "argument"), - potentially_plural_count(provided_arg_count, "argument"), - if provided_arg_count == 1 { "was" } else { "were" } - ), - DiagnosticId::Error(err_code.to_owned()), - ); - // Call out where the function is defined - label_fn_like(tcx, &mut err, fn_def_id); - err.multipart_suggestion( - "use parentheses to construct a tuple", - vec![(start, '('.to_string()), (end, ')'.to_string())], - Applicability::MachineApplicable, - ); - err.emit(); - return true; - } - TupleMatchFound::None => {} - } - false - }; - let compatibility_diagonal = IndexVec::from_raw(compatibility_diagonal); let provided_args = IndexVec::from_iter(provided_args.iter().take(if c_variadic { minimum_input_count @@ -541,7 +458,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { c_variadic, err_code, fn_def_id, - try_tuple_wrap_args, ); } } @@ -558,7 +474,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { c_variadic: bool, err_code: &str, fn_def_id: Option, - try_tuple_wrap_args: impl FnOnce() -> bool, ) { // Don't print if it has error types or is just plain `_` fn has_error_or_infer<'tcx>(tys: impl IntoIterator>) -> bool { @@ -578,7 +493,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (formal_input_ty, expected_input_ty) = formal_and_expected_inputs[expected_idx]; // If either is an error type, we defy the usual convention and consider them to *not* be - // coercible. This prevents our error message heuristic from trying to pass errors into + // coercible. This prevents our error message heuristic from trying to pass errors into // every argument. if (formal_input_ty, expected_input_ty).references_error() { return Compatibility::Incompatible(None); @@ -599,16 +514,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Compatibility::Incompatible(None); } - let subtyping_result = self - .at(&self.misc(provided_arg.span), self.param_env) - .sup(formal_input_ty, coerced_ty); + // Using probe here, since we don't want this subtyping to affect inference. + let subtyping_error = self.probe(|_| { + self.at(&self.misc(provided_arg.span), self.param_env) + .sup(formal_input_ty, coerced_ty) + .err() + }); // Same as above: if either the coerce type or the checked type is an error type, // consider them *not* compatible. let references_error = (coerced_ty, checked_ty).references_error(); - match (references_error, &subtyping_result) { - (false, Ok(_)) => Compatibility::Compatible, - _ => Compatibility::Incompatible(subtyping_result.err()), + match (references_error, subtyping_error) { + (false, None) => Compatibility::Compatible, + (_, subtyping_error) => Compatibility::Incompatible(subtyping_error), } }; @@ -629,9 +547,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .iter() .map(|expr| { let ty = self - .in_progress_typeck_results - .as_ref() - .unwrap() + .typeck_results .borrow() .expr_ty_adjusted_opt(*expr) .unwrap_or_else(|| tcx.ty_error()); @@ -639,6 +555,97 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) .collect(); + // First, check if we just need to wrap some arguments in a tuple. + if let Some((mismatch_idx, terr)) = + compatibility_diagonal.iter().enumerate().find_map(|(i, c)| { + if let Compatibility::Incompatible(Some(terr)) = c { Some((i, terr)) } else { None } + }) + { + // Is the first bad expected argument a tuple? + // Do we have as many extra provided arguments as the tuple's length? + // If so, we might have just forgotten to wrap some args in a tuple. + if let Some(ty::Tuple(tys)) = + formal_and_expected_inputs.get(mismatch_idx.into()).map(|tys| tys.1.kind()) + && provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len() + { + // Wrap up the N provided arguments starting at this position in a tuple. + let provided_as_tuple = tcx.mk_tup( + provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx).take(tys.len()), + ); + + let mut satisfied = true; + // Check if the newly wrapped tuple + rest of the arguments are compatible. + for ((_, expected_ty), provided_ty) in std::iter::zip( + formal_and_expected_inputs.iter().skip(mismatch_idx), + [provided_as_tuple].into_iter().chain( + provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx + tys.len()), + ), + ) { + if !self.can_coerce(provided_ty, *expected_ty) { + satisfied = false; + break; + } + } + + // If they're compatible, suggest wrapping in an arg, and we're done! + // Take some care with spans, so we don't suggest wrapping a macro's + // innards in parenthesis, for example. + if satisfied + && let Some(lo) = + provided_args[mismatch_idx.into()].span.find_ancestor_inside(error_span) + && let Some(hi) = provided_args[(mismatch_idx + tys.len() - 1).into()] + .span + .find_ancestor_inside(error_span) + { + let mut err; + if tys.len() == 1 { + // A tuple wrap suggestion actually occurs within, + // so don't do anything special here. + err = self.report_and_explain_type_error( + TypeTrace::types( + &self.misc(lo), + true, + formal_and_expected_inputs[mismatch_idx.into()].1, + provided_arg_tys[mismatch_idx.into()].0, + ), + terr, + ); + err.span_label( + full_call_span, + format!("arguments to this {} are incorrect", call_name), + ); + } else { + err = tcx.sess.struct_span_err_with_code( + full_call_span, + &format!( + "this {} takes {}{} but {} {} supplied", + call_name, + if c_variadic { "at least " } else { "" }, + potentially_plural_count( + formal_and_expected_inputs.len(), + "argument" + ), + potentially_plural_count(provided_args.len(), "argument"), + if provided_args.len() == 1 { "was" } else { "were" } + ), + DiagnosticId::Error(err_code.to_owned()), + ); + err.multipart_suggestion_verbose( + "wrap these arguments in parentheses to construct a tuple", + vec![ + (lo.shrink_to_lo(), "(".to_string()), + (hi.shrink_to_hi(), ")".to_string()), + ], + Applicability::MachineApplicable, + ); + }; + label_fn_like(tcx, &mut err, fn_def_id); + err.emit(); + return; + } + } + } + // Okay, so here's where it gets complicated in regards to what errors // we emit and how. // There are 3 different "types" of errors we might encounter. @@ -666,7 +673,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) .note( "we would appreciate a bug report: \ - https://github.com/rust-lang/rust-clippy/issues/new", + https://github.com/rust-lang/rust/issues/new", ) .emit(); } @@ -727,13 +734,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } - // Second, let's try tuple wrapping the args. - // FIXME(compiler-errors): This is currently in its own closure because - // I didn't want to factor it out. - if try_tuple_wrap_args() { - return; - } - let mut err = if formal_and_expected_inputs.len() == provided_args.len() { struct_span_err!( tcx.sess, @@ -989,13 +989,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { String::new() }; - // FIXME(compiler-errors): Why do we get permutations with the same type? - if expected_ty != provided_ty { - labels.push(( - provided_span, - format!("expected `{}`{}", expected_ty, provided_ty_name), - )); - } + labels.push(( + provided_span, + format!("expected `{}`{}", expected_ty, provided_ty_name), + )); } suggestion_text = match suggestion_text { @@ -1043,10 +1040,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { needs_comma = true; } - let suggestion_text = - if let Some(provided_idx) = provided_idx + let suggestion_text = if let Some(provided_idx) = provided_idx && let (_, provided_span) = provided_arg_tys[*provided_idx] - && let Ok(arg_text) = source_map.span_to_snippet(provided_span.source_callsite()) { + && let Ok(arg_text) = + source_map.span_to_snippet(provided_span.source_callsite()) + { arg_text } else { // Propose a placeholder of the correct type @@ -1073,38 +1071,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit(); } - fn suggested_tuple_wrap( - &self, - expected_input_tys: &[Ty<'tcx>], - provided_args: &'tcx [hir::Expr<'tcx>], - ) -> TupleMatchFound { - // Only handle the case where we expect only one tuple arg - let [expected_arg_type] = expected_input_tys[..] else { return TupleMatchFound::None }; - let &ty::Tuple(expected_types) = self.resolve_vars_if_possible(expected_arg_type).kind() - else { return TupleMatchFound::None }; - - // First check that there are the same number of types. - if expected_types.len() != provided_args.len() { - return TupleMatchFound::None; - } - - let supplied_types: Vec<_> = provided_args.iter().map(|arg| self.check_expr(arg)).collect(); - - let all_match = iter::zip(expected_types, supplied_types) - .all(|(expected, supplied)| self.can_eq(self.param_env, expected, supplied).is_ok()); - - if !all_match { - return TupleMatchFound::None; - } - match provided_args { - [] => TupleMatchFound::None, - [_] => TupleMatchFound::Single, - [first, .., last] => { - TupleMatchFound::Multiple(first.span.shrink_to_lo(), last.span.shrink_to_hi()) - } - } - } - // AST fragment checking pub(in super::super) fn check_lit( &self, @@ -1652,10 +1618,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn point_at_arg_instead_of_call_if_possible( &self, errors: &mut Vec>, - final_arg_types: &[Option<(Ty<'tcx>, Ty<'tcx>)>], expr: &'tcx hir::Expr<'tcx>, call_sp: Span, args: &'tcx [hir::Expr<'tcx>], + expected_tys: &[Ty<'tcx>], ) { // We *do not* do this for desugared call spans to keep good diagnostics when involving // the `?` operator. @@ -1663,7 +1629,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } - for error in errors { + 'outer: for error in errors { // Only if the cause is somewhere inside the expression we want try to point at arg. // Otherwise, it means that the cause is somewhere else and we should not change // anything because we can break the correct span. @@ -1688,39 +1654,65 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (result_code, code) = (code, parent); } } - let self_: ty::subst::GenericArg<'_> = match unpeel_to_top(error.obligation.cause.code()) { - ObligationCauseCode::BuiltinDerivedObligation(code) | - ObligationCauseCode::DerivedObligation(code) => { - code.parent_trait_pred.self_ty().skip_binder().into() - } - ObligationCauseCode::ImplDerivedObligation(code) => { - code.derived.parent_trait_pred.self_ty().skip_binder().into() - } - _ if let ty::PredicateKind::Trait(predicate) = - error.obligation.predicate.kind().skip_binder() => { + let self_: ty::subst::GenericArg<'_> = + match unpeel_to_top(error.obligation.cause.code()) { + ObligationCauseCode::BuiltinDerivedObligation(code) + | ObligationCauseCode::DerivedObligation(code) => { + code.parent_trait_pred.self_ty().skip_binder().into() + } + ObligationCauseCode::ImplDerivedObligation(code) => { + code.derived.parent_trait_pred.self_ty().skip_binder().into() + } + _ if let ty::PredicateKind::Trait(predicate) = + error.obligation.predicate.kind().skip_binder() => + { predicate.self_ty().into() } - _ => continue, - }; + _ => continue, + }; let self_ = self.resolve_vars_if_possible(self_); + let ty_matches_self = |ty: Ty<'tcx>| ty.walk().any(|arg| arg == self_); + + let typeck_results = self.typeck_results.borrow(); + + for (idx, arg) in args.iter().enumerate() { + // Don't adjust the span if we already have a more precise span + // within one of the args. + if arg.span.contains(error.obligation.cause.span) { + let references_arg = + typeck_results.expr_ty_opt(arg).map_or(false, &ty_matches_self) + || expected_tys.get(idx).copied().map_or(false, &ty_matches_self); + if references_arg && !arg.span.from_expansion() { + error.obligation.cause.map_code(|parent_code| { + ObligationCauseCode::FunctionArgumentObligation { + arg_hir_id: args[idx].hir_id, + call_hir_id: expr.hir_id, + parent_code, + } + }) + } + continue 'outer; + } + } // Collect the argument position for all arguments that could have caused this // `FulfillmentError`. - let mut referenced_in = final_arg_types - .iter() + let mut referenced_in: Vec<_> = std::iter::zip(expected_tys, args) .enumerate() - .filter_map(|(i, arg)| match arg { - Some((checked_ty, coerce_ty)) => Some([(i, *checked_ty), (i, *coerce_ty)]), - _ => None, + .flat_map(|(idx, (expected_ty, arg))| { + if let Some(arg_ty) = typeck_results.expr_ty_opt(arg) { + vec![(idx, arg_ty), (idx, *expected_ty)] + } else { + vec![] + } }) - .flatten() - .flat_map(|(i, ty)| { + .filter_map(|(i, ty)| { let ty = self.resolve_vars_if_possible(ty); // We walk the argument type because the argument's type could have // been `Option`, but the `FulfillmentError` references `T`. - if ty.walk().any(|arg| arg == self_) { Some(i) } else { None } + if ty_matches_self(ty) { Some(i) } else { None } }) - .collect::>(); + .collect(); // Both checked and coerced types could have matched, thus we need to remove // duplicates. @@ -1729,18 +1721,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { referenced_in.sort_unstable(); referenced_in.dedup(); - if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) { + if let &[idx] = &referenced_in[..] { // Do not point at the inside of a macro. // That would often result in poor error messages. - if args[ref_in].span.from_expansion() { - return; + if args[idx].span.from_expansion() { + continue; } // We make sure that only *one* argument matches the obligation failure // and we assign the obligation's span to its expression's. - error.obligation.cause.span = args[ref_in].span; + error.obligation.cause.span = args[idx].span; error.obligation.cause.map_code(|parent_code| { ObligationCauseCode::FunctionArgumentObligation { - arg_hir_id: args[ref_in].hir_id, + arg_hir_id: args[idx].hir_id, call_hir_id: expr.hir_id, parent_code, } diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 93cdf121fbe0f..43e4b7f08e22d 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -231,7 +231,8 @@ impl fmt::Debug for c_void { all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), target_family = "wasm", target_arch = "asmjs", - windows + target_os = "uefi", + windows, ))] #[repr(transparent)] #[unstable( @@ -254,7 +255,8 @@ pub struct VaListImpl<'f> { all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), target_family = "wasm", target_arch = "asmjs", - windows + target_os = "uefi", + windows, ))] #[unstable( feature = "c_variadic", @@ -276,7 +278,8 @@ impl<'f> fmt::Debug for VaListImpl<'f> { #[cfg(all( target_arch = "aarch64", not(any(target_os = "macos", target_os = "ios")), - not(windows) + not(target_os = "uefi"), + not(windows), ))] #[repr(C)] #[derive(Debug)] @@ -297,7 +300,7 @@ pub struct VaListImpl<'f> { } /// PowerPC ABI implementation of a `va_list`. -#[cfg(all(target_arch = "powerpc", not(windows)))] +#[cfg(all(target_arch = "powerpc", not(target_os = "uefi"), not(windows)))] #[repr(C)] #[derive(Debug)] #[unstable( @@ -317,7 +320,7 @@ pub struct VaListImpl<'f> { } /// x86_64 ABI implementation of a `va_list`. -#[cfg(all(target_arch = "x86_64", not(windows)))] +#[cfg(all(target_arch = "x86_64", not(target_os = "uefi"), not(windows)))] #[repr(C)] #[derive(Debug)] #[unstable( @@ -354,7 +357,8 @@ pub struct VaList<'a, 'f: 'a> { all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), target_family = "wasm", target_arch = "asmjs", - windows + target_os = "uefi", + windows, ))] inner: VaListImpl<'f>, @@ -363,7 +367,8 @@ pub struct VaList<'a, 'f: 'a> { any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))), not(target_family = "wasm"), not(target_arch = "asmjs"), - not(windows) + not(target_os = "uefi"), + not(windows), ))] inner: &'a mut VaListImpl<'f>, @@ -375,7 +380,8 @@ pub struct VaList<'a, 'f: 'a> { all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), target_family = "wasm", target_arch = "asmjs", - windows + target_os = "uefi", + windows, ))] #[unstable( feature = "c_variadic", @@ -396,7 +402,8 @@ impl<'f> VaListImpl<'f> { any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))), not(target_family = "wasm"), not(target_arch = "asmjs"), - not(windows) + not(target_os = "uefi"), + not(windows), ))] #[unstable( feature = "c_variadic", diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index a68c6080e3a17..90e2dfd5d3d9b 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -854,6 +854,42 @@ impl AtomicBool { unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 } } + /// Logical "not" with a boolean value. + /// + /// Performs a logical "not" operation on the current value, and sets + /// the new value to the result. + /// + /// Returns the previous value. + /// + /// `fetch_not` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note:** This method is only available on platforms that support atomic + /// operations on `u8`. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_bool_fetch_not)] + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let foo = AtomicBool::new(true); + /// assert_eq!(foo.fetch_not(Ordering::SeqCst), true); + /// assert_eq!(foo.load(Ordering::SeqCst), false); + /// + /// let foo = AtomicBool::new(false); + /// assert_eq!(foo.fetch_not(Ordering::SeqCst), false); + /// assert_eq!(foo.load(Ordering::SeqCst), true); + /// ``` + #[inline] + #[unstable(feature = "atomic_bool_fetch_not", issue = "98485")] + #[cfg(target_has_atomic = "8")] + pub fn fetch_not(&self, order: Ordering) -> bool { + self.fetch_xor(true, order) + } + /// Returns a mutable pointer to the underlying [`bool`]. /// /// Doing non-atomic reads and writes on the resulting integer can be a data race. diff --git a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir index 69742d6bc3b6a..c8c45da19137f 100644 --- a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir @@ -129,6 +129,7 @@ fn array_casts() -> () { _18 = &(*_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL Retag(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _13 = (move _14, move _18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + Retag(_13); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_20); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -171,6 +172,7 @@ fn array_casts() -> () { Retag(_32); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _34 = Option::::None; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + Retag(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _28 = core::panicking::assert_failed::(move _29, move _30, move _32, move _34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL diff --git a/src/test/ui/const-generics/try_unify_ignore_lifetimes.rs b/src/test/ui/const-generics/try_unify_ignore_lifetimes.rs new file mode 100644 index 0000000000000..2ae0ae70dd977 --- /dev/null +++ b/src/test/ui/const-generics/try_unify_ignore_lifetimes.rs @@ -0,0 +1,33 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Num; + +trait NumT { + const VALUE: usize; +} + +impl NumT for Num { + const VALUE: usize = N; +} + +struct Foo<'a, N: NumT>(&'a [u32; N::VALUE]) where [(); N::VALUE]:; + +trait Bar { + type Size: NumT; + + fn bar<'a>(foo: &Foo<'a, Self::Size>) where [(); Self::Size::VALUE]: { + todo!(); + } +} + +trait Baz<'a> { + type Size: NumT; + + fn baz(foo: &Foo<'a, Self::Size>) where [(); Self::Size::VALUE]: { + todo!(); + } +} + +fn main() {} diff --git a/src/test/ui/dst/dst-index.stderr b/src/test/ui/dst/dst-index.stderr index 6bcd70cbaad45..d38af3f89c21b 100644 --- a/src/test/ui/dst/dst-index.stderr +++ b/src/test/ui/dst/dst-index.stderr @@ -1,14 +1,14 @@ -error[E0161]: cannot move a value of type str: the size of str cannot be statically determined +error[E0161]: cannot move a value of type `str` --> $DIR/dst-index.rs:31:5 | LL | S[0]; - | ^^^^ + | ^^^^ the size of `str` cannot be statically determined -error[E0161]: cannot move a value of type dyn Debug: the size of dyn Debug cannot be statically determined +error[E0161]: cannot move a value of type `dyn Debug` --> $DIR/dst-index.rs:34:5 | LL | T[0]; - | ^^^^ + | ^^^^ the size of `dyn Debug` cannot be statically determined error[E0507]: cannot move out of index of `S` --> $DIR/dst-index.rs:31:5 diff --git a/src/test/ui/error-codes/E0161.base.stderr b/src/test/ui/error-codes/E0161.base.stderr index fb578cda17e9f..15d98b657a262 100644 --- a/src/test/ui/error-codes/E0161.base.stderr +++ b/src/test/ui/error-codes/E0161.base.stderr @@ -1,8 +1,8 @@ -error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be statically determined +error[E0161]: cannot move a value of type `dyn Bar` --> $DIR/E0161.rs:16:5 | LL | x.f(); - | ^^^^^ + | ^^^^^ the size of `dyn Bar` cannot be statically determined error: aborting due to previous error diff --git a/src/test/ui/higher-rank-trait-bounds/issue-59311.stderr b/src/test/ui/higher-rank-trait-bounds/issue-59311.stderr index 15e83ab5a347d..43e609cc59efb 100644 --- a/src/test/ui/higher-rank-trait-bounds/issue-59311.stderr +++ b/src/test/ui/higher-rank-trait-bounds/issue-59311.stderr @@ -4,7 +4,7 @@ error: higher-ranked lifetime error LL | v.t(|| {}); | ^^^^^^^^^^ | - = note: could not prove [closure@$DIR/issue-59311.rs:17:9: 17:14] well-formed + = note: could not prove `[closure@$DIR/issue-59311.rs:17:9: 17:14] well-formed` error: higher-ranked lifetime error --> $DIR/issue-59311.rs:17:9 @@ -12,7 +12,7 @@ error: higher-ranked lifetime error LL | v.t(|| {}); | ^^^^^ | - = note: could not prove for<'a> &'a V: 'static + = note: could not prove `for<'a> &'a V: 'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/lifetimes/re-empty-in-error.stderr b/src/test/ui/lifetimes/re-empty-in-error.stderr index 3a5ab62ab96f6..72bb0782f4b4f 100644 --- a/src/test/ui/lifetimes/re-empty-in-error.stderr +++ b/src/test/ui/lifetimes/re-empty-in-error.stderr @@ -4,7 +4,7 @@ error: higher-ranked lifetime error LL | foo(&10); | ^^^^^^^^ | - = note: could not prove for<'b, 'r> &'b (): 'r + = note: could not prove `for<'b, 'r> &'b (): 'r` error: aborting due to previous error diff --git a/src/test/ui/mir/issue-67947.rs b/src/test/ui/mir/issue-67947.rs index 79e75e655ff1f..f73d38f80426f 100644 --- a/src/test/ui/mir/issue-67947.rs +++ b/src/test/ui/mir/issue-67947.rs @@ -1,6 +1,6 @@ struct Bug { A: [(); { *"" }.len()], - //~^ ERROR: cannot move a value of type str + //~^ ERROR: cannot move a value of type `str` //~| ERROR: cannot move out of a shared reference } diff --git a/src/test/ui/mir/issue-67947.stderr b/src/test/ui/mir/issue-67947.stderr index d526218162076..7697a411eb481 100644 --- a/src/test/ui/mir/issue-67947.stderr +++ b/src/test/ui/mir/issue-67947.stderr @@ -1,8 +1,8 @@ -error[E0161]: cannot move a value of type str: the size of str cannot be statically determined +error[E0161]: cannot move a value of type `str` --> $DIR/issue-67947.rs:2:13 | LL | A: [(); { *"" }.len()], - | ^^^^^^^ + | ^^^^^^^ the size of `str` cannot be statically determined error[E0507]: cannot move out of a shared reference --> $DIR/issue-67947.rs:2:15 diff --git a/src/test/ui/object-safety/object-safety-by-value-self-use.rs b/src/test/ui/object-safety/object-safety-by-value-self-use.rs index f903f26c0901d..8e93c538217bb 100644 --- a/src/test/ui/object-safety/object-safety-by-value-self-use.rs +++ b/src/test/ui/object-safety/object-safety-by-value-self-use.rs @@ -12,7 +12,7 @@ trait Baz { } fn use_bar(t: Box) { - t.bar() //~ ERROR cannot move a value of type dyn Bar + t.bar() //~ ERROR cannot move a value of type `dyn Bar` } fn main() { } diff --git a/src/test/ui/object-safety/object-safety-by-value-self-use.stderr b/src/test/ui/object-safety/object-safety-by-value-self-use.stderr index 7ccc0cbdd576b..94fdcdf263ae0 100644 --- a/src/test/ui/object-safety/object-safety-by-value-self-use.stderr +++ b/src/test/ui/object-safety/object-safety-by-value-self-use.stderr @@ -1,8 +1,8 @@ -error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be statically determined +error[E0161]: cannot move a value of type `dyn Bar` --> $DIR/object-safety-by-value-self-use.rs:15:5 | LL | t.bar() - | ^^^^^^^ + | ^^^^^^^ the size of `dyn Bar` cannot be statically determined error: aborting due to previous error diff --git a/src/test/ui/proc-macro/signature.stderr b/src/test/ui/proc-macro/signature.stderr index 78b0beff0da39..a6bd98ddb1977 100644 --- a/src/test/ui/proc-macro/signature.stderr +++ b/src/test/ui/proc-macro/signature.stderr @@ -5,10 +5,7 @@ LL | / pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 { LL | | LL | | loop {} LL | | } - | | ^ - | | | - | |_call the function in a closure: `|| unsafe { /* code */ }` - | required by a bound introduced by this call + | |_^ call the function in a closure: `|| unsafe { /* code */ }` | = help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for `unsafe extern "C" fn(i32, u32) -> u32 {foo}` = note: unsafe function cannot be called generically without an unsafe block diff --git a/src/test/ui/suggestions/args-instead-of-tuple.stderr b/src/test/ui/suggestions/args-instead-of-tuple.stderr index f6d158782dad2..2448a5149654d 100644 --- a/src/test/ui/suggestions/args-instead-of-tuple.stderr +++ b/src/test/ui/suggestions/args-instead-of-tuple.stderr @@ -9,7 +9,7 @@ note: tuple variant defined here | LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T), | ^^ -help: use parentheses to construct a tuple +help: wrap these arguments in parentheses to construct a tuple | LL | let _: Result<(i32, i8), ()> = Ok((1, 2)); | + + @@ -25,7 +25,7 @@ note: tuple variant defined here | LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), | ^^^^ -help: use parentheses to construct a tuple +help: wrap these arguments in parentheses to construct a tuple | LL | let _: Option<(i32, i8, &'static str)> = Some((1, 2, "hi")); | + + @@ -97,7 +97,7 @@ note: function defined here | LL | fn two_ints(_: (i32, i32)) { | ^^^^^^^^ ------------- -help: use parentheses to construct a tuple +help: wrap these arguments in parentheses to construct a tuple | LL | two_ints((1, 2)); | + + @@ -113,7 +113,7 @@ note: function defined here | LL | fn with_generic((a, b): (i32, T)) { | ^^^^^^^^^^^^ ---------------- -help: use parentheses to construct a tuple +help: wrap these arguments in parentheses to construct a tuple | LL | with_generic((3, 4)); | + + @@ -129,7 +129,7 @@ note: function defined here | LL | fn with_generic((a, b): (i32, T)) { | ^^^^^^^^^^^^ ---------------- -help: use parentheses to construct a tuple +help: wrap these arguments in parentheses to construct a tuple | LL | with_generic((a, b)); | + + diff --git a/src/test/ui/tuple/add-tuple-within-arguments.rs b/src/test/ui/tuple/add-tuple-within-arguments.rs new file mode 100644 index 0000000000000..089c703fda5c7 --- /dev/null +++ b/src/test/ui/tuple/add-tuple-within-arguments.rs @@ -0,0 +1,10 @@ +fn foo(s: &str, a: (i32, i32), s2: &str) {} + +fn bar(s: &str, a: (&str,), s2: &str) {} + +fn main() { + foo("hi", 1, 2, "hi"); + //~^ ERROR this function takes 3 arguments but 4 arguments were supplied + bar("hi", "hi", "hi"); + //~^ ERROR mismatched types +} diff --git a/src/test/ui/tuple/add-tuple-within-arguments.stderr b/src/test/ui/tuple/add-tuple-within-arguments.stderr new file mode 100644 index 0000000000000..95df96ca0dd4f --- /dev/null +++ b/src/test/ui/tuple/add-tuple-within-arguments.stderr @@ -0,0 +1,40 @@ +error[E0061]: this function takes 3 arguments but 4 arguments were supplied + --> $DIR/add-tuple-within-arguments.rs:6:5 + | +LL | foo("hi", 1, 2, "hi"); + | ^^^ + | +note: function defined here + --> $DIR/add-tuple-within-arguments.rs:1:4 + | +LL | fn foo(s: &str, a: (i32, i32), s2: &str) {} + | ^^^ ------- ------------- -------- +help: wrap these arguments in parentheses to construct a tuple + | +LL | foo("hi", (1, 2), "hi"); + | + + + +error[E0308]: mismatched types + --> $DIR/add-tuple-within-arguments.rs:8:15 + | +LL | bar("hi", "hi", "hi"); + | --- ^^^^ expected tuple, found `&str` + | | + | arguments to this function are incorrect + | + = note: expected tuple `(&str,)` + found reference `&'static str` +note: function defined here + --> $DIR/add-tuple-within-arguments.rs:3:4 + | +LL | fn bar(s: &str, a: (&str,), s2: &str) {} + | ^^^ ------- ---------- -------- +help: use a trailing comma to create a tuple with one element + | +LL | bar("hi", ("hi",), "hi"); + | + ++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0061, E0308. +For more information about an error, try `rustc --explain E0061`. diff --git a/src/test/ui/tuple/wrong_argument_ice-2.stderr b/src/test/ui/tuple/wrong_argument_ice-2.stderr index c704ae9934b1c..0c2a4c41461fc 100644 --- a/src/test/ui/tuple/wrong_argument_ice-2.stderr +++ b/src/test/ui/tuple/wrong_argument_ice-2.stderr @@ -9,7 +9,7 @@ note: function defined here | LL | fn test(t: (i32, i32)) {} | ^^^^ ------------- -help: use parentheses to construct a tuple +help: wrap these arguments in parentheses to construct a tuple | LL | test((x.qux(), x.qux())); | + + diff --git a/src/test/ui/tuple/wrong_argument_ice.stderr b/src/test/ui/tuple/wrong_argument_ice.stderr index 2b4cb669f5c7d..ec07f1e70cff6 100644 --- a/src/test/ui/tuple/wrong_argument_ice.stderr +++ b/src/test/ui/tuple/wrong_argument_ice.stderr @@ -9,7 +9,7 @@ note: associated function defined here | LL | pub fn push_back(&mut self, value: T) { | ^^^^^^^^^ -help: use parentheses to construct a tuple +help: wrap these arguments in parentheses to construct a tuple | LL | self.acc.push_back((self.current_provides, self.current_requires)); | + + diff --git a/src/test/ui/unsized/return-unsized-from-trait-method.rs b/src/test/ui/unsized/return-unsized-from-trait-method.rs index ebe6edd101014..f053f4b0af89c 100644 --- a/src/test/ui/unsized/return-unsized-from-trait-method.rs +++ b/src/test/ui/unsized/return-unsized-from-trait-method.rs @@ -7,7 +7,7 @@ trait Foo { fn foo(f: Option<&dyn Foo>) { if let Some(f) = f { let _ = f.foo(); - //~^ ERROR cannot move a value of type [u8]: the size of [u8] cannot be statically determined + //~^ ERROR cannot move a value of type `[u8]` } } diff --git a/src/test/ui/unsized/return-unsized-from-trait-method.stderr b/src/test/ui/unsized/return-unsized-from-trait-method.stderr index 4dd7cf5e02fc2..671d409937cac 100644 --- a/src/test/ui/unsized/return-unsized-from-trait-method.stderr +++ b/src/test/ui/unsized/return-unsized-from-trait-method.stderr @@ -1,8 +1,8 @@ -error[E0161]: cannot move a value of type [u8]: the size of [u8] cannot be statically determined +error[E0161]: cannot move a value of type `[u8]` --> $DIR/return-unsized-from-trait-method.rs:9:17 | LL | let _ = f.foo(); - | ^^^^^^^ + | ^^^^^^^ the size of `[u8]` cannot be statically determined error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-fn-param.stderr b/src/test/ui/unsized/unsized-fn-param.stderr index b477260543258..0221ef16b4965 100644 --- a/src/test/ui/unsized/unsized-fn-param.stderr +++ b/src/test/ui/unsized/unsized-fn-param.stderr @@ -2,7 +2,9 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t --> $DIR/unsized-fn-param.rs:11:11 | LL | foo11("bar", &"baz"); - | ^^^^^ doesn't have a size known at compile-time + | ----- ^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call | = help: the trait `Sized` is not implemented for `str` = note: required for the cast from `str` to the object type `dyn AsRef` @@ -15,7 +17,9 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t --> $DIR/unsized-fn-param.rs:13:19 | LL | foo12(&"bar", "baz"); - | ^^^^^ doesn't have a size known at compile-time + | ----- ^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call | = help: the trait `Sized` is not implemented for `str` = note: required for the cast from `str` to the object type `dyn AsRef` @@ -28,7 +32,9 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t --> $DIR/unsized-fn-param.rs:16:11 | LL | foo21("bar", &"baz"); - | ^^^^^ doesn't have a size known at compile-time + | ----- ^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call | = help: the trait `Sized` is not implemented for `str` = note: required for the cast from `str` to the object type `dyn AsRef` @@ -41,7 +47,9 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t --> $DIR/unsized-fn-param.rs:18:19 | LL | foo22(&"bar", "baz"); - | ^^^^^ doesn't have a size known at compile-time + | ----- ^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call | = help: the trait `Sized` is not implemented for `str` = note: required for the cast from `str` to the object type `dyn AsRef` diff --git a/src/test/ui/unsized/unsized3.rs b/src/test/ui/unsized/unsized3.rs index 39b6583bc4ec4..af76aca2c2958 100644 --- a/src/test/ui/unsized/unsized3.rs +++ b/src/test/ui/unsized/unsized3.rs @@ -44,6 +44,7 @@ fn f9(x1: Box>) { fn f10(x1: Box>) { f5(&(32, *x1)); //~^ ERROR the size for values of type + //~| ERROR the size for values of type } pub fn main() {} diff --git a/src/test/ui/unsized/unsized3.stderr b/src/test/ui/unsized/unsized3.stderr index 65bdc4c2ea352..d64091b15eb1f 100644 --- a/src/test/ui/unsized/unsized3.stderr +++ b/src/test/ui/unsized/unsized3.stderr @@ -100,6 +100,29 @@ LL - fn f9(x1: Box>) { LL + fn f9(x1: Box>) { | +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized3.rs:45:9 + | +LL | fn f10(x1: Box>) { + | - this type parameter needs to be `std::marker::Sized` +LL | f5(&(32, *x1)); + | -- ^^^^^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | +note: required because it appears within the type `S` + --> $DIR/unsized3.rs:28:8 + | +LL | struct S { + | ^ + = note: required because it appears within the type `({integer}, S)` + = note: tuples must have a statically known size to be initialized +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn f10(x1: Box>) { +LL + fn f10(x1: Box>) { + | + error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:45:8 | @@ -116,13 +139,21 @@ note: required because it appears within the type `S` LL | struct S { | ^ = note: required because it appears within the type `({integer}, S)` - = note: tuples must have a statically known size to be initialized +note: required by a bound in `f5` + --> $DIR/unsized3.rs:24:7 + | +LL | fn f5(x: &Y) {} + | ^ required by this bound in `f5` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f10(x1: Box>) { LL + fn f10(x1: Box>) { | +help: consider relaxing the implicit `Sized` restriction + | +LL | fn f5(x: &Y) {} + | ++++++++ -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0277`.