diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8a051066c7d21..5385c4d72e4ba 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -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 }) } }; diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 563bcda519065..96bb9cfb1a6bb 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -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", diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index cb6f567c55140..84f8ce5706ae6 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -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); } } } diff --git a/compiler/rustc_error_codes/src/error_codes/E0128.md b/compiler/rustc_error_codes/src/error_codes/E0128.md index 6f8dfe3a73b9e..2ea8ae68ef877 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0128.md +++ b/compiler/rustc_error_codes/src/error_codes/E0128.md @@ -7,7 +7,7 @@ struct Foo { 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 ``` diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 701e4a6329394..9b908b141af14 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -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); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 76e5d30dc5ee2..7eeda6013ed75 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -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) } } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index eeff48a63950e..c171b11e3ffa7 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -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)) - } - 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; + + 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; + } } - if self.tcx.type_of(def_id).subst(self.tcx, substs) != actual { - break; + GenericArgKind::Type(ty) => { + if self.tcx.type_of(def_id).subst(self.tcx, substs) != ty { + break; + } } - num_supplied_defaults += 1; + _ => break, } + num_supplied_defaults += 1; } let len = generics.params.len(); let mut generics = generics.clone(); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index e8891e471f9da..3d0a9d553b028 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -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)] { // FIXME: For a proc macro crate, not sure whether we should return the "host" diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 0f860d11dc21a..e10041a297142 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -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) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index ff8ec1d551323..d055c275299a6 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -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)) + } } } } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 610528956d0a1..7cfb051e703c5 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -307,13 +307,14 @@ define_tables! { mir_for_ctfe: Table)>, promoted_mir: Table>)>, mir_abstract_consts: Table])>, + const_defaults: Table>>, unused_generic_params: Table>>, // `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>, - def_path_hashes: Table> + def_path_hashes: Table>, } #[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)] diff --git a/compiler/rustc_middle/src/hir/map/collector.rs b/compiler/rustc_middle/src/hir/map/collector.rs index a3d891fd1ba5e..4602ed695fe68 100644 --- a/compiler/rustc_middle/src/hir/map/collector.rs +++ b/compiler/rustc_middle/src/hir/map/collector.rs @@ -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); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 53a7d8528d36e..36162cfe92452 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -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` 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) } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 779d6c90f973f..c78151271c171 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -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) +} diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 41a8bc10c8de2..56c38baa2df81 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -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() } } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 79cd26f5668a1..d30a8693959f3 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -18,7 +18,9 @@ pub enum GenericParamDefKind { object_lifetime_default: ObjectLifetimeDefault, synthetic: Option, }, - 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"), } } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 23cedfd499eaa..f61b6946985e5 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -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. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index e6b4739d0a2f5..ed10a1566223e 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -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 }; } diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 77f1668893782..a47846828bd60 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -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(); diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index e48640e1bb965..c5c701082e66c 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -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] } }); diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index dd9cb51c858b4..8a6ac843534c6 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -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, }; diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index de264b5bb0403..e092bb845ffac 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -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)); } } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 7493fd68505fe..d402fa4f8494f 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -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 } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index af241ef8afccf..f9f33492a1ec3 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -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; } diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 2c61c0963ae28..744945c5b0ffb 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -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() }) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index d8f201fd0d8fa..14e3d8498b0d8 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -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 }, @@ -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()]>` - 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()]>` - 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; } diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index 53150a9266434..c3bc1c191ff09 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -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() { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 42e01f1b8d1fe..116519855d776 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -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, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index e6a1cf58fe373..cecdcc9789609 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -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, diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 5a8c53a0c4bd4..f26eb159105d7 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -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] } }) diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs index 75822eadb2ab3..209fd83b3ab34 100644 --- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs @@ -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, diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 916186f4204e2..5c0cb2fb83578 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -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), diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 0ea0ccaceabd4..9625211109d10 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -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( diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 7c5398003f3e6..8076aa7102c6c 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -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() + } } } } diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index a30a81079335d..ddb11b9f3b16b 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -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) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index dc8a804bfea98..56ff9293dd87f 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -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) + } } } } diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs index 4a2dd6faf0c32..731a72ff024dc 100644 --- a/compiler/rustc_typeck/src/check/method/confirm.rs +++ b/compiler/rustc_typeck/src/check/method/confirm.rs @@ -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!(), diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index 9a3d1e42b732a..d6fa6bf0067f9 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -308,7 +308,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Construct a trait-reference `self_ty : Trait` 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(); diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 3006cabc632fd..0742549f8904e 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -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) } } diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 00c6550835b43..5f302f7d0a94e 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -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) + } } } }); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 162fccc602036..cb0eea1b7067c 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -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) diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 3f2f244e44fd2..a05cc36fd4c1c 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -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), diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs index 7713381e62e46..1240946860573 100644 --- a/compiler/rustc_typeck/src/impl_wf_check.rs +++ b/compiler/rustc_typeck/src/impl_wf_check.rs @@ -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( diff --git a/compiler/rustc_typeck/src/variance/solve.rs b/compiler/rustc_typeck/src/variance/solve.rs index 2d3369cba7a1e..1a4d88ced0e45 100644 --- a/compiler/rustc_typeck/src/variance/solve.rs +++ b/compiler/rustc_typeck/src/variance/solve.rs @@ -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; } } diff --git a/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs b/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs new file mode 100644 index 0000000000000..769b6e952dc9c --- /dev/null +++ b/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs @@ -0,0 +1,15 @@ +#![feature(const_generics)] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + +pub struct Defaulted; +impl Defaulted { + pub fn new() -> Self { + Defaulted + } +} +impl Defaulted { + pub fn value(&self) -> usize { + N + } +} diff --git a/src/test/ui/const-generics/defaults/const-default.rs b/src/test/ui/const-generics/defaults/const-default.rs new file mode 100644 index 0000000000000..150c70770ae51 --- /dev/null +++ b/src/test/ui/const-generics/defaults/const-default.rs @@ -0,0 +1,30 @@ +// run-pass + +#![feature(const_generics)] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + + +pub struct ConstDefault; + +impl ConstDefault { + 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(); +} diff --git a/src/test/ui/const-generics/defaults/default-annotation.rs b/src/test/ui/const-generics/defaults/default-annotation.rs new file mode 100644 index 0000000000000..e6e8d732beef3 --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-annotation.rs @@ -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; + +#[stable(feature = "const_default_unstable", since="none")] +pub struct ConstDefaultStable; + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/external.rs b/src/test/ui/const-generics/defaults/external.rs new file mode 100644 index 0000000000000..b39e69ab10b66 --- /dev/null +++ b/src/test/ui/const-generics/defaults/external.rs @@ -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; +impl Local { + fn new() -> Self { + Local + } +} +implLocal { + 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); +} diff --git a/src/test/ui/const-generics/defaults/mismatch.rs b/src/test/ui/const-generics/defaults/mismatch.rs new file mode 100644 index 0000000000000..bf578468bb617 --- /dev/null +++ b/src/test/ui/const-generics/defaults/mismatch.rs @@ -0,0 +1,23 @@ +#![feature(const_generics)] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + +pub struct Example; +pub struct Example2(T); +pub struct Example3(T); +pub struct Example4; + +fn main() { + let e: Example::<13> = (); + //~^ Error: mismatched types + let e: Example2:: = (); + //~^ 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 +} diff --git a/src/test/ui/const-generics/defaults/mismatch.stderr b/src/test/ui/const-generics/defaults/mismatch.stderr new file mode 100644 index 0000000000000..c66eb4cd64594 --- /dev/null +++ b/src/test/ui/const-generics/defaults/mismatch.stderr @@ -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:: = (); + | ------------------- ^^ 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`. diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.rs b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs new file mode 100644 index 0000000000000..a25d4baca1a97 --- /dev/null +++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs @@ -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 {} + +fn foo() {} + +struct Range; diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout new file mode 100644 index 0000000000000..f7a1d2ca4b2ef --- /dev/null +++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout @@ -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 { } + +fn foo() { } + +struct Range; diff --git a/src/test/ui/const-generics/defaults/wrong-order.full.stderr b/src/test/ui/const-generics/defaults/wrong-order.full.stderr index 96deb4a8b5abb..accc73134d899 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.full.stderr +++ b/src/test/ui/const-generics/defaults/wrong-order.full.stderr @@ -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 { diff --git a/src/test/ui/const-generics/defaults/wrong-order.min.stderr b/src/test/ui/const-generics/defaults/wrong-order.min.stderr index b19da76f415d7..c8f1d471b244b 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.min.stderr +++ b/src/test/ui/const-generics/defaults/wrong-order.min.stderr @@ -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 { diff --git a/src/test/ui/const-generics/defaults/wrong-order.rs b/src/test/ui/const-generics/defaults/wrong-order.rs index 4f1c05011b0bf..5c2d9b8ad4751 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.rs +++ b/src/test/ui/const-generics/defaults/wrong-order.rs @@ -2,7 +2,7 @@ #![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete struct A { - //~^ ERROR type parameters with a default must be trailing + //~^ ERROR generic parameters with a default must be trailing arg: T, } diff --git a/src/test/ui/const-generics/min_const_generics/const_default_first.rs b/src/test/ui/const-generics/min_const_generics/const_default_first.rs new file mode 100644 index 0000000000000..ae82c85eb7e4b --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/const_default_first.rs @@ -0,0 +1,9 @@ +#![crate_type = "lib"] +#![feature(const_generics)] +#![feature(const_generics_defaults)] +#![allow(incomplete_features, dead_code)] + +struct Both { +//~^ ERROR: generic parameters with a default must be + v: T +} diff --git a/src/test/ui/const-generics/min_const_generics/const_default_first.stderr b/src/test/ui/const-generics/min_const_generics/const_default_first.stderr new file mode 100644 index 0000000000000..f7a2e484fc61b --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/const_default_first.stderr @@ -0,0 +1,8 @@ +error: generic parameters with a default must be trailing + --> $DIR/const_default_first.rs:6:19 + | +LL | struct Both { + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/min_const_generics/default_function_param.rs b/src/test/ui/const-generics/min_const_generics/default_function_param.rs index 5b0a42a45565c..ebdb5a65bc351 100644 --- a/src/test/ui/const-generics/min_const_generics/default_function_param.rs +++ b/src/test/ui/const-generics/min_const_generics/default_function_param.rs @@ -1,4 +1,6 @@ -fn foo() {} -//~^ ERROR default values for const generic parameters are experimental +#![crate_type = "lib"] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] -fn main() {} +fn foo() {} +//~^ ERROR defaults for const parameters are diff --git a/src/test/ui/const-generics/min_const_generics/default_function_param.stderr b/src/test/ui/const-generics/min_const_generics/default_function_param.stderr index 31b5ad5123ed2..243ac0db5f55f 100644 --- a/src/test/ui/const-generics/min_const_generics/default_function_param.stderr +++ b/src/test/ui/const-generics/min_const_generics/default_function_param.stderr @@ -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() {} - | ^^^ - | - = note: see issue #44580 for more information - = help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable +LL | fn foo() {} + | ^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/const-generics/min_const_generics/type_and_const_defaults.rs b/src/test/ui/const-generics/min_const_generics/type_and_const_defaults.rs new file mode 100644 index 0000000000000..435a63a528345 --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/type_and_const_defaults.rs @@ -0,0 +1,27 @@ +// run-pass +#![feature(const_generics)] +#![feature(const_generics_defaults)] +#![allow(incomplete_features, dead_code)] + +struct Both { + arr: [T; N] +} + +trait BothTrait {} + +enum BothEnum { + Dummy([T; N]) +} + +struct OppOrder { + arr: [T; N] +} + +fn main() { + let _ = OppOrder::<3, u32> { + arr: [0,0,0], + }; + let _ = Both:: { + arr: [0], + }; +} diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr index debb272da3608..c2b7b206653a6 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr @@ -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); diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr index 171efca193831..4a462c328bf64 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr @@ -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); diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs index a85e2a2f2c4f1..c7be8bdaf9c3d 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs @@ -10,6 +10,6 @@ struct Foo()]>(T, U); // FIXME(const_generics_defaults): We still don't know how to deal with type defaults. struct Bar(T); //~^ ERROR constant values inside of type parameter defaults -//~| ERROR type parameters with a default +//~| ERROR generic parameters with a default fn main() {} diff --git a/src/test/ui/error-codes/E0128.stderr b/src/test/ui/error-codes/E0128.stderr index 253aa166bd371..eb66d46936a85 100644 --- a/src/test/ui/error-codes/E0128.stderr +++ b/src/test/ui/error-codes/E0128.stderr @@ -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 { - | ^ defaulted type parameters cannot be forward declared + | ^ defaulted generic parameters cannot be forward declared error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr b/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr index f13803b80f308..5cd38ebab370e 100644 --- a/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr +++ b/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr @@ -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) {} @@ -8,7 +8,7 @@ LL | fn avg(_: 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 -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 S {} diff --git a/src/test/ui/generics/generic-non-trailing-defaults.rs b/src/test/ui/generics/generic-non-trailing-defaults.rs index 8d9883dc7a939..cb2bb2832b70e 100644 --- a/src/test/ui/generics/generic-non-trailing-defaults.rs +++ b/src/test/ui/generics/generic-non-trailing-defaults.rs @@ -1,10 +1,9 @@ struct Heap; struct Vec(A, T); -//~^ ERROR type parameters with a default must be trailing +//~^ ERROR generic parameters with a default must be trailing struct Foo, 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() {} diff --git a/src/test/ui/generics/generic-non-trailing-defaults.stderr b/src/test/ui/generics/generic-non-trailing-defaults.stderr index fb359f673a95e..6d76861750335 100644 --- a/src/test/ui/generics/generic-non-trailing-defaults.stderr +++ b/src/test/ui/generics/generic-non-trailing-defaults.stderr @@ -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, 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, 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, C>(A, B, C); - | ^ defaulted type parameters cannot be forward declared - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0128`. diff --git a/src/test/ui/generics/generic-type-params-forward-mention.rs b/src/test/ui/generics/generic-type-params-forward-mention.rs index ac0cab20d78a2..000c47095d27c 100644 --- a/src/test/ui/generics/generic-type-params-forward-mention.rs +++ b/src/test/ui/generics/generic-type-params-forward-mention.rs @@ -1,6 +1,6 @@ // Ensure that we get an error and not an ICE for this problematic case. struct Foo, 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; } diff --git a/src/test/ui/generics/generic-type-params-forward-mention.stderr b/src/test/ui/generics/generic-type-params-forward-mention.stderr index 97389c337fcbe..fa661c274ebca 100644 --- a/src/test/ui/generics/generic-type-params-forward-mention.stderr +++ b/src/test/ui/generics/generic-type-params-forward-mention.stderr @@ -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, U = bool>(T, U); - | ^ defaulted type parameters cannot be forward declared + | ^ defaulted generic parameters cannot be forward declared error: aborting due to previous error diff --git a/src/test/ui/issues/issue-18183.stderr b/src/test/ui/issues/issue-18183.stderr index c8f8ac9296dc0..a7dc64708d856 100644 --- a/src/test/ui/issues/issue-18183.stderr +++ b/src/test/ui/issues/issue-18183.stderr @@ -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); - | ^^^ defaulted type parameters cannot be forward declared + | ^^^ defaulted generic parameters cannot be forward declared error: aborting due to previous error diff --git a/src/test/ui/issues/issue-26812.rs b/src/test/ui/issues/issue-26812.rs index b2494a91a3f8a..3391ea4b350af 100644 --- a/src/test/ui/issues/issue-26812.rs +++ b/src/test/ui/issues/issue-26812.rs @@ -1,6 +1,6 @@ #![feature(default_type_parameter_fallback)] fn avg(_: 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() {} diff --git a/src/test/ui/issues/issue-26812.stderr b/src/test/ui/issues/issue-26812.stderr index 8d507a7ea0144..fd1bbb9c5673d 100644 --- a/src/test/ui/issues/issue-26812.stderr +++ b/src/test/ui/issues/issue-26812.stderr @@ -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) {} - | ^^^^^^^ defaulted type parameters cannot be forward declared + | ^^^^^^^ defaulted generic parameters cannot be forward declared error: aborting due to previous error diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index ea9a910d1b920..e202b5061a678 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -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),