Skip to content

Commit 564715a

Browse files
authored
Rollup merge of #108557 - Nathan-Fenner:nathanf/adjust-error-span-fix-Some, r=WaffleLapkin
Point error span at Some constructor argument when trait resolution fails This is a follow up to #108254 and #106477 which extends error span refinement to handle a case which I mistakenly believed was handled in #106477. The goal is to refine the error span depicted below: ```rs trait Fancy {} impl <T> Fancy for Option<T> where T: Iterator {} fn want_fancy<F>(f: F) where F: Fancy {} fn example() { want_fancy(Some(5)); // (BEFORE) ^^^^^^^ `{integer}` is not an iterator // (AFTER) ^ `{integer}` is not an iterator } ``` I had used a (slightly more complex) example as an illustrative example in #108254 , but hadn't actually turned it into a test, because I had (incorrectly) believed at the time it was covered by existing behavior. It turns out that `Some` is slightly "special" in that it resolves differently from the other `enum` constructors I had tried, and therefore this test was actually broken. I've now updated the tests to include this example, and fixed the code to correctly resolve the `Some` constructor so that the span of the error is reduced.
2 parents a27a4e4 + be15f17 commit 564715a

File tree

4 files changed

+463
-8
lines changed

4 files changed

+463
-8
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -714,12 +714,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
714714
self.tcx.parent(expr_ctor_def_id)
715715
}
716716
hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => {
717-
// If this is a variant, its parent is the type definition.
718-
if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) {
717+
// For a typical enum like
718+
// `enum Blah<T> { Variant(T) }`
719+
// we get the following resolutions:
720+
// - expr_ctor_def_id ::: DefId(0:29 ~ source_file[b442]::Blah::Variant::{constructor#0})
721+
// - self.tcx.parent(expr_ctor_def_id) ::: DefId(0:28 ~ source_file[b442]::Blah::Variant)
722+
// - self.tcx.parent(self.tcx.parent(expr_ctor_def_id)) ::: DefId(0:26 ~ source_file[b442]::Blah)
723+
724+
// Therefore, we need to go up once to obtain the variant and up twice to obtain the type.
725+
// Note that this pattern still holds even when we `use` a variant or `use` an enum type to rename it, or chain `use` expressions
726+
// together; this resolution is handled automatically by `qpath_res`.
727+
728+
// FIXME: Deal with type aliases?
729+
if in_ty_adt.did() == self.tcx.parent(self.tcx.parent(expr_ctor_def_id)) {
730+
// The constructor definition refers to the "constructor" of the variant:
731+
// For example, `Some(5)` triggers this case.
732+
self.tcx.parent(expr_ctor_def_id)
733+
} else {
719734
// FIXME: Deal with type aliases?
720735
return Err(expr);
721736
}
722-
expr_ctor_def_id
723737
}
724738
_ => {
725739
return Err(expr);

tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs

+74
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,85 @@ struct Burrito<F> {
1818
filling: F,
1919
}
2020

21+
impl<It: Iterator> T1 for Option<It> {}
22+
23+
impl<'a, A: T1> T1 for &'a A {}
24+
2125
fn want<V: T1>(_x: V) {}
2226

27+
enum ExampleTuple<T> {
28+
ExampleTupleVariant(T),
29+
}
30+
use ExampleDifferentTupleVariantName as ExampleYetAnotherTupleVariantName;
31+
use ExampleTuple as ExampleOtherTuple;
32+
use ExampleTuple::ExampleTupleVariant as ExampleDifferentTupleVariantName;
33+
use ExampleTuple::*;
34+
35+
impl<A> T1 for ExampleTuple<A> where A: T3 {}
36+
37+
enum ExampleStruct<T> {
38+
ExampleStructVariant { field: T },
39+
}
40+
use ExampleDifferentStructVariantName as ExampleYetAnotherStructVariantName;
41+
use ExampleStruct as ExampleOtherStruct;
42+
use ExampleStruct::ExampleStructVariant as ExampleDifferentStructVariantName;
43+
use ExampleStruct::*;
44+
45+
impl<A> T1 for ExampleStruct<A> where A: T3 {}
46+
47+
struct ExampleActuallyTupleStruct<T>(T, i32);
48+
use ExampleActuallyTupleStruct as ExampleActuallyTupleStructOther;
49+
50+
impl<A> T1 for ExampleActuallyTupleStruct<A> where A: T3 {}
51+
2352
fn example<Q>(q: Q) {
2453
want(Wrapper { value: Burrito { filling: q } });
2554
//~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
55+
56+
want(Some(()));
57+
//~^ ERROR `()` is not an iterator [E0277]
58+
59+
want(Some(q));
60+
//~^ ERROR `Q` is not an iterator [E0277]
61+
62+
want(&Some(q));
63+
//~^ ERROR `Q` is not an iterator [E0277]
64+
65+
want(&ExampleTuple::ExampleTupleVariant(q));
66+
//~^ ERROR `Q: T3` is not satisfied [E0277]
67+
68+
want(&ExampleTupleVariant(q));
69+
//~^ ERROR `Q: T3` is not satisfied [E0277]
70+
71+
want(&ExampleOtherTuple::ExampleTupleVariant(q));
72+
//~^ ERROR `Q: T3` is not satisfied [E0277]
73+
74+
want(&ExampleDifferentTupleVariantName(q));
75+
//~^ ERROR `Q: T3` is not satisfied [E0277]
76+
77+
want(&ExampleYetAnotherTupleVariantName(q));
78+
//~^ ERROR `Q: T3` is not satisfied [E0277]
79+
80+
want(&ExampleStruct::ExampleStructVariant { field: q });
81+
//~^ ERROR `Q: T3` is not satisfied [E0277]
82+
83+
want(&ExampleStructVariant { field: q });
84+
//~^ ERROR `Q: T3` is not satisfied [E0277]
85+
86+
want(&ExampleOtherStruct::ExampleStructVariant { field: q });
87+
//~^ ERROR `Q: T3` is not satisfied [E0277]
88+
89+
want(&ExampleDifferentStructVariantName { field: q });
90+
//~^ ERROR `Q: T3` is not satisfied [E0277]
91+
92+
want(&ExampleYetAnotherStructVariantName { field: q });
93+
//~^ ERROR `Q: T3` is not satisfied [E0277]
94+
95+
want(&ExampleActuallyTupleStruct(q, 0));
96+
//~^ ERROR `Q: T3` is not satisfied [E0277]
97+
98+
want(&ExampleActuallyTupleStructOther(q, 0));
99+
//~^ ERROR `Q: T3` is not satisfied [E0277]
26100
}
27101

28102
fn main() {}

0 commit comments

Comments
 (0)