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 00d06779e652e..6872d038fb7f0 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 @@ -1442,6 +1442,31 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.can_eq(param_env, goal.trait_ref, trait_assumption.trait_ref) } + fn can_match_host_effect( + &self, + param_env: ty::ParamEnv<'tcx>, + goal: ty::HostEffectPredicate<'tcx>, + assumption: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>, + ) -> bool { + let assumption = self.instantiate_binder_with_fresh_vars( + DUMMY_SP, + infer::BoundRegionConversionTime::HigherRankedType, + assumption, + ); + + assumption.constness.satisfies(goal.constness) + && self.can_eq(param_env, goal.trait_ref, assumption.trait_ref) + } + + fn as_host_effect_clause( + predicate: ty::Predicate<'tcx>, + ) -> Option>> { + predicate.as_clause().and_then(|clause| match clause.kind().skip_binder() { + ty::ClauseKind::HostEffect(pred) => Some(clause.kind().rebind(pred)), + _ => None, + }) + } + fn can_match_projection( &self, param_env: ty::ParamEnv<'tcx>, @@ -1484,6 +1509,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .filter_map(|implied| implied.as_trait_clause()) .any(|implied| self.can_match_trait(param_env, error, implied)) }) + } else if let Some(error) = Self::as_host_effect_clause(error.predicate) { + self.enter_forall(error, |error| { + elaborate(self.tcx, std::iter::once(cond.predicate)) + .filter_map(Self::as_host_effect_clause) + .any(|implied| self.can_match_host_effect(param_env, error, implied)) + }) } else if let Some(error) = error.predicate.as_projection_clause() { self.enter_forall(error, |error| { elaborate(self.tcx, std::iter::once(cond.predicate)) diff --git a/tests/ui/consts/issue-94675.rs b/tests/ui/consts/issue-94675.rs index f2ddc928d122e..0553b676bc3e9 100644 --- a/tests/ui/consts/issue-94675.rs +++ b/tests/ui/consts/issue-94675.rs @@ -10,7 +10,6 @@ impl<'a> Foo<'a> { const fn spam(&mut self, baz: &mut Vec) { self.bar[0] = baz.len(); //~^ ERROR: `Vec: [const] Index<_>` is not satisfied - //~| ERROR: `Vec: [const] Index` is not satisfied //~| ERROR: `Vec: [const] IndexMut` is not satisfied } } diff --git a/tests/ui/consts/issue-94675.stderr b/tests/ui/consts/issue-94675.stderr index 771f2a14c3053..ab7a76a90e02c 100644 --- a/tests/ui/consts/issue-94675.stderr +++ b/tests/ui/consts/issue-94675.stderr @@ -16,17 +16,6 @@ LL | self.bar[0] = baz.len(); note: trait `IndexMut` is implemented but not `const` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -error[E0277]: the trait bound `Vec: [const] Index` is not satisfied - --> $DIR/issue-94675.rs:11:9 - | -LL | self.bar[0] = baz.len(); - | ^^^^^^^^^^^ - | -note: trait `Index` is implemented but not `const` - --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -note: required by a bound in `std::ops::IndexMut::index_mut` - --> $SRC_DIR/core/src/ops/index.rs:LL:COL - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/call.rs b/tests/ui/traits/const-traits/call.rs index c36adc4248f03..360c08e1b7fe9 100644 --- a/tests/ui/traits/const-traits/call.rs +++ b/tests/ui/traits/const-traits/call.rs @@ -6,7 +6,6 @@ const _: () = { assert!((const || true)()); //~^ ERROR }: [const] Fn()` is not satisfied - //~| ERROR }: [const] FnMut()` is not satisfied }; fn main() {} diff --git a/tests/ui/traits/const-traits/call.stderr b/tests/ui/traits/const-traits/call.stderr index b688746e25068..8e32cab6dfcfb 100644 --- a/tests/ui/traits/const-traits/call.stderr +++ b/tests/ui/traits/const-traits/call.stderr @@ -4,15 +4,6 @@ error[E0277]: the trait bound `{closure@$DIR/call.rs:7:14: 7:22}: [const] Fn()` LL | assert!((const || true)()); | ^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `{closure@$DIR/call.rs:7:14: 7:22}: [const] FnMut()` is not satisfied - --> $DIR/call.rs:7:13 - | -LL | assert!((const || true)()); - | ^^^^^^^^^^^^^^^^^ - | -note: required by a bound in `call` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.stderr b/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.stderr index 90e87c724f54d..dab3f14161fac 100644 --- a/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.stderr +++ b/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.stderr @@ -4,15 +4,6 @@ error[E0277]: the trait bound `{closure@$DIR/const_closure-const_trait_impl-ice- LL | (const || (()).foo())(); | ^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `{closure@$DIR/const_closure-const_trait_impl-ice-113381.rs:15:6: 15:14}: [const] FnMut()` is not satisfied - --> $DIR/const_closure-const_trait_impl-ice-113381.rs:15:5 - | -LL | (const || (()).foo())(); - | ^^^^^^^^^^^^^^^^^^^^^^^ - | -note: required by a bound in `call` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.rs b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.rs index ee4ff02f4c7c2..de5bedf0ace76 100644 --- a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.rs +++ b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.rs @@ -10,7 +10,8 @@ impl Foo for () { } fn main() { + // #150052 deduplicate diagnostics for const trait supertraits + // so we only get one error here (const || { (()).foo() })(); //~^ ERROR: }: [const] Fn()` is not satisfied - //~| ERROR: }: [const] FnMut()` is not satisfied } diff --git a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr index 69d289537da1d..efbedca1c7e7f 100644 --- a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr +++ b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr @@ -1,18 +1,9 @@ -error[E0277]: the trait bound `{closure@$DIR/non-const-op-const-closure-non-const-outer.rs:13:6: 13:14}: [const] Fn()` is not satisfied - --> $DIR/non-const-op-const-closure-non-const-outer.rs:13:5 +error[E0277]: the trait bound `{closure@$DIR/non-const-op-const-closure-non-const-outer.rs:15:6: 15:14}: [const] Fn()` is not satisfied + --> $DIR/non-const-op-const-closure-non-const-outer.rs:15:5 | LL | (const || { (()).foo() })(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `{closure@$DIR/non-const-op-const-closure-non-const-outer.rs:13:6: 13:14}: [const] FnMut()` is not satisfied - --> $DIR/non-const-op-const-closure-non-const-outer.rs:13:5 - | -LL | (const || { (()).foo() })(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: required by a bound in `call` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`.