diff options
| author | Amanieu d'Antras <amanieu@gmail.com> | 2021-02-23 15:12:28 +0000 |
|---|---|---|
| committer | Amanieu d'Antras <amanieu@gmail.com> | 2021-02-23 17:25:55 +0000 |
| commit | d87eec1bf67959977c8ebaadc2ddcf4bdc14658a (patch) | |
| tree | 1f777c2c1702ec27d57c346a8c9f7c1b876df372 /compiler/rustc_ast_lowering/src/expr.rs | |
| parent | 9b471a3f5fe57e5c6e08acf665f2094422415a3d (diff) | |
| download | rust-d87eec1bf67959977c8ebaadc2ddcf4bdc14658a.tar.gz rust-d87eec1bf67959977c8ebaadc2ddcf4bdc14658a.zip | |
Add #[rustc_legacy_const_generics]
Diffstat (limited to 'compiler/rustc_ast_lowering/src/expr.rs')
| -rw-r--r-- | compiler/rustc_ast_lowering/src/expr.rs | 90 |
1 files changed, 88 insertions, 2 deletions
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index b118c0eaed4..145a9784010 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -9,7 +9,9 @@ use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::Res; +use rustc_hir::definitions::DefPathData; use rustc_session::parse::feature_err; +use rustc_span::hygiene::ExpnId; use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned}; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{hygiene::ForLoopLoc, DUMMY_SP}; @@ -42,8 +44,12 @@ impl<'hir> LoweringContext<'_, 'hir> { } ExprKind::Tup(ref elts) => hir::ExprKind::Tup(self.lower_exprs(elts)), ExprKind::Call(ref f, ref args) => { - let f = self.lower_expr(f); - hir::ExprKind::Call(f, self.lower_exprs(args)) + if let Some(legacy_args) = self.legacy_const_generic_args(f) { + self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args) + } else { + let f = self.lower_expr(f); + hir::ExprKind::Call(f, self.lower_exprs(args)) + } } ExprKind::MethodCall(ref seg, ref args, span) => { let hir_seg = self.arena.alloc(self.lower_path_segment( @@ -292,6 +298,86 @@ impl<'hir> LoweringContext<'_, 'hir> { } } + /// Checks if an expression refers to a function marked with + /// `#[rustc_legacy_const_generics]` and returns the argument index list + /// from the attribute. + fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option<Vec<usize>> { + if let ExprKind::Path(None, path) = &expr.kind { + if path.segments.last().unwrap().args.is_some() { + return None; + } + if let Some(partial_res) = self.resolver.get_partial_res(expr.id) { + if partial_res.unresolved_segments() != 0 { + return None; + } + if let Res::Def(hir::def::DefKind::Fn, def_id) = partial_res.base_res() { + let attrs = self.item_attrs(def_id); + let attr = attrs + .iter() + .find(|a| self.sess.check_name(a, sym::rustc_legacy_const_generics))?; + let mut ret = vec![]; + for meta in attr.meta_item_list()? { + match meta.literal()?.kind { + LitKind::Int(a, _) => { + ret.push(a as usize); + } + _ => panic!("invalid arg index"), + } + } + return Some(ret); + } + } + } + None + } + + fn lower_legacy_const_generics( + &mut self, + mut f: Expr, + args: Vec<AstP<Expr>>, + legacy_args_idx: &[usize], + ) -> hir::ExprKind<'hir> { + let path = match f.kind { + ExprKind::Path(None, ref mut path) => path, + _ => unreachable!(), + }; + + // Split the arguments into const generics and normal arguments + let mut real_args = vec![]; + let mut generic_args = vec![]; + for (idx, arg) in args.into_iter().enumerate() { + if legacy_args_idx.contains(&idx) { + let parent_def_id = self.current_hir_id_owner.last().unwrap().0; + let node_id = self.resolver.next_node_id(); + + // Add a definition for the in-band const def. + self.resolver.create_def( + parent_def_id, + node_id, + DefPathData::AnonConst, + ExpnId::root(), + arg.span, + ); + + let anon_const = AnonConst { id: node_id, value: arg }; + generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const))); + } else { + real_args.push(arg); + } + } + + // Add generic args to the last element of the path + path.segments.last_mut().unwrap().args = + Some(AstP(GenericArgs::AngleBracketed(AngleBracketedArgs { + span: DUMMY_SP, + args: generic_args, + }))); + + // Now lower everything as normal. + let f = self.lower_expr(&f); + hir::ExprKind::Call(f, self.lower_exprs(&real_args)) + } + /// Emit an error and lower `ast::ExprKind::Let(pat, scrutinee)` into: /// ```rust /// match scrutinee { pats => true, _ => false } |
