Don't point at another arg if we're already pointing at one
This commit is contained in:
parent
75337775f7
commit
23f3b0dfd0
5 changed files with 78 additions and 19 deletions
|
@ -1629,7 +1629,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for error in errors {
|
'outer: for error in errors {
|
||||||
// Only if the cause is somewhere inside the expression we want try to point at arg.
|
// Only if the cause is somewhere inside the expression we want try to point at arg.
|
||||||
// Otherwise, it means that the cause is somewhere else and we should not change
|
// Otherwise, it means that the cause is somewhere else and we should not change
|
||||||
// anything because we can break the correct span.
|
// anything because we can break the correct span.
|
||||||
|
@ -1671,10 +1671,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
let self_ = self.resolve_vars_if_possible(self_);
|
let self_ = self.resolve_vars_if_possible(self_);
|
||||||
|
let ty_matches_self = |ty: Ty<'tcx>| ty.walk().any(|arg| arg == self_);
|
||||||
|
|
||||||
|
let typeck_results = self.typeck_results.borrow();
|
||||||
|
|
||||||
|
for (idx, arg) in args.iter().enumerate() {
|
||||||
|
// Don't adjust the span if we already have a more precise span
|
||||||
|
// within one of the args.
|
||||||
|
if arg.span.contains(error.obligation.cause.span) {
|
||||||
|
let references_arg =
|
||||||
|
typeck_results.expr_ty_opt(arg).map_or(false, &ty_matches_self)
|
||||||
|
|| expected_tys.get(idx).copied().map_or(false, &ty_matches_self);
|
||||||
|
if references_arg && !arg.span.from_expansion() {
|
||||||
|
error.obligation.cause.map_code(|parent_code| {
|
||||||
|
ObligationCauseCode::FunctionArgumentObligation {
|
||||||
|
arg_hir_id: args[idx].hir_id,
|
||||||
|
call_hir_id: expr.hir_id,
|
||||||
|
parent_code,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Collect the argument position for all arguments that could have caused this
|
// Collect the argument position for all arguments that could have caused this
|
||||||
// `FulfillmentError`.
|
// `FulfillmentError`.
|
||||||
let typeck_results = self.typeck_results.borrow();
|
|
||||||
let mut referenced_in: Vec<_> = std::iter::zip(expected_tys, args)
|
let mut referenced_in: Vec<_> = std::iter::zip(expected_tys, args)
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.flat_map(|(idx, (expected_ty, arg))| {
|
.flat_map(|(idx, (expected_ty, arg))| {
|
||||||
|
@ -1688,7 +1710,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let ty = self.resolve_vars_if_possible(ty);
|
let ty = self.resolve_vars_if_possible(ty);
|
||||||
// We walk the argument type because the argument's type could have
|
// We walk the argument type because the argument's type could have
|
||||||
// been `Option<T>`, but the `FulfillmentError` references `T`.
|
// been `Option<T>`, but the `FulfillmentError` references `T`.
|
||||||
if ty.walk().any(|arg| arg == self_) { Some(i) } else { None }
|
if ty_matches_self(ty) { Some(i) } else { None }
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
@ -1699,18 +1721,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
referenced_in.sort_unstable();
|
referenced_in.sort_unstable();
|
||||||
referenced_in.dedup();
|
referenced_in.dedup();
|
||||||
|
|
||||||
if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) {
|
if let &[idx] = &referenced_in[..] {
|
||||||
// Do not point at the inside of a macro.
|
// Do not point at the inside of a macro.
|
||||||
// That would often result in poor error messages.
|
// That would often result in poor error messages.
|
||||||
if args[ref_in].span.from_expansion() {
|
if args[idx].span.from_expansion() {
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
// We make sure that only *one* argument matches the obligation failure
|
// We make sure that only *one* argument matches the obligation failure
|
||||||
// and we assign the obligation's span to its expression's.
|
// and we assign the obligation's span to its expression's.
|
||||||
error.obligation.cause.span = args[ref_in].span;
|
error.obligation.cause.span = args[idx].span;
|
||||||
error.obligation.cause.map_code(|parent_code| {
|
error.obligation.cause.map_code(|parent_code| {
|
||||||
ObligationCauseCode::FunctionArgumentObligation {
|
ObligationCauseCode::FunctionArgumentObligation {
|
||||||
arg_hir_id: args[ref_in].hir_id,
|
arg_hir_id: args[idx].hir_id,
|
||||||
call_hir_id: expr.hir_id,
|
call_hir_id: expr.hir_id,
|
||||||
parent_code,
|
parent_code,
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,7 @@ LL | / pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
|
||||||
LL | |
|
LL | |
|
||||||
LL | | loop {}
|
LL | | loop {}
|
||||||
LL | | }
|
LL | | }
|
||||||
| | ^
|
| |_^ call the function in a closure: `|| unsafe { /* code */ }`
|
||||||
| | |
|
|
||||||
| |_call the function in a closure: `|| unsafe { /* code */ }`
|
|
||||||
| required by a bound introduced by this call
|
|
||||||
|
|
|
|
||||||
= help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
|
= help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
|
||||||
= note: unsafe function cannot be called generically without an unsafe block
|
= note: unsafe function cannot be called generically without an unsafe block
|
||||||
|
|
|
@ -2,7 +2,9 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
|
||||||
--> $DIR/unsized-fn-param.rs:11:11
|
--> $DIR/unsized-fn-param.rs:11:11
|
||||||
|
|
|
|
||||||
LL | foo11("bar", &"baz");
|
LL | foo11("bar", &"baz");
|
||||||
| ^^^^^ doesn't have a size known at compile-time
|
| ----- ^^^^^ doesn't have a size known at compile-time
|
||||||
|
| |
|
||||||
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
= help: the trait `Sized` is not implemented for `str`
|
= help: the trait `Sized` is not implemented for `str`
|
||||||
= note: required for the cast to the object type `dyn AsRef<Path>`
|
= 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
|
||||||
--> $DIR/unsized-fn-param.rs:13:19
|
--> $DIR/unsized-fn-param.rs:13:19
|
||||||
|
|
|
|
||||||
LL | foo12(&"bar", "baz");
|
LL | foo12(&"bar", "baz");
|
||||||
| ^^^^^ doesn't have a size known at compile-time
|
| ----- ^^^^^ doesn't have a size known at compile-time
|
||||||
|
| |
|
||||||
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
= help: the trait `Sized` is not implemented for `str`
|
= help: the trait `Sized` is not implemented for `str`
|
||||||
= note: required for the cast to the object type `dyn AsRef<Path>`
|
= 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
|
||||||
--> $DIR/unsized-fn-param.rs:16:11
|
--> $DIR/unsized-fn-param.rs:16:11
|
||||||
|
|
|
|
||||||
LL | foo21("bar", &"baz");
|
LL | foo21("bar", &"baz");
|
||||||
| ^^^^^ doesn't have a size known at compile-time
|
| ----- ^^^^^ doesn't have a size known at compile-time
|
||||||
|
| |
|
||||||
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
= help: the trait `Sized` is not implemented for `str`
|
= help: the trait `Sized` is not implemented for `str`
|
||||||
= note: required for the cast to the object type `dyn AsRef<str>`
|
= 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
|
||||||
--> $DIR/unsized-fn-param.rs:18:19
|
--> $DIR/unsized-fn-param.rs:18:19
|
||||||
|
|
|
|
||||||
LL | foo22(&"bar", "baz");
|
LL | foo22(&"bar", "baz");
|
||||||
| ^^^^^ doesn't have a size known at compile-time
|
| ----- ^^^^^ doesn't have a size known at compile-time
|
||||||
|
| |
|
||||||
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
= help: the trait `Sized` is not implemented for `str`
|
= help: the trait `Sized` is not implemented for `str`
|
||||||
= note: required for the cast to the object type `dyn AsRef<str>`
|
= note: required for the cast to the object type `dyn AsRef<str>`
|
||||||
|
|
|
@ -44,6 +44,7 @@ fn f9<X: ?Sized>(x1: Box<S<X>>) {
|
||||||
fn f10<X: ?Sized>(x1: Box<S<X>>) {
|
fn f10<X: ?Sized>(x1: Box<S<X>>) {
|
||||||
f5(&(32, *x1));
|
f5(&(32, *x1));
|
||||||
//~^ ERROR the size for values of type
|
//~^ ERROR the size for values of type
|
||||||
|
//~| ERROR the size for values of type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {}
|
pub fn main() {}
|
||||||
|
|
|
@ -101,12 +101,12 @@ LL + fn f9<X>(x1: Box<S<X>>) {
|
||||||
|
|
|
|
||||||
|
|
||||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||||
--> $DIR/unsized3.rs:45:8
|
--> $DIR/unsized3.rs:45:9
|
||||||
|
|
|
|
||||||
LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
|
LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
|
||||||
| - this type parameter needs to be `std::marker::Sized`
|
| - this type parameter needs to be `std::marker::Sized`
|
||||||
LL | f5(&(32, *x1));
|
LL | f5(&(32, *x1));
|
||||||
| -- ^^^^^^^^^^ doesn't have a size known at compile-time
|
| -- ^^^^^^^^^ doesn't have a size known at compile-time
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
|
@ -123,6 +123,37 @@ LL - fn f10<X: ?Sized>(x1: Box<S<X>>) {
|
||||||
LL + fn f10<X>(x1: Box<S<X>>) {
|
LL + fn f10<X>(x1: Box<S<X>>) {
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||||
|
--> $DIR/unsized3.rs:45:8
|
||||||
|
|
|
||||||
|
LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
|
||||||
|
| - this type parameter needs to be `std::marker::Sized`
|
||||||
|
LL | f5(&(32, *x1));
|
||||||
|
| -- ^^^^^^^^^^ doesn't have a size known at compile-time
|
||||||
|
| |
|
||||||
|
| required by a bound introduced by this call
|
||||||
|
|
|
||||||
|
note: required because it appears within the type `S<X>`
|
||||||
|
--> $DIR/unsized3.rs:28:8
|
||||||
|
|
|
||||||
|
LL | struct S<X: ?Sized> {
|
||||||
|
| ^
|
||||||
|
= note: required because it appears within the type `({integer}, S<X>)`
|
||||||
|
note: required by a bound in `f5`
|
||||||
|
--> $DIR/unsized3.rs:24:7
|
||||||
|
|
|
||||||
|
LL | fn f5<Y>(x: &Y) {}
|
||||||
|
| ^ required by this bound in `f5`
|
||||||
|
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
||||||
|
|
|
||||||
|
LL - fn f10<X: ?Sized>(x1: Box<S<X>>) {
|
||||||
|
LL + fn f10<X>(x1: Box<S<X>>) {
|
||||||
|
|
|
||||||
|
help: consider relaxing the implicit `Sized` restriction
|
||||||
|
|
|
||||||
|
LL | fn f5<Y: ?Sized>(x: &Y) {}
|
||||||
|
| ++++++++
|
||||||
|
|
||||||
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue