Skip to content

Commit

Permalink
Rollup merge of rust-lang#108961 - compiler-errors:refine-ct-errors, …
Browse files Browse the repository at this point in the history
…r=BoxyUwU

Refine error spans for const args in hir typeck

Improve just a couple of error messages having to do with mismatched consts.

r? `@ghost` i'll put this up when the dependent commits are merged
  • Loading branch information
matthiaskrgr authored Mar 23, 2023
2 parents c2c2836 + 2e7472f commit 7d4bee3
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 27 deletions.
46 changes: 28 additions & 18 deletions compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use rustc_hir::def::Res;
use rustc_hir::def_id::DefId;
use rustc_infer::traits::ObligationCauseCode;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
use rustc_span::{self, Span};
use rustc_span::{self, symbol::kw, Span};
use rustc_trait_selection::traits;

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

let generics = self.tcx.generics_of(def_id);
let predicate_substs = match unsubstituted_pred.kind().skip_binder() {
ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => pred.trait_ref.substs,
ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => pred.projection_ty.substs,
_ => ty::List::empty(),
ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => pred.trait_ref.substs.to_vec(),
ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
pred.projection_ty.substs.to_vec()
}
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(arg, ty)) => {
vec![ty.into(), arg.into()]
}
ty::PredicateKind::ConstEvaluatable(e) => vec![e.into()],
_ => return false,
};

let find_param_matching = |matches: &dyn Fn(&ty::ParamTy) -> bool| {
predicate_substs.types().find_map(|ty| {
ty.walk().find_map(|arg| {
let find_param_matching = |matches: &dyn Fn(ty::ParamTerm) -> bool| {
predicate_substs.iter().find_map(|arg| {
arg.walk().find_map(|arg| {
if let ty::GenericArgKind::Type(ty) = arg.unpack()
&& let ty::Param(param_ty) = ty.kind()
&& matches(param_ty)
&& let ty::Param(param_ty) = *ty.kind()
&& matches(ty::ParamTerm::Ty(param_ty))
{
Some(arg)
} else if let ty::GenericArgKind::Const(ct) = arg.unpack()
&& let ty::ConstKind::Param(param_ct) = ct.kind()
&& matches(ty::ParamTerm::Const(param_ct))
{
Some(arg)
} else {
Expand All @@ -47,21 +58,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// Prefer generics that are local to the fn item, since these are likely
// to be the cause of the unsatisfied predicate.
let mut param_to_point_at = find_param_matching(&|param_ty| {
self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) == def_id
let mut param_to_point_at = find_param_matching(&|param_term| {
self.tcx.parent(generics.param_at(param_term.index(), self.tcx).def_id) == def_id
});
// Fall back to generic that isn't local to the fn item. This will come
// from a trait or impl, for example.
let mut fallback_param_to_point_at = find_param_matching(&|param_ty| {
self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) != def_id
&& param_ty.name != rustc_span::symbol::kw::SelfUpper
let mut fallback_param_to_point_at = find_param_matching(&|param_term| {
self.tcx.parent(generics.param_at(param_term.index(), self.tcx).def_id) != def_id
&& !matches!(param_term, ty::ParamTerm::Ty(ty) if ty.name == kw::SelfUpper)
});
// Finally, the `Self` parameter is possibly the reason that the predicate
// is unsatisfied. This is less likely to be true for methods, because
// method probe means that we already kinda check that the predicates due
// to the `Self` type are true.
let mut self_param_to_point_at =
find_param_matching(&|param_ty| param_ty.name == rustc_span::symbol::kw::SelfUpper);
let mut self_param_to_point_at = find_param_matching(
&|param_term| matches!(param_term, ty::ParamTerm::Ty(ty) if ty.name == kw::SelfUpper),
);

// Finally, for ambiguity-related errors, we actually want to look
// for a parameter that is the source of the inference type left
Expand Down Expand Up @@ -225,14 +237,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.own_substs(ty::InternalSubsts::identity_for_item(self.tcx, def_id));
let Some((index, _)) = own_substs
.iter()
.filter(|arg| matches!(arg.unpack(), ty::GenericArgKind::Type(_)))
.enumerate()
.find(|(_, arg)| **arg == param_to_point_at) else { return false };
let Some(arg) = segment
.args()
.args
.iter()
.filter(|arg| matches!(arg, hir::GenericArg::Type(_)))
.nth(index) else { return false; };
error.obligation.cause.span = arg
.span()
Expand Down
15 changes: 15 additions & 0 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,21 @@ impl<'tcx> TermKind<'tcx> {
}
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum ParamTerm {
Ty(ParamTy),
Const(ParamConst),
}

impl ParamTerm {
pub fn index(self) -> usize {
match self {
ParamTerm::Ty(ty) => ty.index as usize,
ParamTerm::Const(ct) => ct.index as usize,
}
}
}

/// This kind of predicate has no *direct* correspondent in the
/// syntax, but it roughly corresponds to the syntactic forms:
///
Expand Down
14 changes: 12 additions & 2 deletions compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1282,10 +1282,20 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
),

ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
self.tcx.sess.struct_span_err(
let mut diag = self.tcx.sess.struct_span_err(
span,
&format!("the constant `{}` is not of type `{}`", ct, ty),
)
);
self.note_type_err(
&mut diag,
&obligation.cause,
None,
None,
TypeError::Sorts(ty::error::ExpectedFound::new(true, ty, ct.ty())),
false,
false,
);
diag
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: unconstrained generic constant
--> $DIR/cross_crate_predicate.rs:7:13
--> $DIR/cross_crate_predicate.rs:7:44
|
LL | let _ = const_evaluatable_lib::test1::<T>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^
|
= help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:`
note: required by a bound in `test1`
Expand All @@ -12,10 +12,10 @@ LL | [u8; std::mem::size_of::<T>() - 1]: Sized,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1`

error: unconstrained generic constant
--> $DIR/cross_crate_predicate.rs:7:13
--> $DIR/cross_crate_predicate.rs:7:44
|
LL | let _ = const_evaluatable_lib::test1::<T>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^
|
= help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:`
note: required by a bound in `test1`
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/const-generics/type_mismatch.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: the constant `N` is not of type `u8`
--> $DIR/type_mismatch.rs:2:5
--> $DIR/type_mismatch.rs:2:11
|
LL | bar::<N>()
| ^^^^^^^^
| ^ expected `u8`, found `usize`
|
note: required by a bound in `bar`
--> $DIR/type_mismatch.rs:6:8
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/transmutability/issue-101739-1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ error: the constant `ASSUME_ALIGNMENT` is not of type `Assume`
--> $DIR/issue-101739-1.rs:8:14
|
LL | Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Assume`, found `bool`
|
note: required by a bound in `BikeshedIntrinsicFrom`
--> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL
Expand Down

0 comments on commit 7d4bee3

Please sign in to comment.