lower impl const to bind to host effect param
This commit is contained in:
parent
4f7bb9890c
commit
92f4c59e48
24 changed files with 236 additions and 137 deletions
|
@ -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 {
|
||||
|
|
|
@ -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 =
|
||||
|
@ -260,6 +261,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
path,
|
||||
ParamMode::Optional,
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
);
|
||||
hir::ExprKind::Path(qpath)
|
||||
}
|
||||
|
@ -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))),
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
@ -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) => {
|
||||
|
|
|
@ -85,6 +85,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
|||
allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()),
|
||||
allow_gen_future: Some([sym::gen_future, sym::closure_track_caller][..].into()),
|
||||
generics_def_id_map: Default::default(),
|
||||
host_param_id: None,
|
||||
};
|
||||
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
|
||||
|
||||
|
@ -139,8 +140,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 {
|
||||
|
@ -384,6 +401,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),
|
||||
)
|
||||
|
@ -414,7 +432,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
polarity,
|
||||
defaultness,
|
||||
defaultness_span,
|
||||
constness: self.lower_constness(*constness),
|
||||
generics,
|
||||
of_trait: trait_ref,
|
||||
self_ty: lowered_ty,
|
||||
|
@ -1358,6 +1375,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(
|
||||
|
@ -1405,22 +1445,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();
|
||||
|
@ -1430,14 +1459,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| {
|
||||
|
@ -1476,7 +1506,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,
|
||||
|
|
|
@ -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 {
|
||||
|
@ -1267,6 +1269,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);
|
||||
|
@ -1277,7 +1280,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)
|
||||
}
|
||||
|
||||
|
@ -1361,10 +1364,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(
|
||||
|
@ -2189,7 +2194,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) => {
|
||||
|
@ -2332,8 +2337,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:?}`"),
|
||||
};
|
||||
|
@ -2345,10 +2362,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) }
|
||||
}
|
||||
|
||||
|
@ -2702,6 +2720,57 @@ 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 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()
|
||||
|
|
|
@ -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);
|
||||
|
@ -54,6 +55,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
path,
|
||||
ParamMode::Optional,
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
);
|
||||
break hir::PatKind::Path(qpath);
|
||||
}
|
||||
|
@ -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| {
|
||||
|
|
|
@ -23,6 +23,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
p: &Path,
|
||||
param_mode: ParamMode,
|
||||
itctx: &ImplTraitContext,
|
||||
// constness of the impl/bound if this is a trait path
|
||||
constness: Option<ast::Const>,
|
||||
) -> hir::QPath<'hir> {
|
||||
let qself_position = qself.as_ref().map(|q| q.position);
|
||||
let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx));
|
||||
|
@ -73,6 +75,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
param_mode,
|
||||
parenthesized_generic_args,
|
||||
itctx,
|
||||
// if this is the last segment, add constness to the trait path
|
||||
if i == proj_start - 1 { constness } else { None },
|
||||
)
|
||||
},
|
||||
)),
|
||||
|
@ -119,6 +123,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
param_mode,
|
||||
ParenthesizedGenericArgs::Err,
|
||||
itctx,
|
||||
None,
|
||||
));
|
||||
let qpath = hir::QPath::TypeRelative(ty, hir_segment);
|
||||
|
||||
|
@ -159,6 +164,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
param_mode,
|
||||
ParenthesizedGenericArgs::Err,
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
)
|
||||
})),
|
||||
span: self.lower_span(p.span),
|
||||
|
@ -172,8 +178,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
param_mode: ParamMode,
|
||||
parenthesized_generic_args: ParenthesizedGenericArgs,
|
||||
itctx: &ImplTraitContext,
|
||||
constness: Option<ast::Const>,
|
||||
) -> hir::PathSegment<'hir> {
|
||||
debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,);
|
||||
debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment);
|
||||
let (mut generic_args, infer_args) = if let Some(generic_args) = segment.args.as_deref() {
|
||||
match generic_args {
|
||||
GenericArgs::AngleBracketed(data) => {
|
||||
|
@ -231,6 +238,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
)
|
||||
};
|
||||
|
||||
if let Some(constness) = constness {
|
||||
generic_args.push_constness(self, constness);
|
||||
}
|
||||
|
||||
let has_lifetimes =
|
||||
generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue