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

@ -57,7 +57,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
owner: NodeId,
f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>,
) {
let mut lctx = LoweringContext::new(self.tcx, self.resolver, self.ast_index);
let mut lctx = LoweringContext::new(self.tcx, self.resolver);
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
for (def_id, info) in lctx.children {
@ -193,8 +193,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
ItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
let (generics, (ty, body_id)) = self.lower_generics(
generics,
Const::No,
false,
id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
@ -225,16 +223,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
let itctx = ImplTraitContext::Universal;
let (generics, decl) =
this.lower_generics(generics, header.constness, false, id, itctx, |this| {
this.lower_fn_decl(
decl,
id,
*fn_sig_span,
FnDeclKind::Fn,
coroutine_kind,
)
});
let (generics, decl) = this.lower_generics(generics, id, itctx, |this| {
this.lower_fn_decl(decl, id, *fn_sig_span, FnDeclKind::Fn, coroutine_kind)
});
let sig = hir::FnSig {
decl,
header: this.lower_fn_header(*header, hir::Safety::Safe),
@ -269,8 +260,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
add_ty_alias_where_clause(&mut generics, *where_clauses, true);
let (generics, ty) = self.lower_generics(
&generics,
Const::No,
false,
id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| match ty {
@ -294,8 +283,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
ItemKind::Enum(enum_definition, generics) => {
let (generics, variants) = self.lower_generics(
generics,
Const::No,
false,
id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
@ -309,8 +296,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
ItemKind::Struct(struct_def, generics) => {
let (generics, struct_def) = self.lower_generics(
generics,
Const::No,
false,
id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| this.lower_variant_data(hir_id, struct_def),
@ -320,8 +305,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
ItemKind::Union(vdata, generics) => {
let (generics, vdata) = self.lower_generics(
generics,
Const::No,
false,
id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| this.lower_variant_data(hir_id, vdata),
@ -353,7 +336,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// parent lifetime.
let itctx = ImplTraitContext::Universal;
let (generics, (trait_ref, lowered_ty)) =
self.lower_generics(ast_generics, Const::No, false, id, itctx, |this| {
self.lower_generics(ast_generics, id, itctx, |this| {
let modifiers = TraitBoundModifiers {
constness: BoundConstness::Never,
asyncness: BoundAsyncness::Normal,
@ -405,8 +388,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
ItemKind::Trait(box Trait { is_auto, safety, generics, bounds, items }) => {
let (generics, (safety, items, bounds)) = self.lower_generics(
generics,
Const::No,
false,
id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
@ -426,8 +407,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
ItemKind::TraitAlias(generics, bounds) => {
let (generics, bounds) = self.lower_generics(
generics,
Const::No,
false,
id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
@ -604,50 +583,23 @@ impl<'hir> LoweringContext<'_, 'hir> {
ctxt: AssocCtxt,
parent_hir: &'hir hir::OwnerInfo<'hir>,
) -> hir::OwnerNode<'hir> {
// Evaluate with the lifetimes in `params` in-scope.
// This is used to track which lifetimes have already been defined,
// and which need to be replicated when lowering an async fn.
let parent_item = parent_hir.node().expect_item();
let constness = match parent_item.kind {
match parent_item.kind {
hir::ItemKind::Impl(impl_) => {
self.is_in_trait_impl = impl_.of_trait.is_some();
// N.B. the impl should always lower to methods that have `const host: bool` params if the trait
// is const. It doesn't matter whether the `impl` itself is const. Disallowing const fn from
// calling non-const impls are done through associated types.
if let Some(def_id) = impl_.of_trait.and_then(|tr| tr.trait_def_id()) {
if let Some(local_def) = def_id.as_local() {
match &self.ast_index[local_def] {
AstOwner::Item(ast::Item { attrs, .. }) => attrs
.iter()
.find(|attr| attr.has_name(sym::const_trait))
.map_or(Const::No, |attr| Const::Yes(attr.span)),
_ => Const::No,
}
} else if self.tcx.is_const_trait(def_id) {
// FIXME(effects) span
Const::Yes(self.tcx.def_ident_span(def_id).unwrap())
} else {
Const::No
}
} else {
Const::No
}
}
hir::ItemKind::Trait(_, _, _, _, _) => parent_hir
.attrs
.get(parent_item.hir_id().local_id)
.iter()
.find(|attr| attr.has_name(sym::const_trait))
.map_or(Const::No, |attr| Const::Yes(attr.span)),
hir::ItemKind::Trait(_, _, _, _, _) => {}
kind => {
span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr())
}
};
}
// Evaluate with the lifetimes in `params` in-scope.
// This is used to track which lifetimes have already been defined,
// and which need to be replicated when lowering an async fn.
match ctxt {
AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item, constness)),
AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item, constness)),
AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)),
AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item)),
}
}
@ -663,7 +615,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let fdec = &sig.decl;
let itctx = ImplTraitContext::Universal;
let (generics, (decl, fn_args)) =
self.lower_generics(generics, Const::No, false, i.id, itctx, |this| {
self.lower_generics(generics, i.id, itctx, |this| {
(
// Disallow `impl Trait` in foreign items.
this.lower_fn_decl(
@ -775,11 +727,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}
fn lower_trait_item(
&mut self,
i: &AssocItem,
trait_constness: Const,
) -> &'hir hir::TraitItem<'hir> {
fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
let hir_id = self.lower_node_id(i.id);
self.lower_attrs(hir_id, &i.attrs);
let trait_item_def_id = hir_id.expect_owner();
@ -788,8 +736,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => {
let (generics, kind) = self.lower_generics(
generics,
Const::No,
false,
i.id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
@ -810,7 +756,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
i.id,
FnDeclKind::Trait,
sig.header.coroutine_kind,
trait_constness,
);
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
}
@ -829,7 +774,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
i.id,
FnDeclKind::Trait,
sig.header.coroutine_kind,
trait_constness,
);
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
}
@ -838,8 +782,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
add_ty_alias_where_clause(&mut generics, *where_clauses, false);
let (generics, kind) = self.lower_generics(
&generics,
Const::No,
false,
i.id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
@ -912,11 +854,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.expr(span, hir::ExprKind::Err(guar))
}
fn lower_impl_item(
&mut self,
i: &AssocItem,
constness_of_trait: Const,
) -> &'hir hir::ImplItem<'hir> {
fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
// Since `default impl` is not yet implemented, this is always true in impls.
let has_value = true;
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
@ -926,8 +864,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (generics, kind) = match &i.kind {
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
generics,
Const::No,
false,
i.id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
@ -953,7 +889,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
i.id,
if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
sig.header.coroutine_kind,
constness_of_trait,
);
(generics, hir::ImplItemKind::Fn(sig, body_id))
@ -963,8 +898,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
add_ty_alias_where_clause(&mut generics, *where_clauses, false);
self.lower_generics(
&generics,
Const::No,
false,
i.id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| match ty {
@ -1370,18 +1303,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
id: NodeId,
kind: FnDeclKind,
coroutine_kind: Option<CoroutineKind>,
parent_constness: Const,
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
let header = self.lower_fn_header(sig.header, hir::Safety::Safe);
// Don't pass along the user-provided constness of trait associated functions; we don't want to
// synthesize a host effect param for them. We reject `const` on them during AST validation.
let constness =
if kind == FnDeclKind::Inherent { sig.header.constness } else { parent_constness };
let itctx = ImplTraitContext::Universal;
let (generics, decl) =
self.lower_generics(generics, constness, kind == FnDeclKind::Impl, id, itctx, |this| {
this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)
});
let (generics, decl) = self.lower_generics(generics, id, itctx, |this| {
this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)
});
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
}
@ -1460,8 +1387,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_generics<T>(
&mut self,
generics: &Generics,
constness: Const,
force_append_constness: bool,
parent_node_id: NodeId,
itctx: ImplTraitContext,
f: impl FnOnce(&mut Self) -> T,
@ -1524,30 +1449,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}
// Desugar `~const` bound in generics into an additional `const host: bool` param
// if the effects feature is enabled. This needs to be done before we lower where
// clauses since where clauses need to bind to the DefId of the host param
let host_param_parts = if let Const::Yes(span) = constness
// if this comes from implementing a `const` trait, we must force constness to be appended
// to the impl item, no matter whether effects is enabled.
&& (self.tcx.features().effects() || force_append_constness)
{
let span = self.lower_span(span);
let param_node_id = self.next_node_id();
let hir_id = self.next_id();
let def_id = self.create_def(
self.local_def_id(parent_node_id),
param_node_id,
sym::host,
DefKind::ConstParam,
span,
);
self.host_param_id = Some(def_id);
Some((span, hir_id, def_id))
} else {
None
};
let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new();
predicates.extend(generics.params.iter().filter_map(|param| {
self.lower_generic_bound_predicate(
@ -1595,74 +1496,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);
predicates.extend(impl_trait_bounds.into_iter());
if let Some((span, hir_id, def_id)) = host_param_parts {
let const_node_id = self.next_node_id();
let anon_const_did =
self.create_def(def_id, const_node_id, kw::Empty, DefKind::AnonConst, span);
let const_id = self.next_id();
let const_expr_id = self.next_id();
let bool_id = self.next_id();
self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
self.children.push((anon_const_did, hir::MaybeOwner::NonOwner(const_id)));
let const_body = self.lower_body(|this| {
(&[], hir::Expr {
hir_id: const_expr_id,
kind: hir::ExprKind::Lit(
this.arena.alloc(hir::Lit { node: LitKind::Bool(true), span }),
),
span,
})
});
let default_ac = self.arena.alloc(hir::AnonConst {
def_id: anon_const_did,
hir_id: const_id,
body: const_body,
span,
});
let default_ct = self.arena.alloc(hir::ConstArg {
hir_id: self.next_id(),
kind: hir::ConstArgKind::Anon(default_ac),
is_desugared_from_effects: false,
});
let param = hir::GenericParam {
def_id,
hir_id,
name: hir::ParamName::Plain(Ident { name: sym::host, span }),
span,
kind: hir::GenericParamKind::Const {
ty: self.arena.alloc(self.ty(
span,
hir::TyKind::Path(hir::QPath::Resolved(
None,
self.arena.alloc(hir::Path {
res: Res::PrimTy(hir::PrimTy::Bool),
span,
segments: self.arena.alloc_from_iter([hir::PathSegment {
ident: Ident { name: sym::bool, span },
hir_id: bool_id,
res: Res::PrimTy(hir::PrimTy::Bool),
args: None,
infer_args: false,
}]),
}),
)),
)),
default: Some(default_ct),
is_host_effect: true,
synthetic: true,
},
colon_span: None,
pure_wrt_drop: false,
source: hir::GenericParamSource::Generics,
};
params.push(param);
}
let lowered_generics = self.arena.alloc(hir::Generics {
params: self.arena.alloc_from_iter(params),
predicates: self.arena.alloc_from_iter(predicates),

View File

@ -154,17 +154,10 @@ struct LoweringContext<'a, 'hir> {
/// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this
/// field from the original parameter 'a to the new parameter 'a1.
generics_def_id_map: Vec<LocalDefIdMap<LocalDefId>>,
host_param_id: Option<LocalDefId>,
ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
}
impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn new(
tcx: TyCtxt<'hir>,
resolver: &'a mut ResolverAstLowering,
ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
) -> Self {
fn new(tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering) -> Self {
Self {
// Pseudo-globals.
tcx,
@ -204,8 +197,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// interact with `gen`/`async gen` blocks
allow_async_iterator: [sym::gen_future, sym::async_iterator].into(),
generics_def_id_map: Default::default(),
host_param_id: None,
ast_index,
}
}
@ -2054,11 +2045,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
param: &GenericParam,
source: hir::GenericParamSource,
) -> hir::GenericParam<'hir> {
let (name, kind) = self.lower_generic_param_kind(
param,
source,
attr::contains_name(&param.attrs, sym::rustc_runtime),
);
let (name, kind) = self.lower_generic_param_kind(param, source);
let hir_id = self.lower_node_id(param.id);
self.lower_attrs(hir_id, &param.attrs);
@ -2078,7 +2065,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&mut self,
param: &GenericParam,
source: hir::GenericParamSource,
is_host_effect: bool,
) -> (hir::ParamName, hir::GenericParamKind<'hir>) {
match &param.kind {
GenericParamKind::Lifetime => {
@ -2144,7 +2130,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
(
hir::ParamName::Plain(self.lower_ident(param.ident)),
hir::GenericParamKind::Const { ty, default, is_host_effect, synthetic: false },
hir::GenericParamKind::Const { ty, default, synthetic: false },
)
}
}

View File

@ -838,10 +838,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
rustc_const_panic_str, Normal, template!(Word), WarnFollowing,
EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
),
rustc_attr!(
rustc_runtime, Normal, template!(Word), WarnFollowing,
EncodeCrossCrate::No, INTERNAL_UNSTABLE
),
// ==========================================================================
// Internal attributes, Layout related:

View File

@ -580,7 +580,6 @@ pub enum GenericParamKind<'hir> {
ty: &'hir Ty<'hir>,
/// Optional default value for the const generic param
default: Option<&'hir ConstArg<'hir>>,
is_host_effect: bool,
synthetic: bool,
},
}

View File

@ -935,7 +935,7 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(
match param.kind {
GenericParamKind::Lifetime { .. } => {}
GenericParamKind::Type { ref default, .. } => visit_opt!(visitor, visit_ty, default),
GenericParamKind::Const { ref ty, ref default, is_host_effect: _, synthetic: _ } => {
GenericParamKind::Const { ref ty, ref default, synthetic: _ } => {
try_visit!(visitor.visit_ty(ty));
if let Some(ref default) = default {
try_visit!(visitor.visit_const_param_default(param.hir_id, default));

View File

@ -415,14 +415,6 @@ language_item_table! {
String, sym::String, string, Target::Struct, GenericRequirement::None;
CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None;
EffectsRuntime, sym::EffectsRuntime, effects_runtime, Target::Struct, GenericRequirement::None;
EffectsNoRuntime, sym::EffectsNoRuntime, effects_no_runtime, Target::Struct, GenericRequirement::None;
EffectsMaybe, sym::EffectsMaybe, effects_maybe, Target::Struct, GenericRequirement::None;
EffectsIntersection, sym::EffectsIntersection, effects_intersection, Target::Trait, GenericRequirement::None;
EffectsIntersectionOutput, sym::EffectsIntersectionOutput, effects_intersection_output, Target::AssocTy, GenericRequirement::None;
EffectsCompat, sym::EffectsCompat, effects_compat, Target::Trait, GenericRequirement::Exact(1);
EffectsTyCompat, sym::EffectsTyCompat, effects_ty_compat, Target::Trait, GenericRequirement::Exact(1);
}
pub enum GenericRequirement {

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 {

View File

@ -2134,7 +2134,7 @@ impl<'a> State<'a> {
self.print_type(default);
}
}
GenericParamKind::Const { ty, ref default, is_host_effect: _, synthetic: _ } => {
GenericParamKind::Const { ty, ref default, synthetic: _ } => {
self.word_space(":");
self.print_type(ty);
if let Some(default) = default {

View File

@ -20,7 +20,7 @@ use rustc_target::spec::abi;
use rustc_trait_selection::error_reporting::traits::DefIdOrName;
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use tracing::{debug, instrument, trace};
use tracing::{debug, instrument};
use super::method::MethodCallee;
use super::method::probe::ProbeScope;
@ -836,37 +836,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn_sig.output()
}
#[tracing::instrument(level = "debug", skip(self, span))]
#[tracing::instrument(level = "debug", skip(self, _span))]
pub(super) fn enforce_context_effects(
&self,
span: Span,
callee_did: DefId,
callee_args: GenericArgsRef<'tcx>,
_span: Span,
_callee_did: DefId,
_callee_args: GenericArgsRef<'tcx>,
) {
let tcx = self.tcx;
// fast-reject if callee doesn't have the host effect param (non-const)
let generics = tcx.generics_of(callee_did);
let Some(host_effect_index) = generics.host_effect_index else { return };
let effect = tcx.expected_host_effect_param_for_body(self.body_id);
trace!(?effect, ?generics, ?callee_args);
let param = callee_args.const_at(host_effect_index);
let cause = self.misc(span);
// We know the type of `effect` to be `bool`, there will be no opaque type inference.
match self.at(&cause, self.param_env).eq(infer::DefineOpaqueTypes::Yes, effect, param) {
Ok(infer::InferOk { obligations, value: () }) => {
self.register_predicates(obligations);
}
Err(e) => {
// FIXME(effects): better diagnostic
self.err_ctxt()
.report_mismatched_consts(&cause, self.param_env, effect, param, e)
.emit();
}
}
todo!()
}
fn confirm_overloaded_call(

View File

@ -7,8 +7,6 @@ use rustc_data_structures::unord::{UnordBag, UnordMap, UnordSet};
use rustc_hir as hir;
use rustc_hir::HirId;
use rustc_hir::intravisit::Visitor;
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
use rustc_middle::bug;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
use rustc_session::lint;
use rustc_span::def_id::LocalDefId;
@ -48,7 +46,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
self.fulfillment_cx.borrow_mut().pending_obligations()
);
let fallback_occurred = self.fallback_types() | self.fallback_effects();
let fallback_occurred = self.fallback_types();
if !fallback_occurred {
return;
@ -103,31 +101,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
fallback_occurred
}
fn fallback_effects(&self) -> bool {
let unsolved_effects = self.unsolved_effects();
if unsolved_effects.is_empty() {
return false;
}
// not setting the `fallback_has_occurred` field here because
// that field is only used for type fallback diagnostics.
for effect in unsolved_effects {
let expected = self.tcx.consts.true_;
let cause = self.misc(DUMMY_SP);
match self.at(&cause, self.param_env).eq(DefineOpaqueTypes::Yes, expected, effect) {
Ok(InferOk { obligations, value: () }) => {
self.register_predicates(obligations);
}
Err(e) => {
bug!("cannot eq unsolved effect: {e:?}")
}
}
}
true
}
// Tries to apply a fallback to `ty` if it is an unsolved variable.
//
// - Unconstrained ints are replaced with `i32`.

View File

@ -1262,15 +1262,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
self.fcx.ty_infer(Some(param), inf.span).into()
}
(
&GenericParamDefKind::Const { has_default, is_host_effect, .. },
GenericArg::Infer(inf),
) => {
if has_default && is_host_effect {
self.fcx.var_for_effect(param)
} else {
self.fcx.ct_infer(Some(param), inf.span).into()
}
(&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
self.fcx.ct_infer(Some(param), inf.span).into()
}
_ => unreachable!(),
}
@ -1305,20 +1298,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.fcx.var_for_def(self.span, param)
}
}
GenericParamDefKind::Const { has_default, is_host_effect, .. } => {
GenericParamDefKind::Const { has_default, .. } => {
if has_default {
// N.B. this is a bit of a hack. `infer_args` is passed depending on
// whether the user has provided generic args. E.g. for `Vec::new`
// we would have to infer the generic types. However, for `Vec::<T>::new`
// where the allocator param `A` has a default we will *not* infer. But
// for effect params this is a different story: if the user has not written
// anything explicit for the effect param, we always need to try to infer
// it before falling back to default, such that a `const fn` such as
// `needs_drop::<()>` can still be called in const contexts. (if we defaulted
// instead of inferred, typeck would error)
if is_host_effect {
return self.fcx.var_for_effect(param);
} else if !infer_args {
if !infer_args {
return tcx
.const_param_default(param.def_id)
.instantiate(tcx, preceding_args)

View File

@ -247,12 +247,6 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
fn ct_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
// FIXME ideally this shouldn't use unwrap
match param {
Some(
param @ ty::GenericParamDef {
kind: ty::GenericParamDefKind::Const { is_host_effect: true, .. },
..
},
) => self.var_for_effect(param).as_const().unwrap(),
Some(param) => self.var_for_def(span, param).as_const().unwrap(),
None => self.next_const_var(span),
}

View File

@ -369,17 +369,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
let (obligation, args) =
self.obligation_for_method(cause, trait_def_id, self_ty, opt_input_types);
// FIXME(effects) find a better way to do this
// Operators don't have generic methods, but making them `#[const_trait]` gives them
// `const host: bool`.
let args = if self.tcx.is_const_trait(trait_def_id) {
self.tcx.mk_args_from_iter(
args.iter()
.chain([self.tcx.expected_host_effect_param_for_body(self.body_id).into()]),
)
} else {
args
};
self.construct_obligation_for_trait(m_name, trait_def_id, obligation, args)
}

View File

@ -489,17 +489,6 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
}
}
}
ty::ConstKind::Infer(InferConst::EffectVar(vid)) => {
match self.infcx.unwrap().probe_effect_var(vid) {
Some(value) => return self.fold_const(value),
None => {
return self.canonicalize_const_var(
CanonicalVarInfo { kind: CanonicalVarKind::Effect },
ct,
);
}
}
}
ty::ConstKind::Infer(InferConst::Fresh(_)) => {
bug!("encountered a fresh const during canonicalization")
}
@ -700,8 +689,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
.iter()
.map(|v| CanonicalVarInfo {
kind: match v.kind {
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float)
| CanonicalVarKind::Effect => {
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => {
return *v;
}
CanonicalVarKind::Ty(CanonicalTyVarKind::General(u)) => {

View File

@ -24,7 +24,6 @@
pub use instantiate::CanonicalExt;
use rustc_index::IndexVec;
pub use rustc_middle::infer::canonical::*;
use rustc_middle::infer::unify_key::EffectVarValue;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, GenericArg, List, Ty, TyCtxt};
use rustc_span::Span;
@ -145,15 +144,6 @@ impl<'tcx> InferCtxt<'tcx> {
CanonicalVarKind::Const(ui) => {
self.next_const_var_in_universe(span, universe_map(ui)).into()
}
CanonicalVarKind::Effect => {
let vid = self
.inner
.borrow_mut()
.effect_unification_table()
.new_key(EffectVarValue::Unknown)
.vid;
ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(vid)).into()
}
CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, bound }) => {
let universe_mapped = universe_map(universe);
let placeholder_mapped = ty::PlaceholderConst { universe: universe_mapped, bound };

View File

@ -1,6 +1,5 @@
///! Definition of `InferCtxtLike` from the librarified type layer.
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::infer::unify_key::EffectVarValue;
use rustc_middle::traits::ObligationCause;
use rustc_middle::traits::solve::SolverMode;
use rustc_middle::ty::fold::TypeFoldable;
@ -88,15 +87,6 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
}
}
fn opportunistic_resolve_effect_var(&self, vid: ty::EffectVid) -> ty::Const<'tcx> {
match self.probe_effect_var(vid) {
Some(ct) => ct,
None => {
ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(self.root_effect_var(vid)))
}
}
}
fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> ty::Region<'tcx> {
self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
}
@ -152,10 +142,6 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
self.inner.borrow_mut().const_unification_table().union(a, b);
}
fn equate_effect_vids_raw(&self, a: rustc_type_ir::EffectVid, b: rustc_type_ir::EffectVid) {
self.inner.borrow_mut().effect_unification_table().union(a, b);
}
fn instantiate_ty_var_raw<R: PredicateEmittingRelation<Self>>(
&self,
relation: &mut R,
@ -189,13 +175,6 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
self.inner.borrow_mut().float_unification_table().union_value(vid, value);
}
fn instantiate_effect_var_raw(&self, vid: rustc_type_ir::EffectVid, value: ty::Const<'tcx>) {
self.inner
.borrow_mut()
.effect_unification_table()
.union_value(vid, EffectVarValue::Known(value));
}
fn instantiate_const_var_raw<R: PredicateEmittingRelation<Self>>(
&self,
relation: &mut R,

View File

@ -153,15 +153,6 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
drop(inner);
self.freshen_const(input, ty::InferConst::Fresh)
}
ty::ConstKind::Infer(ty::InferConst::EffectVar(v)) => {
let mut inner = self.infcx.inner.borrow_mut();
let input =
inner.effect_unification_table().probe_value(v).known().ok_or_else(|| {
ty::InferConst::EffectVar(inner.effect_unification_table().find(v).vid)
});
drop(inner);
self.freshen_const(input, ty::InferConst::Fresh)
}
ty::ConstKind::Infer(ty::InferConst::Fresh(i)) => {
if i >= self.const_freshen_count {
bug!(

View File

@ -26,9 +26,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_macros::extension;
pub use rustc_macros::{TypeFoldable, TypeVisitable};
use rustc_middle::infer::canonical::{CanonicalQueryInput, CanonicalVarValues};
use rustc_middle::infer::unify_key::{
ConstVariableOrigin, ConstVariableValue, ConstVidKey, EffectVarValue, EffectVidKey,
};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableValue, ConstVidKey};
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
use rustc_middle::traits::select;
@ -39,7 +37,7 @@ use rustc_middle::ty::fold::{
};
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{
self, ConstVid, EffectVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef,
self, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef,
GenericParamDefKind, InferConst, IntVid, Ty, TyCtxt, TyVid,
};
use rustc_middle::{bug, span_bug};
@ -117,9 +115,6 @@ pub struct InferCtxtInner<'tcx> {
/// Map from floating variable to the kind of float it represents.
float_unification_storage: ut::UnificationTableStorage<ty::FloatVid>,
/// Map from effect variable to the effect param it represents.
effect_unification_storage: ut::UnificationTableStorage<EffectVidKey<'tcx>>,
/// Tracks the set of region variables and the constraints between them.
///
/// This is initially `Some(_)` but when
@ -176,7 +171,6 @@ impl<'tcx> InferCtxtInner<'tcx> {
const_unification_storage: Default::default(),
int_unification_storage: Default::default(),
float_unification_storage: Default::default(),
effect_unification_storage: Default::default(),
region_constraint_storage: Some(Default::default()),
region_obligations: vec![],
opaque_type_storage: Default::default(),
@ -228,10 +222,6 @@ impl<'tcx> InferCtxtInner<'tcx> {
self.const_unification_storage.with_log(&mut self.undo_log)
}
fn effect_unification_table(&mut self) -> UnificationTable<'_, 'tcx, EffectVidKey<'tcx>> {
self.effect_unification_storage.with_log(&mut self.undo_log)
}
#[inline]
pub fn unwrap_region_constraints(&mut self) -> RegionConstraintCollector<'_, 'tcx> {
self.region_constraint_storage
@ -524,7 +514,6 @@ impl fmt::Display for FixupError {
),
Ty(_) => write!(f, "unconstrained type"),
Const(_) => write!(f, "unconstrained const value"),
Effect(_) => write!(f, "unconstrained effect value"),
}
}
}
@ -726,17 +715,6 @@ impl<'tcx> InferCtxt<'tcx> {
vars
}
pub fn unsolved_effects(&self) -> Vec<ty::Const<'tcx>> {
let mut inner = self.inner.borrow_mut();
let mut table = inner.effect_unification_table();
(0..table.len())
.map(|i| ty::EffectVid::from_usize(i))
.filter(|&vid| table.probe_value(vid).is_unknown())
.map(|v| ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(v)))
.collect()
}
#[instrument(skip(self), level = "debug")]
pub fn sub_regions(
&self,
@ -899,13 +877,6 @@ impl<'tcx> InferCtxt<'tcx> {
ty::Const::new_var(self.tcx, vid)
}
fn next_effect_var(&self) -> ty::Const<'tcx> {
let effect_vid =
self.inner.borrow_mut().effect_unification_table().new_key(EffectVarValue::Unknown).vid;
ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(effect_vid))
}
pub fn next_int_var(&self) -> Ty<'tcx> {
let next_int_var_id =
self.inner.borrow_mut().int_unification_table().new_key(ty::IntVarValue::Unknown);
@ -991,10 +962,7 @@ impl<'tcx> InferCtxt<'tcx> {
Ty::new_var(self.tcx, ty_var_id).into()
}
GenericParamDefKind::Const { is_host_effect, .. } => {
if is_host_effect {
return self.var_for_effect(param);
}
GenericParamDefKind::Const { .. } => {
let origin = ConstVariableOrigin { param_def_id: Some(param.def_id), span };
let const_var_id = self
.inner
@ -1007,16 +975,6 @@ impl<'tcx> InferCtxt<'tcx> {
}
}
pub fn var_for_effect(&self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
let ty = self
.tcx
.type_of(param.def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic");
debug_assert_eq!(self.tcx.types.bool, ty);
self.next_effect_var().into()
}
/// Given a set of generics defined on a type or impl, returns the generic parameters mapping
/// each type/region parameter to a fresh inference variable.
pub fn fresh_args_for_item(&self, span: Span, def_id: DefId) -> GenericArgsRef<'tcx> {
@ -1142,13 +1100,6 @@ impl<'tcx> InferCtxt<'tcx> {
.probe_value(vid)
.known()
.unwrap_or(ct),
InferConst::EffectVar(vid) => self
.inner
.borrow_mut()
.effect_unification_table()
.probe_value(vid)
.known()
.unwrap_or(ct),
InferConst::Fresh(_) => ct,
},
ty::ConstKind::Param(_)
@ -1169,10 +1120,6 @@ impl<'tcx> InferCtxt<'tcx> {
self.inner.borrow_mut().const_unification_table().find(var).vid
}
pub fn root_effect_var(&self, var: ty::EffectVid) -> ty::EffectVid {
self.inner.borrow_mut().effect_unification_table().find(var).vid
}
/// Resolves an int var to a rigid int type, if it was constrained to one,
/// or else the root int var in the unification table.
pub fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> Ty<'tcx> {
@ -1238,10 +1185,6 @@ impl<'tcx> InferCtxt<'tcx> {
}
}
pub fn probe_effect_var(&self, vid: EffectVid) -> Option<ty::Const<'tcx>> {
self.inner.borrow_mut().effect_unification_table().probe_value(vid).known()
}
/// Attempts to resolve all type/region/const variables in
/// `value`. Region inference must have been run already (e.g.,
/// by calling `resolve_regions_and_report_errors`). If some
@ -1511,14 +1454,6 @@ impl<'tcx> InferCtxt<'tcx> {
ConstVariableValue::Known { .. } => true,
}
}
TyOrConstInferVar::Effect(v) => {
// If `probe_value` returns `Some`, it never equals
// `ty::ConstKind::Infer(ty::InferConst::Effect(v))`.
//
// Not `inlined_probe_value(v)` because this call site is colder.
self.probe_effect_var(v).is_some()
}
}
}
@ -1545,8 +1480,6 @@ pub enum TyOrConstInferVar {
/// Equivalent to `ty::ConstKind::Infer(ty::InferConst::Var(_))`.
Const(ConstVid),
/// Equivalent to `ty::ConstKind::Infer(ty::InferConst::EffectVar(_))`.
Effect(EffectVid),
}
impl<'tcx> TyOrConstInferVar {
@ -1577,7 +1510,6 @@ impl<'tcx> TyOrConstInferVar {
fn maybe_from_const(ct: ty::Const<'tcx>) -> Option<Self> {
match ct.kind() {
ty::ConstKind::Infer(InferConst::Var(v)) => Some(TyOrConstInferVar::Const(v)),
ty::ConstKind::Infer(InferConst::EffectVar(v)) => Some(TyOrConstInferVar::Effect(v)),
_ => None,
}
}

View File

@ -660,7 +660,6 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
}
}
}
ty::ConstKind::Infer(InferConst::EffectVar(_)) => Ok(c),
// FIXME: Unevaluated constants are also not rigid, so the current
// approach of always relating them structurally is incomplete.
//

View File

@ -176,9 +176,6 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for FullTypeResolver<'a, 'tcx> {
ty::ConstKind::Infer(InferConst::Fresh(_)) => {
bug!("Unexpected const in full const resolver: {:?}", c);
}
ty::ConstKind::Infer(InferConst::EffectVar(evid)) => {
return Err(FixupError { unresolved: super::TyOrConstInferVar::Effect(evid) });
}
_ => {}
}
c.try_super_fold_with(self)

View File

@ -4,7 +4,6 @@ use rustc_data_structures::{snapshot_vec as sv, unify as ut};
use rustc_middle::infer::unify_key::{ConstVariableValue, ConstVidKey};
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid};
use rustc_type_ir::EffectVid;
use rustc_type_ir::visit::TypeVisitableExt;
use tracing::instrument;
use ut::UnifyKey;
@ -129,7 +128,6 @@ struct SnapshotVarData {
int_vars: Range<IntVid>,
float_vars: Range<FloatVid>,
const_vars: (Range<ConstVid>, Vec<ConstVariableOrigin>),
effect_vars: Range<EffectVid>,
}
impl SnapshotVarData {
@ -148,30 +146,16 @@ impl SnapshotVarData {
&mut inner.const_unification_table(),
vars_pre_snapshot.const_var_len,
);
let effect_vars = vars_since_snapshot(
&inner.effect_unification_table(),
vars_pre_snapshot.effect_var_len,
);
let effect_vars = effect_vars.start.vid..effect_vars.end.vid;
SnapshotVarData { region_vars, type_vars, int_vars, float_vars, const_vars, effect_vars }
SnapshotVarData { region_vars, type_vars, int_vars, float_vars, const_vars }
}
fn is_empty(&self) -> bool {
let SnapshotVarData {
region_vars,
type_vars,
int_vars,
float_vars,
const_vars,
effect_vars,
} = self;
let SnapshotVarData { region_vars, type_vars, int_vars, float_vars, const_vars } = self;
region_vars.0.is_empty()
&& type_vars.0.is_empty()
&& int_vars.is_empty()
&& float_vars.is_empty()
&& const_vars.0.is_empty()
&& effect_vars.is_empty()
}
}
@ -258,13 +242,6 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceFudger<'a, 'tcx> {
ct
}
}
ty::InferConst::EffectVar(vid) => {
if self.snapshot_vars.effect_vars.contains(&vid) {
self.infcx.next_effect_var()
} else {
ct
}
}
ty::InferConst::Fresh(_) => {
unreachable!("unexpected fresh infcx var")
}

View File

@ -23,7 +23,6 @@ struct VariableLengths {
int_var_len: usize,
float_var_len: usize,
const_var_len: usize,
effect_var_len: usize,
}
impl<'tcx> InferCtxt<'tcx> {
@ -35,7 +34,6 @@ impl<'tcx> InferCtxt<'tcx> {
int_var_len: inner.int_unification_table().len(),
float_var_len: inner.float_unification_table().len(),
const_var_len: inner.const_unification_table().len(),
effect_var_len: inner.effect_unification_table().len(),
}
}

View File

@ -2,7 +2,7 @@ use std::marker::PhantomData;
use rustc_data_structures::undo_log::{Rollback, UndoLogs};
use rustc_data_structures::{snapshot_vec as sv, unify as ut};
use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey, RegionVidKey};
use rustc_middle::infer::unify_key::{ConstVidKey, RegionVidKey};
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey};
use tracing::debug;
@ -22,7 +22,6 @@ pub(crate) enum UndoLog<'tcx> {
ConstUnificationTable(sv::UndoLog<ut::Delegate<ConstVidKey<'tcx>>>),
IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
EffectUnificationTable(sv::UndoLog<ut::Delegate<EffectVidKey<'tcx>>>),
RegionConstraintCollector(region_constraints::UndoLog<'tcx>),
RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>),
ProjectionCache(traits::UndoLog<'tcx>),
@ -50,7 +49,6 @@ impl_from! {
FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
ConstUnificationTable(sv::UndoLog<ut::Delegate<ConstVidKey<'tcx>>>),
EffectUnificationTable(sv::UndoLog<ut::Delegate<EffectVidKey<'tcx>>>),
RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>),
ProjectionCache(traits::UndoLog<'tcx>),
@ -65,7 +63,6 @@ impl<'tcx> Rollback<UndoLog<'tcx>> for InferCtxtInner<'tcx> {
UndoLog::ConstUnificationTable(undo) => self.const_unification_storage.reverse(undo),
UndoLog::IntUnificationTable(undo) => self.int_unification_storage.reverse(undo),
UndoLog::FloatUnificationTable(undo) => self.float_unification_storage.reverse(undo),
UndoLog::EffectUnificationTable(undo) => self.effect_unification_storage.reverse(undo),
UndoLog::RegionConstraintCollector(undo) => {
self.region_constraint_storage.as_mut().unwrap().reverse(undo)
}

View File

@ -542,11 +542,7 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
}
fn check_generic_param(&mut self, cx: &LateContext<'_>, param: &hir::GenericParam<'_>) {
if let GenericParamKind::Const { is_host_effect, .. } = param.kind {
// `host` params are explicitly allowed to be lowercase.
if is_host_effect {
return;
}
if let GenericParamKind::Const { .. } = param.kind {
NonUpperCaseGlobals::check_upper_case(cx, "const parameter", &param.name.ident());
}
}

View File

@ -330,7 +330,6 @@ provide! { tcx, def_id, other, cdata,
.process_decoded(tcx, || panic!("{def_id:?} does not have trait_impl_trait_tys")))
}
associated_type_for_effects => { table }
associated_types_for_impl_traits_in_associated_fn => { table_defaulted_array }
visibility => { cdata.get_visibility(def_id.index) }

View File

@ -1479,9 +1479,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
for &def_id in associated_item_def_ids {
self.encode_info_for_assoc_item(def_id);
}
if let Some(assoc_def_id) = self.tcx.associated_type_for_effects(def_id) {
record!(self.tables.associated_type_for_effects[def_id] <- assoc_def_id);
}
}
if let DefKind::Closure | DefKind::SyntheticCoroutineBody = def_kind
&& let Some(coroutine_kind) = self.tcx.coroutine_kind(def_id)

View File

@ -394,7 +394,6 @@ define_tables! {
explicit_implied_predicates_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
associated_types_for_impl_traits_in_associated_fn: Table<DefIndex, LazyArray<DefId>>,
associated_type_for_effects: Table<DefIndex, Option<LazyValue<DefId>>>,
opt_rpitit_info: Table<DefIndex, Option<LazyValue<ty::ImplTraitInTraitData>>>,
is_effects_desugaring: Table<DefIndex, bool>,
unused_generic_params: Table<DefIndex, UnusedGenericParams>,

View File

@ -172,70 +172,3 @@ impl<'tcx> UnifyValue for ConstVariableValue<'tcx> {
}
}
}
/// values for the effect inference variable
#[derive(Clone, Copy, Debug)]
pub enum EffectVarValue<'tcx> {
Unknown,
Known(ty::Const<'tcx>),
}
impl<'tcx> EffectVarValue<'tcx> {
pub fn known(self) -> Option<ty::Const<'tcx>> {
match self {
EffectVarValue::Unknown => None,
EffectVarValue::Known(value) => Some(value),
}
}
pub fn is_unknown(self) -> bool {
match self {
EffectVarValue::Unknown => true,
EffectVarValue::Known(_) => false,
}
}
}
impl<'tcx> UnifyValue for EffectVarValue<'tcx> {
type Error = NoError;
fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
match (*value1, *value2) {
(EffectVarValue::Unknown, EffectVarValue::Unknown) => Ok(EffectVarValue::Unknown),
(EffectVarValue::Unknown, EffectVarValue::Known(val))
| (EffectVarValue::Known(val), EffectVarValue::Unknown) => {
Ok(EffectVarValue::Known(val))
}
(EffectVarValue::Known(_), EffectVarValue::Known(_)) => {
bug!("equating known inference variables: {value1:?} {value2:?}")
}
}
}
}
#[derive(PartialEq, Copy, Clone, Debug)]
pub struct EffectVidKey<'tcx> {
pub vid: ty::EffectVid,
pub phantom: PhantomData<ty::Const<'tcx>>,
}
impl<'tcx> From<ty::EffectVid> for EffectVidKey<'tcx> {
fn from(vid: ty::EffectVid) -> Self {
EffectVidKey { vid, phantom: PhantomData }
}
}
impl<'tcx> UnifyKey for EffectVidKey<'tcx> {
type Value = EffectVarValue<'tcx>;
#[inline]
fn index(&self) -> u32 {
self.vid.as_u32()
}
#[inline]
fn from_index(i: u32) -> Self {
EffectVidKey::from(ty::EffectVid::from_u32(i))
}
fn tag() -> &'static str {
"EffectVidKey"
}
}

View File

@ -854,12 +854,6 @@ rustc_queries! {
separate_provide_extern
}
query associated_type_for_effects(def_id: DefId) -> Option<DefId> {
desc { |tcx| "creating associated items for effects in `{}`", tcx.def_path_str(def_id) }
cache_on_disk_if { def_id.is_local() }
separate_provide_extern
}
/// Given an impl trait in trait `opaque_ty_def_id`, create and return the corresponding
/// associated item.
query associated_type_for_impl_trait_in_trait(opaque_ty_def_id: LocalDefId) -> LocalDefId {

View File

@ -646,13 +646,6 @@ bidirectional_lang_item_map! {
Destruct,
DiscriminantKind,
DynMetadata,
EffectsCompat,
EffectsIntersection,
EffectsIntersectionOutput,
EffectsMaybe,
EffectsNoRuntime,
EffectsRuntime,
EffectsTyCompat,
Fn,
FnMut,
FnOnce,

View File

@ -592,9 +592,6 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsSuggestableVisitor<'tcx> {
match c.kind() {
ConstKind::Infer(InferConst::Var(_)) if self.infer_suggestable => {}
// effect variables are always suggestable, because they are not visible
ConstKind::Infer(InferConst::EffectVar(_)) => {}
ConstKind::Infer(..)
| ConstKind::Bound(..)
| ConstKind::Placeholder(..)

View File

@ -354,9 +354,7 @@ impl FlagComputation {
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
match infer {
InferConst::Fresh(_) => self.add_flags(TypeFlags::HAS_CT_FRESH),
InferConst::Var(_) | InferConst::EffectVar(_) => {
self.add_flags(TypeFlags::HAS_CT_INFER)
}
InferConst::Var(_) => self.add_flags(TypeFlags::HAS_CT_INFER),
}
}
ty::ConstKind::Bound(debruijn, _) => {

View File

@ -501,12 +501,11 @@ impl<'tcx> GenericArgs<'tcx> {
#[inline]
pub fn non_erasable_generics(
&'tcx self,
tcx: TyCtxt<'tcx>,
def_id: DefId,
// FIXME(effects): Remove these
_tcx: TyCtxt<'tcx>,
_def_id: DefId,
) -> impl DoubleEndedIterator<Item = GenericArgKind<'tcx>> + 'tcx {
let generics = tcx.generics_of(def_id);
self.iter().enumerate().filter_map(|(i, k)| match k.unpack() {
_ if Some(i) == generics.host_effect_index => None,
self.iter().filter_map(|k| match k.unpack() {
ty::GenericArgKind::Lifetime(_) => None,
generic => Some(generic),
})

View File

@ -14,7 +14,7 @@ use crate::ty::{EarlyBinder, GenericArgsRef};
pub enum GenericParamDefKind {
Lifetime,
Type { has_default: bool, synthetic: bool },
Const { has_default: bool, is_host_effect: bool, synthetic: bool },
Const { has_default: bool, synthetic: bool },
}
impl GenericParamDefKind {
@ -81,10 +81,6 @@ impl GenericParamDef {
}
}
pub fn is_host_effect(&self) -> bool {
matches!(self.kind, GenericParamDefKind::Const { is_host_effect: true, .. })
}
pub fn default_value<'tcx>(
&self,
tcx: TyCtxt<'tcx>,
@ -133,9 +129,6 @@ pub struct Generics {
pub has_self: bool,
pub has_late_bound_regions: Option<Span>,
// The index of the host effect when instantiated. (i.e. might be index to parent args)
pub host_effect_index: Option<usize>,
}
impl<'tcx> rustc_type_ir::inherent::GenericsOf<TyCtxt<'tcx>> for &'tcx Generics {
@ -216,12 +209,10 @@ impl<'tcx> Generics {
pub fn own_requires_monomorphization(&self) -> bool {
for param in &self.own_params {
match param.kind {
GenericParamDefKind::Type { .. }
| GenericParamDefKind::Const { is_host_effect: false, .. } => {
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
return true;
}
GenericParamDefKind::Lifetime
| GenericParamDefKind::Const { is_host_effect: true, .. } => {}
GenericParamDefKind::Lifetime => {}
}
}
false
@ -300,8 +291,6 @@ impl<'tcx> Generics {
own_params.start = 1;
}
let verbose = tcx.sess.verbose_internals();
// Filter the default arguments.
//
// This currently uses structural equality instead
@ -316,8 +305,6 @@ impl<'tcx> Generics {
param.default_value(tcx).is_some_and(|default| {
default.instantiate(tcx, args) == args[param.index as usize]
})
// filter out trailing effect params, if we're not in `-Zverbose-internals`.
|| (!verbose && matches!(param.kind, GenericParamDefKind::Const { is_host_effect: true, .. }))
})
.count();

View File

@ -476,7 +476,6 @@ impl<'tcx> Instance<'tcx> {
pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
let args = GenericArgs::for_item(tcx, def_id, |param, _| match param.kind {
ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
ty::GenericParamDefKind::Const { is_host_effect: true, .. } => tcx.consts.true_.into(),
ty::GenericParamDefKind::Type { .. } => {
bug!("Instance::mono: {:?} has type parameters", def_id)
}

View File

@ -17,10 +17,10 @@ use rustc_span::sym;
use rustc_target::abi::{Float, Integer, IntegerType, Size};
use rustc_target::spec::abi::Abi;
use smallvec::{SmallVec, smallvec};
use tracing::{debug, instrument, trace};
use tracing::{debug, instrument};
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::query::{IntoQueryParam, Providers};
use crate::query::Providers;
use crate::ty::layout::{FloatExt, IntegerExt};
use crate::ty::{
self, Asyncness, FallibleTypeFolder, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeFoldable,
@ -865,48 +865,6 @@ impl<'tcx> TyCtxt<'tcx> {
|| self.extern_crate(key).is_some_and(|e| e.is_direct())
}
/// Whether the item has a host effect param. This is different from `TyCtxt::is_const`,
/// because the item must also be "maybe const", and the crate where the item is
/// defined must also have the effects feature enabled.
pub fn has_host_param(self, def_id: impl IntoQueryParam<DefId>) -> bool {
self.generics_of(def_id).host_effect_index.is_some()
}
pub fn expected_host_effect_param_for_body(self, def_id: impl Into<DefId>) -> ty::Const<'tcx> {
let def_id = def_id.into();
// FIXME(effects): This is suspicious and should probably not be done,
// especially now that we enforce host effects and then properly handle
// effect vars during fallback.
let mut host_always_on = !self.features().effects()
|| self.sess.opts.unstable_opts.unleash_the_miri_inside_of_you;
// Compute the constness required by the context.
let const_context = self.hir().body_const_context(def_id);
let kind = self.def_kind(def_id);
debug_assert_ne!(kind, DefKind::ConstParam);
if self.has_attr(def_id, sym::rustc_do_not_const_check) {
trace!("do not const check this context");
host_always_on = true;
}
match const_context {
_ if host_always_on => self.consts.true_,
Some(hir::ConstContext::Static(_) | hir::ConstContext::Const { .. }) => {
self.consts.false_
}
Some(hir::ConstContext::ConstFn) => {
let host_idx = self
.generics_of(def_id)
.host_effect_index
.expect("ConstContext::Maybe must have host effect param");
ty::GenericArgs::identity_for_item(self, def_id).const_at(host_idx)
}
None => self.consts.true_,
}
}
/// Expand any [weak alias types][weak] contained within the given `value`.
///
/// This should be used over other normalization routines in situations where

View File

@ -1522,7 +1522,6 @@ fn create_mono_items_for_default_impls<'tcx>(
// it, to validate whether or not the impl is legal to instantiate at all.
let only_region_params = |param: &ty::GenericParamDef, _: &_| match param.kind {
GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
GenericParamDefKind::Const { is_host_effect: true, .. } => tcx.consts.true_.into(),
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
unreachable!(
"`own_requires_monomorphization` check means that \

View File

@ -431,7 +431,6 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
);
CanonicalVarKind::Const(self.delegate.universe_of_ct(vid).unwrap())
}
ty::InferConst::EffectVar(_) => CanonicalVarKind::Effect,
ty::InferConst::Fresh(_) => todo!(),
},
ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode {

View File

@ -76,9 +76,6 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for EagerResolv
resolved
}
}
ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => {
self.delegate.opportunistic_resolve_effect_var(vid)
}
_ => {
if c.has_infer() {
c.super_fold_with(self)

View File

@ -270,11 +270,6 @@ where
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Vec<Candidate<I>>;
fn consider_builtin_effects_intersection_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution>;
}
impl<D, I> EvalCtxt<'_, D>
@ -481,9 +476,6 @@ where
Some(TraitSolverLangItem::TransmuteTrait) => {
G::consider_builtin_transmute_candidate(self, goal)
}
Some(TraitSolverLangItem::EffectsIntersection) => {
G::consider_builtin_effects_intersection_candidate(self, goal)
}
_ => Err(NoSolution),
}
};

View File

@ -182,12 +182,6 @@ where
let (ct, ty) = goal.predicate;
let ct_ty = match ct.kind() {
// FIXME: Ignore effect vars because canonicalization doesn't handle them correctly
// and if we stall on the var then we wind up creating ambiguity errors in a probe
// for this goal which contains an effect var. Which then ends up ICEing.
ty::ConstKind::Infer(ty::InferConst::EffectVar(_)) => {
return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
}
ty::ConstKind::Infer(_) => {
return self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
}

View File

@ -911,68 +911,6 @@ where
) -> Result<Candidate<I>, NoSolution> {
panic!("`TransmuteFrom` does not have an associated type: {:?}", goal)
}
fn consider_builtin_effects_intersection_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
let ty::Tuple(types) = goal.predicate.self_ty().kind() else {
return Err(NoSolution);
};
let cx = ecx.cx();
let mut first_non_maybe = None;
let mut non_maybe_count = 0;
for ty in types.iter() {
if !matches!(ty::EffectKind::try_from_ty(cx, ty), Some(ty::EffectKind::Maybe)) {
first_non_maybe.get_or_insert(ty);
non_maybe_count += 1;
}
}
match non_maybe_count {
0 => {
let ty = ty::EffectKind::Maybe.to_ty(cx);
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
ecx.instantiate_normalizes_to_term(goal, ty.into());
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}
1 => {
let ty = first_non_maybe.unwrap();
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
ecx.instantiate_normalizes_to_term(goal, ty.into());
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}
_ => {
let mut min = ty::EffectKind::Maybe;
for ty in types.iter() {
// We can't find the intersection if the types used are generic.
//
// FIXME(effects): do we want to look at where clauses to get some
// clue for the case where generic types are being used?
let Some(kind) = ty::EffectKind::try_from_ty(cx, ty) else {
return Err(NoSolution);
};
let Some(result) = ty::EffectKind::intersection(min, kind) else {
return Err(NoSolution);
};
min = result;
}
let ty = min.to_ty(cx);
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
ecx.instantiate_normalizes_to_term(goal, ty.into());
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}
}
}
}
impl<D, I> EvalCtxt<'_, D>

View File

@ -719,47 +719,6 @@ where
}
})
}
fn consider_builtin_effects_intersection_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
return Err(NoSolution);
}
let ty::Tuple(types) = goal.predicate.self_ty().kind() else {
return Err(NoSolution);
};
let cx = ecx.cx();
let maybe_count = types
.iter()
.filter_map(|ty| ty::EffectKind::try_from_ty(cx, ty))
.filter(|&ty| ty == ty::EffectKind::Maybe)
.count();
// Don't do concrete type check unless there are more than one type that will influence the result.
// This would allow `(Maybe, T): Min` pass even if we know nothing about `T`.
if types.len() - maybe_count > 1 {
let mut min = ty::EffectKind::Maybe;
for ty in types.iter() {
let Some(kind) = ty::EffectKind::try_from_ty(ecx.cx(), ty) else {
return Err(NoSolution);
};
let Some(result) = ty::EffectKind::intersection(min, kind) else {
return Err(NoSolution);
};
min = result;
}
}
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
.enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
}
}
impl<D, I> EvalCtxt<'_, D>

View File

@ -588,7 +588,6 @@ impl<'tcx> Stable<'tcx> for ty::Generics {
.has_late_bound_regions
.as_ref()
.map(|late_bound_regions| late_bound_regions.stable(tables)),
host_effect_index: self.host_effect_index,
}
}
}
@ -603,7 +602,7 @@ impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind {
ty::GenericParamDefKind::Type { has_default, synthetic } => {
GenericParamDefKind::Type { has_default: *has_default, synthetic: *synthetic }
}
ty::GenericParamDefKind::Const { has_default, is_host_effect: _, synthetic: _ } => {
ty::GenericParamDefKind::Const { has_default, synthetic: _ } => {
GenericParamDefKind::Const { has_default: *has_default }
}
}

View File

@ -195,14 +195,6 @@ symbols! {
Display,
DoubleEndedIterator,
Duration,
EffectsCompat,
EffectsIntersection,
EffectsIntersectionOutput,
EffectsMaybe,
EffectsNoRuntime,
EffectsRuntime,
EffectsTyCompat,
Effects__,
Encodable,
Encoder,
Enumerate,
@ -1737,7 +1729,6 @@ symbols! {
rustc_reallocator,
rustc_regions,
rustc_reservation_impl,
rustc_runtime,
rustc_safe_intrinsic,
rustc_serialize,
rustc_skip_during_method_dispatch,

View File

@ -2374,50 +2374,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
})
}
/// For effects predicates such as `<u32 as Add>::Effects: Compat<host>`, pretend that the
/// predicate that failed was `u32: Add`. Return the constness of such predicate to later
/// print as `u32: ~const Add`.
// FIXME(effects): Remove this.
fn get_effects_trait_pred_override(
&self,
p: ty::PolyTraitPredicate<'tcx>,
leaf: ty::PolyTraitPredicate<'tcx>,
span: Span,
) -> (ty::PolyTraitPredicate<'tcx>, ty::PolyTraitPredicate<'tcx>, Option<ty::BoundConstness>)
{
let trait_ref = p.to_poly_trait_ref();
if !self.tcx.is_lang_item(trait_ref.def_id(), LangItem::EffectsCompat) {
return (p, leaf, None);
}
let Some(ty::Alias(ty::AliasTyKind::Projection, projection)) =
trait_ref.self_ty().no_bound_vars().map(Ty::kind)
else {
return (p, leaf, None);
};
let constness = trait_ref.skip_binder().args.const_at(1);
let constness = if constness == self.tcx.consts.true_ || constness.is_ct_infer() {
None
} else if constness == self.tcx.consts.false_ {
Some(ty::BoundConstness::Const)
} else if matches!(constness.kind(), ty::ConstKind::Param(_)) {
Some(ty::BoundConstness::ConstIfConst)
} else {
self.dcx().span_bug(span, format!("Unknown constness argument: {constness:?}"));
};
let new_pred = p.map_bound(|mut trait_pred| {
trait_pred.trait_ref = projection.trait_ref(self.tcx);
trait_pred
});
let new_leaf = leaf.map_bound(|mut trait_pred| {
trait_pred.trait_ref = projection.trait_ref(self.tcx);
trait_pred
});
(new_pred, new_leaf, constness)
_span: Span,
) -> (ty::PolyTraitPredicate<'tcx>, ty::PolyTraitPredicate<'tcx>, ty::BoundConstness) {
(p, leaf, ty::BoundConstness::NotConst)
}
fn add_tuple_trait_message(

View File

@ -450,7 +450,6 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
ty::ConstKind::Infer(var) => {
let var = match var {
ty::InferConst::Var(vid) => TyOrConstInferVar::Const(vid),
ty::InferConst::EffectVar(vid) => TyOrConstInferVar::Effect(vid),
ty::InferConst::Fresh(_) => {
bug!("encountered fresh const in fulfill")
}

View File

@ -547,7 +547,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
// Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396).
ty::FnDef(def_id, _args) => {
ty::FnDef(def_id, _) => {
let tcx = self.tcx();
if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible()
&& tcx.codegen_fn_attrs(def_id).target_features.is_empty()

View File

@ -1821,8 +1821,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|cand: ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_bound_vars();
// (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`,
// `DiscriminantKindCandidate`, `ConstDestructCandidate`
// to anything else.
// or `DiscriminantKindCandidate` to anything else.
//
// This is a fix for #53123 and prevents winnowing from accidentally extending the
// lifetime of a variable.

View File

@ -4,9 +4,8 @@ use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, ImplTraitInTraitData, Ty, TyCtxt};
use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::sym;
use rustc_span::symbol::kw;
pub(crate) fn provide(providers: &mut Providers) {
@ -15,7 +14,6 @@ pub(crate) fn provide(providers: &mut Providers) {
associated_item_def_ids,
associated_items,
associated_types_for_impl_traits_in_associated_fn,
associated_type_for_effects,
associated_type_for_impl_trait_in_trait,
impl_item_implementor_ids,
..*providers
@ -46,8 +44,7 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] {
)
})
.copied(),
)
.chain(tcx.associated_type_for_effects(def_id)),
),
)
}
hir::ItemKind::Impl(impl_) => {
@ -73,8 +70,7 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] {
)
})
.copied()
}))
.chain(tcx.associated_type_for_effects(def_id)),
})),
)
}
_ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
@ -171,134 +167,6 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A
}
}
/// Given an `def_id` of a trait or a trait impl:
///
/// If `def_id` is a trait that has `#[const_trait]`, then it synthesizes
/// a new def id corresponding to a new associated type for the effects.
///
/// If `def_id` is an impl, then synthesize the associated type according
/// to the constness of the impl.
fn associated_type_for_effects(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
// don't synthesize the associated type even if the user has written `const_trait`
// if the effects feature is disabled.
if !tcx.features().effects() {
return None;
}
let (feed, parent_did) = match tcx.def_kind(def_id) {
DefKind::Trait => {
let trait_def_id = def_id;
let attr = tcx.get_attr(def_id, sym::const_trait)?;
let span = attr.span;
let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, kw::Empty, DefKind::AssocTy);
let local_def_id = trait_assoc_ty.def_id();
let def_id = local_def_id.to_def_id();
// Copy span of the attribute.
trait_assoc_ty.def_ident_span(Some(span));
trait_assoc_ty.associated_item(ty::AssocItem {
name: kw::Empty,
kind: ty::AssocKind::Type,
def_id,
trait_item_def_id: None,
container: ty::TraitContainer,
fn_has_self_parameter: false,
opt_rpitit_info: None,
is_effects_desugaring: true,
});
// No default type
trait_assoc_ty.defaultness(hir::Defaultness::Default { has_value: false });
trait_assoc_ty.is_type_alias_impl_trait(false);
(trait_assoc_ty, trait_def_id)
}
DefKind::Impl { .. } => {
let impl_def_id = def_id;
let trait_id = tcx.trait_id_of_impl(def_id.to_def_id())?;
// first get the DefId of the assoc type on the trait, if there is not,
// then we don't need to generate it on the impl.
let trait_assoc_id = tcx.associated_type_for_effects(trait_id)?;
// FIXME(effects): span
let span = tcx.def_ident_span(def_id).unwrap();
let impl_assoc_ty = tcx.at(span).create_def(def_id, kw::Empty, DefKind::AssocTy);
let local_def_id = impl_assoc_ty.def_id();
let def_id = local_def_id.to_def_id();
impl_assoc_ty.def_ident_span(Some(span));
impl_assoc_ty.associated_item(ty::AssocItem {
name: kw::Empty,
kind: ty::AssocKind::Type,
def_id,
trait_item_def_id: Some(trait_assoc_id),
container: ty::ImplContainer,
fn_has_self_parameter: false,
opt_rpitit_info: None,
is_effects_desugaring: true,
});
// no default value.
impl_assoc_ty.defaultness(hir::Defaultness::Final);
// set the type of the associated type! If this is a const impl,
// we set to Maybe, otherwise we set to `Runtime`.
let type_def_id = if tcx.is_const_trait_impl_raw(impl_def_id.to_def_id()) {
tcx.require_lang_item(hir::LangItem::EffectsMaybe, Some(span))
} else {
tcx.require_lang_item(hir::LangItem::EffectsRuntime, Some(span))
};
// FIXME(effects): make impls use `Min` for their effect types
impl_assoc_ty.type_of(ty::EarlyBinder::bind(Ty::new_adt(
tcx,
tcx.adt_def(type_def_id),
ty::GenericArgs::empty(),
)));
(impl_assoc_ty, impl_def_id)
}
def_kind => bug!(
"associated_type_for_effects: {:?} should be Trait or Impl but is {:?}",
def_id,
def_kind
),
};
feed.feed_hir();
// visibility is public.
feed.visibility(ty::Visibility::Public);
// Copy generics_of of the trait/impl, making the trait/impl as parent.
feed.generics_of({
let parent_generics = tcx.generics_of(parent_did);
let parent_count = parent_generics.parent_count + parent_generics.own_params.len();
ty::Generics {
parent: Some(parent_did.to_def_id()),
parent_count,
own_params: vec![],
param_def_id_to_index: parent_generics.param_def_id_to_index.clone(),
has_self: false,
has_late_bound_regions: None,
host_effect_index: parent_generics.host_effect_index,
}
});
feed.explicit_item_super_predicates(ty::EarlyBinder::bind(&[]));
// There are no inferred outlives for the synthesized associated type.
feed.inferred_outlives_of(&[]);
Some(feed.def_id().to_def_id())
}
/// Given an `fn_def_id` of a trait or a trait implementation:
///
/// if `fn_def_id` is a function defined inside a trait, then it synthesizes
@ -494,7 +362,6 @@ fn associated_type_for_impl_trait_in_impl(
param_def_id_to_index,
has_self: false,
has_late_bound_regions: trait_assoc_generics.has_late_bound_regions,
host_effect_index: parent_generics.host_effect_index,
}
});

View File

@ -108,7 +108,6 @@ impl<I: Interner> CanonicalVarInfo<I> {
CanonicalVarKind::PlaceholderRegion(..) => false,
CanonicalVarKind::Const(_) => true,
CanonicalVarKind::PlaceholderConst(_) => false,
CanonicalVarKind::Effect => true,
}
}
@ -118,17 +117,15 @@ impl<I: Interner> CanonicalVarInfo<I> {
CanonicalVarKind::Ty(_)
| CanonicalVarKind::PlaceholderTy(_)
| CanonicalVarKind::Const(_)
| CanonicalVarKind::PlaceholderConst(_)
| CanonicalVarKind::Effect => false,
| CanonicalVarKind::PlaceholderConst(_) => false,
}
}
pub fn expect_placeholder_index(self) -> usize {
match self.kind {
CanonicalVarKind::Ty(_)
| CanonicalVarKind::Region(_)
| CanonicalVarKind::Const(_)
| CanonicalVarKind::Effect => panic!("expected placeholder: {self:?}"),
CanonicalVarKind::Ty(_) | CanonicalVarKind::Region(_) | CanonicalVarKind::Const(_) => {
panic!("expected placeholder: {self:?}")
}
CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.var().as_usize(),
CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.var().as_usize(),
@ -161,9 +158,6 @@ pub enum CanonicalVarKind<I: Interner> {
/// Some kind of const inference variable.
Const(UniverseIndex),
/// Effect variable `'?E`.
Effect,
/// A "placeholder" that represents "any const".
PlaceholderConst(I::PlaceholderConst),
}
@ -180,7 +174,6 @@ impl<I: Interner> CanonicalVarKind<I> {
CanonicalVarKind::Ty(CanonicalTyVarKind::Float | CanonicalTyVarKind::Int) => {
UniverseIndex::ROOT
}
CanonicalVarKind::Effect => UniverseIndex::ROOT,
}
}
@ -205,8 +198,7 @@ impl<I: Interner> CanonicalVarKind<I> {
CanonicalVarKind::PlaceholderConst(placeholder) => {
CanonicalVarKind::PlaceholderConst(placeholder.with_updated_universe(ui))
}
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float)
| CanonicalVarKind::Effect => {
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => {
assert_eq!(ui, UniverseIndex::ROOT);
self
}
@ -311,10 +303,6 @@ impl<I: Interner> CanonicalVarValues<I> {
Region::new_anon_bound(cx, ty::INNERMOST, ty::BoundVar::from_usize(i))
.into()
}
CanonicalVarKind::Effect => {
Const::new_anon_bound(cx, ty::INNERMOST, ty::BoundVar::from_usize(i))
.into()
}
CanonicalVarKind::Const(_) | CanonicalVarKind::PlaceholderConst(_) => {
Const::new_anon_bound(cx, ty::INNERMOST, ty::BoundVar::from_usize(i))
.into()

View File

@ -84,32 +84,12 @@ rustc_index::newtype_index! {
pub struct ConstVid {}
}
rustc_index::newtype_index! {
/// An **effect** **v**ariable **ID**.
///
/// Handling effect infer variables happens separately from const infer variables
/// because we do not want to reuse any of the const infer machinery. If we try to
/// relate an effect variable with a normal one, we would ICE, which can catch bugs
/// where we are not correctly using the effect var for an effect param. Fallback
/// is also implemented on top of having separate effect and normal const variables.
#[encodable]
#[orderable]
#[debug_format = "?{}e"]
#[gate_rustc_only]
pub struct EffectVid {}
}
/// An inference variable for a const, for use in const generics.
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
pub enum InferConst {
/// Infer the value of the const.
Var(ConstVid),
/// Infer the value of the effect.
///
/// For why this is separate from the `Var` variant above, see the
/// documentation on `EffectVid`.
EffectVar(EffectVid),
/// A fresh const variable. See `infer::freshen` for more details.
Fresh(u32),
}
@ -118,7 +98,6 @@ impl fmt::Debug for InferConst {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
InferConst::Var(var) => write!(f, "{var:?}"),
InferConst::EffectVar(var) => write!(f, "{var:?}"),
InferConst::Fresh(var) => write!(f, "Fresh({var:?})"),
}
}
@ -128,7 +107,7 @@ impl fmt::Debug for InferConst {
impl<CTX> HashStable<CTX> for InferConst {
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
match self {
InferConst::Var(_) | InferConst::EffectVar(_) => {
InferConst::Var(_) => {
panic!("const variables should not be hashed: {self:?}")
}
InferConst::Fresh(i) => i.hash_stable(hcx, hasher),

View File

@ -1,59 +0,0 @@
use crate::Interner;
use crate::inherent::*;
use crate::lang_items::TraitSolverLangItem::{EffectsMaybe, EffectsNoRuntime, EffectsRuntime};
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum EffectKind {
Maybe,
Runtime,
NoRuntime,
}
impl EffectKind {
pub fn try_from_def_id<I: Interner>(cx: I, def_id: I::DefId) -> Option<EffectKind> {
if cx.is_lang_item(def_id, EffectsMaybe) {
Some(EffectKind::Maybe)
} else if cx.is_lang_item(def_id, EffectsRuntime) {
Some(EffectKind::Runtime)
} else if cx.is_lang_item(def_id, EffectsNoRuntime) {
Some(EffectKind::NoRuntime)
} else {
None
}
}
pub fn to_def_id<I: Interner>(self, cx: I) -> I::DefId {
let lang_item = match self {
EffectKind::Maybe => EffectsMaybe,
EffectKind::NoRuntime => EffectsNoRuntime,
EffectKind::Runtime => EffectsRuntime,
};
cx.require_lang_item(lang_item)
}
pub fn try_from_ty<I: Interner>(cx: I, ty: I::Ty) -> Option<EffectKind> {
if let crate::Adt(def, _) = ty.kind() {
Self::try_from_def_id(cx, def.def_id())
} else {
None
}
}
pub fn to_ty<I: Interner>(self, cx: I) -> I::Ty {
I::Ty::new_adt(cx, cx.adt_def(self.to_def_id(cx)), Default::default())
}
/// Returns an intersection between two effect kinds. If one effect kind
/// is more permissive than the other (e.g. `Maybe` vs `Runtime`), this
/// returns the less permissive effect kind (`Runtime`).
pub fn intersection(a: Self, b: Self) -> Option<Self> {
use EffectKind::*;
match (a, b) {
(Maybe, x) | (x, Maybe) => Some(x),
(Runtime, Runtime) => Some(Runtime),
(NoRuntime, NoRuntime) => Some(NoRuntime),
(Runtime, NoRuntime) | (NoRuntime, Runtime) => None,
}
}
}

View File

@ -4,7 +4,6 @@ use smallvec::smallvec;
use crate::data_structures::HashSet;
use crate::inherent::*;
use crate::lang_items::TraitSolverLangItem;
use crate::outlives::{Component, push_outlives_components};
use crate::{self as ty, Interner, Upcast as _};
@ -130,70 +129,6 @@ impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
return;
}
// HACK(effects): The following code is required to get implied bounds for effects associated
// types to work with super traits.
//
// Suppose `data` is a trait predicate with the form `<T as Tr>::Fx: EffectsCompat<somebool>`
// and we know that `trait Tr: ~const SuperTr`, we need to elaborate this predicate into
// `<T as SuperTr>::Fx: EffectsCompat<somebool>`.
//
// Since the semantics for elaborating bounds about effects is equivalent to elaborating
// bounds about super traits (elaborate `T: Tr` into `T: SuperTr`), we place effects elaboration
// next to super trait elaboration.
if cx.is_lang_item(data.def_id(), TraitSolverLangItem::EffectsCompat)
&& matches!(self.mode, Filter::All)
{
// first, ensure that the predicate we've got looks like a `<T as Tr>::Fx: EffectsCompat<somebool>`.
if let ty::Alias(ty::AliasTyKind::Projection, alias_ty) = data.self_ty().kind()
{
// look for effects-level bounds that look like `<Self as Tr>::Fx: TyCompat<<Self as SuperTr>::Fx>`
// on the trait, which is proof to us that `Tr: ~const SuperTr`. We're looking for bounds on the
// associated trait, so we use `explicit_implied_predicates_of` since it gives us more than just
// `Self: SuperTr` bounds.
let bounds = cx.explicit_implied_predicates_of(cx.parent(alias_ty.def_id));
// instantiate the implied bounds, so we get `<T as Tr>::Fx` and not `<Self as Tr>::Fx`.
let elaborated = bounds.iter_instantiated(cx, alias_ty.args).filter_map(
|(clause, _)| {
let ty::ClauseKind::Trait(tycompat_bound) =
clause.kind().skip_binder()
else {
return None;
};
if !cx.is_lang_item(
tycompat_bound.def_id(),
TraitSolverLangItem::EffectsTyCompat,
) {
return None;
}
// extract `<T as SuperTr>::Fx` from the `TyCompat` bound.
let supertrait_effects_ty =
tycompat_bound.trait_ref.args.type_at(1);
let ty::Alias(ty::AliasTyKind::Projection, supertrait_alias_ty) =
supertrait_effects_ty.kind()
else {
return None;
};
// The self types (`T`) must be equal for `<T as Tr>::Fx` and `<T as SuperTr>::Fx`.
if supertrait_alias_ty.self_ty() != alias_ty.self_ty() {
return None;
};
// replace the self type in the original bound `<T as Tr>::Fx: EffectsCompat<somebool>`
// to the effects type of the super trait. (`<T as SuperTr>::Fx`)
let elaborated_bound = data.with_self_ty(cx, supertrait_effects_ty);
Some(
elaboratable
.child(bound_clause.rebind(elaborated_bound).upcast(cx)),
)
},
);
self.extend_deduped(elaborated);
}
}
let map_to_child_clause =
|(index, (clause, span)): (usize, (I::Clause, I::Span))| {
elaboratable.child_with_derived_cause(

View File

@ -38,10 +38,6 @@ pub trait InferCtxtLike: Sized {
&self,
vid: ty::ConstVid,
) -> <Self::Interner as Interner>::Const;
fn opportunistic_resolve_effect_var(
&self,
vid: ty::EffectVid,
) -> <Self::Interner as Interner>::Const;
fn opportunistic_resolve_lt_var(
&self,
vid: ty::RegionVid,
@ -71,7 +67,6 @@ pub trait InferCtxtLike: Sized {
fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid);
fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid);
fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid);
fn equate_effect_vids_raw(&self, a: ty::EffectVid, b: ty::EffectVid);
fn instantiate_ty_var_raw<R: PredicateEmittingRelation<Self>>(
&self,
@ -83,11 +78,6 @@ pub trait InferCtxtLike: Sized {
) -> RelateResult<Self::Interner, ()>;
fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue);
fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue);
fn instantiate_effect_var_raw(
&self,
vid: ty::EffectVid,
value: <Self::Interner as Interner>::Const,
);
fn instantiate_const_var_raw<R: PredicateEmittingRelation<Self>>(
&self,
relation: &mut R,

View File

@ -20,13 +20,6 @@ pub enum TraitSolverLangItem {
Destruct,
DiscriminantKind,
DynMetadata,
EffectsCompat,
EffectsIntersection,
EffectsIntersectionOutput,
EffectsMaybe,
EffectsNoRuntime,
EffectsRuntime,
EffectsTyCompat,
Fn,
FnMut,
FnOnce,

View File

@ -43,7 +43,6 @@ mod macros;
mod binder;
mod canonical;
mod const_kind;
mod effects;
mod flags;
mod generic_arg;
mod infer_ctxt;
@ -67,7 +66,6 @@ pub use canonical::*;
#[cfg(feature = "nightly")]
pub use codec::*;
pub use const_kind::*;
pub use effects::*;
pub use flags::*;
pub use generic_arg::*;
pub use infer_ctxt::*;

View File

@ -179,23 +179,9 @@ where
Ok(a)
}
(
ty::ConstKind::Infer(ty::InferConst::EffectVar(a_vid)),
ty::ConstKind::Infer(ty::InferConst::EffectVar(b_vid)),
) => {
infcx.equate_effect_vids_raw(a_vid, b_vid);
Ok(a)
}
// All other cases of inference with other variables are errors.
(
ty::ConstKind::Infer(ty::InferConst::Var(_) | ty::InferConst::EffectVar(_)),
ty::ConstKind::Infer(_),
)
| (
ty::ConstKind::Infer(_),
ty::ConstKind::Infer(ty::InferConst::Var(_) | ty::InferConst::EffectVar(_)),
) => {
(ty::ConstKind::Infer(ty::InferConst::Var(_)), ty::ConstKind::Infer(_))
| (ty::ConstKind::Infer(_), ty::ConstKind::Infer(ty::InferConst::Var(_))) => {
panic!(
"tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {a:?} and {b:?}"
)
@ -211,16 +197,6 @@ where
Ok(a)
}
(ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)), _) => {
infcx.instantiate_effect_var_raw(vid, b);
Ok(b)
}
(_, ty::ConstKind::Infer(ty::InferConst::EffectVar(vid))) => {
infcx.instantiate_effect_var_raw(vid, a);
Ok(a)
}
(ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..))
if infcx.cx().features().generic_const_exprs() || infcx.next_trait_solver() =>
{

View File

@ -1393,7 +1393,6 @@ pub struct Generics {
pub param_def_id_to_index: Vec<(GenericDef, u32)>,
pub has_self: bool,
pub has_late_bound_regions: Option<Span>,
pub host_effect_index: Option<usize>,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]

View File

@ -1069,47 +1069,3 @@ pub trait FnPtr: Copy + Clone {
pub macro SmartPointer($item:item) {
/* compiler built-in */
}
// Support traits and types for the desugaring of const traits and
// `~const` bounds. Not supposed to be used by anything other than
// the compiler.
#[doc(hidden)]
#[unstable(
feature = "effect_types",
issue = "none",
reason = "internal module for implementing effects"
)]
#[allow(missing_debug_implementations)] // these unit structs don't need `Debug` impls.
pub mod effects {
#[lang = "EffectsNoRuntime"]
pub struct NoRuntime;
#[lang = "EffectsMaybe"]
pub struct Maybe;
#[lang = "EffectsRuntime"]
pub struct Runtime;
#[lang = "EffectsCompat"]
pub trait Compat<#[rustc_runtime] const RUNTIME: bool> {}
impl Compat<false> for NoRuntime {}
impl Compat<true> for Runtime {}
impl<#[rustc_runtime] const RUNTIME: bool> Compat<RUNTIME> for Maybe {}
#[lang = "EffectsTyCompat"]
#[marker]
pub trait TyCompat<T: ?Sized> {}
impl<T: ?Sized> TyCompat<T> for T {}
impl<T: ?Sized> TyCompat<Maybe> for T {}
#[lang = "EffectsIntersection"]
pub trait Intersection {
#[lang = "EffectsIntersectionOutput"]
type Output: ?Sized;
}
// FIXME(effects): remove this after next trait solver lands
impl Intersection for () {
type Output = Maybe;
}
}

View File

@ -156,7 +156,7 @@ fn clean_param_env<'tcx>(
.iter()
.inspect(|param| {
if cfg!(debug_assertions) {
debug_assert!(!param.is_anonymous_lifetime() && !param.is_host_effect());
debug_assert!(!param.is_anonymous_lifetime());
if let ty::GenericParamDefKind::Type { synthetic, .. } = param.kind {
debug_assert!(!synthetic && param.name != kw::SelfUpper);
}

View File

@ -542,7 +542,7 @@ fn clean_generic_param_def(
synthetic,
})
}
ty::GenericParamDefKind::Const { has_default, synthetic, is_host_effect: _ } => {
ty::GenericParamDefKind::Const { has_default, synthetic } => {
(def.name, GenericParamDefKind::Const {
ty: Box::new(clean_middle_ty(
ty::Binder::dummy(
@ -617,7 +617,7 @@ fn clean_generic_param<'tcx>(
synthetic,
})
}
hir::GenericParamKind::Const { ty, default, synthetic, is_host_effect: _ } => {
hir::GenericParamKind::Const { ty, default, synthetic } => {
(param.name.ident().name, GenericParamDefKind::Const {
ty: Box::new(clean_ty(ty, cx)),
default: default.map(|ct| {
@ -797,7 +797,7 @@ fn clean_ty_generics<'tcx>(
}
true
}
ty::GenericParamDefKind::Const { is_host_effect, .. } => !is_host_effect,
ty::GenericParamDefKind::Const { .. } => true,
})
.map(|param| clean_generic_param_def(param, ParamDefaults::Yes, cx))
.collect();

View File

@ -1366,8 +1366,7 @@ impl GenericParamDef {
pub(crate) fn is_synthetic_param(&self) -> bool {
match self.kind {
GenericParamDefKind::Lifetime { .. } => false,
GenericParamDefKind::Const { synthetic: is_host_effect, .. } => is_host_effect,
GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
GenericParamDefKind::Type { synthetic, .. } => synthetic,
}
}

View File

@ -114,10 +114,6 @@ pub(crate) fn clean_middle_generic_args<'tcx>(
// Elide internal host effect args.
let param = generics.param_at(index, cx.tcx);
if param.is_host_effect() {
return None;
}
let arg = ty::Binder::bind_with_vars(arg, bound_vars);
// Elide arguments that coincide with their default.

View File

@ -207,16 +207,7 @@ fn path_segment_certainty(
if cx.tcx.res_generics_def_id(path_segment.res).is_some() {
let generics = cx.tcx.generics_of(def_id);
let own_count = generics.own_params.len()
- usize::from(generics.host_effect_index.is_some_and(|index| {
// Check that the host index actually belongs to this resolution.
// E.g. for `Add::add`, host_effect_index is `Some(2)`, but it's part of the parent `Add`
// trait's generics.
// Add params: [Self#0, Rhs#1, host#2] parent_count=0, count=3
// Add::add params: [] parent_count=3, count=3
// (3..3).contains(&host_effect_index) => false
(generics.parent_count..generics.count()).contains(&index)
}));
let own_count = generics.own_params.len();
let lhs = if (parent_certainty.is_certain() || generics.parent_count == 0) && own_count == 0 {
Certainty::Certain(None)
} else {
@ -310,8 +301,7 @@ fn type_is_inferable_from_arguments(cx: &LateContext<'_>, expr: &Expr<'_>) -> bo
// Check that all type parameters appear in the functions input types.
(0..(generics.parent_count + generics.own_params.len()) as u32).all(|index| {
Some(index as usize) == generics.host_effect_index
|| fn_sig
fn_sig
.inputs()
.iter()
.any(|input_ty| contains_param(*input_ty.skip_binder(), index))

View File

@ -86,51 +86,3 @@ trait Tuple {}
trait LegacyReceiver {}
impl<T: ?Sized> LegacyReceiver for &T {}
impl<T: ?Sized> LegacyReceiver for &mut T {}
#[stable(feature = "minicore", since = "1.0.0")]
pub mod effects {
use super::Sized;
#[lang = "EffectsNoRuntime"]
#[stable(feature = "minicore", since = "1.0.0")]
pub struct NoRuntime;
#[lang = "EffectsMaybe"]
#[stable(feature = "minicore", since = "1.0.0")]
pub struct Maybe;
#[lang = "EffectsRuntime"]
#[stable(feature = "minicore", since = "1.0.0")]
pub struct Runtime;
#[lang = "EffectsCompat"]
#[stable(feature = "minicore", since = "1.0.0")]
pub trait Compat<#[rustc_runtime] const RUNTIME: bool> {}
#[stable(feature = "minicore", since = "1.0.0")]
impl Compat<false> for NoRuntime {}
#[stable(feature = "minicore", since = "1.0.0")]
impl Compat<true> for Runtime {}
#[stable(feature = "minicore", since = "1.0.0")]
impl<#[rustc_runtime] const RUNTIME: bool> Compat<RUNTIME> for Maybe {}
#[lang = "EffectsTyCompat"]
#[marker]
#[stable(feature = "minicore", since = "1.0.0")]
pub trait TyCompat<T: ?Sized> {}
#[stable(feature = "minicore", since = "1.0.0")]
impl<T: ?Sized> TyCompat<T> for T {}
#[stable(feature = "minicore", since = "1.0.0")]
impl<T: ?Sized> TyCompat<T> for Maybe {}
#[stable(feature = "minicore", since = "1.0.0")]
impl<T: ?Sized> TyCompat<Maybe> for T {}
#[lang = "EffectsIntersection"]
#[stable(feature = "minicore", since = "1.0.0")]
pub trait Intersection {
#[lang = "EffectsIntersectionOutput"]
#[stable(feature = "minicore", since = "1.0.0")]
type Output: ?Sized;
}
}

View File

@ -536,35 +536,3 @@ fn test_const_eval_select() {
const_eval_select((), const_fn, rt_fn);
}
mod effects {
use super::Sized;
#[lang = "EffectsNoRuntime"]
pub struct NoRuntime;
#[lang = "EffectsMaybe"]
pub struct Maybe;
#[lang = "EffectsRuntime"]
pub struct Runtime;
#[lang = "EffectsCompat"]
pub trait Compat<#[rustc_runtime] const RUNTIME: bool> {}
impl Compat<false> for NoRuntime {}
impl Compat<true> for Runtime {}
impl<#[rustc_runtime] const RUNTIME: bool> Compat<RUNTIME> for Maybe {}
#[lang = "EffectsTyCompat"]
#[marker]
pub trait TyCompat<T: ?Sized> {}
impl<T: ?Sized> TyCompat<T> for T {}
impl<T: ?Sized> TyCompat<T> for Maybe {}
impl<T: ?Sized> TyCompat<Maybe> for T {}
#[lang = "EffectsIntersection"]
pub trait Intersection {
#[lang = "EffectsIntersectionOutput"]
type Output: ?Sized;
}
}