Remove associated type based effects logic
This commit is contained in:
parent
8aca4bab08
commit
a16d491054
73 changed files with 85 additions and 1519 deletions
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue