mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-15 05:26:47 +00:00
Auto merge of #115221 - compiler-errors:walk-path, r=estebank
Walk through full path in `point_at_path_if_possible` We already had sufficient information to point at the `[u8]` in `Option::<[u8]>::None` (the `fallback_param_to_point_at` parameter), we just were neither using it nor walking through hir paths sufficiently to encounter it. This should alleviate the need to add additional logic to extract params in a somewhat arbitrary manner of looking at the grandparent def path: https://github.com/rust-lang/rust/pull/115219#discussion_r1305946358 r? `@estebank`
This commit is contained in:
commit
ac89e1615d
@ -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};
|
||||
@ -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, ..) => {
|
||||
@ -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]
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -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?
|
||||
@ -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:
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>`
|
||||
|
@ -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>`
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 `()`
|
||||
|
|
||||
= help: the following other types implement trait `Foo<N>`:
|
||||
<() as Foo<0>>
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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`
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
6
tests/ui/trait-bounds/enum-unit-variant-trait-bound.rs
Normal file
6
tests/ui/trait-bounds/enum-unit-variant-trait-bound.rs
Normal file
@ -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
tests/ui/trait-bounds/enum-unit-variant-trait-bound.stderr
Normal file
13
tests/ui/trait-bounds/enum-unit-variant-trait-bound.stderr
Normal file
@ -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`.
|
@ -38,10 +38,10 @@ 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
|
||||
|
|
||||
@ -49,10 +49,10 @@ 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
|
||||
|
|
||||
@ -60,10 +60,10 @@ 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
|
||||
|
@ -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]`
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user