Rollup merge of #75378 - petrochenkov:isident, r=Mark-Simulacrum
Introduce `rustc_lexer::is_ident` and use it in couple of places Implements the suggestion from https://github.com/rust-lang/rust/pull/74537#issuecomment-662261979.
This commit is contained in:
@@ -3257,6 +3257,7 @@ dependencies = [
|
|||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
"rustc_errors",
|
"rustc_errors",
|
||||||
"rustc_feature",
|
"rustc_feature",
|
||||||
|
"rustc_lexer",
|
||||||
"rustc_macros",
|
"rustc_macros",
|
||||||
"rustc_serialize",
|
"rustc_serialize",
|
||||||
"rustc_session",
|
"rustc_session",
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ rustc_errors = { path = "../librustc_errors" }
|
|||||||
rustc_span = { path = "../librustc_span" }
|
rustc_span = { path = "../librustc_span" }
|
||||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||||
rustc_feature = { path = "../librustc_feature" }
|
rustc_feature = { path = "../librustc_feature" }
|
||||||
|
rustc_lexer = { path = "../librustc_lexer" }
|
||||||
rustc_macros = { path = "../librustc_macros" }
|
rustc_macros = { path = "../librustc_macros" }
|
||||||
rustc_session = { path = "../librustc_session" }
|
rustc_session = { path = "../librustc_session" }
|
||||||
rustc_ast = { path = "../librustc_ast" }
|
rustc_ast = { path = "../librustc_ast" }
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ enum AttrError {
|
|||||||
MultipleItem(String),
|
MultipleItem(String),
|
||||||
UnknownMetaItem(String, &'static [&'static str]),
|
UnknownMetaItem(String, &'static [&'static str]),
|
||||||
MissingSince,
|
MissingSince,
|
||||||
|
NonIdentFeature,
|
||||||
MissingFeature,
|
MissingFeature,
|
||||||
MultipleStabilityLevels,
|
MultipleStabilityLevels,
|
||||||
UnsupportedLiteral(&'static str, /* is_bytestr */ bool),
|
UnsupportedLiteral(&'static str, /* is_bytestr */ bool),
|
||||||
@@ -40,6 +41,9 @@ fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) {
|
|||||||
AttrError::MissingSince => {
|
AttrError::MissingSince => {
|
||||||
struct_span_err!(diag, span, E0542, "missing 'since'").emit();
|
struct_span_err!(diag, span, E0542, "missing 'since'").emit();
|
||||||
}
|
}
|
||||||
|
AttrError::NonIdentFeature => {
|
||||||
|
struct_span_err!(diag, span, E0546, "'feature' is not an identifier").emit();
|
||||||
|
}
|
||||||
AttrError::MissingFeature => {
|
AttrError::MissingFeature => {
|
||||||
struct_span_err!(diag, span, E0546, "missing 'feature'").emit();
|
struct_span_err!(diag, span, E0546, "missing 'feature'").emit();
|
||||||
}
|
}
|
||||||
@@ -344,6 +348,14 @@ where
|
|||||||
|
|
||||||
match (feature, reason, issue) {
|
match (feature, reason, issue) {
|
||||||
(Some(feature), reason, Some(_)) => {
|
(Some(feature), reason, Some(_)) => {
|
||||||
|
if !rustc_lexer::is_ident(&feature.as_str()) {
|
||||||
|
handle_errors(
|
||||||
|
&sess.parse_sess,
|
||||||
|
attr.span,
|
||||||
|
AttrError::NonIdentFeature,
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let level = Unstable { reason, issue: issue_num, is_soft };
|
let level = Unstable { reason, issue: issue_num, is_soft };
|
||||||
if sym::unstable == meta_name {
|
if sym::unstable == meta_name {
|
||||||
stab = Some(Stability { level, feature });
|
stab = Some(Stability { level, feature });
|
||||||
|
|||||||
@@ -319,18 +319,10 @@ pub struct Ident {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Ident {
|
impl Ident {
|
||||||
fn is_valid(string: &str) -> bool {
|
|
||||||
let mut chars = string.chars();
|
|
||||||
if let Some(start) = chars.next() {
|
|
||||||
rustc_lexer::is_id_start(start) && chars.all(rustc_lexer::is_id_continue)
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn new(sess: &ParseSess, sym: Symbol, is_raw: bool, span: Span) -> Ident {
|
fn new(sess: &ParseSess, sym: Symbol, is_raw: bool, span: Span) -> Ident {
|
||||||
let sym = nfc_normalize(&sym.as_str());
|
let sym = nfc_normalize(&sym.as_str());
|
||||||
let string = sym.as_str();
|
let string = sym.as_str();
|
||||||
if !Self::is_valid(&string) {
|
if !rustc_lexer::is_ident(&string) {
|
||||||
panic!("`{:?}` is not a valid identifier", string)
|
panic!("`{:?}` is not a valid identifier", string)
|
||||||
}
|
}
|
||||||
if is_raw && !sym.can_be_raw() {
|
if is_raw && !sym.can_be_raw() {
|
||||||
|
|||||||
@@ -274,6 +274,16 @@ pub fn is_id_continue(c: char) -> bool {
|
|||||||
|| (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_continue(c))
|
|| (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_continue(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The passed string is lexically an identifier.
|
||||||
|
pub fn is_ident(string: &str) -> bool {
|
||||||
|
let mut chars = string.chars();
|
||||||
|
if let Some(start) = chars.next() {
|
||||||
|
is_id_start(start) && chars.all(is_id_continue)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Cursor<'_> {
|
impl Cursor<'_> {
|
||||||
/// Parses a token from the input string.
|
/// Parses a token from the input string.
|
||||||
fn advance_token(&mut self) -> Token {
|
fn advance_token(&mut self) -> Token {
|
||||||
|
|||||||
@@ -2358,7 +2358,7 @@ impl Clean<Stability> for attr::Stability {
|
|||||||
fn clean(&self, _: &DocContext<'_>) -> Stability {
|
fn clean(&self, _: &DocContext<'_>) -> Stability {
|
||||||
Stability {
|
Stability {
|
||||||
level: stability::StabilityLevel::from_attr_level(&self.level),
|
level: stability::StabilityLevel::from_attr_level(&self.level),
|
||||||
feature: Some(self.feature.to_string()).filter(|f| !f.is_empty()),
|
feature: self.feature.to_string(),
|
||||||
since: match self.level {
|
since: match self.level {
|
||||||
attr::Stable { ref since } => since.to_string(),
|
attr::Stable { ref since } => since.to_string(),
|
||||||
_ => String::new(),
|
_ => String::new(),
|
||||||
|
|||||||
@@ -1525,7 +1525,7 @@ pub struct ProcMacro {
|
|||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Stability {
|
pub struct Stability {
|
||||||
pub level: stability::StabilityLevel,
|
pub level: stability::StabilityLevel,
|
||||||
pub feature: Option<String>,
|
pub feature: String,
|
||||||
pub since: String,
|
pub since: String,
|
||||||
pub unstable_reason: Option<String>,
|
pub unstable_reason: Option<String>,
|
||||||
pub issue: Option<NonZeroU32>,
|
pub issue: Option<NonZeroU32>,
|
||||||
|
|||||||
@@ -2144,7 +2144,7 @@ fn stability_tags(item: &clean::Item) -> String {
|
|||||||
if item
|
if item
|
||||||
.stability
|
.stability
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|s| s.level == stability::Unstable && s.feature.as_deref() != Some("rustc_private"))
|
.map(|s| s.level == stability::Unstable && s.feature != "rustc_private")
|
||||||
== Some(true)
|
== Some(true)
|
||||||
{
|
{
|
||||||
tags += &tag_html("unstable", "Experimental");
|
tags += &tag_html("unstable", "Experimental");
|
||||||
@@ -2195,14 +2195,15 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
|
|||||||
|
|
||||||
// Render unstable items. But don't render "rustc_private" crates (internal compiler crates).
|
// Render unstable items. But don't render "rustc_private" crates (internal compiler crates).
|
||||||
// Those crates are permanently unstable so it makes no sense to render "unstable" everywhere.
|
// Those crates are permanently unstable so it makes no sense to render "unstable" everywhere.
|
||||||
if let Some(stab) = item.stability.as_ref().filter(|stab| {
|
if let Some(stab) = item
|
||||||
stab.level == stability::Unstable && stab.feature.as_deref() != Some("rustc_private")
|
.stability
|
||||||
}) {
|
.as_ref()
|
||||||
|
.filter(|stab| stab.level == stability::Unstable && stab.feature != "rustc_private")
|
||||||
|
{
|
||||||
let mut message =
|
let mut message =
|
||||||
"<span class='emoji'>🔬</span> This is a nightly-only experimental API.".to_owned();
|
"<span class='emoji'>🔬</span> This is a nightly-only experimental API.".to_owned();
|
||||||
|
|
||||||
if let Some(feature) = stab.feature.as_deref() {
|
let mut feature = format!("<code>{}</code>", Escape(&stab.feature));
|
||||||
let mut feature = format!("<code>{}</code>", Escape(&feature));
|
|
||||||
if let (Some(url), Some(issue)) = (&cx.shared.issue_tracker_base_url, stab.issue) {
|
if let (Some(url), Some(issue)) = (&cx.shared.issue_tracker_base_url, stab.issue) {
|
||||||
feature.push_str(&format!(
|
feature.push_str(&format!(
|
||||||
" <a href=\"{url}{issue}\">#{issue}</a>",
|
" <a href=\"{url}{issue}\">#{issue}</a>",
|
||||||
@@ -2212,7 +2213,6 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message.push_str(&format!(" ({})", feature));
|
message.push_str(&format!(" ({})", feature));
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(unstable_reason) = &stab.unstable_reason {
|
if let Some(unstable_reason) = &stab.unstable_reason {
|
||||||
let mut ids = cx.id_map.borrow_mut();
|
let mut ids = cx.id_map.borrow_mut();
|
||||||
|
|||||||
Reference in New Issue
Block a user