Skip to content

Commit a411304

Browse files
committed
add test and address some nits
1 parent 46c582d commit a411304

File tree

4 files changed

+142
-38
lines changed

4 files changed

+142
-38
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -524,11 +524,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
524524
// Sometimes macros mess up the spans, so do not normalize the
525525
// arg span to equal the error span, because that's less useful
526526
// than pointing out the arg expr in the wrong context.
527-
if normalized_span.source_equal(error_span) {
528-
span
529-
} else {
530-
normalized_span
531-
}
527+
if normalized_span.source_equal(error_span) { span } else { normalized_span }
532528
};
533529

534530
// Precompute the provided types and spans, since that's all we typically need for below
@@ -781,8 +777,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
781777
// can be collated pretty easily if needed.
782778

783779
// Next special case: if there is only one "Incompatible" error, just emit that
784-
if let [Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(err)))] =
785-
&errors[..]
780+
if let [
781+
Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(err))),
782+
] = &errors[..]
786783
{
787784
let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx];
788785
let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx];
@@ -1524,21 +1521,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15241521
// Our block must be a `assign desugar local; assignment`
15251522
if let Some(hir::Node::Block(hir::Block {
15261523
stmts:
1527-
[hir::Stmt {
1528-
kind:
1529-
hir::StmtKind::Local(hir::Local {
1530-
source: hir::LocalSource::AssignDesugar(_),
1531-
..
1532-
}),
1533-
..
1534-
}, hir::Stmt {
1535-
kind:
1536-
hir::StmtKind::Expr(hir::Expr {
1537-
kind: hir::ExprKind::Assign(..),
1538-
..
1539-
}),
1540-
..
1541-
}],
1524+
[
1525+
hir::Stmt {
1526+
kind:
1527+
hir::StmtKind::Local(hir::Local {
1528+
source:
1529+
hir::LocalSource::AssignDesugar(_),
1530+
..
1531+
}),
1532+
..
1533+
},
1534+
hir::Stmt {
1535+
kind:
1536+
hir::StmtKind::Expr(hir::Expr {
1537+
kind: hir::ExprKind::Assign(..),
1538+
..
1539+
}),
1540+
..
1541+
},
1542+
],
15421543
..
15431544
})) = self.tcx.hir().find(blk.hir_id)
15441545
{
@@ -2129,13 +2130,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21292130
// field which can be "blamed" for the missing trait, so that it can be highlighted.
21302131
match expr.kind {
21312132
hir::ExprKind::Struct(
2132-
hir::QPath::Resolved(
2133-
_,
2134-
hir::Path { res: hir::def::Res::Def(struct_def_kind, struct_def_id), .. },
2135-
),
2133+
struct_path,
21362134
struct_fields,
21372135
_, // NOTE: "Rest" fields in structs are currently ignored by this function.
21382136
) => {
2137+
// FIXME: No attempt is currently made to resolve type aliases.
2138+
let Res::Def(struct_def_kind, struct_def_id) = self.typeck_results.borrow().qpath_res(struct_path, expr.hir_id) else {
2139+
return Err(expr);
2140+
};
2141+
21392142
let PointableType::Adt(impl_self_ty_path) = impl_self_ty else {
21402143
// An Adt expression requires an Adt type and vice-versa.
21412144
return Err(expr);
@@ -2144,7 +2147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21442147
let (struct_variant_def, struct_def_generics): (&ty::VariantDef, &ty::Generics) =
21452148
match struct_def_kind {
21462149
hir::def::DefKind::Struct => {
2147-
if &impl_self_ty_path.did() != struct_def_id {
2150+
if impl_self_ty_path.did() != struct_def_id {
21482151
// If the struct is not the same as `Self`, we cannot refine.
21492152
return Err(expr);
21502153
}
@@ -2164,7 +2167,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21642167
(struct_variant_defs[0], struct_def_generics)
21652168
}
21662169
hir::def::DefKind::Variant => {
2167-
let variant_def_id = *struct_def_id;
2170+
let variant_def_id = struct_def_id;
21682171
let struct_def_id = self.tcx.parent(variant_def_id);
21692172

21702173
if impl_self_ty_path.did() != struct_def_id {

compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2556,9 +2556,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
25562556
debug!(?predicates);
25572557
assert_eq!(predicates.0.parent, None);
25582558
let mut obligations = Vec::with_capacity(predicates.0.predicates.len());
2559-
for (index, (predicate, span)) in
2560-
predicates.0.predicates.into_iter().enumerate()
2561-
{
2559+
for (index, (predicate, span)) in predicates.0.predicates.into_iter().enumerate() {
25622560
let span = *span;
25632561
let cause = cause.clone().derived_cause(parent_trait_pred, |derived| {
25642562
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {

src/test/ui/traits/bad-trait-error-span-in-call.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,19 @@ impl<A: T3, B: T3> T2 for (A, B) {}
5151

5252
fn want<V: T1>(_x: V) {}
5353

54+
// Some more-complex examples:
55+
type AliasBurrito<T> = GenericBurrito<T, T>;
56+
57+
// The following example is fairly confusing. The idea is that we want to "misdirect" the location
58+
// of the error.
59+
60+
struct Two<A, B> {
61+
a: A,
62+
b: B,
63+
}
64+
65+
impl<X, Y: T1, Z> T1 for Two<Two<X, Y>, Z> {}
66+
5467
fn example<Q>(q: Q) {
5568
// In each of the following examples, we expect the error span to point at the 'q' variable,
5669
// since the missing constraint is `Q: T3`.
@@ -78,6 +91,20 @@ fn example<Q>(q: Q) {
7891
// Verifies for tuple:
7992
want(Wrapper { value: (3, q) });
8093
//~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
94+
95+
// Verifies for type alias to struct:
96+
want(Wrapper { value: AliasBurrito { spiciness: q, filling: q } });
97+
//~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
98+
99+
want(Two { a: Two { a: (), b: q }, b: () });
100+
//~^ ERROR the trait bound `Q: T1` is not satisfied [E0277]
101+
102+
// We *should* blame the 'q'.
103+
// FIXME: Right now, the wrong field is blamed.
104+
want(
105+
Two { a: Two { a: (), b: Two { a: Two { a: (), b: q }, b: () } }, b: () },
106+
//~^ ERROR the trait bound `Q: T1` is not satisfied [E0277]
107+
);
81108
}
82109

83110
fn main() {}

src/test/ui/traits/bad-trait-error-span-in-call.stderr

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0277]: the trait bound `Q: T3` is not satisfied
2-
--> $DIR/bad-trait-error-span-in-call.rs:59:60
2+
--> $DIR/bad-trait-error-span-in-call.rs:72:60
33
|
44
LL | want(Wrapper { value: Burrito { spicy: false, filling: q } });
55
| ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
@@ -25,7 +25,7 @@ LL | fn example<Q: T3>(q: Q) {
2525
| ++++
2626

2727
error[E0277]: the trait bound `Q: T3` is not satisfied
28-
--> $DIR/bad-trait-error-span-in-call.rs:63:84
28+
--> $DIR/bad-trait-error-span-in-call.rs:76:84
2929
|
3030
LL | want(Wrapper { value: BurritoKinds::SmallBurrito { spicy: true, small_filling: q } });
3131
| ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
@@ -51,7 +51,7 @@ LL | fn example<Q: T3>(q: Q) {
5151
| ++++
5252

5353
error[E0277]: the trait bound `Q: T3` is not satisfied
54-
--> $DIR/bad-trait-error-span-in-call.rs:67:39
54+
--> $DIR/bad-trait-error-span-in-call.rs:80:39
5555
|
5656
LL | want(Wrapper { value: Taco(false, q) });
5757
| ---- ^ the trait `T3` is not implemented for `Q`
@@ -79,7 +79,7 @@ LL | fn example<Q: T3>(q: Q) {
7979
| ++++
8080

8181
error[E0277]: the trait bound `Q: T3` is not satisfied
82-
--> $DIR/bad-trait-error-span-in-call.rs:71:53
82+
--> $DIR/bad-trait-error-span-in-call.rs:84:53
8383
|
8484
LL | want(Wrapper { value: TacoKinds::OneTaco(false, q) });
8585
| ---- ^ the trait `T3` is not implemented for `Q`
@@ -107,7 +107,7 @@ LL | fn example<Q: T3>(q: Q) {
107107
| ++++
108108

109109
error[E0277]: the trait bound `Q: T3` is not satisfied
110-
--> $DIR/bad-trait-error-span-in-call.rs:75:74
110+
--> $DIR/bad-trait-error-span-in-call.rs:88:74
111111
|
112112
LL | want(Wrapper { value: GenericBurrito { spiciness: NotSpicy, filling: q } });
113113
| ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
@@ -133,7 +133,7 @@ LL | fn example<Q: T3>(q: Q) {
133133
| ++++
134134

135135
error[E0277]: the trait bound `Q: T3` is not satisfied
136-
--> $DIR/bad-trait-error-span-in-call.rs:79:31
136+
--> $DIR/bad-trait-error-span-in-call.rs:92:31
137137
|
138138
LL | want(Wrapper { value: (3, q) });
139139
| ---- ^ the trait `T3` is not implemented for `Q`
@@ -160,6 +160,82 @@ help: consider restricting type parameter `Q`
160160
LL | fn example<Q: T3>(q: Q) {
161161
| ++++
162162

163-
error: aborting due to 6 previous errors
163+
error[E0277]: the trait bound `Q: T3` is not satisfied
164+
--> $DIR/bad-trait-error-span-in-call.rs:96:27
165+
|
166+
LL | want(Wrapper { value: AliasBurrito { spiciness: q, filling: q } });
167+
| ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q`
168+
| |
169+
| required by a bound introduced by this call
170+
|
171+
note: required for `GenericBurrito<Q, Q>` to implement `T2`
172+
--> $DIR/bad-trait-error-span-in-call.rs:47:16
173+
|
174+
LL | impl<X, Y: T3> T2 for GenericBurrito<X, Y> {}
175+
| ^^ ^^^^^^^^^^^^^^^^^^^^
176+
note: required for `Wrapper<GenericBurrito<Q, Q>>` to implement `T1`
177+
--> $DIR/bad-trait-error-span-in-call.rs:16:13
178+
|
179+
LL | impl<B: T2> T1 for Wrapper<B> {}
180+
| ^^ ^^^^^^^^^^
181+
note: required by a bound in `want`
182+
--> $DIR/bad-trait-error-span-in-call.rs:52:12
183+
|
184+
LL | fn want<V: T1>(_x: V) {}
185+
| ^^ required by this bound in `want`
186+
help: consider restricting type parameter `Q`
187+
|
188+
LL | fn example<Q: T3>(q: Q) {
189+
| ++++
190+
191+
error[E0277]: the trait bound `Q: T1` is not satisfied
192+
--> $DIR/bad-trait-error-span-in-call.rs:99:19
193+
|
194+
LL | want(Two { a: Two { a: (), b: q }, b: () });
195+
| ---- ^^^^^^^^^^^^^^^^^^^ the trait `T1` is not implemented for `Q`
196+
| |
197+
| required by a bound introduced by this call
198+
|
199+
note: required for `Two<Two<(), Q>, ()>` to implement `T1`
200+
--> $DIR/bad-trait-error-span-in-call.rs:65:19
201+
|
202+
LL | impl<X, Y: T1, Z> T1 for Two<Two<X, Y>, Z> {}
203+
| ^^ ^^^^^^^^^^^^^^^^^
204+
note: required by a bound in `want`
205+
--> $DIR/bad-trait-error-span-in-call.rs:52:12
206+
|
207+
LL | fn want<V: T1>(_x: V) {}
208+
| ^^ required by this bound in `want`
209+
help: consider restricting type parameter `Q`
210+
|
211+
LL | fn example<Q: T1>(q: Q) {
212+
| ++++
213+
214+
error[E0277]: the trait bound `Q: T1` is not satisfied
215+
--> $DIR/bad-trait-error-span-in-call.rs:105:27
216+
|
217+
LL | want(
218+
| ---- required by a bound introduced by this call
219+
LL | Two { a: Two { a: (), b: Two { a: Two { a: (), b: q }, b: () } }, b: () },
220+
| ^^ the trait `T1` is not implemented for `Q`
221+
|
222+
note: required for `Two<Two<(), Q>, ()>` to implement `T1`
223+
--> $DIR/bad-trait-error-span-in-call.rs:65:19
224+
|
225+
LL | impl<X, Y: T1, Z> T1 for Two<Two<X, Y>, Z> {}
226+
| ^^ ^^^^^^^^^^^^^^^^^
227+
= note: 1 redundant requirement hidden
228+
= note: required for `Two<Two<(), Two<Two<(), Q>, ()>>, ()>` to implement `T1`
229+
note: required by a bound in `want`
230+
--> $DIR/bad-trait-error-span-in-call.rs:52:12
231+
|
232+
LL | fn want<V: T1>(_x: V) {}
233+
| ^^ required by this bound in `want`
234+
help: consider restricting type parameter `Q`
235+
|
236+
LL | fn example<Q: T1>(q: Q) {
237+
| ++++
238+
239+
error: aborting due to 9 previous errors
164240

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

0 commit comments

Comments
 (0)