Auto merge of #75384 - JulianKnodt:cg_def, r=varkor,lcnr
implement `feature(const_generics_defaults)` Implements const generics defaults `struct Example<const N: usize=3>`, as well as a query for getting the default of a given const-parameter's def id. There are some remaining FIXME's but they were specified as not blocking for merging this PR. This also puts the defaults behind the unstable feature gate `#![feature(const_generics_defaults)]`. ~~This currently creates a field which is always false on `GenericParamDefKind` for future use when consts are permitted to have defaults. I'm not sure if this is exactly what is best for adding default parameters, but I mimicked the style of type defaults, so hopefully this is ok.~~ r? `@lcnr`
This commit is contained in:
commit
5b33de3340
73 changed files with 517 additions and 191 deletions
|
@ -2290,7 +2290,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
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, default })
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1150,20 +1150,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
|
||||
fn visit_generics(&mut self, generics: &'a Generics) {
|
||||
let mut prev_ty_default = None;
|
||||
let cg_defaults = self.session.features_untracked().const_generics_defaults;
|
||||
|
||||
let mut prev_param_default = None;
|
||||
for param in &generics.params {
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime => (),
|
||||
GenericParamKind::Type { default: Some(_), .. } => {
|
||||
prev_ty_default = Some(param.ident.span);
|
||||
GenericParamKind::Type { default: Some(_), .. }
|
||||
| GenericParamKind::Const { default: Some(_), .. } => {
|
||||
prev_param_default = Some(param.ident.span);
|
||||
}
|
||||
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
|
||||
if let Some(span) = prev_ty_default {
|
||||
if let Some(span) = prev_param_default {
|
||||
let mut err = self.err_handler().struct_span_err(
|
||||
span,
|
||||
"type parameters with a default must be trailing",
|
||||
"generic parameters with a default must be trailing",
|
||||
);
|
||||
if matches!(param.kind, GenericParamKind::Const { .. }) {
|
||||
if matches!(param.kind, GenericParamKind::Const { .. }) && !cg_defaults {
|
||||
err.note(
|
||||
"using type defaults and const parameters \
|
||||
in the same parameter list is currently not permitted",
|
||||
|
|
|
@ -2659,8 +2659,10 @@ impl<'a> State<'a> {
|
|||
s.word_space(":");
|
||||
s.print_type(ty);
|
||||
s.print_type_bounds(":", ¶m.bounds);
|
||||
if let Some(ref _default) = default {
|
||||
// FIXME(const_generics_defaults): print the `default` value here
|
||||
if let Some(ref default) = default {
|
||||
s.s.space();
|
||||
s.word_space("=");
|
||||
s.print_expr(&default.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ struct Foo<T = U, U = ()> {
|
|||
field1: T,
|
||||
field2: U,
|
||||
}
|
||||
// error: type parameters with a default cannot use forward declared
|
||||
// error: generic parameters with a default cannot use forward declared
|
||||
// identifiers
|
||||
```
|
||||
|
||||
|
|
|
@ -366,6 +366,9 @@ pub trait Visitor<'v>: Sized {
|
|||
fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) {
|
||||
walk_generic_param(self, p)
|
||||
}
|
||||
fn visit_const_param_default(&mut self, _param: HirId, ct: &'v AnonConst) {
|
||||
walk_const_param_default(self, ct)
|
||||
}
|
||||
fn visit_generics(&mut self, g: &'v Generics<'v>) {
|
||||
walk_generics(self, g)
|
||||
}
|
||||
|
@ -869,13 +872,17 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Generi
|
|||
GenericParamKind::Const { ref ty, ref default } => {
|
||||
visitor.visit_ty(ty);
|
||||
if let Some(ref default) = default {
|
||||
visitor.visit_anon_const(default);
|
||||
visitor.visit_const_param_default(param.hir_id, default);
|
||||
}
|
||||
}
|
||||
}
|
||||
walk_list!(visitor, visit_param_bound, param.bounds);
|
||||
}
|
||||
|
||||
pub fn walk_const_param_default<'v, V: Visitor<'v>>(visitor: &mut V, ct: &'v AnonConst) {
|
||||
visitor.visit_anon_const(ct)
|
||||
}
|
||||
|
||||
pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) {
|
||||
walk_list!(visitor, visit_generic_param, generics.params);
|
||||
walk_list!(visitor, visit_where_predicate, generics.where_clause.predicates);
|
||||
|
|
|
@ -2266,8 +2266,10 @@ impl<'a> State<'a> {
|
|||
GenericParamKind::Const { ref ty, ref default } => {
|
||||
self.word_space(":");
|
||||
self.print_type(ty);
|
||||
if let Some(ref _default) = default {
|
||||
// FIXME(const_generics_defaults): print the `default` value here
|
||||
if let Some(ref default) = default {
|
||||
self.s.space();
|
||||
self.word_space("=");
|
||||
self.print_anon_const(&default)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ use rustc_hir::{Item, ItemKind, Node};
|
|||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::{
|
||||
self,
|
||||
subst::{Subst, SubstsRef},
|
||||
subst::{GenericArgKind, Subst, SubstsRef},
|
||||
Region, Ty, TyCtxt, TypeFoldable,
|
||||
};
|
||||
use rustc_span::{sym, BytePos, DesugaringKind, Pos, Span};
|
||||
|
@ -957,33 +957,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
) -> SubstsRef<'tcx> {
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
let mut num_supplied_defaults = 0;
|
||||
let mut type_params = generics
|
||||
.params
|
||||
.iter()
|
||||
.rev()
|
||||
.filter_map(|param| match param.kind {
|
||||
ty::GenericParamDefKind::Lifetime => None,
|
||||
ty::GenericParamDefKind::Type { has_default, .. } => {
|
||||
Some((param.def_id, has_default))
|
||||
|
||||
let default_params = generics.params.iter().rev().filter_map(|param| match param.kind {
|
||||
ty::GenericParamDefKind::Type { has_default: true, .. } => Some(param.def_id),
|
||||
ty::GenericParamDefKind::Const { has_default: true } => Some(param.def_id),
|
||||
_ => None,
|
||||
});
|
||||
for (def_id, actual) in default_params.zip(substs.iter().rev()) {
|
||||
match actual.unpack() {
|
||||
GenericArgKind::Const(c) => {
|
||||
if self.tcx.const_param_default(def_id).subst(self.tcx, substs) != c {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ty::GenericParamDefKind::Const => None, // FIXME(const_generics_defaults)
|
||||
})
|
||||
.peekable();
|
||||
let has_default = {
|
||||
let has_default = type_params.peek().map(|(_, has_default)| has_default);
|
||||
*has_default.unwrap_or(&false)
|
||||
};
|
||||
if has_default {
|
||||
let types = substs.types().rev();
|
||||
for ((def_id, has_default), actual) in type_params.zip(types) {
|
||||
if !has_default {
|
||||
break;
|
||||
GenericArgKind::Type(ty) => {
|
||||
if self.tcx.type_of(def_id).subst(self.tcx, substs) != ty {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if self.tcx.type_of(def_id).subst(self.tcx, substs) != actual {
|
||||
break;
|
||||
}
|
||||
num_supplied_defaults += 1;
|
||||
_ => break,
|
||||
}
|
||||
num_supplied_defaults += 1;
|
||||
}
|
||||
let len = generics.params.len();
|
||||
let mut generics = generics.clone();
|
||||
|
|
|
@ -953,6 +953,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
|||
self.root.tables.expn_that_defined.get(self, id).unwrap().decode((self, sess))
|
||||
}
|
||||
|
||||
fn get_const_param_default(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
id: DefIndex,
|
||||
) -> rustc_middle::ty::Const<'tcx> {
|
||||
self.root.tables.const_defaults.get(self, id).unwrap().decode((self, tcx))
|
||||
}
|
||||
|
||||
/// Iterates over all the stability attributes in the given crate.
|
||||
fn get_lib_features(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Option<Symbol>)] {
|
||||
// FIXME: For a proc macro crate, not sure whether we should return the "host"
|
||||
|
|
|
@ -122,6 +122,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
|||
promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) }
|
||||
mir_abstract_const => { cdata.get_mir_abstract_const(tcx, def_id.index) }
|
||||
unused_generic_params => { cdata.get_unused_generic_params(def_id.index) }
|
||||
const_param_default => { tcx.mk_const(cdata.get_const_param_default(tcx, def_id.index)) }
|
||||
mir_const_qualif => { cdata.mir_const_qualif(def_id.index) }
|
||||
fn_sig => { cdata.fn_sig(def_id.index, tcx) }
|
||||
inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) }
|
||||
|
|
|
@ -1876,13 +1876,12 @@ impl EncodeContext<'a, 'tcx> {
|
|||
default.is_some(),
|
||||
);
|
||||
}
|
||||
GenericParamKind::Const { .. } => {
|
||||
self.encode_info_for_generic_param(
|
||||
def_id.to_def_id(),
|
||||
EntryKind::ConstParam,
|
||||
true,
|
||||
);
|
||||
// FIXME(const_generics_defaults)
|
||||
GenericParamKind::Const { ref default, .. } => {
|
||||
let def_id = def_id.to_def_id();
|
||||
self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true);
|
||||
if default.is_some() {
|
||||
record!(self.tables.const_defaults[def_id] <- self.tcx.const_param_default(def_id))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -307,13 +307,14 @@ define_tables! {
|
|||
mir_for_ctfe: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
|
||||
promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
|
||||
mir_abstract_consts: Table<DefIndex, Lazy!(&'tcx [mir::abstract_const::Node<'tcx>])>,
|
||||
const_defaults: Table<DefIndex, Lazy<rustc_middle::ty::Const<'tcx>>>,
|
||||
unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>,
|
||||
// `def_keys` and `def_path_hashes` represent a lazy version of a
|
||||
// `DefPathTable`. This allows us to avoid deserializing an entire
|
||||
// `DefPathTable` up front, since we may only ever use a few
|
||||
// definitions from any given crate.
|
||||
def_keys: Table<DefIndex, Lazy<DefKey>>,
|
||||
def_path_hashes: Table<DefIndex, Lazy<DefPathHash>>
|
||||
def_path_hashes: Table<DefIndex, Lazy<DefPathHash>>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)]
|
||||
|
|
|
@ -395,6 +395,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_const_param_default(&mut self, param: HirId, ct: &'hir AnonConst) {
|
||||
self.with_parent(param, |this| intravisit::walk_const_param_default(this, ct))
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) {
|
||||
self.with_dep_node_owner(ti.def_id, ti, |this, hash| {
|
||||
this.insert_with_hash(ti.span, ti.hir_id(), Node::TraitItem(ti), hash);
|
||||
|
|
|
@ -93,6 +93,12 @@ rustc_queries! {
|
|||
desc { |tcx| "computing the optional const parameter of `{}`", tcx.def_path_str(key.to_def_id()) }
|
||||
}
|
||||
|
||||
/// Given the def_id of a const-generic parameter, computes the associated default const
|
||||
/// parameter. e.g. `fn example<const N: usize=3>` called on `N` would return `3`.
|
||||
query const_param_default(param: DefId) -> &'tcx ty::Const<'tcx> {
|
||||
desc { |tcx| "compute const default for a given parameter `{}`", tcx.def_path_str(param) }
|
||||
}
|
||||
|
||||
/// Records the type of every item.
|
||||
query type_of(key: DefId) -> Ty<'tcx> {
|
||||
desc { |tcx| "computing type of `{}`", tcx.def_path_str(key) }
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::ty::{self, Ty, TyCtxt};
|
|||
use crate::ty::{ParamEnv, ParamEnvAnd};
|
||||
use rustc_errors::ErrorReported;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_macros::HashStable;
|
||||
|
||||
mod int;
|
||||
|
@ -202,3 +202,18 @@ impl<'tcx> Const<'tcx> {
|
|||
.unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Const<'tcx> {
|
||||
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
|
||||
let default_def_id = match tcx.hir().get(hir_id) {
|
||||
hir::Node::GenericParam(hir::GenericParam {
|
||||
kind: hir::GenericParamKind::Const { ty: _, default: Some(ac) },
|
||||
..
|
||||
}) => tcx.hir().local_def_id(ac.hir_id),
|
||||
_ => span_bug!(
|
||||
tcx.def_span(def_id),
|
||||
"`const_param_default` expected a generic parameter with a constant"
|
||||
),
|
||||
};
|
||||
Const::from_anon_const(tcx, default_def_id)
|
||||
}
|
||||
|
|
|
@ -2221,7 +2221,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
let adt_def = self.adt_def(wrapper_def_id);
|
||||
let substs =
|
||||
InternalSubsts::for_item(self, wrapper_def_id, |param, substs| match param.kind {
|
||||
GenericParamDefKind::Lifetime | GenericParamDefKind::Const => bug!(),
|
||||
GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(),
|
||||
GenericParamDefKind::Type { has_default, .. } => {
|
||||
if param.index == 0 {
|
||||
ty_param.into()
|
||||
|
@ -2416,7 +2416,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())).into()
|
||||
}
|
||||
GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(),
|
||||
GenericParamDefKind::Const => {
|
||||
GenericParamDefKind::Const { .. } => {
|
||||
self.mk_const_param(param.index, param.name, self.type_of(param.def_id)).into()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,9 @@ pub enum GenericParamDefKind {
|
|||
object_lifetime_default: ObjectLifetimeDefault,
|
||||
synthetic: Option<hir::SyntheticTyParamKind>,
|
||||
},
|
||||
Const,
|
||||
Const {
|
||||
has_default: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl GenericParamDefKind {
|
||||
|
@ -26,14 +28,14 @@ impl GenericParamDefKind {
|
|||
match self {
|
||||
GenericParamDefKind::Lifetime => "lifetime",
|
||||
GenericParamDefKind::Type { .. } => "type",
|
||||
GenericParamDefKind::Const => "constant",
|
||||
GenericParamDefKind::Const { .. } => "constant",
|
||||
}
|
||||
}
|
||||
pub fn to_ord(&self, tcx: TyCtxt<'_>) -> ast::ParamKindOrd {
|
||||
match self {
|
||||
GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime,
|
||||
GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type,
|
||||
GenericParamDefKind::Const => {
|
||||
GenericParamDefKind::Const { .. } => {
|
||||
ast::ParamKindOrd::Const { unordered: tcx.features().const_generics }
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +107,7 @@ impl<'tcx> Generics {
|
|||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => own_counts.lifetimes += 1,
|
||||
GenericParamDefKind::Type { .. } => own_counts.types += 1,
|
||||
GenericParamDefKind::Const => own_counts.consts += 1,
|
||||
GenericParamDefKind::Const { .. } => own_counts.consts += 1,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,8 +123,8 @@ impl<'tcx> Generics {
|
|||
GenericParamDefKind::Type { has_default, .. } => {
|
||||
own_defaults.types += has_default as usize;
|
||||
}
|
||||
GenericParamDefKind::Const => {
|
||||
// FIXME(const_generics:defaults)
|
||||
GenericParamDefKind::Const { has_default } => {
|
||||
own_defaults.consts += has_default as usize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +148,9 @@ impl<'tcx> Generics {
|
|||
pub fn own_requires_monomorphization(&self) -> bool {
|
||||
for param in &self.params {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => return true,
|
||||
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
|
||||
return true;
|
||||
}
|
||||
GenericParamDefKind::Lifetime => {}
|
||||
}
|
||||
}
|
||||
|
@ -189,7 +193,7 @@ impl<'tcx> Generics {
|
|||
pub fn const_param(&'tcx self, param: &ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef {
|
||||
let param = self.param_at(param.index as usize, tcx);
|
||||
match param.kind {
|
||||
GenericParamDefKind::Const => param,
|
||||
GenericParamDefKind::Const { .. } => param,
|
||||
_ => bug!("expected const parameter, but found another generic parameter"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -593,7 +593,7 @@ fn polymorphize<'tcx>(
|
|||
},
|
||||
|
||||
// Simple case: If parameter is a const or type parameter..
|
||||
ty::GenericParamDefKind::Const | ty::GenericParamDefKind::Type { .. } if
|
||||
ty::GenericParamDefKind::Const { .. } | ty::GenericParamDefKind::Type { .. } if
|
||||
// ..and is within range and unused..
|
||||
unused.contains(param.index).unwrap_or(false) =>
|
||||
// ..then use the identity for this parameter.
|
||||
|
|
|
@ -1949,6 +1949,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
|
|||
trait_impls_of: trait_def::trait_impls_of_provider,
|
||||
all_local_trait_impls: trait_def::all_local_trait_impls,
|
||||
type_uninhabited_from: inhabitedness::type_uninhabited_from,
|
||||
const_param_default: consts::const_param_default,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
|
|
@ -193,17 +193,19 @@ pub trait Printer<'tcx>: Sized {
|
|||
.params
|
||||
.iter()
|
||||
.rev()
|
||||
.take_while(|param| {
|
||||
match param.kind {
|
||||
ty::GenericParamDefKind::Lifetime => false,
|
||||
ty::GenericParamDefKind::Type { has_default, .. } => {
|
||||
has_default
|
||||
&& substs[param.index as usize]
|
||||
== GenericArg::from(
|
||||
self.tcx().type_of(param.def_id).subst(self.tcx(), substs),
|
||||
)
|
||||
}
|
||||
ty::GenericParamDefKind::Const => false, // FIXME(const_generics_defaults)
|
||||
.take_while(|param| match param.kind {
|
||||
ty::GenericParamDefKind::Lifetime => false,
|
||||
ty::GenericParamDefKind::Type { has_default, .. } => {
|
||||
has_default
|
||||
&& substs[param.index as usize]
|
||||
== GenericArg::from(
|
||||
self.tcx().type_of(param.def_id).subst(self.tcx(), substs),
|
||||
)
|
||||
}
|
||||
ty::GenericParamDefKind::Const { has_default } => {
|
||||
has_default
|
||||
&& substs[param.index as usize]
|
||||
== GenericArg::from(self.tcx().const_param_default(param.def_id))
|
||||
}
|
||||
})
|
||||
.count();
|
||||
|
|
|
@ -1175,7 +1175,8 @@ fn create_mono_items_for_default_impls<'tcx>(
|
|||
let substs =
|
||||
InternalSubsts::for_item(tcx, method.def_id, |param, _| match param.kind {
|
||||
GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
|
||||
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
|
||||
GenericParamDefKind::Type { .. }
|
||||
| GenericParamDefKind::Const { .. } => {
|
||||
trait_ref.substs[param.index as usize]
|
||||
}
|
||||
});
|
||||
|
|
|
@ -507,10 +507,9 @@ 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)
|
||||
hir::GenericParamKind::Type { default, .. } if default.is_some() => {
|
||||
AnnotationKind::Container
|
||||
}
|
||||
// Allow stability attributes on default generic arguments.
|
||||
hir::GenericParamKind::Type { default: Some(_), .. }
|
||||
| hir::GenericParamKind::Const { default: Some(_), .. } => AnnotationKind::Container,
|
||||
_ => AnnotationKind::Prohibited,
|
||||
};
|
||||
|
||||
|
|
|
@ -928,8 +928,11 @@ impl ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
|
|||
self.visit(self.ev.tcx.type_of(param.def_id));
|
||||
}
|
||||
}
|
||||
GenericParamDefKind::Const => {
|
||||
GenericParamDefKind::Const { has_default, .. } => {
|
||||
self.visit(self.ev.tcx.type_of(param.def_id));
|
||||
if has_default {
|
||||
self.visit(self.ev.tcx.const_param_default(param.def_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1741,7 +1744,8 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> {
|
|||
self.visit(self.tcx.type_of(param.def_id));
|
||||
}
|
||||
}
|
||||
GenericParamDefKind::Const => {
|
||||
// FIXME(const_evaluatable_checked): May want to look inside const here
|
||||
GenericParamDefKind::Const { .. } => {
|
||||
self.visit(self.tcx.type_of(param.def_id));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -450,12 +450,12 @@ impl<'a> Resolver<'a> {
|
|||
self.session,
|
||||
span,
|
||||
E0128,
|
||||
"type parameters with a default cannot use \
|
||||
"generic parameters with a default cannot use \
|
||||
forward declared identifiers"
|
||||
);
|
||||
err.span_label(
|
||||
span,
|
||||
"defaulted type parameters cannot be forward declared".to_string(),
|
||||
"defaulted generic parameters cannot be forward declared".to_string(),
|
||||
);
|
||||
err
|
||||
}
|
||||
|
|
|
@ -132,10 +132,10 @@ crate enum RibKind<'a> {
|
|||
/// We passed through a `macro_rules!` statement
|
||||
MacroDefinition(DefId),
|
||||
|
||||
/// All bindings in this rib are type parameters that can't be used
|
||||
/// from the default of a type parameter because they're not declared
|
||||
/// before said type parameter. Also see the `visit_generics` override.
|
||||
ForwardTyParamBanRibKind,
|
||||
/// All bindings in this rib are generic parameters that can't be used
|
||||
/// from the default of a generic parameter because they're not declared
|
||||
/// before said generic parameter. Also see the `visit_generics` override.
|
||||
ForwardGenericParamBanRibKind,
|
||||
|
||||
/// We are inside of the type of a const parameter. Can't refer to any
|
||||
/// parameters.
|
||||
|
@ -154,7 +154,7 @@ impl RibKind<'_> {
|
|||
| ModuleRibKind(_)
|
||||
| MacroDefinition(_)
|
||||
| ConstParamTyRibKind => false,
|
||||
AssocItemRibKind | ItemRibKind(_) | ForwardTyParamBanRibKind => true,
|
||||
AssocItemRibKind | ItemRibKind(_) | ForwardGenericParamBanRibKind => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -555,15 +555,16 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
|||
// provide previous type parameters as they're built. We
|
||||
// put all the parameters on the ban list and then remove
|
||||
// them one by one as they are processed and become available.
|
||||
let mut default_ban_rib = Rib::new(ForwardTyParamBanRibKind);
|
||||
let mut default_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
|
||||
let mut found_default = false;
|
||||
default_ban_rib.bindings.extend(generics.params.iter().filter_map(
|
||||
|param| match param.kind {
|
||||
GenericParamKind::Const { .. } | GenericParamKind::Lifetime { .. } => None,
|
||||
GenericParamKind::Type { ref default, .. } => {
|
||||
found_default |= default.is_some();
|
||||
found_default.then_some((Ident::with_dummy_span(param.ident.name), Res::Err))
|
||||
GenericParamKind::Type { default: Some(_), .. }
|
||||
| GenericParamKind::Const { default: Some(_), .. } => {
|
||||
found_default = true;
|
||||
Some((Ident::with_dummy_span(param.ident.name), Res::Err))
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
));
|
||||
|
||||
|
@ -591,8 +592,8 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
|||
|
||||
if let Some(ref ty) = default {
|
||||
self.ribs[TypeNS].push(default_ban_rib);
|
||||
self.with_rib(ValueNS, ForwardTyParamBanRibKind, |this| {
|
||||
// HACK: We use an empty `ForwardTyParamBanRibKind` here which
|
||||
self.with_rib(ValueNS, ForwardGenericParamBanRibKind, |this| {
|
||||
// HACK: We use an empty `ForwardGenericParamBanRibKind` here which
|
||||
// is only used to forbid the use of const parameters inside of
|
||||
// type defaults.
|
||||
//
|
||||
|
@ -865,7 +866,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
| ItemRibKind(..)
|
||||
| ConstantItemRibKind(..)
|
||||
| ModuleRibKind(..)
|
||||
| ForwardTyParamBanRibKind
|
||||
| ForwardGenericParamBanRibKind
|
||||
| ConstParamTyRibKind => {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -2004,7 +2004,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
GenericParamDefKind::Type { object_lifetime_default, .. } => {
|
||||
Some(object_lifetime_default)
|
||||
}
|
||||
GenericParamDefKind::Lifetime | GenericParamDefKind::Const => None,
|
||||
GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
|
|
|
@ -228,7 +228,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.
|
||||
/// Error E0128: generic parameters with a default cannot use forward-declared identifiers.
|
||||
ForwardDeclaredTyParam, // FIXME(const_generics_defaults)
|
||||
/// ERROR E0770: the type of const parameters must not depend on other generic parameters.
|
||||
ParamInTyOfConstParam(Symbol),
|
||||
|
@ -238,7 +238,7 @@ enum ResolutionError<'a> {
|
|||
///
|
||||
/// This error is only emitted when using `min_const_generics`.
|
||||
ParamInNonTrivialAnonConst { name: Symbol, is_type: bool },
|
||||
/// Error E0735: type parameters with a default cannot use `Self`
|
||||
/// Error E0735: generic parameters with a default cannot use `Self`
|
||||
SelfInTyParamDefault,
|
||||
/// Error E0767: use of unreachable label
|
||||
UnreachableLabel { name: Symbol, definition_span: Span, suggestion: Option<LabelSuggestion> },
|
||||
|
@ -2592,8 +2592,8 @@ impl<'a> Resolver<'a> {
|
|||
debug!("validate_res_from_ribs({:?})", res);
|
||||
let ribs = &all_ribs[rib_index + 1..];
|
||||
|
||||
// An invalid forward use of a type parameter from a previous default.
|
||||
if let ForwardTyParamBanRibKind = all_ribs[rib_index].kind {
|
||||
// An invalid forward use of a generic parameter from a previous default.
|
||||
if let ForwardGenericParamBanRibKind = all_ribs[rib_index].kind {
|
||||
if record_used {
|
||||
let res_error = if rib_ident.name == kw::SelfUpper {
|
||||
ResolutionError::SelfInTyParamDefault
|
||||
|
@ -2617,7 +2617,7 @@ impl<'a> Resolver<'a> {
|
|||
| ClosureOrAsyncRibKind
|
||||
| ModuleRibKind(..)
|
||||
| MacroDefinition(..)
|
||||
| ForwardTyParamBanRibKind => {
|
||||
| ForwardGenericParamBanRibKind => {
|
||||
// Nothing to do. Continue.
|
||||
}
|
||||
ItemRibKind(_) | FnItemRibKind | AssocItemRibKind => {
|
||||
|
@ -2689,7 +2689,9 @@ impl<'a> Resolver<'a> {
|
|||
|
||||
// We only forbid constant items if we are inside of type defaults,
|
||||
// for example `struct Foo<T, U = [u8; std::mem::size_of::<T>()]>`
|
||||
ForwardTyParamBanRibKind => {
|
||||
ForwardGenericParamBanRibKind => {
|
||||
// FIXME(const_generic_defaults): we may need to distinguish between
|
||||
// being in type parameter defaults and const parameter defaults
|
||||
in_ty_param_default = true;
|
||||
continue;
|
||||
}
|
||||
|
@ -2782,7 +2784,9 @@ impl<'a> Resolver<'a> {
|
|||
|
||||
// We only forbid constant items if we are inside of type defaults,
|
||||
// for example `struct Foo<T, U = [u8; std::mem::size_of::<T>()]>`
|
||||
ForwardTyParamBanRibKind => {
|
||||
ForwardGenericParamBanRibKind => {
|
||||
// FIXME(const_generic_defaults): we may need to distinguish between
|
||||
// being in type parameter defaults and const parameter defaults
|
||||
in_ty_param_default = true;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -614,11 +614,12 @@ 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, ref default } = param.kind {
|
||||
if let hir::GenericParamKind::Const { ref ty, 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
|
||||
if let Some(default) = default {
|
||||
param_text.push_str(" = ");
|
||||
param_text.push_str(&id_to_string(&scx.tcx.hir(), default.hir_id));
|
||||
}
|
||||
}
|
||||
if !param.bounds.is_empty() {
|
||||
|
|
|
@ -384,6 +384,7 @@ symbols! {
|
|||
const_fn_fn_ptr_basics,
|
||||
const_fn_transmute,
|
||||
const_fn_union,
|
||||
const_generic_defaults,
|
||||
const_generics,
|
||||
const_generics_defaults,
|
||||
const_if_match,
|
||||
|
|
|
@ -176,7 +176,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
|
||||
for param in generics.params.iter() {
|
||||
let value = match param.kind {
|
||||
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
|
||||
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
|
||||
trait_ref.substs[param.index as usize].to_string()
|
||||
}
|
||||
GenericParamDefKind::Lifetime => continue,
|
||||
|
|
|
@ -483,7 +483,7 @@ fn vtable_methods<'tcx>(
|
|||
let substs = trait_ref.map_bound(|trait_ref| {
|
||||
InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
|
||||
GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
|
||||
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
|
||||
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
|
||||
trait_ref.substs[param.index as usize]
|
||||
}
|
||||
})
|
||||
|
|
|
@ -337,7 +337,7 @@ impl<'tcx> OnUnimplementedFormatString {
|
|||
.iter()
|
||||
.filter_map(|param| {
|
||||
let value = match param.kind {
|
||||
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
|
||||
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
|
||||
trait_ref.substs[param.index as usize].to_string()
|
||||
}
|
||||
GenericParamDefKind::Lifetime => return None,
|
||||
|
|
|
@ -739,7 +739,7 @@ fn bound_vars_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> {
|
|||
tcx.mk_region(ty::RegionKind::ReLateBound(ty::INNERMOST, br)).into()
|
||||
}
|
||||
|
||||
ty::GenericParamDefKind::Const => tcx
|
||||
ty::GenericParamDefKind::Const { .. } => tcx
|
||||
.mk_const(ty::Const {
|
||||
val: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)),
|
||||
ty: tcx.type_of(param.def_id),
|
||||
|
|
|
@ -64,7 +64,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
kind: hir::TyKind::Path(rustc_hir::QPath::Resolved(_, path)),
|
||||
..
|
||||
}),
|
||||
GenericParamDefKind::Const,
|
||||
GenericParamDefKind::Const { .. },
|
||||
) => match path.res {
|
||||
Res::Err => {
|
||||
add_braces_suggestion(arg, &mut err);
|
||||
|
@ -93,7 +93,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
},
|
||||
(
|
||||
GenericArg::Type(hir::Ty { kind: hir::TyKind::Path(_), .. }),
|
||||
GenericParamDefKind::Const,
|
||||
GenericParamDefKind::Const { .. },
|
||||
) => add_braces_suggestion(arg, &mut err),
|
||||
(
|
||||
GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
|
||||
|
@ -236,7 +236,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
match (arg, ¶m.kind, arg_count.explicit_late_bound) {
|
||||
(GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
|
||||
| (GenericArg::Type(_), GenericParamDefKind::Type { .. }, _)
|
||||
| (GenericArg::Const(_), GenericParamDefKind::Const, _) => {
|
||||
| (GenericArg::Const(_), GenericParamDefKind::Const { .. }, _) => {
|
||||
substs.push(ctx.provided_kind(param, arg));
|
||||
args.next();
|
||||
params.next();
|
||||
|
@ -282,7 +282,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
GenericParamDefKind::Type { .. } => {
|
||||
ParamKindOrd::Type
|
||||
}
|
||||
GenericParamDefKind::Const => {
|
||||
GenericParamDefKind::Const { .. } => {
|
||||
ParamKindOrd::Const {
|
||||
unordered: tcx
|
||||
.features()
|
||||
|
@ -499,7 +499,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
let expected_min = if infer_args {
|
||||
0
|
||||
} else {
|
||||
param_counts.consts + named_type_param_count - default_counts.types
|
||||
param_counts.consts + named_type_param_count
|
||||
- default_counts.types
|
||||
- default_counts.consts
|
||||
};
|
||||
|
||||
check_generics(
|
||||
|
|
|
@ -443,7 +443,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self.astconv.ast_ty_to_ty(&ty).into()
|
||||
}
|
||||
}
|
||||
(GenericParamDefKind::Const, GenericArg::Const(ct)) => {
|
||||
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
||||
ty::Const::from_opt_const_arg_anon_const(
|
||||
tcx,
|
||||
ty::WithOptConstParam {
|
||||
|
@ -504,15 +504,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
tcx.ty_error().into()
|
||||
}
|
||||
}
|
||||
GenericParamDefKind::Const => {
|
||||
GenericParamDefKind::Const { has_default } => {
|
||||
let ty = tcx.at(self.span).type_of(param.def_id);
|
||||
// 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()
|
||||
if !infer_args && has_default {
|
||||
tcx.const_param_default(param.def_id).into()
|
||||
} else {
|
||||
// We've already errored above about the mismatch.
|
||||
tcx.const_error(ty).into()
|
||||
if infer_args {
|
||||
self.astconv.ct_infer(ty, Some(param), self.span).into()
|
||||
} else {
|
||||
// We've already errored above about the mismatch.
|
||||
tcx.const_error(ty).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -792,11 +792,11 @@ fn compare_synthetic_generics<'tcx>(
|
|||
let trait_m_generics = tcx.generics_of(trait_m.def_id);
|
||||
let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| match param.kind {
|
||||
GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
|
||||
GenericParamDefKind::Lifetime | GenericParamDefKind::Const => None,
|
||||
GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None,
|
||||
});
|
||||
let trait_m_type_params = trait_m_generics.params.iter().filter_map(|param| match param.kind {
|
||||
GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
|
||||
GenericParamDefKind::Lifetime | GenericParamDefKind::Const => None,
|
||||
GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None,
|
||||
});
|
||||
for ((impl_def_id, impl_synthetic), (trait_def_id, trait_synthetic)) in
|
||||
impl_m_type_params.zip(trait_m_type_params)
|
||||
|
|
|
@ -1405,7 +1405,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
|
||||
self.fcx.to_ty(ty).into()
|
||||
}
|
||||
(GenericParamDefKind::Const, GenericArg::Const(ct)) => {
|
||||
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
||||
self.fcx.const_arg_to_const(&ct.value, param.def_id).into()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
|
@ -1443,10 +1443,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.fcx.var_for_def(self.span, param)
|
||||
}
|
||||
}
|
||||
GenericParamDefKind::Const => {
|
||||
// FIXME(const_generics_defaults)
|
||||
// No const parameters were provided, we have to infer them.
|
||||
self.fcx.var_for_def(self.span, param)
|
||||
GenericParamDefKind::Const { has_default, .. } => {
|
||||
if !infer_args && has_default {
|
||||
tcx.const_param_default(param.def_id).into()
|
||||
} else {
|
||||
self.fcx.var_for_def(self.span, param)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -358,7 +358,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
|
||||
self.cfcx.to_ty(ty).into()
|
||||
}
|
||||
(GenericParamDefKind::Const, GenericArg::Const(ct)) => {
|
||||
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
||||
self.cfcx.const_arg_to_const(&ct.value, param.def_id).into()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
|
|
|
@ -308,7 +308,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Construct a trait-reference `self_ty : Trait<input_tys>`
|
||||
let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime | GenericParamDefKind::Const => {}
|
||||
GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => {}
|
||||
GenericParamDefKind::Type { .. } => {
|
||||
if param.index == 0 {
|
||||
return self_ty.into();
|
||||
|
|
|
@ -1700,7 +1700,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
// In general, during probe we erase regions.
|
||||
self.tcx.lifetimes.re_erased.into()
|
||||
}
|
||||
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
|
||||
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
|
||||
self.var_for_def(self.span, param)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -713,10 +713,11 @@ fn check_where_clauses<'tcx, 'fcx>(
|
|||
let generics = tcx.generics_of(def_id);
|
||||
|
||||
let is_our_default = |def: &ty::GenericParamDef| match def.kind {
|
||||
GenericParamDefKind::Type { has_default, .. } => {
|
||||
GenericParamDefKind::Type { has_default, .. }
|
||||
| GenericParamDefKind::Const { has_default } => {
|
||||
has_default && def.index >= generics.parent_count as u32
|
||||
}
|
||||
_ => unreachable!(),
|
||||
GenericParamDefKind::Lifetime => unreachable!(),
|
||||
};
|
||||
|
||||
// Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.
|
||||
|
@ -771,10 +772,15 @@ fn check_where_clauses<'tcx, 'fcx>(
|
|||
|
||||
fcx.tcx.mk_param_from_def(param)
|
||||
}
|
||||
|
||||
GenericParamDefKind::Const => {
|
||||
// FIXME(const_generics_defaults)
|
||||
fcx.tcx.mk_param_from_def(param)
|
||||
GenericParamDefKind::Const { .. } => {
|
||||
if is_our_default(param) {
|
||||
let default_ct = tcx.const_param_default(param.def_id);
|
||||
// Const params currently have to be concrete.
|
||||
assert!(!default_ct.needs_subst());
|
||||
default_ct.into()
|
||||
} else {
|
||||
fcx.tcx.mk_param_from_def(param)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -254,10 +254,15 @@ impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
|
|||
self.tcx.ensure().type_of(def_id);
|
||||
}
|
||||
hir::GenericParamKind::Type { .. } => {}
|
||||
hir::GenericParamKind::Const { .. } => {
|
||||
hir::GenericParamKind::Const { default, .. } => {
|
||||
let def_id = self.tcx.hir().local_def_id(param.hir_id);
|
||||
self.tcx.ensure().type_of(def_id);
|
||||
// FIXME(const_generics_defaults)
|
||||
if let Some(default) = default {
|
||||
let default_def_id = self.tcx.hir().local_def_id(default.hir_id);
|
||||
// need to store default and type of default
|
||||
self.tcx.ensure().type_of(default_def_id);
|
||||
self.tcx.ensure().const_param_default(def_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1523,7 +1528,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
|||
|lint| {
|
||||
lint.build(
|
||||
"defaults for type parameters are only allowed in \
|
||||
`struct`, `enum`, `type`, or `trait` definitions.",
|
||||
`struct`, `enum`, `type`, or `trait` definitions",
|
||||
)
|
||||
.emit();
|
||||
},
|
||||
|
@ -1549,13 +1554,21 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
|||
i += 1;
|
||||
Some(param_def)
|
||||
}
|
||||
GenericParamKind::Const { .. } => {
|
||||
GenericParamKind::Const { default, .. } => {
|
||||
if !allow_defaults && default.is_some() {
|
||||
tcx.sess.span_err(
|
||||
param.span,
|
||||
"defaults for const parameters are only allowed in \
|
||||
`struct`, `enum`, `type`, or `trait` definitions",
|
||||
);
|
||||
}
|
||||
|
||||
let param_def = ty::GenericParamDef {
|
||||
index: type_start + i as u32,
|
||||
name: param.name.ident().name,
|
||||
def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(),
|
||||
pure_wrt_drop: param.pure_wrt_drop,
|
||||
kind: ty::GenericParamDefKind::Const,
|
||||
kind: ty::GenericParamDefKind::Const { has_default: default.is_some() },
|
||||
};
|
||||
i += 1;
|
||||
Some(param_def)
|
||||
|
|
|
@ -83,7 +83,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
|
|||
return generics
|
||||
.params
|
||||
.iter()
|
||||
.filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const))
|
||||
.filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. }))
|
||||
.nth(arg_index)
|
||||
.map(|param| param.def_id);
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
|
|||
tcx.generics_of(type_dependent_def)
|
||||
.params
|
||||
.iter()
|
||||
.filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const))
|
||||
.filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. }))
|
||||
.nth(idx)
|
||||
.map(|param| param.def_id)
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
|
|||
generics
|
||||
.params
|
||||
.iter()
|
||||
.filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const))
|
||||
.filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. }))
|
||||
.nth(arg_index)
|
||||
.map(|param| param.def_id)
|
||||
}
|
||||
|
@ -436,6 +436,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
|||
.discr_type()
|
||||
.to_ty(tcx),
|
||||
|
||||
Node::GenericParam(&GenericParam {
|
||||
hir_id: param_hir_id,
|
||||
kind: GenericParamKind::Const { default: Some(ct), .. },
|
||||
..
|
||||
}) if ct.hir_id == hir_id => tcx.type_of(tcx.hir().local_def_id(param_hir_id)),
|
||||
|
||||
x => tcx.ty_error_with_message(
|
||||
DUMMY_SP,
|
||||
&format!("unexpected const parent in type_of_def_id(): {:?}", x),
|
||||
|
|
|
@ -173,7 +173,7 @@ fn enforce_impl_params_are_constrained(
|
|||
);
|
||||
}
|
||||
}
|
||||
ty::GenericParamDefKind::Const => {
|
||||
ty::GenericParamDefKind::Const { .. } => {
|
||||
let param_ct = ty::ParamConst::for_def(param);
|
||||
if !input_parameters.contains(&cgp::Parameter::from(param_ct)) {
|
||||
report_unused_parameter(
|
||||
|
|
|
@ -78,7 +78,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
|
|||
|
||||
// Make all const parameters invariant.
|
||||
for param in generics.params.iter() {
|
||||
if let ty::GenericParamDefKind::Const = param.kind {
|
||||
if let ty::GenericParamDefKind::Const { .. } = param.kind {
|
||||
variances[param.index as usize] = ty::Invariant;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
#![feature(const_generics)]
|
||||
#![feature(const_generics_defaults)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
pub struct Defaulted<const N: usize=3>;
|
||||
impl Defaulted {
|
||||
pub fn new() -> Self {
|
||||
Defaulted
|
||||
}
|
||||
}
|
||||
impl<const N: usize> Defaulted<N> {
|
||||
pub fn value(&self) -> usize {
|
||||
N
|
||||
}
|
||||
}
|
30
src/test/ui/const-generics/defaults/const-default.rs
Normal file
30
src/test/ui/const-generics/defaults/const-default.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
// run-pass
|
||||
|
||||
#![feature(const_generics)]
|
||||
#![feature(const_generics_defaults)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
|
||||
pub struct ConstDefault<const N: usize = 3>;
|
||||
|
||||
impl<const N: usize> ConstDefault<N> {
|
||||
fn foo(self) -> usize {
|
||||
N
|
||||
}
|
||||
}
|
||||
|
||||
impl ConstDefault {
|
||||
fn new() -> Self {
|
||||
ConstDefault
|
||||
}
|
||||
|
||||
fn bar(self) {}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let s = ConstDefault::new();
|
||||
assert_eq!(s.foo(), 3);
|
||||
|
||||
let w = ConstDefault::<3>;
|
||||
w.bar();
|
||||
}
|
20
src/test/ui/const-generics/defaults/default-annotation.rs
Normal file
20
src/test/ui/const-generics/defaults/default-annotation.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
// run-pass
|
||||
#![feature(staged_api)]
|
||||
|
||||
#![feature(const_generics)]
|
||||
#![feature(const_generics_defaults)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
#![stable(feature = "const_default_test", since="none")]
|
||||
|
||||
|
||||
#[unstable(feature = "const_default_stable", issue="none")]
|
||||
pub struct ConstDefaultUnstable<const N: usize = 3>;
|
||||
|
||||
#[stable(feature = "const_default_unstable", since="none")]
|
||||
pub struct ConstDefaultStable<const N: usize = {
|
||||
#[stable(feature = "const_default_unstable_val", since="none")]
|
||||
3
|
||||
}>;
|
||||
|
||||
fn main() {}
|
27
src/test/ui/const-generics/defaults/external.rs
Normal file
27
src/test/ui/const-generics/defaults/external.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
// aux-build:const_defaulty.rs
|
||||
// check-pass
|
||||
#![feature(const_generics_defaults)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
extern crate const_defaulty;
|
||||
use const_defaulty::Defaulted;
|
||||
|
||||
struct Local<const N: usize=4>;
|
||||
impl Local {
|
||||
fn new() -> Self {
|
||||
Local
|
||||
}
|
||||
}
|
||||
impl<const N: usize>Local<N> {
|
||||
fn value(&self) -> usize {
|
||||
N
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let v = Defaulted::new();
|
||||
assert_eq!(v.value(), 3);
|
||||
|
||||
let l = Local::new();
|
||||
assert_eq!(l.value(), 4);
|
||||
}
|
23
src/test/ui/const-generics/defaults/mismatch.rs
Normal file
23
src/test/ui/const-generics/defaults/mismatch.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
#![feature(const_generics)]
|
||||
#![feature(const_generics_defaults)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
pub struct Example<const N: usize=13>;
|
||||
pub struct Example2<T=u32, const N: usize=13>(T);
|
||||
pub struct Example3<const N: usize=13, T=u32>(T);
|
||||
pub struct Example4<const N: usize=13, const M: usize=4>;
|
||||
|
||||
fn main() {
|
||||
let e: Example::<13> = ();
|
||||
//~^ Error: mismatched types
|
||||
let e: Example2::<u32, 13> = ();
|
||||
//~^ Error: mismatched types
|
||||
let e: Example3::<13, u32> = ();
|
||||
//~^ Error: mismatched types
|
||||
let e: Example3::<7> = ();
|
||||
//~^ Error: mismatched types
|
||||
// FIXME(const_generics_defaults): There should be a note for the error below, but it is
|
||||
// missing.
|
||||
let e: Example4::<7> = ();
|
||||
//~^ Error: mismatched types
|
||||
}
|
52
src/test/ui/const-generics/defaults/mismatch.stderr
Normal file
52
src/test/ui/const-generics/defaults/mismatch.stderr
Normal file
|
@ -0,0 +1,52 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/mismatch.rs:11:26
|
||||
|
|
||||
LL | let e: Example::<13> = ();
|
||||
| ------------- ^^ expected struct `Example`, found `()`
|
||||
| |
|
||||
| expected due to this
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/mismatch.rs:13:32
|
||||
|
|
||||
LL | let e: Example2::<u32, 13> = ();
|
||||
| ------------------- ^^ expected struct `Example2`, found `()`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected struct `Example2`
|
||||
found unit type `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/mismatch.rs:15:32
|
||||
|
|
||||
LL | let e: Example3::<13, u32> = ();
|
||||
| ------------------- ^^ expected struct `Example3`, found `()`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected struct `Example3`
|
||||
found unit type `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/mismatch.rs:17:26
|
||||
|
|
||||
LL | let e: Example3::<7> = ();
|
||||
| ------------- ^^ expected struct `Example3`, found `()`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected struct `Example3<7_usize>`
|
||||
found unit type `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/mismatch.rs:21:26
|
||||
|
|
||||
LL | let e: Example4::<7> = ();
|
||||
| ------------- ^^ expected struct `Example4`, found `()`
|
||||
| |
|
||||
| expected due to this
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
13
src/test/ui/const-generics/defaults/pretty-printing-ast.rs
Normal file
13
src/test/ui/const-generics/defaults/pretty-printing-ast.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Test the AST pretty printer correctly handles default values for const generics
|
||||
// check-pass
|
||||
// compile-flags: -Z unpretty=expanded
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(const_generics_defaults)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait Foo<const KIND: bool = true> {}
|
||||
|
||||
fn foo<const SIZE: usize = 5>() {}
|
||||
|
||||
struct Range<const FROM: usize = 0, const LEN: usize = 0, const TO: usize = {FROM + LEN}>;
|
|
@ -0,0 +1,20 @@
|
|||
#![feature(prelude_import)]
|
||||
#![no_std]
|
||||
// Test the AST pretty printer correctly handles default values for const generics
|
||||
// check-pass
|
||||
// compile-flags: -Z unpretty=expanded
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(const_generics_defaults)]
|
||||
#![allow(incomplete_features)]
|
||||
#[prelude_import]
|
||||
use ::std::prelude::rust_2015::*;
|
||||
#[macro_use]
|
||||
extern crate std;
|
||||
|
||||
trait Foo<const KIND : bool = true> { }
|
||||
|
||||
fn foo<const SIZE : usize = 5>() { }
|
||||
|
||||
struct Range<const FROM : usize = 0, const LEN : usize = 0, const TO : usize =
|
||||
{ FROM + LEN }>;
|
|
@ -1,4 +1,4 @@
|
|||
error: type parameters with a default must be trailing
|
||||
error: generic parameters with a default must be trailing
|
||||
--> $DIR/wrong-order.rs:4:10
|
||||
|
|
||||
LL | struct A<T = u32, const N: usize> {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: type parameters with a default must be trailing
|
||||
error: generic parameters with a default must be trailing
|
||||
--> $DIR/wrong-order.rs:4:10
|
||||
|
|
||||
LL | struct A<T = u32, const N: usize> {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
|
||||
|
||||
struct A<T = u32, const N: usize> {
|
||||
//~^ ERROR type parameters with a default must be trailing
|
||||
//~^ ERROR generic parameters with a default must be trailing
|
||||
arg: T,
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
#![crate_type = "lib"]
|
||||
#![feature(const_generics)]
|
||||
#![feature(const_generics_defaults)]
|
||||
#![allow(incomplete_features, dead_code)]
|
||||
|
||||
struct Both<const N: usize=3, T> {
|
||||
//~^ ERROR: generic parameters with a default must be
|
||||
v: T
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
error: generic parameters with a default must be trailing
|
||||
--> $DIR/const_default_first.rs:6:19
|
||||
|
|
||||
LL | struct Both<const N: usize=3, T> {
|
||||
| ^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
fn foo<const SIZE: usize = 5>() {}
|
||||
//~^ ERROR default values for const generic parameters are experimental
|
||||
#![crate_type = "lib"]
|
||||
#![feature(const_generics_defaults)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
fn main() {}
|
||||
fn foo<const SIZE: usize = 5usize>() {}
|
||||
//~^ ERROR defaults for const parameters are
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
error[E0658]: default values for const generic parameters are experimental
|
||||
--> $DIR/default_function_param.rs:1:26
|
||||
error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
|
||||
--> $DIR/default_function_param.rs:5:14
|
||||
|
|
||||
LL | fn foo<const SIZE: usize = 5>() {}
|
||||
| ^^^
|
||||
|
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
= help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable
|
||||
LL | fn foo<const SIZE: usize = 5usize>() {}
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// run-pass
|
||||
#![feature(const_generics)]
|
||||
#![feature(const_generics_defaults)]
|
||||
#![allow(incomplete_features, dead_code)]
|
||||
|
||||
struct Both<T=u32, const N: usize=3> {
|
||||
arr: [T; N]
|
||||
}
|
||||
|
||||
trait BothTrait<T=u32, const N: usize=3> {}
|
||||
|
||||
enum BothEnum<T=u32, const N: usize=3> {
|
||||
Dummy([T; N])
|
||||
}
|
||||
|
||||
struct OppOrder<const N: usize=3, T=u32> {
|
||||
arr: [T; N]
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = OppOrder::<3, u32> {
|
||||
arr: [0,0,0],
|
||||
};
|
||||
let _ = Both::<u8, 1> {
|
||||
arr: [0],
|
||||
};
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
error: type parameters with a default must be trailing
|
||||
error: generic parameters with a default must be trailing
|
||||
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:12
|
||||
|
|
||||
LL | struct Bar<T = [u8; N], const N: usize>(T);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: type parameters with a default must be trailing
|
||||
error: generic parameters with a default must be trailing
|
||||
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:12
|
||||
|
|
||||
LL | struct Bar<T = [u8; N], const N: usize>(T);
|
||||
|
|
|
@ -10,6 +10,6 @@ struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
|
|||
// FIXME(const_generics_defaults): We still don't know how to deal with type defaults.
|
||||
struct Bar<T = [u8; N], const N: usize>(T);
|
||||
//~^ ERROR constant values inside of type parameter defaults
|
||||
//~| ERROR type parameters with a default
|
||||
//~| ERROR generic parameters with a default
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error[E0128]: type parameters with a default cannot use forward declared identifiers
|
||||
error[E0128]: generic parameters with a default cannot use forward declared identifiers
|
||||
--> $DIR/E0128.rs:1:14
|
||||
|
|
||||
LL | struct Foo<T=U, U=()> {
|
||||
| ^ defaulted type parameters cannot be forward declared
|
||||
| ^ defaulted generic parameters cannot be forward declared
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions.
|
||||
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
|
||||
--> $DIR/feature-gate-default_type_parameter_fallback.rs:3:8
|
||||
|
|
||||
LL | fn avg<T=i32>(_: T) {}
|
||||
|
@ -8,7 +8,7 @@ LL | fn avg<T=i32>(_: T) {}
|
|||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
|
||||
|
||||
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions.
|
||||
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
|
||||
--> $DIR/feature-gate-default_type_parameter_fallback.rs:8:6
|
||||
|
|
||||
LL | impl<T=i32> S<T> {}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
struct Heap;
|
||||
|
||||
struct Vec<A = Heap, T>(A, T);
|
||||
//~^ ERROR type parameters with a default must be trailing
|
||||
//~^ ERROR generic parameters with a default must be trailing
|
||||
|
||||
struct Foo<A, B = Vec<C>, C>(A, B, C);
|
||||
//~^ ERROR type parameters with a default must be trailing
|
||||
//~| ERROR type parameters with a default cannot use forward declared identifiers
|
||||
//~^ ERROR generic parameters with a default must be trailing
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,21 +1,14 @@
|
|||
error: type parameters with a default must be trailing
|
||||
error: generic parameters with a default must be trailing
|
||||
--> $DIR/generic-non-trailing-defaults.rs:3:12
|
||||
|
|
||||
LL | struct Vec<A = Heap, T>(A, T);
|
||||
| ^
|
||||
|
||||
error: type parameters with a default must be trailing
|
||||
error: generic parameters with a default must be trailing
|
||||
--> $DIR/generic-non-trailing-defaults.rs:6:15
|
||||
|
|
||||
LL | struct Foo<A, B = Vec<C>, C>(A, B, C);
|
||||
| ^
|
||||
|
||||
error[E0128]: type parameters with a default cannot use forward declared identifiers
|
||||
--> $DIR/generic-non-trailing-defaults.rs:6:23
|
||||
|
|
||||
LL | struct Foo<A, B = Vec<C>, C>(A, B, C);
|
||||
| ^ defaulted type parameters cannot be forward declared
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0128`.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Ensure that we get an error and not an ICE for this problematic case.
|
||||
struct Foo<T = Option<U>, U = bool>(T, U);
|
||||
//~^ ERROR type parameters with a default cannot use forward declared identifiers
|
||||
//~^ ERROR generic parameters with a default cannot use forward declared identifiers
|
||||
fn main() {
|
||||
let x: Foo;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error[E0128]: type parameters with a default cannot use forward declared identifiers
|
||||
error[E0128]: generic parameters with a default cannot use forward declared identifiers
|
||||
--> $DIR/generic-type-params-forward-mention.rs:2:23
|
||||
|
|
||||
LL | struct Foo<T = Option<U>, U = bool>(T, U);
|
||||
| ^ defaulted type parameters cannot be forward declared
|
||||
| ^ defaulted generic parameters cannot be forward declared
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error[E0128]: type parameters with a default cannot use forward declared identifiers
|
||||
error[E0128]: generic parameters with a default cannot use forward declared identifiers
|
||||
--> $DIR/issue-18183.rs:1:20
|
||||
|
|
||||
LL | pub struct Foo<Bar=Bar>(Bar);
|
||||
| ^^^ defaulted type parameters cannot be forward declared
|
||||
| ^^^ defaulted generic parameters cannot be forward declared
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#![feature(default_type_parameter_fallback)]
|
||||
|
||||
fn avg<T=T::Item>(_: T) {}
|
||||
//~^ ERROR type parameters with a default cannot use forward declared identifiers
|
||||
//~^ ERROR generic parameters with a default cannot use forward declared identifiers
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error[E0128]: type parameters with a default cannot use forward declared identifiers
|
||||
error[E0128]: generic parameters with a default cannot use forward declared identifiers
|
||||
--> $DIR/issue-26812.rs:3:10
|
||||
|
|
||||
LL | fn avg<T=T::Item>(_: T) {}
|
||||
| ^^^^^^^ defaulted type parameters cannot be forward declared
|
||||
| ^^^^^^^ defaulted generic parameters cannot be forward declared
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -408,6 +408,10 @@ pub fn eq_use_tree(l: &UseTree, r: &UseTree) -> bool {
|
|||
eq_path(&l.prefix, &r.prefix) && eq_use_tree_kind(&l.kind, &r.kind)
|
||||
}
|
||||
|
||||
pub fn eq_anon_const(l: &AnonConst, r: &AnonConst) -> bool {
|
||||
eq_expr(&l.value, &r.value)
|
||||
}
|
||||
|
||||
pub fn eq_use_tree_kind(l: &UseTreeKind, r: &UseTreeKind) -> bool {
|
||||
use UseTreeKind::*;
|
||||
match (l, r) {
|
||||
|
@ -418,10 +422,6 @@ pub fn eq_use_tree_kind(l: &UseTreeKind, r: &UseTreeKind) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn eq_anon_const(l: &AnonConst, r: &AnonConst) -> bool {
|
||||
eq_expr(&l.value, &r.value)
|
||||
}
|
||||
|
||||
pub fn eq_defaultness(l: Defaultness, r: Defaultness) -> bool {
|
||||
matches!(
|
||||
(l, r),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue