Skip to content

Commit bac0e55

Browse files
committed
On let binding type point to type parameter that introduced unmet bound
On the following example, point at `String` instead of the whole type: ``` error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/own-bound-span.rs:14:24 | LL | let _: <S as D>::P<String>; | ^^^^^^ the trait `Copy` is not implemented for `String` | note: required by a bound in `D::P` --> $DIR/own-bound-span.rs:4:15 | LL | type P<T: Copy>; | ^^^^ required by this bound in `D::P` ```
1 parent 120c24d commit bac0e55

14 files changed

+200
-77
lines changed

compiler/rustc_hir_typeck/src/closure.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
231231
let inferred_sig = self.normalize(
232232
span,
233233
self.deduce_sig_from_projection(
234-
Some(span),
234+
Some(span),
235235
bound_predicate.rebind(proj_predicate),
236236
),
237237
);

compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs

+74-68
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2020
else {
2121
return false;
2222
};
23-
let hir = self.tcx.hir();
24-
let hir::Node::Expr(expr) = hir.get(hir_id) else {
25-
return false;
26-
};
2723

2824
let Some(unsubstituted_pred) = self
2925
.tcx
@@ -69,15 +65,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6965

7066
// Account for enum variant constructors, where the type param corresponds to the enum
7167
// itself.
72-
let enum_def_id = if let hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, _) =
73-
self.tcx.def_kind(def_id)
74-
{
75-
// `def_id` corresponds to a constructor, and its parent is the variant, and we want
76-
// the enum.
77-
Some(self.tcx.parent(self.tcx.parent(def_id)))
78-
} else {
79-
None
80-
};
68+
let enum_def_id =
69+
if let DefKind::Ctor(hir::def::CtorOf::Variant, _) = self.tcx.def_kind(def_id) {
70+
// `def_id` corresponds to a constructor, and its parent is the variant, and we want
71+
// the enum.
72+
Some(self.tcx.parent(self.tcx.parent(def_id)))
73+
} else {
74+
None
75+
};
8176
let variant_param_to_point_at = find_param_matching(&|param_term| {
8277
// FIXME: It would be nice to make this not use string manipulation,
8378
// but it's pretty hard to do this, since `ty::ParamTy` is missing
@@ -90,11 +85,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
9085
};
9186
// Account for enum variant constructors, where the type param corresponds to the enum
9287
// itself.
93-
let def_id = if let Some(def_id) = enum_def_id {
94-
def_id
95-
} else {
96-
def_id
97-
};
88+
let def_id = if let Some(def_id) = enum_def_id { def_id } else { def_id };
9889
self.tcx.parent(generics.param_at(param_term.index(), self.tcx).def_id) == def_id
9990
&& include
10091
});
@@ -127,68 +118,83 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
127118
self.find_ambiguous_parameter_in(def_id, error.root_obligation.predicate);
128119
}
129120

130-
if self.closure_span_overlaps_error(error, expr.span) {
131-
return false;
132-
}
133-
134-
match &expr.kind {
135-
hir::ExprKind::Path(qpath) => {
136-
let def_id = if let Some(def_id) = enum_def_id {
137-
def_id
138-
} else {
139-
def_id
140-
};
141-
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind {
142-
for segment in path.segments {
143-
if let Some(param) = variant_param_to_point_at
144-
&& self.point_at_generic_if_possible(error, def_id, param, segment)
145-
{
146-
return true;
147-
}
148-
}
121+
let hir = self.tcx.hir();
122+
let (expr, qpath) = match hir.get(hir_id) {
123+
hir::Node::Expr(expr) => {
124+
if self.closure_span_overlaps_error(error, expr.span) {
125+
return false;
149126
}
150-
if let hir::Node::Expr(hir::Expr {
151-
kind: hir::ExprKind::Call(callee, args),
152-
hir_id: call_hir_id,
153-
span: call_span,
154-
..
155-
}) = hir.get_parent(expr.hir_id)
156-
&& callee.hir_id == expr.hir_id
157-
{
158-
if self.closure_span_overlaps_error(error, *call_span) {
159-
return false;
160-
}
127+
let qpath =
128+
if let hir::ExprKind::Path(qpath) = expr.kind { Some(qpath) } else { None };
161129

162-
for param in
163-
[param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
164-
.into_iter()
165-
.flatten()
130+
(Some(*expr), qpath)
131+
}
132+
hir::Node::Ty(hir::Ty { kind: hir::TyKind::Path(qpath), .. }) => (None, Some(*qpath)),
133+
_ => return false,
134+
};
135+
136+
if let Some(qpath) = qpath {
137+
let def_id = if let Some(def_id) = enum_def_id { def_id } else { def_id };
138+
if let hir::QPath::Resolved(None, path) = qpath {
139+
for segment in path.segments {
140+
if let Some(param) = variant_param_to_point_at
141+
&& self.point_at_generic_if_possible(error, def_id, param, segment)
166142
{
167-
if self.blame_specific_arg_if_possible(
168-
error,
169-
def_id,
170-
param,
171-
*call_hir_id,
172-
callee.span,
173-
None,
174-
args,
175-
)
176-
{
177-
return true;
178-
}
143+
return true;
179144
}
180145
}
146+
}
147+
if let hir::QPath::TypeRelative(_ty, segment) = qpath {
148+
if let Some(param) = variant_param_to_point_at
149+
&& self.point_at_generic_if_possible(error, def_id, param, segment)
150+
{
151+
return true;
152+
}
153+
}
154+
if let hir::Node::Expr(hir::Expr {
155+
kind: hir::ExprKind::Call(callee, args),
156+
hir_id: call_hir_id,
157+
span: call_span,
158+
..
159+
}) = hir.get_parent(hir_id)
160+
&& callee.hir_id == hir_id
161+
{
162+
if self.closure_span_overlaps_error(error, *call_span) {
163+
return false;
164+
}
181165

182-
for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
166+
for param in
167+
[param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
183168
.into_iter()
184169
.flatten()
185170
{
186-
if self.point_at_path_if_possible(error, def_id, param, qpath) {
171+
if self.blame_specific_arg_if_possible(
172+
error,
173+
def_id,
174+
param,
175+
*call_hir_id,
176+
callee.span,
177+
None,
178+
args,
179+
)
180+
{
187181
return true;
188182
}
189183
}
190184
}
191-
hir::ExprKind::MethodCall(segment, receiver, args, ..) => {
185+
186+
for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
187+
.into_iter()
188+
.flatten()
189+
{
190+
if self.point_at_path_if_possible(error, def_id, param, &qpath) {
191+
return true;
192+
}
193+
}
194+
}
195+
196+
match expr.map(|e| e.kind) {
197+
Some(hir::ExprKind::MethodCall(segment, receiver, args, ..)) => {
192198
for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
193199
.into_iter()
194200
.flatten()
@@ -220,7 +226,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
220226
return true;
221227
}
222228
}
223-
hir::ExprKind::Struct(qpath, fields, ..) => {
229+
Some(hir::ExprKind::Struct(qpath, fields, ..)) => {
224230
if let Res::Def(DefKind::Struct | DefKind::Variant, variant_def_id) =
225231
self.typeck_results.borrow().qpath_res(qpath, hir_id)
226232
{

compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,17 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
317317

318318
fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span) {
319319
// FIXME: normalization and escaping regions
320-
let ty = if !ty.has_escaping_bound_vars() { self.normalize(span, ty) } else { ty };
320+
let ty = if !ty.has_escaping_bound_vars() {
321+
if let ty::Alias(ty::AliasKind::Projection, ty::AliasTy { args, def_id, .. }) =
322+
ty.kind()
323+
{
324+
self.add_required_obligations_for_hir(span, *def_id, args, hir_id);
325+
self.select_obligations_where_possible(|_| {});
326+
}
327+
self.normalize(span, ty)
328+
} else {
329+
ty
330+
};
321331
self.write_ty(hir_id, ty)
322332
}
323333

tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ trait Foo<T> {
99
fn f<T:Foo<isize>>(t: &T) {
1010
let u: <T as Foo<usize>>::Bar = t.get_bar();
1111
//~^ ERROR the trait bound `T: Foo<usize>` is not satisfied
12+
//~| ERROR the trait bound `T: Foo<usize>` is not satisfied
1213
}
1314

1415
fn main() { }

tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
error[E0277]: the trait bound `T: Foo<usize>` is not satisfied
2+
--> $DIR/associated-types-invalid-trait-ref-issue-18865.rs:10:22
3+
|
4+
LL | let u: <T as Foo<usize>>::Bar = t.get_bar();
5+
| ^^^^^ the trait `Foo<usize>` is not implemented for `T`
6+
|
7+
help: consider further restricting this bound
8+
|
9+
LL | fn f<T:Foo<isize> + Foo<usize>>(t: &T) {
10+
| ++++++++++++
11+
112
error[E0277]: the trait bound `T: Foo<usize>` is not satisfied
213
--> $DIR/associated-types-invalid-trait-ref-issue-18865.rs:10:12
314
|
@@ -9,6 +20,6 @@ help: consider further restricting this bound
920
LL | fn f<T:Foo<isize> + Foo<usize>>(t: &T) {
1021
| ++++++++++++
1122

12-
error: aborting due to previous error
23+
error: aborting due to 2 previous errors
1324

1425
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
trait Trait {
2+
type P<T: Copy, U: Copy>;
3+
}
4+
impl Trait for () {
5+
type P<T: Copy, U: Copy> = ();
6+
}
7+
fn main() {
8+
let _: <() as Trait>::P<String, String>;
9+
//~^ ERROR the trait bound `String: Copy` is not satisfied
10+
//~| ERROR the trait bound `String: Copy` is not satisfied
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0277]: the trait bound `String: Copy` is not satisfied
2+
--> $DIR/multiple-type-params-with-unmet-bounds.rs:8:29
3+
|
4+
LL | let _: <() as Trait>::P<String, String>;
5+
| ^^^^^^ the trait `Copy` is not implemented for `String`
6+
|
7+
note: required by a bound in `Trait::P`
8+
--> $DIR/multiple-type-params-with-unmet-bounds.rs:2:15
9+
|
10+
LL | type P<T: Copy, U: Copy>;
11+
| ^^^^ required by this bound in `Trait::P`
12+
13+
error[E0277]: the trait bound `String: Copy` is not satisfied
14+
--> $DIR/multiple-type-params-with-unmet-bounds.rs:8:12
15+
|
16+
LL | let _: <() as Trait>::P<String, String>;
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
18+
|
19+
note: required by a bound in `Trait::P`
20+
--> $DIR/multiple-type-params-with-unmet-bounds.rs:2:15
21+
|
22+
LL | type P<T: Copy, U: Copy>;
23+
| ^^^^ required by this bound in `Trait::P`
24+
25+
error: aborting due to 2 previous errors
26+
27+
For more information about this error, try `rustc --explain E0277`.

tests/ui/generic-associated-types/own-bound-span.rs

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ trait D {
44
type P<T: Copy>;
55
//~^ NOTE required by this bound in `D::P`
66
//~| NOTE required by a bound in `D::P`
7+
//~| NOTE required by this bound in `D::P`
8+
//~| NOTE required by a bound in `D::P`
79
}
810

911
impl D for S {
@@ -14,4 +16,6 @@ fn main() {
1416
let _: <S as D>::P<String>;
1517
//~^ ERROR the trait bound `String: Copy` is not satisfied
1618
//~| NOTE the trait `Copy` is not implemented for `String`
19+
//~| ERROR the trait bound `String: Copy` is not satisfied
20+
//~| NOTE the trait `Copy` is not implemented for `String`
1721
}

tests/ui/generic-associated-types/own-bound-span.stderr

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
error[E0277]: the trait bound `String: Copy` is not satisfied
2-
--> $DIR/own-bound-span.rs:14:12
2+
--> $DIR/own-bound-span.rs:16:24
3+
|
4+
LL | let _: <S as D>::P<String>;
5+
| ^^^^^^ the trait `Copy` is not implemented for `String`
6+
|
7+
note: required by a bound in `D::P`
8+
--> $DIR/own-bound-span.rs:4:15
9+
|
10+
LL | type P<T: Copy>;
11+
| ^^^^ required by this bound in `D::P`
12+
13+
error[E0277]: the trait bound `String: Copy` is not satisfied
14+
--> $DIR/own-bound-span.rs:16:12
315
|
416
LL | let _: <S as D>::P<String>;
517
| ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
@@ -10,6 +22,6 @@ note: required by a bound in `D::P`
1022
LL | type P<T: Copy>;
1123
| ^^^^ required by this bound in `D::P`
1224

13-
error: aborting due to previous error
25+
error: aborting due to 2 previous errors
1426

1527
For more information about this error, try `rustc --explain E0277`.

tests/ui/issues/issue-66353.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ trait _A {
1111
fn main() {
1212
_Func::< <() as _A>::AssocT >::func(());
1313
//~^ ERROR the trait bound `(): _A` is not satisfied
14+
//~| ERROR the trait bound `(): _A` is not satisfied
1415
//~| ERROR the trait bound `(): _Func<_>` is not satisfied
1516
}

tests/ui/issues/issue-66353.stderr

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
error[E0277]: the trait bound `(): _A` is not satisfied
2+
--> $DIR/issue-66353.rs:12:15
3+
|
4+
LL | _Func::< <() as _A>::AssocT >::func(());
5+
| ^^ the trait `_A` is not implemented for `()`
6+
17
error[E0277]: the trait bound `(): _A` is not satisfied
28
--> $DIR/issue-66353.rs:12:14
39
|
@@ -12,6 +18,6 @@ LL | _Func::< <() as _A>::AssocT >::func(());
1218
| |
1319
| required by a bound introduced by this call
1420

15-
error: aborting due to 2 previous errors
21+
error: aborting due to 3 previous errors
1622

1723
For more information about this error, try `rustc --explain E0277`.

tests/ui/object-safety/assoc_type_bounds_sized_used.rs

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ fn bop<T: Bop + ?Sized>() {
1212
let _ = <T as Bop>::Bar::default();
1313
//~^ ERROR: trait bounds were not satisfied
1414
//~| ERROR: the size for values of type `T` cannot be known at compilation time
15+
//~| ERROR: the size for values of type `T` cannot be known at compilation time
1516
}
1617

1718
fn main() {

0 commit comments

Comments
 (0)