Skip to content

Commit

Permalink
Rollup merge of rust-lang#113210 - fee1-dead-contrib:effects-mvp, r=o…
Browse files Browse the repository at this point in the history
…li-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`
  • Loading branch information
Dylan-DPC authored Jul 5, 2023
2 parents 99f7d36 + 25fc6c1 commit 9b87a8c
Show file tree
Hide file tree
Showing 15 changed files with 269 additions and 26 deletions.
9 changes: 9 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2652,6 +2652,15 @@ pub struct NormalAttr {
pub tokens: Option<LazyAttrTokenStream>,
}

impl NormalAttr {
pub fn from_ident(ident: Ident) -> Self {
Self {
item: AttrItem { path: Path::from_ident(ident), args: AttrArgs::Empty, tokens: None },
tokens: None,
}
}
}

#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct AttrItem {
pub path: Path,
Expand Down
9 changes: 1 addition & 8 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -673,14 +673,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_attrs(
inner_hir_id,
&[Attribute {
kind: AttrKind::Normal(ptr::P(NormalAttr {
item: AttrItem {
path: Path::from_ident(Ident::new(sym::track_caller, span)),
args: AttrArgs::Empty,
tokens: None,
},
tokens: None,
})),
kind: AttrKind::Normal(ptr::P(NormalAttr::from_ident(Ident::new(sym::track_caller, span)))),
id: self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id(),
style: AttrStyle::Outer,
span: unstable_span,
Expand Down
117 changes: 108 additions & 9 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use super::ResolverAstLoweringExt;
use super::{AstOwner, ImplTraitContext, ImplTraitPosition};
use super::{FnDeclKind, LoweringContext, ParamMode};

use hir::definitions::DefPathData;
use rustc_ast::ptr::P;
use rustc_ast::visit::AssocCtxt;
use rustc_ast::*;
Expand Down Expand Up @@ -257,10 +258,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
);

let itctx = ImplTraitContext::Universal;
let (generics, decl) = this.lower_generics(generics, id, &itctx, |this| {
let ret_id = asyncness.opt_return_id();
this.lower_fn_decl(&decl, id, *fn_sig_span, FnDeclKind::Fn, ret_id)
});
let (generics, decl) =
this.lower_generics(generics, header.constness, id, &itctx, |this| {
let ret_id = asyncness.opt_return_id();
this.lower_fn_decl(&decl, id, *fn_sig_span, FnDeclKind::Fn, ret_id)
});
let sig = hir::FnSig {
decl,
header: this.lower_fn_header(*header),
Expand Down Expand Up @@ -295,6 +297,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
add_ty_alias_where_clause(&mut generics, *where_clauses, true);
let (generics, ty) = self.lower_generics(
&generics,
Const::No,
id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| match ty {
Expand All @@ -316,6 +319,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ItemKind::Enum(enum_definition, generics) => {
let (generics, variants) = self.lower_generics(
generics,
Const::No,
id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
Expand All @@ -329,6 +333,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ItemKind::Struct(struct_def, generics) => {
let (generics, struct_def) = self.lower_generics(
generics,
Const::No,
id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| this.lower_variant_data(hir_id, struct_def),
Expand All @@ -338,6 +343,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ItemKind::Union(vdata, generics) => {
let (generics, vdata) = self.lower_generics(
generics,
Const::No,
id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| this.lower_variant_data(hir_id, vdata),
Expand Down Expand Up @@ -369,7 +375,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// parent lifetime.
let itctx = ImplTraitContext::Universal;
let (generics, (trait_ref, lowered_ty)) =
self.lower_generics(ast_generics, id, &itctx, |this| {
self.lower_generics(ast_generics, *constness, id, &itctx, |this| {
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
this.lower_trait_ref(
trait_ref,
Expand Down Expand Up @@ -410,8 +416,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
}))
}
ItemKind::Trait(box Trait { is_auto, unsafety, 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, (unsafety, items, bounds)) = self.lower_generics(
generics,
constness,
id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
Expand All @@ -431,6 +444,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ItemKind::TraitAlias(generics, bounds) => {
let (generics, bounds) = self.lower_generics(
generics,
Const::No,
id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
Expand Down Expand Up @@ -593,7 +607,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let fdec = &sig.decl;
let itctx = ImplTraitContext::Universal;
let (generics, (fn_dec, fn_args)) =
self.lower_generics(generics, i.id, &itctx, |this| {
self.lower_generics(generics, Const::No, i.id, &itctx, |this| {
(
// Disallow `impl Trait` in foreign items.
this.lower_fn_decl(
Expand Down Expand Up @@ -745,6 +759,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
add_ty_alias_where_clause(&mut generics, *where_clauses, false);
let (generics, kind) = self.lower_generics(
&generics,
Const::No,
i.id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
Expand Down Expand Up @@ -843,6 +858,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
add_ty_alias_where_clause(&mut generics, *where_clauses, false);
self.lower_generics(
&generics,
Const::No,
i.id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| match ty {
Expand Down Expand Up @@ -1201,9 +1217,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
let header = self.lower_fn_header(sig.header);
let itctx = ImplTraitContext::Universal;
let (generics, decl) = self.lower_generics(generics, id, &itctx, |this| {
this.lower_fn_decl(&sig.decl, id, sig.span, kind, is_async)
});
let (generics, decl) =
self.lower_generics(generics, sig.header.constness, id, &itctx, |this| {
this.lower_fn_decl(&sig.decl, id, sig.span, kind, is_async)
});
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
}

Expand Down Expand Up @@ -1275,6 +1292,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_generics<T>(
&mut self,
generics: &Generics,
constness: Const,
parent_node_id: NodeId,
itctx: &ImplTraitContext,
f: impl FnOnce(&mut Self) -> T,
Expand Down Expand Up @@ -1372,6 +1390,87 @@ 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();
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 hir_id = self.next_id();
let const_id = self.next_id();
let const_expr_id = self.next_id();
let bool_id = self.next_id();

self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
self.children.push((anon_const, hir::MaybeOwner::NonOwner(const_id)));

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)))),
span,
id: attr_id,
style: AttrStyle::Outer,
},
]);
self.attrs.insert(hir_id.local_id, attrs);

let const_body = self.lower_body(|this| {
(
&[],
hir::Expr {
hir_id: const_expr_id,
kind: hir::ExprKind::Lit(
this.arena.alloc(hir::Lit { node: LitKind::Bool(true), span }),
),
span,
},
)
});

let param = hir::GenericParam {
def_id,
hir_id,
name: hir::ParamName::Plain(Ident { name: sym::host, span }),
span,
kind: hir::GenericParamKind::Const {
ty: self.arena.alloc(self.ty(
span,
hir::TyKind::Path(hir::QPath::Resolved(
None,
self.arena.alloc(hir::Path {
res: Res::PrimTy(hir::PrimTy::Bool),
span,
segments: self.arena.alloc_from_iter([hir::PathSegment {
ident: Ident { name: sym::bool, span },
hir_id: bool_id,
res: Res::PrimTy(hir::PrimTy::Bool),
args: None,
infer_args: false,
}]),
}),
)),
)),
default: Some(hir::AnonConst { def_id: anon_const, hir_id: const_id, body: const_body }),
},
colon_span: None,
pure_wrt_drop: false,
source: hir::GenericParamSource::Generics,
};

params.push(param);
}

let lowered_generics = self.arena.alloc(hir::Generics {
params: self.arena.alloc_from_iter(params),
predicates: self.arena.alloc_from_iter(predicates),
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,8 @@ declare_features! (
(active, doc_masked, "1.21.0", Some(44027), None),
/// Allows `dyn* Trait` objects.
(incomplete, dyn_star, "1.65.0", Some(102425), None),
// Uses generic effect parameters for ~const bounds
(active, effects, "CURRENT_RUSTC_VERSION", Some(102090), None),
/// Allows `X..Y` patterns.
(active, exclusive_range_pattern, "1.11.0", Some(37854), None),
/// Allows exhaustive pattern matching on types that contain uninhabited types.
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
and it is only intended to be used in `alloc`."
),

rustc_attr!(
rustc_host, AttributeType::Normal, template!(Word), ErrorFollowing,
"#[rustc_host] annotates const generic parameters as the `host` effect param, \
and it is only intended for internal use and as a desugaring."
),

BuiltinAttribute {
name: sym::rustc_diagnostic_item,
// FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`.
Expand Down
30 changes: 25 additions & 5 deletions compiler/rustc_hir_analysis/src/collect/generics_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint;
use rustc_span::symbol::{kw, Symbol};
use rustc_span::Span;
use rustc_span::{sym, Span};

pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
use rustc_hir::*;
Expand Down Expand Up @@ -101,6 +101,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
param_def_id_to_index,
has_self: generics.has_self,
has_late_bound_regions: generics.has_late_bound_regions,
host_effect_index: None,
};
} else {
// HACK(eddyb) this provides the correct generics when
Expand Down Expand Up @@ -226,10 +227,12 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
let has_self = opt_self.is_some();
let mut parent_has_self = false;
let mut own_start = has_self as u32;
let mut host_effect_index = None;
let parent_count = parent_def_id.map_or(0, |def_id| {
let generics = tcx.generics_of(def_id);
assert!(!has_self);
parent_has_self = generics.has_self;
host_effect_index = generics.host_effect_index;
own_start = generics.count() as u32;
generics.parent_count + generics.params.len()
});
Expand All @@ -251,11 +254,11 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {

// Now create the real type and const parameters.
let type_start = own_start - has_self as u32 + params.len() as u32;
let mut i = 0;
let mut i: u32 = 0;
let mut next_index = || {
let prev = i;
i += 1;
prev as u32 + type_start
prev + type_start
};

const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in \
Expand Down Expand Up @@ -295,16 +298,32 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
})
}
GenericParamKind::Const { default, .. } => {
if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() {
let is_host_param = tcx.has_attr(param.def_id, sym::rustc_host);

if !matches!(allow_defaults, Defaults::Allowed)
&& default.is_some()
// `rustc_host` effect params are allowed to have defaults.
&& !is_host_param
{
tcx.sess.span_err(
param.span,
"defaults for const parameters are only allowed in \
`struct`, `enum`, `type`, or `trait` definitions",
);
}

let index = next_index();

if is_host_param {
if let Some(idx) = host_effect_index {
bug!("parent also has host effect param? index: {idx}, def: {def_id:?}");
}

host_effect_index = Some(parent_count + index as usize);
}

Some(ty::GenericParamDef {
index: next_index(),
index,
name: param.name.ident().name,
def_id: param.def_id.to_def_id(),
pure_wrt_drop: param.pure_wrt_drop,
Expand Down Expand Up @@ -356,6 +375,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
param_def_id_to_index,
has_self: has_self || parent_has_self,
has_late_bound_regions: has_late_bound_regions(tcx, node),
host_effect_index,
}
}

Expand Down
Loading

0 comments on commit 9b87a8c

Please sign in to comment.