about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2025-01-06 20:59:33 +0100
committerGitHub <noreply@github.com>2025-01-06 20:59:33 +0100
commit68791efa2961780361eba4d98cdf75608c2adacf (patch)
tree5a1a2d1a6ed8c50275a774f0c42890e0567f5879 /compiler
parent44c6e83b492dcfa0d8cd763b2b18fcd1be9f6fb4 (diff)
parent62d6ee3a26a9fbc2f0d99939bffd387452793856 (diff)
downloadrust-68791efa2961780361eba4d98cdf75608c2adacf.tar.gz
rust-68791efa2961780361eba4d98cdf75608c2adacf.zip
Rollup merge of #134951 - compiler-errors:double-trait-err-msg, r=davidtwco
Suppress host effect predicates if underlying trait doesn't hold

Don't report two errors for when the (`HostEffectPredicate`) `T: const Trait` isn't implemented because (`TraitPredicate`) `T: Trait` doesn't even hold.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs57
1 files changed, 38 insertions, 19 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 f9a30408326..14639039ae9 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
@@ -114,7 +114,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         //
                         // We rely on a few heuristics to identify cases where this root
                         // obligation is more important than the leaf obligation:
-                        let (main_trait_predicate, o) = if let ty::PredicateKind::Clause(
+                        let (main_trait_predicate, main_obligation) = if let ty::PredicateKind::Clause(
                             ty::ClauseKind::Trait(root_pred)
                         ) = root_obligation.predicate.kind().skip_binder()
                             && !leaf_trait_predicate.self_ty().skip_binder().has_escaping_bound_vars()
@@ -199,7 +199,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             notes,
                             parent_label,
                             append_const_msg,
-                        } = self.on_unimplemented_note(main_trait_predicate, o, &mut long_ty_file);
+                        } = self.on_unimplemented_note(main_trait_predicate, main_obligation, &mut long_ty_file);
 
                         let have_alt_message = message.is_some() || label.is_some();
                         let is_try_conversion = self.is_try_conversion(span, main_trait_ref.def_id());
@@ -538,23 +538,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     }
 
                     ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => {
-                        // FIXME(const_trait_impl): We should recompute the predicate with `~const`
-                        // if it's `const`, and if it holds, explain that this bound only
-                        // *conditionally* holds. If that fails, we should also do selection
-                        // to drill this down to an impl or built-in source, so we can
-                        // point at it and explain that while the trait *is* implemented,
-                        // that implementation is not const.
-                        let err_msg = self.get_standard_error_message(
-                            bound_predicate.rebind(ty::TraitPredicate {
-                                trait_ref: predicate.trait_ref,
-                                polarity: ty::PredicatePolarity::Positive,
-                            }),
-                            None,
-                            Some(predicate.constness),
-                            None,
-                            String::new(),
-                        );
-                        struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg)
+                        self.report_host_effect_error(bound_predicate.rebind(predicate), obligation.param_env, span)
                     }
 
                     ty::PredicateKind::Subtype(predicate) => {
@@ -763,6 +747,41 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         applied_do_not_recommend
     }
 
+    fn report_host_effect_error(
+        &self,
+        predicate: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
+        param_env: ty::ParamEnv<'tcx>,
+        span: Span,
+    ) -> Diag<'a> {
+        // FIXME(const_trait_impl): We should recompute the predicate with `~const`
+        // if it's `const`, and if it holds, explain that this bound only
+        // *conditionally* holds. If that fails, we should also do selection
+        // to drill this down to an impl or built-in source, so we can
+        // point at it and explain that while the trait *is* implemented,
+        // that implementation is not const.
+        let trait_ref = predicate.map_bound(|predicate| ty::TraitPredicate {
+            trait_ref: predicate.trait_ref,
+            polarity: ty::PredicatePolarity::Positive,
+        });
+        let err_msg = self.get_standard_error_message(
+            trait_ref,
+            None,
+            Some(predicate.constness()),
+            None,
+            String::new(),
+        );
+        let mut diag = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg);
+        if !self.predicate_may_hold(&Obligation::new(
+            self.tcx,
+            ObligationCause::dummy(),
+            param_env,
+            trait_ref,
+        )) {
+            diag.downgrade_to_delayed_bug();
+        }
+        diag
+    }
+
     fn emit_specialized_closure_kind_error(
         &self,
         obligation: &PredicateObligation<'tcx>,