Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1630,7 +1630,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {

let op_arg_ty = self.normalize(op_arg_ty, term_location);
let category = if from_hir_call {
ConstraintCategory::CallArgument(func_ty)
ConstraintCategory::CallArgument(self.infcx.tcx.erase_regions(func_ty))
} else {
ConstraintCategory::Boring
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@ LL | let a = bar(f, x);
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

error: lifetime may not live long enough
--> $DIR/project-fn-ret-invariant.rs:40:13
--> $DIR/project-fn-ret-invariant.rs:42:13
|
LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
LL | let f = foo; // <-- No consistent type can be inferred for `f` here.
LL | let a = bar(f, x);
...
LL | let b = bar(f, y);
| ^^^^^^^^^ argument requires that `'b` must outlive `'a`
|
= help: consider adding the following bound: `'b: 'a`
= note: requirement occurs because of a function pointer to `foo`
= note: the function `foo` is invariant over the parameter `'a`
= note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant
= note: the struct `Type<'a>` is invariant over the parameter `'a`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does erasing regions change diagnostics?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, good question -- I have no idea. My first suspicion when I put this PR up was due to the Ord implementation on ConstraintCategory and something about the sorting of constraints in best_blame_constraint, but I can look into it further.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's because we're not sorting by variance_info, but only the constraint:

categorized_path.sort_by(|p0, p1| p0.category.cmp(&p1.category));

And we have several constraints that differ only in variant info:

1ms DEBUG rustc_borrowck::region_infer sorted_path=[
│     BlameConstraint {
│         category: CallArgument(
│             Some(
│                 fn(fn() -> Type<'_> {foo::<'_>}, <fn() -> Type<'_> {foo::<'_>} as std::ops::FnOnce<()>>::Output) -> <fn() -> Type<'_> {foo::<'_>} as std::ops::FnOnce<()>>::Output {bar::<fn() -> Type<'_> {foo::<'_>}>},
│             ),
│         ),
│         from_closure: false,
│         cause: ObligationCause {
│             span: src/test/ui/associated-types/cache/project-fn-ret-invariant.rs:42:13: 42:22 (#0),
│             body_id: HirId {
│                 owner: OwnerId {
│                     def_id: DefId(0:0 ~ project_fn_ret_invariant[129b]),
│                 },
│                 local_id: 0,
│             },
│             code: InternedObligationCauseCode {
│                 code: None,
│             },
│         },
│         variance_info: Invariant {
│             ty: Type<'_>,
│             param_index: 0,
│         },
│         outlives_constraint: ('_#19r: '_#6r) due to Single(bb1[8]) (Invariant { ty: Type<'_>, param_index: 0 }) (CallArgument(Some(fn(fn() -> Type<'_> {foo::<'_>}, <fn() -> Type<'_> {foo::<'_>} as std::ops::FnOnce<()>>::Output) -> <fn() -> Type<'_> {foo::<'_>} as std::ops::FnOnce<()>>::Output {bar::<fn() -> Type<'_> {foo::<'_>}>}))),
│     },
│     BlameConstraint {
│         category: CallArgument(
│             Some(
│                 fn(fn() -> Type<'_> {foo::<'_>}, <fn() -> Type<'_> {foo::<'_>} as std::ops::FnOnce<()>>::Output) -> <fn() -> Type<'_> {foo::<'_>} as std::ops::FnOnce<()>>::Output {bar::<fn() -> Type<'_> {foo::<'_>}>},
│             ),
│         ),
│         from_closure: false,
│         cause: ObligationCause {
│             span: src/test/ui/associated-types/cache/project-fn-ret-invariant.rs:42:13: 42:22 (#0),
│             body_id: HirId {
│                 owner: OwnerId {
│                     def_id: DefId(0:0 ~ project_fn_ret_invariant[129b]),
│                 },
│                 local_id: 0,
│             },
│             code: InternedObligationCauseCode {
│                 code: None,
│             },
│         },
│         variance_info: Invariant {
│             ty: fn() -> Type<'_> {foo::<'_>},
│             param_index: 0,
│         },
│         outlives_constraint: ('_#6r: '_#18r) due to Single(bb1[8]) (Invariant { ty: fn() -> Type<'_> {foo::<'_>}, param_index: 0 }) (CallArgument(Some(fn(fn() -> Type<'_> {foo::<'_>}, <fn() -> Type<'_> {foo::<'_>} as std::ops::FnOnce<()>>::Output) -> <fn() -> Type<'_> {foo::<'_>} as std::ops::FnOnce<()>>::Output {bar::<fn() -> Type<'_> {foo::<'_>}>}))),
│     },

[...]

-- so erasing regions probably causes hashes to change which causes the order constraints get ordered out to change.

Copy link
Member Author

@compiler-errors compiler-errors Oct 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The differing variance_info causes this error message to change slightly in the note, as seen above. I think it's harmless imo. Same with all these other errors changing slightly.

= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

help: `'a` and `'b` must be the same: replace one with the other
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
let f = foo; // <-- No consistent type can be inferred for `f` here.
let a = bar(f, x);
//[oneuse]~^ ERROR lifetime may not live long enough
//[oneuse]~| ERROR lifetime may not live long enough
let b = bar(f, y);
//[oneuse]~^ ERROR lifetime may not live long enough
(a, b)
}

Expand Down
31 changes: 31 additions & 0 deletions src/test/ui/borrowck/issue-103624.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// edition:2021

struct StructA {
b: StructB,
}

async fn spawn_blocking<T>(f: impl (Fn() -> T) + Send + Sync + 'static) -> T {
todo!()
}

impl StructA {
async fn foo(&self) {
let bar = self.b.bar().await;
spawn_blocking(move || {
//~^ ERROR borrowed data escapes outside of associated function
self.b;
//~^ ERROR cannot move out of `self.b`, as `self` is a captured variable in an `Fn` closure
})
.await;
}
}

struct StructB {}

impl StructB {
async fn bar(&self) -> Option<u8> {
None
}
}

fn main() {}
35 changes: 35 additions & 0 deletions src/test/ui/borrowck/issue-103624.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
error[E0507]: cannot move out of `self.b`, as `self` is a captured variable in an `Fn` closure
--> $DIR/issue-103624.rs:16:13
|
LL | async fn foo(&self) {
| ----- captured outer variable
LL | let bar = self.b.bar().await;
LL | spawn_blocking(move || {
| ------- captured by this `Fn` closure
LL |
LL | self.b;
| ^^^^^^ move occurs because `self.b` has type `StructB`, which does not implement the `Copy` trait

error[E0521]: borrowed data escapes outside of associated function
--> $DIR/issue-103624.rs:14:9
|
LL | async fn foo(&self) {
| -----
| |
| `self` is a reference that is only valid in the associated function body
| let's call the lifetime of this reference `'1`
LL | let bar = self.b.bar().await;
LL | / spawn_blocking(move || {
LL | |
LL | | self.b;
LL | |
LL | | })
| | ^
| | |
| |__________`self` escapes the associated function body here
| argument requires that `'1` must outlive `'static`

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0507, E0521.
For more information about an error, try `rustc --explain E0507`.