Skip to content

Commit

Permalink
Auto merge of rust-lang#114545 - fee1-dead-contrib:lower-impl-effect,…
Browse files Browse the repository at this point in the history
… r=oli-obk

correctly lower `impl const` to bind to host effect param

r? `@oli-obk`
  • Loading branch information
bors committed Aug 8, 2023
2 parents f525bb4 057be38 commit f88a8b7
Show file tree
Hide file tree
Showing 64 changed files with 463 additions and 371 deletions.
10 changes: 10 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 313,16 @@ pub enum TraitBoundModifier {
MaybeConstMaybe,
}

impl TraitBoundModifier {
pub fn to_constness(self) -> Const {
match self {
// FIXME(effects) span
Self::MaybeConst => Const::Yes(DUMMY_SP),
_ => Const::No,
}
}
}

/// The AST represents all type param bounds as types.
/// `typeck::collect::compute_bounds` matches these against
/// the "special" built-in traits (see `middle::lang_items`) and
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ast_lowering/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 207,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&sym.path,
ParamMode::Optional,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
hir::InlineAsmOperand::SymStatic { path, def_id }
} else {
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 100,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ParamMode::Optional,
ParenthesizedGenericArgs::Err,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
));
let receiver = self.lower_expr(receiver);
let args =
Expand Down Expand Up @@ -260,6 261,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
path,
ParamMode::Optional,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
hir::ExprKind::Path(qpath)
}
Expand Down Expand Up @@ -307,6 309,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&se.path,
ParamMode::Optional,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
)),
self.arena
.alloc_from_iter(se.fields.iter().map(|x| self.lower_expr_field(x))),
Expand Down Expand Up @@ -1179,6 1182,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
path,
ParamMode::Optional,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
// Destructure like a tuple struct.
let tuple_struct_pat = hir::PatKind::TupleStruct(
Expand All @@ -1198,6 1202,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
path,
ParamMode::Optional,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
// Destructure like a unit struct.
let unit_struct_pat = hir::PatKind::Path(qpath);
Expand All @@ -1222,6 1227,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&se.path,
ParamMode::Optional,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
let fields_omitted = match &se.rest {
StructRest::Base(e) => {
Expand Down
84 changes: 59 additions & 25 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 90,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()),
allow_gen_future,
generics_def_id_map: Default::default(),
host_param_id: None,
};
lctx.with_hir_id_owner(owner, |lctx| f(lctx));

Expand Down Expand Up @@ -144,8 145,24 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
// This is used to track which lifetimes have already been defined,
// and which need to be replicated when lowering an async fn.

if let hir::ItemKind::Impl(impl_) = parent_hir.node().expect_item().kind {
lctx.is_in_trait_impl = impl_.of_trait.is_some();
match parent_hir.node().expect_item().kind {
hir::ItemKind::Impl(impl_) => {
lctx.is_in_trait_impl = impl_.of_trait.is_some();
}
hir::ItemKind::Trait(_, _, generics, _, _) if lctx.tcx.features().effects => {
lctx.host_param_id = generics
.params
.iter()
.find(|param| {
parent_hir
.attrs
.get(param.hir_id.local_id)
.iter()
.any(|attr| attr.has_name(sym::rustc_host))
})
.map(|param| param.def_id);
}
_ => {}
}

match ctxt {
Expand Down Expand Up @@ -389,6 406,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_generics(ast_generics, *constness, id, &itctx, |this| {
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
this.lower_trait_ref(
*constness,
trait_ref,
&ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
)
Expand Down Expand Up @@ -419,7 437,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
polarity,
defaultness,
defaultness_span,
constness: self.lower_constness(*constness),
generics,
of_trait: trait_ref,
self_ty: lowered_ty,
Expand Down Expand Up @@ -1363,6 1380,29 @@ 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 && self.tcx.features().effects {
if let Some(param) = generics.params.iter().find(|x| {
x.attrs.iter().any(|x| x.has_name(sym::rustc_host))
}) {
// user has manually specified a `rustc_host` param, in this case, we set
// the param id so that lowering logic can use that. But we don't create
// another host param, so this gives `None`.
self.host_param_id = Some(self.local_def_id(param.id));
None
} else {
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, DefPathData::TypeNs(sym::host), 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(
Expand Down Expand Up @@ -1410,22 1450,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);
predicates.extend(impl_trait_bounds.into_iter());

// Desugar `~const` bound in generics into an additional `const host: bool` param
// if the effects feature is enabled.
if let Const::Yes(span) = constness && self.tcx.features().effects
// Do not add host param if it already has it (manually specified)
&& !params.iter().any(|x| {
self.attrs.get(&x.hir_id.local_id).map_or(false, |attrs| {
attrs.iter().any(|x| x.has_name(sym::rustc_host))
})
})
{
let param_node_id = self.next_node_id();
if let Some((span, hir_id, def_id)) = host_param_parts {
let const_node_id = self.next_node_id();
let def_id = self.create_def(self.local_def_id(parent_node_id), param_node_id, DefPathData::TypeNs(sym::host), span);
let anon_const: LocalDefId = self.create_def(def_id, const_node_id, DefPathData::AnonConst, span);
let anon_const: LocalDefId =
self.create_def(def_id, const_node_id, DefPathData::AnonConst, span);

let hir_id = self.next_id();
let const_id = self.next_id();
let const_expr_id = self.next_id();
let bool_id = self.next_id();
Expand All @@ -1435,14 1464,15 @@ impl<'hir> LoweringContext<'_, 'hir> {

let attr_id = self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id();

let attrs = self.arena.alloc_from_iter([
Attribute {
kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new(sym::rustc_host, span)))),
let attrs = self.arena.alloc_from_iter([Attribute {
kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new(
sym::rustc_host,
span,
id: attr_id,
style: AttrStyle::Outer,
},
]);
)))),
span,
id: attr_id,
style: AttrStyle::Outer,
}]);
self.attrs.insert(hir_id.local_id, attrs);

let const_body = self.lower_body(|this| {
Expand Down Expand Up @@ -1481,7 1511,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
}),
)),
)),
default: Some(hir::AnonConst { def_id: anon_const, hir_id: const_id, body: const_body }),
default: Some(hir::AnonConst {
def_id: anon_const,
hir_id: const_id,
body: const_body,
}),
},
colon_span: None,
pure_wrt_drop: false,
Expand Down
95 changes: 87 additions & 8 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 142,8 @@ 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<FxHashMap<LocalDefId, LocalDefId>>,

host_param_id: Option<LocalDefId>,
}

trait ResolverAstLoweringExt {
Expand Down Expand Up @@ -1262,6 1264,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span: t.span
},
itctx,
ast::Const::No,
);
let bounds = this.arena.alloc_from_iter([bound]);
let lifetime_bound = this.elided_dyn_bound(t.span);
Expand All @@ -1272,7 1275,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}

let id = self.lower_node_id(t.id);
let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx);
let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx, None);
self.ty_path(id, t.span, qpath)
}

Expand Down Expand Up @@ -1356,10 1359,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| match bound {
GenericBound::Trait(
ty,
TraitBoundModifier::None
modifier @ (TraitBoundModifier::None
| TraitBoundModifier::MaybeConst
| TraitBoundModifier::Negative,
) => Some(this.lower_poly_trait_ref(ty, itctx)),
| TraitBoundModifier::Negative),
) => {
Some(this.lower_poly_trait_ref(ty, itctx, modifier.to_constness()))
}
// `~const ?Bound` will cause an error during AST validation
// anyways, so treat it like `?Bound` as compilation proceeds.
GenericBound::Trait(
Expand Down Expand Up @@ -1952,7 1957,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
) -> hir::GenericBound<'hir> {
match tpb {
GenericBound::Trait(p, modifier) => hir::GenericBound::Trait(
self.lower_poly_trait_ref(p, itctx),
self.lower_poly_trait_ref(p, itctx, modifier.to_constness()),
self.lower_trait_bound_modifier(*modifier),
),
GenericBound::Outlives(lifetime) => {
Expand Down Expand Up @@ -2095,8 2100,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}

fn lower_trait_ref(&mut self, p: &TraitRef, itctx: &ImplTraitContext) -> hir::TraitRef<'hir> {
let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) {
fn lower_trait_ref(
&mut self,
constness: ast::Const,
p: &TraitRef,
itctx: &ImplTraitContext,
) -> hir::TraitRef<'hir> {
let path = match self.lower_qpath(
p.ref_id,
&None,
&p.path,
ParamMode::Explicit,
itctx,
Some(constness),
) {
hir::QPath::Resolved(None, path) => path,
qpath => panic!("lower_trait_ref: unexpected QPath `{qpath:?}`"),
};
Expand All @@ -2108,10 2125,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&mut self,
p: &PolyTraitRef,
itctx: &ImplTraitContext,
constness: ast::Const,
) -> hir::PolyTraitRef<'hir> {
let bound_generic_params =
self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
let trait_ref = self.lower_trait_ref(&p.trait_ref, itctx);
let trait_ref = self.lower_trait_ref(constness, &p.trait_ref, itctx);
hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
}

Expand Down Expand Up @@ -2465,6 2483,67 @@ struct GenericArgsCtor<'hir> {
}

impl<'hir> GenericArgsCtor<'hir> {
fn push_constness(&mut self, lcx: &mut LoweringContext<'_, 'hir>, constness: ast::Const) {
if !lcx.tcx.features().effects {
return;
}

// if bound is non-const, don't add host effect param
let ast::Const::Yes(span) = constness else { return };

let span = lcx.lower_span(span);

let id = lcx.next_node_id();
let hir_id = lcx.next_id();
let body = lcx.lower_body(|lcx| {
(
&[],
match constness {
ast::Const::Yes(_) => {
let hir_id = lcx.next_id();
let res =
Res::Def(DefKind::ConstParam, lcx.host_param_id.unwrap().to_def_id());
let expr_kind = hir::ExprKind::Path(hir::QPath::Resolved(
None,
lcx.arena.alloc(hir::Path {
span,
res,
segments: arena_vec![lcx; hir::PathSegment::new(Ident {
name: sym::host,
span,
}, hir_id, res)],
}),
));
lcx.expr(span, expr_kind)
}
ast::Const::No => lcx.expr(
span,
hir::ExprKind::Lit(
lcx.arena.alloc(hir::Lit { span, node: ast::LitKind::Bool(true) }),
),
),
},
)
});

let attr_id = lcx.tcx.sess.parse_sess.attr_id_generator.mk_attr_id();
let attr = lcx.arena.alloc(Attribute {
kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new(sym::rustc_host, span)))),
span,
id: attr_id,
style: AttrStyle::Outer,
});
lcx.attrs.insert(hir_id.local_id, std::slice::from_ref(attr));

let def_id =
lcx.create_def(lcx.current_hir_id_owner.def_id, id, DefPathData::AnonConst, span);
lcx.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
self.args.push(hir::GenericArg::Const(hir::ConstArg {
value: hir::AnonConst { def_id, hir_id, body },
span,
}))
}

fn is_empty(&self) -> bool {
self.args.is_empty()
&& self.bindings.is_empty()
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_ast_lowering/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
path,
ParamMode::Optional,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct");
break hir::PatKind::TupleStruct(qpath, pats, ddpos);
Expand All @@ -54,6 55,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
path,
ParamMode::Optional,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
break hir::PatKind::Path(qpath);
}
Expand All @@ -64,6 66,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
path,
ParamMode::Optional,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);

let fs = self.arena.alloc_from_iter(fields.iter().map(|f| {
Expand Down
Loading

0 comments on commit f88a8b7

Please sign in to comment.