mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Remove associated type based effects logic
This commit is contained in:
parent
8aca4bab08
commit
a16d491054
@ -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),
|
||||
|
@ -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(¶m.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, ¶m.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 ¶m.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 },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
},
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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 {
|
||||
|
@ -3,13 +3,8 @@
|
||||
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_middle::ty::fold::FnMutDelegate;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::def_id::DefId;
|
||||
|
||||
use crate::hir_ty_lowering::PredicateFilter;
|
||||
|
||||
/// Collects together a list of type bounds. These lists of bounds occur in many places
|
||||
/// in Rust's syntax:
|
||||
@ -47,12 +42,9 @@ impl<'tcx> Bounds<'tcx> {
|
||||
pub(crate) fn push_trait_bound(
|
||||
&mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
defining_def_id: DefId,
|
||||
bound_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
span: Span,
|
||||
polarity: ty::PredicatePolarity,
|
||||
constness: Option<ty::BoundConstness>,
|
||||
predicate_filter: PredicateFilter,
|
||||
) {
|
||||
let clause = (
|
||||
bound_trait_ref
|
||||
@ -68,137 +60,6 @@ impl<'tcx> Bounds<'tcx> {
|
||||
} else {
|
||||
self.clauses.push(clause);
|
||||
}
|
||||
|
||||
// FIXME(effects): Lift this out of `push_trait_bound`, and move it somewhere else.
|
||||
// Perhaps moving this into `lower_poly_trait_ref`, just like we lower associated
|
||||
// type bounds.
|
||||
if !tcx.features().effects() {
|
||||
return;
|
||||
}
|
||||
match predicate_filter {
|
||||
PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => {
|
||||
return;
|
||||
}
|
||||
PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
|
||||
// Ok.
|
||||
}
|
||||
}
|
||||
|
||||
// For `T: ~const Tr` or `T: const Tr`, we need to add an additional bound on the
|
||||
// associated type of `<T as Tr>` and make sure that the effect is compatible.
|
||||
let compat_val = match (tcx.def_kind(defining_def_id), constness) {
|
||||
// FIXME(effects): revisit the correctness of this
|
||||
(_, Some(ty::BoundConstness::Const)) => tcx.consts.false_,
|
||||
// body owners that can have trait bounds
|
||||
(
|
||||
DefKind::Const | DefKind::Fn | DefKind::AssocFn,
|
||||
Some(ty::BoundConstness::ConstIfConst),
|
||||
) => tcx.expected_host_effect_param_for_body(defining_def_id),
|
||||
|
||||
(_, None) => {
|
||||
if !tcx.is_const_trait(bound_trait_ref.def_id()) {
|
||||
return;
|
||||
}
|
||||
tcx.consts.true_
|
||||
}
|
||||
(DefKind::Trait, Some(ty::BoundConstness::ConstIfConst)) => {
|
||||
// we are in a trait, where `bound_trait_ref` could be:
|
||||
// (1) a super trait `trait Foo: ~const Bar`.
|
||||
// - This generates `<Self as Foo>::Effects: TyCompat<<Self as Bar>::Effects>`
|
||||
//
|
||||
// (2) a where clause `where for<..> Something: ~const Bar`.
|
||||
// - This generates `for<..> <Self as Foo>::Effects: TyCompat<<Something as Bar>::Effects>`
|
||||
let Some(own_fx) = tcx.associated_type_for_effects(defining_def_id) else {
|
||||
tcx.dcx().span_delayed_bug(span, "should not have allowed `~const` on a trait that doesn't have `#[const_trait]`");
|
||||
return;
|
||||
};
|
||||
let own_fx_ty = Ty::new_projection(
|
||||
tcx,
|
||||
own_fx,
|
||||
ty::GenericArgs::identity_for_item(tcx, own_fx),
|
||||
);
|
||||
let Some(their_fx) = tcx.associated_type_for_effects(bound_trait_ref.def_id())
|
||||
else {
|
||||
tcx.dcx().span_delayed_bug(span, "`~const` on trait without Effects assoc");
|
||||
return;
|
||||
};
|
||||
let their_fx_ty =
|
||||
Ty::new_projection(tcx, their_fx, bound_trait_ref.skip_binder().args);
|
||||
let compat = tcx.require_lang_item(LangItem::EffectsTyCompat, Some(span));
|
||||
let clause = bound_trait_ref
|
||||
.map_bound(|_| {
|
||||
let trait_ref = ty::TraitRef::new(tcx, compat, [own_fx_ty, their_fx_ty]);
|
||||
ty::ClauseKind::Trait(ty::TraitPredicate {
|
||||
trait_ref,
|
||||
polarity: ty::PredicatePolarity::Positive,
|
||||
})
|
||||
})
|
||||
.upcast(tcx);
|
||||
|
||||
self.clauses.push((clause, span));
|
||||
return;
|
||||
}
|
||||
|
||||
(DefKind::Impl { of_trait: true }, Some(ty::BoundConstness::ConstIfConst)) => {
|
||||
// this is a where clause on an impl header.
|
||||
// push `<T as Tr>::Effects` into the set for the `Min` bound.
|
||||
let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else {
|
||||
tcx.dcx().span_delayed_bug(span, "`~const` on trait without Effects assoc");
|
||||
return;
|
||||
};
|
||||
|
||||
let ty = bound_trait_ref
|
||||
.map_bound(|trait_ref| Ty::new_projection(tcx, assoc, trait_ref.args));
|
||||
|
||||
// When the user has written `for<'a, T> X<'a, T>: ~const Foo`, replace the
|
||||
// binders to dummy ones i.e. `X<'static, ()>` so they can be referenced in
|
||||
// the `Min` associated type properly (which doesn't allow using `for<>`)
|
||||
// This should work for any bound variables as long as they don't have any
|
||||
// bounds e.g. `for<T: Trait>`.
|
||||
// FIXME(effects) reconsider this approach to allow compatibility with `for<T: Tr>`
|
||||
let ty = tcx.replace_bound_vars_uncached(ty, FnMutDelegate {
|
||||
regions: &mut |_| tcx.lifetimes.re_static,
|
||||
types: &mut |_| tcx.types.unit,
|
||||
consts: &mut |_| unimplemented!("`~const` does not support const binders"),
|
||||
});
|
||||
|
||||
self.effects_min_tys.insert(ty, span);
|
||||
return;
|
||||
}
|
||||
// for
|
||||
// ```
|
||||
// trait Foo { type Bar: ~const Trait }
|
||||
// ```
|
||||
// ensure that `<Self::Bar as Trait>::Effects: TyCompat<Self::Effects>`.
|
||||
//
|
||||
// FIXME(effects) this is equality for now, which wouldn't be helpful for a non-const implementor
|
||||
// that uses a `Bar` that implements `Trait` with `Maybe` effects.
|
||||
(DefKind::AssocTy, Some(ty::BoundConstness::ConstIfConst)) => {
|
||||
// FIXME(effects): implement this
|
||||
return;
|
||||
}
|
||||
// probably illegal in this position.
|
||||
(_, Some(ty::BoundConstness::ConstIfConst)) => {
|
||||
tcx.dcx().span_delayed_bug(span, "invalid `~const` encountered");
|
||||
return;
|
||||
}
|
||||
};
|
||||
// create a new projection type `<T as Tr>::Effects`
|
||||
let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else {
|
||||
tcx.dcx().span_delayed_bug(
|
||||
span,
|
||||
"`~const` trait bound has no effect assoc yet no errors encountered?",
|
||||
);
|
||||
return;
|
||||
};
|
||||
let self_ty = Ty::new_projection(tcx, assoc, bound_trait_ref.skip_binder().args);
|
||||
// make `<T as Tr>::Effects: Compat<runtime>`
|
||||
let new_trait_ref =
|
||||
ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::EffectsCompat, Some(span)), [
|
||||
ty::GenericArg::from(self_ty),
|
||||
compat_val.into(),
|
||||
]);
|
||||
self.clauses.push((bound_trait_ref.rebind(new_trait_ref).upcast(tcx), span));
|
||||
}
|
||||
|
||||
pub(crate) fn push_projection_bound(
|
||||
|
@ -58,15 +58,9 @@ fn equate_intrinsic_type<'tcx>(
|
||||
|
||||
// the host effect param should be invisible as it shouldn't matter
|
||||
// whether effects is enabled for the intrinsic provider crate.
|
||||
let consts_count = if generics.host_effect_index.is_some() {
|
||||
own_counts.consts - 1
|
||||
} else {
|
||||
own_counts.consts
|
||||
};
|
||||
|
||||
if gen_count_ok(own_counts.lifetimes, n_lts, "lifetime")
|
||||
&& gen_count_ok(own_counts.types, n_tps, "type")
|
||||
&& gen_count_ok(consts_count, n_cts, "const")
|
||||
&& gen_count_ok(own_counts.consts, n_cts, "const")
|
||||
{
|
||||
let _ = check_function_signature(
|
||||
tcx,
|
||||
|
@ -913,12 +913,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
|
||||
hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => Ok(()),
|
||||
|
||||
// Const parameters are well formed if their type is structural match.
|
||||
hir::GenericParamKind::Const {
|
||||
ty: hir_ty,
|
||||
default: _,
|
||||
is_host_effect: _,
|
||||
synthetic: _,
|
||||
} => {
|
||||
hir::GenericParamKind::Const { ty: hir_ty, default: _, synthetic: _ } => {
|
||||
let ty = tcx.type_of(param.def_id).instantiate_identity();
|
||||
|
||||
if tcx.features().unsized_const_params() {
|
||||
|
@ -53,7 +53,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||
param_def_id_to_index,
|
||||
has_self: opaque_ty_generics.has_self,
|
||||
has_late_bound_regions: opaque_ty_generics.has_late_bound_regions,
|
||||
host_effect_index: parent_generics.host_effect_index,
|
||||
};
|
||||
}
|
||||
|
||||
@ -161,7 +160,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||
param_def_id_to_index,
|
||||
has_self: generics.has_self,
|
||||
has_late_bound_regions: generics.has_late_bound_regions,
|
||||
host_effect_index: None,
|
||||
};
|
||||
} else {
|
||||
// HACK(eddyb) this provides the correct generics when
|
||||
@ -292,12 +290,10 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||
let has_self = opt_self.is_some();
|
||||
let mut parent_has_self = false;
|
||||
let mut own_start = has_self as u32;
|
||||
let mut host_effect_index = None;
|
||||
let parent_count = parent_def_id.map_or(0, |def_id| {
|
||||
let generics = tcx.generics_of(def_id);
|
||||
assert!(!has_self);
|
||||
parent_has_self = generics.has_self;
|
||||
host_effect_index = generics.host_effect_index;
|
||||
own_start = generics.count() as u32;
|
||||
generics.parent_count + generics.own_params.len()
|
||||
});
|
||||
@ -361,12 +357,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||
kind,
|
||||
})
|
||||
}
|
||||
GenericParamKind::Const { ty: _, default, is_host_effect, synthetic } => {
|
||||
if !matches!(allow_defaults, Defaults::Allowed)
|
||||
&& default.is_some()
|
||||
// `host` effect params are allowed to have defaults.
|
||||
&& !is_host_effect
|
||||
{
|
||||
GenericParamKind::Const { ty: _, default, synthetic } => {
|
||||
if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() {
|
||||
tcx.dcx().span_err(
|
||||
param.span,
|
||||
"defaults for const parameters are only allowed in \
|
||||
@ -376,27 +368,12 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||
|
||||
let index = next_index();
|
||||
|
||||
if is_host_effect {
|
||||
if let Some(idx) = host_effect_index {
|
||||
tcx.dcx().span_delayed_bug(
|
||||
param.span,
|
||||
format!("parent also has host effect param? index: {idx}, def: {def_id:?}"),
|
||||
);
|
||||
}
|
||||
|
||||
host_effect_index = Some(index as usize);
|
||||
}
|
||||
|
||||
Some(ty::GenericParamDef {
|
||||
index,
|
||||
name: param.name.ident().name,
|
||||
def_id: param.def_id.to_def_id(),
|
||||
pure_wrt_drop: param.pure_wrt_drop,
|
||||
kind: ty::GenericParamDefKind::Const {
|
||||
has_default: default.is_some(),
|
||||
is_host_effect,
|
||||
synthetic,
|
||||
},
|
||||
kind: ty::GenericParamDefKind::Const { has_default: default.is_some(), synthetic },
|
||||
})
|
||||
}
|
||||
}));
|
||||
@ -459,7 +436,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||
param_def_id_to_index,
|
||||
has_self: has_self || parent_has_self,
|
||||
has_late_bound_regions: has_late_bound_regions(tcx, node),
|
||||
host_effect_index,
|
||||
}
|
||||
}
|
||||
|
||||
@ -540,8 +516,7 @@ impl<'v> Visitor<'v> for AnonConstInParamTyDetector {
|
||||
type Result = ControlFlow<()>;
|
||||
|
||||
fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) -> Self::Result {
|
||||
if let GenericParamKind::Const { ty, default: _, is_host_effect: _, synthetic: _ } = p.kind
|
||||
{
|
||||
if let GenericParamKind::Const { ty, default: _, synthetic: _ } = p.kind {
|
||||
let prev = self.in_param_ty;
|
||||
self.in_param_ty = true;
|
||||
let res = self.visit_ty(ty);
|
||||
|
@ -78,7 +78,6 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
|
||||
#[instrument(level = "trace", skip(tcx), ret)]
|
||||
fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> {
|
||||
use rustc_hir::*;
|
||||
use rustc_middle::ty::Ty;
|
||||
|
||||
match tcx.opt_rpitit_info(def_id.to_def_id()) {
|
||||
Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) => {
|
||||
@ -345,26 +344,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
debug!(?predicates);
|
||||
}
|
||||
|
||||
// add `Self::Effects: Compat<HOST>` to ensure non-const impls don't get called
|
||||
// in const contexts.
|
||||
if let Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(..), .. }) = node
|
||||
&& let Some(host_effect_index) = generics.host_effect_index
|
||||
{
|
||||
let parent = generics.parent.unwrap();
|
||||
let Some(assoc_def_id) = tcx.associated_type_for_effects(parent) else {
|
||||
bug!("associated_type_for_effects returned None when there is host effect in generics");
|
||||
};
|
||||
let effects =
|
||||
Ty::new_projection(tcx, assoc_def_id, ty::GenericArgs::identity_for_item(tcx, parent));
|
||||
let param = generics.param_at(host_effect_index, tcx);
|
||||
let span = tcx.def_span(param.def_id);
|
||||
let host = ty::Const::new_param(tcx, ty::ParamConst::for_def(param));
|
||||
let compat = tcx.require_lang_item(LangItem::EffectsCompat, Some(span));
|
||||
let trait_ref =
|
||||
ty::TraitRef::new(tcx, compat, [ty::GenericArg::from(effects), host.into()]);
|
||||
predicates.push((ty::Binder::dummy(trait_ref).upcast(tcx), span));
|
||||
}
|
||||
|
||||
ty::GenericPredicates {
|
||||
parent: generics.parent,
|
||||
predicates: tcx.arena.alloc_from_iter(predicates),
|
||||
|
@ -186,7 +186,6 @@ impl<'tcx> GenericsBuilder<'tcx> {
|
||||
param_def_id_to_index,
|
||||
has_self,
|
||||
has_late_bound_regions: sig_generics.has_late_bound_regions,
|
||||
host_effect_index: sig_generics.host_effect_index,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -472,10 +471,6 @@ fn check_constraints<'tcx>(
|
||||
}));
|
||||
};
|
||||
|
||||
if tcx.has_host_param(sig_id) {
|
||||
emit("delegation to a function with effect parameter is not supported yet");
|
||||
}
|
||||
|
||||
if let Some(local_sig_id) = sig_id.as_local()
|
||||
&& tcx.hir().opt_delegation_sig_id(local_sig_id).is_some()
|
||||
{
|
||||
|
@ -694,15 +694,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
);
|
||||
|
||||
debug!(?poly_trait_ref);
|
||||
bounds.push_trait_bound(
|
||||
tcx,
|
||||
self.item_def_id().to_def_id(),
|
||||
poly_trait_ref,
|
||||
span,
|
||||
polarity,
|
||||
constness,
|
||||
predicate_filter,
|
||||
);
|
||||
bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);
|
||||
|
||||
let mut dup_constraints = FxIndexMap::default();
|
||||
for constraint in trait_segment.args().constraints {
|
||||
|
@ -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 {
|
||||
|
@ -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(
|
||||
|
@ -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`.
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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)) => {
|
||||
|
@ -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 };
|
||||
|
@ -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,
|
||||
|
@ -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!(
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
//
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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", ¶m.name.ident());
|
||||
}
|
||||
}
|
||||
|
@ -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) }
|
||||
|
@ -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)
|
||||
|
@ -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>,
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -646,13 +646,6 @@ bidirectional_lang_item_map! {
|
||||
Destruct,
|
||||
DiscriminantKind,
|
||||
DynMetadata,
|
||||
EffectsCompat,
|
||||
EffectsIntersection,
|
||||
EffectsIntersectionOutput,
|
||||
EffectsMaybe,
|
||||
EffectsNoRuntime,
|
||||
EffectsRuntime,
|
||||
EffectsTyCompat,
|
||||
Fn,
|
||||
FnMut,
|
||||
FnOnce,
|
||||
|
@ -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(..)
|
||||
|
@ -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, _) => {
|
||||
|
@ -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),
|
||||
})
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
}
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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(
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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),
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
@ -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(
|
||||
|
@ -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,
|
||||
|
@ -20,13 +20,6 @@ pub enum TraitSolverLangItem {
|
||||
Destruct,
|
||||
DiscriminantKind,
|
||||
DynMetadata,
|
||||
EffectsCompat,
|
||||
EffectsIntersection,
|
||||
EffectsIntersectionOutput,
|
||||
EffectsMaybe,
|
||||
EffectsNoRuntime,
|
||||
EffectsRuntime,
|
||||
EffectsTyCompat,
|
||||
Fn,
|
||||
FnMut,
|
||||
FnOnce,
|
||||
|
@ -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::*;
|
||||
|
@ -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() =>
|
||||
{
|
||||
|
@ -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)]
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user