Skip to content

Commit b574158

Browse files
authored
Rollup merge of #133403 - compiler-errors:adjust-host-effect-preds, r=fee1-dead,lcnr
Make `adjust_fulfillment_errors` work with `HostEffectPredicate` and `const_conditions` Greatly improves the spans for reporting unsatisfied `~const` bounds :) r? project-const-traits or maybe ``@lcnr`` (if you want to deal with a diagnostics PR lmao)
2 parents ae6a7db + d5c5d58 commit b574158

36 files changed

+434
-186
lines changed

compiler/rustc_hir_typeck/src/callee.rs

+15-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_ast::util::parser::PREC_UNAMBIGUOUS;
44
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
55
use rustc_hir::def::{self, CtorKind, Namespace, Res};
66
use rustc_hir::def_id::DefId;
7-
use rustc_hir::{self as hir, LangItem};
7+
use rustc_hir::{self as hir, HirId, LangItem};
88
use rustc_hir_analysis::autoderef::Autoderef;
99
use rustc_infer::infer;
1010
use rustc_infer::traits::{self, Obligation, ObligationCause, ObligationCauseCode};
@@ -428,7 +428,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
428428
) -> Ty<'tcx> {
429429
let (fn_sig, def_id) = match *callee_ty.kind() {
430430
ty::FnDef(def_id, args) => {
431-
self.enforce_context_effects(call_expr.span, def_id, args);
431+
self.enforce_context_effects(Some(call_expr.hir_id), call_expr.span, def_id, args);
432432
let fn_sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, args);
433433

434434
// Unit testing: function items annotated with
@@ -837,6 +837,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
837837
#[tracing::instrument(level = "debug", skip(self, span))]
838838
pub(super) fn enforce_context_effects(
839839
&self,
840+
call_hir_id: Option<HirId>,
840841
span: Span,
841842
callee_did: DefId,
842843
callee_args: GenericArgsRef<'tcx>,
@@ -867,10 +868,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
867868
if self.tcx.is_conditionally_const(callee_did) {
868869
let q = self.tcx.const_conditions(callee_did);
869870
// FIXME(const_trait_impl): Use this span with a better cause code.
870-
for (cond, _) in q.instantiate(self.tcx, callee_args) {
871+
for (idx, (cond, pred_span)) in
872+
q.instantiate(self.tcx, callee_args).into_iter().enumerate()
873+
{
874+
let cause = self.cause(
875+
span,
876+
if let Some(hir_id) = call_hir_id {
877+
ObligationCauseCode::HostEffectInExpr(callee_did, pred_span, hir_id, idx)
878+
} else {
879+
ObligationCauseCode::WhereClause(callee_did, pred_span)
880+
},
881+
);
871882
self.register_predicate(Obligation::new(
872883
self.tcx,
873-
self.misc(span),
884+
cause,
874885
self.param_env,
875886
cond.to_host_effect_clause(self.tcx, host),
876887
));

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
185185
span: Span,
186186
method: MethodCallee<'tcx>,
187187
) {
188-
self.enforce_context_effects(span, method.def_id, method.args);
188+
self.enforce_context_effects(Some(hir_id), span, method.def_id, method.args);
189189
self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id)));
190190
self.write_args(hir_id, method.args);
191191
}
@@ -263,6 +263,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
263263
}
264264
Adjust::Deref(Some(overloaded_deref)) => {
265265
self.enforce_context_effects(
266+
None,
266267
expr.span,
267268
overloaded_deref.method_call(self.tcx),
268269
self.tcx.mk_args(&[a.target.into()]),

compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs

+166-64
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,56 @@ use rustc_trait_selection::traits;
1111

1212
use crate::FnCtxt;
1313

14+
enum ClauseFlavor {
15+
/// Predicate comes from `predicates_of`.
16+
Where,
17+
/// Predicate comes from `const_conditions`.
18+
Const,
19+
}
20+
1421
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1522
pub(crate) fn adjust_fulfillment_error_for_expr_obligation(
1623
&self,
1724
error: &mut traits::FulfillmentError<'tcx>,
1825
) -> bool {
19-
let ObligationCauseCode::WhereClauseInExpr(def_id, _, hir_id, idx) =
20-
*error.obligation.cause.code().peel_derives()
21-
else {
22-
return false;
26+
let (def_id, hir_id, idx, flavor) = match *error.obligation.cause.code().peel_derives() {
27+
ObligationCauseCode::WhereClauseInExpr(def_id, _, hir_id, idx) => {
28+
(def_id, hir_id, idx, ClauseFlavor::Where)
29+
}
30+
ObligationCauseCode::HostEffectInExpr(def_id, _, hir_id, idx) => {
31+
(def_id, hir_id, idx, ClauseFlavor::Const)
32+
}
33+
_ => return false,
2334
};
2435

25-
let Some(uninstantiated_pred) = self
26-
.tcx
27-
.predicates_of(def_id)
28-
.instantiate_identity(self.tcx)
29-
.predicates
30-
.into_iter()
31-
.nth(idx)
32-
else {
33-
return false;
36+
let uninstantiated_pred = match flavor {
37+
ClauseFlavor::Where => {
38+
if let Some(pred) = self
39+
.tcx
40+
.predicates_of(def_id)
41+
.instantiate_identity(self.tcx)
42+
.predicates
43+
.into_iter()
44+
.nth(idx)
45+
{
46+
pred
47+
} else {
48+
return false;
49+
}
50+
}
51+
ClauseFlavor::Const => {
52+
if let Some((pred, _)) = self
53+
.tcx
54+
.const_conditions(def_id)
55+
.instantiate_identity(self.tcx)
56+
.into_iter()
57+
.nth(idx)
58+
{
59+
pred.to_host_effect_clause(self.tcx, ty::BoundConstness::Maybe)
60+
} else {
61+
return false;
62+
}
63+
}
3464
};
3565

3666
let generics = self.tcx.generics_of(def_id);
@@ -39,6 +69,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3969
ty::ClauseKind::Trait(pred) => {
4070
(pred.trait_ref.args.to_vec(), Some(pred.self_ty().into()))
4171
}
72+
ty::ClauseKind::HostEffect(pred) => {
73+
(pred.trait_ref.args.to_vec(), Some(pred.self_ty().into()))
74+
}
4275
ty::ClauseKind::Projection(pred) => (pred.projection_term.args.to_vec(), None),
4376
ty::ClauseKind::ConstArgHasType(arg, ty) => (vec![ty.into(), arg.into()], None),
4477
ty::ClauseKind::ConstEvaluatable(e) => (vec![e.into()], None),
@@ -94,39 +127,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
94127
self.find_ambiguous_parameter_in(def_id, error.root_obligation.predicate);
95128
}
96129

97-
let (expr, qpath) = match self.tcx.hir_node(hir_id) {
98-
hir::Node::Expr(expr) => {
99-
if self.closure_span_overlaps_error(error, expr.span) {
100-
return false;
130+
match self.tcx.hir_node(hir_id) {
131+
hir::Node::Expr(expr) => self.point_at_expr_if_possible(
132+
error,
133+
def_id,
134+
expr,
135+
predicate_self_type_to_point_at,
136+
param_to_point_at,
137+
fallback_param_to_point_at,
138+
self_param_to_point_at,
139+
),
140+
141+
hir::Node::Ty(hir::Ty { kind: hir::TyKind::Path(qpath), .. }) => {
142+
for param in [
143+
predicate_self_type_to_point_at,
144+
param_to_point_at,
145+
fallback_param_to_point_at,
146+
self_param_to_point_at,
147+
]
148+
.into_iter()
149+
.flatten()
150+
{
151+
if self.point_at_path_if_possible(error, def_id, param, &qpath) {
152+
return true;
153+
}
101154
}
102-
let qpath =
103-
if let hir::ExprKind::Path(qpath) = expr.kind { Some(qpath) } else { None };
104155

105-
(Some(&expr.kind), qpath)
156+
false
106157
}
107-
hir::Node::Ty(hir::Ty { kind: hir::TyKind::Path(qpath), .. }) => (None, Some(*qpath)),
108-
_ => return false,
109-
};
110158

111-
if let Some(qpath) = qpath {
112-
// Prefer pointing at the turbofished arg that corresponds to the
113-
// self type of the failing predicate over anything else.
114-
if let Some(param) = predicate_self_type_to_point_at
115-
&& self.point_at_path_if_possible(error, def_id, param, &qpath)
116-
{
117-
return true;
118-
}
159+
_ => false,
160+
}
161+
}
119162

120-
if let hir::Node::Expr(hir::Expr {
121-
kind: hir::ExprKind::Call(callee, args),
122-
hir_id: call_hir_id,
123-
span: call_span,
124-
..
125-
}) = self.tcx.parent_hir_node(hir_id)
126-
&& callee.hir_id == hir_id
127-
{
128-
if self.closure_span_overlaps_error(error, *call_span) {
129-
return false;
163+
fn point_at_expr_if_possible(
164+
&self,
165+
error: &mut traits::FulfillmentError<'tcx>,
166+
callee_def_id: DefId,
167+
expr: &'tcx hir::Expr<'tcx>,
168+
predicate_self_type_to_point_at: Option<ty::GenericArg<'tcx>>,
169+
param_to_point_at: Option<ty::GenericArg<'tcx>>,
170+
fallback_param_to_point_at: Option<ty::GenericArg<'tcx>>,
171+
self_param_to_point_at: Option<ty::GenericArg<'tcx>>,
172+
) -> bool {
173+
if self.closure_span_overlaps_error(error, expr.span) {
174+
return false;
175+
}
176+
177+
match expr.kind {
178+
hir::ExprKind::Call(
179+
hir::Expr { kind: hir::ExprKind::Path(qpath), span: callee_span, .. },
180+
args,
181+
) => {
182+
if let Some(param) = predicate_self_type_to_point_at
183+
&& self.point_at_path_if_possible(error, callee_def_id, param, &qpath)
184+
{
185+
return true;
130186
}
131187

132188
for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
@@ -135,32 +191,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
135191
{
136192
if self.blame_specific_arg_if_possible(
137193
error,
138-
def_id,
194+
callee_def_id,
139195
param,
140-
*call_hir_id,
141-
callee.span,
196+
expr.hir_id,
197+
*callee_span,
142198
None,
143199
args,
144200
) {
145201
return true;
146202
}
147203
}
204+
205+
for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
206+
.into_iter()
207+
.flatten()
208+
{
209+
if self.point_at_path_if_possible(error, callee_def_id, param, &qpath) {
210+
return true;
211+
}
212+
}
148213
}
214+
hir::ExprKind::Path(qpath) => {
215+
// If the parent is an call, then process this as a call.
216+
//
217+
// This is because the `WhereClauseInExpr` obligations come from
218+
// the well-formedness of the *path* expression, but we care to
219+
// point at the call expression (namely, its args).
220+
if let hir::Node::Expr(
221+
call_expr @ hir::Expr { kind: hir::ExprKind::Call(callee, ..), .. },
222+
) = self.tcx.parent_hir_node(expr.hir_id)
223+
&& callee.hir_id == expr.hir_id
224+
{
225+
return self.point_at_expr_if_possible(
226+
error,
227+
callee_def_id,
228+
call_expr,
229+
predicate_self_type_to_point_at,
230+
param_to_point_at,
231+
fallback_param_to_point_at,
232+
self_param_to_point_at,
233+
);
234+
}
149235

150-
for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
151-
.into_iter()
152-
.flatten()
153-
{
154-
if self.point_at_path_if_possible(error, def_id, param, &qpath) {
236+
// Otherwise, just try to point at path components.
237+
238+
if let Some(param) = predicate_self_type_to_point_at
239+
&& self.point_at_path_if_possible(error, callee_def_id, param, &qpath)
240+
{
155241
return true;
156242
}
157-
}
158-
}
159243

160-
match expr {
161-
Some(hir::ExprKind::MethodCall(segment, receiver, args, ..)) => {
244+
for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
245+
.into_iter()
246+
.flatten()
247+
{
248+
if self.point_at_path_if_possible(error, callee_def_id, param, &qpath) {
249+
return true;
250+
}
251+
}
252+
}
253+
hir::ExprKind::MethodCall(segment, receiver, args, ..) => {
162254
if let Some(param) = predicate_self_type_to_point_at
163-
&& self.point_at_generic_if_possible(error, def_id, param, segment)
255+
&& self.point_at_generic_if_possible(error, callee_def_id, param, segment)
164256
{
165257
// HACK: This is not correct, since `predicate_self_type_to_point_at` might
166258
// not actually correspond to the receiver of the method call. But we
@@ -170,7 +262,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
170262
error.obligation.cause.map_code(|parent_code| {
171263
ObligationCauseCode::FunctionArg {
172264
arg_hir_id: receiver.hir_id,
173-
call_hir_id: hir_id,
265+
call_hir_id: expr.hir_id,
174266
parent_code,
175267
}
176268
});
@@ -183,9 +275,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
183275
{
184276
if self.blame_specific_arg_if_possible(
185277
error,
186-
def_id,
278+
callee_def_id,
187279
param,
188-
hir_id,
280+
expr.hir_id,
189281
segment.ident.span,
190282
Some(receiver),
191283
args,
@@ -194,7 +286,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
194286
}
195287
}
196288
if let Some(param_to_point_at) = param_to_point_at
197-
&& self.point_at_generic_if_possible(error, def_id, param_to_point_at, segment)
289+
&& self.point_at_generic_if_possible(
290+
error,
291+
callee_def_id,
292+
param_to_point_at,
293+
segment,
294+
)
198295
{
199296
return true;
200297
}
@@ -208,17 +305,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
208305
return true;
209306
}
210307
}
211-
Some(hir::ExprKind::Struct(qpath, fields, ..)) => {
308+
hir::ExprKind::Struct(qpath, fields, ..) => {
212309
if let Res::Def(DefKind::Struct | DefKind::Variant, variant_def_id) =
213-
self.typeck_results.borrow().qpath_res(qpath, hir_id)
310+
self.typeck_results.borrow().qpath_res(qpath, expr.hir_id)
214311
{
215312
for param in
216313
[param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
217314
.into_iter()
218315
.flatten()
219316
{
220-
let refined_expr =
221-
self.point_at_field_if_possible(def_id, param, variant_def_id, fields);
317+
let refined_expr = self.point_at_field_if_possible(
318+
callee_def_id,
319+
param,
320+
variant_def_id,
321+
fields,
322+
);
222323

223324
match refined_expr {
224325
None => {}
@@ -242,7 +343,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
242343
.into_iter()
243344
.flatten()
244345
{
245-
if self.point_at_path_if_possible(error, def_id, param, qpath) {
346+
if self.point_at_path_if_possible(error, callee_def_id, param, qpath) {
246347
return true;
247348
}
248349
}
@@ -525,7 +626,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
525626
expr: &'tcx hir::Expr<'tcx>,
526627
) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
527628
match obligation_cause_code {
528-
traits::ObligationCauseCode::WhereClauseInExpr(_, _, _, _) => {
629+
traits::ObligationCauseCode::WhereClauseInExpr(_, _, _, _)
630+
| ObligationCauseCode::HostEffectInExpr(..) => {
529631
// This is the "root"; we assume that the `expr` is already pointing here.
530632
// Therefore, we return `Ok` so that this `expr` can be refined further.
531633
Ok(expr)

0 commit comments

Comments
 (0)