Support HIR wf checking for function signatures

During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.

This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.

As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).

As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
This commit is contained in:
Aaron Hill 2021-07-18 11:33:49 -05:00
parent da7d405357
commit db0324ebb2
No known key found for this signature in database
GPG key ID: B4087E510E98B164
28 changed files with 240 additions and 91 deletions

View file

@ -1,8 +1,11 @@
error[E0277]: the trait bound `Self: Get` is not satisfied
--> $DIR/associated-types-for-unimpl-trait.rs:10:8
--> $DIR/associated-types-for-unimpl-trait.rs:10:40
|
LL | trait Get {
| --------- required by this bound in `Get`
...
LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
| ^^^^ the trait `Get` is not implemented for `Self`
| ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
|
help: consider further restricting `Self`
|

View file

@ -1,8 +1,11 @@
error[E0277]: the trait bound `T: Get` is not satisfied
--> $DIR/associated-types-no-suitable-bound.rs:11:8
--> $DIR/associated-types-no-suitable-bound.rs:11:21
|
LL | trait Get {
| --------- required by this bound in `Get`
...
LL | fn uhoh<T>(foo: <T as Get>::Value) {}
| ^^^^ the trait `Get` is not implemented for `T`
| ^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T`
|
help: consider restricting type parameter `T`
|

View file

@ -1,8 +1,11 @@
error[E0277]: the trait bound `Self: Get` is not satisfied
--> $DIR/associated-types-no-suitable-supertrait-2.rs:17:8
--> $DIR/associated-types-no-suitable-supertrait-2.rs:17:40
|
LL | trait Get {
| --------- required by this bound in `Get`
...
LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
| ^^^^ the trait `Get` is not implemented for `Self`
| ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
|
help: consider further restricting `Self`
|

View file

@ -1,8 +1,11 @@
error[E0277]: the trait bound `Self: Get` is not satisfied
--> $DIR/associated-types-no-suitable-supertrait.rs:17:8
--> $DIR/associated-types-no-suitable-supertrait.rs:17:40
|
LL | trait Get {
| --------- required by this bound in `Get`
...
LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
| ^^^^ the trait `Get` is not implemented for `Self`
| ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
|
help: consider further restricting `Self`
|
@ -10,10 +13,13 @@ LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Ge
| ^^^^^^^^^^^^^^^
error[E0277]: the trait bound `(T, U): Get` is not satisfied
--> $DIR/associated-types-no-suitable-supertrait.rs:22:8
--> $DIR/associated-types-no-suitable-supertrait.rs:22:40
|
LL | trait Get {
| --------- required by this bound in `Get`
...
LL | fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
| ^^^^ the trait `Get` is not implemented for `(T, U)`
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)`
error: aborting due to 2 previous errors

View file

@ -1,8 +1,11 @@
error[E0277]: the trait bound `Self: Get` is not satisfied
--> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:8
--> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:40
|
LL | trait Get {
| --------- required by this bound in `Get`
...
LL | fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value);
| ^^^^ the trait `Get` is not implemented for `Self`
| ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
|
help: consider further restricting `Self`
|

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/object-safety-err-ret.rs:17:15
--> $DIR/object-safety-err-ret.rs:17:16
|
LL | fn use_dyn(v: &dyn Foo) {
| ^^^^^^^^ `Foo` cannot be made into an object
| ^^^^^^^ `Foo` cannot be made into an object
|
= help: consider moving `test` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `Trait` cannot be made into an object
--> $DIR/E0038.rs:5:16
--> $DIR/E0038.rs:5:20
|
LL | fn call_foo(x: Box<dyn Trait>) {
| ^^^^^^^^^^^^^^ `Trait` cannot be made into an object
| ^^^^^^^^^ `Trait` cannot be made into an object
|
= help: consider moving `foo` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `NonObjectSafe1` cannot be made into an object
--> $DIR/feature-gate-object_safe_for_dispatch.rs:18:38
--> $DIR/feature-gate-object_safe_for_dispatch.rs:18:39
|
LL | fn takes_non_object_safe_ref<T>(obj: &dyn NonObjectSafe1) {
| ^^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object
| ^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/feature-gate-object_safe_for_dispatch.rs:4:23
@ -35,10 +35,10 @@ LL | fn static_fn() where Self: Sized {}
| ^^^^^^^^^^^^^^^^^
error[E0038]: the trait `NonObjectSafe3` cannot be made into an object
--> $DIR/feature-gate-object_safe_for_dispatch.rs:27:35
--> $DIR/feature-gate-object_safe_for_dispatch.rs:27:39
|
LL | fn takes_non_object_safe_box(obj: Box<dyn NonObjectSafe3>) {
| ^^^^^^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object
| ^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object
|
= help: consider moving `foo` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/gat-in-trait-path.rs:21:13
--> $DIR/gat-in-trait-path.rs:21:17
|
LL | fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
|
= help: consider moving `A` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `X` cannot be made into an object
--> $DIR/issue-67510-pass.rs:7:19
--> $DIR/issue-67510-pass.rs:7:23
|
LL | fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object
| ^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object
|
= help: consider moving `Y` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `StreamingIterator` cannot be made into an object
--> $DIR/trait-objects.rs:10:16
--> $DIR/trait-objects.rs:10:21
|
LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object
|
= help: consider moving `Item` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

View file

@ -1,8 +1,11 @@
error[E0277]: the trait bound `isize: HasState` is not satisfied
--> $DIR/issue-18611.rs:1:4
--> $DIR/issue-18611.rs:1:18
|
LL | fn add_state(op: <isize as HasState>::State) {
| ^^^^^^^^^ the trait `HasState` is not implemented for `isize`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasState` is not implemented for `isize`
...
LL | trait HasState {
| -------------- required by this bound in `HasState`
error: aborting due to previous error

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `Bar` cannot be made into an object
--> $DIR/issue-18959.rs:11:11
--> $DIR/issue-18959.rs:11:12
|
LL | fn foo(b: &dyn Bar) {
| ^^^^^^^^ `Bar` cannot be made into an object
| ^^^^^^^ `Bar` cannot be made into an object
|
= help: consider moving `foo` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `Trait` cannot be made into an object
--> $DIR/object-unsafe-trait-references-self.rs:6:11
--> $DIR/object-unsafe-trait-references-self.rs:6:12
|
LL | fn bar(x: &dyn Trait) {}
| ^^^^^^^^^^ `Trait` cannot be made into an object
| ^^^^^^^^^ `Trait` cannot be made into an object
|
= help: consider moving `baz` to another trait
= help: consider moving `bat` to another trait
@ -17,10 +17,10 @@ LL | fn bat(&self) -> Self {}
| ^^^^ ...because method `bat` references the `Self` type in its return type
error[E0038]: the trait `Other` cannot be made into an object
--> $DIR/object-unsafe-trait-references-self.rs:10:11
--> $DIR/object-unsafe-trait-references-self.rs:10:12
|
LL | fn foo(x: &dyn Other) {}
| ^^^^^^^^^^ `Other` cannot be made into an object
| ^^^^^^^^^ `Other` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-unsafe-trait-references-self.rs:8:14

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `Trait` cannot be made into an object
--> $DIR/object-unsafe-trait-should-use-where-sized.rs:9:11
--> $DIR/object-unsafe-trait-should-use-where-sized.rs:9:12
|
LL | fn bar(x: &dyn Trait) {}
| ^^^^^^^^^^ `Trait` cannot be made into an object
| ^^^^^^^^^ `Trait` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-unsafe-trait-should-use-where-sized.rs:5:8

View file

@ -1,8 +1,11 @@
error[E0277]: the trait bound `(): Foo` is not satisfied
--> $DIR/wf-foreign-fn-decl-ret.rs:11:12
--> $DIR/wf-foreign-fn-decl-ret.rs:11:25
|
LL | pub trait Foo {
| ------------- required by this bound in `Foo`
...
LL | pub fn lint_me() -> <() as Foo>::Assoc;
| ^^^^^^^ the trait `Foo` is not implemented for `()`
| ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied
--> $DIR/wf-foreign-fn-decl-ret.rs:14:32

View file

@ -1,11 +1,11 @@
error[E0277]: the trait bound `T: Copy` is not satisfied
--> $DIR/wf-in-fn-arg.rs:10:14
--> $DIR/wf-in-fn-arg.rs:10:15
|
LL | struct MustBeCopy<T:Copy> {
| ---- required by this bound in `MustBeCopy`
...
LL | fn bar<T>(_: &MustBeCopy<T>)
| ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
| ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
|
help: consider restricting type parameter `T`
|

View file

@ -1,11 +1,11 @@
error[E0277]: the trait bound `Self: Eq` is not satisfied
--> $DIR/wf-trait-default-fn-arg.rs:11:22
--> $DIR/wf-trait-default-fn-arg.rs:11:23
|
LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
| -- required by this bound in `Bar`
...
LL | fn bar(&self, x: &Bar<Self>) {
| ^^^^^^^^^^ the trait `Eq` is not implemented for `Self`
| ^^^^^^^^^ the trait `Eq` is not implemented for `Self`
|
help: consider further restricting `Self`
|

View file

@ -1,11 +1,11 @@
error[E0277]: the trait bound `Self: Eq` is not satisfied
--> $DIR/wf-trait-fn-arg.rs:10:22
--> $DIR/wf-trait-fn-arg.rs:10:23
|
LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
| -- required by this bound in `Bar`
...
LL | fn bar(&self, x: &Bar<Self>);
| ^^^^^^^^^^ the trait `Eq` is not implemented for `Self`
| ^^^^^^^^^ the trait `Eq` is not implemented for `Self`
|
help: consider further restricting `Self`
|