Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In which we start to parse const generics defaults #80547

Merged
merged 7 commits into from
Jan 1, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
@@ -368,6 +368,8 @@ pub enum GenericParamKind {
ty: P<Ty>,
/// Span of the `const` keyword.
kw_span: Span,
/// Optional default value for the const generic param
default: Option<AnonConst>,
},
}

3 changes: 2 additions & 1 deletion compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
@@ -790,8 +790,9 @@ pub fn noop_flat_map_generic_param<T: MutVisitor>(
GenericParamKind::Type { default } => {
visit_opt(default, |default| vis.visit_ty(default));
}
GenericParamKind::Const { ty, kw_span: _ } => {
GenericParamKind::Const { ty, kw_span: _, default } => {
vis.visit_ty(ty);
visit_opt(default, |default| vis.visit_anon_const(default));
}
}
smallvec![param]
7 changes: 6 additions & 1 deletion compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
@@ -578,7 +578,12 @@ pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Generi
match param.kind {
GenericParamKind::Lifetime => (),
GenericParamKind::Type { ref default } => walk_list!(visitor, visit_ty, default),
GenericParamKind::Const { ref ty, .. } => visitor.visit_ty(ty),
GenericParamKind::Const { ref ty, ref default, .. } => {
visitor.visit_ty(ty);
if let Some(default) = default {
visitor.visit_anon_const(default);
}
}
}
}

5 changes: 3 additions & 2 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
@@ -2242,13 +2242,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {

(hir::ParamName::Plain(param.ident), kind)
}
GenericParamKind::Const { ref ty, kw_span: _ } => {
GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
let ty = self
.with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
this.lower_ty(&ty, ImplTraitContext::disallowed())
});
let default = default.as_ref().map(|def| self.lower_anon_const(def));

(hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const { ty })
(hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const { ty, default })
}
};

6 changes: 3 additions & 3 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
@@ -733,7 +733,7 @@ fn validate_generic_param_order(
let (ord_kind, ident) = match &param.kind {
GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident),
GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident),
GenericParamKind::Const { ref ty, kw_span: _ } => {
GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
let ty = pprust::ty_to_string(ty);
let unordered = sess.features_untracked().const_generics;
(ParamKindOrd::Const { unordered }, Some(format!("const {}: {}", param.ident, ty)))
@@ -774,8 +774,8 @@ fn validate_generic_param_order(
}
GenericParamKind::Type { default: None } => (),
GenericParamKind::Lifetime => (),
// FIXME(const_generics:defaults)
GenericParamKind::Const { ty: _, kw_span: _ } => (),
// FIXME(const_generics_defaults)
GenericParamKind::Const { ty: _, kw_span: _, default: _ } => (),
}
first = false;
}
4 changes: 4 additions & 0 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
@@ -619,6 +619,10 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
extended_key_value_attributes,
"arbitrary expressions in key-value attributes are unstable"
);
gate_all!(
const_generics_defaults,
"default values for const generic parameters are experimental"
);
if sess.parse_sess.span_diagnostic.err_count() == 0 {
// Errors for `destructuring_assignment` can get quite noisy, especially where `_` is
// involved, so we only emit errors where there are no other parsing errors.
8 changes: 6 additions & 2 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
@@ -2668,13 +2668,17 @@ impl<'a> State<'a> {
s.print_type(default)
}
}
ast::GenericParamKind::Const { ref ty, kw_span: _ } => {
ast::GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
s.word_space("const");
s.print_ident(param.ident);
s.s.space();
s.word_space(":");
s.print_type(ty);
s.print_type_bounds(":", &param.bounds)
s.print_type_bounds(":", &param.bounds);
if let Some(ref _default) = default {
// FIXME(const_generics_defaults): print the `default` value here
todo!();
}
}
}
});
3 changes: 2 additions & 1 deletion compiler/rustc_builtin_macros/src/deriving/mod.rs
Original file line number Diff line number Diff line change
@@ -145,7 +145,8 @@ fn inject_impl_of_structural_trait(
*default = None;
ast::GenericArg::Type(cx.ty_ident(span, param.ident))
}
ast::GenericParamKind::Const { ty: _, kw_span: _ } => {
ast::GenericParamKind::Const { ty: _, kw_span: _, default } => {
*default = None;
ast::GenericArg::Const(cx.const_ident(span, param.ident))
}
})
6 changes: 5 additions & 1 deletion compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
@@ -581,7 +581,7 @@ declare_features! (
/// Allows `if let` guard in match arms.
(active, if_let_guard, "1.47.0", Some(51114), None),

/// Allows non-trivial generic constants which have to be manually propageted upwards.
/// Allows non-trivial generic constants which have to be manually propagated upwards.
(active, const_evaluatable_checked, "1.48.0", Some(76560), None),

/// Allows basic arithmetic on floating point types in a `const fn`.
@@ -623,6 +623,9 @@ declare_features! (
/// `:pat2018` and `:pat2021` macro matchers.
(active, edition_macro_pats, "1.51.0", Some(54883), None),

/// Allows const generics to have default values (e.g. `struct Foo<const N: usize = 3>(...);`).
(active, const_generics_defaults, "1.51.0", Some(44580), None),

// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
@@ -647,6 +650,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
sym::repr128,
sym::unsized_locals,
sym::capture_disjoint_fields,
sym::const_generics_defaults,
];

/// Some features are not allowed to be used together at the same time, if
2 changes: 2 additions & 0 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
@@ -418,6 +418,8 @@ pub enum GenericParamKind<'hir> {
},
Const {
ty: &'hir Ty<'hir>,
/// Optional default value for the const generic param
default: Option<AnonConst>,
},
}

7 changes: 6 additions & 1 deletion compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
@@ -877,7 +877,12 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Generi
match param.kind {
GenericParamKind::Lifetime { .. } => {}
GenericParamKind::Type { ref default, .. } => walk_list!(visitor, visit_ty, default),
GenericParamKind::Const { ref ty } => visitor.visit_ty(ty),
GenericParamKind::Const { ref ty, ref default } => {
visitor.visit_ty(ty);
if let Some(ref default) = default {
visitor.visit_anon_const(default);
}
}
}
walk_list!(visitor, visit_param_bound, param.bounds);
}
8 changes: 6 additions & 2 deletions compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
@@ -2205,9 +2205,13 @@ impl<'a> State<'a> {
self.print_type(&default)
}
}
GenericParamKind::Const { ref ty } => {
GenericParamKind::Const { ref ty, ref default } => {
self.word_space(":");
self.print_type(ty)
self.print_type(ty);
if let Some(ref _default) = default {
// FIXME(const_generics_defaults): print the `default` value here
todo!();
}
}
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
@@ -958,7 +958,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
ty::GenericParamDefKind::Type { has_default, .. } => {
Some((param.def_id, has_default))
}
ty::GenericParamDefKind::Const => None, // FIXME(const_generics:defaults)
ty::GenericParamDefKind::Const => None, // FIXME(const_generics_defaults)
})
.peekable();
let has_default = {
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
@@ -1834,7 +1834,7 @@ impl EncodeContext<'a, 'tcx> {
EntryKind::ConstParam,
true,
);
// FIXME(const_generics:defaults)
// FIXME(const_generics_defaults)
}
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/print/mod.rs
Original file line number Diff line number Diff line change
@@ -203,7 +203,7 @@ pub trait Printer<'tcx>: Sized {
self.tcx().type_of(param.def_id).subst(self.tcx(), substs),
)
}
ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults)
ty::GenericParamDefKind::Const => false, // FIXME(const_generics_defaults)
}
})
.count();
18 changes: 16 additions & 2 deletions compiler/rustc_parse/src/parser/generics.rs
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ use rustc_ast::{
self as ast, Attribute, GenericBounds, GenericParam, GenericParamKind, WhereClause,
};
use rustc_errors::PResult;
use rustc_span::symbol::kw;
use rustc_span::symbol::{kw, sym};

impl<'a> Parser<'a> {
/// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
@@ -56,12 +56,26 @@ impl<'a> Parser<'a> {
self.expect(&token::Colon)?;
let ty = self.parse_ty()?;

// Parse optional const generics default value, taking care of feature gating the spans
// with the unstable syntax mechanism.
let default = if self.eat(&token::Eq) {
// The gated span goes from the `=` to the end of the const argument that follows (and
// which could be a block expression).
let start = self.prev_token.span;
let const_arg = self.parse_const_arg()?;
let span = start.to(const_arg.value.span);
self.sess.gated_spans.gate(sym::const_generics_defaults, span);
Some(const_arg)
} else {
None
};

Ok(GenericParam {
ident,
id: ast::DUMMY_NODE_ID,
attrs: preceding_attrs.into(),
bounds: Vec::new(),
kind: GenericParamKind::Const { ty, kw_span: const_span },
kind: GenericParamKind::Const { ty, kw_span: const_span, default },
is_placeholder: false,
})
}
29 changes: 18 additions & 11 deletions compiler/rustc_parse/src/parser/path.rs
Original file line number Diff line number Diff line change
@@ -515,6 +515,23 @@ impl<'a> Parser<'a> {
}
}

/// Parse a const argument, e.g. `<3>`. It is assumed the angle brackets will be parsed by
/// the caller.
pub(super) fn parse_const_arg(&mut self) -> PResult<'a, AnonConst> {
// Parse const argument.
let value = if let token::OpenDelim(token::Brace) = self.token.kind {
self.parse_block_expr(
None,
self.token.span,
BlockCheckMode::Default,
ast::AttrVec::new(),
)?
} else {
self.handle_unambiguous_unbraced_const_arg()?
};
Ok(AnonConst { id: ast::DUMMY_NODE_ID, value })
}

/// Parse a generic argument in a path segment.
/// This does not include constraints, e.g., `Item = u8`, which is handled in `parse_angle_arg`.
fn parse_generic_arg(&mut self) -> PResult<'a, Option<GenericArg>> {
@@ -524,17 +541,7 @@ impl<'a> Parser<'a> {
GenericArg::Lifetime(self.expect_lifetime())
} else if self.check_const_arg() {
// Parse const argument.
let value = if let token::OpenDelim(token::Brace) = self.token.kind {
self.parse_block_expr(
None,
self.token.span,
BlockCheckMode::Default,
ast::AttrVec::new(),
)?
} else {
self.handle_unambiguous_unbraced_const_arg()?
};
GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })
GenericArg::Const(self.parse_const_arg()?)
} else if self.check_type() {
// Parse type argument.
match self.parse_ty() {
2 changes: 1 addition & 1 deletion compiler/rustc_passes/src/stability.rs
Original file line number Diff line number Diff line change
@@ -443,7 +443,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {

fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
let kind = match &p.kind {
// FIXME(const_generics:defaults)
// FIXME(const_generics_defaults)
hir::GenericParamKind::Type { default, .. } if default.is_some() => {
AnnotationKind::Container
}
3 changes: 2 additions & 1 deletion compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
@@ -586,7 +586,8 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
// Allow all following defaults to refer to this type parameter.
default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name));
}
GenericParamKind::Const { ref ty, kw_span: _ } => {
GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
// FIXME(const_generics_defaults): handle `default` value here
for bound in &param.bounds {
self.visit_param_bound(bound);
}
2 changes: 1 addition & 1 deletion compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
@@ -214,7 +214,7 @@ enum ResolutionError<'a> {
/// Error E0530: `X` bindings cannot shadow `Y`s.
BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'a>),
/// Error E0128: type parameters with a default cannot use forward-declared identifiers.
ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
ForwardDeclaredTyParam, // FIXME(const_generics_defaults)
/// ERROR E0770: the type of const parameters must not depend on other generic parameters.
ParamInTyOfConstParam(Symbol),
/// constant values inside of type parameter defaults must not depend on generic parameters.
5 changes: 4 additions & 1 deletion compiler/rustc_save_analysis/src/dump_visitor.rs
Original file line number Diff line number Diff line change
@@ -1343,9 +1343,12 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
self.visit_ty(ty);
}
}
hir::GenericParamKind::Const { ref ty } => {
hir::GenericParamKind::Const { ref ty, ref default } => {
self.process_bounds(param.bounds);
self.visit_ty(ty);
if let Some(default) = default {
self.visit_anon_const(default);
}
}
}
}
6 changes: 5 additions & 1 deletion compiler/rustc_save_analysis/src/sig.rs
Original file line number Diff line number Diff line change
@@ -614,9 +614,13 @@ impl<'hir> Sig for hir::Generics<'hir> {
start: offset + text.len(),
end: offset + text.len() + param_text.as_str().len(),
});
if let hir::GenericParamKind::Const { ref ty } = param.kind {
if let hir::GenericParamKind::Const { ref ty, ref default } = param.kind {
param_text.push_str(": ");
param_text.push_str(&ty_to_string(&ty));
if let Some(ref _default) = default {
// FIXME(const_generics_defaults): push the `default` value here
todo!();
}
}
if !param.bounds.is_empty() {
param_text.push_str(": ");
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
@@ -368,6 +368,7 @@ symbols! {
const_fn_transmute,
const_fn_union,
const_generics,
const_generics_defaults,
const_if_match,
const_impl_trait,
const_in_array_repeat_expressions,
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/astconv/generics.rs
Original file line number Diff line number Diff line change
@@ -387,7 +387,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
defaults.types += has_default as usize
}
GenericParamDefKind::Const => {
// FIXME(const_generics:defaults)
// FIXME(const_generics_defaults)
}
};
}
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/astconv/mod.rs
Original file line number Diff line number Diff line change
@@ -486,7 +486,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
GenericParamDefKind::Const => {
let ty = tcx.at(self.span).type_of(param.def_id);
// FIXME(const_generics:defaults)
// FIXME(const_generics_defaults)
if infer_args {
// No const parameters were provided, we can infer all.
self.astconv.ct_infer(ty, Some(param), self.span).into()
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
@@ -1376,7 +1376,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
GenericParamDefKind::Const => {
// FIXME(const_generics:defaults)
// FIXME(const_generics_defaults)
// No const parameters were provided, we have to infer them.
self.fcx.var_for_def(self.span, param)
}
8 changes: 4 additions & 4 deletions compiler/rustc_typeck/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
@@ -286,9 +286,9 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
// We currently only check wf of const params here.
hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => (),

// Const parameters are well formed if their
// type is structural match.
hir::GenericParamKind::Const { ty: hir_ty } => {
// Const parameters are well formed if their type is structural match.
// FIXME(const_generics_defaults): we also need to check that the `default` is wf.
hir::GenericParamKind::Const { ty: hir_ty, default: _ } => {
let ty = tcx.type_of(tcx.hir().local_def_id(param.hir_id));

let err_ty_str;
@@ -785,7 +785,7 @@ fn check_where_clauses<'tcx, 'fcx>(
}

GenericParamDefKind::Const => {
// FIXME(const_generics:defaults)
// FIXME(const_generics_defaults)
fcx.tcx.mk_param_from_def(param)
}
}
Loading