1
Fork 0

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.
This commit is contained in:
Matthias Krüger 2023-03-02 23:05:28 +01:00 committed by GitHub
commit 564715a5b7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 463 additions and 8 deletions

View file

@ -714,12 +714,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.parent(expr_ctor_def_id)
}
hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => {
// If this is a variant, its parent is the type definition.
if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) {
// For a typical enum like
// `enum Blah<T> { Variant(T) }`
// we get the following resolutions:
// - expr_ctor_def_id ::: DefId(0:29 ~ source_file[b442]::Blah::Variant::{constructor#0})
// - self.tcx.parent(expr_ctor_def_id) ::: DefId(0:28 ~ source_file[b442]::Blah::Variant)
// - self.tcx.parent(self.tcx.parent(expr_ctor_def_id)) ::: DefId(0:26 ~ source_file[b442]::Blah)
// Therefore, we need to go up once to obtain the variant and up twice to obtain the type.
// Note that this pattern still holds even when we `use` a variant or `use` an enum type to rename it, or chain `use` expressions
// together; this resolution is handled automatically by `qpath_res`.
// FIXME: Deal with type aliases?
if in_ty_adt.did() == self.tcx.parent(self.tcx.parent(expr_ctor_def_id)) {
// The constructor definition refers to the "constructor" of the variant:
// For example, `Some(5)` triggers this case.
self.tcx.parent(expr_ctor_def_id)
} else {
// FIXME: Deal with type aliases?
return Err(expr);
}
expr_ctor_def_id
}
_ => {
return Err(expr);