Skip to content

Walk through full path in point_at_path_if_possible #115221

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 60 additions & 24 deletions compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::FnCtxt;
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_infer::{infer::type_variable::TypeVariableOriginKind, traits::ObligationCauseCode};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
Expand Down Expand Up @@ -133,15 +133,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
}
// Notably, we only point to params that are local to the
// item we're checking, since those are the ones we are able
// to look in the final `hir::PathSegment` for. Everything else
// would require a deeper search into the `qpath` than I think
// is worthwhile.
if let Some(param_to_point_at) = param_to_point_at
&& self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath)

for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
.into_iter()
.flatten()
{
return true;
if self.point_at_path_if_possible(error, def_id, param, qpath) {
return true;
}
}
}
hir::ExprKind::MethodCall(segment, receiver, args, ..) => {
Expand All @@ -166,12 +165,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
return true;
}
// Handle `Self` param specifically, since it's separated in
// the method call representation
if self_param_to_point_at.is_some() {
error.obligation.cause.span = receiver
.span
.find_ancestor_in_same_ctxt(error.obligation.cause.span)
.unwrap_or(receiver.span);
return true;
}
}
hir::ExprKind::Struct(qpath, fields, ..) => {
if let Res::Def(
hir::def::DefKind::Struct | hir::def::DefKind::Variant,
variant_def_id,
) = self.typeck_results.borrow().qpath_res(qpath, hir_id)
if let Res::Def(DefKind::Struct | DefKind::Variant, variant_def_id) =
self.typeck_results.borrow().qpath_res(qpath, hir_id)
{
for param in
[param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
Expand All @@ -193,10 +199,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
}
if let Some(param_to_point_at) = param_to_point_at
&& self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath)

for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
.into_iter()
.flatten()
{
return true;
if self.point_at_path_if_possible(error, def_id, param, qpath) {
return true;
}
}
}
_ => {}
Expand All @@ -213,17 +223,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
qpath: &hir::QPath<'tcx>,
) -> bool {
match qpath {
hir::QPath::Resolved(_, path) => {
if let Some(segment) = path.segments.last()
&& self.point_at_generic_if_possible(error, def_id, param, segment)
hir::QPath::Resolved(self_ty, path) => {
for segment in path.segments.iter().rev() {
if let Res::Def(kind, def_id) = segment.res
&& !matches!(kind, DefKind::Mod | DefKind::ForeignMod)
&& self.point_at_generic_if_possible(error, def_id, param, segment)
{
return true;
}
}
// Handle `Self` param specifically, since it's separated in
// the path representation
if let Some(self_ty) = self_ty
&& let ty::GenericArgKind::Type(ty) = param.unpack()
&& ty == self.tcx.types.self_param
{
error.obligation.cause.span = self_ty
.span
.find_ancestor_in_same_ctxt(error.obligation.cause.span)
.unwrap_or(self_ty.span);
return true;
}
}
hir::QPath::TypeRelative(_, segment) => {
hir::QPath::TypeRelative(self_ty, segment) => {
if self.point_at_generic_if_possible(error, def_id, param, segment) {
return true;
}
// Handle `Self` param specifically, since it's separated in
// the path representation
if let ty::GenericArgKind::Type(ty) = param.unpack()
&& ty == self.tcx.types.self_param
{
error.obligation.cause.span = self_ty
.span
.find_ancestor_in_same_ctxt(error.obligation.cause.span)
.unwrap_or(self_ty.span);
return true;
}
}
_ => {}
}
Expand Down Expand Up @@ -618,14 +654,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};

let variant_def_id = match expr_struct_def_kind {
hir::def::DefKind::Struct => {
DefKind::Struct => {
if in_ty_adt.did() != expr_struct_def_id {
// FIXME: Deal with type aliases?
return Err(expr);
}
expr_struct_def_id
}
hir::def::DefKind::Variant => {
DefKind::Variant => {
// If this is a variant, its parent is the type definition.
if in_ty_adt.did() != self.tcx.parent(expr_struct_def_id) {
// FIXME: Deal with type aliases?
Expand Down Expand Up @@ -727,14 +763,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};

let variant_def_id = match expr_struct_def_kind {
hir::def::DefKind::Ctor(hir::def::CtorOf::Struct, hir::def::CtorKind::Fn) => {
DefKind::Ctor(hir::def::CtorOf::Struct, hir::def::CtorKind::Fn) => {
if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) {
// FIXME: Deal with type aliases?
return Err(expr);
}
self.tcx.parent(expr_ctor_def_id)
}
hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => {
DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => {
// For a typical enum like
// `enum Blah<T> { Variant(T) }`
// we get the following resolutions:
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/associated-consts/associated-const-array-len.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0277]: the trait bound `i32: Foo` is not satisfied
--> $DIR/associated-const-array-len.rs:5:16
--> $DIR/associated-const-array-len.rs:5:17
|
LL | const X: [i32; <i32 as Foo>::ID] = [0, 1, 2];
| ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
| ^^^ the trait `Foo` is not implemented for `i32`

error: aborting due to previous error

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/associated-types/issue-44153.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0271]: type mismatch resolving `<() as Array>::Element == &()`
--> $DIR/issue-44153.rs:18:5
--> $DIR/issue-44153.rs:18:6
|
LL | <() as Visit>::visit();
| ^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Array>::Element == &()`
| ^^ type mismatch resolving `<() as Array>::Element == &()`
|
note: expected this to be `&()`
--> $DIR/issue-44153.rs:10:20
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/associated-types/substs-ppaux.normal.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ LL | let x: () = foo::<'static>();
| ++

error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/substs-ppaux.rs:49:5
--> $DIR/substs-ppaux.rs:49:6
|
LL | <str as Foo<u8>>::bar;
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
| ^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `str`
note: required for `str` to implement `Foo<'_, '_, u8>`
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/associated-types/substs-ppaux.verbose.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ LL | let x: () = foo::<'static>();
| ++

error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/substs-ppaux.rs:49:5
--> $DIR/substs-ppaux.rs:49:6
|
LL | <str as Foo<u8>>::bar;
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
| ^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `str`
note: required for `str` to implement `Foo<'?0, '?1, u8>`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0277]: the trait bound `[Adt; std::mem::size_of::<Self::Assoc>()]: Foo` is not satisfied
--> $DIR/dont-evaluate-array-len-on-err-1.rs:15:9
--> $DIR/dont-evaluate-array-len-on-err-1.rs:15:10
|
LL | <[Adt; std::mem::size_of::<Self::Assoc>()] as Foo>::bar()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[Adt; std::mem::size_of::<Self::Assoc>()]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[Adt; std::mem::size_of::<Self::Assoc>()]`

error: aborting due to previous error

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/const-generics/exhaustive-value.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0277]: the trait bound `(): Foo<N>` is not satisfied
--> $DIR/exhaustive-value.rs:262:5
--> $DIR/exhaustive-value.rs:262:16
|
LL | <() as Foo<N>>::test()
| ^^^^^^^^^^^^^^^^^^^^ the trait `Foo<N>` is not implemented for `()`
| ^ the trait `Foo<N>` is not implemented for `()`
Comment on lines 4 to +5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interestingly, I would have expected the span to point at () here, based on the output of the other tests.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's some subtlety in the ordering of what params to prefer over others. Right now we prefer non-self params over self params in qpaths, though arguably pointing at either of the params here is good enough.

|
= help: the following other types implement trait `Foo<N>`:
<() as Foo<0>>
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/consts/missing-larger-array-impl.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0277]: the trait bound `[X; 35]: Default` is not satisfied
--> $DIR/missing-larger-array-impl.rs:7:5
--> $DIR/missing-larger-array-impl.rs:7:6
|
LL | <[X; 35] as Default>::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `[X; 35]`
| ^^^^^^^ the trait `Default` is not implemented for `[X; 35]`
|
= help: the following other types implement trait `Default`:
[T; 0]
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/generic-const-items/unsatisfied-bounds.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ LL | Infallible: From<T>;
| ^^^^^^^ required by this bound in `K`

error[E0277]: the trait bound `Vec<u8>: Copy` is not satisfied
--> $DIR/unsatisfied-bounds.rs:32:13
--> $DIR/unsatisfied-bounds.rs:32:26
|
LL | let _ = <() as Trait<Vec<u8>>>::A;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Vec<u8>`
| ^^^^^^^ the trait `Copy` is not implemented for `Vec<u8>`
|
note: required by a bound in `Trait::A`
--> $DIR/unsatisfied-bounds.rs:17:12
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/issues/issue-39970.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0271]: type mismatch resolving `<() as Array<'a>>::Element == ()`
--> $DIR/issue-39970.rs:19:5
--> $DIR/issue-39970.rs:19:6
|
LL | <() as Visit>::visit();
| ^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Array<'a>>::Element == ()`
| ^^ type mismatch resolving `<() as Array<'a>>::Element == ()`
|
note: expected this to be `()`
--> $DIR/issue-39970.rs:10:20
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0277]: the trait bound `u32: ~const Plus` is not satisfied
--> $DIR/call-const-trait-method-fail.rs:25:7
--> $DIR/call-const-trait-method-fail.rs:25:5
|
LL | a.plus(b)
| ^^^^ the trait `Plus` is not implemented for `u32`
| ^ the trait `Plus` is not implemented for `u32`
|
= help: the trait `Plus` is implemented for `u32`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: ~const Bar` is not satisfied
--> $DIR/trait-where-clause-const.rs:21:5
|
LL | T::b();
| ^^^^ the trait `Bar` is not implemented for `T`
| ^ the trait `Bar` is not implemented for `T`
|
note: required by a bound in `Foo::b`
--> $DIR/trait-where-clause-const.rs:15:24
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: Bar` is not satisfied
--> $DIR/trait-where-clause.rs:14:5
|
LL | T::b();
| ^^^^ the trait `Bar` is not implemented for `T`
| ^ the trait `Bar` is not implemented for `T`
|
note: required by a bound in `Foo::b`
--> $DIR/trait-where-clause.rs:8:24
Expand Down
6 changes: 6 additions & 0 deletions tests/ui/trait-bounds/enum-unit-variant-trait-bound.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Regression test for one part of issue #105306.

fn main() {
let _ = Option::<[u8]>::None;
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
}
13 changes: 13 additions & 0 deletions tests/ui/trait-bounds/enum-unit-variant-trait-bound.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/enum-unit-variant-trait-bound.rs:4:22
|
LL | let _ = Option::<[u8]>::None;
| ^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
note: required by a bound in `None`
--> $SRC_DIR/core/src/option.rs:LL:COL

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
12 changes: 6 additions & 6 deletions tests/ui/traits/suggest-where-clause.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -38,32 +38,32 @@ LL + fn check<T: Iterator, U>() {
|

error[E0277]: the trait bound `u64: From<T>` is not satisfied
--> $DIR/suggest-where-clause.rs:15:5
--> $DIR/suggest-where-clause.rs:15:18
|
LL | <u64 as From<T>>::from;
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `From<T>` is not implemented for `u64`
| ^ the trait `From<T>` is not implemented for `u64`
|
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
LL | fn check<T: Iterator, U: ?Sized>() where u64: From<T> {
| ++++++++++++++++++

error[E0277]: the trait bound `u64: From<<T as Iterator>::Item>` is not satisfied
--> $DIR/suggest-where-clause.rs:18:5
--> $DIR/suggest-where-clause.rs:18:18
|
LL | <u64 as From<<T as Iterator>::Item>>::from;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<<T as Iterator>::Item>` is not implemented for `u64`
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<<T as Iterator>::Item>` is not implemented for `u64`
|
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
LL | fn check<T: Iterator, U: ?Sized>() where u64: From<<T as Iterator>::Item> {
| ++++++++++++++++++++++++++++++++++++++

error[E0277]: the trait bound `Misc<_>: From<T>` is not satisfied
--> $DIR/suggest-where-clause.rs:23:5
--> $DIR/suggest-where-clause.rs:23:22
|
LL | <Misc<_> as From<T>>::from;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<T>` is not implemented for `Misc<_>`
| ^ the trait `From<T>` is not implemented for `Misc<_>`

error[E0277]: the size for values of type `[T]` cannot be known at compilation time
--> $DIR/suggest-where-clause.rs:28:20
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/unevaluated_fixed_size_array_len.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0277]: the trait bound `[(); 0]: Foo` is not satisfied
--> $DIR/unevaluated_fixed_size_array_len.rs:12:5
--> $DIR/unevaluated_fixed_size_array_len.rs:12:6
|
LL | <[(); 0] as Foo>::foo()
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[(); 0]`
| ^^^^^^^ the trait `Foo` is not implemented for `[(); 0]`
|
= help: the trait `Foo` is implemented for `[(); 1]`

Expand Down