Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement new effects desugaring #120639

Merged
merged 10 commits into from
Jun 29, 2024
Merged
1 change: 0 additions & 1 deletion compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
ParamMode::Optional,
ParenthesizedGenericArgs::Err,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
// Method calls can't have bound modifiers
None,
));
Expand Down
111 changes: 74 additions & 37 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,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);
let mut lctx = LoweringContext::new(self.tcx, self.resolver, self.ast_index);
lctx.with_hir_id_owner(owner, |lctx| f(lctx));

for (def_id, info) in lctx.children {
Expand Down Expand Up @@ -190,6 +190,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (generics, (ty, body_id)) = self.lower_generics(
generics,
Const::No,
false,
id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
Expand Down Expand Up @@ -221,7 +222,7 @@ impl<'hir> LoweringContext<'_, 'hir> {

let itctx = ImplTraitContext::Universal;
let (generics, decl) =
this.lower_generics(generics, header.constness, id, itctx, |this| {
this.lower_generics(generics, header.constness, false, id, itctx, |this| {
this.lower_fn_decl(
decl,
id,
Expand Down Expand Up @@ -265,6 +266,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (generics, ty) = self.lower_generics(
&generics,
Const::No,
false,
id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| match ty {
Expand Down Expand Up @@ -293,6 +295,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (generics, variants) = self.lower_generics(
generics,
Const::No,
false,
id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
Expand All @@ -307,6 +310,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
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),
Expand All @@ -317,6 +321,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (generics, vdata) = self.lower_generics(
generics,
Const::No,
false,
id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| this.lower_variant_data(hir_id, vdata),
Expand Down Expand Up @@ -348,12 +353,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
// parent lifetime.
let itctx = ImplTraitContext::Universal;
let (generics, (trait_ref, lowered_ty)) =
self.lower_generics(ast_generics, *constness, id, itctx, |this| {
self.lower_generics(ast_generics, Const::No, false, id, itctx, |this| {
let modifiers = TraitBoundModifiers {
constness: match *constness {
Const::Yes(span) => BoundConstness::Maybe(span),
Const::No => BoundConstness::Never,
},
constness: BoundConstness::Never,
asyncness: BoundAsyncness::Normal,
// we don't use this in bound lowering
polarity: BoundPolarity::Positive,
Expand Down Expand Up @@ -389,6 +391,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(*s)),
};
hir::ItemKind::Impl(self.arena.alloc(hir::Impl {
constness: self.lower_constness(*constness),
safety: self.lower_safety(*safety, hir::Safety::Safe),
polarity,
defaultness,
Expand All @@ -400,15 +403,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
}))
}
ItemKind::Trait(box Trait { is_auto, safety, generics, bounds, items }) => {
// FIXME(const_trait_impl, effects, fee1-dead) this should be simplified if possible
let constness = attrs
.unwrap_or(&[])
.iter()
.find(|x| x.has_name(sym::const_trait))
.map_or(Const::No, |x| Const::Yes(x.span));
let (generics, (safety, items, bounds)) = self.lower_generics(
generics,
constness,
Const::No,
false,
id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
Expand All @@ -429,6 +427,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (generics, bounds) = self.lower_generics(
generics,
Const::No,
false,
id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
Expand Down Expand Up @@ -609,30 +608,45 @@ impl<'hir> LoweringContext<'_, 'hir> {
// This is used to track which lifetimes have already been defined,
// and which need to be replicated when lowering an async fn.

let generics = match parent_hir.node().expect_item().kind {
let parent_item = parent_hir.node().expect_item();
let constness = match parent_item.kind {
hir::ItemKind::Impl(impl_) => {
self.is_in_trait_impl = impl_.of_trait.is_some();
&impl_.generics
// 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 {
self.tcx
.get_attr(def_id, sym::const_trait)
.map_or(Const::No, |attr| Const::Yes(attr.span))
}
} else {
Const::No
}
}
hir::ItemKind::Trait(_, _, generics, _, _) => generics,
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)),
kind => {
span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr())
}
};

if self.tcx.features().effects {
self.host_param_id = generics
.params
.iter()
.find(|param| {
matches!(param.kind, hir::GenericParamKind::Const { is_host_effect: true, .. })
})
.map(|param| param.def_id);
}

match ctxt {
AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)),
AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item)),
AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item, constness)),
AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item, constness)),
}
}

Expand All @@ -648,7 +662,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let fdec = &sig.decl;
let itctx = ImplTraitContext::Universal;
let (generics, (fn_dec, fn_args)) =
self.lower_generics(generics, Const::No, i.id, itctx, |this| {
self.lower_generics(generics, Const::No, false, i.id, itctx, |this| {
(
// Disallow `impl Trait` in foreign items.
this.lower_fn_decl(
Expand Down Expand Up @@ -765,7 +779,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}

fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
fn lower_trait_item(
&mut self,
i: &AssocItem,
trait_constness: Const,
) -> &'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();
Expand All @@ -775,6 +793,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (generics, kind) = self.lower_generics(
generics,
Const::No,
false,
i.id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
Expand All @@ -795,6 +814,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
i.id,
FnDeclKind::Trait,
sig.header.coroutine_kind,
trait_constness,
);
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
}
Expand All @@ -813,6 +833,7 @@ 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)
}
Expand All @@ -822,6 +843,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (generics, kind) = self.lower_generics(
&generics,
Const::No,
false,
i.id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
Expand Down Expand Up @@ -894,7 +916,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.expr(span, hir::ExprKind::Err(guar))
}

fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
fn lower_impl_item(
&mut self,
i: &AssocItem,
constness_of_trait: Const,
) -> &'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);
Expand All @@ -905,6 +931,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
generics,
Const::No,
false,
i.id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
Expand All @@ -930,6 +957,7 @@ 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))
Expand All @@ -940,6 +968,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_generics(
&generics,
Const::No,
false,
i.id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| match ty {
Expand Down Expand Up @@ -1352,15 +1381,18 @@ 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);
// 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 { Const::No };
let constness =
if kind == FnDeclKind::Inherent { sig.header.constness } else { parent_constness };
let itctx = ImplTraitContext::Universal;
let (generics, decl) = self.lower_generics(generics, constness, id, itctx, |this| {
this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)
});
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)
});
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
}

Expand Down Expand Up @@ -1436,6 +1468,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&mut self,
generics: &Generics,
constness: Const,
force_append_constness: bool,
parent_node_id: NodeId,
itctx: ImplTraitContext,
f: impl FnOnce(&mut Self) -> T,
Expand Down Expand Up @@ -1496,7 +1529,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
// 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
&& self.tcx.features().effects
// 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();
Expand Down Expand Up @@ -1609,13 +1644,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
}),
)),
)),
// FIXME(effects) we might not need a default.
default: Some(self.arena.alloc(hir::AnonConst {
def_id: anon_const,
hir_id: const_id,
body: const_body,
span,
})),
is_host_effect: true,
synthetic: true,
},
colon_span: None,
pure_wrt_drop: false,
Expand Down
Loading
Loading