diff options
| author | Michael Goulet <michael@errs.io> | 2025-01-22 20:13:36 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2025-01-31 18:21:58 +0000 |
| commit | 304b3cfcb298c6bd6f7644ec3c78f28dd72eba1c (patch) | |
| tree | 8decd8ff3c6d7247a91d1537ae460656630b22a3 | |
| parent | d8b176f6836fa7efa0cdeb3488bceebbd5b219fb (diff) | |
| download | rust-304b3cfcb298c6bd6f7644ec3c78f28dd72eba1c.tar.gz rust-304b3cfcb298c6bd6f7644ec3c78f28dd72eba1c.zip | |
Manually walk into WF obligations in BestObligation proof tree visitor
18 files changed, 160 insertions, 100 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index acd00d9f74f..abb79493432 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -1,7 +1,7 @@ use std::ops::Deref; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_infer::infer::canonical::query_response::make_query_region_constraints; use rustc_infer::infer::canonical::{ Canonical, CanonicalExt as _, CanonicalQueryInput, CanonicalVarInfo, CanonicalVarValues, @@ -98,9 +98,10 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< param_env: ty::ParamEnv<'tcx>, arg: ty::GenericArg<'tcx>, ) -> Option<Vec<Goal<'tcx, ty::Predicate<'tcx>>>> { - crate::traits::wf::unnormalized_obligations(&self.0, param_env, arg).map(|obligations| { - obligations.into_iter().map(|obligation| obligation.into()).collect() - }) + crate::traits::wf::unnormalized_obligations(&self.0, param_env, arg, DUMMY_SP, CRATE_DEF_ID) + .map(|obligations| { + obligations.into_iter().map(|obligation| obligation.into()).collect() + }) } fn clone_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 2c55f13a0df..c64bc19835b 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -10,13 +10,13 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as _}; -use rustc_type_ir::solve::NoSolution; +use rustc_type_ir::solve::{Goal, NoSolution}; use tracing::{instrument, trace}; use crate::solve::Certainty; use crate::solve::delegate::SolverDelegate; use crate::solve::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor}; -use crate::traits::{FulfillmentError, FulfillmentErrorCode}; +use crate::traits::{FulfillmentError, FulfillmentErrorCode, wf}; pub(super) fn fulfillment_error_for_no_solution<'tcx>( infcx: &InferCtxt<'tcx>, @@ -207,14 +207,10 @@ impl<'tcx> BestObligation<'tcx> { | GoalSource::AliasBoundConstCondition | GoalSource::InstantiateHigherRanked | GoalSource::AliasWellFormed - ) && match self.consider_ambiguities { - true => { - matches!( - nested_goal.result(), - Ok(Certainty::Maybe(MaybeCause::Ambiguity)) - ) - } - false => matches!(nested_goal.result(), Err(_)), + ) && match (self.consider_ambiguities, nested_goal.result()) { + (true, Ok(Certainty::Maybe(MaybeCause::Ambiguity))) + | (false, Err(_)) => true, + _ => false, } }, ) @@ -233,6 +229,39 @@ impl<'tcx> BestObligation<'tcx> { candidates } + + /// HACK: We walk the nested obligations for a well-formed arg manually, + /// since there's nontrivial logic in `wf.rs` to set up an obligation cause. + /// Ideally we'd be able to track this better. + fn visit_well_formed_goal( + &mut self, + candidate: &inspect::InspectCandidate<'_, 'tcx>, + arg: ty::GenericArg<'tcx>, + ) -> ControlFlow<PredicateObligation<'tcx>> { + let infcx = candidate.goal().infcx(); + let param_env = candidate.goal().goal().param_env; + let body_id = self.obligation.cause.body_id; + + for obligation in wf::unnormalized_obligations(infcx, param_env, arg, self.span(), body_id) + .into_iter() + .flatten() + { + let nested_goal = candidate.instantiate_proof_tree_for_nested_goal( + GoalSource::Misc, + Goal::new(infcx.tcx, obligation.param_env, obligation.predicate), + self.span(), + ); + // Skip nested goals that aren't the *reason* for our goal's failure. + match (self.consider_ambiguities, nested_goal.result()) { + (true, Ok(Certainty::Maybe(MaybeCause::Ambiguity))) | (false, Err(_)) => {} + _ => continue, + } + + self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?; + } + + ControlFlow::Break(self.obligation.clone()) + } } impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { @@ -283,6 +312,9 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { polarity: ty::PredicatePolarity::Positive, })) } + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { + return self.visit_well_formed_goal(candidate, arg); + } _ => ChildMode::PassThrough, }; @@ -355,12 +387,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { } // Skip nested goals that aren't the *reason* for our goal's failure. - match self.consider_ambiguities { - true if matches!( - nested_goal.result(), - Ok(Certainty::Maybe(MaybeCause::Ambiguity)) - ) => {} - false if matches!(nested_goal.result(), Err(_)) => {} + match (self.consider_ambiguities, nested_goal.result()) { + (true, Ok(Certainty::Maybe(MaybeCause::Ambiguity))) | (false, Err(_)) => {} _ => continue, } diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index e735020a63e..9ba48cd588f 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -194,47 +194,57 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { let goals = instantiated_goals .into_iter() - .map(|(source, goal)| match goal.predicate.kind().no_bound_vars() { - Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => { - let unconstrained_term = match term.unpack() { - ty::TermKind::Ty(_) => infcx.next_ty_var(span).into(), - ty::TermKind::Const(_) => infcx.next_const_var(span).into(), - }; - let goal = - goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term }); - // We have to use a `probe` here as evaluating a `NormalizesTo` can constrain the - // expected term. This means that candidates which only fail due to nested goals - // and which normalize to a different term then the final result could ICE: when - // building their proof tree, the expected term was unconstrained, but when - // instantiating the candidate it is already constrained to the result of another - // candidate. - let proof_tree = infcx - .probe(|_| infcx.evaluate_root_goal_raw(goal, GenerateProofTree::Yes).1); - InspectGoal::new( - infcx, - self.goal.depth + 1, - proof_tree.unwrap(), - Some(NormalizesToTermHack { term, unconstrained_term }), - source, - ) - } - _ => { - // We're using a probe here as evaluating a goal could constrain - // inference variables by choosing one candidate. If we then recurse - // into another candidate who ends up with different inference - // constraints, we get an ICE if we already applied the constraints - // from the chosen candidate. - let proof_tree = infcx - .probe(|_| infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1) - .unwrap(); - InspectGoal::new(infcx, self.goal.depth + 1, proof_tree, None, source) - } - }) + .map(|(source, goal)| self.instantiate_proof_tree_for_nested_goal(source, goal, span)) .collect(); (goals, opt_impl_args) } + pub fn instantiate_proof_tree_for_nested_goal( + &self, + source: GoalSource, + goal: Goal<'tcx, ty::Predicate<'tcx>>, + span: Span, + ) -> InspectGoal<'a, 'tcx> { + let infcx = self.goal.infcx; + match goal.predicate.kind().no_bound_vars() { + Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => { + let unconstrained_term = match term.unpack() { + ty::TermKind::Ty(_) => infcx.next_ty_var(span).into(), + ty::TermKind::Const(_) => infcx.next_const_var(span).into(), + }; + let goal = + goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term }); + // We have to use a `probe` here as evaluating a `NormalizesTo` can constrain the + // expected term. This means that candidates which only fail due to nested goals + // and which normalize to a different term then the final result could ICE: when + // building their proof tree, the expected term was unconstrained, but when + // instantiating the candidate it is already constrained to the result of another + // candidate. + let proof_tree = + infcx.probe(|_| infcx.evaluate_root_goal_raw(goal, GenerateProofTree::Yes).1); + InspectGoal::new( + infcx, + self.goal.depth + 1, + proof_tree.unwrap(), + Some(NormalizesToTermHack { term, unconstrained_term }), + source, + ) + } + _ => { + // We're using a probe here as evaluating a goal could constrain + // inference variables by choosing one candidate. If we then recurse + // into another candidate who ends up with different inference + // constraints, we get an ICE if we already applied the constraints + // from the chosen candidate. + let proof_tree = infcx + .probe(|_| infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1) + .unwrap(); + InspectGoal::new(infcx, self.goal.depth + 1, proof_tree, None, source) + } + } + } + /// Visit all nested goals of this candidate, rolling back /// all inference constraints. pub fn visit_nested_in_probe<V: ProofTreeVisitor<'tcx>>(&self, visitor: &mut V) -> V::Result { diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index 1339739ce7f..ec0b7903396 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -5,8 +5,8 @@ use rustc_infer::traits::query::type_op::ImpliedOutlivesBounds; use rustc_middle::infer::canonical::CanonicalQueryResponse; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFolder, TypeVisitableExt}; -use rustc_span::Span; use rustc_span::def_id::CRATE_DEF_ID; +use rustc_span::{DUMMY_SP, Span}; use rustc_type_ir::outlives::{Component, push_outlives_components}; use smallvec::{SmallVec, smallvec}; use tracing::debug; @@ -92,7 +92,9 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( // From the full set of obligations, just filter down to the region relationships. for obligation in - wf::unnormalized_obligations(ocx.infcx, param_env, arg).into_iter().flatten() + wf::unnormalized_obligations(ocx.infcx, param_env, arg, DUMMY_SP, CRATE_DEF_ID) + .into_iter() + .flatten() { assert!(!obligation.has_escaping_bound_vars()); let Some(pred) = obligation.predicate.kind().no_bound_vars() else { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 20b675bcb76..37d49cc2f55 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -8,8 +8,8 @@ use rustc_middle::ty::{ self, GenericArg, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; -use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; -use rustc_span::{DUMMY_SP, Span}; +use rustc_span::Span; +use rustc_span::def_id::{DefId, LocalDefId}; use tracing::{debug, instrument, trace}; use crate::infer::InferCtxt; @@ -89,6 +89,8 @@ pub fn unnormalized_obligations<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, arg: GenericArg<'tcx>, + span: Span, + body_id: LocalDefId, ) -> Option<PredicateObligations<'tcx>> { debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg)); @@ -106,8 +108,8 @@ pub fn unnormalized_obligations<'tcx>( let mut wf = WfPredicates { infcx, param_env, - body_id: CRATE_DEF_ID, - span: DUMMY_SP, + body_id, + span, out: PredicateObligations::new(), recursion_depth: 0, item: None, diff --git a/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr b/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr index bf53089675d..81ace4ebb6d 100644 --- a/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr +++ b/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr @@ -5,6 +5,8 @@ LL | fn main() -> Foo::Bar::<Vec<[u32]>> {} | ^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u32]` +note: required by an implicit `Sized` bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-88119.stderr b/tests/ui/const-generics/issues/issue-88119.stderr index f219c90849a..c497f1b6d0b 100644 --- a/tests/ui/const-generics/issues/issue-88119.stderr +++ b/tests/ui/const-generics/issues/issue-88119.stderr @@ -6,35 +6,29 @@ LL | #![feature(const_trait_impl, generic_const_exprs)] | = help: remove one of these features -error[E0284]: type annotations needed: cannot normalize `<&T as ConstName>::{constant#0}` - --> $DIR/issue-88119.rs:19:49 +error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::<T>()` can be evaluated` + --> $DIR/issue-88119.rs:21:5 | -LL | impl<T: ?Sized + ConstName> const ConstName for &T - | ^^ cannot normalize `<&T as ConstName>::{constant#0}` +LL | [(); name_len::<T>()]:, + | ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::<T>()` can be evaluated` | -note: required for `&T` to implement `~const ConstName` - --> $DIR/issue-88119.rs:19:35 +note: required by a bound in `<&T as ConstName>` + --> $DIR/issue-88119.rs:21:10 | -LL | impl<T: ?Sized + ConstName> const ConstName for &T - | ^^^^^^^^^ ^^ -LL | where LL | [(); name_len::<T>()]:, - | --------------------- unsatisfied trait bound introduced here + | ^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>` -error[E0284]: type annotations needed: cannot normalize `<&mut T as ConstName>::{constant#0}` - --> $DIR/issue-88119.rs:26:49 +error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::<T>()` can be evaluated` + --> $DIR/issue-88119.rs:28:5 | -LL | impl<T: ?Sized + ConstName> const ConstName for &mut T - | ^^^^^^ cannot normalize `<&mut T as ConstName>::{constant#0}` +LL | [(); name_len::<T>()]:, + | ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::<T>()` can be evaluated` | -note: required for `&mut T` to implement `~const ConstName` - --> $DIR/issue-88119.rs:26:35 +note: required by a bound in `<&mut T as ConstName>` + --> $DIR/issue-88119.rs:28:10 | -LL | impl<T: ?Sized + ConstName> const ConstName for &mut T - | ^^^^^^^^^ ^^^^^^ -LL | where LL | [(); name_len::<T>()]:, - | --------------------- unsatisfied trait bound introduced here + | ^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>` error: aborting due to 3 previous errors diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr index 1b76669ccb0..4f685c508c7 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr @@ -16,23 +16,13 @@ LL | where LL | T: AsExpression<Self::SqlType>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check` -error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied - --> $DIR/as_expression.rs:55:15 - | -LL | SelectInt.check("bar"); - | ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str` - | - = help: the trait `AsExpression<Integer>` is not implemented for `&str` - but trait `AsExpression<Text>` is implemented for it - = help: for that trait implementation, expected `Text`, found `Integer` - error[E0271]: type mismatch resolving `<SelectInt as Expression>::SqlType == Text` --> $DIR/as_expression.rs:55:5 | LL | SelectInt.check("bar"); | ^^^^^^^^^^^^^^^^^^^^^^ expected `Text`, found `Integer` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0271, E0277. For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs index 583b3c4675a..48c1ed2b02d 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs @@ -53,7 +53,7 @@ impl<T> Foo for T where T: Expression {} fn main() { SelectInt.check("bar"); - //~^ ERROR the trait bound `&str: AsExpression<Integer>` is not satisfied - //[next]~| the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied + //[current]~^ ERROR the trait bound `&str: AsExpression<Integer>` is not satisfied + //[next]~^^ the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied //[next]~| type mismatch } diff --git a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr index 1cfc2a6d944..a95670ced86 100644 --- a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr +++ b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr @@ -18,6 +18,11 @@ help: this trait has no implementations, consider adding one | LL | trait Foo {} | ^^^^^^^^^ +note: required by a bound in `A` + --> $DIR/alias-bounds-when-not-wf.rs:8:11 + | +LL | type A<T: Foo> = T; + | ^^^ required by this bound in `A` error[E0277]: the trait bound `usize: Foo` is not satisfied --> $DIR/alias-bounds-when-not-wf.rs:16:10 diff --git a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr index 377dfc8b529..425f2d59222 100644 --- a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr +++ b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr @@ -1,8 +1,8 @@ -error[E0284]: type annotations needed: cannot normalize `X::{constant#0}` +error[E0284]: type annotations needed: cannot satisfy `the constant `{ || {} }` can be evaluated` --> $DIR/const-region-infer-to-static-in-binder.rs:4:10 | LL | struct X<const FN: fn() = { || {} }>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `X::{constant#0}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `{ || {} }` can be evaluated` error: using function pointers as const generic parameters is forbidden --> $DIR/const-region-infer-to-static-in-binder.rs:4:20 diff --git a/tests/ui/traits/next-solver/specialization-transmute.stderr b/tests/ui/traits/next-solver/specialization-transmute.stderr index b96bfab927d..2d0c503bc95 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.stderr +++ b/tests/ui/traits/next-solver/specialization-transmute.stderr @@ -10,11 +10,11 @@ LL | #![feature(specialization)] error: cannot normalize `<T as Default>::Id: '_` -error[E0284]: type annotations needed: cannot normalize `<T as Default>::Id` +error[E0282]: type annotations needed --> $DIR/specialization-transmute.rs:15:23 | LL | fn intu(&self) -> &Self::Id { - | ^^^^^^^^^ cannot normalize `<T as Default>::Id` + | ^^^^^^^^^ cannot infer type for reference `&<T as Default>::Id` error[E0284]: type annotations needed: cannot satisfy `<T as Default>::Id normalizes-to T` --> $DIR/specialization-transmute.rs:17:9 @@ -36,4 +36,5 @@ LL | fn transmute<T: Default<Id = U>, U: Copy>(t: T) -> U { error: aborting due to 4 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0284`. +Some errors have detailed explanations: E0282, E0284. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.next.stderr b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.next.stderr index 1bcc0dbaf67..92ad83c3300 100644 --- a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.next.stderr +++ b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.next.stderr @@ -9,6 +9,8 @@ error: the constant `N` is not of type `usize` | LL | fn func<const N: u32>() -> [(); N]; | ^^^^^^^ expected `usize`, found `u32` + | + = note: the length of array `[(); N]` must be type `usize` error: aborting due to 2 previous errors diff --git a/tests/ui/union/union-derive-eq.next.stderr b/tests/ui/union/union-derive-eq.next.stderr index 3952b1f1284..151ceebe1ba 100644 --- a/tests/ui/union/union-derive-eq.next.stderr +++ b/tests/ui/union/union-derive-eq.next.stderr @@ -7,6 +7,8 @@ LL | union U2 { LL | a: PartialEqNotEq, | ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq` | +note: required by a bound in `AssertParamIsEq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `PartialEqNotEq` with `#[derive(Eq)]` | diff --git a/tests/ui/wf/wf-normalization-sized.next.stderr b/tests/ui/wf/wf-normalization-sized.next.stderr index 1e898fb7b78..83b56bb6b19 100644 --- a/tests/ui/wf/wf-normalization-sized.next.stderr +++ b/tests/ui/wf/wf-normalization-sized.next.stderr @@ -5,6 +5,7 @@ LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = (); | ^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[[[[[u8]]]]]` + = note: slice and array elements must have `Sized` type error[E0277]: the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time --> $DIR/wf-normalization-sized.rs:19:11 @@ -13,6 +14,7 @@ LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = (); | ^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[[[[[u8]]]]]` + = note: slice and array elements must have `Sized` type = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the size for values of type `str` cannot be known at compilation time @@ -22,6 +24,8 @@ LL | const _: <Vec<str> as WellUnformed>::RequestNormalize = (); | ^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` +note: required by an implicit `Sized` bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/wf-normalization-sized.rs:22:11 @@ -30,6 +34,8 @@ LL | const _: <Vec<str> as WellUnformed>::RequestNormalize = (); | ^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` +note: required by an implicit `Sized` bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors diff --git a/tests/ui/wf/wf-trait-fn-arg.next.stderr b/tests/ui/wf/wf-trait-fn-arg.next.stderr index c55dc5c8a12..d5dd36fad6d 100644 --- a/tests/ui/wf/wf-trait-fn-arg.next.stderr +++ b/tests/ui/wf/wf-trait-fn-arg.next.stderr @@ -4,6 +4,11 @@ error[E0277]: the trait bound `Self: Eq` is not satisfied LL | fn bar(&self, x: &Bar<Self>); | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` | +note: required by a bound in `Bar` + --> $DIR/wf-trait-fn-arg.rs:11:15 + | +LL | struct Bar<T: Eq + ?Sized> { + | ^^ required by this bound in `Bar` help: consider further restricting `Self` | LL | fn bar(&self, x: &Bar<Self>) where Self: Eq; diff --git a/tests/ui/wf/wf-trait-fn-ret.next.stderr b/tests/ui/wf/wf-trait-fn-ret.next.stderr index b3dca17672d..0ad786c2fd5 100644 --- a/tests/ui/wf/wf-trait-fn-ret.next.stderr +++ b/tests/ui/wf/wf-trait-fn-ret.next.stderr @@ -4,6 +4,11 @@ error[E0277]: the trait bound `Self: Eq` is not satisfied LL | fn bar(&self) -> &Bar<Self>; | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` | +note: required by a bound in `Bar` + --> $DIR/wf-trait-fn-ret.rs:10:15 + | +LL | struct Bar<T: Eq + ?Sized> { + | ^^ required by this bound in `Bar` help: consider further restricting `Self` | LL | fn bar(&self) -> &Bar<Self> where Self: Eq; diff --git a/tests/ui/wf/wf-trait-fn-where-clause.next.stderr b/tests/ui/wf/wf-trait-fn-where-clause.next.stderr index 8c8a5fa3e70..db5454d0f3c 100644 --- a/tests/ui/wf/wf-trait-fn-where-clause.next.stderr +++ b/tests/ui/wf/wf-trait-fn-where-clause.next.stderr @@ -4,6 +4,11 @@ error[E0277]: the trait bound `Self: Eq` is not satisfied LL | Bar<Self>: Copy; | ^^^^ the trait `Eq` is not implemented for `Self` | +note: required by a bound in `Bar` + --> $DIR/wf-trait-fn-where-clause.rs:10:15 + | +LL | struct Bar<T: Eq + ?Sized> { + | ^^ required by this bound in `Bar` help: consider further restricting `Self` | LL | Bar<Self>: Copy, Self: Eq; |
