Skip to content

Commit

Permalink
Don't ICE when RPITIT captures more method args than trait definition
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Sep 15, 2024
1 parent 8c2c9a9 commit b53f5ce
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 8 deletions.
15 changes: 10 additions & 5 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
num_trait_args,
num_impl_args,
def_id,
impl_def_id: impl_m.container_id(tcx),
impl_m_def_id: impl_m.def_id,
ty,
return_span,
}) {
Expand Down Expand Up @@ -844,12 +844,18 @@ where

struct RemapHiddenTyRegions<'tcx> {
tcx: TyCtxt<'tcx>,
/// Map from early/late params of the impl to identity regions of the RPITIT (GAT)
/// in the trait.
map: FxIndexMap<ty::Region<'tcx>, ty::Region<'tcx>>,
num_trait_args: usize,
num_impl_args: usize,
/// Def id of the RPITIT (GAT) in the *trait*.
def_id: DefId,
impl_def_id: DefId,
/// Def id of the impl method which owns the opaque hidden type we're remapping.
impl_m_def_id: DefId,
/// The hidden type we're remapping. Useful for diagnostics.
ty: Ty<'tcx>,
/// Span of the return type. Useful for diagnostics.
return_span: Span,
}

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

Expand All @@ -899,7 +904,7 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
);
}
} else {
let guar = match region.opt_param_def_id(self.tcx, self.tcx.parent(self.def_id)) {
let guar = match region.opt_param_def_id(self.tcx, self.impl_m_def_id) {
Some(def_id) => {
let return_span = if let ty::Alias(ty::Opaque, opaque_ty) = self.ty.kind() {
self.tcx.def_span(opaque_ty.def_id)
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_middle/src/ty/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,9 @@ impl<'tcx> Generics {
let param = self.param_at(param.index as usize, tcx);
match param.kind {
GenericParamDefKind::Lifetime => param,
_ => bug!("expected lifetime parameter, but found another generic parameter"),
_ => {
bug!("expected lifetime parameter, but found another generic parameter: {param:#?}")
}
}
}

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

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

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Make sure we don't ICE when an RPITIT captures more method args than the
// trait definition, which is not allowed. Due to the default lifetime capture
// rules of RPITITs, this is only doable if we use precise capturing.

pub trait Foo {
fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use<Self>;
//~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
}

impl Foo for () {
fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {}
//~^ ERROR return type captures more lifetimes than trait definition
//~| WARN impl trait in impl method signature does not match trait method signature
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
--> $DIR/rpitit-captures-more-method-lifetimes.rs:6:53
|
LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use<Self>;
| ^^^^^^^^^
|
= note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope

error: return type captures more lifetimes than trait definition
--> $DIR/rpitit-captures-more-method-lifetimes.rs:11:40
|
LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {}
| --- ^^^^^^^^^^^^^^^^
| |
| this lifetime was captured
|
note: hidden type must only reference lifetimes captured by this impl trait
--> $DIR/rpitit-captures-more-method-lifetimes.rs:6:40
|
LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use<Self>;
| ^^^^^^^^^^^^^^^^^^^^^^
= note: hidden type inferred to be `impl Sized + 'im`

warning: impl trait in impl method signature does not match trait method signature
--> $DIR/rpitit-captures-more-method-lifetimes.rs:11:40
|
LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use<Self>;
| ---------------------- return type from trait method defined here
...
LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {}
| ^^^^^^^^^^^^^^^^
|
= note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate
= note: we are soliciting feedback, see issue #121718 <https://github.com/rust-lang/rust/issues/121718> for more information
= note: `#[warn(refining_impl_trait_reachable)]` on by default
help: replace the return type so that it matches the trait
|
LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized {}
| ~~~~~~~~~~

error: aborting due to 2 previous errors; 1 warning emitted

0 comments on commit b53f5ce

Please sign in to comment.