Auto merge of #113215 - compiler-errors:rpitit-predicates-tweaks, r=spastorino
Make RPITITs assume/require their parent method's predicates Removes a FIXME from the `param_env` query where we were manually adding the parent function's predicates to the RPITIT's assumptions. r? `@spastorino`
This commit is contained in:
commit
0130c3a06e
8 changed files with 76 additions and 41 deletions
|
@ -63,7 +63,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||||
use rustc_hir::*;
|
use rustc_hir::*;
|
||||||
|
|
||||||
match tcx.opt_rpitit_info(def_id.to_def_id()) {
|
match tcx.opt_rpitit_info(def_id.to_def_id()) {
|
||||||
Some(ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
|
Some(ImplTraitInTraitData::Trait { opaque_def_id, fn_def_id }) => {
|
||||||
let opaque_ty_id = tcx.hir().local_def_id_to_hir_id(opaque_def_id.expect_local());
|
let opaque_ty_id = tcx.hir().local_def_id_to_hir_id(opaque_def_id.expect_local());
|
||||||
let opaque_ty_node = tcx.hir().get(opaque_ty_id);
|
let opaque_ty_node = tcx.hir().get(opaque_ty_id);
|
||||||
let Node::Item(&Item { kind: ItemKind::OpaqueTy(OpaqueTy { lifetime_mapping, .. }), .. }) = opaque_ty_node else {
|
let Node::Item(&Item { kind: ItemKind::OpaqueTy(OpaqueTy { lifetime_mapping, .. }), .. }) = opaque_ty_node else {
|
||||||
|
@ -71,6 +71,18 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut predicates = Vec::new();
|
let mut predicates = Vec::new();
|
||||||
|
|
||||||
|
// RPITITs should inherit the predicates of their parent. This is
|
||||||
|
// both to ensure that the RPITITs are only instantiated when the
|
||||||
|
// parent predicates would hold, and also so that the param-env
|
||||||
|
// inherits these predicates as assumptions.
|
||||||
|
let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
|
||||||
|
predicates.extend(
|
||||||
|
tcx.explicit_predicates_of(fn_def_id).instantiate_own(tcx, identity_substs),
|
||||||
|
);
|
||||||
|
|
||||||
|
// We also install bidirectional outlives predicates for the RPITIT
|
||||||
|
// to keep the duplicates lifetimes from opaque lowering in sync.
|
||||||
compute_bidirectional_outlives_predicates(
|
compute_bidirectional_outlives_predicates(
|
||||||
tcx,
|
tcx,
|
||||||
def_id,
|
def_id,
|
||||||
|
@ -89,12 +101,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||||
|
|
||||||
Some(ImplTraitInTraitData::Impl { fn_def_id }) => {
|
Some(ImplTraitInTraitData::Impl { fn_def_id }) => {
|
||||||
let assoc_item = tcx.associated_item(def_id);
|
let assoc_item = tcx.associated_item(def_id);
|
||||||
let trait_assoc_predicates = tcx.predicates_of(assoc_item.trait_item_def_id.unwrap());
|
let trait_assoc_predicates =
|
||||||
|
tcx.explicit_predicates_of(assoc_item.trait_item_def_id.unwrap());
|
||||||
|
|
||||||
let impl_assoc_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
|
let impl_assoc_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
|
||||||
let impl_def_id = tcx.parent(fn_def_id);
|
let impl_def_id = tcx.parent(fn_def_id);
|
||||||
let impl_trait_ref_substs =
|
let impl_trait_ref_substs =
|
||||||
tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder().substs;
|
tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity().substs;
|
||||||
|
|
||||||
let impl_assoc_substs =
|
let impl_assoc_substs =
|
||||||
impl_assoc_identity_substs.rebase_onto(tcx, impl_def_id, impl_trait_ref_substs);
|
impl_assoc_identity_substs.rebase_onto(tcx, impl_def_id, impl_trait_ref_substs);
|
||||||
|
|
|
@ -574,7 +574,9 @@ fn foo(&self) -> Self::T { String::new() }
|
||||||
let Some(hir_id) = body_owner_def_id.as_local() else {
|
let Some(hir_id) = body_owner_def_id.as_local() else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
let hir_id = tcx.hir().local_def_id_to_hir_id(hir_id);
|
let Some(hir_id) = tcx.opt_local_def_id_to_hir_id(hir_id) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
// When `body_owner` is an `impl` or `trait` item, look in its associated types for
|
// When `body_owner` is an `impl` or `trait` item, look in its associated types for
|
||||||
// `expected` and point at it.
|
// `expected` and point at it.
|
||||||
let parent_id = tcx.hir().get_parent_item(hir_id);
|
let parent_id = tcx.hir().get_parent_item(hir_id);
|
||||||
|
|
|
@ -1151,10 +1151,10 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
|
||||||
let assoc_item = tcx.associated_item(def_id);
|
let assoc_item = tcx.associated_item(def_id);
|
||||||
match assoc_item.container {
|
match assoc_item.container {
|
||||||
ty::AssocItemContainer::ImplContainer => true,
|
ty::AssocItemContainer::ImplContainer => true,
|
||||||
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) always encode RPITITs,
|
// Always encode RPITITs, since we need to be able to project
|
||||||
// since we need to be able to "project" from an RPITIT associated item
|
// from an RPITIT associated item to an opaque when installing
|
||||||
// to an opaque when installing the default projection predicates in
|
// the default projection predicates in default trait methods
|
||||||
// default trait methods with RPITITs.
|
// with RPITITs.
|
||||||
ty::AssocItemContainer::TraitContainer => {
|
ty::AssocItemContainer::TraitContainer => {
|
||||||
assoc_item.defaultness(tcx).has_value() || assoc_item.opt_rpitit_info.is_some()
|
assoc_item.defaultness(tcx).has_value() || assoc_item.opt_rpitit_info.is_some()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,7 @@ use rustc_hir::def::DefKind;
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, EarlyBinder, ImplTraitInTraitData, ToPredicate, Ty, TyCtxt, TypeSuperVisitable,
|
self, EarlyBinder, ToPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
|
||||||
TypeVisitable, TypeVisitor,
|
|
||||||
};
|
};
|
||||||
use rustc_session::config::TraitSolver;
|
use rustc_session::config::TraitSolver;
|
||||||
use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
|
use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
|
||||||
|
@ -120,22 +119,6 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
|
||||||
let ty::InstantiatedPredicates { mut predicates, .. } =
|
let ty::InstantiatedPredicates { mut predicates, .. } =
|
||||||
tcx.predicates_of(def_id).instantiate_identity(tcx);
|
tcx.predicates_of(def_id).instantiate_identity(tcx);
|
||||||
|
|
||||||
// When computing the param_env of an RPITIT, use predicates of the containing function,
|
|
||||||
// *except* for the additional assumption that the RPITIT normalizes to the trait method's
|
|
||||||
// default opaque type. This is needed to properly check the item bounds of the assoc
|
|
||||||
// type hold (`check_type_bounds`), since that method already installs a similar projection
|
|
||||||
// bound, so they will conflict.
|
|
||||||
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): I don't like this, we should
|
|
||||||
// at least be making sure that the generics in RPITITs and their parent fn don't
|
|
||||||
// get out of alignment, or else we do actually need to substitute these predicates.
|
|
||||||
if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. })
|
|
||||||
| Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id)
|
|
||||||
{
|
|
||||||
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Should not need to add the predicates
|
|
||||||
// from the parent fn to our assumptions
|
|
||||||
predicates.extend(tcx.predicates_of(fn_def_id).instantiate_identity(tcx).predicates);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, we have to normalize the bounds in the environment, in
|
// Finally, we have to normalize the bounds in the environment, in
|
||||||
// case they contain any associated type projections. This process
|
// case they contain any associated type projections. This process
|
||||||
// can yield errors if the put in illegal associated types, like
|
// can yield errors if the put in illegal associated types, like
|
||||||
|
|
|
@ -6,11 +6,7 @@ LL | MyTrait::foo(&self)
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
help: consider removing the leading `&`-reference
|
= help: the trait `MyTrait` is implemented for `Outer`
|
||||||
|
|
|
||||||
LL - MyTrait::foo(&self)
|
|
||||||
LL + MyTrait::foo(self)
|
|
||||||
|
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
|
error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
|
||||||
--> $DIR/issue-102140.rs:26:9
|
--> $DIR/issue-102140.rs:26:9
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||||
--> $DIR/wf-bounds.rs:13:22
|
--> $DIR/wf-bounds.rs:17:22
|
||||||
|
|
|
|
||||||
LL | fn nya() -> impl Wf<Vec<[u8]>>;
|
LL | fn nya() -> impl Wf<Vec<[u8]>>;
|
||||||
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||||
|
@ -9,14 +9,14 @@ note: required by a bound in `Vec`
|
||||||
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||||
|
|
||||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||||
--> $DIR/wf-bounds.rs:16:23
|
--> $DIR/wf-bounds.rs:20:23
|
||||||
|
|
|
|
||||||
LL | fn nya2() -> impl Wf<[u8]>;
|
LL | fn nya2() -> impl Wf<[u8]>;
|
||||||
| ^^^^^^^^ doesn't have a size known at compile-time
|
| ^^^^^^^^ doesn't have a size known at compile-time
|
||||||
|
|
|
|
||||||
= help: the trait `Sized` is not implemented for `[u8]`
|
= help: the trait `Sized` is not implemented for `[u8]`
|
||||||
note: required by a bound in `Wf`
|
note: required by a bound in `Wf`
|
||||||
--> $DIR/wf-bounds.rs:8:10
|
--> $DIR/wf-bounds.rs:10:10
|
||||||
|
|
|
|
||||||
LL | trait Wf<T> {
|
LL | trait Wf<T> {
|
||||||
| ^ required by this bound in `Wf`
|
| ^ required by this bound in `Wf`
|
||||||
|
@ -26,7 +26,7 @@ LL | trait Wf<T: ?Sized> {
|
||||||
| ++++++++
|
| ++++++++
|
||||||
|
|
||||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||||
--> $DIR/wf-bounds.rs:19:44
|
--> $DIR/wf-bounds.rs:23:44
|
||||||
|
|
|
|
||||||
LL | fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
|
LL | fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
|
||||||
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||||
|
@ -35,6 +35,23 @@ LL | fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
|
||||||
note: required by a bound in `Vec`
|
note: required by a bound in `Vec`
|
||||||
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error[E0277]: `T` doesn't implement `std::fmt::Display`
|
||||||
|
--> $DIR/wf-bounds.rs:26:26
|
||||||
|
|
|
||||||
|
LL | fn nya4<T>() -> impl Wf<NeedsDisplay<T>>;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
|
||||||
|
|
|
||||||
|
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
|
||||||
|
note: required by a bound in `NeedsDisplay`
|
||||||
|
--> $DIR/wf-bounds.rs:14:24
|
||||||
|
|
|
||||||
|
LL | struct NeedsDisplay<T: Display>(T);
|
||||||
|
| ^^^^^^^ required by this bound in `NeedsDisplay`
|
||||||
|
help: consider restricting type parameter `T`
|
||||||
|
|
|
||||||
|
LL | fn nya4<T: std::fmt::Display>() -> impl Wf<NeedsDisplay<T>>;
|
||||||
|
| +++++++++++++++++++
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||||
--> $DIR/wf-bounds.rs:13:22
|
--> $DIR/wf-bounds.rs:17:22
|
||||||
|
|
|
|
||||||
LL | fn nya() -> impl Wf<Vec<[u8]>>;
|
LL | fn nya() -> impl Wf<Vec<[u8]>>;
|
||||||
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||||
|
@ -9,14 +9,14 @@ note: required by a bound in `Vec`
|
||||||
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||||
|
|
||||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||||
--> $DIR/wf-bounds.rs:16:23
|
--> $DIR/wf-bounds.rs:20:23
|
||||||
|
|
|
|
||||||
LL | fn nya2() -> impl Wf<[u8]>;
|
LL | fn nya2() -> impl Wf<[u8]>;
|
||||||
| ^^^^^^^^ doesn't have a size known at compile-time
|
| ^^^^^^^^ doesn't have a size known at compile-time
|
||||||
|
|
|
|
||||||
= help: the trait `Sized` is not implemented for `[u8]`
|
= help: the trait `Sized` is not implemented for `[u8]`
|
||||||
note: required by a bound in `Wf`
|
note: required by a bound in `Wf`
|
||||||
--> $DIR/wf-bounds.rs:8:10
|
--> $DIR/wf-bounds.rs:10:10
|
||||||
|
|
|
|
||||||
LL | trait Wf<T> {
|
LL | trait Wf<T> {
|
||||||
| ^ required by this bound in `Wf`
|
| ^ required by this bound in `Wf`
|
||||||
|
@ -26,7 +26,7 @@ LL | trait Wf<T: ?Sized> {
|
||||||
| ++++++++
|
| ++++++++
|
||||||
|
|
||||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||||
--> $DIR/wf-bounds.rs:19:44
|
--> $DIR/wf-bounds.rs:23:44
|
||||||
|
|
|
|
||||||
LL | fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
|
LL | fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
|
||||||
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||||
|
@ -35,6 +35,23 @@ LL | fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
|
||||||
note: required by a bound in `Vec`
|
note: required by a bound in `Vec`
|
||||||
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error[E0277]: `T` doesn't implement `std::fmt::Display`
|
||||||
|
--> $DIR/wf-bounds.rs:26:26
|
||||||
|
|
|
||||||
|
LL | fn nya4<T>() -> impl Wf<NeedsDisplay<T>>;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
|
||||||
|
|
|
||||||
|
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
|
||||||
|
note: required by a bound in `NeedsDisplay`
|
||||||
|
--> $DIR/wf-bounds.rs:14:24
|
||||||
|
|
|
||||||
|
LL | struct NeedsDisplay<T: Display>(T);
|
||||||
|
| ^^^^^^^ required by this bound in `NeedsDisplay`
|
||||||
|
help: consider restricting type parameter `T`
|
||||||
|
|
|
||||||
|
LL | fn nya4<T: std::fmt::Display>() -> impl Wf<NeedsDisplay<T>>;
|
||||||
|
| +++++++++++++++++++
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
|
|
@ -5,10 +5,14 @@
|
||||||
#![feature(return_position_impl_trait_in_trait)]
|
#![feature(return_position_impl_trait_in_trait)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
trait Wf<T> {
|
trait Wf<T> {
|
||||||
type Output;
|
type Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct NeedsDisplay<T: Display>(T);
|
||||||
|
|
||||||
trait Uwu {
|
trait Uwu {
|
||||||
fn nya() -> impl Wf<Vec<[u8]>>;
|
fn nya() -> impl Wf<Vec<[u8]>>;
|
||||||
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
|
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
|
||||||
|
@ -18,6 +22,9 @@ trait Uwu {
|
||||||
|
|
||||||
fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
|
fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
|
||||||
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
|
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
|
||||||
|
|
||||||
|
fn nya4<T>() -> impl Wf<NeedsDisplay<T>>;
|
||||||
|
//~^ ERROR `T` doesn't implement `std::fmt::Display`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue