Print ParamTy span when accessing a field (#52082)
This commit is contained in:
parent
59367b074f
commit
f922483112
3 changed files with 184 additions and 3 deletions
|
@ -1393,9 +1393,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let mut err = self.no_such_field_err(field.span, field, expr_t);
|
let mut err = self.no_such_field_err(field.span, field, expr_t);
|
||||||
|
|
||||||
match expr_t.kind {
|
match expr_t.kind {
|
||||||
ty::Adt(def, _) if !def.is_enum() => {
|
|
||||||
self.suggest_fields_on_recordish(&mut err, def, field);
|
|
||||||
}
|
|
||||||
ty::Array(_, len) => {
|
ty::Array(_, len) => {
|
||||||
self.maybe_suggest_array_indexing(&mut err, expr, base, field, len);
|
self.maybe_suggest_array_indexing(&mut err, expr, base, field, len);
|
||||||
}
|
}
|
||||||
|
@ -1405,6 +1402,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let deref_t = match expr_t.kind {
|
||||||
|
ty::Ref(_, ref_t, _) => ref_t,
|
||||||
|
_ => &expr_t
|
||||||
|
};
|
||||||
|
match deref_t.kind {
|
||||||
|
ty::Adt(def, _) if !def.is_enum() => {
|
||||||
|
self.suggest_fields_on_recordish(&mut err, def, field);
|
||||||
|
}
|
||||||
|
ty::Param(param_ty) => {
|
||||||
|
self.explain_param(&mut err, param_ty);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
if field.name == kw::Await {
|
if field.name == kw::Await {
|
||||||
// We know by construction that `<expr>.await` is either on Rust 2015
|
// We know by construction that `<expr>.await` is either on Rust 2015
|
||||||
// or results in `ExprKind::Await`. Suggest switching the edition to 2018.
|
// or results in `ExprKind::Await`. Suggest switching the edition to 2018.
|
||||||
|
@ -1491,6 +1502,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn explain_param(
|
||||||
|
&self,
|
||||||
|
err: &mut DiagnosticBuilder<'_>,
|
||||||
|
param: ty::ParamTy,
|
||||||
|
) {
|
||||||
|
let generics = self.tcx.generics_of(self.body_id.owner_def_id());
|
||||||
|
let param_def_id = generics.type_param(¶m, self.tcx).def_id;
|
||||||
|
let param_hir_id = match self.tcx.hir().as_local_hir_id(param_def_id) {
|
||||||
|
Some(x) => x,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
let param_span = self.tcx.hir().span(param_hir_id);
|
||||||
|
let param_name = self.tcx.hir().ty_param_name(param_hir_id);
|
||||||
|
|
||||||
|
err.span_note(param_span, &format!("Type parameter '{}' was declared here", param_name));
|
||||||
|
}
|
||||||
|
|
||||||
fn suggest_fields_on_recordish(
|
fn suggest_fields_on_recordish(
|
||||||
&self,
|
&self,
|
||||||
err: &mut DiagnosticBuilder<'_>,
|
err: &mut DiagnosticBuilder<'_>,
|
||||||
|
|
54
src/test/ui/typeck/issue-52082.rs
Normal file
54
src/test/ui/typeck/issue-52082.rs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
// Fix issue 52082: Confusing error if accidentially defining a type paramter with the same name as
|
||||||
|
// an existing type
|
||||||
|
//
|
||||||
|
// To this end, make sure that when trying to retrieve a field of a (reference to) type parameter,
|
||||||
|
// rustc points to the point where the parameter was defined.
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Point
|
||||||
|
{
|
||||||
|
x: i32,
|
||||||
|
y: i32
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Point
|
||||||
|
{
|
||||||
|
fn add(a: &Point, b: &Point) -> Point
|
||||||
|
{
|
||||||
|
Point {x: a.x + b.x, y: a.y + b.y}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Eq
|
||||||
|
{
|
||||||
|
fn equals_ref<T>(a: &T, b: &T) -> bool;
|
||||||
|
fn equals_val<T>(a: T, b: T) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for Point
|
||||||
|
{
|
||||||
|
fn equals_ref<Point>(a: &Point, b: &Point) -> bool
|
||||||
|
{
|
||||||
|
a.x == b.x && a.y == b.y //~ ERROR no field `x` on type `&Point` [E0609]
|
||||||
|
//~|ERROR no field `x` on type `&Point` [E0609]
|
||||||
|
//~|ERROR no field `y` on type `&Point` [E0609]
|
||||||
|
//~|ERROR no field `y` on type `&Point` [E0609]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn equals_val<Point>(a: Point, b: Point) -> bool
|
||||||
|
{
|
||||||
|
a.x == b.x && a.y == b.y //~ ERROR no field `x` on type `Point` [E0609]
|
||||||
|
//~|ERROR no field `x` on type `Point` [E0609]
|
||||||
|
//~|ERROR no field `y` on type `Point` [E0609]
|
||||||
|
//~|ERROR no field `y` on type `Point` [E0609]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main()
|
||||||
|
{
|
||||||
|
let p1 = Point {x: 0, y: 10};
|
||||||
|
let p2 = Point {x: 20, y: 42};
|
||||||
|
println!("{:?}", Point::add(&p1, &p2));
|
||||||
|
println!("p1: {:?}, p2: {:?}", p1, p2);
|
||||||
|
println!("&p1 == &p2: {:?}", Point::equals_ref(&p1, &p2));
|
||||||
|
println!("p1 == p2: {:?}", Point::equals_val(p1, p2));
|
||||||
|
}
|
99
src/test/ui/typeck/issue-52082.stderr
Normal file
99
src/test/ui/typeck/issue-52082.stderr
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
error[E0609]: no field `x` on type `&Point`
|
||||||
|
--> $DIR/issue-52082.rs:31:11
|
||||||
|
|
|
||||||
|
LL | a.x == b.x && a.y == b.y
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
note: Type parameter 'Point' was declared here
|
||||||
|
--> $DIR/issue-52082.rs:29:19
|
||||||
|
|
|
||||||
|
LL | fn equals_ref<Point>(a: &Point, b: &Point) -> bool
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error[E0609]: no field `x` on type `&Point`
|
||||||
|
--> $DIR/issue-52082.rs:31:18
|
||||||
|
|
|
||||||
|
LL | a.x == b.x && a.y == b.y
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
note: Type parameter 'Point' was declared here
|
||||||
|
--> $DIR/issue-52082.rs:29:19
|
||||||
|
|
|
||||||
|
LL | fn equals_ref<Point>(a: &Point, b: &Point) -> bool
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error[E0609]: no field `y` on type `&Point`
|
||||||
|
--> $DIR/issue-52082.rs:31:25
|
||||||
|
|
|
||||||
|
LL | a.x == b.x && a.y == b.y
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
note: Type parameter 'Point' was declared here
|
||||||
|
--> $DIR/issue-52082.rs:29:19
|
||||||
|
|
|
||||||
|
LL | fn equals_ref<Point>(a: &Point, b: &Point) -> bool
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error[E0609]: no field `y` on type `&Point`
|
||||||
|
--> $DIR/issue-52082.rs:31:32
|
||||||
|
|
|
||||||
|
LL | a.x == b.x && a.y == b.y
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
note: Type parameter 'Point' was declared here
|
||||||
|
--> $DIR/issue-52082.rs:29:19
|
||||||
|
|
|
||||||
|
LL | fn equals_ref<Point>(a: &Point, b: &Point) -> bool
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error[E0609]: no field `x` on type `Point`
|
||||||
|
--> $DIR/issue-52082.rs:39:11
|
||||||
|
|
|
||||||
|
LL | a.x == b.x && a.y == b.y
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
note: Type parameter 'Point' was declared here
|
||||||
|
--> $DIR/issue-52082.rs:37:19
|
||||||
|
|
|
||||||
|
LL | fn equals_val<Point>(a: Point, b: Point) -> bool
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error[E0609]: no field `x` on type `Point`
|
||||||
|
--> $DIR/issue-52082.rs:39:18
|
||||||
|
|
|
||||||
|
LL | a.x == b.x && a.y == b.y
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
note: Type parameter 'Point' was declared here
|
||||||
|
--> $DIR/issue-52082.rs:37:19
|
||||||
|
|
|
||||||
|
LL | fn equals_val<Point>(a: Point, b: Point) -> bool
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error[E0609]: no field `y` on type `Point`
|
||||||
|
--> $DIR/issue-52082.rs:39:25
|
||||||
|
|
|
||||||
|
LL | a.x == b.x && a.y == b.y
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
note: Type parameter 'Point' was declared here
|
||||||
|
--> $DIR/issue-52082.rs:37:19
|
||||||
|
|
|
||||||
|
LL | fn equals_val<Point>(a: Point, b: Point) -> bool
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error[E0609]: no field `y` on type `Point`
|
||||||
|
--> $DIR/issue-52082.rs:39:32
|
||||||
|
|
|
||||||
|
LL | a.x == b.x && a.y == b.y
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
note: Type parameter 'Point' was declared here
|
||||||
|
--> $DIR/issue-52082.rs:37:19
|
||||||
|
|
|
||||||
|
LL | fn equals_val<Point>(a: Point, b: Point) -> bool
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 8 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0609`.
|
Loading…
Reference in a new issue