Skip to content
Closed
69 changes: 32 additions & 37 deletions compiler/rustc_ast/src/attr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,34 +235,6 @@ impl AttributeExt for Attribute {
}
}

fn deprecation_note(&self) -> Option<Ident> {
match &self.kind {
AttrKind::Normal(normal) if normal.item.path == sym::deprecated => {
let meta = &normal.item;

// #[deprecated = "..."]
if let Some(s) = meta.value_str() {
return Some(Ident { name: s, span: meta.span() });
}

// #[deprecated(note = "...")]
if let Some(list) = meta.meta_item_list() {
for nested in list {
if let Some(mi) = nested.meta_item()
&& mi.path == sym::note
&& let Some(s) = mi.value_str()
{
return Some(Ident { name: s, span: mi.span });
}
}
}

None
}
_ => None,
}
}

fn doc_resolution_scope(&self) -> Option<AttrStyle> {
match &self.kind {
AttrKind::DocComment(..) => Some(self.style),
Expand Down Expand Up @@ -341,6 +313,34 @@ impl Attribute {
)],
}
}

pub fn deprecation_note(&self) -> Option<Ident> {
match &self.kind {
AttrKind::Normal(normal) if normal.item.path == sym::deprecated => {
let meta = &normal.item;

// #[deprecated = "..."]
if let Some(s) = meta.value_str() {
return Some(Ident { name: s, span: meta.span() });
}

// #[deprecated(note = "...")]
if let Some(list) = meta.meta_item_list() {
for nested in list {
if let Some(mi) = nested.meta_item()
&& mi.path == sym::note
&& let Some(s) = mi.value_str()
{
return Some(Ident { name: s, span: mi.span });
}
}
}

None
}
_ => None,
}
}
}

impl AttrItem {
Expand Down Expand Up @@ -824,19 +824,19 @@ pub fn mk_attr_name_value_str(
mk_attr(g, style, unsafety, path, args, span)
}

pub fn filter_by_name<A: AttributeExt>(attrs: &[A], name: Symbol) -> impl Iterator<Item = &A> {
pub fn filter_by_name(attrs: &[Attribute], name: Symbol) -> impl Iterator<Item = &Attribute> {
attrs.iter().filter(move |attr| attr.has_name(name))
}

pub fn find_by_name<A: AttributeExt>(attrs: &[A], name: Symbol) -> Option<&A> {
pub fn find_by_name(attrs: &[Attribute], name: Symbol) -> Option<&Attribute> {
filter_by_name(attrs, name).next()
}

pub fn first_attr_value_str_by_name(attrs: &[impl AttributeExt], name: Symbol) -> Option<Symbol> {
pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: Symbol) -> Option<Symbol> {
find_by_name(attrs, name).and_then(|attr| attr.value_str())
}

pub fn contains_name(attrs: &[impl AttributeExt], name: Symbol) -> bool {
pub fn contains_name(attrs: &[Attribute], name: Symbol) -> bool {
find_by_name(attrs, name).is_some()
}

Expand Down Expand Up @@ -911,11 +911,6 @@ pub trait AttributeExt: Debug {
/// * `#[doc(...)]` returns `None`.
fn doc_str(&self) -> Option<Symbol>;

/// Returns the deprecation note if this is deprecation attribute.
/// * `#[deprecated = "note"]` returns `Some("note")`.
/// * `#[deprecated(note = "note", ...)]` returns `Some("note")`.
fn deprecation_note(&self) -> Option<Ident>;

/// Returns whether this attribute is any of the proc macro attributes.
/// i.e. `proc_macro`, `proc_macro_attribute` or `proc_macro_derive`.
fn is_proc_macro_attr(&self) -> bool {
Expand Down
7 changes: 3 additions & 4 deletions compiler/rustc_attr_parsing/src/attributes/util.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::num::IntErrorKind;

use rustc_ast::LitKind;
use rustc_ast::attr::AttributeExt;
use rustc_ast::{LitKind, ast};
use rustc_feature::is_builtin_attr_name;
use rustc_hir::RustcVersion;
use rustc_hir::limit::Limit;
Expand All @@ -27,8 +26,8 @@ pub fn parse_version(s: Symbol) -> Option<RustcVersion> {
Some(RustcVersion { major, minor, patch })
}

pub fn is_builtin_attr(attr: &impl AttributeExt) -> bool {
attr.is_doc_comment().is_some() || attr.name().is_some_and(|name| is_builtin_attr_name(name))
pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
attr.is_doc_comment() || attr.name().is_some_and(|name| is_builtin_attr_name(name))
}

/// Parse a single integer.
Expand Down
43 changes: 43 additions & 0 deletions compiler/rustc_expand/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,49 @@ mod metavar_exprs {
pub span: Span,
pub key: MacroRulesNormalizedIdent,
}

#[derive(Diagnostic)]
#[diag(r#"`${"{"}concat(..){"}"}` is not generating a valid identifier"#)]
pub(crate) struct ConcatInvalidIdent {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub reason: InvalidIdentReason,
}

#[derive(Subdiagnostic)]
pub(crate) enum InvalidIdentReason {
#[note(r#"this `${"{"}concat(..){"}"}` invocation generated an empty ident"#)]
Empty,
#[note(r#"this `${"{"}concat(..){"}"}` invocation generated `{$symbol}`, but {$start} is neither '_' nor XID_Start"#)]
#[note(
"see <https://doc.rust-lang.org/reference/identifiers.html> for the definition of valid identifiers"
)]
InvalidStart { symbol: Symbol, start: char },
#[note(r#"this `${"{"}concat(..){"}"}` invocation generated `{$symbol}`, but {$not_continue} is not XID_Continue"#)]
#[note(
"see <https://doc.rust-lang.org/reference/identifiers.html> for the definition of valid identifiers"
)]
InvalidContinue { symbol: Symbol, not_continue: char },
}

impl InvalidIdentReason {
pub(crate) fn new(symbol: Symbol) -> Self {
let mut chars = symbol.as_str().chars();
if let Some(start) = chars.next() {
if rustc_lexer::is_id_start(start) {
let not_continue = chars
.find(|c| !rustc_lexer::is_id_continue(*c))
.expect("InvalidIdentReason: cannot find invalid ident reason");
InvalidIdentReason::InvalidContinue { symbol, not_continue }
} else {
InvalidIdentReason::InvalidStart { symbol, start }
}
} else {
InvalidIdentReason::Empty
}
}
}
}

#[derive(Diagnostic)]
Expand Down
15 changes: 8 additions & 7 deletions compiler/rustc_expand/src/mbe/transcribe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ use rustc_span::{
use smallvec::{SmallVec, smallvec};

use crate::errors::{
CountRepetitionMisplaced, MacroVarStillRepeating, MetaVarsDifSeqMatchers, MustRepeatOnce,
MveUnrecognizedVar, NoRepeatableVar, NoSyntaxVarsExprRepeat, VarNoTypo,
VarTypoSuggestionRepeatable, VarTypoSuggestionUnrepeatable, VarTypoSuggestionUnrepeatableLabel,
ConcatInvalidIdent, CountRepetitionMisplaced, InvalidIdentReason, MacroVarStillRepeating,
MetaVarsDifSeqMatchers, MustRepeatOnce, MveUnrecognizedVar, NoRepeatableVar,
NoSyntaxVarsExprRepeat, VarNoTypo, VarTypoSuggestionRepeatable, VarTypoSuggestionUnrepeatable,
VarTypoSuggestionUnrepeatableLabel,
};
use crate::mbe::macro_parser::NamedMatch;
use crate::mbe::macro_parser::NamedMatch::*;
Expand Down Expand Up @@ -656,10 +657,10 @@ fn metavar_expr_concat<'tx>(
let symbol = nfc_normalize(&concatenated);
let concatenated_span = tscx.visited_dspan(dspan);
if !rustc_lexer::is_ident(symbol.as_str()) {
return Err(dcx.struct_span_err(
concatenated_span,
"`${concat(..)}` is not generating a valid identifier",
));
return Err(dcx.create_err(ConcatInvalidIdent {
span: concatenated_span,
reason: InvalidIdentReason::new(symbol),
}));
}
tscx.psess.symbol_gallery.insert(symbol, concatenated_span);

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ declare_features! (
/// Target features on hexagon.
(unstable, hexagon_target_feature, "1.27.0", Some(150250)),
/// Allows `impl(crate) trait Foo` restrictions.
(incomplete, impl_restriction, "1.96.0", Some(105077)),
(unstable, impl_restriction, "CURRENT_RUSTC_VERSION", Some(105077)),
/// Allows `impl Trait` to be used inside associated types (RFC 2515).
(unstable, impl_trait_in_assoc_type, "1.70.0", Some(63063)),
/// Allows `impl Trait` in bindings (`let`).
Expand Down
8 changes: 0 additions & 8 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1424,14 +1424,6 @@ impl AttributeExt for Attribute {
}
}

#[inline]
fn deprecation_note(&self) -> Option<Ident> {
match &self {
Attribute::Parsed(AttributeKind::Deprecated { deprecation, .. }) => deprecation.note,
_ => None,
}
}

fn is_automatically_derived_attr(&self) -> bool {
matches!(self, Attribute::Parsed(AttributeKind::AutomaticallyDerived(..)))
}
Expand Down
97 changes: 47 additions & 50 deletions compiler/rustc_mir_transform/src/ssa_range_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,13 @@ impl<'tcx> MutVisitor<'tcx> for RangeSet<'tcx, '_, '_> {
fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) {
self.super_statement(statement, location);
match &statement.kind {
StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(operand)) => {
StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(operand))
if let Some(place) = operand.place()
&& self.is_ssa(place)
{
let successor = location.successor_within_block();
let range = WrappingRange { start: 1, end: 1 };
self.insert_range(place, successor, range);
}
&& self.is_ssa(place) =>
{
let successor = location.successor_within_block();
let range = WrappingRange { start: 1, end: 1 };
self.insert_range(place, successor, range);
}
_ => {}
}
Expand All @@ -159,58 +158,56 @@ impl<'tcx> MutVisitor<'tcx> for RangeSet<'tcx, '_, '_> {
fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) {
self.super_terminator(terminator, location);
match &terminator.kind {
TerminatorKind::Assert { cond, expected, target, .. } => {
TerminatorKind::Assert { cond, expected, target, .. }
if let Some(place) = cond.place()
&& self.is_ssa(place)
{
let successor = Location { block: *target, statement_index: 0 };
if location.dominates(successor, &self.dominators) {
assert_ne!(location.block, successor.block);
let val = *expected as u128;
let range = WrappingRange { start: val, end: val };
self.insert_range(place, successor, range);
}
&& self.is_ssa(place) =>
{
let successor = Location { block: *target, statement_index: 0 };
if location.dominates(successor, &self.dominators) {
assert_ne!(location.block, successor.block);
let val = *expected as u128;
let range = WrappingRange { start: val, end: val };
self.insert_range(place, successor, range);
}
}
TerminatorKind::SwitchInt { discr, targets } => {
TerminatorKind::SwitchInt { discr, targets }
if let Some(place) = discr.place()
&& self.is_ssa(place)
// Reduce the potential compile-time overhead.
&& targets.all_targets().len() < 16
{
let mut distinct_targets: FxHashMap<BasicBlock, u64> = FxHashMap::default();
for (_, target) in targets.iter() {
let targets = distinct_targets.entry(target).or_default();
*targets += 1;
&& targets.all_targets().len() < 16 =>
{
let mut distinct_targets: FxHashMap<BasicBlock, u64> = FxHashMap::default();
for (_, target) in targets.iter() {
let targets = distinct_targets.entry(target).or_default();
*targets += 1;
}
for (val, target) in targets.iter() {
if distinct_targets[&target] != 1 {
// FIXME: For multiple targets, the range can be the union of their values.
continue;
}
for (val, target) in targets.iter() {
if distinct_targets[&target] != 1 {
// FIXME: For multiple targets, the range can be the union of their values.
continue;
}
let successor = Location { block: target, statement_index: 0 };
if self.unique_predecessors.contains(successor.block) {
assert_ne!(location.block, successor.block);
let range = WrappingRange { start: val, end: val };
self.insert_range(place, successor, range);
}
let successor = Location { block: target, statement_index: 0 };
if self.unique_predecessors.contains(successor.block) {
assert_ne!(location.block, successor.block);
let range = WrappingRange { start: val, end: val };
self.insert_range(place, successor, range);
}
}

// FIXME: The range for the otherwise target be extend to more types.
// For instance, `val` is within the range [4, 1) at the otherwise target of `matches!(val, 1 | 2 | 3)`.
let otherwise = Location { block: targets.otherwise(), statement_index: 0 };
if place.ty(self.local_decls, self.tcx).ty.is_bool()
&& let [val] = targets.all_values()
&& self.unique_predecessors.contains(otherwise.block)
{
assert_ne!(location.block, otherwise.block);
let range = if val.get() == 0 {
WrappingRange { start: 1, end: 1 }
} else {
WrappingRange { start: 0, end: 0 }
};
self.insert_range(place, otherwise, range);
}
// FIXME: The range for the otherwise target be extend to more types.
// For instance, `val` is within the range [4, 1) at the otherwise target of `matches!(val, 1 | 2 | 3)`.
let otherwise = Location { block: targets.otherwise(), statement_index: 0 };
if place.ty(self.local_decls, self.tcx).ty.is_bool()
&& let [val] = targets.all_values()
&& self.unique_predecessors.contains(otherwise.block)
{
assert_ne!(location.block, otherwise.block);
let range = if val.get() == 0 {
WrappingRange { start: 1, end: 1 }
} else {
WrappingRange { start: 0, end: 0 }
};
self.insert_range(place, otherwise, range);
}
}
_ => {}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_resolve/src/rustdoc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ pub fn may_be_doc_link(link_type: LinkType) -> bool {

/// Simplified version of `preprocessed_markdown_links` from rustdoc.
/// Must return at least the same links as it, but may add some more links on top of that.
pub(crate) fn attrs_to_preprocessed_links<A: AttributeExt + Clone>(attrs: &[A]) -> Vec<Box<str>> {
pub(crate) fn attrs_to_preprocessed_links(attrs: &[ast::Attribute]) -> Vec<Box<str>> {
let (doc_fragments, other_attrs) =
attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), false);
let mut doc =
Expand Down
7 changes: 1 addition & 6 deletions src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use arrayvec::ArrayVec;
use itertools::Either;
use rustc_abi::{ExternAbi, VariantIdx};
use rustc_ast as ast;
use rustc_ast::attr::AttributeExt;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::thin_vec::ThinVec;
use rustc_hir as hir;
Expand Down Expand Up @@ -501,11 +500,7 @@ impl Item {
}

pub(crate) fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
let deprecation_notes = self
.attrs
.other_attrs
.iter()
.filter_map(|attr| attr.deprecation_note().map(|note| note.span));
let deprecation_notes = find_attr!(&self.attrs.other_attrs, Deprecated { deprecation, .. } => deprecation.note.map(|note| note.span)).flatten();

span_of_fragments(&self.attrs.doc_strings)
.into_iter()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#![feature(impl_restriction)]
#![expect(incomplete_features)]

pub impl(crate) trait TopLevel {}

Expand Down
1 change: 0 additions & 1 deletion tests/ui/impl-restriction/feature-gate-impl-restriction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
//@[with_gate] check-pass

#![cfg_attr(with_gate, feature(impl_restriction))]
#![cfg_attr(with_gate, allow(incomplete_features))]
#![feature(auto_traits, const_trait_impl)]

pub impl(crate) trait Bar {} //[without_gate]~ ERROR `impl` restrictions are experimental
Expand Down
Loading
Loading