Skip to content

Commit e4cd161

Browse files
committed
Auto merge of rust-lang#113210 - fee1-dead-contrib:effects-mvp, r=oli-obk
Effects/keyword generics MVP This adds `feature(effects)`, which adds `const host: bool` to the generics of const functions, const traits and const impls. This will be used to replace the current logic around const traits. r? `@oli-obk`
2 parents dfe0683 + 25fc6c1 commit e4cd161

File tree

15 files changed

+269
-26
lines changed

15 files changed

+269
-26
lines changed

compiler/rustc_ast/src/ast.rs

+9
Original file line numberDiff line numberDiff line change
@@ -2652,6 +2652,15 @@ pub struct NormalAttr {
26522652
pub tokens: Option<LazyAttrTokenStream>,
26532653
}
26542654

2655+
impl NormalAttr {
2656+
pub fn from_ident(ident: Ident) -> Self {
2657+
Self {
2658+
item: AttrItem { path: Path::from_ident(ident), args: AttrArgs::Empty, tokens: None },
2659+
tokens: None,
2660+
}
2661+
}
2662+
}
2663+
26552664
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
26562665
pub struct AttrItem {
26572666
pub path: Path,

compiler/rustc_ast_lowering/src/expr.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -673,14 +673,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
673673
self.lower_attrs(
674674
inner_hir_id,
675675
&[Attribute {
676-
kind: AttrKind::Normal(ptr::P(NormalAttr {
677-
item: AttrItem {
678-
path: Path::from_ident(Ident::new(sym::track_caller, span)),
679-
args: AttrArgs::Empty,
680-
tokens: None,
681-
},
682-
tokens: None,
683-
})),
676+
kind: AttrKind::Normal(ptr::P(NormalAttr::from_ident(Ident::new(sym::track_caller, span)))),
684677
id: self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id(),
685678
style: AttrStyle::Outer,
686679
span: unstable_span,

compiler/rustc_ast_lowering/src/item.rs

+108-9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use super::ResolverAstLoweringExt;
33
use super::{AstOwner, ImplTraitContext, ImplTraitPosition};
44
use super::{FnDeclKind, LoweringContext, ParamMode};
55

6+
use hir::definitions::DefPathData;
67
use rustc_ast::ptr::P;
78
use rustc_ast::visit::AssocCtxt;
89
use rustc_ast::*;
@@ -257,10 +258,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
257258
);
258259

259260
let itctx = ImplTraitContext::Universal;
260-
let (generics, decl) = this.lower_generics(generics, id, &itctx, |this| {
261-
let ret_id = asyncness.opt_return_id();
262-
this.lower_fn_decl(&decl, id, *fn_sig_span, FnDeclKind::Fn, ret_id)
263-
});
261+
let (generics, decl) =
262+
this.lower_generics(generics, header.constness, id, &itctx, |this| {
263+
let ret_id = asyncness.opt_return_id();
264+
this.lower_fn_decl(&decl, id, *fn_sig_span, FnDeclKind::Fn, ret_id)
265+
});
264266
let sig = hir::FnSig {
265267
decl,
266268
header: this.lower_fn_header(*header),
@@ -295,6 +297,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
295297
add_ty_alias_where_clause(&mut generics, *where_clauses, true);
296298
let (generics, ty) = self.lower_generics(
297299
&generics,
300+
Const::No,
298301
id,
299302
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
300303
|this| match ty {
@@ -316,6 +319,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
316319
ItemKind::Enum(enum_definition, generics) => {
317320
let (generics, variants) = self.lower_generics(
318321
generics,
322+
Const::No,
319323
id,
320324
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
321325
|this| {
@@ -329,6 +333,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
329333
ItemKind::Struct(struct_def, generics) => {
330334
let (generics, struct_def) = self.lower_generics(
331335
generics,
336+
Const::No,
332337
id,
333338
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
334339
|this| this.lower_variant_data(hir_id, struct_def),
@@ -338,6 +343,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
338343
ItemKind::Union(vdata, generics) => {
339344
let (generics, vdata) = self.lower_generics(
340345
generics,
346+
Const::No,
341347
id,
342348
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
343349
|this| this.lower_variant_data(hir_id, vdata),
@@ -369,7 +375,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
369375
// parent lifetime.
370376
let itctx = ImplTraitContext::Universal;
371377
let (generics, (trait_ref, lowered_ty)) =
372-
self.lower_generics(ast_generics, id, &itctx, |this| {
378+
self.lower_generics(ast_generics, *constness, id, &itctx, |this| {
373379
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
374380
this.lower_trait_ref(
375381
trait_ref,
@@ -410,8 +416,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
410416
}))
411417
}
412418
ItemKind::Trait(box Trait { is_auto, unsafety, generics, bounds, items }) => {
419+
// FIXME(const_trait_impl, effects, fee1-dead) this should be simplified if possible
420+
let constness = attrs
421+
.unwrap_or(&[])
422+
.iter()
423+
.find(|x| x.has_name(sym::const_trait))
424+
.map_or(Const::No, |x| Const::Yes(x.span));
413425
let (generics, (unsafety, items, bounds)) = self.lower_generics(
414426
generics,
427+
constness,
415428
id,
416429
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
417430
|this| {
@@ -431,6 +444,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
431444
ItemKind::TraitAlias(generics, bounds) => {
432445
let (generics, bounds) = self.lower_generics(
433446
generics,
447+
Const::No,
434448
id,
435449
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
436450
|this| {
@@ -593,7 +607,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
593607
let fdec = &sig.decl;
594608
let itctx = ImplTraitContext::Universal;
595609
let (generics, (fn_dec, fn_args)) =
596-
self.lower_generics(generics, i.id, &itctx, |this| {
610+
self.lower_generics(generics, Const::No, i.id, &itctx, |this| {
597611
(
598612
// Disallow `impl Trait` in foreign items.
599613
this.lower_fn_decl(
@@ -745,6 +759,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
745759
add_ty_alias_where_clause(&mut generics, *where_clauses, false);
746760
let (generics, kind) = self.lower_generics(
747761
&generics,
762+
Const::No,
748763
i.id,
749764
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
750765
|this| {
@@ -843,6 +858,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
843858
add_ty_alias_where_clause(&mut generics, *where_clauses, false);
844859
self.lower_generics(
845860
&generics,
861+
Const::No,
846862
i.id,
847863
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
848864
|this| match ty {
@@ -1201,9 +1217,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
12011217
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
12021218
let header = self.lower_fn_header(sig.header);
12031219
let itctx = ImplTraitContext::Universal;
1204-
let (generics, decl) = self.lower_generics(generics, id, &itctx, |this| {
1205-
this.lower_fn_decl(&sig.decl, id, sig.span, kind, is_async)
1206-
});
1220+
let (generics, decl) =
1221+
self.lower_generics(generics, sig.header.constness, id, &itctx, |this| {
1222+
this.lower_fn_decl(&sig.decl, id, sig.span, kind, is_async)
1223+
});
12071224
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
12081225
}
12091226

@@ -1275,6 +1292,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
12751292
fn lower_generics<T>(
12761293
&mut self,
12771294
generics: &Generics,
1295+
constness: Const,
12781296
parent_node_id: NodeId,
12791297
itctx: &ImplTraitContext,
12801298
f: impl FnOnce(&mut Self) -> T,
@@ -1372,6 +1390,87 @@ impl<'hir> LoweringContext<'_, 'hir> {
13721390
let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);
13731391
predicates.extend(impl_trait_bounds.into_iter());
13741392

1393+
// Desugar `~const` bound in generics into an additional `const host: bool` param
1394+
// if the effects feature is enabled.
1395+
if let Const::Yes(span) = constness && self.tcx.features().effects
1396+
// Do not add host param if it already has it (manually specified)
1397+
&& !params.iter().any(|x| {
1398+
self.attrs.get(&x.hir_id.local_id).map_or(false, |attrs| {
1399+
attrs.iter().any(|x| x.has_name(sym::rustc_host))
1400+
})
1401+
})
1402+
{
1403+
let param_node_id = self.next_node_id();
1404+
let const_node_id = self.next_node_id();
1405+
let def_id = self.create_def(self.local_def_id(parent_node_id), param_node_id, DefPathData::TypeNs(sym::host), span);
1406+
let anon_const: LocalDefId = self.create_def(def_id, const_node_id, DefPathData::AnonConst, span);
1407+
1408+
let hir_id = self.next_id();
1409+
let const_id = self.next_id();
1410+
let const_expr_id = self.next_id();
1411+
let bool_id = self.next_id();
1412+
1413+
self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
1414+
self.children.push((anon_const, hir::MaybeOwner::NonOwner(const_id)));
1415+
1416+
let attr_id = self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id();
1417+
1418+
let attrs = self.arena.alloc_from_iter([
1419+
Attribute {
1420+
kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new(sym::rustc_host, span)))),
1421+
span,
1422+
id: attr_id,
1423+
style: AttrStyle::Outer,
1424+
},
1425+
]);
1426+
self.attrs.insert(hir_id.local_id, attrs);
1427+
1428+
let const_body = self.lower_body(|this| {
1429+
(
1430+
&[],
1431+
hir::Expr {
1432+
hir_id: const_expr_id,
1433+
kind: hir::ExprKind::Lit(
1434+
this.arena.alloc(hir::Lit { node: LitKind::Bool(true), span }),
1435+
),
1436+
span,
1437+
},
1438+
)
1439+
});
1440+
1441+
let param = hir::GenericParam {
1442+
def_id,
1443+
hir_id,
1444+
name: hir::ParamName::Plain(Ident { name: sym::host, span }),
1445+
span,
1446+
kind: hir::GenericParamKind::Const {
1447+
ty: self.arena.alloc(self.ty(
1448+
span,
1449+
hir::TyKind::Path(hir::QPath::Resolved(
1450+
None,
1451+
self.arena.alloc(hir::Path {
1452+
res: Res::PrimTy(hir::PrimTy::Bool),
1453+
span,
1454+
segments: self.arena.alloc_from_iter([hir::PathSegment {
1455+
ident: Ident { name: sym::bool, span },
1456+
hir_id: bool_id,
1457+
res: Res::PrimTy(hir::PrimTy::Bool),
1458+
args: None,
1459+
infer_args: false,
1460+
}]),
1461+
}),
1462+
)),
1463+
)),
1464+
default: Some(hir::AnonConst { def_id: anon_const, hir_id: const_id, body: const_body }),
1465+
},
1466+
colon_span: None,
1467+
pure_wrt_drop: false,
1468+
source: hir::GenericParamSource::Generics,
1469+
};
1470+
1471+
params.push(param);
1472+
}
1473+
13751474
let lowered_generics = self.arena.alloc(hir::Generics {
13761475
params: self.arena.alloc_from_iter(params),
13771476
predicates: self.arena.alloc_from_iter(predicates),

compiler/rustc_feature/src/active.rs

+2
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,8 @@ declare_features! (
391391
(active, doc_masked, "1.21.0", Some(44027), None),
392392
/// Allows `dyn* Trait` objects.
393393
(incomplete, dyn_star, "1.65.0", Some(102425), None),
394+
// Uses generic effect parameters for ~const bounds
395+
(active, effects, "CURRENT_RUSTC_VERSION", Some(102090), None),
394396
/// Allows `X..Y` patterns.
395397
(active, exclusive_range_pattern, "1.11.0", Some(37854), None),
396398
/// Allows exhaustive pattern matching on types that contain uninhabited types.

compiler/rustc_feature/src/builtin_attrs.rs

+6
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
723723
and it is only intended to be used in `alloc`."
724724
),
725725

726+
rustc_attr!(
727+
rustc_host, AttributeType::Normal, template!(Word), ErrorFollowing,
728+
"#[rustc_host] annotates const generic parameters as the `host` effect param, \
729+
and it is only intended for internal use and as a desugaring."
730+
),
731+
726732
BuiltinAttribute {
727733
name: sym::rustc_diagnostic_item,
728734
// FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`.

compiler/rustc_hir_analysis/src/collect/generics_of.rs

+25-5
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_hir::def_id::LocalDefId;
99
use rustc_middle::ty::{self, TyCtxt};
1010
use rustc_session::lint;
1111
use rustc_span::symbol::{kw, Symbol};
12-
use rustc_span::Span;
12+
use rustc_span::{sym, Span};
1313

1414
pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
1515
use rustc_hir::*;
@@ -101,6 +101,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
101101
param_def_id_to_index,
102102
has_self: generics.has_self,
103103
has_late_bound_regions: generics.has_late_bound_regions,
104+
host_effect_index: None,
104105
};
105106
} else {
106107
// HACK(eddyb) this provides the correct generics when
@@ -226,10 +227,12 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
226227
let has_self = opt_self.is_some();
227228
let mut parent_has_self = false;
228229
let mut own_start = has_self as u32;
230+
let mut host_effect_index = None;
229231
let parent_count = parent_def_id.map_or(0, |def_id| {
230232
let generics = tcx.generics_of(def_id);
231233
assert!(!has_self);
232234
parent_has_self = generics.has_self;
235+
host_effect_index = generics.host_effect_index;
233236
own_start = generics.count() as u32;
234237
generics.parent_count + generics.params.len()
235238
});
@@ -251,11 +254,11 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
251254

252255
// Now create the real type and const parameters.
253256
let type_start = own_start - has_self as u32 + params.len() as u32;
254-
let mut i = 0;
257+
let mut i: u32 = 0;
255258
let mut next_index = || {
256259
let prev = i;
257260
i += 1;
258-
prev as u32 + type_start
261+
prev + type_start
259262
};
260263

261264
const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in \
@@ -295,16 +298,32 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
295298
})
296299
}
297300
GenericParamKind::Const { default, .. } => {
298-
if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() {
301+
let is_host_param = tcx.has_attr(param.def_id, sym::rustc_host);
302+
303+
if !matches!(allow_defaults, Defaults::Allowed)
304+
&& default.is_some()
305+
// `rustc_host` effect params are allowed to have defaults.
306+
&& !is_host_param
307+
{
299308
tcx.sess.span_err(
300309
param.span,
301310
"defaults for const parameters are only allowed in \
302311
`struct`, `enum`, `type`, or `trait` definitions",
303312
);
304313
}
305314

315+
let index = next_index();
316+
317+
if is_host_param {
318+
if let Some(idx) = host_effect_index {
319+
bug!("parent also has host effect param? index: {idx}, def: {def_id:?}");
320+
}
321+
322+
host_effect_index = Some(parent_count + index as usize);
323+
}
324+
306325
Some(ty::GenericParamDef {
307-
index: next_index(),
326+
index,
308327
name: param.name.ident().name,
309328
def_id: param.def_id.to_def_id(),
310329
pure_wrt_drop: param.pure_wrt_drop,
@@ -356,6 +375,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
356375
param_def_id_to_index,
357376
has_self: has_self || parent_has_self,
358377
has_late_bound_regions: has_late_bound_regions(tcx, node),
378+
host_effect_index,
359379
}
360380
}
361381

0 commit comments

Comments
 (0)