Skip to content

Commit 30afeb0

Browse files
Adjust HostEffect error spans correctly to point at args
1 parent 17c6efa commit 30afeb0

36 files changed

+361
-136
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

+93-14
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),
@@ -95,6 +128,51 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
95128
}
96129

97130
match self.tcx.hir_node(hir_id) {
131+
hir::Node::Expr(&hir::Expr {
132+
kind:
133+
hir::ExprKind::Call(
134+
hir::Expr { kind: hir::ExprKind::Path(qpath), span: callee_span, .. },
135+
args,
136+
),
137+
span,
138+
..
139+
}) => {
140+
if self.closure_span_overlaps_error(error, span) {
141+
return false;
142+
}
143+
144+
if let Some(param) = predicate_self_type_to_point_at
145+
&& self.point_at_path_if_possible(error, def_id, param, &qpath)
146+
{
147+
return true;
148+
}
149+
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.blame_specific_arg_if_possible(
155+
error,
156+
def_id,
157+
param,
158+
hir_id,
159+
*callee_span,
160+
None,
161+
args,
162+
) {
163+
return true;
164+
}
165+
}
166+
167+
for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
168+
.into_iter()
169+
.flatten()
170+
{
171+
if self.point_at_path_if_possible(error, def_id, param, &qpath) {
172+
return true;
173+
}
174+
}
175+
}
98176
hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::Path(qpath), span, .. }) => {
99177
if self.closure_span_overlaps_error(error, span) {
100178
return false;
@@ -544,7 +622,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
544622
expr: &'tcx hir::Expr<'tcx>,
545623
) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
546624
match obligation_cause_code {
547-
traits::ObligationCauseCode::WhereClauseInExpr(_, _, _, _) => {
625+
traits::ObligationCauseCode::WhereClauseInExpr(_, _, _, _)
626+
| ObligationCauseCode::HostEffectInExpr(..) => {
548627
// This is the "root"; we assume that the `expr` is already pointing here.
549628
// Therefore, we return `Ok` so that this `expr` can be refined further.
550629
Ok(expr)

compiler/rustc_hir_typeck/src/place_op.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
296296
);
297297
};
298298
*deref = OverloadedDeref { mutbl, span: deref.span };
299-
self.enforce_context_effects(expr.span, method.def_id, method.args);
299+
self.enforce_context_effects(None, expr.span, method.def_id, method.args);
300300
// If this is a union field, also throw an error for `DerefMut` of `ManuallyDrop` (see RFC 2514).
301301
// This helps avoid accidental drops.
302302
if inside_union

compiler/rustc_middle/src/traits/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,10 @@ pub enum ObligationCauseCode<'tcx> {
204204
/// list of the item.
205205
WhereClauseInExpr(DefId, Span, HirId, usize),
206206

207+
/// Like `WhereClauseinExpr`, but indexes into the `const_conditions`
208+
/// rather than the `predicates_of`.
209+
HostEffectInExpr(DefId, Span, HirId, usize),
210+
207211
/// A type like `&'a T` is WF only if `T: 'a`.
208212
ReferenceOutlivesReferent(Ty<'tcx>),
209213

compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -2803,6 +2803,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
28032803
}
28042804
ObligationCauseCode::WhereClause(item_def_id, span)
28052805
| ObligationCauseCode::WhereClauseInExpr(item_def_id, span, ..)
2806+
| ObligationCauseCode::HostEffectInExpr(item_def_id, span, ..)
28062807
if !span.is_dummy() =>
28072808
{
28082809
if let ObligationCauseCode::WhereClauseInExpr(_, _, hir_id, pos) = &cause_code {
@@ -2966,7 +2967,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
29662967
err.help(help);
29672968
}
29682969
}
2969-
ObligationCauseCode::WhereClause(..) | ObligationCauseCode::WhereClauseInExpr(..) => {
2970+
ObligationCauseCode::WhereClause(..)
2971+
| ObligationCauseCode::WhereClauseInExpr(..)
2972+
| ObligationCauseCode::HostEffectInExpr(..) => {
29702973
// We hold the `DefId` of the item introducing the obligation, but displaying it
29712974
// doesn't add user usable information. It always point at an associated item.
29722975
}

tests/ui/consts/const-block-const-bound.stderr

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
error[E0277]: the trait bound `UnconstDrop: const Destruct` is not satisfied
2-
--> $DIR/const-block-const-bound.rs:18:9
2+
--> $DIR/const-block-const-bound.rs:18:11
33
|
44
LL | f(UnconstDrop);
5-
| ^^^^^^^^^^^^^^
5+
| - ^^^^^^^^^^^
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
note: required by a bound in `f`
10+
--> $DIR/const-block-const-bound.rs:8:15
11+
|
12+
LL | const fn f<T: ~const Destruct>(x: T) {}
13+
| ^^^^^^ required by this bound in `f`
614

715
error: aborting due to 1 previous error
816

tests/ui/consts/constifconst-call-in-const-position.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ error[E0277]: the trait bound `T: const Tr` is not satisfied
22
--> $DIR/constifconst-call-in-const-position.rs:17:38
33
|
44
LL | const fn foo<T: ~const Tr>() -> [u8; T::a()] {
5-
| ^^^^^^
5+
| ^
66

77
error[E0277]: the trait bound `T: const Tr` is not satisfied
88
--> $DIR/constifconst-call-in-const-position.rs:18:9
99
|
1010
LL | [0; T::a()]
11-
| ^^^^^^
11+
| ^
1212

1313
error: aborting due to 2 previous errors
1414

tests/ui/consts/fn_trait_refs.stderr

+65-10
Original file line numberDiff line numberDiff line change
@@ -121,34 +121,89 @@ LL | T: ~const FnMut<()> + ~const Destruct,
121121
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
122122

123123
error[E0277]: the trait bound `fn() -> i32 {one}: const Destruct` is not satisfied
124-
--> $DIR/fn_trait_refs.rs:70:24
124+
--> $DIR/fn_trait_refs.rs:70:32
125125
|
126126
LL | let test_one = test_fn(one);
127-
| ^^^^^^^^^^^^
127+
| ------- ^^^
128+
| |
129+
| required by a bound introduced by this call
130+
|
131+
note: required by a bound in `test_fn`
132+
--> $DIR/fn_trait_refs.rs:35:24
133+
|
134+
LL | const fn test_fn<T>(mut f: T) -> (T::Output, T::Output, T::Output)
135+
| ------- required by a bound in this function
136+
LL | where
137+
LL | T: ~const Fn<()> + ~const Destruct,
138+
| ^^^^^^ required by this bound in `test_fn`
128139

129140
error[E0277]: the trait bound `fn() -> i32 {two}: const Destruct` is not satisfied
130-
--> $DIR/fn_trait_refs.rs:73:24
141+
--> $DIR/fn_trait_refs.rs:73:36
131142
|
132143
LL | let test_two = test_fn_mut(two);
133-
| ^^^^^^^^^^^^^^^^
144+
| ----------- ^^^
145+
| |
146+
| required by a bound introduced by this call
147+
|
148+
note: required by a bound in `test_fn_mut`
149+
--> $DIR/fn_trait_refs.rs:49:27
150+
|
151+
LL | const fn test_fn_mut<T>(mut f: T) -> (T::Output, T::Output)
152+
| ----------- required by a bound in this function
153+
LL | where
154+
LL | T: ~const FnMut<()> + ~const Destruct,
155+
| ^^^^^^ required by this bound in `test_fn_mut`
134156

135157
error[E0277]: the trait bound `&T: ~const Destruct` is not satisfied
136-
--> $DIR/fn_trait_refs.rs:39:9
158+
--> $DIR/fn_trait_refs.rs:39:19
137159
|
138160
LL | tester_fn(&f),
139-
| ^^^^^^^^^^^^^
161+
| --------- ^^
162+
| |
163+
| required by a bound introduced by this call
164+
|
165+
note: required by a bound in `tester_fn`
166+
--> $DIR/fn_trait_refs.rs:14:24
167+
|
168+
LL | const fn tester_fn<T>(f: T) -> T::Output
169+
| --------- required by a bound in this function
170+
LL | where
171+
LL | T: ~const Fn<()> + ~const Destruct,
172+
| ^^^^^^ required by this bound in `tester_fn`
140173

141174
error[E0277]: the trait bound `&T: ~const Destruct` is not satisfied
142-
--> $DIR/fn_trait_refs.rs:41:9
175+
--> $DIR/fn_trait_refs.rs:41:23
143176
|
144177
LL | tester_fn_mut(&f),
145-
| ^^^^^^^^^^^^^^^^^
178+
| ------------- ^^
179+
| |
180+
| required by a bound introduced by this call
181+
|
182+
note: required by a bound in `tester_fn_mut`
183+
--> $DIR/fn_trait_refs.rs:21:27
184+
|
185+
LL | const fn tester_fn_mut<T>(mut f: T) -> T::Output
186+
| ------------- required by a bound in this function
187+
LL | where
188+
LL | T: ~const FnMut<()> + ~const Destruct,
189+
| ^^^^^^ required by this bound in `tester_fn_mut`
146190

147191
error[E0277]: the trait bound `&mut T: ~const Destruct` is not satisfied
148-
--> $DIR/fn_trait_refs.rs:53:9
192+
--> $DIR/fn_trait_refs.rs:53:23
149193
|
150194
LL | tester_fn_mut(&mut f),
151-
| ^^^^^^^^^^^^^^^^^^^^^
195+
| ------------- ^^^^^^
196+
| |
197+
| required by a bound introduced by this call
198+
|
199+
note: required by a bound in `tester_fn_mut`
200+
--> $DIR/fn_trait_refs.rs:21:27
201+
|
202+
LL | const fn tester_fn_mut<T>(mut f: T) -> T::Output
203+
| ------------- required by a bound in this function
204+
LL | where
205+
LL | T: ~const FnMut<()> + ~const Destruct,
206+
| ^^^^^^ required by this bound in `tester_fn_mut`
152207

153208
error[E0015]: cannot call non-const closure in constant functions
154209
--> $DIR/fn_trait_refs.rs:16:5

0 commit comments

Comments
 (0)