Add has_default to GenericParamDefKind::Const

This currently creates a field which is always false on GenericParamDefKind for future use when
consts are permitted to have defaults

Update const_generics:default locations

Previously just ignored them, now actually do something about them.

Fix using type check instead of value

Add parsing

This adds all the necessary changes to lower const-generics defaults from parsing.

Change P<Expr> to AnonConst

This matches the arguments passed to instantiations of const generics, and makes it specific to
just anonymous constants.

Attempt to fix lowering bugs
This commit is contained in:
kadmin 2020-08-11 00:02:45 +00:00
parent 79e5814f45
commit e4e5db4e42
39 changed files with 158 additions and 77 deletions

View File

@ -385,6 +385,7 @@ 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>,
},

View File

@ -785,8 +785,8 @@ pub fn noop_flat_map_generic_param<T: MutVisitor>(
visit_opt(default, |default| vis.visit_ty(default));
}
GenericParamKind::Const { ty, kw_span: _, default } => {
vis.visit_ty(ty);
visit_opt(default, |default| vis.visit_anon_const(default));
vis.visit_ty(ty);
}
}
smallvec![param]

View File

@ -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 })
}
};

View File

@ -1174,6 +1174,17 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
}
}
if !self.session.features_untracked().const_generics_defaults {
if let GenericParamKind::Const { default: Some(ref default), .. } = param.kind {
let mut err = self.err_handler().struct_span_err(
default.value.span,
"default values for const generic parameters are unstable",
);
err.note("to enable them use #![feature(const_generic_defaults)]");
err.emit();
break;
}
}
}
validate_generic_param_order(

View File

@ -2661,6 +2661,9 @@ impl<'a> State<'a> {
s.print_type_bounds(":", &param.bounds);
if let Some(ref _default) = default {
// FIXME(const_generics_defaults): print the `default` value here
s.s.space();
s.word_space("=");
// s.print_anon_const(&default);
}
}
}

View File

@ -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)
}
}
}

View File

@ -963,10 +963,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
.rev()
.filter_map(|param| match param.kind {
ty::GenericParamDefKind::Lifetime => None,
ty::GenericParamDefKind::Type { has_default, .. } => {
ty::GenericParamDefKind::Type { has_default, .. }
| ty::GenericParamDefKind::Const { has_default } => {
Some((param.def_id, has_default))
}
ty::GenericParamDefKind::Const => None, // FIXME(const_generics_defaults)
})
.peekable();
let has_default = {

View File

@ -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()
}
}

View File

@ -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,
}
}
@ -118,12 +120,10 @@ impl<'tcx> Generics {
for param in &self.params {
match param.kind {
GenericParamDefKind::Lifetime => (),
GenericParamDefKind::Type { has_default, .. } => {
GenericParamDefKind::Type { has_default, .. } |
GenericParamDefKind::Const { has_default } => {
own_defaults.types += has_default as usize;
}
GenericParamDefKind::Const => {
// FIXME(const_generics:defaults)
}
}
}
@ -146,7 +146,7 @@ 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 +189,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"),
}
}

View File

@ -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.

View File

@ -193,17 +193,22 @@ 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(crate::ty::Const::from_anon_const(
self.tcx(),
param.def_id.expect_local(),
))
}
})
.count();

View File

@ -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]
}
});

View File

@ -928,8 +928,13 @@ 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 {
// how should the error case be handled here?
// let default_const = self.ev.tcx.const_eval_poly(param.def_id).unwrap();
// self.visit(default_const);
}
}
}
}
@ -1741,7 +1746,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> {
self.visit(self.tcx.type_of(param.def_id));
}
}
GenericParamDefKind::Const => {
GenericParamDefKind::Const { .. } => {
self.visit(self.tcx.type_of(param.def_id));
}
}

View File

@ -616,6 +616,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
self.visit_ty(ty);
self.ribs[TypeNS].pop().unwrap();
self.ribs[ValueNS].pop().unwrap();
// FIXME(const_generics:default) do something with default here?
}
}
}

View File

@ -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()
})

View File

@ -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() {

View File

@ -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,

View File

@ -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,

View File

@ -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]
}
})

View File

@ -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,

View File

@ -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),

View File

@ -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, &param.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()

View File

@ -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,16 +504,34 @@ 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 {
if !infer_args && has_default {
let c = ty::Const::from_anon_const(tcx, param.def_id.expect_local());
ty::subst::GenericArg::from(c)
} else 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()
}
/*
if !infer_args && has_default {
/*
if default_needs_object_self(param) {
missing_type_params.push(param.name.to_string());
tcx.const_error(ty).into()
} else {
}
*/
} else if infer_args {
// No const parameters were provided, we can infer all.
self.astconv.ct_infer(ty, Some(param), self.span).into()
} else {
// We've already errored above about the mismatch.
tcx.const_error(ty).into()
}
*/
}
}
}

View File

@ -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)

View File

@ -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,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.fcx.var_for_def(self.span, param)
}
}
GenericParamDefKind::Const => {
// FIXME(const_generics_defaults)
GenericParamDefKind::Const { has_default, .. } => {
if infer_args || !has_default {
return self.fcx.var_for_def(self.span, param);
}
// FIXME(const_generics:defaults)
// No const parameters were provided, we have to infer them.
self.fcx.var_for_def(self.span, param)
todo!()
}
}
}

View File

@ -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!(),

View File

@ -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();

View File

@ -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)
}
}

View File

@ -758,7 +758,7 @@ fn check_where_clauses<'tcx, 'fcx>(
fcx.tcx.mk_param_from_def(param)
}
GenericParamDefKind::Type { .. } => {
GenericParamDefKind::Const { .. } | GenericParamDefKind::Type { .. } => {
// If the param has a default, ...
if is_our_default(param) {
let default_ty = fcx.tcx.type_of(param.def_id);
@ -771,11 +771,6 @@ 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)
}
}
});

View File

@ -1549,13 +1549,13 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
i += 1;
Some(param_def)
}
GenericParamKind::Const { .. } => {
GenericParamKind::Const { default, .. } => {
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)

View File

@ -83,7 +83,8 @@ 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 +122,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 +212,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)
}

View File

@ -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(

View File

@ -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;
}
}

View File

@ -0,0 +1,15 @@
// check-pass
#![feature(const_generics)]
#![feature(const_generic_defaults)]
#![allow(incomplete_features)]
#[derive(Default)]
pub struct ConstDefault<const N: usize = 3> {
items: [u32; N]
}
pub fn main() {
let s = ConstDefault::default();
}

View File

@ -1,3 +1,6 @@
#![feature(const_generic_defaults)]
#![feature(min_const_generics)]
fn foo<const SIZE: usize = 5>() {}
//~^ ERROR default values for const generic parameters are experimental

View File

@ -1,4 +1,2 @@
trait Foo<const KIND: bool = true> {}
//~^ ERROR default values for const generic parameters are experimental
fn main() {}

View File

@ -0,0 +1,5 @@
#![feature(min_const_generics)]
#![crate_type="lib"]
struct A<const N: usize = 3>;
//~^ ERROR default values for

View File

@ -0,0 +1,10 @@
error: default values for const generic parameters are unstable
--> $DIR/feature-gate-const_generic_defaults.rs:4:27
|
LL | struct A<const N: usize = 3>;
| ^
|
= note: to enable them use #![feature(const_generic_defaults)]
error: aborting due to previous error

View File

@ -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),