Skip to content

Commit 23f3b0d

Browse files
Don't point at another arg if we're already pointing at one
1 parent 7533777 commit 23f3b0d

File tree

5 files changed

+77
-18
lines changed

5 files changed

+77
-18
lines changed

compiler/rustc_typeck/src/check/fn_ctxt/checks.rs

+30-8
Original file line numberDiff line numberDiff line change
@@ -1629,7 +1629,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16291629
return;
16301630
}
16311631

1632-
for error in errors {
1632+
'outer: for error in errors {
16331633
// Only if the cause is somewhere inside the expression we want try to point at arg.
16341634
// Otherwise, it means that the cause is somewhere else and we should not change
16351635
// anything because we can break the correct span.
@@ -1671,10 +1671,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16711671
_ => continue,
16721672
};
16731673
let self_ = self.resolve_vars_if_possible(self_);
1674+
let ty_matches_self = |ty: Ty<'tcx>| ty.walk().any(|arg| arg == self_);
1675+
1676+
let typeck_results = self.typeck_results.borrow();
1677+
1678+
for (idx, arg) in args.iter().enumerate() {
1679+
// Don't adjust the span if we already have a more precise span
1680+
// within one of the args.
1681+
if arg.span.contains(error.obligation.cause.span) {
1682+
let references_arg =
1683+
typeck_results.expr_ty_opt(arg).map_or(false, &ty_matches_self)
1684+
|| expected_tys.get(idx).copied().map_or(false, &ty_matches_self);
1685+
if references_arg && !arg.span.from_expansion() {
1686+
error.obligation.cause.map_code(|parent_code| {
1687+
ObligationCauseCode::FunctionArgumentObligation {
1688+
arg_hir_id: args[idx].hir_id,
1689+
call_hir_id: expr.hir_id,
1690+
parent_code,
1691+
}
1692+
})
1693+
}
1694+
continue 'outer;
1695+
}
1696+
}
16741697

16751698
// Collect the argument position for all arguments that could have caused this
16761699
// `FulfillmentError`.
1677-
let typeck_results = self.typeck_results.borrow();
16781700
let mut referenced_in: Vec<_> = std::iter::zip(expected_tys, args)
16791701
.enumerate()
16801702
.flat_map(|(idx, (expected_ty, arg))| {
@@ -1688,7 +1710,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16881710
let ty = self.resolve_vars_if_possible(ty);
16891711
// We walk the argument type because the argument's type could have
16901712
// been `Option<T>`, but the `FulfillmentError` references `T`.
1691-
if ty.walk().any(|arg| arg == self_) { Some(i) } else { None }
1713+
if ty_matches_self(ty) { Some(i) } else { None }
16921714
})
16931715
.collect();
16941716

@@ -1699,18 +1721,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16991721
referenced_in.sort_unstable();
17001722
referenced_in.dedup();
17011723

1702-
if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) {
1724+
if let &[idx] = &referenced_in[..] {
17031725
// Do not point at the inside of a macro.
17041726
// That would often result in poor error messages.
1705-
if args[ref_in].span.from_expansion() {
1706-
return;
1727+
if args[idx].span.from_expansion() {
1728+
continue;
17071729
}
17081730
// We make sure that only *one* argument matches the obligation failure
17091731
// and we assign the obligation's span to its expression's.
1710-
error.obligation.cause.span = args[ref_in].span;
1732+
error.obligation.cause.span = args[idx].span;
17111733
error.obligation.cause.map_code(|parent_code| {
17121734
ObligationCauseCode::FunctionArgumentObligation {
1713-
arg_hir_id: args[ref_in].hir_id,
1735+
arg_hir_id: args[idx].hir_id,
17141736
call_hir_id: expr.hir_id,
17151737
parent_code,
17161738
}

src/test/ui/proc-macro/signature.stderr

+1-4
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@ LL | / pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
55
LL | |
66
LL | | loop {}
77
LL | | }
8-
| | ^
9-
| | |
10-
| |_call the function in a closure: `|| unsafe { /* code */ }`
11-
| required by a bound introduced by this call
8+
| |_^ call the function in a closure: `|| unsafe { /* code */ }`
129
|
1310
= help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
1411
= note: unsafe function cannot be called generically without an unsafe block

src/test/ui/unsized/unsized-fn-param.stderr

+12-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
22
--> $DIR/unsized-fn-param.rs:11:11
33
|
44
LL | foo11("bar", &"baz");
5-
| ^^^^^ doesn't have a size known at compile-time
5+
| ----- ^^^^^ doesn't have a size known at compile-time
6+
| |
7+
| required by a bound introduced by this call
68
|
79
= help: the trait `Sized` is not implemented for `str`
810
= note: required for the cast to the object type `dyn AsRef<Path>`
@@ -15,7 +17,9 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
1517
--> $DIR/unsized-fn-param.rs:13:19
1618
|
1719
LL | foo12(&"bar", "baz");
18-
| ^^^^^ doesn't have a size known at compile-time
20+
| ----- ^^^^^ doesn't have a size known at compile-time
21+
| |
22+
| required by a bound introduced by this call
1923
|
2024
= help: the trait `Sized` is not implemented for `str`
2125
= note: required for the cast to the object type `dyn AsRef<Path>`
@@ -28,7 +32,9 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
2832
--> $DIR/unsized-fn-param.rs:16:11
2933
|
3034
LL | foo21("bar", &"baz");
31-
| ^^^^^ doesn't have a size known at compile-time
35+
| ----- ^^^^^ doesn't have a size known at compile-time
36+
| |
37+
| required by a bound introduced by this call
3238
|
3339
= help: the trait `Sized` is not implemented for `str`
3440
= note: required for the cast to the object type `dyn AsRef<str>`
@@ -41,7 +47,9 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
4147
--> $DIR/unsized-fn-param.rs:18:19
4248
|
4349
LL | foo22(&"bar", "baz");
44-
| ^^^^^ doesn't have a size known at compile-time
50+
| ----- ^^^^^ doesn't have a size known at compile-time
51+
| |
52+
| required by a bound introduced by this call
4553
|
4654
= help: the trait `Sized` is not implemented for `str`
4755
= note: required for the cast to the object type `dyn AsRef<str>`

src/test/ui/unsized/unsized3.rs

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ fn f9<X: ?Sized>(x1: Box<S<X>>) {
4444
fn f10<X: ?Sized>(x1: Box<S<X>>) {
4545
f5(&(32, *x1));
4646
//~^ ERROR the size for values of type
47+
//~| ERROR the size for values of type
4748
}
4849

4950
pub fn main() {}

src/test/ui/unsized/unsized3.stderr

+33-2
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,29 @@ LL - fn f9<X: ?Sized>(x1: Box<S<X>>) {
100100
LL + fn f9<X>(x1: Box<S<X>>) {
101101
|
102102

103+
error[E0277]: the size for values of type `X` cannot be known at compilation time
104+
--> $DIR/unsized3.rs:45:9
105+
|
106+
LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
107+
| - this type parameter needs to be `std::marker::Sized`
108+
LL | f5(&(32, *x1));
109+
| -- ^^^^^^^^^ doesn't have a size known at compile-time
110+
| |
111+
| required by a bound introduced by this call
112+
|
113+
note: required because it appears within the type `S<X>`
114+
--> $DIR/unsized3.rs:28:8
115+
|
116+
LL | struct S<X: ?Sized> {
117+
| ^
118+
= note: required because it appears within the type `({integer}, S<X>)`
119+
= note: tuples must have a statically known size to be initialized
120+
help: consider removing the `?Sized` bound to make the type parameter `Sized`
121+
|
122+
LL - fn f10<X: ?Sized>(x1: Box<S<X>>) {
123+
LL + fn f10<X>(x1: Box<S<X>>) {
124+
|
125+
103126
error[E0277]: the size for values of type `X` cannot be known at compilation time
104127
--> $DIR/unsized3.rs:45:8
105128
|
@@ -116,13 +139,21 @@ note: required because it appears within the type `S<X>`
116139
LL | struct S<X: ?Sized> {
117140
| ^
118141
= note: required because it appears within the type `({integer}, S<X>)`
119-
= note: tuples must have a statically known size to be initialized
142+
note: required by a bound in `f5`
143+
--> $DIR/unsized3.rs:24:7
144+
|
145+
LL | fn f5<Y>(x: &Y) {}
146+
| ^ required by this bound in `f5`
120147
help: consider removing the `?Sized` bound to make the type parameter `Sized`
121148
|
122149
LL - fn f10<X: ?Sized>(x1: Box<S<X>>) {
123150
LL + fn f10<X>(x1: Box<S<X>>) {
124151
|
152+
help: consider relaxing the implicit `Sized` restriction
153+
|
154+
LL | fn f5<Y: ?Sized>(x: &Y) {}
155+
| ++++++++
125156

126-
error: aborting due to 5 previous errors
157+
error: aborting due to 6 previous errors
127158

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

0 commit comments

Comments
 (0)