Skip to content
Open
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
11 changes: 11 additions & 0 deletions compiler/rustc_attr_ir/src/data_structures.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::borrow::Cow;
use std::fmt;
use std::path::PathBuf;
use std::range::RangeInclusive;

pub use ReprAttr::*;
use rustc_abi::Align;
Expand All @@ -16,6 +17,7 @@ use rustc_macros::{
Decodable, Decodable_NoContext, Encodable, Encodable_NoContext, PrintAttribute, StableHash,
};
use rustc_span::def_id::DefId;
use rustc_span::edition::Edition;
use rustc_span::hygiene::Transparency;
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
use rustc_structures::{CollapseMacroDebuginfo, CrateType, Limit, NativeLibKind, SanitizerSet};
Expand Down Expand Up @@ -119,6 +121,12 @@ pub enum InstrumentFnAttr {
Off,
}

#[derive(Clone, Copy, Debug, StableHash, Encodable, Decodable, PrintAttribute)]
pub struct EditionRedirect {
pub range: RangeInclusive<Edition>,
pub span: Span,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Default, PrintAttribute)]
#[derive(Encodable, Decodable, StableHash)]
pub enum OptimizeAttr {
Expand Down Expand Up @@ -1267,6 +1275,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_dyn_incompatible_trait]`.
RustcDynIncompatibleTrait(Span),

/// Represents `#[rustc_edition_redirect = "..."]`.
RustcEditionRedirect(EditionRedirect),

/// Represents `#[rustc_effective_visibility]`.
RustcEffectiveVisibility,

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_attr_ir/src/encode_cross_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ impl AttributeKind {
RustcDumpVariancesOfOpaques => No,
RustcDumpVtable(..) => No,
RustcDynIncompatibleTrait(..) => No,
RustcEditionRedirect(..) => No,
RustcEffectiveVisibility => Yes,
RustcEiiForeignItem => No,
RustcEvaluateWhereClauses => Yes,
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_attr_ir/src/pretty_printing.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::num::NonZero;
use std::ops::Deref;
use std::path::PathBuf;
use std::range::RangeInclusive;

use rustc_abi::Align;
use rustc_ast::ast::{Path, join_path_idents};
Expand All @@ -12,6 +13,7 @@ use rustc_ast::{AttrId, AttrStyle, IntTy, UintTy};
use rustc_ast_pretty::pp::Printer;
use rustc_data_structures::fx::FxIndexMap;
use rustc_span::def_id::DefId;
use rustc_span::edition::Edition;
use rustc_span::hygiene::Transparency;
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
use rustc_structures::{CollapseMacroDebuginfo, CrateType, Limit, NativeLibKind, SanitizerSet};
Expand Down Expand Up @@ -190,7 +192,7 @@ macro_rules! print_tup {

print_tup!(A B C D E F G H);
print_skip!(Span, (), ErrorGuaranteed, AttrId);
print_disp!(u8, u16, u32, u128, usize, bool, NonZero<u32>, Limit);
print_disp!(u8, u16, u32, u128, usize, bool, NonZero<u32>, Edition, Limit);
print_debug!(
Symbol,
Ident,
Expand All @@ -210,4 +212,5 @@ print_debug!(
CrateType,
NativeLibKind,
CollapseMacroDebuginfo,
RangeInclusive<Edition>,
);
33 changes: 31 additions & 2 deletions compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
use std::path::PathBuf;
use std::range::RangeInclusive;

use rustc_ast::{LitIntType, LitKind, MetaItemLit};
use rustc_attr_ir::lang_items::LangItem;
use rustc_attr_ir::target::GenericParamKind;
use rustc_attr_ir::{
BorrowckGraphvizFormatKind, CguFields, CguKind, RustcCleanAttribute, RustcCleanQueries,
RustcMirKind,
BorrowckGraphvizFormatKind, CguFields, CguKind, EditionRedirect, RustcCleanAttribute,
RustcCleanQueries, RustcMirKind,
};
use rustc_data_structures::fx::FxHashMap;
use rustc_feature::AttributeStability;
use rustc_span::Symbol;
use rustc_span::edition::Edition;

use super::prelude::*;
use super::util::parse_single_integer;
Expand Down Expand Up @@ -342,6 +344,33 @@ impl AttributeParser for RustcCguTestAttributeParser {
}
}

pub(crate) struct RustcEditionRedirectParser;

impl SingleAttributeParser for RustcEditionRedirectParser {
const PATH: &[Symbol] = &[sym::rustc_edition_redirect];
const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Use)]);
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "2021..=2024");
const STABILITY: AttributeStability = unstable!(rustc_attrs);

fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
let value = cx.expect_name_value(args, cx.attr_span, Some(sym::rustc_edition_redirect))?;
let value = cx.expect_string_literal(value)?;
let Some((start, last)) = value.as_str().split_once("..=").and_then(|(start, end)| {
let start = if start.is_empty() { Edition::Edition2015 } else { start.parse().ok()? };
let last = end.parse().ok()?;
(start <= last).then_some((start, last))
}) else {
cx.emit_err(diagnostics::InvalidEditionRedirect { span: cx.attr_span });
return None;
};

Some(AttributeKind::RustcEditionRedirect(EditionRedirect {
range: RangeInclusive { start, last },
span: cx.attr_span,
}))
}
}

pub(crate) struct RustcDeprecatedSafe2024Parser;

impl SingleAttributeParser for RustcDeprecatedSafe2024Parser {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ attribute_parsers!(
Single<RustcDummyParser>,
Single<RustcDumpDefPathParser>,
Single<RustcDumpSymbolNameParser>,
Single<RustcEditionRedirectParser>,
Single<RustcForceInlineParser>,
Single<RustcIfThisChangedParser>,
Single<RustcLegacyConstGenericsParser>,
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_attr_parsing/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ pub(crate) struct ItemFollowingInnerAttr {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag("invalid edition range in edition redirect")]
pub(crate) struct InvalidEditionRedirect {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag("unreachable configuration predicate")]
pub(crate) struct UnreachableCfgSelectPredicate {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ pub static BUILTIN_ATTRIBUTES: &[Symbol] = &[
sym::rustc_eii_foreign_item,
sym::rustc_allowed_through_unstable_modules,
sym::rustc_deprecated_safe_2024,
sym::rustc_edition_redirect,
sym::rustc_pub_transparent,

// ==========================================================================
Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1313,7 +1313,14 @@ impl CrateMetadata {
let res = Res::Def(self.def_kind(id), self.local_def_id(id));
let vis = self.get_visibility(tcx, id);

ModChild { ident, res, vis, reexport_chain: Default::default() }
ModChild {
ident,
res,
vis,
reexport_chain: Default::default(),
// Children with redirects are encoded as full `ModChild`s.
edition_redirects: Default::default(),
}
}

/// Iterates over all named children of the given module,
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1737,11 +1737,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let module_children = tcx.module_children_local(local_def_id);

record_array!(self.tables.module_children_non_reexports[def_id] <-
module_children.iter().filter(|child| child.reexport_chain.is_empty())
module_children.iter().filter(|child| child.reexport_chain.is_empty()
&& child.edition_redirects.is_empty())
.map(|child| child.res.def_id().index));

record_defaulted_array!(self.tables.module_children_reexports[def_id] <-
module_children.iter().filter(|child| !child.reexport_chain.is_empty()));
module_children.iter().filter(|child| !child.reexport_chain.is_empty()
|| !child.edition_redirects.is_empty()));

let ambig_module_children = tcx
.resolutions(())
Expand Down
7 changes: 3 additions & 4 deletions compiler/rustc_metadata/src/rmeta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,10 +402,9 @@ define_tables! {
explicit_implied_const_bounds: Table<DefIndex, LazyArray<(ty::PolyTraitRef<'static>, Span)>>,
inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
opt_rpitit_info: Table<DefIndex, Option<LazyValue<ty::ImplTraitInTraitData>>>,
// Reexported names are not associated with individual `DefId`s,
// e.g. a glob import can introduce a lot of names, all with the same `DefId`.
// That's why the encoded list needs to contain `ModChild` structures describing all the names
// individually instead of `DefId`s.
// Names requiring data beyond the item's own `DefId` are encoded as full `ModChild`s.
// This includes reexports, where a glob can introduce many names with the same `DefId`, and
// proper items carrying edition redirects.
module_children_reexports: Table<DefIndex, LazyArray<ModChild>>,
ambig_module_children: Table<DefIndex, LazyArray<AmbigModChild>>,
cross_crate_inlinable: Table<DefIndex, bool>,
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_middle/src/middle/resolve.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! This module contains types that carry name resolution results from `rustc_resolve` to a
//! consumer in another crate (e.g. AST lowering, metadata, or a query).

use std::range::RangeInclusive;

use rustc_ast::node_id::NodeMap;
use rustc_ast::{self as ast, NodeId};
use rustc_attr_ir::StrippedCfgItem;
Expand All @@ -13,6 +15,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LocalModId,
use rustc_hir::definitions::PerParentDisambiguatorState;
use rustc_hir::{MissingLifetimeKind, TraitCandidate};
use rustc_macros::{StableHash, TyDecodable, TyEncodable};
use rustc_span::edition::Edition;
use rustc_span::{ExpnId, Ident, Span, Symbol};
use smallvec::SmallVec;

Expand Down Expand Up @@ -132,6 +135,13 @@ impl Reexport {
}
}

/// A different item that a module child resolves to within an inclusive edition range.
#[derive(Clone, Copy, Debug, TyEncodable, TyDecodable, StableHash)]
pub struct EditionRedirect {
pub range: RangeInclusive<Edition>,
pub target: Res<!>,
}

/// This structure is supposed to keep enough data to re-create `Decl`s for other crates
/// during name resolution. Right now the bindings are not recreated entirely precisely so we may
/// need to add more data in the future to correctly support macros 2.0, for example.
Expand All @@ -149,6 +159,8 @@ pub struct ModChild {
/// Reexport chain linking this module child to its original reexported item.
/// Empty if the module child is a proper item.
pub reexport_chain: SmallVec<[Reexport; 2]>,
/// Edition-dependent alternatives, sorted by their range.
pub edition_redirects: SmallVec<[EditionRedirect; 1]>,
}

/// Same as `ModChild`, however, it includes ambiguity error.
Expand Down
18 changes: 16 additions & 2 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ use rustc_feature::BUILTIN_ATTRIBUTE_SET;
use rustc_hir::attrs::diagnostic::Directive;
use rustc_hir::attrs::lang_items::LangItem;
use rustc_hir::attrs::{
AttributeKind, DocAttribute, DocInline, EiiDecl, EiiImpl, EiiImplResolution, InlineAttr,
OptimizeAttr, ReprAttr,
AttributeKind, DocAttribute, DocInline, EditionRedirect, EiiDecl, EiiImpl, EiiImplResolution,
InlineAttr, OptimizeAttr, ReprAttr,
};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalModId;
Expand Down Expand Up @@ -239,6 +239,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
AttributeKind::Linkage(_linkage, span) => {
self.check_linkage(*span, hir_id, target, item)
}
AttributeKind::RustcEditionRedirect(redirect) => {
self.check_rustc_edition_redirect(item, redirect)
}

// All of the following attributes have no specific checks.
// tidy-alphabetical-start
Expand Down Expand Up @@ -467,6 +470,17 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
})
}

/// Rejects the use of edition redirect on non-single use statements.
fn check_rustc_edition_redirect(&self, item: Option<&Item<'_>>, redirect: &EditionRedirect) {
let Some(Item { kind: ItemKind::Use(_, use_kind), .. }) = item else {
return;
};
if matches!(use_kind, hir::UseKind::Single(_)) {
return;
}
self.dcx().emit_err(diagnostics::EditionRedirectNonSingleUse { attr_span: redirect.span });
}

fn check_rustc_must_implement_one_of(
&self,
attr_span: Span,
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_passes/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol};
use crate::check_attr::ProcMacroKind;
use crate::lang_items::Duplicate;

#[derive(Diagnostic)]
#[diag("`#[rustc_edition_redirect]` can only be applied to a single import")]
#[help("use a separate, non-braced `use` item")]
pub(crate) struct EditionRedirectNonSingleUse {
#[primary_span]
pub attr_span: Span,
}

#[derive(Diagnostic)]
#[diag("`{$no_mangle_attr}` attribute may not be used in combination with `{$export_name_attr}`")]
pub(crate) struct MixedExportNameAndNoMangle {
Expand Down
Loading