From 7f3c6d7c047c7dc8a7cc10fa83c464d2aa6be631 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 15 Feb 2019 22:25:42 +0000 Subject: [PATCH] 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 9436c600c9f..94b036fded5 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 b6cf4c1b84d..e933e4b7180 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 b10e8937325..727c441b0e8 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 231dcc9bfd2..56e7d789356 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 5f7b9cc3366..08da74f47d4 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)) - } + 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)) } - GenericParamKind::Type { .. } => { - type_count += 1; - None - } - }) - .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 28e01bd9793..925cde5b5cc 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 40d3ee9cc0b..776adc077fc 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 a76aa7454cb..e68702bfe3a 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 23e9cd55cdc..cde6eb22bb8 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 05ca54df298..bc323e2cf8a 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