Skip to content

Commit b53f5ce

Browse files
Don't ICE when RPITIT captures more method args than trait definition
1 parent 8c2c9a9 commit b53f5ce

File tree

4 files changed

+73
-8
lines changed

4 files changed

+73
-8
lines changed

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
726726
num_trait_args,
727727
num_impl_args,
728728
def_id,
729-
impl_def_id: impl_m.container_id(tcx),
729+
impl_m_def_id: impl_m.def_id,
730730
ty,
731731
return_span,
732732
}) {
@@ -844,12 +844,18 @@ where
844844

845845
struct RemapHiddenTyRegions<'tcx> {
846846
tcx: TyCtxt<'tcx>,
847+
/// Map from early/late params of the impl to identity regions of the RPITIT (GAT)
848+
/// in the trait.
847849
map: FxIndexMap<ty::Region<'tcx>, ty::Region<'tcx>>,
848850
num_trait_args: usize,
849851
num_impl_args: usize,
852+
/// Def id of the RPITIT (GAT) in the *trait*.
850853
def_id: DefId,
851-
impl_def_id: DefId,
854+
/// Def id of the impl method which owns the opaque hidden type we're remapping.
855+
impl_m_def_id: DefId,
856+
/// The hidden type we're remapping. Useful for diagnostics.
852857
ty: Ty<'tcx>,
858+
/// Span of the return type. Useful for diagnostics.
853859
return_span: Span,
854860
}
855861

@@ -885,8 +891,7 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
885891
ty::ReLateParam(_) => {}
886892
// Remap early-bound regions as long as they don't come from the `impl` itself,
887893
// in which case we don't really need to renumber them.
888-
ty::ReEarlyParam(ebr)
889-
if ebr.index >= self.tcx.generics_of(self.impl_def_id).count() as u32 => {}
894+
ty::ReEarlyParam(ebr) if ebr.index as usize >= self.num_impl_args => {}
890895
_ => return Ok(region),
891896
}
892897

@@ -899,7 +904,7 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
899904
);
900905
}
901906
} else {
902-
let guar = match region.opt_param_def_id(self.tcx, self.tcx.parent(self.def_id)) {
907+
let guar = match region.opt_param_def_id(self.tcx, self.impl_m_def_id) {
903908
Some(def_id) => {
904909
let return_span = if let ty::Alias(ty::Opaque, opaque_ty) = self.ty.kind() {
905910
self.tcx.def_span(opaque_ty.def_id)

compiler/rustc_middle/src/ty/generics.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,9 @@ impl<'tcx> Generics {
255255
let param = self.param_at(param.index as usize, tcx);
256256
match param.kind {
257257
GenericParamDefKind::Lifetime => param,
258-
_ => bug!("expected lifetime parameter, but found another generic parameter"),
258+
_ => {
259+
bug!("expected lifetime parameter, but found another generic parameter: {param:#?}")
260+
}
259261
}
260262
}
261263

@@ -264,7 +266,7 @@ impl<'tcx> Generics {
264266
let param = self.param_at(param.index as usize, tcx);
265267
match param.kind {
266268
GenericParamDefKind::Type { .. } => param,
267-
_ => bug!("expected type parameter, but found another generic parameter"),
269+
_ => bug!("expected type parameter, but found another generic parameter: {param:#?}"),
268270
}
269271
}
270272

@@ -273,7 +275,7 @@ impl<'tcx> Generics {
273275
let param = self.param_at(param.index as usize, tcx);
274276
match param.kind {
275277
GenericParamDefKind::Const { .. } => param,
276-
_ => bug!("expected const parameter, but found another generic parameter"),
278+
_ => bug!("expected const parameter, but found another generic parameter: {param:#?}"),
277279
}
278280
}
279281

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Make sure we don't ICE when an RPITIT captures more method args than the
2+
// trait definition, which is not allowed. Due to the default lifetime capture
3+
// rules of RPITITs, this is only doable if we use precise capturing.
4+
5+
pub trait Foo {
6+
fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use<Self>;
7+
//~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
8+
}
9+
10+
impl Foo for () {
11+
fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {}
12+
//~^ ERROR return type captures more lifetimes than trait definition
13+
//~| WARN impl trait in impl method signature does not match trait method signature
14+
}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
2+
--> $DIR/rpitit-captures-more-method-lifetimes.rs:6:53
3+
|
4+
LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use<Self>;
5+
| ^^^^^^^^^
6+
|
7+
= note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
8+
9+
error: return type captures more lifetimes than trait definition
10+
--> $DIR/rpitit-captures-more-method-lifetimes.rs:11:40
11+
|
12+
LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {}
13+
| --- ^^^^^^^^^^^^^^^^
14+
| |
15+
| this lifetime was captured
16+
|
17+
note: hidden type must only reference lifetimes captured by this impl trait
18+
--> $DIR/rpitit-captures-more-method-lifetimes.rs:6:40
19+
|
20+
LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use<Self>;
21+
| ^^^^^^^^^^^^^^^^^^^^^^
22+
= note: hidden type inferred to be `impl Sized + 'im`
23+
24+
warning: impl trait in impl method signature does not match trait method signature
25+
--> $DIR/rpitit-captures-more-method-lifetimes.rs:11:40
26+
|
27+
LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use<Self>;
28+
| ---------------------- return type from trait method defined here
29+
...
30+
LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {}
31+
| ^^^^^^^^^^^^^^^^
32+
|
33+
= note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate
34+
= note: we are soliciting feedback, see issue #121718 <https://github.com/rust-lang/rust/issues/121718> for more information
35+
= note: `#[warn(refining_impl_trait_reachable)]` on by default
36+
help: replace the return type so that it matches the trait
37+
|
38+
LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized {}
39+
| ~~~~~~~~~~
40+
41+
error: aborting due to 2 previous errors; 1 warning emitted
42+

0 commit comments

Comments
 (0)