1
Fork 0

Remove associated type based effects logic

This commit is contained in:
Michael Goulet 2024-10-20 20:22:11 +00:00
parent 8aca4bab08
commit a16d491054
73 changed files with 85 additions and 1519 deletions

View file

@ -3,13 +3,8 @@
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir::LangItem;
use rustc_hir::def::DefKind;
use rustc_middle::ty::fold::FnMutDelegate;
use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
use rustc_span::Span;
use rustc_span::def_id::DefId;
use crate::hir_ty_lowering::PredicateFilter;
/// Collects together a list of type bounds. These lists of bounds occur in many places
/// in Rust's syntax:
@ -47,12 +42,9 @@ impl<'tcx> Bounds<'tcx> {
pub(crate) fn push_trait_bound(
&mut self,
tcx: TyCtxt<'tcx>,
defining_def_id: DefId,
bound_trait_ref: ty::PolyTraitRef<'tcx>,
span: Span,
polarity: ty::PredicatePolarity,
constness: Option<ty::BoundConstness>,
predicate_filter: PredicateFilter,
) {
let clause = (
bound_trait_ref
@ -68,137 +60,6 @@ impl<'tcx> Bounds<'tcx> {
} else {
self.clauses.push(clause);
}
// FIXME(effects): Lift this out of `push_trait_bound`, and move it somewhere else.
// Perhaps moving this into `lower_poly_trait_ref`, just like we lower associated
// type bounds.
if !tcx.features().effects() {
return;
}
match predicate_filter {
PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => {
return;
}
PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
// Ok.
}
}
// For `T: ~const Tr` or `T: const Tr`, we need to add an additional bound on the
// associated type of `<T as Tr>` and make sure that the effect is compatible.
let compat_val = match (tcx.def_kind(defining_def_id), constness) {
// FIXME(effects): revisit the correctness of this
(_, Some(ty::BoundConstness::Const)) => tcx.consts.false_,
// body owners that can have trait bounds
(
DefKind::Const | DefKind::Fn | DefKind::AssocFn,
Some(ty::BoundConstness::ConstIfConst),
) => tcx.expected_host_effect_param_for_body(defining_def_id),
(_, None) => {
if !tcx.is_const_trait(bound_trait_ref.def_id()) {
return;
}
tcx.consts.true_
}
(DefKind::Trait, Some(ty::BoundConstness::ConstIfConst)) => {
// we are in a trait, where `bound_trait_ref` could be:
// (1) a super trait `trait Foo: ~const Bar`.
// - This generates `<Self as Foo>::Effects: TyCompat<<Self as Bar>::Effects>`
//
// (2) a where clause `where for<..> Something: ~const Bar`.
// - This generates `for<..> <Self as Foo>::Effects: TyCompat<<Something as Bar>::Effects>`
let Some(own_fx) = tcx.associated_type_for_effects(defining_def_id) else {
tcx.dcx().span_delayed_bug(span, "should not have allowed `~const` on a trait that doesn't have `#[const_trait]`");
return;
};
let own_fx_ty = Ty::new_projection(
tcx,
own_fx,
ty::GenericArgs::identity_for_item(tcx, own_fx),
);
let Some(their_fx) = tcx.associated_type_for_effects(bound_trait_ref.def_id())
else {
tcx.dcx().span_delayed_bug(span, "`~const` on trait without Effects assoc");
return;
};
let their_fx_ty =
Ty::new_projection(tcx, their_fx, bound_trait_ref.skip_binder().args);
let compat = tcx.require_lang_item(LangItem::EffectsTyCompat, Some(span));
let clause = bound_trait_ref
.map_bound(|_| {
let trait_ref = ty::TraitRef::new(tcx, compat, [own_fx_ty, their_fx_ty]);
ty::ClauseKind::Trait(ty::TraitPredicate {
trait_ref,
polarity: ty::PredicatePolarity::Positive,
})
})
.upcast(tcx);
self.clauses.push((clause, span));
return;
}
(DefKind::Impl { of_trait: true }, Some(ty::BoundConstness::ConstIfConst)) => {
// this is a where clause on an impl header.
// push `<T as Tr>::Effects` into the set for the `Min` bound.
let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else {
tcx.dcx().span_delayed_bug(span, "`~const` on trait without Effects assoc");
return;
};
let ty = bound_trait_ref
.map_bound(|trait_ref| Ty::new_projection(tcx, assoc, trait_ref.args));
// When the user has written `for<'a, T> X<'a, T>: ~const Foo`, replace the
// binders to dummy ones i.e. `X<'static, ()>` so they can be referenced in
// the `Min` associated type properly (which doesn't allow using `for<>`)
// This should work for any bound variables as long as they don't have any
// bounds e.g. `for<T: Trait>`.
// FIXME(effects) reconsider this approach to allow compatibility with `for<T: Tr>`
let ty = tcx.replace_bound_vars_uncached(ty, FnMutDelegate {
regions: &mut |_| tcx.lifetimes.re_static,
types: &mut |_| tcx.types.unit,
consts: &mut |_| unimplemented!("`~const` does not support const binders"),
});
self.effects_min_tys.insert(ty, span);
return;
}
// for
// ```
// trait Foo { type Bar: ~const Trait }
// ```
// ensure that `<Self::Bar as Trait>::Effects: TyCompat<Self::Effects>`.
//
// FIXME(effects) this is equality for now, which wouldn't be helpful for a non-const implementor
// that uses a `Bar` that implements `Trait` with `Maybe` effects.
(DefKind::AssocTy, Some(ty::BoundConstness::ConstIfConst)) => {
// FIXME(effects): implement this
return;
}
// probably illegal in this position.
(_, Some(ty::BoundConstness::ConstIfConst)) => {
tcx.dcx().span_delayed_bug(span, "invalid `~const` encountered");
return;
}
};
// create a new projection type `<T as Tr>::Effects`
let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else {
tcx.dcx().span_delayed_bug(
span,
"`~const` trait bound has no effect assoc yet no errors encountered?",
);
return;
};
let self_ty = Ty::new_projection(tcx, assoc, bound_trait_ref.skip_binder().args);
// make `<T as Tr>::Effects: Compat<runtime>`
let new_trait_ref =
ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::EffectsCompat, Some(span)), [
ty::GenericArg::from(self_ty),
compat_val.into(),
]);
self.clauses.push((bound_trait_ref.rebind(new_trait_ref).upcast(tcx), span));
}
pub(crate) fn push_projection_bound(

View file

@ -58,15 +58,9 @@ fn equate_intrinsic_type<'tcx>(
// the host effect param should be invisible as it shouldn't matter
// whether effects is enabled for the intrinsic provider crate.
let consts_count = if generics.host_effect_index.is_some() {
own_counts.consts - 1
} else {
own_counts.consts
};
if gen_count_ok(own_counts.lifetimes, n_lts, "lifetime")
&& gen_count_ok(own_counts.types, n_tps, "type")
&& gen_count_ok(consts_count, n_cts, "const")
&& gen_count_ok(own_counts.consts, n_cts, "const")
{
let _ = check_function_signature(
tcx,

View file

@ -913,12 +913,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => Ok(()),
// Const parameters are well formed if their type is structural match.
hir::GenericParamKind::Const {
ty: hir_ty,
default: _,
is_host_effect: _,
synthetic: _,
} => {
hir::GenericParamKind::Const { ty: hir_ty, default: _, synthetic: _ } => {
let ty = tcx.type_of(param.def_id).instantiate_identity();
if tcx.features().unsized_const_params() {

View file

@ -53,7 +53,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
param_def_id_to_index,
has_self: opaque_ty_generics.has_self,
has_late_bound_regions: opaque_ty_generics.has_late_bound_regions,
host_effect_index: parent_generics.host_effect_index,
};
}
@ -161,7 +160,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
param_def_id_to_index,
has_self: generics.has_self,
has_late_bound_regions: generics.has_late_bound_regions,
host_effect_index: None,
};
} else {
// HACK(eddyb) this provides the correct generics when
@ -292,12 +290,10 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
let has_self = opt_self.is_some();
let mut parent_has_self = false;
let mut own_start = has_self as u32;
let mut host_effect_index = None;
let parent_count = parent_def_id.map_or(0, |def_id| {
let generics = tcx.generics_of(def_id);
assert!(!has_self);
parent_has_self = generics.has_self;
host_effect_index = generics.host_effect_index;
own_start = generics.count() as u32;
generics.parent_count + generics.own_params.len()
});
@ -361,12 +357,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
kind,
})
}
GenericParamKind::Const { ty: _, default, is_host_effect, synthetic } => {
if !matches!(allow_defaults, Defaults::Allowed)
&& default.is_some()
// `host` effect params are allowed to have defaults.
&& !is_host_effect
{
GenericParamKind::Const { ty: _, default, synthetic } => {
if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() {
tcx.dcx().span_err(
param.span,
"defaults for const parameters are only allowed in \
@ -376,27 +368,12 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
let index = next_index();
if is_host_effect {
if let Some(idx) = host_effect_index {
tcx.dcx().span_delayed_bug(
param.span,
format!("parent also has host effect param? index: {idx}, def: {def_id:?}"),
);
}
host_effect_index = Some(index as usize);
}
Some(ty::GenericParamDef {
index,
name: param.name.ident().name,
def_id: param.def_id.to_def_id(),
pure_wrt_drop: param.pure_wrt_drop,
kind: ty::GenericParamDefKind::Const {
has_default: default.is_some(),
is_host_effect,
synthetic,
},
kind: ty::GenericParamDefKind::Const { has_default: default.is_some(), synthetic },
})
}
}));
@ -459,7 +436,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
param_def_id_to_index,
has_self: has_self || parent_has_self,
has_late_bound_regions: has_late_bound_regions(tcx, node),
host_effect_index,
}
}
@ -540,8 +516,7 @@ impl<'v> Visitor<'v> for AnonConstInParamTyDetector {
type Result = ControlFlow<()>;
fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) -> Self::Result {
if let GenericParamKind::Const { ty, default: _, is_host_effect: _, synthetic: _ } = p.kind
{
if let GenericParamKind::Const { ty, default: _, synthetic: _ } = p.kind {
let prev = self.in_param_ty;
self.in_param_ty = true;
let res = self.visit_ty(ty);

View file

@ -78,7 +78,6 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
#[instrument(level = "trace", skip(tcx), ret)]
fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> {
use rustc_hir::*;
use rustc_middle::ty::Ty;
match tcx.opt_rpitit_info(def_id.to_def_id()) {
Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) => {
@ -345,26 +344,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
debug!(?predicates);
}
// add `Self::Effects: Compat<HOST>` to ensure non-const impls don't get called
// in const contexts.
if let Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(..), .. }) = node
&& let Some(host_effect_index) = generics.host_effect_index
{
let parent = generics.parent.unwrap();
let Some(assoc_def_id) = tcx.associated_type_for_effects(parent) else {
bug!("associated_type_for_effects returned None when there is host effect in generics");
};
let effects =
Ty::new_projection(tcx, assoc_def_id, ty::GenericArgs::identity_for_item(tcx, parent));
let param = generics.param_at(host_effect_index, tcx);
let span = tcx.def_span(param.def_id);
let host = ty::Const::new_param(tcx, ty::ParamConst::for_def(param));
let compat = tcx.require_lang_item(LangItem::EffectsCompat, Some(span));
let trait_ref =
ty::TraitRef::new(tcx, compat, [ty::GenericArg::from(effects), host.into()]);
predicates.push((ty::Binder::dummy(trait_ref).upcast(tcx), span));
}
ty::GenericPredicates {
parent: generics.parent,
predicates: tcx.arena.alloc_from_iter(predicates),

View file

@ -186,7 +186,6 @@ impl<'tcx> GenericsBuilder<'tcx> {
param_def_id_to_index,
has_self,
has_late_bound_regions: sig_generics.has_late_bound_regions,
host_effect_index: sig_generics.host_effect_index,
}
}
}
@ -472,10 +471,6 @@ fn check_constraints<'tcx>(
}));
};
if tcx.has_host_param(sig_id) {
emit("delegation to a function with effect parameter is not supported yet");
}
if let Some(local_sig_id) = sig_id.as_local()
&& tcx.hir().opt_delegation_sig_id(local_sig_id).is_some()
{

View file

@ -694,15 +694,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
);
debug!(?poly_trait_ref);
bounds.push_trait_bound(
tcx,
self.item_def_id().to_def_id(),
poly_trait_ref,
span,
polarity,
constness,
predicate_filter,
);
bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);
let mut dup_constraints = FxIndexMap::default();
for constraint in trait_segment.args().constraints {