Skip to content

Commit 104e1a4

Browse files
authored
Rollup merge of rust-lang#125501 - compiler-errors:opaque-opaque-anon-ct, r=BoxyUwU
Resolve anon const's parent predicates to direct parent instead of opaque's parent When an anon const is inside of an opaque, rust-lang#99801 added a hack to resolve the anon const's parent predicates *not* to the opaque's predicates, but to the opaque's *parent's* predicates. This is insufficient when considering nested opaques. This means that the `predicates_of` an anon const might reference duplicated lifetimes (installed by `compute_bidirectional_outlives_predicates`) when computing known outlives in MIR borrowck, leading to these ICEs: Fixes rust-lang#121574 Fixes rust-lang#118403 ~~Instead, we should be using the `OpaqueTypeOrigin` to acquire the owner item (fn/type alias/etc) of the opaque, whose predicates we're fine to mention.~~ ~~I think it's a bit sketchy that we're doing this at all, tbh; I think it *should* be fine for the anon const to inherit the predicates of the opaque it's located inside. However, that would also mean that we need to make sure the `generics_of` that anon const line up in the same way.~~ ~~None of this is important to solve right now; I just want to fix these ICEs so we can land rust-lang#125468, which accidentally fixes these issues in a different and unrelated way.~~ edit: We don't need this special case anyways because we install the right parent item in `generics_of` anyways: https://github.com/rust-lang/rust/blob/213ad10c8f0fc275648552366275dc4e07f97462/compiler/rustc_hir_analysis/src/collect/generics_of.rs#L150 r? `@BoxyUwU`
2 parents 363fbb9 + de517b7 commit 104e1a4

File tree

6 files changed

+71
-97
lines changed

6 files changed

+71
-97
lines changed

Diff for: compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+47-75
Original file line numberDiff line numberDiff line change
@@ -461,83 +461,55 @@ pub(super) fn explicit_predicates_of<'tcx>(
461461
}
462462
}
463463
} else {
464-
if matches!(def_kind, DefKind::AnonConst) && tcx.features().generic_const_exprs {
465-
let hir_id = tcx.local_def_id_to_hir_id(def_id);
466-
let parent_def_id = tcx.hir().get_parent_item(hir_id);
467-
468-
if let Some(defaulted_param_def_id) =
469-
tcx.hir().opt_const_param_default_param_def_id(hir_id)
470-
{
471-
// In `generics_of` we set the generics' parent to be our parent's parent which means that
472-
// we lose out on the predicates of our actual parent if we dont return those predicates here.
473-
// (See comment in `generics_of` for more information on why the parent shenanigans is necessary)
474-
//
475-
// struct Foo<T, const N: usize = { <T as Trait>::ASSOC }>(T) where T: Trait;
476-
// ^^^ ^^^^^^^^^^^^^^^^^^^^^^^ the def id we are calling
477-
// ^^^ explicit_predicates_of on
478-
// parent item we dont have set as the
479-
// parent of generics returned by `generics_of`
480-
//
481-
// In the above code we want the anon const to have predicates in its param env for `T: Trait`
482-
// and we would be calling `explicit_predicates_of(Foo)` here
483-
let parent_preds = tcx.explicit_predicates_of(parent_def_id);
484-
485-
// If we dont filter out `ConstArgHasType` predicates then every single defaulted const parameter
486-
// will ICE because of #106994. FIXME(generic_const_exprs): remove this when a more general solution
487-
// to #106994 is implemented.
488-
let filtered_predicates = parent_preds
489-
.predicates
490-
.into_iter()
491-
.filter(|(pred, _)| {
492-
if let ty::ClauseKind::ConstArgHasType(ct, _) = pred.kind().skip_binder() {
493-
match ct.kind() {
494-
ty::ConstKind::Param(param_const) => {
495-
let defaulted_param_idx = tcx
496-
.generics_of(parent_def_id)
497-
.param_def_id_to_index[&defaulted_param_def_id.to_def_id()];
498-
param_const.index < defaulted_param_idx
499-
}
500-
_ => bug!(
501-
"`ConstArgHasType` in `predicates_of`\
502-
that isn't a `Param` const"
503-
),
464+
if matches!(def_kind, DefKind::AnonConst)
465+
&& tcx.features().generic_const_exprs
466+
&& let Some(defaulted_param_def_id) =
467+
tcx.hir().opt_const_param_default_param_def_id(tcx.local_def_id_to_hir_id(def_id))
468+
{
469+
// In `generics_of` we set the generics' parent to be our parent's parent which means that
470+
// we lose out on the predicates of our actual parent if we dont return those predicates here.
471+
// (See comment in `generics_of` for more information on why the parent shenanigans is necessary)
472+
//
473+
// struct Foo<T, const N: usize = { <T as Trait>::ASSOC }>(T) where T: Trait;
474+
// ^^^ ^^^^^^^^^^^^^^^^^^^^^^^ the def id we are calling
475+
// ^^^ explicit_predicates_of on
476+
// parent item we dont have set as the
477+
// parent of generics returned by `generics_of`
478+
//
479+
// In the above code we want the anon const to have predicates in its param env for `T: Trait`
480+
// and we would be calling `explicit_predicates_of(Foo)` here
481+
let parent_def_id = tcx.local_parent(def_id);
482+
let parent_preds = tcx.explicit_predicates_of(parent_def_id);
483+
484+
// If we dont filter out `ConstArgHasType` predicates then every single defaulted const parameter
485+
// will ICE because of #106994. FIXME(generic_const_exprs): remove this when a more general solution
486+
// to #106994 is implemented.
487+
let filtered_predicates = parent_preds
488+
.predicates
489+
.into_iter()
490+
.filter(|(pred, _)| {
491+
if let ty::ClauseKind::ConstArgHasType(ct, _) = pred.kind().skip_binder() {
492+
match ct.kind() {
493+
ty::ConstKind::Param(param_const) => {
494+
let defaulted_param_idx = tcx
495+
.generics_of(parent_def_id)
496+
.param_def_id_to_index[&defaulted_param_def_id.to_def_id()];
497+
param_const.index < defaulted_param_idx
504498
}
505-
} else {
506-
true
499+
_ => bug!(
500+
"`ConstArgHasType` in `predicates_of`\
501+
that isn't a `Param` const"
502+
),
507503
}
508-
})
509-
.cloned();
510-
return GenericPredicates {
511-
parent: parent_preds.parent,
512-
predicates: { tcx.arena.alloc_from_iter(filtered_predicates) },
513-
};
514-
}
515-
516-
let parent_def_kind = tcx.def_kind(parent_def_id);
517-
if matches!(parent_def_kind, DefKind::OpaqueTy) {
518-
// In `instantiate_identity` we inherit the predicates of our parent.
519-
// However, opaque types do not have a parent (see `gather_explicit_predicates_of`), which means
520-
// that we lose out on the predicates of our actual parent if we dont return those predicates here.
521-
//
522-
//
523-
// fn foo<T: Trait>() -> impl Iterator<Output = Another<{ <T as Trait>::ASSOC }> > { todo!() }
524-
// ^^^^^^^^^^^^^^^^^^^ the def id we are calling
525-
// explicit_predicates_of on
526-
//
527-
// In the above code we want the anon const to have predicates in its param env for `T: Trait`.
528-
// However, the anon const cannot inherit predicates from its parent since it's opaque.
529-
//
530-
// To fix this, we call `explicit_predicates_of` directly on `foo`, the parent's parent.
531-
532-
// In the above example this is `foo::{opaque#0}` or `impl Iterator`
533-
let parent_hir_id = tcx.local_def_id_to_hir_id(parent_def_id.def_id);
534-
535-
// In the above example this is the function `foo`
536-
let item_def_id = tcx.hir().get_parent_item(parent_hir_id);
537-
538-
// In the above code example we would be calling `explicit_predicates_of(foo)` here
539-
return tcx.explicit_predicates_of(item_def_id);
540-
}
504+
} else {
505+
true
506+
}
507+
})
508+
.cloned();
509+
return GenericPredicates {
510+
parent: parent_preds.parent,
511+
predicates: { tcx.arena.alloc_from_iter(filtered_predicates) },
512+
};
541513
}
542514
gather_explicit_predicates_of(tcx, def_id)
543515
}

Diff for: tests/crashes/118403.rs

-8
This file was deleted.

Diff for: tests/crashes/121574-2.rs

-8
This file was deleted.

Diff for: tests/crashes/121574.rs

-6
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//@ check-pass
2+
3+
#![feature(generic_const_exprs)]
4+
//~^ WARN the feature `generic_const_exprs` is incomplete and may not be safe to use
5+
6+
pub fn y<'a, U: 'a>() -> impl IntoIterator<Item = impl IntoIterator<Item = [u8; { 1 + 2 }]> + 'a> {
7+
[[[1, 2, 3]]]
8+
}
9+
// Make sure that the `predicates_of` for `{ 1 + 2 }` don't mention the duplicated lifetimes of
10+
// the *outer* iterator. Whether they should mention the duplicated lifetimes of the *inner*
11+
// iterator are another question, but not really something we need to answer immediately.
12+
13+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/double-opaque-parent-predicates.rs:3:12
3+
|
4+
LL | #![feature(generic_const_exprs)]
5+
| ^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
8+
= note: `#[warn(incomplete_features)]` on by default
9+
10+
warning: 1 warning emitted
11+

0 commit comments

Comments
 (0)