Skip to content

regression: non-defining opaque type use in defining scope #105826

Closed
@digama0

Description

@digama0

Here is an example which uses a RPIT on a borrowed type in three different ways:

use std::io::Write;

struct A(Vec<u8>);

struct B<'a> {
  one: &'a mut A,
  two: &'a mut Vec<u8>,
  three: Vec<u8>,
}

impl<'a> B<'a> {
  fn one(&mut self) -> &mut impl Write { &mut self.one.0 }
  fn two(&mut self) -> &mut impl Write { &mut self.two } // fail
  fn three(&mut self) -> &mut impl Write { &mut self.three }
}

struct C<'a>(B<'a>);

impl<'a> C<'a> {
  fn one(&mut self) -> &mut impl Write { self.0.one() } // fail on beta
  fn two(&mut self) -> &mut impl Write { self.0.two() } // fail on beta
  fn three(&mut self) -> &mut impl Write { self.0.three() } // fail on beta
}

IMO this is perfectly reasonable code and there should be no errors (EDIT: see below). On stable (rustc 1.66.0 (69f9c33d7 2022-12-12)) we have the following:

error[E0700]: hidden type for `impl std::io::Write` captures lifetime that does not appear in bounds
  --> src/main.rs:13:42
   |
11 | impl<'a> B<'a> {
   |      -- hidden type `&'a mut Vec<u8>` captures the lifetime `'a` as defined here
12 |   fn one(&mut self) -> &mut impl Write { &mut self.one.0 }
13 |   fn two(&mut self) -> &mut impl Write { &mut self.two } // fail
   |                                          ^^^^^^^^^^^^^

And on beta (rustc 1.67.0-beta.2 (352eb59a4 2022-12-13)) and nightly (rustc 1.68.0-nightly (b70baa4f9 2022-12-14)) we get some additional errors:

error[E0700]: hidden type for `impl std::io::Write` captures lifetime that does not appear in bounds
  --> src/main.rs:13:42
   |
11 | impl<'a> B<'a> {
   |      -- hidden type `&'a mut Vec<u8>` captures the lifetime `'a` as defined here
12 |   fn one(&mut self) -> &mut impl Write { &mut self.one.0 }
13 |   fn two(&mut self) -> &mut impl Write { &mut self.two } // fail
   |                                          ^^^^^^^^^^^^^

error: non-defining opaque type use in defining scope
  --> src/main.rs:20:42
   |
20 |   fn one(&mut self) -> &mut impl Write { self.0.one() } // fail on beta
   |                                          ^^^^^^^^^^^^ lifetime `'a` is part of concrete type but not used in parameter list of the `impl Trait` type alias

error: non-defining opaque type use in defining scope
  --> src/main.rs:21:42
   |
21 |   fn two(&mut self) -> &mut impl Write { self.0.two() } // fail on beta
   |                                          ^^^^^^^^^^^^ lifetime `'a` is part of concrete type but not used in parameter list of the `impl Trait` type alias

error: non-defining opaque type use in defining scope
  --> src/main.rs:22:44
   |
22 |   fn three(&mut self) -> &mut impl Write { self.0.three() } // fail on beta
   |                                            ^^^^^^^^^^^^^^ lifetime `'a` is part of concrete type but not used in parameter list of the `impl Trait` type alias

EDIT: On second thought, I guess the first error (on stable) is reasonable, since we are actually returning a &mut &'a mut Vec<u8> in that case. If you either use &mut *self.two in the body or &mut (impl Write + 'a) in the return type then the error goes away. But the second error is still a regression.

Version it worked on

It most recently worked on: rustc 1.66.0 (69f9c33 2022-12-12)

Version with regression

rustc --version --verbose:

rustc 1.67.0-beta.2 (352eb59a4 2022-12-13)
binary: rustc
commit-hash: 352eb59a4c33abf739914422f2ad975925750146
commit-date: 2022-12-13
host: x86_64-unknown-linux-gnu
release: 1.67.0-beta.2
LLVM version: 15.0.6

@rustbot modify labels: +regression-from-stable-to-beta -regression-untriaged

Metadata

Metadata

Assignees

Labels

C-bugCategory: This is a bug.P-criticalCritical priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.regression-from-stable-to-betaPerformance or correctness regression from stable to beta.

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions