Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 19 additions & 17 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,25 +237,27 @@ impl SpanLowerer {
#[extension(trait ResolverAstLoweringExt)]
impl ResolverAstLowering {
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 ExprKind::Path(None, path) = &expr.kind else {
return None;
};

if let Res::Def(DefKind::Fn, def_id) = self.partial_res_map.get(&expr.id)?.full_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;
}
// Don't perform legacy const generics rewriting if the path already
// has generic arguments.
if path.segments.last().unwrap().args.is_some() {
return None;
}

if let Some(v) = self.legacy_const_generic_args.get(&def_id) {
return v.clone();
}
}
let def_id = self.partial_res_map.get(&expr.id)?.full_res()?.opt_def_id()?;

// 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;
}

if let Some(v) = self.legacy_const_generic_args.get(&def_id) {
return v.clone();
}

None
Expand Down
46 changes: 46 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use rustc_ast::{LitIntType, LitKind, MetaItemLit};

use super::prelude::*;
use super::util::parse_single_integer;
use crate::session_diagnostics::RustcScalableVectorCountOutOfRange;
Expand Down Expand Up @@ -41,6 +43,50 @@ impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeEndParser
}
}

pub(crate) struct RustcLegacyConstGenericsParser;

impl<S: Stage> SingleAttributeParser<S> for RustcLegacyConstGenericsParser {
const PATH: &[Symbol] = &[sym::rustc_legacy_const_generics];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
const TEMPLATE: AttributeTemplate = template!(List: &["N"]);

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let ArgParser::List(meta_items) = args else {
cx.expected_list(cx.attr_span, args);
return None;
};

let mut parsed_indexes = ThinVec::new();
let mut errored = false;

for possible_index in meta_items.mixed() {
if let MetaItemOrLitParser::Lit(MetaItemLit {
kind: LitKind::Int(index, LitIntType::Unsuffixed),
..
}) = possible_index
{
parsed_indexes.push((index.0 as usize, possible_index.span()));
} else {
cx.expected_integer_literal(possible_index.span());
errored = true;
}
}
if errored {
return None;
} else if parsed_indexes.is_empty() {
cx.expected_at_least_one_argument(args.span()?);
return None;
}

Some(AttributeKind::RustcLegacyConstGenerics {
fn_indexes: parsed_indexes,
attr_span: cx.attr_span,
})
}
}

pub(crate) struct RustcObjectLifetimeDefaultParser;

impl<S: Stage> SingleAttributeParser<S> for RustcObjectLifetimeDefaultParser {
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ use crate::attributes::proc_macro_attrs::{
use crate::attributes::prototype::CustomMirParser;
use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser};
use crate::attributes::rustc_internal::{
RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser, RustcMainParser,
RustcObjectLifetimeDefaultParser, RustcScalableVectorParser,
RustcSimdMonomorphizeLaneLimitParser,
RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser,
RustcLegacyConstGenericsParser, RustcMainParser, RustcObjectLifetimeDefaultParser,
RustcScalableVectorParser, RustcSimdMonomorphizeLaneLimitParser,
};
use crate::attributes::semantics::MayDangleParser;
use crate::attributes::stability::{
Expand Down Expand Up @@ -209,6 +209,7 @@ attribute_parsers!(
Single<RustcForceInlineParser>,
Single<RustcLayoutScalarValidRangeEndParser>,
Single<RustcLayoutScalarValidRangeStartParser>,
Single<RustcLegacyConstGenericsParser>,
Single<RustcObjectLifetimeDefaultParser>,
Single<RustcScalableVectorParser>,
Single<RustcSimdMonomorphizeLaneLimitParser>,
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_layout_scalar_valid_range_start]`.
RustcLayoutScalarValidRangeStart(Box<u128>, Span),

/// Represents `#[rustc_legacy_const_generics]`
RustcLegacyConstGenerics { fn_indexes: ThinVec<(usize, Span)>, attr_span: Span },

/// Represents `#[rustc_main]`.
RustcMain,

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/attrs/encode_cross_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ impl AttributeKind {
RustcCoherenceIsCore(..) => No,
RustcLayoutScalarValidRangeEnd(..) => Yes,
RustcLayoutScalarValidRangeStart(..) => Yes,
RustcLegacyConstGenerics { .. } => Yes,
RustcMain => No,
RustcObjectLifetimeDefault => No,
RustcPassIndirectlyInNonRusticAbis(..) => No,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/attrs/pretty_printing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ macro_rules! print_tup {

print_tup!(A B C D E F G H);
print_skip!(Span, (), ErrorGuaranteed);
print_disp!(u16, u128, bool, NonZero<u32>, Limit);
print_disp!(u16, u128, usize, bool, NonZero<u32>, Limit);
print_debug!(
Symbol,
Ident,
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ pub struct ResolverGlobalCtxt {
#[derive(Debug)]
pub struct ResolverAstLowering {
pub legacy_const_generic_args: FxHashMap<DefId, Option<Vec<usize>>>,

/// Resolutions for nodes that have a single resolution.
pub partial_res_map: NodeMap<hir::def::PartialRes>,
/// Resolutions for import nodes, which have multiple resolutions in different namespaces.
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -478,9 +478,6 @@ passes_rustc_legacy_const_generics_index_exceed =
*[other] arguments
}
passes_rustc_legacy_const_generics_index_negative =
arguments should be non-negative integers
passes_rustc_legacy_const_generics_only =
#[rustc_legacy_const_generics] functions must only have const generics
.label = non-const generic parameter
Expand Down
64 changes: 19 additions & 45 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ use std::collections::hash_map::Entry;
use std::slice;

use rustc_abi::{Align, ExternAbi, Size};
use rustc_ast::{AttrStyle, LitKind, MetaItemKind, ast};
use rustc_ast::{AttrStyle, MetaItemKind, ast};
use rustc_attr_parsing::{AttributeParser, Late};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
use rustc_feature::{
ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP,
Expand Down Expand Up @@ -211,6 +212,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
Attribute::Parsed(AttributeKind::MacroExport { span, .. }) => {
self.check_macro_export(hir_id, *span, target)
},
Attribute::Parsed(AttributeKind::RustcLegacyConstGenerics{attr_span, fn_indexes}) => {
self.check_rustc_legacy_const_generics(item, *attr_span, fn_indexes)
},
Attribute::Parsed(AttributeKind::Doc(attr)) => self.check_doc_attrs(attr, hir_id, target),
Attribute::Parsed(AttributeKind::EiiImpls(impls)) => {
self.check_eii_impl(impls, target)
Expand Down Expand Up @@ -306,9 +310,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
[sym::rustc_never_returns_null_ptr, ..] => {
self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target)
}
[sym::rustc_legacy_const_generics, ..] => {
self.check_rustc_legacy_const_generics(hir_id, attr, span, target, item)
}
[sym::rustc_lint_query_instability, ..] => {
self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target)
}
Expand Down Expand Up @@ -1218,76 +1219,49 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
/// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument.
fn check_rustc_legacy_const_generics(
&self,
hir_id: HirId,
attr: &Attribute,
span: Span,
target: Target,
item: Option<ItemLike<'_>>,
attr_span: Span,
index_list: &ThinVec<(usize, Span)>,
) {
let is_function = matches!(target, Target::Fn);
if !is_function {
self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
attr_span: attr.span(),
defn_span: span,
on_crate: hir_id == CRATE_HIR_ID,
});
return;
}

let Some(list) = attr.meta_item_list() else {
// The attribute form is validated on AST.
return;
};

let Some(ItemLike::Item(Item {
kind: ItemKind::Fn { sig: FnSig { decl, .. }, generics, .. },
..
})) = item
else {
bug!("should be a function item");
// No error here, since it's already given by the parser
return;
};

for param in generics.params {
match param.kind {
hir::GenericParamKind::Const { .. } => {}
_ => {
self.dcx().emit_err(errors::RustcLegacyConstGenericsOnly {
attr_span: attr.span(),
attr_span,
param_span: param.span,
});
return;
}
}
}

if list.len() != generics.params.len() {
if index_list.len() != generics.params.len() {
self.dcx().emit_err(errors::RustcLegacyConstGenericsIndex {
attr_span: attr.span(),
attr_span,
generics_span: generics.span,
});
return;
}

let arg_count = decl.inputs.len() as u128 + generics.params.len() as u128;
let mut invalid_args = vec![];
for meta in list {
if let Some(LitKind::Int(val, _)) = meta.lit().map(|lit| &lit.kind) {
if *val >= arg_count {
let span = meta.span();
self.dcx().emit_err(errors::RustcLegacyConstGenericsIndexExceed {
span,
arg_count: arg_count as usize,
});
return;
}
} else {
invalid_args.push(meta.span());
let arg_count = decl.inputs.len() + generics.params.len();
for (index, span) in index_list {
if *index >= arg_count {
self.dcx().emit_err(errors::RustcLegacyConstGenericsIndexExceed {
span: *span,
arg_count,
});
}
}

if !invalid_args.is_empty() {
self.dcx().emit_err(errors::RustcLegacyConstGenericsIndexNegative { invalid_args });
}
}

/// Helper function for checking that the provided attribute is only applied to a function or
Expand Down
7 changes: 0 additions & 7 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,13 +290,6 @@ pub(crate) struct RustcLegacyConstGenericsIndexExceed {
pub arg_count: usize,
}

#[derive(Diagnostic)]
#[diag(passes_rustc_legacy_const_generics_index_negative)]
pub(crate) struct RustcLegacyConstGenericsIndexNegative {
#[primary_span]
pub invalid_args: Vec<Span>,
}

#[derive(Diagnostic)]
#[diag(passes_rustc_dirty_clean)]
pub(crate) struct RustcDirtyClean {
Expand Down
Loading
Loading