From 725ba9625eca99537cb0caf2998b363e784dd654 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 15 Feb 2019 22:20:46 +0000 Subject: [PATCH 01/13] Add Const kind to HIR Co-Authored-By: Gabriel Smith --- src/librustc/hir/mod.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index d774359fa79ec..d7d56ef659afb 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -389,10 +389,17 @@ impl PathSegment { } } +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +pub struct ConstArg { + pub value: AnonConst, + pub span: Span, +} + #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum GenericArg { Lifetime(Lifetime), Type(Ty), + Const(ConstArg), } impl GenericArg { @@ -400,6 +407,7 @@ impl GenericArg { match self { GenericArg::Lifetime(l) => l.span, GenericArg::Type(t) => t.span, + GenericArg::Const(c) => c.span, } } @@ -407,6 +415,7 @@ impl GenericArg { match self { GenericArg::Lifetime(l) => l.id, GenericArg::Type(t) => t.id, + GenericArg::Const(c) => c.value.id, } } } @@ -448,6 +457,7 @@ impl GenericArgs { } break; } + GenericArg::Const(_) => {} } } } @@ -464,6 +474,7 @@ impl GenericArgs { match arg { GenericArg::Lifetime(_) => own_counts.lifetimes += 1, GenericArg::Type(_) => own_counts.types += 1, + GenericArg::Const(_) => own_counts.consts += 1, }; } @@ -528,6 +539,9 @@ pub enum GenericParamKind { Type { default: Option>, synthetic: Option, + }, + Const { + ty: P, } } @@ -548,6 +562,7 @@ pub struct GenericParam { pub struct GenericParamCount { pub lifetimes: usize, pub types: usize, + pub consts: usize, } /// Represents lifetimes and type parameters attached to a declaration @@ -582,6 +597,7 @@ impl Generics { match param.kind { GenericParamKind::Lifetime { .. } => own_counts.lifetimes += 1, GenericParamKind::Type { .. } => own_counts.types += 1, + GenericParamKind::Const { .. } => own_counts.consts += 1, }; } @@ -1302,7 +1318,7 @@ impl BodyOwnerKind { /// These are usually found nested inside types (e.g., array lengths) /// or expressions (e.g., repeat counts), and also used to define /// explicit discriminant values for enum variants. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)] pub struct AnonConst { pub id: NodeId, pub hir_id: HirId, From d44030d8ec6245edabdbe23a69be21bffb51eb11 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 15 Feb 2019 22:21:57 +0000 Subject: [PATCH 02/13] Add pretty-printing for const generics Co-Authored-By: Gabriel Smith --- src/librustc/hir/print.rs | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 9b6fcf259be14..031b3a3233d6f 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1711,31 +1711,25 @@ impl<'a> State<'a> { } }; - let mut types = vec![]; - let mut elide_lifetimes = true; - for arg in &generic_args.args { - match arg { - GenericArg::Lifetime(lt) => { - if !lt.is_elided() { - elide_lifetimes = false; - } - } - GenericArg::Type(ty) => { - types.push(ty); - } + let mut nonelided_generic_args: bool = false; + let elide_lifetimes = generic_args.args.iter().all(|arg| match arg { + GenericArg::Lifetime(lt) => lt.is_elided(), + _ => { + nonelided_generic_args = true; + true } - } - if !elide_lifetimes { + }); + + if nonelided_generic_args { start_or_comma(self)?; self.commasep(Inconsistent, &generic_args.args, |s, generic_arg| { match generic_arg { - GenericArg::Lifetime(lt) => s.print_lifetime(lt), + GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt), + GenericArg::Lifetime(_) => Ok(()), GenericArg::Type(ty) => s.print_type(ty), + GenericArg::Const(ct) => s.print_anon_const(&ct.value), } })?; - } else if !types.is_empty() { - start_or_comma(self)?; - self.commasep(Inconsistent, &types, |s, ty| s.print_type(&ty))?; } // FIXME(eddyb) This would leak into error messages, e.g.: @@ -2106,7 +2100,12 @@ impl<'a> State<'a> { } pub fn print_generic_param(&mut self, param: &GenericParam) -> io::Result<()> { + if let GenericParamKind::Const { .. } = param.kind { + self.word_space("const")?; + } + self.print_ident(param.name.ident())?; + match param.kind { GenericParamKind::Lifetime { .. } => { let mut sep = ":"; @@ -2133,6 +2132,10 @@ impl<'a> State<'a> { _ => Ok(()), } } + GenericParamKind::Const { ref ty } => { + self.word_space(":")?; + self.print_type(ty) + } } } From 9a5f7b1eae10482d5d314c14db25f5abd6533bbe Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 15 Feb 2019 22:22:54 +0000 Subject: [PATCH 03/13] Move const generic error from lowering to collect Co-Authored-By: Gabriel Smith --- src/librustc/hir/lowering.rs | 25 +++++++++---------------- src/librustc_typeck/collect.rs | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 84487c40f8745..52c3eb26d6180 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -36,7 +36,7 @@ use crate::hir::HirVec; use crate::hir::map::{DefKey, DefPathData, Definitions}; use crate::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace, CRATE_DEF_INDEX}; use crate::hir::def::{Def, PathResolution, PerNS}; -use crate::hir::GenericArg; +use crate::hir::{GenericArg, ConstArg}; use crate::lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, ELIDED_LIFETIMES_IN_PATHS}; use crate::middle::cstore::CrateStore; @@ -1172,13 +1172,10 @@ impl<'a> LoweringContext<'a> { ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)), ast::GenericArg::Type(ty) => GenericArg::Type(self.lower_ty_direct(&ty, itctx)), ast::GenericArg::Const(ct) => { - // FIXME(const_generics): const generics are not yet defined in the HIR. - self.sess.struct_span_err( - ct.value.span, - "const generics in any position are currently unsupported", - ).emit(); - self.sess.abort_if_errors(); - bug!(); + GenericArg::Const(ConstArg { + value: self.lower_anon_const(&ct), + span: ct.value.span, + }) } } } @@ -2520,14 +2517,10 @@ impl<'a> LoweringContext<'a> { (hir::ParamName::Plain(ident), kind) } - GenericParamKind::Const { .. } => { - // FIXME(const_generics): const generics are not yet defined in the HIR. - self.sess.struct_span_err( - param.ident.span, - "const generics in any position are currently unsupported", - ).emit(); - self.sess.abort_if_errors(); - bug!(); + GenericParamKind::Const { ref ty } => { + (hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const { + ty: self.lower_ty(&ty, ImplTraitContext::disallowed()), + }) } }; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 4a2d526263c03..db508a5772689 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -132,6 +132,10 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> { self.tcx.type_of(def_id); } hir::GenericParamKind::Type { .. } => {} + hir::GenericParamKind::Const { .. } => { + let def_id = self.tcx.hir().local_def_id(param.id); + self.tcx.type_of(def_id); + } } } intravisit::walk_generics(self, generics); @@ -1041,6 +1045,21 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty i += 1; Some(ty_param) } + GenericParamKind::Const { .. } => { + if param.name.ident().name == keywords::SelfUpper.name() { + span_bug!( + param.span, + "`Self` should not be the name of a regular parameter", + ); + } + + tcx.sess.struct_span_err( + param.span, + "const generics in any position are currently unsupported", + ).emit(); + tcx.sess.abort_if_errors(); + bug!(); + } _ => None, }), ); From 475f20c73db54517255416b66db2edb304e85729 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 15 Feb 2019 22:24:00 +0000 Subject: [PATCH 04/13] Add Const kind to rustdoc Co-Authored-By: Gabriel Smith --- src/librustdoc/clean/auto_trait.rs | 1 + src/librustdoc/clean/mod.rs | 54 ++++++++++++++++++++++++++++-- src/librustdoc/core.rs | 13 +++++-- src/librustdoc/html/format.rs | 10 ++++++ src/librustdoc/html/render.rs | 3 +- 5 files changed, 75 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index b99181c0d4f9e..8796cfa01e0ea 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -773,6 +773,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { } } GenericParamDefKind::Lifetime => {} + GenericParamDefKind::Const { .. } => {} } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d12b5021ca9fa..b08646ec00421 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1253,6 +1253,15 @@ impl Clean for hir::GenericParam { } } +impl Clean for hir::ConstArg { + fn clean(&self, cx: &DocContext) -> Constant { + Constant { + type_: cx.tcx.type_of(cx.tcx.hir().body_owner_def_id(self.value.body)).clean(cx), + expr: print_const_expr(cx, self.value.body), + } + } +} + impl<'tcx> Clean for ty::GenericParamDef { fn clean(&self, _cx: &DocContext) -> Lifetime { Lifetime(self.name.to_string()) @@ -1418,6 +1427,10 @@ pub enum GenericParamDefKind { default: Option, synthetic: Option, }, + Const { + did: DefId, + ty: Type, + }, } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)] @@ -1430,7 +1443,10 @@ pub struct GenericParamDef { impl GenericParamDef { pub fn is_synthetic_type_param(&self) -> bool { match self.kind { - GenericParamDefKind::Lifetime => false, + GenericParamDefKind::Lifetime | + GenericParamDefKind::Const { .. } => { + false + } GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(), } } @@ -1494,6 +1510,12 @@ impl Clean for hir::GenericParam { synthetic: synthetic, }) } + hir::GenericParamKind::Const { ref ty } => { + (self.name.ident().name.clean(cx), GenericParamDefKind::Const { + did: cx.tcx.hir().local_def_id(self.id), + ty: ty.clean(cx), + }) + } }; GenericParamDef { @@ -1533,6 +1555,7 @@ impl Clean for hir::Generics { GenericParamDefKind::Type { did, ref bounds, .. } => { cx.impl_trait_bounds.borrow_mut().insert(did, bounds.clone()); } + GenericParamDefKind::Const { .. } => unreachable!(), } param }) @@ -1566,6 +1589,7 @@ impl Clean for hir::Generics { break } } + GenericParamDefKind::Const { .. } => {} } } } @@ -2544,6 +2568,7 @@ impl Clean for hir::Ty { let provided_params = &path.segments.last().expect("segments were empty"); let mut ty_substs = FxHashMap::default(); let mut lt_substs = FxHashMap::default(); + let mut const_substs = FxHashMap::default(); provided_params.with_generic_args(|generic_args| { let mut indices: GenericParamCount = Default::default(); for param in generics.params.iter() { @@ -2595,10 +2620,32 @@ impl Clean for hir::Ty { } indices.types += 1; } + hir::GenericParamKind::Const { .. } => { + let const_param_def = + Def::ConstParam(cx.tcx.hir().local_def_id(param.id)); + let mut j = 0; + let const_ = generic_args.args.iter().find_map(|arg| { + match arg { + hir::GenericArg::Const(ct) => { + if indices.consts == j { + return Some(ct); + } + j += 1; + None + } + _ => None, + } + }); + if let Some(ct) = const_.cloned() { + const_substs.insert(const_param_def, ct.clean(cx)); + } + // FIXME(const_generics:defaults) + indices.consts += 1; + } } } }); - return cx.enter_alias(ty_substs, lt_substs, || ty.clean(cx)); + return cx.enter_alias(ty_substs, lt_substs, const_substs, || ty.clean(cx)); } resolve_type(cx, path.clean(cx), self.id) } @@ -3190,6 +3237,9 @@ impl Clean for hir::GenericArgs { GenericArg::Type(ty) => { types.push(ty.clean(cx)); } + GenericArg::Const(..) => { + unimplemented!() // FIXME(const_generics) + } } } GenericArgs::AngleBracketed { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index e90127ca162d2..5df82c7cc9e9a 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -65,6 +65,8 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> { pub ty_substs: RefCell>, /// Table `NodeId` of lifetime parameter definition -> substituted lifetime pub lt_substs: RefCell>, + /// Table node id of const parameter definition -> substituted const + pub ct_substs: RefCell>, /// Table DefId of `impl Trait` in argument position -> bounds pub impl_trait_bounds: RefCell>>, pub send_trait: Option, @@ -85,14 +87,18 @@ impl<'a, 'tcx, 'rcx> DocContext<'a, 'tcx, 'rcx> { pub fn enter_alias(&self, ty_substs: FxHashMap, lt_substs: FxHashMap, + ct_substs: FxHashMap, f: F) -> R where F: FnOnce() -> R { - let (old_tys, old_lts) = - (mem::replace(&mut *self.ty_substs.borrow_mut(), ty_substs), - mem::replace(&mut *self.lt_substs.borrow_mut(), lt_substs)); + let (old_tys, old_lts, old_cts) = ( + mem::replace(&mut *self.ty_substs.borrow_mut(), ty_substs), + mem::replace(&mut *self.lt_substs.borrow_mut(), lt_substs), + mem::replace(&mut *self.ct_substs.borrow_mut(), ct_substs), + ); let r = f(); *self.ty_substs.borrow_mut() = old_tys; *self.lt_substs.borrow_mut() = old_lts; + *self.ct_substs.borrow_mut() = old_cts; r } @@ -527,6 +533,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt renderinfo: RefCell::new(renderinfo), ty_substs: Default::default(), lt_substs: Default::default(), + ct_substs: Default::default(), impl_trait_bounds: Default::default(), send_trait: send_trait, fake_def_ids: Default::default(), diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 35555f61bd150..4fbbaf0f2e183 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -138,6 +138,16 @@ impl fmt::Display for clean::GenericParamDef { Ok(()) } + clean::GenericParamDefKind::Const { ref ty, .. } => { + f.write_str("const ")?; + f.write_str(&self.name)?; + + if f.alternate() { + write!(f, ": {:#}", ty) + } else { + write!(f, ": {}", ty) + } + } } } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index e660d27d74b4c..bf0757902fe0e 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1746,7 +1746,8 @@ impl<'a> Cache { for param in &generics.params { match param.kind { clean::GenericParamDefKind::Lifetime => {} - clean::GenericParamDefKind::Type { did, .. } => { + clean::GenericParamDefKind::Type { did, .. } | + clean::GenericParamDefKind::Const { did, .. } => { self.typarams.insert(did, param.name.clone()); } } From ddf881110dc496c56b0b7c3b423ed9692af77ff4 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 15 Feb 2019 22:24:22 +0000 Subject: [PATCH 05/13] Add E0111 Co-Authored-By: Gabriel Smith --- src/librustc_typeck/diagnostics.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 71767fcfd4933..3c4a0760f3ee2 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -1326,6 +1326,10 @@ type X = u32; // ok! ``` "##, +E0111: r##" +You tried to give a const parameter to a type which doesn't need it. +"##, + E0116: r##" You can only define an inherent implementation for a type in the same crate where the type was defined. For example, an `impl` block as below is not allowed From 7f3c6d7c047c7dc8a7cc10fa83c464d2aa6be631 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 15 Feb 2019 22:25:42 +0000 Subject: [PATCH 06/13] Take Const into account in HIR Co-Authored-By: Gabriel Smith --- src/librustc/hir/intravisit.rs | 2 + src/librustc/hir/map/mod.rs | 1 + src/librustc/ich/impls_hir.rs | 11 +- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/middle/resolve_lifetime.rs | 165 ++++++++++---------- src/librustc_lint/builtin.rs | 21 +-- src/librustc_metadata/encoder.rs | 28 ++++ src/librustc_mir/monomorphize/collector.rs | 5 +- src/librustc_typeck/astconv.rs | 39 +++-- src/librustc_typeck/check/compare_method.rs | 5 +- 10 files changed, 166 insertions(+), 113 deletions(-) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 9436c600c9fd3..94b036fded5a1 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -334,6 +334,7 @@ pub trait Visitor<'v> : Sized { match generic_arg { GenericArg::Lifetime(lt) => self.visit_lifetime(lt), GenericArg::Type(ty) => self.visit_ty(ty), + GenericArg::Const(ct) => self.visit_anon_const(&ct.value), } } fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { @@ -752,6 +753,7 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Generi match param.kind { GenericParamKind::Lifetime { .. } => {} GenericParamKind::Type { ref default, .. } => walk_list!(visitor, visit_ty, default), + GenericParamKind::Const { ref ty } => visitor.visit_ty(ty), } walk_list!(visitor, visit_param_bound, ¶m.bounds); } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index b6cf4c1b84d0c..e933e4b7180c4 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -398,6 +398,7 @@ impl<'hir> Map<'hir> { Some(match param.kind { GenericParamKind::Lifetime { .. } => Def::Local(param.id), GenericParamKind::Type { .. } => Def::TyParam(self.local_def_id(param.id)), + GenericParamKind::Const { .. } => Def::ConstParam(self.local_def_id(param.id)), }) } } diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index b10e893732597..727c441b0e8db 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -179,9 +179,15 @@ impl_stable_hash_for!(struct hir::PathSegment { args }); +impl_stable_hash_for!(struct hir::ConstArg { + value, + span, +}); + impl_stable_hash_for!(enum hir::GenericArg { Lifetime(lt), - Type(ty) + Type(ty), + Const(ct), }); impl_stable_hash_for!(struct hir::GenericArgs { @@ -231,6 +237,9 @@ impl<'a> HashStable> for hir::GenericParamKind { default.hash_stable(hcx, hasher); synthetic.hash_stable(hcx, hasher); } + hir::GenericParamKind::Const { ref ty } => { + ty.hash_stable(hcx, hasher); + } } } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 231dcc9bfd272..56e7d78935698 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -704,7 +704,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { hir_id, expr_ty, def); match def { - Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) | + Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) | Def::ConstParam(..) | Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => { Ok(self.cat_rvalue_node(hir_id, span, expr_ty)) } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 5f7b9cc33660f..08da74f47d450 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -527,23 +527,20 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } else { 0 }; - let mut type_count = 0; - let lifetimes = generics - .params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - Some(Region::early(&self.tcx.hir(), &mut index, param)) - } - GenericParamKind::Type { .. } => { - type_count += 1; - None - } - }) - .collect(); + let mut non_lifetime_count = 0; + let lifetimes = generics.params.iter().filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => { + Some(Region::early(&self.tcx.hir(), &mut index, param)) + } + GenericParamKind::Type { .. } | + GenericParamKind::Const { .. } => { + non_lifetime_count += 1; + None + } + }).collect(); let scope = Scope::Binder { lifetimes, - next_early_index: index + type_count, + next_early_index: index + non_lifetime_count, abstract_type_parent: true, track_lifetime_uses, s: ROOT_SCOPE, @@ -708,7 +705,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let mut elision = None; let mut lifetimes = FxHashMap::default(); - let mut type_count = 0; + let mut non_lifetime_count = 0; for param in &generics.params { match param.kind { GenericParamKind::Lifetime { .. } => { @@ -725,12 +722,13 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { lifetimes.insert(name, reg); } } - GenericParamKind::Type { .. } => { - type_count += 1; + GenericParamKind::Type { .. } | + GenericParamKind::Const { .. } => { + non_lifetime_count += 1; } } } - let next_early_index = index + type_count; + let next_early_index = index + non_lifetime_count; if let Some(elision_region) = elision { let scope = Scope::Elision { @@ -788,23 +786,20 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let generics = &trait_item.generics; let mut index = self.next_early_index(); debug!("visit_ty: index = {}", index); - let mut type_count = 0; - let lifetimes = generics - .params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - Some(Region::early(&self.tcx.hir(), &mut index, param)) - } - GenericParamKind::Type { .. } => { - type_count += 1; - None - } - }) - .collect(); + let mut non_lifetime_count = 0; + let lifetimes = generics.params.iter().filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => { + Some(Region::early(&self.tcx.hir(), &mut index, param)) + } + GenericParamKind::Type { .. } | + GenericParamKind::Const { .. } => { + non_lifetime_count += 1; + None + } + }).collect(); let scope = Scope::Binder { lifetimes, - next_early_index: index + type_count, + next_early_index: index + non_lifetime_count, s: self.scope, track_lifetime_uses: true, abstract_type_parent: true, @@ -842,24 +837,21 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { Type(ref ty) => { let generics = &impl_item.generics; let mut index = self.next_early_index(); - let mut next_early_index = index; + let mut non_lifetime_count = 0; debug!("visit_ty: index = {}", index); - let lifetimes = generics - .params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - Some(Region::early(&self.tcx.hir(), &mut index, param)) - } - GenericParamKind::Type { .. } => { - next_early_index += 1; - None - } - }) - .collect(); + let lifetimes = generics.params.iter().filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => { + Some(Region::early(&self.tcx.hir(), &mut index, param)) + } + GenericParamKind::Const { .. } | + GenericParamKind::Type { .. } => { + non_lifetime_count += 1; + None + } + }).collect(); let scope = Scope::Binder { lifetimes, - next_early_index, + next_early_index: index + non_lifetime_count, s: self.scope, track_lifetime_uses: true, abstract_type_parent: true, @@ -874,19 +866,19 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let mut index = self.next_early_index(); let mut next_early_index = index; debug!("visit_ty: index = {}", index); - let lifetimes = generics - .params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - Some(Region::early(&self.tcx.hir(), &mut index, param)) - } - GenericParamKind::Type { .. } => { - next_early_index += 1; - None - } - }) - .collect(); + let lifetimes = generics.params.iter().filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => { + Some(Region::early(&self.tcx.hir(), &mut index, param)) + } + GenericParamKind::Type { .. } => { + next_early_index += 1; + None + } + GenericParamKind::Const { .. } => { + next_early_index += 1; + None + } + }).collect(); let scope = Scope::Binder { lifetimes, @@ -950,6 +942,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.visit_ty(&ty); } } + GenericParamKind::Const { ref ty, .. } => { + walk_list!(self, visit_param_bound, ¶m.bounds); + self.visit_ty(&ty); + } } } for predicate in &generics.where_clause.predicates { @@ -1395,6 +1391,10 @@ fn object_lifetime_defaults_for_item( Set1::Many => Set1::Many, }) } + GenericParamKind::Const { .. } => { + // Generic consts don't impose any constraints. + None + } }) .collect() } @@ -1703,25 +1703,22 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } - let mut type_count = 0; - let lifetimes = generics - .params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - if self.map.late_bound.contains(¶m.id) { - Some(Region::late(&self.tcx.hir(), param)) - } else { - Some(Region::early(&self.tcx.hir(), &mut index, param)) - } - } - GenericParamKind::Type { .. } => { - type_count += 1; - None + let mut non_lifetime_count = 0; + let lifetimes = generics.params.iter().filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => { + if self.map.late_bound.contains(¶m.id) { + Some(Region::late(&self.tcx.hir(), param)) + } else { + Some(Region::early(&self.tcx.hir(), &mut index, param)) } - }) - .collect(); - let next_early_index = index + type_count; + } + GenericParamKind::Type { .. } | + GenericParamKind::Const { .. } => { + non_lifetime_count += 1; + None + } + }).collect(); + let next_early_index = index + non_lifetime_count; let scope = Scope::Binder { lifetimes, @@ -2011,6 +2008,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } i += 1; } + GenericArg::Const(ct) => { + self.visit_anon_const(&ct.value); + } } } @@ -2768,8 +2768,9 @@ fn insert_late_bound_lifetimes( match param.kind { hir::GenericParamKind::Lifetime { .. } => { /* fall through */ } - // Types are not late-bound. - hir::GenericParamKind::Type { .. } => continue, + // Neither types nor consts are late-bound. + hir::GenericParamKind::Type { .. } + | hir::GenericParamKind::Const { .. } => continue, } let lt_name = hir::LifetimeName::Param(param.name.modern()); diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 28e01bd9793fd..925cde5b5cc8b 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -907,11 +907,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems { for param in &generics.params { match param.kind { GenericParamKind::Lifetime { .. } => {} - GenericParamKind::Type { .. } => { - let mut err = cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS, - it.span, - "functions generic over \ - types must be mangled"); + GenericParamKind::Type { .. } | + GenericParamKind::Const { .. } => { + let mut err = cx.struct_span_lint( + NO_MANGLE_GENERIC_ITEMS, + it.span, + "functions generic over types or consts must be mangled", + ); err.span_suggestion_short( no_mangle_attr.span, "remove this attribute", @@ -1791,14 +1793,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitOutlivesRequirements { for param in &generics.params { let param_name = match param.kind { - hir::GenericParamKind::Lifetime { .. } => { continue; }, + hir::GenericParamKind::Lifetime { .. } => continue, hir::GenericParamKind::Type { .. } => { match param.name { - hir::ParamName::Fresh(_) => { continue; }, - hir::ParamName::Error => { continue; }, - hir::ParamName::Plain(name) => name.to_string() + hir::ParamName::Fresh(_) => continue, + hir::ParamName::Error => continue, + hir::ParamName::Plain(name) => name.to_string(), } } + hir::GenericParamKind::Const { .. } => continue, }; let bound_spans = self.collect_outlives_bound_spans( cx, def_id, ¶m_name, ¶m.bounds, infer_static diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 40d3ee9cc0b11..776adc077fc08 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1331,6 +1331,29 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } } + fn encode_info_for_const_param(&mut self, def_id: DefId) -> Entry<'tcx> { + debug!("IsolatedEncoder::encode_info_for_const_param({:?})", def_id); + let tcx = self.tcx; + Entry { + kind: EntryKind::Type, + visibility: self.lazy(&ty::Visibility::Public), + span: self.lazy(&tcx.def_span(def_id)), + attributes: LazySeq::empty(), + children: LazySeq::empty(), + stability: None, + deprecation: None, + + ty: Some(self.encode_item_type(def_id)), + inherent_impls: LazySeq::empty(), + variances: LazySeq::empty(), + generics: None, + predicates: None, + predicates_defined_on: None, + + mir: None, + } + } + fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> { debug!("IsolatedEncoder::encode_info_for_closure({:?})", def_id); let tcx = self.tcx; @@ -1684,6 +1707,11 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { let encode_info = IsolatedEncoder::encode_info_for_ty_param; self.record(def_id, encode_info, (def_id, has_default)); } + hir::GenericParamKind::Const { .. } => { + let def_id = self.tcx.hir().local_def_id(param.id); + let encode_info = IsolatedEncoder::encode_info_for_const_param; + self.record(def_id, encode_info, def_id); + } } } } diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index a76aa7454cbe4..e68702bfe3ae0 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1090,7 +1090,10 @@ fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, for param in &generics.params { match param.kind { hir::GenericParamKind::Lifetime { .. } => {} - hir::GenericParamKind::Type { .. } => return, + hir::GenericParamKind::Type { .. } | + hir::GenericParamKind::Const { .. } => { + return + } } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 23e9cd55cdce7..cde6eb22bb8ae 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -500,19 +500,20 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { args.next(); params.next(); } - (GenericArg::Lifetime(_), GenericParamDefKind::Type { .. }) => { - // We expected a type argument, but got a lifetime - // argument. This is an error, but we need to handle it - // gracefully so we can report sensible errors. In this - // case, we're simply going to infer this argument. - args.next(); - } - (GenericArg::Type(_), GenericParamDefKind::Lifetime) => { - // We expected a lifetime argument, but got a type + (GenericArg::Type(_), GenericParamDefKind::Lifetime) + | (GenericArg::Const(_), GenericParamDefKind::Lifetime) => { + // We expected a lifetime argument, but got a type or const // argument. That means we're inferring the lifetimes. substs.push(inferred_kind(None, param, infer_types)); params.next(); } + (_, _) => { + // We expected one kind of parameter, but the user provided + // another. This is an error, but we need to handle it + // gracefully so we can report sensible errors. + // In this case, we're simply going to infer this argument. + args.next(); + } } } (Some(_), None) => { @@ -524,12 +525,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { (None, Some(¶m)) => { // If there are fewer arguments than parameters, it means // we're inferring the remaining arguments. - match param.kind { - GenericParamDefKind::Lifetime | GenericParamDefKind::Type { .. } => { - let kind = inferred_kind(Some(&substs), param, infer_types); - substs.push(kind); - } - } + substs.push(inferred_kind(Some(&substs), param, infer_types)); args.next(); params.next(); } @@ -1459,9 +1455,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { let mut has_err = false; for segment in segments { segment.with_generic_args(|generic_args| { - let (mut err_for_lt, mut err_for_ty) = (false, false); + let (mut err_for_lt, mut err_for_ty, mut err_for_ct) = (false, false, false); for arg in &generic_args.args { let (mut span_err, span, kind) = match arg { + // FIXME(varkor): unify E0109, E0110 and E0111. hir::GenericArg::Lifetime(lt) => { if err_for_lt { continue } err_for_lt = true; @@ -1480,10 +1477,18 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { ty.span, "type") } + hir::GenericArg::Const(ct) => { + if err_for_ct { continue } + err_for_ct = true; + (struct_span_err!(self.tcx().sess, ct.span, E0111, + "const parameters are not allowed on this type"), + ct.span, + "const") + } }; span_err.span_label(span, format!("{} argument not allowed", kind)) .emit(); - if err_for_lt && err_for_ty { + if err_for_lt && err_for_ty && err_for_ct { break; } } diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 05ca54df2984b..bc323e2cf8a98 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -840,8 +840,9 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let bounds = impl_m.generics.params.iter().find_map(|param| { match param.kind { GenericParamKind::Lifetime { .. } => None, - GenericParamKind::Type { .. } => { - if param.hir_id == impl_hir_id { + GenericParamKind::Type { .. } | + GenericParamKind::Const { .. } => { + if param.hir_id == impl_node_id { Some(¶m.bounds) } else { None From 10602f1dbf55522072ce85095bf041649e52ad6f Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 15 Feb 2019 22:26:05 +0000 Subject: [PATCH 07/13] Drive-by cleanup Co-Authored-By: Gabriel Smith --- src/librustc/hir/def.rs | 2 +- src/librustc/hir/pat_util.rs | 13 ------------- src/librustc/middle/reachable.rs | 7 +++++-- src/librustdoc/clean/mod.rs | 6 +++--- src/librustdoc/core.rs | 2 +- 5 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index b15bea017762e..f6d864f5b404d 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -52,13 +52,13 @@ pub enum Def { AssociatedExistential(DefId), PrimTy(hir::PrimTy), TyParam(DefId), - ConstParam(DefId), SelfTy(Option /* trait */, Option /* impl */), ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]` // Value namespace Fn(DefId), Const(DefId), + ConstParam(DefId), Static(DefId, bool /* is_mutbl */), StructCtor(DefId, CtorKind), // `DefId` refers to `NodeId` of the struct's constructor VariantCtor(DefId, CtorKind), // `DefId` refers to the enum variant diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index e2df290a455c4..312351ab850c2 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -64,19 +64,6 @@ impl hir::Pat { } } - pub fn is_const(&self) -> bool { - match self.node { - PatKind::Path(hir::QPath::TypeRelative(..)) => true, - PatKind::Path(hir::QPath::Resolved(_, ref path)) => { - match path.def { - Def::Const(..) | Def::AssociatedConst(..) => true, - _ => false - } - } - _ => false - } - } - /// Call `f` on every "binding" in a pattern, e.g., on `a` in /// `match foo() { Some(a) => (), None => () }` pub fn each_binding(&self, mut f: F) diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 99d0c5e88d638..0562fddb2b523 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -315,8 +315,11 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { Node::Ty(_) | Node::MacroDef(_) => {} _ => { - bug!("found unexpected thingy in worklist: {}", - self.tcx.hir().node_to_string(search_item)) + bug!( + "found unexpected node kind in worklist: {} ({:?})", + self.tcx.hir().node_to_string(search_item), + node, + ); } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b08646ec00421..92afbc56c557b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1502,7 +1502,7 @@ impl Clean for hir::GenericParam { }; (name, GenericParamDefKind::Lifetime) } - hir::GenericParamKind::Type { ref default, synthetic, .. } => { + hir::GenericParamKind::Type { ref default, synthetic } => { (self.name.ident().name.clean(cx), GenericParamDefKind::Type { did: cx.tcx.hir().local_def_id(self.id), bounds: self.bounds.clean(cx), @@ -2577,7 +2577,7 @@ impl Clean for hir::Ty { let mut j = 0; let lifetime = generic_args.args.iter().find_map(|arg| { match arg { - GenericArg::Lifetime(lt) => { + hir::GenericArg::Lifetime(lt) => { if indices.lifetimes == j { return Some(lt); } @@ -2602,7 +2602,7 @@ impl Clean for hir::Ty { let mut j = 0; let type_ = generic_args.args.iter().find_map(|arg| { match arg { - GenericArg::Type(ty) => { + hir::GenericArg::Type(ty) => { if indices.types == j { return Some(ty); } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 5df82c7cc9e9a..59820e4e5d1ae 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -218,7 +218,7 @@ impl<'a, 'tcx, 'rcx> DocContext<'a, 'tcx, 'rcx> { name: hir::LifetimeName::Param(name), })); } - ty::GenericParamDefKind::Type {..} => { + ty::GenericParamDefKind::Type { .. } => { args.push(hir::GenericArg::Type(self.ty_param_to_ty(param.clone()))); } } From 2279907fd268b6e800c8e586f247f806003e81f5 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 15 Feb 2019 22:26:29 +0000 Subject: [PATCH 08/13] Take Const into account with nonstandard style lint Co-Authored-By: Gabriel Smith --- src/librustc_lint/nonstandard_style.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index c2dd9a3d1b84f..ee5e715161adc 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -455,6 +455,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals { } } } + + fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) { + if let GenericParamKind::Const { .. } = param.kind { + NonUpperCaseGlobals::check_upper_case( + cx, + "const parameter", + ¶m.name.ident(), + ); + } + } } #[cfg(test)] From 9cfdb800859a5a5cea876e97232644325931f4fc Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 15 Feb 2019 22:26:36 +0000 Subject: [PATCH 09/13] Update tests Co-Authored-By: Gabriel Smith --- src/test/ui/generic/generic-no-mangle.rs | 4 ++-- src/test/ui/generic/generic-no-mangle.stderr | 8 ++++---- src/test/ui/lint/suggestions.rs | 6 +++--- src/test/ui/lint/suggestions.stderr | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/test/ui/generic/generic-no-mangle.rs b/src/test/ui/generic/generic-no-mangle.rs index 15e662a41de22..994aebc7f6e3e 100644 --- a/src/test/ui/generic/generic-no-mangle.rs +++ b/src/test/ui/generic/generic-no-mangle.rs @@ -1,10 +1,10 @@ #![deny(no_mangle_generic_items)] #[no_mangle] -pub fn foo() {} //~ ERROR functions generic over types must be mangled +pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled #[no_mangle] -pub extern fn bar() {} //~ ERROR functions generic over types must be mangled +pub extern fn bar() {} //~ ERROR functions generic over types or consts must be mangled #[no_mangle] pub fn baz(x: &i32) -> &i32 { x } diff --git a/src/test/ui/generic/generic-no-mangle.stderr b/src/test/ui/generic/generic-no-mangle.stderr index 639ee19910155..3da39f1dc17cb 100644 --- a/src/test/ui/generic/generic-no-mangle.stderr +++ b/src/test/ui/generic/generic-no-mangle.stderr @@ -1,9 +1,9 @@ -error: functions generic over types must be mangled +error: functions generic over types or consts must be mangled --> $DIR/generic-no-mangle.rs:4:1 | LL | #[no_mangle] | ------------ help: remove this attribute -LL | pub fn foo() {} //~ ERROR functions generic over types must be mangled +LL | pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled | ^^^^^^^^^^^^^^^^^^ | note: lint level defined here @@ -12,12 +12,12 @@ note: lint level defined here LL | #![deny(no_mangle_generic_items)] | ^^^^^^^^^^^^^^^^^^^^^^^ -error: functions generic over types must be mangled +error: functions generic over types or consts must be mangled --> $DIR/generic-no-mangle.rs:7:1 | LL | #[no_mangle] | ------------ help: remove this attribute -LL | pub extern fn bar() {} //~ ERROR functions generic over types must be mangled +LL | pub extern fn bar() {} //~ ERROR functions generic over types or consts must be mangled | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/lint/suggestions.rs b/src/test/ui/lint/suggestions.rs index a497953d73a05..67bd6dd501bd8 100644 --- a/src/test/ui/lint/suggestions.rs +++ b/src/test/ui/lint/suggestions.rs @@ -10,7 +10,7 @@ #[no_mangle] //~^ HELP remove this attribute pub fn defiant(_t: T) {} -//~^ WARN functions generic over types must be mangled +//~^ WARN functions generic over types or consts must be mangled #[no_mangle] fn rio_grande() {} @@ -23,7 +23,7 @@ mod badlands { //~^ ERROR const items should never be #[no_mangle] //~| HELP try a static value #[no_mangle] pub fn val_jean() {} - //~^ WARN functions generic over types must be mangled + //~^ WARN functions generic over types or consts must be mangled //~| HELP remove this attribute // ... but we can suggest just-`pub` instead of restricted @@ -31,7 +31,7 @@ mod badlands { //~^ ERROR const items should never be #[no_mangle] //~| HELP try a static value #[no_mangle] pub(crate) fn crossfield() {} - //~^ WARN functions generic over types must be mangled + //~^ WARN functions generic over types or consts must be mangled //~| HELP remove this attribute } diff --git a/src/test/ui/lint/suggestions.stderr b/src/test/ui/lint/suggestions.stderr index c70f17f95d028..1e4eabc9db0f7 100644 --- a/src/test/ui/lint/suggestions.stderr +++ b/src/test/ui/lint/suggestions.stderr @@ -54,7 +54,7 @@ LL | #[no_mangle] const DISCOVERY: usize = 1; | = note: #[deny(no_mangle_const_items)] on by default -warning: functions generic over types must be mangled +warning: functions generic over types or consts must be mangled --> $DIR/suggestions.rs:12:1 | LL | #[no_mangle] @@ -73,7 +73,7 @@ LL | #[no_mangle] pub const DAUNTLESS: bool = true; | | | help: try a static value: `pub static` -warning: functions generic over types must be mangled +warning: functions generic over types or consts must be mangled --> $DIR/suggestions.rs:25:18 | LL | #[no_mangle] pub fn val_jean() {} @@ -89,7 +89,7 @@ LL | #[no_mangle] pub(crate) const VETAR: bool = true; | | | help: try a static value: `pub static` -warning: functions generic over types must be mangled +warning: functions generic over types or consts must be mangled --> $DIR/suggestions.rs:33:18 | LL | #[no_mangle] pub(crate) fn crossfield() {} From 18ce997e51117d3dd40aa1187a2c3cdf58f74167 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 15 Feb 2019 23:34:04 +0000 Subject: [PATCH 10/13] Fix rebase issue --- src/librustc_lint/nonstandard_style.rs | 2 +- src/librustc_typeck/check/compare_method.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index ee5e715161adc..7c66289703ac8 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -456,7 +456,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals { } } - fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) { + fn check_generic_param(&mut self, cx: &LateContext<'_, '_>, param: &hir::GenericParam) { if let GenericParamKind::Const { .. } = param.kind { NonUpperCaseGlobals::check_upper_case( cx, diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index bc323e2cf8a98..5f1c2efb6a457 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -842,7 +842,7 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, GenericParamKind::Lifetime { .. } => None, GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { - if param.hir_id == impl_node_id { + if param.hir_id == impl_hir_id { Some(¶m.bounds) } else { None From 2a1b6c52d34aa021a3930fdea954b3228fba0f71 Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 16 Feb 2019 13:03:30 +0000 Subject: [PATCH 11/13] Check for Const param in collect --- src/librustc_typeck/collect.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index db508a5772689..8f382243bb5a3 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1320,10 +1320,10 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> { }, Node::GenericParam(param) => match ¶m.kind { - hir::GenericParamKind::Type { - default: Some(ref ty), - .. - } => icx.to_ty(ty), + hir::GenericParamKind::Type { default: Some(ref ty), .. } | + hir::GenericParamKind::Const { ref ty, .. } => { + icx.to_ty(ty) + } x => bug!("unexpected non-type Node::GenericParam: {:?}", x), }, From 425fb58cacb9dbded92e46ee1bdeaa9dda4a219e Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 16 Feb 2019 13:03:58 +0000 Subject: [PATCH 12/13] Don't abort early when collecting const generics --- src/librustc_typeck/collect.rs | 5 +++-- .../ui/const-generics/const-param-before-other-params.rs | 1 + .../const-generics/const-param-before-other-params.stderr | 8 +++++++- src/test/ui/feature-gates/feature-gate-const_generics.rs | 1 + .../ui/feature-gates/feature-gate-const_generics.stderr | 8 +++++++- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 8f382243bb5a3..84de38beafad9 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1053,12 +1053,13 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty ); } + // Emit an error, but skip the parameter rather than aborting to + // continue to get other errors. tcx.sess.struct_span_err( param.span, "const generics in any position are currently unsupported", ).emit(); - tcx.sess.abort_if_errors(); - bug!(); + None } _ => None, }), diff --git a/src/test/ui/const-generics/const-param-before-other-params.rs b/src/test/ui/const-generics/const-param-before-other-params.rs index 3f120cbc4d337..47f826789e03e 100644 --- a/src/test/ui/const-generics/const-param-before-other-params.rs +++ b/src/test/ui/const-generics/const-param-before-other-params.rs @@ -8,6 +8,7 @@ fn foo(_: T) { fn bar(_: &'a ()) { //~^ ERROR lifetime parameters must be declared prior to const parameters + //~^^ ERROR const generics in any position are currently unsupported } fn main() {} diff --git a/src/test/ui/const-generics/const-param-before-other-params.stderr b/src/test/ui/const-generics/const-param-before-other-params.stderr index aedcaf52e2688..a43415d0e5a43 100644 --- a/src/test/ui/const-generics/const-param-before-other-params.stderr +++ b/src/test/ui/const-generics/const-param-before-other-params.stderr @@ -22,5 +22,11 @@ error: const generics in any position are currently unsupported LL | fn foo(_: T) { | ^ -error: aborting due to 3 previous errors +error: const generics in any position are currently unsupported + --> $DIR/const-param-before-other-params.rs:9:14 + | +LL | fn bar(_: &'a ()) { + | ^ + +error: aborting due to 4 previous errors diff --git a/src/test/ui/feature-gates/feature-gate-const_generics.rs b/src/test/ui/feature-gates/feature-gate-const_generics.rs index a8a4ed5772299..907e00b11e556 100644 --- a/src/test/ui/feature-gates/feature-gate-const_generics.rs +++ b/src/test/ui/feature-gates/feature-gate-const_generics.rs @@ -2,5 +2,6 @@ fn foo() {} //~ ERROR const generics are unstable //~^ const generics in any position are currently unsupported struct Foo([(); X]); //~ ERROR const generics are unstable +//~^ const generics in any position are currently unsupported fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-const_generics.stderr b/src/test/ui/feature-gates/feature-gate-const_generics.stderr index 905cc07b6a175..3ab1aa2367f1c 100644 --- a/src/test/ui/feature-gates/feature-gate-const_generics.stderr +++ b/src/test/ui/feature-gates/feature-gate-const_generics.stderr @@ -20,6 +20,12 @@ error: const generics in any position are currently unsupported LL | fn foo() {} //~ ERROR const generics are unstable | ^ -error: aborting due to 3 previous errors +error: const generics in any position are currently unsupported + --> $DIR/feature-gate-const_generics.rs:4:18 + | +LL | struct Foo([(); X]); //~ ERROR const generics are unstable + | ^ + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0658`. From 727e20410c61293f38b7f7984a469dc7daad632a Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 16 Feb 2019 13:04:15 +0000 Subject: [PATCH 13/13] Add a test for const parameter uppercase lint --- .../const-parameter-uppercase-lint.rs | 8 ++++++++ .../const-parameter-uppercase-lint.stderr | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/test/ui/const-generics/const-parameter-uppercase-lint.rs create mode 100644 src/test/ui/const-generics/const-parameter-uppercase-lint.stderr diff --git a/src/test/ui/const-generics/const-parameter-uppercase-lint.rs b/src/test/ui/const-generics/const-parameter-uppercase-lint.rs new file mode 100644 index 0000000000000..37fe9af98b3df --- /dev/null +++ b/src/test/ui/const-generics/const-parameter-uppercase-lint.rs @@ -0,0 +1,8 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +#![deny(non_upper_case_globals)] + +fn noop() { + //~^ ERROR const generics in any position are currently unsupported +} diff --git a/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr b/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr new file mode 100644 index 0000000000000..9683e91cef30c --- /dev/null +++ b/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr @@ -0,0 +1,19 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/const-parameter-uppercase-lint.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + +error[E0601]: `main` function not found in crate `const_parameter_uppercase_lint` + | + = note: consider adding a `main` function to `$DIR/const-parameter-uppercase-lint.rs` + +error: const generics in any position are currently unsupported + --> $DIR/const-parameter-uppercase-lint.rs:6:15 + | +LL | fn noop() { + | ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0601`.