Skip to content

Commit 7c2ee33

Browse files
Refine error spans for const args in hir typeck
1 parent 44f5180 commit 7c2ee33

File tree

4 files changed

+49
-24
lines changed

4 files changed

+49
-24
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs

+28-18
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_hir::def::Res;
44
use rustc_hir::def_id::DefId;
55
use rustc_infer::traits::ObligationCauseCode;
66
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
7-
use rustc_span::{self, Span};
7+
use rustc_span::{self, symbol::kw, Span};
88
use rustc_trait_selection::traits;
99

1010
use std::ops::ControlFlow;
@@ -25,17 +25,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2525

2626
let generics = self.tcx.generics_of(def_id);
2727
let predicate_substs = match unsubstituted_pred.kind().skip_binder() {
28-
ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => pred.trait_ref.substs,
29-
ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => pred.projection_ty.substs,
30-
_ => ty::List::empty(),
28+
ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => pred.trait_ref.substs.to_vec(),
29+
ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
30+
pred.projection_ty.substs.to_vec()
31+
}
32+
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(arg, ty)) => {
33+
vec![ty.into(), arg.into()]
34+
}
35+
ty::PredicateKind::ConstEvaluatable(e) => vec![e.into()],
36+
_ => return false,
3137
};
3238

33-
let find_param_matching = |matches: &dyn Fn(&ty::ParamTy) -> bool| {
34-
predicate_substs.types().find_map(|ty| {
35-
ty.walk().find_map(|arg| {
39+
let find_param_matching = |matches: &dyn Fn(ty::ParamTerm) -> bool| {
40+
predicate_substs.iter().find_map(|arg| {
41+
arg.walk().find_map(|arg| {
3642
if let ty::GenericArgKind::Type(ty) = arg.unpack()
37-
&& let ty::Param(param_ty) = ty.kind()
38-
&& matches(param_ty)
43+
&& let ty::Param(param_ty) = *ty.kind()
44+
&& matches(ty::ParamTerm::Ty(param_ty))
45+
{
46+
Some(arg)
47+
} else if let ty::GenericArgKind::Const(ct) = arg.unpack()
48+
&& let ty::ConstKind::Param(param_ct) = ct.kind()
49+
&& matches(ty::ParamTerm::Const(param_ct))
3950
{
4051
Some(arg)
4152
} else {
@@ -47,21 +58,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4758

4859
// Prefer generics that are local to the fn item, since these are likely
4960
// to be the cause of the unsatisfied predicate.
50-
let mut param_to_point_at = find_param_matching(&|param_ty| {
51-
self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) == def_id
61+
let mut param_to_point_at = find_param_matching(&|param_term| {
62+
self.tcx.parent(generics.param_at(param_term.index(), self.tcx).def_id) == def_id
5263
});
5364
// Fall back to generic that isn't local to the fn item. This will come
5465
// from a trait or impl, for example.
55-
let mut fallback_param_to_point_at = find_param_matching(&|param_ty| {
56-
self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) != def_id
57-
&& param_ty.name != rustc_span::symbol::kw::SelfUpper
66+
let mut fallback_param_to_point_at = find_param_matching(&|param_term| {
67+
self.tcx.parent(generics.param_at(param_term.index(), self.tcx).def_id) != def_id
68+
&& !matches!(param_term, ty::ParamTerm::Ty(ty) if ty.name == kw::SelfUpper)
5869
});
5970
// Finally, the `Self` parameter is possibly the reason that the predicate
6071
// is unsatisfied. This is less likely to be true for methods, because
6172
// method probe means that we already kinda check that the predicates due
6273
// to the `Self` type are true.
63-
let mut self_param_to_point_at =
64-
find_param_matching(&|param_ty| param_ty.name == rustc_span::symbol::kw::SelfUpper);
74+
let mut self_param_to_point_at = find_param_matching(
75+
&|param_term| matches!(param_term, ty::ParamTerm::Ty(ty) if ty.name == kw::SelfUpper),
76+
);
6577

6678
// Finally, for ambiguity-related errors, we actually want to look
6779
// for a parameter that is the source of the inference type left
@@ -225,14 +237,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
225237
.own_substs(ty::InternalSubsts::identity_for_item(self.tcx, def_id));
226238
let Some((index, _)) = own_substs
227239
.iter()
228-
.filter(|arg| matches!(arg.unpack(), ty::GenericArgKind::Type(_)))
229240
.enumerate()
230241
.find(|(_, arg)| **arg == param_to_point_at) else { return false };
231242
let Some(arg) = segment
232243
.args()
233244
.args
234245
.iter()
235-
.filter(|arg| matches!(arg, hir::GenericArg::Type(_)))
236246
.nth(index) else { return false; };
237247
error.obligation.cause.span = arg
238248
.span()

compiler/rustc_middle/src/ty/mod.rs

+15
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,21 @@ impl<'tcx> TermKind<'tcx> {
10351035
}
10361036
}
10371037

1038+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
1039+
pub enum ParamTerm {
1040+
Ty(ParamTy),
1041+
Const(ParamConst),
1042+
}
1043+
1044+
impl ParamTerm {
1045+
pub fn index(self) -> usize {
1046+
match self {
1047+
ParamTerm::Ty(ty) => ty.index as usize,
1048+
ParamTerm::Const(ct) => ct.index as usize,
1049+
}
1050+
}
1051+
}
1052+
10381053
/// This kind of predicate has no *direct* correspondent in the
10391054
/// syntax, but it roughly corresponds to the syntactic forms:
10401055
///

tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: unconstrained generic constant
2-
--> $DIR/cross_crate_predicate.rs:7:13
2+
--> $DIR/cross_crate_predicate.rs:7:44
33
|
44
LL | let _ = const_evaluatable_lib::test1::<T>();
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^
66
|
77
= help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:`
88
note: required by a bound in `test1`
@@ -12,10 +12,10 @@ LL | [u8; std::mem::size_of::<T>() - 1]: Sized,
1212
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1`
1313

1414
error: unconstrained generic constant
15-
--> $DIR/cross_crate_predicate.rs:7:13
15+
--> $DIR/cross_crate_predicate.rs:7:44
1616
|
1717
LL | let _ = const_evaluatable_lib::test1::<T>();
18-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
| ^
1919
|
2020
= help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:`
2121
note: required by a bound in `test1`

tests/ui/const-generics/type_mismatch.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: the constant `N` is not of type `u8`
2-
--> $DIR/type_mismatch.rs:2:5
2+
--> $DIR/type_mismatch.rs:2:11
33
|
44
LL | bar::<N>()
5-
| ^^^^^^^^
5+
| ^
66
|
77
note: required by a bound in `bar`
88
--> $DIR/type_mismatch.rs:6:8

0 commit comments

Comments
 (0)