Address review comments
This commit is contained in:
parent
00eca69bff
commit
2451f124c9
6 changed files with 78 additions and 90 deletions
|
@ -44,7 +44,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
}
|
}
|
||||||
ExprKind::Tup(ref elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),
|
ExprKind::Tup(ref elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),
|
||||||
ExprKind::Call(ref f, ref args) => {
|
ExprKind::Call(ref f, ref args) => {
|
||||||
if let Some(legacy_args) = self.legacy_const_generic_args(f) {
|
if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) {
|
||||||
self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args)
|
self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args)
|
||||||
} else {
|
} else {
|
||||||
let f = self.lower_expr(f);
|
let f = self.lower_expr(f);
|
||||||
|
@ -298,39 +298,6 @@ 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(
|
fn lower_legacy_const_generics(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut f: Expr,
|
mut f: Expr,
|
||||||
|
@ -366,12 +333,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add generic args to the last element of the path
|
// Add generic args to the last element of the path.
|
||||||
path.segments.last_mut().unwrap().args =
|
let last_segment = path.segments.last_mut().unwrap();
|
||||||
Some(AstP(GenericArgs::AngleBracketed(AngleBracketedArgs {
|
assert!(last_segment.args.is_none());
|
||||||
span: DUMMY_SP,
|
last_segment.args = Some(AstP(GenericArgs::AngleBracketed(AngleBracketedArgs {
|
||||||
args: generic_args,
|
span: DUMMY_SP,
|
||||||
})));
|
args: generic_args,
|
||||||
|
})));
|
||||||
|
|
||||||
// Now lower everything as normal.
|
// Now lower everything as normal.
|
||||||
let f = self.lower_expr(&f);
|
let f = self.lower_expr(&f);
|
||||||
|
|
|
@ -175,7 +175,7 @@ pub trait ResolverAstLowering {
|
||||||
|
|
||||||
fn item_generics_num_lifetimes(&self, def: DefId, sess: &Session) -> usize;
|
fn item_generics_num_lifetimes(&self, def: DefId, sess: &Session) -> usize;
|
||||||
|
|
||||||
fn item_attrs(&self, def_id: DefId, sess: &Session) -> Vec<ast::Attribute>;
|
fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>;
|
||||||
|
|
||||||
/// Obtains resolution for a `NodeId` with a single resolution.
|
/// Obtains resolution for a `NodeId` with a single resolution.
|
||||||
fn get_partial_res(&mut self, id: NodeId) -> Option<PartialRes>;
|
fn get_partial_res(&mut self, id: NodeId) -> Option<PartialRes>;
|
||||||
|
@ -2828,16 +2828,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute> {
|
|
||||||
if let Some(_local_def_id) = def_id.as_local() {
|
|
||||||
// FIXME: This doesn't actually work, items doesn't include everything?
|
|
||||||
//self.items[&hir::ItemId { def_id: local_def_id }].attrs.into()
|
|
||||||
Vec::new()
|
|
||||||
} else {
|
|
||||||
self.resolver.item_attrs(def_id, self.sess)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body<'_>>) -> Vec<hir::BodyId> {
|
fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body<'_>>) -> Vec<hir::BodyId> {
|
||||||
|
|
|
@ -789,6 +789,23 @@ impl CheckAttrVisitor<'tcx> {
|
||||||
})) = item
|
})) = item
|
||||||
{
|
{
|
||||||
let arg_count = decl.inputs.len() as u128 + generics.params.len() as u128;
|
let arg_count = decl.inputs.len() as u128 + generics.params.len() as u128;
|
||||||
|
for param in generics.params {
|
||||||
|
match param.kind {
|
||||||
|
hir::GenericParamKind::Const { .. } => {}
|
||||||
|
_ => {
|
||||||
|
self.tcx
|
||||||
|
.sess
|
||||||
|
.struct_span_err(
|
||||||
|
meta.span(),
|
||||||
|
"#[rustc_legacy_const_generics] functions must \
|
||||||
|
only have const generics",
|
||||||
|
)
|
||||||
|
.span_label(param.span, "non-const generic parameter")
|
||||||
|
.emit();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if *val >= arg_count {
|
if *val >= arg_count {
|
||||||
let span = meta.span();
|
let span = meta.span();
|
||||||
self.tcx
|
self.tcx
|
||||||
|
|
|
@ -2326,8 +2326,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
|
|
||||||
ExprKind::Call(ref callee, ref arguments) => {
|
ExprKind::Call(ref callee, ref arguments) => {
|
||||||
self.resolve_expr(callee, Some(expr));
|
self.resolve_expr(callee, Some(expr));
|
||||||
let const_args = self.legacy_const_generic_args(callee).unwrap_or(Vec::new());
|
let const_args = self.r.legacy_const_generic_args(callee).unwrap_or(Vec::new());
|
||||||
for (idx, argument) in arguments.iter().enumerate() {
|
for (idx, argument) in arguments.iter().enumerate() {
|
||||||
|
// Constant arguments need to be treated as AnonConst since
|
||||||
|
// that is how they will be later lowered to HIR.
|
||||||
if const_args.contains(&idx) {
|
if const_args.contains(&idx) {
|
||||||
self.with_constant_rib(
|
self.with_constant_rib(
|
||||||
IsRepeatExpr::No,
|
IsRepeatExpr::No,
|
||||||
|
@ -2418,42 +2420,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
Some((ident.name, ns)),
|
Some((ident.name, ns)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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.r.get_partial_res(expr.id) {
|
|
||||||
if partial_res.unresolved_segments() != 0 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
if let Res::Def(def::DefKind::Fn, def_id) = partial_res.base_res() {
|
|
||||||
if def_id.is_local() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let attrs = self.r.cstore().item_attrs(def_id, self.r.session);
|
|
||||||
let attr = attrs
|
|
||||||
.iter()
|
|
||||||
.find(|a| self.r.session.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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Resolver<'a> {
|
impl<'a> Resolver<'a> {
|
||||||
|
|
|
@ -29,6 +29,7 @@ use rustc_ast::unwrap_or;
|
||||||
use rustc_ast::visit::{self, Visitor};
|
use rustc_ast::visit::{self, Visitor};
|
||||||
use rustc_ast::{self as ast, NodeId};
|
use rustc_ast::{self as ast, NodeId};
|
||||||
use rustc_ast::{Crate, CRATE_NODE_ID};
|
use rustc_ast::{Crate, CRATE_NODE_ID};
|
||||||
|
use rustc_ast::{Expr, ExprKind, LitKind};
|
||||||
use rustc_ast::{ItemKind, ModKind, Path};
|
use rustc_ast::{ItemKind, ModKind, Path};
|
||||||
use rustc_ast_lowering::ResolverAstLowering;
|
use rustc_ast_lowering::ResolverAstLowering;
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
|
@ -1076,8 +1077,8 @@ impl ResolverAstLowering for Resolver<'_> {
|
||||||
self.cstore().item_generics_num_lifetimes(def_id, sess)
|
self.cstore().item_generics_num_lifetimes(def_id, sess)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_attrs(&self, def_id: DefId, sess: &Session) -> Vec<ast::Attribute> {
|
fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>> {
|
||||||
self.cstore().item_attrs(def_id, sess)
|
self.legacy_const_generic_args(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_partial_res(&mut self, id: NodeId) -> Option<PartialRes> {
|
fn get_partial_res(&mut self, id: NodeId) -> Option<PartialRes> {
|
||||||
|
@ -3312,6 +3313,49 @@ impl<'a> Resolver<'a> {
|
||||||
pub fn opt_span(&self, def_id: DefId) -> Option<Span> {
|
pub fn opt_span(&self, def_id: DefId) -> Option<Span> {
|
||||||
if let Some(def_id) = def_id.as_local() { Some(self.def_id_to_span[def_id]) } else { None }
|
if let Some(def_id) = def_id.as_local() { Some(self.def_id_to_span[def_id]) } else { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if an expression refers to a function marked with
|
||||||
|
/// `#[rustc_legacy_const_generics]` and returns the argument index list
|
||||||
|
/// from the attribute.
|
||||||
|
pub fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>> {
|
||||||
|
if let ExprKind::Path(None, path) = &expr.kind {
|
||||||
|
// Don't perform legacy const generics rewriting if the path already
|
||||||
|
// has generic arguments.
|
||||||
|
if path.segments.last().unwrap().args.is_some() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let partial_res = self.partial_res_map.get(&expr.id)?;
|
||||||
|
if partial_res.unresolved_segments() != 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Res::Def(def::DefKind::Fn, def_id) = partial_res.base_res() {
|
||||||
|
// We only support cross-crate argument rewriting. Uses
|
||||||
|
// within the same crate should be updated to use the new
|
||||||
|
// const generics style.
|
||||||
|
if def_id.is_local() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let attrs = self.cstore().item_attrs(def_id, self.session);
|
||||||
|
let attr = attrs
|
||||||
|
.iter()
|
||||||
|
.find(|a| self.session.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 names_to_string(names: &[Symbol]) -> String {
|
fn names_to_string(names: &[Symbol]) -> String {
|
||||||
|
|
|
@ -26,6 +26,9 @@ extern {
|
||||||
fn foo7(_: u8);
|
fn foo7(_: u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustc_legacy_const_generics(0)] //~ ERROR #[rustc_legacy_const_generics] functions must only have
|
||||||
|
fn foo3<X>() {}
|
||||||
|
|
||||||
#[rustc_legacy_const_generics] //~ ERROR malformed `rustc_legacy_const_generics` attribute
|
#[rustc_legacy_const_generics] //~ ERROR malformed `rustc_legacy_const_generics` attribute
|
||||||
fn bar1() {}
|
fn bar1() {}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue