Skip to content

Commit f88a8b7

Browse files
committed
Auto merge of rust-lang#114545 - fee1-dead-contrib:lower-impl-effect, r=oli-obk
correctly lower `impl const` to bind to host effect param r? `@oli-obk`
2 parents f525bb4 + 057be38 commit f88a8b7

File tree

64 files changed

+463
-371
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+463
-371
lines changed

compiler/rustc_ast/src/ast.rs

+10
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,16 @@ pub enum TraitBoundModifier {
313313
MaybeConstMaybe,
314314
}
315315

316+
impl TraitBoundModifier {
317+
pub fn to_constness(self) -> Const {
318+
match self {
319+
// FIXME(effects) span
320+
Self::MaybeConst => Const::Yes(DUMMY_SP),
321+
_ => Const::No,
322+
}
323+
}
324+
}
325+
316326
/// The AST represents all type param bounds as types.
317327
/// `typeck::collect::compute_bounds` matches these against
318328
/// the "special" built-in traits (see `middle::lang_items`) and

compiler/rustc_ast_lowering/src/asm.rs

+1
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
207207
&sym.path,
208208
ParamMode::Optional,
209209
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
210+
None,
210211
);
211212
hir::InlineAsmOperand::SymStatic { path, def_id }
212213
} else {

compiler/rustc_ast_lowering/src/expr.rs

+6
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
100100
ParamMode::Optional,
101101
ParenthesizedGenericArgs::Err,
102102
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
103+
None,
103104
));
104105
let receiver = self.lower_expr(receiver);
105106
let args =
@@ -260,6 +261,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
260261
path,
261262
ParamMode::Optional,
262263
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
264+
None,
263265
);
264266
hir::ExprKind::Path(qpath)
265267
}
@@ -307,6 +309,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
307309
&se.path,
308310
ParamMode::Optional,
309311
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
312+
None,
310313
)),
311314
self.arena
312315
.alloc_from_iter(se.fields.iter().map(|x| self.lower_expr_field(x))),
@@ -1179,6 +1182,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
11791182
path,
11801183
ParamMode::Optional,
11811184
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
1185+
None,
11821186
);
11831187
// Destructure like a tuple struct.
11841188
let tuple_struct_pat = hir::PatKind::TupleStruct(
@@ -1198,6 +1202,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
11981202
path,
11991203
ParamMode::Optional,
12001204
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
1205+
None,
12011206
);
12021207
// Destructure like a unit struct.
12031208
let unit_struct_pat = hir::PatKind::Path(qpath);
@@ -1222,6 +1227,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
12221227
&se.path,
12231228
ParamMode::Optional,
12241229
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
1230+
None,
12251231
);
12261232
let fields_omitted = match &se.rest {
12271233
StructRest::Base(e) => {

compiler/rustc_ast_lowering/src/item.rs

+59-25
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
9090
allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()),
9191
allow_gen_future,
9292
generics_def_id_map: Default::default(),
93+
host_param_id: None,
9394
};
9495
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
9596

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

147-
if let hir::ItemKind::Impl(impl_) = parent_hir.node().expect_item().kind {
148-
lctx.is_in_trait_impl = impl_.of_trait.is_some();
148+
match parent_hir.node().expect_item().kind {
149+
hir::ItemKind::Impl(impl_) => {
150+
lctx.is_in_trait_impl = impl_.of_trait.is_some();
151+
}
152+
hir::ItemKind::Trait(_, _, generics, _, _) if lctx.tcx.features().effects => {
153+
lctx.host_param_id = generics
154+
.params
155+
.iter()
156+
.find(|param| {
157+
parent_hir
158+
.attrs
159+
.get(param.hir_id.local_id)
160+
.iter()
161+
.any(|attr| attr.has_name(sym::rustc_host))
162+
})
163+
.map(|param| param.def_id);
164+
}
165+
_ => {}
149166
}
150167

151168
match ctxt {
@@ -389,6 +406,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
389406
self.lower_generics(ast_generics, *constness, id, &itctx, |this| {
390407
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
391408
this.lower_trait_ref(
409+
*constness,
392410
trait_ref,
393411
&ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
394412
)
@@ -419,7 +437,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
419437
polarity,
420438
defaultness,
421439
defaultness_span,
422-
constness: self.lower_constness(*constness),
423440
generics,
424441
of_trait: trait_ref,
425442
self_ty: lowered_ty,
@@ -1363,6 +1380,29 @@ impl<'hir> LoweringContext<'_, 'hir> {
13631380
}
13641381
}
13651382

1383+
// Desugar `~const` bound in generics into an additional `const host: bool` param
1384+
// if the effects feature is enabled. This needs to be done before we lower where
1385+
// clauses since where clauses need to bind to the DefId of the host param
1386+
let host_param_parts = if let Const::Yes(span) = constness && self.tcx.features().effects {
1387+
if let Some(param) = generics.params.iter().find(|x| {
1388+
x.attrs.iter().any(|x| x.has_name(sym::rustc_host))
1389+
}) {
1390+
// user has manually specified a `rustc_host` param, in this case, we set
1391+
// the param id so that lowering logic can use that. But we don't create
1392+
// another host param, so this gives `None`.
1393+
self.host_param_id = Some(self.local_def_id(param.id));
1394+
None
1395+
} else {
1396+
let param_node_id = self.next_node_id();
1397+
let hir_id = self.next_id();
1398+
let def_id = self.create_def(self.local_def_id(parent_node_id), param_node_id, DefPathData::TypeNs(sym::host), span);
1399+
self.host_param_id = Some(def_id);
1400+
Some((span, hir_id, def_id))
1401+
}
1402+
} else {
1403+
None
1404+
};
1405+
13661406
let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new();
13671407
predicates.extend(generics.params.iter().filter_map(|param| {
13681408
self.lower_generic_bound_predicate(
@@ -1410,22 +1450,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
14101450
let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);
14111451
predicates.extend(impl_trait_bounds.into_iter());
14121452

1413-
// Desugar `~const` bound in generics into an additional `const host: bool` param
1414-
// if the effects feature is enabled.
1415-
if let Const::Yes(span) = constness && self.tcx.features().effects
1416-
// Do not add host param if it already has it (manually specified)
1417-
&& !params.iter().any(|x| {
1418-
self.attrs.get(&x.hir_id.local_id).map_or(false, |attrs| {
1419-
attrs.iter().any(|x| x.has_name(sym::rustc_host))
1420-
})
1421-
})
1422-
{
1423-
let param_node_id = self.next_node_id();
1453+
if let Some((span, hir_id, def_id)) = host_param_parts {
14241454
let const_node_id = self.next_node_id();
1425-
let def_id = self.create_def(self.local_def_id(parent_node_id), param_node_id, DefPathData::TypeNs(sym::host), span);
1426-
let anon_const: LocalDefId = self.create_def(def_id, const_node_id, DefPathData::AnonConst, span);
1455+
let anon_const: LocalDefId =
1456+
self.create_def(def_id, const_node_id, DefPathData::AnonConst, span);
14271457

1428-
let hir_id = self.next_id();
14291458
let const_id = self.next_id();
14301459
let const_expr_id = self.next_id();
14311460
let bool_id = self.next_id();
@@ -1435,14 +1464,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
14351464

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

1438-
let attrs = self.arena.alloc_from_iter([
1439-
Attribute {
1440-
kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new(sym::rustc_host, span)))),
1467+
let attrs = self.arena.alloc_from_iter([Attribute {
1468+
kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new(
1469+
sym::rustc_host,
14411470
span,
1442-
id: attr_id,
1443-
style: AttrStyle::Outer,
1444-
},
1445-
]);
1471+
)))),
1472+
span,
1473+
id: attr_id,
1474+
style: AttrStyle::Outer,
1475+
}]);
14461476
self.attrs.insert(hir_id.local_id, attrs);
14471477

14481478
let const_body = self.lower_body(|this| {
@@ -1481,7 +1511,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
14811511
}),
14821512
)),
14831513
)),
1484-
default: Some(hir::AnonConst { def_id: anon_const, hir_id: const_id, body: const_body }),
1514+
default: Some(hir::AnonConst {
1515+
def_id: anon_const,
1516+
hir_id: const_id,
1517+
body: const_body,
1518+
}),
14851519
},
14861520
colon_span: None,
14871521
pure_wrt_drop: false,

compiler/rustc_ast_lowering/src/lib.rs

+87-8
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ struct LoweringContext<'a, 'hir> {
142142
/// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this
143143
/// field from the original parameter 'a to the new parameter 'a1.
144144
generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>,
145+
146+
host_param_id: Option<LocalDefId>,
145147
}
146148

147149
trait ResolverAstLoweringExt {
@@ -1262,6 +1264,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12621264
span: t.span
12631265
},
12641266
itctx,
1267+
ast::Const::No,
12651268
);
12661269
let bounds = this.arena.alloc_from_iter([bound]);
12671270
let lifetime_bound = this.elided_dyn_bound(t.span);
@@ -1272,7 +1275,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12721275
}
12731276

12741277
let id = self.lower_node_id(t.id);
1275-
let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx);
1278+
let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx, None);
12761279
self.ty_path(id, t.span, qpath)
12771280
}
12781281

@@ -1356,10 +1359,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13561359
this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| match bound {
13571360
GenericBound::Trait(
13581361
ty,
1359-
TraitBoundModifier::None
1362+
modifier @ (TraitBoundModifier::None
13601363
| TraitBoundModifier::MaybeConst
1361-
| TraitBoundModifier::Negative,
1362-
) => Some(this.lower_poly_trait_ref(ty, itctx)),
1364+
| TraitBoundModifier::Negative),
1365+
) => {
1366+
Some(this.lower_poly_trait_ref(ty, itctx, modifier.to_constness()))
1367+
}
13631368
// `~const ?Bound` will cause an error during AST validation
13641369
// anyways, so treat it like `?Bound` as compilation proceeds.
13651370
GenericBound::Trait(
@@ -1952,7 +1957,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19521957
) -> hir::GenericBound<'hir> {
19531958
match tpb {
19541959
GenericBound::Trait(p, modifier) => hir::GenericBound::Trait(
1955-
self.lower_poly_trait_ref(p, itctx),
1960+
self.lower_poly_trait_ref(p, itctx, modifier.to_constness()),
19561961
self.lower_trait_bound_modifier(*modifier),
19571962
),
19581963
GenericBound::Outlives(lifetime) => {
@@ -2095,8 +2100,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
20952100
}
20962101
}
20972102

2098-
fn lower_trait_ref(&mut self, p: &TraitRef, itctx: &ImplTraitContext) -> hir::TraitRef<'hir> {
2099-
let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) {
2103+
fn lower_trait_ref(
2104+
&mut self,
2105+
constness: ast::Const,
2106+
p: &TraitRef,
2107+
itctx: &ImplTraitContext,
2108+
) -> hir::TraitRef<'hir> {
2109+
let path = match self.lower_qpath(
2110+
p.ref_id,
2111+
&None,
2112+
&p.path,
2113+
ParamMode::Explicit,
2114+
itctx,
2115+
Some(constness),
2116+
) {
21002117
hir::QPath::Resolved(None, path) => path,
21012118
qpath => panic!("lower_trait_ref: unexpected QPath `{qpath:?}`"),
21022119
};
@@ -2108,10 +2125,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21082125
&mut self,
21092126
p: &PolyTraitRef,
21102127
itctx: &ImplTraitContext,
2128+
constness: ast::Const,
21112129
) -> hir::PolyTraitRef<'hir> {
21122130
let bound_generic_params =
21132131
self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
2114-
let trait_ref = self.lower_trait_ref(&p.trait_ref, itctx);
2132+
let trait_ref = self.lower_trait_ref(constness, &p.trait_ref, itctx);
21152133
hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
21162134
}
21172135

@@ -2465,6 +2483,67 @@ struct GenericArgsCtor<'hir> {
24652483
}
24662484

24672485
impl<'hir> GenericArgsCtor<'hir> {
2486+
fn push_constness(&mut self, lcx: &mut LoweringContext<'_, 'hir>, constness: ast::Const) {
2487+
if !lcx.tcx.features().effects {
2488+
return;
2489+
}
2490+
2491+
// if bound is non-const, don't add host effect param
2492+
let ast::Const::Yes(span) = constness else { return };
2493+
2494+
let span = lcx.lower_span(span);
2495+
2496+
let id = lcx.next_node_id();
2497+
let hir_id = lcx.next_id();
2498+
let body = lcx.lower_body(|lcx| {
2499+
(
2500+
&[],
2501+
match constness {
2502+
ast::Const::Yes(_) => {
2503+
let hir_id = lcx.next_id();
2504+
let res =
2505+
Res::Def(DefKind::ConstParam, lcx.host_param_id.unwrap().to_def_id());
2506+
let expr_kind = hir::ExprKind::Path(hir::QPath::Resolved(
2507+
None,
2508+
lcx.arena.alloc(hir::Path {
2509+
span,
2510+
res,
2511+
segments: arena_vec![lcx; hir::PathSegment::new(Ident {
2512+
name: sym::host,
2513+
span,
2514+
}, hir_id, res)],
2515+
}),
2516+
));
2517+
lcx.expr(span, expr_kind)
2518+
}
2519+
ast::Const::No => lcx.expr(
2520+
span,
2521+
hir::ExprKind::Lit(
2522+
lcx.arena.alloc(hir::Lit { span, node: ast::LitKind::Bool(true) }),
2523+
),
2524+
),
2525+
},
2526+
)
2527+
});
2528+
2529+
let attr_id = lcx.tcx.sess.parse_sess.attr_id_generator.mk_attr_id();
2530+
let attr = lcx.arena.alloc(Attribute {
2531+
kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new(sym::rustc_host, span)))),
2532+
span,
2533+
id: attr_id,
2534+
style: AttrStyle::Outer,
2535+
});
2536+
lcx.attrs.insert(hir_id.local_id, std::slice::from_ref(attr));
2537+
2538+
let def_id =
2539+
lcx.create_def(lcx.current_hir_id_owner.def_id, id, DefPathData::AnonConst, span);
2540+
lcx.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
2541+
self.args.push(hir::GenericArg::Const(hir::ConstArg {
2542+
value: hir::AnonConst { def_id, hir_id, body },
2543+
span,
2544+
}))
2545+
}
2546+
24682547
fn is_empty(&self) -> bool {
24692548
self.args.is_empty()
24702549
&& self.bindings.is_empty()

compiler/rustc_ast_lowering/src/pat.rs

+3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
3838
path,
3939
ParamMode::Optional,
4040
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
41+
None,
4142
);
4243
let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct");
4344
break hir::PatKind::TupleStruct(qpath, pats, ddpos);
@@ -54,6 +55,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
5455
path,
5556
ParamMode::Optional,
5657
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
58+
None,
5759
);
5860
break hir::PatKind::Path(qpath);
5961
}
@@ -64,6 +66,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
6466
path,
6567
ParamMode::Optional,
6668
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
69+
None,
6770
);
6871

6972
let fs = self.arena.alloc_from_iter(fields.iter().map(|f| {

0 commit comments

Comments
 (0)