enable do_not_recommend attr for method call errors in current solver#158882
Conversation
| if let ObligationCauseCode::ImplDerived(c) = &code { | ||
| if self.tcx.do_not_recommend_impl(c.impl_or_alias_def_id) { | ||
| if let Some(parent) = parent_pred.take() { |
There was a problem hiding this comment.
i'd chain this let
| loop { | ||
| if let ObligationCauseCode::ImplDerived(c) = &code { |
There was a problem hiding this comment.
i think it should be possible to use while let instead of loop { if let }
There was a problem hiding this comment.
Hmm... the method you're editing, report_no_match_method_error, is called by both solvers, not just the current solver. The difference seems to be that the caller, check_expr_method_call, calls self.lookup_method, and Err is returned, but the contents of the Err are different depending on the solver:
the old solver returns a bunch of stuff:
NoMatch(NoMatchData { static_candidates: [], unsatisfied_predicates: [(Binder { value: TraitPredicate(<u8 as DoNotMentionThis>, polarity:Positive), bound_vars: [] }, Some(Binder { value: TraitPredicate(<LocalType<u8> as std::clone::Clone>, polarity:Positive), bound_vars: [] }), Some(ObligationCause { span: tests/ui/diagnostic_namespace/do_not_recommend/method_call.rs:23:19: 23:24 (#0), body_id: DefId(0:8 ~ method_call[38bf]::main), code: ImplDerived(ImplDerivedCause { derived: DerivedCause { parent_trait_pred: Binder { value: TraitPredicate(<_ as std::clone::Clone>, polarity:Positive), bound_vars: [] }, parent_code: Misc }, impl_or_alias_def_id: DefId(0:9 ~ method_call[38bf]::{impl#0}), impl_def_predicate_index: Some(1), span: tests/ui/diagnostic_namespace/do_not_recommend/method_call.rs:11:9: 11:25 (#0) }) }))], out_of_scope_traits: [], similar_candidate: None, mode: MethodCall })
the new solver does not:
NoMatch(NoMatchData { static_candidates: [], unsatisfied_predicates: [], out_of_scope_traits: [], similar_candidate: None, mode: MethodCall })
figuring out where exactly the difference is is a bit annoying due to lack of tracing output related to errors - my guess is that the new solver is calling TypeErrCtxt::apply_do_not_recommend (or some other caller of TyCtxt::do_not_recommend_impl) somewhere and the old solver probably should too, but that's just a guess.
IMO, either both solvers should return #[diagnostic::do_not_recommend] things in unsatisfied_predicates, or neither should, and the error output should be the same across both solvers. I don't quite understand the context here though, so feel free to let me know if I'm missing something!
|
Reminder, once the PR becomes ready for a review, use |
It appears the compiler handles UFCS and method call syntax differently, in the latter It might be related to (see the revision output) that the next solver talkes about I'm not sure what I can or should change about that, that seems like a much more involved change. @rustbot ready |
Apologies for not being more specific! When I said
it was indeed some other caller of rust/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs Lines 439 to 448 in 5e91de6 We want to replicate that logic in the old solver: filter out impls that have rust/compiler/rustc_hir_typeck/src/method/probe.rs Lines 2086 to 2097 in 5e91de6 On a tangent, the only other caller of rust/compiler/rustc_hir_typeck/src/method/probe.rs Lines 1918 to 1925 in 5e91de6 As an example WIP, changing your PR to be this functional change instead: diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index dfb1dae10ae..f0798f484e3 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -1887,7 +1887,14 @@ fn select_trait_candidate(
) -> traits::SelectionResult<'tcx, traits::Selection<'tcx>> {
let obligation =
traits::Obligation::new(self.tcx, self.misc(self.span), self.param_env, trait_ref);
- traits::SelectionContext::new(self).select(&obligation)
+ let candidate = traits::SelectionContext::new(self).select(&obligation);
+ if let Ok(Some(traits::ImplSource::UserDefined(ref impl_source_user_defined_data))) =
+ candidate
+ && self.infcx.tcx.do_not_recommend_impl(impl_source_user_defined_data.impl_def_id)
+ {
+ return Err(traits::SelectionError::Unimplemented);
+ }
+ candidate
}
/// Used for ambiguous method call error reporting. Uses probing that throws away the result internally,makes your test pass (if you stop branching the output by changing the old solver output to be the same as the new solver output). however,
This is all predicated on that we're making the old solver behave like the new solver. If we instead want to make the new solver behave like the old solver, we probably want to change something about that first line of code I linked. I haven't investigated that plan of action though, no idea what that might entail :3 I'm so sorry I'm being so nitpicky! this got way more involved than I expected, haha 💔 @rustbot author |
|
actually wait, looking into the original issue, we might want to continue calling since the original issue does have a nested obligation ( but yeah, probably something to do with this area of code, rather than after the two solvers codepaths have already merged |
You cannot |
How so? There are two callers:
that seems like "only used in diagnostics" to me. Where do we disagree? My guess on where the misunderstanding is, is that the function may be called when compiling code that does not error, but my hypothesis is that the result is only ever used in error reporting. So a delayed_bug will explode, because the function is called, but it's still a diagnostics-only function because the result is unused. Let me know if you discover otherwise, if the result is actually used in compilation results. |
|
Ah, I think you're right. Still, that makes me somewhat uneasy. |
|
fair! four options I see:
|
0bfd5c4 to
77bce37
Compare
|
I've just renamed the method, I think that's the best option other than some big refactoring that I don't have the stomach for rn. @rustbot ready |
|
@bors r+ rollup |
… r=khyperia enable `do_not_recommend` attr for method call errors in current solver This should help with rust-lang#146381 (comment) The logic is mostly copied from the `apply_do_not_recommend` function. r? @khyperia :3
Rollup of 11 pull requests Successful merges: - #159210 (`rust-analyzer` subtree update) - #158655 (Fix coroutine MIR saved local remapping) - #159205 (bootstrap: Replace `ShouldRun::crates` with `crate_or_deps_filtered`) - #159208 (Fix `attr_on_non_tail_expr` typo) - #157524 (Fix relative paths in private import suggestions) - #158325 (Document NonNull layout guarantees) - #158882 (enable `do_not_recommend` attr for method call errors in current solver) - #158982 (Pretty-print MIR user types too.) - #159069 (Add codegen test for constant returns after local use) - #159163 (rustc_target: Add acquire-release to implied features of v8) - #159201 (borrowck: Represent 'best blame constraint' as index into `Vec<OutlivesConstraint>`)
Rollup of 11 pull requests Successful merges: - #159210 (`rust-analyzer` subtree update) - #158655 (Fix coroutine MIR saved local remapping) - #159205 (bootstrap: Replace `ShouldRun::crates` with `crate_or_deps_filtered`) - #159208 (Fix `attr_on_non_tail_expr` typo) - #157524 (Fix relative paths in private import suggestions) - #158325 (Document NonNull layout guarantees) - #158882 (enable `do_not_recommend` attr for method call errors in current solver) - #158982 (Pretty-print MIR user types too.) - #159069 (Add codegen test for constant returns after local use) - #159163 (rustc_target: Add acquire-release to implied features of v8) - #159201 (borrowck: Represent 'best blame constraint' as index into `Vec<OutlivesConstraint>`)
Rollup merge of #158882 - mejrs:do_not_recommend_old_solver, r=khyperia enable `do_not_recommend` attr for method call errors in current solver This should help with #146381 (comment) The logic is mostly copied from the `apply_do_not_recommend` function. r? @khyperia :3
This should help with #146381 (comment)
The logic is mostly copied from the
apply_do_not_recommendfunction.r? @khyperia :3