diff options
| author | mejrs <59372212+mejrs@users.noreply.github.com> | 2024-11-04 12:06:19 +0100 |
|---|---|---|
| committer | mejrs <59372212+mejrs@users.noreply.github.com> | 2024-11-04 12:06:19 +0100 |
| commit | 5a48fe2c202a7aff935daf6b7cc56a12ad0ae72a (patch) | |
| tree | 17da2caf7a1759639c18789b47d92ff9355ff5cd /compiler/rustc_trait_selection/src | |
| parent | 1e4f10ba6476e48a42a79b9f846a2d9366525b9e (diff) | |
| download | rust-5a48fe2c202a7aff935daf6b7cc56a12ad0ae72a.tar.gz rust-5a48fe2c202a7aff935daf6b7cc56a12ad0ae72a.zip | |
Suggest creating unary tuples
Diffstat (limited to 'compiler/rustc_trait_selection/src')
| -rw-r--r-- | compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs | 35 |
2 files changed, 39 insertions, 0 deletions
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 6014ed555b6..74c37e1bea0 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -466,6 +466,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } self.try_to_add_help_message( + &root_obligation, &obligation, leaf_trait_predicate, &mut err, @@ -2428,6 +2429,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn try_to_add_help_message( &self, + root_obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>, trait_predicate: ty::PolyTraitPredicate<'tcx>, err: &mut Diag<'_>, @@ -2511,6 +2513,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { impl_candidates.as_slice(), span, ); + + self.suggest_tuple_wrapping(err, root_obligation, obligation); } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 8e0bdce1280..cd8dc4572c2 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4436,6 +4436,41 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } + /// If the type failed selection but the trait is implemented for `(T,)`, suggest that the user + /// creates a unary tuple + /// + /// This is a common gotcha when using libraries that emulate variadic functions with traits for tuples. + pub(super) fn suggest_tuple_wrapping( + &self, + err: &mut Diag<'_>, + root_obligation: &PredicateObligation<'tcx>, + obligation: &PredicateObligation<'tcx>, + ) { + let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = obligation.cause.code() else { + return; + }; + + let Some(root_pred) = root_obligation.predicate.as_trait_clause() else { return }; + + let trait_ref = root_pred.map_bound(|root_pred| { + root_pred + .trait_ref + .with_self_ty(self.tcx, Ty::new_tup(self.tcx, &[root_pred.trait_ref.self_ty()])) + }); + + let obligation = + Obligation::new(self.tcx, obligation.cause.clone(), obligation.param_env, trait_ref); + + if self.predicate_must_hold_modulo_regions(&obligation) { + let arg_span = self.tcx.hir().span(*arg_hir_id); + err.multipart_suggestion_verbose( + format!("use a unary tuple instead"), + vec![(arg_span.shrink_to_lo(), "(".into()), (arg_span.shrink_to_hi(), ",)".into())], + Applicability::MaybeIncorrect, + ); + } + } + pub(super) fn explain_hrtb_projection( &self, diag: &mut Diag<'_>, |
