Skip to content

Commit df00987

Browse files
Baranowskiandjo403
authored andcommitted
Print ParamTy span when accessing a field (rust-lang#52082)
1 parent 77b0b82 commit df00987

File tree

3 files changed

+184
-3
lines changed

3 files changed

+184
-3
lines changed

src/librustc_typeck/check/expr.rs

+31-3
Original file line numberDiff line numberDiff line change
@@ -1397,9 +1397,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13971397
let mut err = self.no_such_field_err(field.span, field, expr_t);
13981398

13991399
match expr_t.kind {
1400-
ty::Adt(def, _) if !def.is_enum() => {
1401-
self.suggest_fields_on_recordish(&mut err, def, field);
1402-
}
14031400
ty::Array(_, len) => {
14041401
self.maybe_suggest_array_indexing(&mut err, expr, base, field, len);
14051402
}
@@ -1409,6 +1406,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14091406
_ => {}
14101407
}
14111408

1409+
let deref_t = match expr_t.kind {
1410+
ty::Ref(_, ref_t, _) => ref_t,
1411+
_ => &expr_t
1412+
};
1413+
match deref_t.kind {
1414+
ty::Adt(def, _) if !def.is_enum() => {
1415+
self.suggest_fields_on_recordish(&mut err, def, field);
1416+
}
1417+
ty::Param(param_ty) => {
1418+
self.explain_param(&mut err, param_ty);
1419+
}
1420+
_ => {}
1421+
}
1422+
14121423
if field.name == kw::Await {
14131424
// We know by construction that `<expr>.await` is either on Rust 2015
14141425
// or results in `ExprKind::Await`. Suggest switching the edition to 2018.
@@ -1495,6 +1506,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14951506
err.emit();
14961507
}
14971508

1509+
fn explain_param(
1510+
&self,
1511+
err: &mut DiagnosticBuilder<'_>,
1512+
param: ty::ParamTy,
1513+
) {
1514+
let generics = self.tcx.generics_of(self.body_id.owner_def_id());
1515+
let param_def_id = generics.type_param(&param, self.tcx).def_id;
1516+
let param_hir_id = match self.tcx.hir().as_local_hir_id(param_def_id) {
1517+
Some(x) => x,
1518+
None => return,
1519+
};
1520+
let param_span = self.tcx.hir().span(param_hir_id);
1521+
let param_name = self.tcx.hir().ty_param_name(param_hir_id);
1522+
1523+
err.span_note(param_span, &format!("Type parameter '{}' was declared here", param_name));
1524+
}
1525+
14981526
fn suggest_fields_on_recordish(
14991527
&self,
15001528
err: &mut DiagnosticBuilder<'_>,

src/test/ui/typeck/issue-52082.rs

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Fix issue 52082: Confusing error if accidentially defining a type paramter with the same name as
2+
// an existing type
3+
//
4+
// To this end, make sure that when trying to retrieve a field of a (reference to) type parameter,
5+
// rustc points to the point where the parameter was defined.
6+
#[derive(Debug)]
7+
struct Point
8+
{
9+
x: i32,
10+
y: i32
11+
}
12+
13+
impl Point
14+
{
15+
fn add(a: &Point, b: &Point) -> Point
16+
{
17+
Point {x: a.x + b.x, y: a.y + b.y}
18+
}
19+
}
20+
21+
trait Eq
22+
{
23+
fn equals_ref<T>(a: &T, b: &T) -> bool;
24+
fn equals_val<T>(a: T, b: T) -> bool;
25+
}
26+
27+
impl Eq for Point
28+
{
29+
fn equals_ref<Point>(a: &Point, b: &Point) -> bool
30+
{
31+
a.x == b.x && a.y == b.y //~ ERROR no field `x` on type `&Point` [E0609]
32+
//~|ERROR no field `x` on type `&Point` [E0609]
33+
//~|ERROR no field `y` on type `&Point` [E0609]
34+
//~|ERROR no field `y` on type `&Point` [E0609]
35+
}
36+
37+
fn equals_val<Point>(a: Point, b: Point) -> bool
38+
{
39+
a.x == b.x && a.y == b.y //~ ERROR no field `x` on type `Point` [E0609]
40+
//~|ERROR no field `x` on type `Point` [E0609]
41+
//~|ERROR no field `y` on type `Point` [E0609]
42+
//~|ERROR no field `y` on type `Point` [E0609]
43+
}
44+
}
45+
46+
fn main()
47+
{
48+
let p1 = Point {x: 0, y: 10};
49+
let p2 = Point {x: 20, y: 42};
50+
println!("{:?}", Point::add(&p1, &p2));
51+
println!("p1: {:?}, p2: {:?}", p1, p2);
52+
println!("&p1 == &p2: {:?}", Point::equals_ref(&p1, &p2));
53+
println!("p1 == p2: {:?}", Point::equals_val(p1, p2));
54+
}

src/test/ui/typeck/issue-52082.stderr

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
error[E0609]: no field `x` on type `&Point`
2+
--> $DIR/issue-52082.rs:31:11
3+
|
4+
LL | a.x == b.x && a.y == b.y
5+
| ^
6+
|
7+
note: Type parameter 'Point' was declared here
8+
--> $DIR/issue-52082.rs:29:19
9+
|
10+
LL | fn equals_ref<Point>(a: &Point, b: &Point) -> bool
11+
| ^^^^^
12+
13+
error[E0609]: no field `x` on type `&Point`
14+
--> $DIR/issue-52082.rs:31:18
15+
|
16+
LL | a.x == b.x && a.y == b.y
17+
| ^
18+
|
19+
note: Type parameter 'Point' was declared here
20+
--> $DIR/issue-52082.rs:29:19
21+
|
22+
LL | fn equals_ref<Point>(a: &Point, b: &Point) -> bool
23+
| ^^^^^
24+
25+
error[E0609]: no field `y` on type `&Point`
26+
--> $DIR/issue-52082.rs:31:25
27+
|
28+
LL | a.x == b.x && a.y == b.y
29+
| ^
30+
|
31+
note: Type parameter 'Point' was declared here
32+
--> $DIR/issue-52082.rs:29:19
33+
|
34+
LL | fn equals_ref<Point>(a: &Point, b: &Point) -> bool
35+
| ^^^^^
36+
37+
error[E0609]: no field `y` on type `&Point`
38+
--> $DIR/issue-52082.rs:31:32
39+
|
40+
LL | a.x == b.x && a.y == b.y
41+
| ^
42+
|
43+
note: Type parameter 'Point' was declared here
44+
--> $DIR/issue-52082.rs:29:19
45+
|
46+
LL | fn equals_ref<Point>(a: &Point, b: &Point) -> bool
47+
| ^^^^^
48+
49+
error[E0609]: no field `x` on type `Point`
50+
--> $DIR/issue-52082.rs:39:11
51+
|
52+
LL | a.x == b.x && a.y == b.y
53+
| ^
54+
|
55+
note: Type parameter 'Point' was declared here
56+
--> $DIR/issue-52082.rs:37:19
57+
|
58+
LL | fn equals_val<Point>(a: Point, b: Point) -> bool
59+
| ^^^^^
60+
61+
error[E0609]: no field `x` on type `Point`
62+
--> $DIR/issue-52082.rs:39:18
63+
|
64+
LL | a.x == b.x && a.y == b.y
65+
| ^
66+
|
67+
note: Type parameter 'Point' was declared here
68+
--> $DIR/issue-52082.rs:37:19
69+
|
70+
LL | fn equals_val<Point>(a: Point, b: Point) -> bool
71+
| ^^^^^
72+
73+
error[E0609]: no field `y` on type `Point`
74+
--> $DIR/issue-52082.rs:39:25
75+
|
76+
LL | a.x == b.x && a.y == b.y
77+
| ^
78+
|
79+
note: Type parameter 'Point' was declared here
80+
--> $DIR/issue-52082.rs:37:19
81+
|
82+
LL | fn equals_val<Point>(a: Point, b: Point) -> bool
83+
| ^^^^^
84+
85+
error[E0609]: no field `y` on type `Point`
86+
--> $DIR/issue-52082.rs:39:32
87+
|
88+
LL | a.x == b.x && a.y == b.y
89+
| ^
90+
|
91+
note: Type parameter 'Point' was declared here
92+
--> $DIR/issue-52082.rs:37:19
93+
|
94+
LL | fn equals_val<Point>(a: Point, b: Point) -> bool
95+
| ^^^^^
96+
97+
error: aborting due to 8 previous errors
98+
99+
For more information about this error, try `rustc --explain E0609`.

0 commit comments

Comments
 (0)